glpk-4.52.1/0000755000062000006210000000000012175170322011716 5ustar maomkpasswdglpk-4.52.1/aclocal.m40000644000062000006210000010422712175147600013567 0ustar maomkpasswd# generated automatically by aclocal 1.12.5 -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.12' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.12.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.12.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated. For more info, see: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl dnl Support for Objective C++ was only introduced in Autoconf 2.65, dnl but we still cater to Autoconf 2.62. m4_ifdef([AC_PROG_OBJCXX], [AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2001-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2012 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of '-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) glpk-4.52.1/AUTHORS0000644000062000006210000000313512175147600012773 0ustar maomkpasswdThe GLPK package was developed and programmed by Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. E-mail: Paper mail: 125871, Russia, Moscow, Volokolamskoye sh., 4, Moscow Aviation Institute, Andrew O. Makhorin -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.2.2 (MingW32) mQGiBD8UdT8RBAC6yWYxoa1b7U973J0jBuQpgZnhXlGJJpMZgAW9efDBD17vhkJm hPVOQBKRUeOOLcW3/a7NMoNLMdmF1Rgz1FPVy3RgBDsYj4Sp4RBCsX/o0xXh+jxe gncr4bdN0Ruk03pezVtLi9oYygdxfI51SsjZ2vwYP6BhMwv+xrIgcnc4qwCgoCit 26mTd0FoGOmsQuipo6X5LaUD/1l7NqFIjiGdWthyG3TqsiK5Ew7xF3fLEABXKPjb PMRTMucX8XXHmW8RUD1vP1uGDnEn6s+fjc3/RtaqKjqGMdLt4XgHQkImaVguNpSS IxN3LaK600BgAbwSd1bomRqWNlczAM7469VvGG9ASpCBveUUrqwerHZcUbvngL62 pIcqA/41dO0xYrOTqMRhuguYMgHL2xbwB2Aj2TqRwBm697DIS25B9nE+8UsbjGRx q3EmeuHeZ5kN5RbESXkGUB8whIcYxvH16HRNmM1ZjmFoBVL2Z6S2gpa2ZUqsq7BZ s+hriElm3dfOQCt79/o852uKWu5bSjw2yiemVA2T8tG4OoN6DrQjQW5kcmV3IE1h a2hvcmluIDxtYW9AbWFpMi5yY25ldC5ydT6IWwQTEQIAGwUCPxR1PwYLCQgHAwID FQIDAxYCAQIeAQIXgAAKCRDRe/IwWYHoGKpHAJ44MmzWKr8OiTc0Bb6/RD56aekp 3wCdGznQMCfWFkehQPbeNaB5yFIs+8a5AQ0EPxR1UBAEAO3U3H5M0iYv06C4kKty 6ReWyYH4CzMAfp2lPVUKzRSjPtoAJ6SkrBSKMT+U+DahxZ4K4HbinvHq3uvlwWax xw0wKxJl4oY6EGE1Jqn3B//Ak47RaNMnrs9V739WT1YNRpQvh4wOCeMekBzksf43 hm4dSV4PMQkLmrEeG2+BYaZnAAMFA/4tVHhjGRkxzcTcfHCB+Yo3PXeIQMuIs00c VKCrNReLni/3BWZC0w9tFzZSdz+URXefPWDGuAC16vLCVOD06NcIQGutPe189dUn Kf9Bl6qc9DyWsxSTdF/PbLqcLfEe9g7fHhIwdY+w/hSq2n3NEURMzHiMT1U3CvHd As5IzV/yD4hGBBgRAgAGBQI/FHVQAAoJENF78jBZgegYRZEAmwReJkMSrbs0EQs2 wjyTCMd5KDh3AKCR2/RvVad9RT3ShYnUiPPYTL2/Nw== =OfLQ -----END PGP PUBLIC KEY BLOCK----- glpk-4.52.1/ChangeLog0000644000062000006210000031454712175147600013511 0ustar maomkpasswdSun Jul 28 12:00:00 2013 Andrew Makhorin * GLPK 4.52.1 (36:1:0) has been released. * src/Makefile.am Version information bug was fixed. Thanks to Sebastien Villemot for bug report. * src/proxy/proxy.c A minor bug (incorrect use of glp_term_out) was fixed. * src/glpios03.c The simple rounding heuristic routine was changed to check only global constraints. * src/glpcpx.c The code was changed to issue the warning message 'lower/upper bound redefined' only once. Thu Jul 18 12:00:00 2013 Andrew Makhorin * GLPK 4.52 (36:0:1) has been released. * src/misc/wclique1.h, src/misc/wclique1.c Greedy heuristic to find maximum weight clique was implemented. * src/cglib/cfg.h, src/cglib/cfg.c, src/cglib/cfg1.c Conflict graph routines (used to generate clique cuts) were implemented. * src/glpios08.c New version of the clique cut generator was implemented. Now it is able to efficiently process very large and/or dense conflict graphs. Old rudimentary version was removed from the package. * examples/misp1.dat, examples/misp2.dat Two data files for the maximum independent set problem (MISP) were added to illustrate efficiency of using the clique cuts. * src/glpios03.c Simple rounding heuristic applied for every node subproblem was implemented. * proxy/proxy.c Some bugs were fixed in the proximity search heuristic routine. Thanks to Giorgio Sartor <0gioker0@gmail.com>. * src/glpapi21.c New command-line option '--proxy [nnn]' was added to glpsol to enable using the proximity search heuristic. * src/glpspx02.c A feature was added to switch to the primal simplex in case of stalling due to dual degeneracy (for GLP_DUALP only). * src/glpmps.c A bug (incorrect processing of LI column indicator) was fixed in the mps format reading routine. Thanks to Charles Brixko for bug report. Wed Jun 19 12:00:00 2013 Andrew Makhorin * GLPK 4.51 (36:0:0) has been released. * src/bflib/sgf.c, src/bflib/sgf.h Singleton and dense phases of sparse Gaussian factorizer were implemented. * src/bflib/lufint.c, src/bflib/lufint.h Interface routines to LU-factorization were added. * src/bflib/fhvint.c, src/bflib/fhvint.h Interface routines to FHV-factorization were changed to use lufint.c routines. * src/glplpf.c, src/glplpf.h Routines implementing Schur-complement version of the LP basis factorization were changed to use lufint.c routines. * src/glpbfd.c, src/glpbfd.h Interface routines to the LP basis factorization were changed due to changes in glplpf.c routines. * src/glpluf.c, src/glpluf.c Old version of LU-factorization was removed from the package. (This old version was used for 10 years since 3.0.6.) * src/misc/triang.c, src/misc/triang.h Routine to find maximal triangular part of rectangular matrix was added. * src/glpini01.c The API routine glp_adv_basis that constructs advanced initial LP basis was replaced by an improved version, which (unlike the old version) takes into account numerical values of constraint coefficients. * src/proxy/* Routines that implement the proximity search heuristic for MIP were added. Thanks to Giorgio Sartor <0gioker0@gmail.com> for contribution. * src/glpk.h iocp.ps_heur was added to enable/disable proxy heuristic. * glpsol --proxy command-line option was added. * src/zlib/*.* zlib general purpose compression library, version 1.2.7, was ANSIfied and modified according to GLPK requirements and included in the distribution as an external software module. This version replaced the old one (1.2.5). For details please see src/zlib/README. * src/glpk.h, src/env/time.c The API routine glp_time was changed to return double rather than glp_long. * src/glplib02.c Routines that implement glp_long type (64-bit arithmetic) were removed from the package. * src/glpk.h, src/env/alloc.c New API routine glp_alloc was added. It makes obsolete two API routines glp_malloc and glp_calloc which were replaced by macros to use glp_alloc (hence 36:0:0). * src/glpios10.c A bug was fixed that caused numerical instability in the FPUMP heuristic (the bug was introduced in glpk 4.40). Fri May 24 12:00:00 2013 Andrew Makhorin * GLPK 4.50 (35:0:0) has been released * src/Makefile.am Though API was not changed since 4.49, symbols _glp_lpx_* were removed from the export list, hence 35:0:0. * src/glpfhv.h, src/glpfhv.c Old routines for FHV-factorization were removed. * src/bflib/*.h, src/bflib/*.c New version of basis factorization routines, including routines for FHV-factorization, were added. * src/glpbfd.c LP basis factorization driver was changed according to the new routines for FHV-factorization. * doc/glpk.tex Some clarifications about using the name index routines were added. Thanks to Xypron for suggestion. * doc/gmpl.tex Some typos were corrected. Thanks to Jeffrey Kantor for report. * src/glprlx.c A serious bug was *tentatively* fixed. This bug is inherited from the original Fortran version of the RELAX-IV code. Unfortunately, the code is very intricate, so this bug is still under investigation. Thanks to Sylvain Fournier for bug report. RELAX-IV bug details -------------------- In the original RELAX-IV code there are four similar fragments in subroutines ascnt1 and ascnt2 like this: C C DECREASE THE PRICES OF THE SCANNED NODES BY DELPRC. C ADJUST FLOW TO MAINTAIN COMPLEMENTARY SLACKNESS WITH C THE PRICES. C NB = 0 DO 6 I=1,NSAVE . . . IF (RC(ARC).EQ.0) THEN DELX=DELX+U(ARC) NB = NB + 1 PRDCSR(NB) = ARC END IF . . . On some instances the variable NB becomes greater than N (the number of nodes) that leads to indexing error, because the array PRDCSR is declared as array of N elements (more precisely, as array of MAXNN elements, however, NB becomes even much greater than MAXNN). Tue Apr 16 12:00:00 2013 Andrew Makhorin * GLPK 4.49 (34:0:0) has been released * glprlx.c, glprlx.h C version of the Fortran code RELAX-IV (relaxation method of Bertsekas and Tseng) was added. * glpapi17.c API routine glp_mincost_relax4, which is a driver to RELAX-IV code, was added and documented. * glpnet03.c API routine glp_netgen_prob (Klingman's standard network problems) was added and documented. * glpapi12.c A bug (wrong dual feasibility test) was fixed in API routine glp_warm_up. Thanks to David T. Price for bug report. * glpapi10.c Obsolete API routine lpx_check_kkt was replaced by API routine glp_check_kkt. * glpk.h All old API routines whose names begin with 'lpx_' were removed from API and no more available. * glpk.tex, graphs.tex These documents were essentially reformatted. Mon Jan 28 12:00:00 2013 Andrew Makhorin * GLPK 4.48 (33:0:0) has been released * src/glpmps.c A bug in glp_write_mps was fixed. Thanks to Raniere Gaia Costa da Silva for bug report. * glpk.h glp_prob declaration changed (now it is incomplete struct); glp_tree declaration changed (now it is incomplete struct); glp_tran declaration changed (now it is incomplete struct); glp_long declaration removed; glp_time declaration removed; glp_difftime removed from API; glp_data removed from API; glp_sdf_* removed from API; glp_mem_usage declaration changed (glp_long -> size_t); glp_realloc declaration added (not documented yet). * glpenv.h, glpenv05.c Dynamic memory allocation routines were reimplemented. * glpk.h, glpnet03.c Routine glp_netgen_prob was added (not documented yet). * configure.ac Check for gmp.h was added. Thanks to Heinrich Schuchardt for suggestion. * w32/glpk.def, w64/glpk.def Changes were made to export only API symbols. Fri Sep 09 12:00:00 2011 Andrew Makhorin * GLPK 4.47 (32:0:32) has been released * src/glpapi20.c New API routine glp_infeas1 to solve 0-1 feasibility problem was added and documented (see doc/cnfsat.pdf). * src/glpnpp06.c Some new preprocessor routines for SAT-CNF encoding, which are used by the routine glp_intfeas1, were added. * src/glpnpp.h The header was modified due to additions. * src/glpapi21.c The glpsol solver was modified to bypass model postprocessing if the solution reported is neither optimal nor feasible. * src/glpapi21.c New glpsol options (--minisat and --objbnd) were added. * examples/pbn/*.* The paint-by-numbers puzzle model (pbn.mod) was modified to print solution in PostScript format and to check for multiple solutions. Some benchmark examples from encoded in MathProg were included in the distribution. For more details see examples/pbn/README and examples/pbn/pbn.pdf. * examples/Makefile.am A minor bug was fixed to correctly build glpk in a separate directory. Thanks to Marco Atzeri for bug report. Tue Aug 09 12:00:00 2011 Andrew Makhorin * GLPK 4.46 (31:0:31) has been released * src/glpk.h, src/Makefile glpk.h was relocated from 'include' to 'src', and 'include' subdir was removed; src/Makefile.am was changed appropriately. * src/zlib/*.* zlib general purpose compression library, version 1.2.5, was ANSIfied and modified according to GLPK requirements and included in the distribution as an external software module. For details see src/zlib/README. * src/glpdmx.c The following new API routines were added: glp_read_cnfsat - read CNF-SAT problem data in DIMACS format glp_check_cnfsat - check for CNF-SAT problem instance glp_write_cnfsat - write CNF-SAT problem data in DIMACS format * src/minisat/*.* MiniSat, a CNF-SAT solver, version 1.14.1, was ANSIfied and modified according to GLPK requirements and included in the distribution as an external software module. For details see minisat/README and minisat/LICENSE. * src/glpapi19.c The API routine glp_minisat1, which is a driver to the MiniSat solver, was included in the package. * doc/satcnf.* The document "CNF Satisfiability Problem" was included in the package. It is a supplement to the GLPK Reference Manual. * src/glpapi20.c New glpsol options (--cnf, --wcnf, and --minisat) was added. * glpsql.c Some bugs were fixed. Thanks to Xypron . Sun Dec 05 12:00:00 2010 Andrew Makhorin * GLPK 4.45 (30:0:30) has been released * glplpx01.c A bug (it_cnt) in routine reset_parms was fixed. Thanks to Ali Baharev for report. * glpmpl03.c A bug (print "text\") was fixed. Thanks to Xypron for report. * glpsql.c A precision bug was fixed. Thanks to Xypron . * glpk.tex Some typos were corrected. Thanks to Robbie Morrison . Thu Jun 03 12:00:00 2010 Andrew Makhorin * GLPK 4.44 (29:0:29) has been released * glpapi14.c glpmpl.h glpmpl01.c glpmpl03.c glpmpl04.c Implemented suffixes for variables and constraints. * glpmpl06.c Made changes to allow comment records in CSV files. * glpapi17.c Added and documented new API routine glp_cpp to solve Critical Path Problem. Sat Feb 20 12:00:00 2010 Andrew Makhorin * GLPK 4.43 (28:0:28) has been released * glplib.h, glplib.c, glpenv.h, glpenv.c The module glpenv was split into two modules glpenv and glplib. * glpenv01.c, glpenv03.c, glpenv04.c, glpenv06.c The following new API routines were added and documented: glp_init_env, glp_free_env, glp_open_tee, glp_close_tee, glp_error (macro), glp_difftime. * glpapi16.c New API routine glp_top_sort (topological sorting of ayclic digraph) was added and documented. * glpapi17.c A serious bug was fixed in the routine glp_asn_prob_hall. * glpnpp05.c A bug was fixed in the LP/MIP preprocessor (hidden covering inequalities). * glpsql.c Some improvements were made in the table driver (NULL data). Thanks to Xypron for contribution. * configure.ac Changes were made to use .dylib rather than .so under Mac OS. Thanks to Noli Sicad for testing Wed Jan 13 12:00:00 2010 Andrew Makhorin * GLPK 4.42 (27:0:27) has been released * glpapi01.c, glpapi11.c, glpapi12.c, glpdmx.c The following new API routines were added and documented: glp_check_dup (check for duplicate elements in sparse matrix); glp_sort_matrix (sort elements of the constraint matrix); glp_read_prob (read problem data in GLPK format); glp_write_prob (write problem data in GLPK format); glp_analyze_bound (analyze active bound of non-basic variable); glp_analyze_coef (analyze obj. coefficient at basic variable); glp_print_ranges (print sensitivity analysis report; replaces lpx_print_sens_bnds). * glpapi20.c New command-line options were added to glpsol: --glp (read problem data in GLPK format); --wglp (write problem data in GLPK format); --lp (replaces --cpxlp); --wlp (replaces --wcpxlp); --ranges (print sensitivity analysis report). * glpapi06.c In the routine glp_init_smcp default value of the parameter out_frq was changed to 500 (it was 200). * glpipp.h, glpipp01.c, glpipp02.c The old MIP preprocessor module was removed. * glpapi09.c Now the MIP solver uses the new MIP preprocessor (NPP). * glplpx03.c lpx_write_opb was disabled due to replacing IPP with NPP. * glpnet09.c Kellerman's heuristic to cover edges by cliques was added. * glplib08.c Recognition of special filenames "/dev/stdin", "/dev/stdout", and "/dev/stderr" was added. * glpk.tex Chapter "Graph and network routines" was carried out from the reference manual as a separate document. Mon Dec 21 12:00:00 2009 Andrew Makhorin * GLPK 4.41 (26:0:26) has been released * glpapi12.c The following new API routines were added: glp_transform_row (replaces lpx_transform_row); glp_transform_col (replaces lpx_transform_col); glp_prim_rtest (replaces lpx_prim_ratio_test); glp_dual_rtest (replaces lpx_dual_ratio_test). Note that values returned by glp_prim_rtest and glp_dual_rtest differ from the ones retutned by the deprecated routines. * glpnpp*.* The LP/MIP preprocessor was essentially re-implemented. * glpios03.c The feature to remove inactive cuts from the active subproblem was implemented. * glpios11.c The feature processing cuts stored in the cut pool was improved (now it uses estimation of objective degradation). * glpscg.* Obsolete implemetation of the conflict graph was removed. * glpmpl.h, glpmpl03.c, glpmpl04.c FILE was replaced by XFILE to allow using GLPK I/O routines. * glpsql.c, examples/sql, doc/tables.tex The SQL table driver was changed to allow multiple arguments separated by semicolon in SQL statements. Thanks to Xypron . * glpk.h, glpapi14.c New API routine glp_time was added (not documented yet). * glpapi20.c Two new options were added to glpsol: --seed value (initialize pseudo-random number generator used in MathProg model with specified seed value), and --ini filename (use as initial basis previously saved with -w option). * examples/xyacfs.mod Thanks to Nigel Galloway for contribution. * examples/dbf/*.* Thanks to Noli Sicad for contribution. * w32/*.*, w64/*.* Scripts to build GLPK with Microsoft Visual Studio 2010 were added. Thanks to Xypron for contribution and testing. Tue Nov 03 12:00:00 2009 Andrew Makhorin * GLPK 4.40 (25:0:25) has been released * glpdmx.c Two new API routines were added: glp_read_ccdata (read graph in DIMACS clique/coloring format); glp_write_ccdata (write graph in DIMACS clique/coloring format). Also an example file examples/sample.col was added. * glpapi19.c, glpnet08.c New API routine glp_wclique_exact was added. It is intended to find a maximum weight clique with the exact algorithm developed by Prof. P. Ostergard. * glpnpp02.c A bug was fixed in the LP preprocessor (routine npp_empty_col). Thanks to Stefan Vigerske for the bug report. * glpios10.c A bug was fixed and some improvements were made in the FPUMP heuristic module. Thanks to Xypron . * glpapi12.c A bug was fixed in the API routine glp_warm_up (dual feasibility test was incorrect in maximization case). Thanks to Uday Venkatadri for the bug report. * glpapi16.c Two new API routines were added: glp_del_vertices (remove vertices from graph); glp_del_arc (remove arc from graph). * glpios09.c The hybrid pseudocost branching heuristic was included in the MIP solver. It is available on API level (iocp.br_tech should be set to GLP_BR_PCH) and in the stand-alone solver glpsol (via the command-line option --pcost). This heuristic may be useful on solving hard MIP instances. * glpios03.c The branching heuristic by Driebeck and Tomlin (used in the MIP solver by default) was changed to switch to branching on most fractional variable if an lower bound of degradation of the objective is close to zero for all branching candidates. Sun Jul 26 12:00:00 2009 Andrew Makhorin * GLPK 4.39 (24:0:24) has been released * glpsdf.c New API routines to read plain data files were added. * glpcpx.h, glpini.h, glpscl.h These headers were removed. * glpcpx.c API routines glp_read_lp and glp_write_lp to read/write files in CPLEX LP format were re-implemented. Now glp_write_lp correctly writes double-bounded (ranged) rows by introducing slack variables rather than by duplicating the rows. The data structure glp_cpxcp and routine glp_init_cpxcp were added. * amd/* The 'xfree(NULL)' bug was fixed in the AMD routines. Thanks to Niels Klitgord for the bug report. * glpapi16.c New API routines glp_set_vertex_name, glp_create_v_index, glp_find_vertex, and glp_delete_v_index were added. * glpdmx.c New API routines glp_read_asnprob, glp_write_asnprob, glp_read_ccformat, and glp_write_ccformat were added (the two latter routines are not documented yet). * glpapi18.c New API routines glp_check_asnprob, glp_asnprob_lp, glp_asnprob_okalg, and glp_asnprob_hall were added. * glpini01.c, glpini02.c The message "Crashing..." was changed to "Constructing initial basis..." due to suggestion by Thomas Kahle . * glpapi14.c New API routines glp_printf, glp_vprintf, glp_malloc, glp_calloc, glp_free, and glp_assert were added. * glplpp.h, glplpp01.c, glplpp02.c Old LP presolver routines were removed. Now glp_simplex uses new preprocessing routines (see glpnpp). * glpapi12.c New API routine glp_warm_up was added; it replaces the routine lpx_warm_up. Sat May 02 12:00:00 2009 Andrew Makhorin * GLPK 4.38 (23:0:23) has been released * glpmps.c API routines to read/write MPS files were re-implemented. * glpspx02.c Some improvements were made in the dual simplex routine. * glpk.h New structure glp_iptcp was added. * glpnpp.h, glpnpp01.c, glpnpp02.c New LP/MIP preprocessor. Currently it includes only some basic routines and used only in the interior-point solver. * glpapi08.c API routine glp_interior was replaced by an improved version (new LP/MIP preprocessor, new ordering algorithms). New API routine glp_init_iptcp was added. API routine glp_ipt_status may return two new statuses due to changes in glp_interior. * glpsol.c New command-line options were added (ordering algorithm used in the interior-point solver). * amd/*.*, colamd/*.* Two external software modules AMD and COLAMD/SYMAMD used in the interior-point solver were included in the distribution. For details see amd/README and colamd/README. * glpnet03.c, glpnet04.c, glpnet05.c A minor bug was fixed (_G => G_). Thanks to Nelson H. F. Beebe for bug report. Sun Mar 29 12:00:00 2009 Andrew Makhorin * GLPK 4.37 (22:0:22) has been released * glpk.h iocp.fp_heur was added to enable/disable fpump heuristic. * glpios10.c ios_feas_pump was added (feasibility pump heuristic). * glpsol.c --fpump command-line option was added. * glpsds.c Plain data set routines were added to facilitate reading plain data in application programs. Currently these routines are not in API, though declared in glpk.h. * glpapi08.c A bug was fixed in the internal routine restore. (Due to this bug dual solution components were computed incorrectly if the problem was scaled.) * glpapi10.c, glpapi11.c The following new API routines were added: glp_print_sol (replaces lpx_print_sol); glp_print_ipt (replaces lpx_print_ips); glp_print_mip (replaces lpx_print_mip); _glp_check_kkt (replaces lpx_check_kkt, lpx_check_int). Now the routine lpx_print_prob (deprecated) is equivalent to the routine glp_write_lp. * glpapi18.c, glpapi19.c The following new API routines were added: glp_read_graph (read graph from plain text file); glp_write_graph (write graph to plain text file); glp_weak_comp (find all weakly connected components); glp_strong_comp (find all strongly connected components). * configure.ac, Makefile.am Changes were made: (a) to allow using autoreconf/autoheader; (b) to allow building glpk in a directory other than its source directory. Thanks to Marco Atzeri for bug report. * examples/shiftcover.mod An example model in MathProg was added. Thanks to Larry D'Agostino for contribution. Fri Feb 06 12:00:00 2009 Andrew Makhorin * GLPK 4.36 (21:0:21) has been released * glpnet06.c, glpnet07.c, glpapi19.c The following new API routines were added: glp_mincost_okalg find minimum-cost flow with out-of-kilter algorithm glp_maxflow_ffalg find maximal flow with Ford-Fulkerson algorithm * glpsol.c Two new command-line options were added: --mincost read min-cost flow data in DIMACS format --maxflow read maximum flow data in DIMACS format * doc/glpk.* New edition of the reference manual was included. * glpk.h Duplicate symbols were removed to allow using swig. Thanks to Kelly Westbrooks and Nigel Galloway for suggestion. * glpcpx.c A minor defect was fixed in the routine glp_write_lp. Thanks to Sebastien Briais for bug report. * glpsql.c A minor bug was fixed. Thanks to Xypron for patch. * examples/hashi.mod, examples/shikaku.mod Two example models in MathProg were added. Thanks to Sebastian Nowozin for contribution. * examples/qfit.mod, examples/yacfs.mod Two example models in MathProg were added. Thanks to Nigel Galloway for contribution. Fri Jan 09 12:00:00 2009 Andrew Makhorin * GLPK 4.35 (20:0:20) has been released * glpk.h, glpapi.c, glpnet.c The following new API routines were added: glp_create_graph create graph glp_set_graph_name assign (change) graph name glp_add_vertices add new vertices to graph glp_add_arc add new arc to graph glp_erase_graph erase graph content glp_delete_graph delete graph glp_read_mincost read minimum cost flow problem data in DIMACS format glp_write_mincost write minimum cost flow problem data in DIMACS format glp_mincost_lp convert minimum cost flow problem to LP glp_netgen Klingman's network problem generator glp_gridgen grid-like network problem generator glp_read_maxflow read maximum flow problem data in DIMACS format glp_write_maxflow write maximum flow problem data in DIMACS format glp_maxflow_lp convert maximum flow problem to LP glp_rmfgen Goldfarb's maximum flow problem generator * doc/glpk.* New edition of the reference manual was included. * examples/sample.min, examples/sample.max Two example data files in DIMACS format were added. * glplib04.c The statement "if (c = '\n') fflush(stdout)" was added to the internal routine xputc to provide "real-time" terminal output. Thanks to Luiz Bettoni for suggestion. * glpmpl05.c A minor bug was fixed in the internal routine mpl_fn_time2str. Thanks to Stefan Vigerske for bug report. * w32/makefile, w64/makefile The flag -O2 (/O2) was added to some makefiles. Thu Dec 04 12:00:00 2008 Andrew Makhorin * GLPK 4.34 (19:0:19) has been released * src/glpios03.c A bug was fixed in the internal routine branch_on. Thanks to Nigel Galloway for bug report. * src/glpmpl05.c Three new MathProg functions were included: gmtime obtaining current calendar time str2time converting character string to calendar time time2str converting calendar time to character string Thanks to Xypron . * doc/glpk.*, doc/gmpl.* A new edition of the GLPK reference manual and GNU MathProg language description were included. Thu Oct 30 12:00:00 2008 Andrew Makhorin * GLPK 4.33 (18:0:18) has been released * glpapi*.* The following new API routines were added: glp_copy_prob copy problem object content glp_exact solve LP in exact arithmetic (makes lpx_exact deprecated) glp_get_unbnd_ray determine variable causing unboundedness (makes lpx_get_ray_info deprecated) glp_interior solve LP with interior-point method (makes lpx_interior deprecated) * glpapi*.* The following new API routines for processing models written in the GNU Mathprog language were added to the package: glp_mpl_alloc_wksp allocate the translator workspace glp_mpl_read_model read and translate model section glp_mpl_read_data read and translate data section glp_mpl_generate generate the model glp_mpl_build_prob build LP/MIP instance from the model glp_mpl_postsolve postsolve the model glp_mpl_free_wksp deallocate the translator workspace (These routines make lpx_read_model deprecated.) * src/glpapi17.c, examples/glpsol.c The stand-alone solver glpsol was re-implemented with new API routines. * src/glpsql.c Some bugs were fixed in the SQL table driver. Thanks to Xypron . * examples/cplex/*.* A crude implementation of CPLEX-like interface to GLPK API was added to the package. See examples/cplex/README. Fri Oct 03 12:00:00 2008 Andrew Makhorin * GLPK 4.32 (17:0:17) has been released * glpmpl01.c A bug was fixed. Due to this bug iterated expressions having an indexing expression whose dummy indices are bound to some values, i.e. like sum{(i+1,j,k-1) in E} x[i,j,k] are evaluated incorrectly. Namely, current value of such expressions is not invalidated when corresponding dummy indices (like i and k in the example above) are changed, that erroneously results in the same value evaluated for the first time. * glpios03.c Euclidean reduction of the local objective bound was added in the routine glpios03.c. * glpapi11.c The following new branch-and-cut API routines were added: glp_ios_row_attr determine additional row attributes; glp_ios_pool_size determine current size of the cut pool; glp_ios_add_row add constraint to the cut pool; glp_ios_del_row delete constraint from the cut pool; glp_ios_clear_pool delete all constraints from the cut pool. * glpapi08.c The following new features were included in the branch-and-cut solver (the API routine glp_intopt): MIP presolver; mixed cover cut generator; clique cut generator. Due to the MIP presolver glp_intopt may additionally return GLP_ENOPFS and GLP_ENODFS, if primal or dual infeasibility of LP relaxation is detected by the presolver. Also the return code GLP_EMIPGAP was introduced to correctly indicate that the mip gap tolerance is reached. * glplpx01.c Now the obsolete API routines lpx_integer and lpx_intopt are completely superseded by the API routine glp_intopt that makes them deprecated. * glpmpl05.c Now the table driver name "iODBC" can be specified as "ODBC". * glpmpl03.c A bug fixed in the routine free_dca. Thanks to Xypron . * glpsql.c A bug was fixed in the SQL table driver. Thanks to Xypron . * examples/glpsol.c Changes were made to allow multiple MathProg data files. * doc/glpk.* A new edition of the GLPK reference manual was included. * doc/tables.* A new edition of the supplement "Using data tables in the GNU MathProg language" was included. Tue Sep 02 12:00:00 2008 Andrew Makhorin * GLPK 4.31 (16:0:16) has been released * glpspx.h, glpspx01.c, glpspx02.c, glpapi06.c The dual simplex solver (spx_dual_opt) was replaced by a new implementation of the two-phase dual simplex method (spx_dual). Old simplex method routines (spx_prim_opt, spx_prim_feas, and spx_dual_opt) were removed from the package. * glpk.h, glpscl.h, glpscl.c, glpapi04.c New API routine glp_scale_prob was added. It replaces routine lpx_scale_prob which is deprecated. * glpk.h, glpini.h, glpini01.c, glpini02.c, glpapi05.c New API routines glp_std_basis, glp_adv_basis, glp_cpx_basis were added. They replace routines lpx_std_basis, lpx_adv_basis, lpx_cpx_basis which are deprecated. * glpdmp.c 8-byte data alignment was added to the module (sufficient for both ILP32 and LP64 environments). * glplib07.c 16-byte data alignment was added to the module to provide compatibility with LP64 environment (8-byte is not sufficient due to jmp_buf; thanks to Xypron for investigation). * glplpx16.c New version of the routine lpx_write_pb was added. Thanks to Oscar Gustafsson for the contribution. * w32/VC9, w64/VC9 Makefiles and batch files were added to build GLPK under 32- and 64-bit Windows with Microsoft Visual Studio Express 2008. Thanks to Heinrich Schuchardt for the contribution and testing. * w32/DM, w32/OWC Makefiles and batch files were added to build GLPK with Digital Mars C/C++ 8.50 and Open Watcom C/C++ 1.6 (32-bit Windows). Wed Aug 13 12:00:00 2008 Andrew Makhorin * GLPK 4.30 (15:0:15) has been released * glpspx.h, glpspx03.c, glpapi06.c The primal simplex solver (spx_prim_opt, spx_prim_feas) was replaced by a new implementation (spx_primal), which currently provides the same features as the old version. * glpmpl01.c, glpmpl03.c Some changes were made in the MathProg translator to allow <, <=, >=, and > on comparing symbolic values. Thanks to Heinrich Schuchardt for patches. * glplpx10.c Internal routine set_d_eps in the exact LP solver was changed to prevent approximation errors in case of integral data. Thanks to Markus Pilz for bug report. XXX XXX XX 12:00:00 2008 Andrew Makhorin * GLPK 4.29 (14:0:14) has been released * configure.ac The configure script was changed to disable optional features by default. For details see file INSTALL. * glpipp02.c A bug was fixed in the internal routine reduce_bounds. Thanks to Anne-Laurence Putz for the bug report. * glpapi01.c New API routine glp_erase_prob was added. * glpapi13.c New API routines glp_read_mps and glp_write_mps were added. They replace API routines lpx_read_mps, lpx_read_freemps, lpx_write_mps, and lpx_write_freemps, which are deprecated. * glpapi14.c New API routines glp_read_lp and glp_write_lp were added. They replace API routines lpx_read_cpxlp and lpx_write_cpxlp, which are deprecated. * glpsql.c Minor bug was fixed. Thanks to Xypron for the bug report. Tue Mar 25 12:00:00 2008 Andrew Makhorin * GLPK 4.28 (13:0:13) has been released * glplib.h, glplib.c Three wrapper routines xdlopen, xdlsym, and xdlclose, which provide the shared library support, were added. A particular version of these routines depends on the option --enable-dl passed to the configure script (see file INSTALL for details). Thanks to Rafael Laboissiere for useful advices concerning the shared library support. * glpsql.c A static linking to iODBC and MySQL libraries used in the MathProg table drivers was replaced by a dynamic linking to corresponding shared libraries. Many thanks to Heinrich Schuchardt for the contribution and to Vijay Patil for testing this feature under Windows XP. * glpgmp.h, glpgmp.c A bug (which appeared only on 64-bit platforms) was fixed. Thanks to Axel Simon for the bug report. * glpapi.c A bug was fixed in the api routine glp_add_cols. (If the basis is valid, adding column keeps it valid, however, col->bind was set to -1 rather to 0.) Thanks to Cedric[FR] for the bug report. * glplib.c 64-bit unsigned int type glp_ulong and corresponding routines were replaced by 64-bit signed int type xlong_t. * glpk.h, glpapi.c The type glp_ulong was replaced by glp_long. This affects only the api routine glp_mem_usage. * glplib.c Compressed data file support was added. This feature requires the zlib data compression libraries and allows compressing and decompressing .gz files "on the fly". * glpcli.h, glpcli.c Command-line interface routines were added. (This feature is incomplete so far.) Sun Mar 02 12:00:00 2008 Andrew Makhorin * GLPK 4.27 (12:0:12) has been released * glpsql.h, glpsql.c Two MathProg table drivers for iODBC and MySQL contributed by Heinrich Schuchardt were added to the package. * glpmpl05.c Mathprog table driver for xBASE was added to the package. * glpmpl03.c A minor was fixed in the MathProg translator (if some field specified in the table statement is missing in corresponding input table, the bug causes abnormal termination). Thanks to Heinrich Schuchardt for the bug report. * glpmpl.h, glpmpl.c STRING data type was replaced by plain character strings. Sun Feb 17 12:00:00 2008 Andrew Makhorin * GLPK 4.26 (11:0:11) has been released * glpmpl.h, glpmpl01.c, glpmpl03.c, glpmpl05.c The table statement was implemented. Description of this new feature is given in file doc/tables.txt. * glpios03.c A bug causing zero divide error on computing euclidean norm of the cut coefficient vector was fixed. Wed Dec 19 12:00:00 2007 Andrew Makhorin * GLPK 4.25 (10:0:10) has been released * glpapi10.c Routines lpx_eval_tab_row and lpx_eval_tab_col were replaced by glp_eval_tab_row and glp_eval_tab_col. * glpios03.c, glpios05.c Gomory's mixed integer cuts were implemented. * glpscs.h, glpscs.c Segmented character string routines are no longer used and were removed from the package. Wed Nov 21 12:00:00 2007 Andrew Makhorin * GLPK 4.24 (9:0:9) has been released * src/glplpx16.c A bug was fixed in the routine lpx_write_cpxlp. If a variable x has upper bound and no lower bound, it should appear in the bounds section as "-inf <= x <= u", not as "x <= u". Thanks to Enric Rodriguez for the bug report. * src/glpios03.c, src/glpios04.c, src/glpios05.c MIR (mixed integer rounding) cuts were implemented. Sun Oct 28 12:00:00 2007 Andrew Makhorin * GLPK 4.23 (8:0:8) has been released * src/glplib05.c, configure.ac Check for vsnprintf was added. * include/glppds.h, src/glppds.c A module to scan plain data was added. * src/glpapi09.c The following new API routines were added: glp_read_sol read basic solution from text file; glp_write_sol write basic solution to text file; glp_read_ipt read interior-point solution from text file; glp_write_ipt write interior-point solution to text file; glp_read_mip read MIP solution from text file; glp_write_mip write MIP solution to text file. * src/glpapi12.c Advanced API routine glp_free_env was added. * examples/glpsol.c The following three command-line options were added: --mipgap tol set relative MIP gap tolerance -r filename read solution from filename -w filename write solution to filename Wed Sep 19 12:00:00 2007 Andrew Makhorin * GLPK 4.22 (7:0:7) has been released * src/glpios02.c A bug was fixed in the MIP preprocessor (ios_preprocess_node). Thanks to Roberto Bagnara (Department of Mathematics, University of Parma, Italy) for the bug report. * src/glpios02.c A bug was fixed in the MIP preprocessor (col_implied_bounds), due to which constraint coefficients with small magnitude could lead to wrong implied bounds of structural variables. * src/glpipp02.c A similar bug was fixed in the routine reduce_bounds. * src/glpapi01.c A bug was fixed in the routines glp_set_mat_row and glp_set_mat_col. (The bug appeared due to incorrect removing zero elements from the row/column lists.) * src/glplpx14.c A bug was fixed in the API routines lpx_read_mps and lpx_read_freemps, due to which bounds of type LI specified in BOUNDS section were incorrectly processed. * src/glplib05.c A call to standard function vsprintf was replaced by a call to vsnprintf for security reasons. Many thanks to Peter T. Breuer and Rafael Laboissiere . Tue Aug 28 12:00:00 2007 Andrew Makhorin * GLPK 4.21 (6:0:6) has been released * glpscg.h, glpscg.c Routines to maintain sparse cliqued graph were added. * glpios02.c MIP preprocessing routines were added. * glpk.h, glpios.h, glpios03.c New reasons for calling the callback routine were introduced in the MIP solver. * glpapi08.c Default backtracking strategy was changed to best local bound. * glpapi11.c New API routine glp_term_out to enable/disable terminal output was added. * glprng.h, glprng02.c Two routines to generate uniformly distributed pseudo-random floating-point numbers were added. Thu Jul 26 12:00:00 2007 Andrew Makhorin * GLPK 4.20 (5:0:5) has been released * glpk.h, glpapi08.c The routine lpx_integer was replaced by an equivalent routine glp_intopt. Also new API routine glp_init_iocp was added. * glpiet.h, glpiet.c Routines implementing the implicit enumeration tree are no longer used and therefore were removed from the package. * glpios.h, glpios01.c, glpios02, glpios03 Routines implementing the integer optimization suite being replaced by a new version were removed from the package. * glpmip.h, glpmip01.c, glpmip02.c Routines implementing the B&B method being replaced by a new version were removed from the package. * glpios.h, glpios01.c, glpios02.c Routines implementing a new version of the integer optimization suite (IOS) based on the B&B method were added to the package. * glpk.h, glpapi10.c Branch-and-bound interface routines were added to the package. * examples/tspsol.c The TSP solver based on old version of the integer optimization suite is no more supported and was removed from the package. * glpipp02.c An error in the routine reduce_bounds was fixed; thanks to Graham Rockwell for the bug report. * glpk.latex A new edition of the reference manual was included. Thu Jul 05 12:00:00 2007 Andrew Makhorin * GLPK 4.19 (4:0:4) has been released The principal change is upgrading to GPLv3. * glpapi01.c A serious bug in the routine glp_del_cols was fixed; thanks to Cedric[FR] for the bug report. The bug appeared because on deleting non-basic columns the basis header remained valid, however, contained invalid (old) column ordinal numbers. * glpapi10.c A new advanced API routine glp_mem_limit was added. * glplpx01.c The case GLP_EBOUND was added to the routine lpx_simplex. Thanks to Cameron Kellough for the bug report. * glplpx19.c An API routine lpx_write_pb to write the problem instance in OPB (pseudo boolean) format format was added. Thanks to Oscar Gustafsson for the contribution. * glpsol.c Two new options --wpb and --wnpb were added to glpsol to write the problem instance in OPB format. Mon Jun 25 12:00:00 2007 Andrew Makhorin * GLPK 4.18 (3:0:3) has been released * glplib.h Type names ulong_t and uldiv_t were changed to glp_ulong and glp_uldiv to avoid conflicts with standard type names on some platforms. Thanks to Boris Wirtz for the bug report. * glpbfd.*, glpfhv.*, glplpf.* LP basis factorization routines were made tidy. * glpk.h, glpapi04.c The following API routines were added: glp_set_rii, glp_set_sjj, glp_get_rii, glp_get_sjj. * glpk.h, glpapi06.c The routine lpx_simplex was replaced by an equivalent routine glp_simplex. Also new API routine glp_init_smcp was added. * glpk.h, glpapi09.c The following advanced API routines were added: glp_bf_exists, glp_factorize, glp_bf_updated, glp_get_bfcp, glp_set_bfcp, glp_get_bhead, glp_get_row_bind, glp_get_col_bind, glp_ftran, glp_btran. * glpk.latex A new edition of the reference manual was included. * examples/dea.mod, examples/food.mod, examples/food2.mod Three examples in the MathProg language were added. Thanks to Sebastian Nowozin . Sat May 26 12:00:00 2007 Andrew Makhorin * GLPK 4.17 (2:0:2) has been released * glpdmp.h, glpdmp.c Memory pool routines were replaced by a new version. * glpscs.h, glpscs.c Segmented string routines were replaced by a new version. * glplpx08.c, glplpx09.c Now the MIP problem may have no integer columns. * glpapi01.c The routines glp_set_mat_row, glp_set_mat_col, and glp_load_mat were modified to allow zero elements (which are not stored in the constraint matrix). * glpscf.h, glpscf.c Schur complement factorization routines were implemented. * glplpf.h, glplpf.c LP basis factorization routines based on LU-factorization and Schur complement were implemented. * glplpx02.c, glplpx03.c New control parameter LPX_K_BFTYPE was introduced to choose the basis factorization type used by the simplex method routines. * glpsol.c Three new command-line options were added to choose the basis factorization type used by the simplex method routines: --luf, --cbg, and --cgr. * glpk.latex A new edition of the reference manual was included. Sat May 05 12:00:00 2007 Andrew Makhorin * GLPK 4.16 (1:0:1) has been released * glpk.h, glpapi.c, glplpx01.c, glplpx02.c Names of a number basic api routines were changed and now have the prefix 'glp_'. To keep backward compatibility these routines are also available via their old names prefixed with 'lpx_'. * glplpx19.c Three new api routines were added: glp_version, glp_term_hook, and glp_mem_usage. * glpk.latex, gmpl.texi A new edition of the reference manuals was included. * lpglpk40.c This example program is no longer supported and therefore was removed from the package. Sun Feb 18 12:00:00 2007 Andrew Makhorin * GLPK 4.15 (0:0:0) has been released * configure.ac, Makefile.am Autotools specification files were changed to use GNU Libtool that allows building the static as well as shared GLPK library. Thanks to Rafael Laboissiere . Mon Feb 05 08:00:00 2007 Andrew Makhorin * GLPK 4.14 has been released Now GLPK conforms to ILP32, LLP64, and LP64 programming models (the latter seems to be the ultimate choice regarding 64-bit architectures). Note that GLPK itself is a 32-bit application, and the conformity only means that the package works correctly on all these arenae. Nevertheless, on 64-bit platforms it is possible to use more than 4GB of memory, if necessary. * Makefile Starting from this release only the header glpk.h is needed to be installed. * glplib01.c Two routines bigmul and bigdiv which performs multiplication and division of unsigned integers of arbitrary precision were added. * glplib02.c A set of 64-bit arithmetic routines were added. * glplib04.c Some low-level library routines were improved and renamed. * glpcfg.h The macro GLP_TM_SPEC were introduced to specify a version of the time routine depending on the host environment. Mon Nov 13 12:00:00 2006 Andrew Makhorin * GLPK 4.13 has been released * configure.in '-lm' bug was fixed. * glpbfx.h, glpbfx.c Basis factorization interface routines based on exact (bignum) arithmetic were implemented. * glpssx.h, glpssx1.c, glpssx2.c Simplex method routines based on exact (bignum) arithmetic were implemented. * glplpx6e.c The routine lpx_exact, which is an easy-to-use driver to the exact simplex method, was added. * glpsol.c Two command-line options were added: '--exact' and '--xcheck'. Wed Nov 08 12:00:00 2006 Andrew Makhorin * GLPK 4.12 has been released * glpcfg.h The package configuration file was added. * glplib2.c Alternative version of the routines umalloc, ucalloc, and ufree was provided. It does not limit the amount of allocated memory to INT_MAX bytes and therefore can be used on platforms where sizeof(void *) > sizeof(int). To enable this version one should define the preprocessor variable GLP_HUGE_MEM. * glprng.c The routine rng_create_rand was changed to initialize the generator using seed = 1, not 0, to conform ISO C requirements. * glpgmp.h, glpgmp.c A set of bignum arithmetic routines implementing operations on integers and rationals was added. These routines are compatible with the GNU MP library. NOTE: To attain a much better performance it is recommended to use, if possible, the original GNU MP library rather than the GLPK version, by defining the preprocessor variable GLP_USE_GMP. * glplux.h, glplux.c A tentative implementation of sparse LU-factorization based on exact (bignum) arithmetic was added. * glpssx.h, glpssx.c A tentative implementation of some simplex method routines based on exact (bignum) arithmetic was added. * glplpx6f.c A preliminary implementation of the routine lpx_exact_check was added. This routine checks the current basis for primal and dual feasibility using exact (bignum) arithmetic. * examples/glpsol.c The command-line option '--xcheck' was introduced to check the current basis for feasibility using exact (bignum) arithmetic. Tue Jul 25 12:00:00 2006 Andrew Makhorin * GLPK 4.11 has been released. * include/glpbfi.h, src/glpbfi.c Basis factorization interface routines were added. * include/glpluf.h, src/glpluf1.c Hypersparse solution routines were added. * include/glpinv.h, src/glpinv1.c Hypersparse solution routines (fake version) were added. * include/glpmpl.h, src/glpmpl.c Built-in functions card, length, and substr were implemented. Output redirection in the printf statement was implemented. * examples/graph.mod, examples/crypto.mod Two example models illustrating new features of the modeling language were included. Thu May 11 12:00:00 2006 Andrew Makhorin * GLPK 4.10 has been released. * src/glplpx8a.c A fragment was added to the routines lpx_read_mps and lpx_read_freemps to accept LI bound type (it is similar to LO, however, additionally marks the column as integer). * include/glpbfi.h, src/glpbfi.c The module glpbfi which implements the basis factorization interface (BFI) was added. * src/glplpx7a.c The routine lpx_cover_cut to generate mixed cover cuts was added. * src/glplpx7b.c The routine lpx_clique_cut to generate clique cuts and related routines to maintain the conflict graph were added. * include/glplpx.h, src/glplpx5.c The routine lpx_cpx_basis implementing Bixby's algorithm to construct an initial LP basis was added. * examples/glpsol.c Command-line option '--bib' was added which allows building an initial LP basis using Bixby's algorithm. Default command-line option '--mps' was changed to '--freemps'. * examples/cf12a.mod, examples/cf12b.mod Two examples in MathProg (curve fitting problem) were added. Thanks to Dr. Harley Mackenzie . Tue Jan 17 12:00:00 2006 Andrew Makhorin * GLPK 4.9 has been released. * glpipp.h, glpipp1.c, glpipp2.c A MIP presolver were implemented (currently incomplete). It is used internally in the routine lpx_intopt (see below). * glplpx6d.c, glplpx7a.c An advanced branch-and-bound solver (the routine lpx_intopt) were implemented. * glplpx6c.c The routine lpx_check_int to check MIP feasibility conditions was added. * glplpx8a.c The routine lpx_print_mip was changed to print MIP feasibility conditions. * glpmpl.h, glpmpl1.c, glpmpl3.c The built-in functions sin, cos, atan, and atan2 were added to the MathProg language. * doc/lang.* Some typos were fixed. Thanks to Minh Ha Duong (CIRED, CNRS). Wed Jan 12 12:00:00 2005 Andrew Makhorin * GLPK 4.8 has been released. * glpspx.h, glpspx1.c, glpspx2.c, glplpx6a.c Simplex method routines were changed due to a new format of the constraint matrix. * glpmat.h, glpmat.c Sparse matrix routines were re-implemented using storage-by-rows format. * glpipm.h, glpipm.c, glplpx6b.c Interior-point method routines were changed due to a new format of sparse matrices. * glpchol.h, glpchol.c Old version of Cholesky factorization routines being replaced by a new one (see glpmat.c) was removed from the package. * glplpx8c.c Minor bug was fixed in api routine lpx_read_cpxlp. Mon Aug 23 12:00:00 2004 Andrew Makhorin * GLPK 4.7 has been released. * glplpx.h, glplpx1.c New core API routines were added (but not documented yet): lpx_order_matrix, lpx_create_index, lpx_find_row, lpx_find_col, lpx_delete_index. * glplpx8a.c API routine lpx_read_mps was re-implemented, and two new API routines lpx_read_freemps and lpx_write_freemps were added to support free MPS format. * glplpx8c.c Two API routines lpx_read_cpxlp and lpx_write_cpxlp (formerly named lpx_read_lpt and lpx_write_lpt) were re-implemented. * glpmps.h, glpmps.c This module formerly used in lpx_read_mps was removed from the package. * glplpt.h, glplpt.c This module formerly used in lpx_read_lpt was removed from the package. * glpmip.h, glpmip1.h, glpmip2.h New MIP routines mip_best_node and mip_relative_gap were added due to suggestion of Brady Hunsaker . * glpsol.c The following new command-options were added: --freemps to read problem data in free MPS format --wfreemps to write problem data in free MPS format --cpxlp to read problem data in CPLEX LP format --wcpxlp to write problem data in CPLEX LP format --bas to read LP basis from a text file in MPS format --wbas to write LP basis to a text file in MPS format --mostf to use "most fractional" branching heuristic --bestb to use "best bound" backtracking heuristic * contrib/deli/*.* GLPK Delphi interface module was temporarily removed from the distribution due to licensing problems. * contrib/glpkmex/*.* GLPK Matlab interface module was temporarily removed from the distribution due to licensing problems. * contrib/jni/*.* GLPK Java interface module was temporarily removed from the distribution due to licensing problems. Wed Aug 04 12:00:00 2004 Andrew Makhorin * GLPK 4.6 has been released. * glpmpl.h, glpmpl1.c, glpmpl2.c, glpmpl3.c, glpmpl4.c Three new statements were implemented in the GNU MathProg language: solve, printf, and for. Also some bugs were fixed. * glplpx.h, glplpx8e.c Two API routines were added: lpx_read_prob and lpx_write_prob, which allow reading and writing problem data in GNU LP format. * glpsol.c Three new command-line options were added: --glp (to read problem data in GNU LP format), --wglp (to write problem data in GNU LP format), and --name (to change problem name). * glprng.h, glprng.c A portable pseudo-random number generator was implemented as a separate module. * glplib4.c The old implementation of a pseudo-random number generator was removed from the package. * doc/lang.*, doc/refman.* New edition of the GLPK documentation was included. * contrib/glpkmex/*.* A new version of GLPKMEX was included in the distribution. For more details see contrib/glpkmex/ChangeLog. Mon Jul 19 12:00:00 2004 Andrew Makhorin * GLPK 4.5 has been released. * glpmip.h, glpmip1.c, glpmip2.c, glplpx6c.c New implementation of the branch-and-bound method was added. It replaces the old implementation, which was removed from the package. * glpies.h, glpies1.c, glpies2.c, glpies3.c Modules used in the old implementation of the branch-and-bound method were removed from the package. * glplib2.c Now if the preprocessor variable GLPHUGEMEM is defined, other version of the routines umalloc, ucalloc, and ufree is used on compiling the package. This allows avoiding memory allocation problems on platforms where sizeof(void *) > sizeof(int), for example, where addresses are 64-bit while integers are 32-bit. The modification was made due to a bug report provided by Karel Zimmermann and Christophe Caron . Sat Jan 17 12:00:00 2004 Andrew Makhorin * GLPK 4.4 has been released. * glplpx.h, glplpx*.c All API routines were re-implemented using new data structures. Some new API routines were added and some existing API routines became obsolete as shown below: Obsolete API routine Equivalent new API routine lpx_check_name (no more supported) lpx_set_obj_c0 lpx_set_obj_coef lpx_set_row_coef (no more supported) lpx_set_col_coef lpx_set_obj_coef lpx_load_mat (no more supported) lpx_load_mat3 lpx_load_matrix lpx_unmark_all (no more supported) lpx_mark_row (no more supported) lpx_mark_col (no more supported) lpx_clear_mat (no more supported) lpx_del_items lpx_del_rows, lpx_del_cols lpx_get_row_bnds lpx_get_row_type, lpx_get_row_lb, lpx_get_row_ub lpx_get_col_bnds lpx_get_col_type, lpx_get_col_lb, lpx_get_col_ub lpx_get_obj_c0 lpx_get_obj_coef lpx_get_row_coef (no more supported) lpx_get_col_coef lpx_get_obj_coef lpx_get_row_mark (no more supported) lpx_get_col_mark (no more supported) lpx_get_row_info lpx_get_row_stat, lpx_get_row_prim, lpx_get_row_dual lpx_get_col_info lpx_get_col_stat, lpx_get_col_prim, lpx_get_col_dual lpx_get_ips_stat lpx_ipt_status lpx_get_ips_row lpx_ipt_row_prim, lpx_ipt_row_dual lpx_get_ips_col lpx_ipt_col_prim, lpx_ipt_col_dual lpx_get_ips_obj lpx_ipt_obj_val lpx_get_mip_stat lpx_mip_status lpx_get_mip_row lpx_mip_row_val lpx_get_mip_col lpx_mip_col_val lpx_get_mip_obj lpx_mip_obj_val Obsolete API routines were kept for backward compatibility, however, they will be removed in the future. * doc/refman.* New edition of the GLPK reference manual containing description of all new API routines was included. * contrib/glpkmex/*.* GLPKMEX, a Matlab MEX interface to GLPK package, contributed by Nicolo Giorgetti was included. * doc/GLPK_FAQ.txt GLPK FAQ contributed by Harley Mackenzie was included. Fri Dec 12 12:00:00 2003 Andrew Makhorin * GLPK 4.3 has been released. * configure.in The bug, due to which the standard math library is not linked on some platforms, was fixed. * glpmpl3.c The bug (0 ** y) was fixed in the routine fp_power. * glpmpl.h, glpmpl1.c, glpmpl3.c Some new built-in functions (round, trunc, Irand224, Uniform01, Uniform, Normal01, Normal) were added to the MathProg language. * glpmpl1.c The MathProg syntax was changed to allow writing 'subj to'. * glplpx.h, glplpx1.c, glplpx2.c The new api routine lpx_get_ray_info was added. * glplpx8a.c The api routine lpx_print_sol was changed to print the number of non-basic variable, which causes primal unboundness. * glpmps.c The code was changed to avoid errors on compiling the package on Mac OS X. Thanks to Andre Girard for the bug report. * doc/lang.*, doc/refman.* Several typos were fixed and some new material was added in the glpk documentation. Fri Nov 14 12:00:00 2003 Andrew Makhorin * GLPK 4.2 has been released. * glpiet.h, glpiet.c, glpios.h, glpios1.c, glpios2.c, glpios3.c A preliminary implementation of the Integer Optimization Suite (IOS) was included in the package. Eventually IOS will replace the Implicit Enumeration Suite (IES). * glplpx.h, glplpx6d.c A dummy version of the integer optimization routine lpx_intopt was included in the package. Later this routine will replace the routine lpx_integer. * examples/glpsol.c A new command-line option --int-opt was added to the solver to call lpx_intopt rather than lpx_integer. * glpbcs.h, glpbcs1.c, glpbcs2.c Being replaced by IOS routines (see above) the Branch-and-Cut Framework (BCS) routines were removed from the package. * examples/tspsol.c Stand-alone Symmetric TSP solver was completely re-programmed using IOS routines. * glplib.h, glplib2.c, glplib4.c The random-number generator was implemented. It is based on the module GB_FLIB from the Stanford GraphBase originally developed by Donald Knuth. * glphbsm.c, glplpx8a.c, glpmps.c All calls to fopen/fclose were replaced by corresponding calls to ufopen/ufclose due to bug reports provided by Morten Welinder and . * glpmps.c The code was made re-entrant. * glplpx8b.c API routine lpx_print_sens_bnds for bounds sensitivity analysis contributed by Brady Hunsaker was added to the package. This feature is also available in glpsol via the command-line option --bounds. * contrib/jni/*.* New version of GLPK JNI (Java Native Interface) contributed by Chris Rosebrugh was added to the package. * contrib/deli/*.* GLPK DELI (Delphi Interface) contributed by Ivo van Baren was added to the package. * glplpx3.c Default method to scale the problem was changed to equilibration scaling (lp->scale = 1 in lpx_reset_parms). * glplpx6a.c Two minor (non-critical) typos were fixed due to report provided by Andrew Hamilton-Wright . * glplpp2.c An untested case (line 941) had been tested due to bug report provided by Jiri Spitz . * w32bc5.mak, w32vc6.mak, w32vc6d.mak, d32dmc.mak Several makefiles were added to allow building GLPK library for some non-GNU 32-bit platforms. Sat Aug 23 12:00:00 2003 Andrew Makhorin * GLPK 4.1 has been released. * glpmpl1.c, glpmpl3.c Some bugs were fixed in the MathProg translator due to the bug reports provided by Giles Thompson : conditional set expressions were incorrectly parsed; dimen attribute was not set by default when a set was used recursively in its own declaration; logical expressions ... in if ... then ... else ... did not work; displaying set expressions did not free memory allocated for temporary results. * glpmpl3.c (reduce_terms) Implementation of summation of linear forms over domain was improved to reduce complexity of that operation from O(n*n) to O(n*log n). The improvement was made due to a report provided by Sebastien de Menten . * glplpx6a.c (line 1056), glpmip1.c (line 641) Two minor bugs were fixed due to the bug report provided by Kendall Demaree . * glplpx.h, glplpx6a.c The method of one artificial variable implemented in the routine lpx_prim_art and used on the phase I in the glpk simplex solver has a serious defect: for some lp instances it erroneously reports that the problem has no primal feasible solution. This error appears when the column of the artificial variable, which enters the basis to make it primal feasible, has large constraint coefficients, that leads to small reduced costs of non-basic variables and premature termination of the search, i.e. to wrong conclusion that the problem has no primal feasible solution. To avoid this defect the routine lpx_prim_feas was included. It implements the method of implicit artifical variables (based on minimization of the sum of infeasibilities), which is a bit slower but much more robust. The routine lpx_prim_feas having the same functionality now is used instead the routine lpx_prim_art. * glpinv.h, glpinv.c The test used in the routine inv_update to detect low accuracy after updating LU-factorization of the basis matrix was replaced by a new, more robust test. * glplpx6c.c Selecting an active node to be solved next in the routine btrack_bestp was changed. Now, if any integer feasible solution has not been found yet, the routine chooses an active node which has the minimal sum of integer infeasibilities. * glpmip.h, glpmip1.c The additional flag int_obj was included in the structure MIPTREE used by the branch-and-bound. This flag is set in the routine mip_create_tree and used in the routine is_better. It means that the objective is integral, i.e. depends only on integer variables with integer objective coefficients. The test used in the routine check_integrality was also replaced by a new, more reasonable one. * glplpx1.c A minor bug was fixed in the routine lpx_check_name. * glpmpl.h, glpmpl4.c, glplpx8d.c The flag skip_data was added to the parameter list of the routine mpl_read_model. If this flag is set, the data section in the model file is ignored. Corresponding change was made in the routine lpx_read_model. Now, if both model and data files are specified, the data section in the model file is ignored. * glplpx8c.c A minor bug (wrong format used for writing free columns) in the routine lpx_write_lpt was fixed due to the bug report provided by Bernhard Schmidt * sample/glpsol.c The command-line parameter --tmlim, which allows limiting the solution time, was added. * doc/lang.*, doc/refman.* New edition of the GLPK documentation was included. * java-binding/*.* New version of the GLPK JNI (Java Native Interface) package was included in the distribution. * sample/lpglpk40.c A non-trivial example was added. It allows using GLPK as a base LP solver for Concorde, a program for solving Traveling Salesman Problem (TSP). For details see comments in lpglpk40.c. * sample/*.mod Some examples of LP and MIP models written in GNU MathProg were added. Tue May 06 12:00:00 2003 Andrew Makhorin * GLPK 4.0 has been released. * glpmpl.h, glpmpl1.c, glpmpl2.c, glpmpl3.c, glpmpl4.c The model translator for the GNU MathProg modeling language was implemented and included in the package. * glplpx.h, glplpx8d.c The api routine lpx_read_model, which is an interface to the MathProg translator, was included in the package. * glplpx.h, glplpx8a.c The api routine lpx_print_prob for writing LP/MIP problem data in plain text format was included in the package. * sample/glpsol.c New version of the GLPK stand-alone LP/MIP solver that supports the GNU MathProg modeling language was implemented. * doc/lang.latex, doc/lang.dvi, doc/lang.ps The document "GLPK: Modeling Language GNU MathProg" was included in the package. * doc/refman.latex, doc/refman.dvi, doc/refman.ps New edition of the GLPK Reference Manual was included in the package. * glplpx8c.c A bug in the api routine lpx_write_lpt was fixed. Due to that bug an addressing error occured in the routine if the objective function has the non-zero constant term. * glplan.h, glplan1.c, glplan2.c, glplan3.c, glplan4.c, * glplan5.c, glplan6.c, glplan7.c, glplan8.c, glplpx8b.c All modules of the translator for the GLPK/L modeling language were removed from the package, because GLPK/L being completely superseded by GNU MathProg is no more supported. Tue Mar 25 12:00:00 2003 Andrew Makhorin * GLPK 3.3 has been released. * glplpp.h, glplpp1.c, glplpp2.c An implementation of the built-in LP presolver was added to the package. * glplpx.h The flag presol was added to the structure LPX. This flag tells the lpx_simplex whether the built-in LP presolver should be used or not. By default this flag is off. Also three macros (namely LPX_E_NOPFS, LPX_E_NODFS, and LPX_K_PRESOL) that concern using the LP presolver were introduced. * glplpx3.c, glplpx6a.c These modules was changed to use the built-in LP presolver. * sample/glpsol.c Command line options --presol and --nopresol that concern using the LP presolver were added to the stand-alone LP/MIP solver. * glplan1.c This module was changed to allow declaring sets like A[1:10] in the models written in the GLPK/L modeling language. * doc/refman.latex, doc/lang.latex New editions of the documents "GLPK User's Guide" and "GLPK/L Modeling Language" were included in the distribution. * java-binding/*.* The package GLPK JNI (Java Native Interface) implementing Java binding for GLPK was included in the distribution. This package was developed and programmed by Yuri Victorovich . Tue Feb 18 12:00:00 2003 Andrew Makhorin * GLPK 3.2.4 has been released. * glplpx6b.c The code was changed to allow auxiliary variables have non-zero objective coefficients. Also a minor bug was fixed (the constant term was not considered on displaying the objective function value). * sample/glpsol.c The code was changed to fix a bug (the command-line option 'bfs' was not recognized). The bug was fixed due to report provided by Olivier . * glplpt.c The code was changed to fix a bug (binary variables were treated erroneously as integer ones). * glplpx6b.c The code was changed to fix a bug (variables that have no lower bounds were incorrectly processed on converting to the standard formulation). The bug was fixed due to report kindly provided by Kjell Eikland . Mon Nov 11 12:00:00 2002 Andrew Makhorin * GLPK 3.2.3 has been released. * glpmip.h, glpmip1.c A preliminary implementation of the branch-and-bound driver based on the implicit enumeration suite (glpies) was added to the package. This module is not documented yet. * glplpx6c.c A new implementation of the api routine lpx_integer which now is based on the b&b driver (see glpmip above) was included in the package. This new implementation has exactly the same functionality as the old version and therefore all changes are transparent to the api user. * glpbbm.h, glpbbm.c * glprsm.h, glprsm1.c, glprsm2.c * glplp.h, glplp.c These modules were removed from the package, because they were used only in the old version of the routine lpx_integer, which was replaced by the new version (see glplpx6c above). * glplpx.h, glplpx6a.c The api routine lpx_check_kkt was included in the package and its description was added in the reference manual. This routine allows checking Karush-Kuhn-Tucker optimality conditions for an LP solution. * glplpx.h, glplpx8a.c Now the api routine lpx_print_sol also prints information about "solution quality" obtained via the api routine lpx_check_kkt. * glplpx.h, glplpx8a.c New api routines lpx_read_bas and lpx_write_bas were included in the package and documented. The routine lpx_write_bas allows writing a current basis from an LP object to a text file in the MPS format. The routine lpx_read_bas allows reading a basis prepared in the MPS format from a text file into an LP object. * glplpt.c The parsing routine which reads LP problem data prepared in the CPLEX LP format was modified to allow specifying lower bounds of variables also in the form 'variable >= lower bound' (in the bounds section). This modification was made due to a notice provided by Ivan Luzzi . * glplpx.h, glplpx8c.c The api routine lpx_write_lpt which allows writing LP problem data from an LP object to a text file using the CPLEX LP format was included in the package and documented. * glplpx.h, glplpx3.c The control parameter LPX_K_LPTORIG that affects the behavior of the api routine lpx_write_lpt was introduced. * glplan6.c The semantics of the language GLPK/L was changed to allow selection in case when not all mute letters of a predicate (the operand that follows the keyword 'where') are presented in a parameter (the operand that precedes the keyword 'where'), i.e. to allow writing something like this: y[j] := sum(i, x[i] where p[i,j]); The paragraph "Selection" in the langauge description (page 25) was also correspondingly changed. This change of the language semantics was undertaken due to a notice provided by Peter Lee . * sample/hwd.lpm A nice example of LP model written in GLPK/L and contributed by Peter Lee was included in the package. * glplpx6b.c The api routine lpx_interior was modified: a) to compute dual values for all structural as well as auxiliary variables; b) to allow specifying non-zero objective coefficients at auxiliary variables. * sample/glpsol.c Three new command-line options were added to the solver, which are: --plain, --orig, and --wrlpt. Mon Oct 14 12:00:00 2002 Andrew Makhorin * GLPK 3.2.2 has been released. * glplpt.h, glplpt.c A module that reads LP/MIP problem data in CPLEX LP format was implemented. * glplpx8c.c An api routine lpx_read_lpt that reads LP/MIP problem data in CPLEX LP format was implemented. * sample/glpsol.c, sample/plan.lpt A new command-line option '--lpt' that allows reading LP/MIP problem data in CPLEX LP format was added to the solver. * doc/refman.latex, doc/refman.dvi, doc/refman.ps A new edition of the Reference Manual was included. * source/*.c Casting to (unsigned char) was added in some calls to the classification functions (isalpha, etc.). The bug was fixed due to report provided by Morten Welinder . * glplpx8a.c The local routine mps_numb used in the routine lpx_write_mps was modified to correctly format floating-point numbers that have two digits in the decimal exponent. The bug was fixed due to report provided by Vlahos Kiriakos . * glplan.h, glplan1.c, ..., glplan8.c Several serious bugs were fixed in the language processor due to reports provided by : (a) a static search tree used to find sparse array elements was sometimes overwritten that caused the message 'assertion failed' to appear; the bug was fixed by creating separate search trees in parsing routines; (b) a variable declared using the predicate-controlled variable declaration statement had wrong order of domain sets, because the variable array was built as a copy of the predicate array; the bug was fixed by using the internal routine transpose that coordinates mute letters (and therefore domain sets) on copying sparse arrays; (c) sometimes assignment statements like x[#a,#b,#c] := ... was incorrectly processed; the bug was fixed by including an appropriate check into the internal routine assign_stmt. * glp_simplex.c An additional check to see if all lower bounds are not greater than corresponding upper bounds was included in the routine to prevent wrong results to appear. Such incorrectness sometimes was not detected, namely, when variables with such bounds were non-basic and never entered the basis. * glpspx1.c Maximal number of simplex iterations before reinversion was decreased from 100 to 50. This allowed to improve accuracy and, that is more important, to reduce the solution time for many serial lp problems approximately 1.5--2 times. * glpspx2.c A check to see if all elements in the column chosen to enter the basis are close to zero in the routine spx_prim_chuzr was temporarily removed because this check gave wrong conclusion in case when the corresponding non-basic variable had zero column in the constraint matrix. An analogous check to see if all elements in the row chosen to leave the basis are close to zero in the routine spx_dual_chuzc was also temporarily removed on the same reason. The bug was fixed due to reports provided by Flavio Keidi Miyazawa and Vlahos Kiriakos . Mon Aug 12 12:00:00 2002 Andrew Makhorin * GLPK 3.2.1 has been released. * glpbcs.h, glpbcs1.c, glpbcs2.c * glpies.h, glpies1.c, glpies2.c, glpies3.c A preliminary implementation of the branch-and-cut framework was included in the package. * doc/brcut.txt The document "GLPK: A Preliminary Implementation of the Branch-And-Cut Framework" was included in the distribution. * sample/tspsol.c An illustrative program for solving symmetric TSP based on the branch-and-cut method was included in the package. * glpdmp.h, glpdmp.c A new, re-enterable version of routines for managing dynamic memory pools was included in the package. * glpavl.h, glpavl.c A new, re-enterable version of routines for managing AVL search trees was included in the package. * glplib.h, glplib2.c Two new low-level routines ufopen and ufclose were included in the package. * glplpx.h, glplpx7.c The following new api routines were added: lpx_eval_activity, lpx_eval_red_cost, lpx_reduce_form, lpx_mixed_gomory. * glptsp.h, glptsp.c A module for reading TSP data using TSPLIB format was included in the package. Mon Jul 15 12:00:00 2002 Andrew Makhorin * GLPK 3.2 has been released. * glplpx.h, glplpx1.c, glplpx2.c The identifier 'class' (used as a member name in the structure LPX and as an argument name in the routine lpx_set_class) was changed to 'clss' in order to avoid conflicts with C++ reserved words. * glpk.h, glplpx.h, glplpx1.c, glplpx2.c, glplpx6a.c, * glplpx6b.c, glplpx6c.c, glplpx7.c, glplpx8.c The following new api routines were added: lpx_set_obj_name, lpx_get_obj_name, lpx_get_row_mark, lpx_get_col_mark, lpx_transform_row, lpx_transform_col, lpx_prim_ratio_test, lpx_dual_ratio_test, lpx_interior, lpx_get_ips_stat, lpx_get_ips_row, lpx_get_ips_col, lpx_get_ips_obj, lpx_read_lpm, lpx_write_mps, lpx_print_ips. * glpsol.c The solver was completely re-programmed using new api routines. * lang.latex, lang.dvi, lang.ps New edition of the document "GLPK: Modeling Language GLPK/L" was included in the distribution. * refman.latex, refman.dvi, refman.ps New edition of the document "GLPK: Reference Manual" (which contains descriptions of all new api routines) was included in the distribution. * glpapi.h, glpapi1.c, glpapi2.c, glpapi3.c, glpapi4.c These files (which contain old api routines) were removed from the package. * glpipm1.c, glpipm2.c The file glpipm1.c was renamed to glpipm.c. The file glpipm2.c was used only by old api routines and therefore was removed from the package. * language.texinfo Old version of the document "GLPK: Modeling Language GLPK/L" was removed from the distribution. Mon May 27 12:00:00 2002 Andrew Makhorin * GLPK 3.1 has been released. * glplpx.h, glplpx1.c, glplpx2.c, glplpx3.c, glplpx4.c, * glplpx5.c, glplpx6.c, glplpx7.c, glplpx8.c A preliminary implementation of new API routines was completed. * refman.latex, refman.dvi, refman.ps A draft edition of the document "GLPK Reference Manual", which describes new API routines, was included. * glplib3.c A bug in measuring long time intervals was fixed up. * glprsm3.c This module contains some obsolete routines not longer used and therefore it was removed from the package (into the subdirectory 'oldsrc'). * glprsm.h Some declarations related to the module 'glprsm3.c' (see above) were removed. * guide.texinfo The document "GLPK User's Guide" describing old API routines was removed from the package (into the subdirectory 'oldsrc'). * newapi.txt The document "New GLPK API Routines" was removed at all, because it is superseded by the new reference manual (see above). Mon May 13 12:00:00 2002 Andrew Makhorin * GLPK 3.0.8 has been released. * glplpx.h, glplpx1.c, glplpx2.c, glplpx3.c, glplpx4.c, * glplpx5.c, glplpx6.c, glplpx7.c A preliminary (currently incomplete) implementation of new api routines was included. * sample/newsamp.c A sample program for the new api routines was included. * newapi.txt A draft of the document "New GLPK API Routines" was included. * glpapi2.c, glpapi5.c, glpapi6.c These modules (which contain the api routines glp_call_rsm1, glp_simplex1, glp_pivot_in, glp_pivot_out) were removed from the package (to the subdirectory 'oldsrc') since these routines are functionally superseded by the new api routines. * glpk.h, glpapi2.c, glpapi3.c, glpapi4.c The api routines glp_simplex2, glp_call_ipm1, glp_call_bbm1 were renamed to glp_simplex, glp_interior, glp_integer, respectively. * sample/glpsol.c Some command-line options (which got obsolete due to the recent changes in api) were excluded. * doc/guide.texinfo New edition of the document "GLPK User's Guide" was included in the distribution to reflect the changes in some api routines. * doc/libref.texinfo This document was removed from the package (to the subdirectory 'oldsrc') since it describes the library routines, most of which got obsolete and no longer used. * Makefile.in A minor bug was fixed up due to bug report from Hans Schwengeler . Mon Apr 22 12:00:00 2002 Andrew Makhorin * GLPK 3.0.7 has been released. * glpduff.h, glpduff.c, glpspx.h, glpspx1.c, glpspx2.c, * glpapi7.c These modules were replaced by a new implementation of the simplex method and therefore they were removed from the package (however they still can be found in the subdirectory 'oldsrc'). * glprsm1.c The routine crash_aa was replaced by a new implementation and therefore it was removed from the file 'glprsm1.c'. * glplpx.h, glplpx.c, glpspx.h, glpspx1.c, glpspx2.c, glpspx3.c, * glpspx4.c, glpapi7.c New (currently incomplete) implementation of the simplex method components was included in the package. Thu Mar 28 12:00:00 2002 Andrew Makhorin * GLPK 3.0.6 has been released. * glpluf.h, glpluf.c, glpinv.h, glpinv.c New version of LU-factorization and basis maintenance routines (based on Forrest-Tomlin updating technique) was implemented. * glpeta.h, glpeta.c, glpfhv.h, glpfhv.c, glpgel.h, glpgel.c, * glppfi.h, glppfi.c, glprfi.h, glprfi.c These routines implement some other forms of the basis matrix. Now they became obsolete being functionally superseded by the new version of basis maintenance routines (see above) and were removed from the package (however they still can be found in the subdirectory 'oldsrc'). * glpbbm.c, glprsm.h, glprsm1.h, glprsm2.h, glpspx.h, glpspx2.c, * glprsm2.c, glpsol.c Necessary changes were made in order to use the new version of basis maintenance routines. Tue Jan 29 12:00:00 2002 Andrew Makhorin * GLPK 3.0.5 has been released. Structure of the package was re-organized in order to simplify its maintenance. * doc/guide.texinfo New edition of the document "GLPK User's Guide" was included in the distribution. Now the document includes descriptions of some additional API routines recently added to the package. * doc/newapi.txt The document "Additional GLPK API Routines" was removed from the distribution, because the corresponding material was included in the user's guide (see above). Mon Dec 10 12:00:00 2001 Andrew Makhorin * GLPK 3.0.4 has been released. * glpspx.h, glpspx1.c, glpspx2.c, glpapi/glp_simplex2.h A new, more efficient version of the two-phase primal simplex method was implemented (advanced initial basis, projected steepest edge, recursive computations of solution components). * glpapi/glp_call_bbm1.c Now LP relaxation can be solved either using rsm1_driver(), or using glp_simplex2(). The choice is controlled by the parameter 'meth' (a member of struct bbm1). * sample/glpsol.c The new implementation of the simplex method is now used by default. The old version is available via --old-sim option. * glpmat/gm_scaling.c Now this routine displays only two lines: an initial "quality" and a final "quality". * glplp/prepro_lp.c Identifiers 'fmin' and 'fmax' renamed to 'f_min' and 'f_max' in order to avoid conflict with . The bug was fixed due to report provided by Sami Farin . Wed Oct 03 12:00:00 2001 Andrew Makhorin * GLPK 3.0.3 has been released. * glprsm/harris_row.c, glprsm/harris_col.c The relative tolerance used on the first pass of the two-pass ratio test was replaced by the absolute tolerance. * glprsm/rsm_primal.c, glprsm/rsm_feas.c, glprsm/rsm_dual.c The absolute tolerance passed to the two-pass ratio test routine was decaresed (for both primal and dual simplex). These changes were made in order to improve numerical stability of the simplex method. * glprsm/glp_call_rsm1.c, glprsm/glp_call_bbm1.c, * glprsm/glp_simplex1, glprsm/glp_pivoting.c Default form of the inverse was changed from RFI to AFI. Mon Sep 24 12:00:00 2001 Andrew Makhorin * GLPK 3.0.2 has been released. * glpfhv.h, glpfhv.c New version of the basis maintaining routines was implemented. These routines, which are based on so called FHV-factorization (a variety of LU-factorization) and Gustavson's data structures, perform the main operations on the basis matrix faster at the expense of some worsening numerical accuracy. * glprsm.h, glprsm/afi.c The routines, which implement AFI (Advanced Form of the Inverse) based on FHV-factorization, were added to the package. This new form is available via the parameter form = 3 (on API level) or via the option --afi (in GLPSOL solver). * EFI was renamed to PFI In order to correct terminology the acronym EFI (Elimination Form of the Inverse) was replaced by PFI (Product Form of the Inverse) everywhere in the source code and the documentation. * glpset/umalloc.c, glpset/ucalloc.c * glpset/get_atom.c, glpset/get_atomv.c These memory management routines were changed in order *not* to clear allocated memory blocks by binary zeros. Wed Aug 01 12:00:00 2001 Andrew Makhorin * GLPK 3.0.1 has been released. * glpapi/old_api.c, glplp/extract_lp.c, store_lpsol.c Old API routines were deleted from the package. * include/glpk.h, include/glpapi.h, include/glplp.h Specifications of old API routines and data structures were removed from the headers. * sample/glpsol.c New version of the stand-alone solver GLPSOL that now uses new API routines was implemented. * glpapi/glp_set_row_fctr.c, glpapi/glp_set_col_fctr.c, * glpapi/glp_get_row_fctr.c, glpapi/glp_get_col_fctr.c, * glpapi/glp_scale_prob.c Scaling routines were added. * glpapi/glp_write_mps.c The routine for writing problem data in MPS format was added. * glpapi/glp_simplex1.c Comprehensive driver to the simplex method was added. * glpapi/glp_pivoting.c The routines glp_pivot_in() and glp_pivot_out() intended for basis maintaining were added. * glprsm/create_rsm.c, glprsm/delete_rsm.c, glprsm/scale_rsm.c, * glprsm/build_basis.c Additional low level routines related to the simplex method were added. * glpk.h, glpapi.h, glprsm.h Additional specifications for new routines and data structures were added. * sample/lpglpk30.c A non-trivial example was added. It allows using GLPK as a base LP solver for Concorde, a program for solving Traveling Salesman Problem (TSP). For details see comments in 'lpglpk30.c'. * doc/newapi.txt The document "Additional GLPK API Routines" that describes some new API routines was included. Thu Jul 19 12:00:00 2001 Andrew Makhorin * GLPK 3.0 has been released. Now GLPK is provided with new API, which is intended for using the package in more complex algorithmic schemes. * glpapi/old_api.c All routines related to old API were gathered in one file named 'old_api.c'. * glpapi/*.c These routines that implement new API were added to the package. * include/glpk.h, include/glpapi.h Specifications of new API routines and data structures were added to these headers. Specifications of old API routines and data structures were locked by #ifdef GLP_OLD_API directive. * doc/guide.texinfo New edition of the document "GLPK User's Guide" that correspond to new API was included. Thu Jun 14 12:00:00 2001 Andrew Makhorin * GLPK 2.4.1 has been released. * doc/glpk_ml.texinfo The new document "Modeling Language GLPK/L" was included. * doc/glpk_ug.texinfo New edition of the document "GLPK User's Guide" was included. * doc/language.txt The preliminary document "GLPK/L Modeling Language: A Brief description" was removed from the distribution, because it has been replaced by the new document "Modeling Language GLPK/L". * glplang/l_spar.c The routine comparison() was re-programmed in order to implement the relation operation as specified in the language description. * glpmip.h, glpmip/*.c The partition 'glpmip' was renamed to 'glpbbm'. Thu May 10 12:00:00 2001 Andrew Makhorin * GLPK 2.4 has been released. Now GLPK includes an implementation of a preliminary version of the GLPK/L modeling language. * glplang.h, glplang/*.c The header 'glplang.h' and a set of routines that implements the GLPK/L language processor (the partition 'glplang') were added to the package. * doc/language.txt The document "GLPK/L Modeling Language: A Brief Description (Supplement to GLPK User's Guide)" in plain text format was included in the package (see the file 'language.txt' in the subdirectory 'doc' of the distribution). * ex/model1.lpm, ex/model2.lpm Two examples of model descriptions written in GLPK/L were added to the package. * sample/glpsol.c This program was modified in order: a) to allow processing model description written in GLPK/L; b) to allow solving pure LP problem using the interior point method. * sample/glpipm.c This program was removed from the package, because its function was passed to the GLPSOL solver. * Makefile.in This file was changed in order to install the GLPSOL solver executable. Mon Apr 09 12:00:00 2001 Andrew Makhorin * GLPK 2.3 has been released. * glpmip.h, glpmip/*.c These routines (that implement the branch-and-bound method) were re-programmed in order to improve robustness of implementation. In particular, heuristic routines were carried out from the main driver routine. Additional GLPK API routines were documented. New edition of the document "GLPK User's Guide" was included in the package. The preliminary document "Mixed Integer Programming Using GLPK Version 2.2 (Supplement to GLPK User's Guide)" was removed from the package, because this material was included in GLPK User's Guide. Thu Mar 15 12:00:00 2001 Andrew Makhorin * GLPK 2.2 has been released. Now GLPK includes a tentative implementation of the branch-and-bound procedure based on the dual simplex method for mixed integer linear programming (MIP). The preliminary document "Mixed Integer Programming Using GLPK Version 2.2 (Supplement to GLPK User's Guide)" was included into the package in plain text format (see the file 'mip.txt' in the subdirectory 'doc' of the distribution). * glpmip.h, glpmip/*.c, glpapi/glp_integer.c These routines (that implement the branch-and-bound method) were added to the package. * sample/glpsol.c This program was modified in order to allow solving LP and MIP problems. * glprsm/rsm_primal.c, glprsm/rsm_dual.c, glprsm/rsm_feas.c, * glprsm/rsm1_driver.c These routines (which are drivers to basic components of the revised simplex method) were added to the package. Mon Feb 19 12:00:00 2001 Andrew Makhorin * GLPK 2.1 has been released. * glprsm.h, glprsm/*.c These routines (that implement components of the revised simplex method) were re-programmed and documented. The document "GLPK Implementation of the Revised Simplex Method" was included into the package. Thu Jan 25 12:00:00 2001 Andrew Makhorin * GLPK 2.0 has been released. Now GLPK includes a tentative implementation of the primal-dual interior point method for large-scale linear programming (for more details see the file `NEWS' in the distribution). A number of routines related to the interior point method were added to the package. * insist.c The routine `insist' and the macro of the same name were introduced into the package in order to replace the standard macro `assert'. Some routines require the expression specified in the `assert' macro to be evaluated, but compiling the package with NDEBUG option prevents from that. This bug was fixed due to bug report provided by Peter A. Huegler . * Makefile.in Minor bug was fixed due to a patch provided by Alexandre Oliva . Wed Jan 10 12:00:00 2001 Andrew Makhorin * GLPK 1.1.2 has been released. * umalloc.c, ufree.c, create_pool.c, get_atom.c, get_atomv.c These routines were changed in order to fix a bug due to report provided by Andrew Hood . Because of this bug data alignment error occured on the Sparc computer. Tue Dec 14 12:00:00 2000 Andrew Makhorin * GLPK 1.1.1 has been released. Minor bug was fixed in `Makefile.in'. GLPK Library Reference was included. Mon Nov 27 12:00:00 2000 Andrew Makhorin * GLPK 1.1 has been released. Minor changes were made in order to co-ordinate GLPK routines and their descriptions. GLPK User's Guide was included. Fri Oct 20 12:00:00 2000 Andrew Makhorin * GLPK 1.0 has been released. glpk-4.52.1/config.guess0000755000062000006210000012760712175147600014256 0ustar maomkpasswd#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-09-25' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-gnueabi else echo ${UNAME_MACHINE}-unknown-linux-gnueabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: glpk-4.52.1/config.h.in0000644000062000006210000000130712175147600013745 0ustar maomkpasswd/* config.h.in (GLPK configuration template file) */ #undef HAVE_SYS_TIME_H /* defined if the header can be used */ #undef HAVE_GETTIMEOFDAY /* defined if the gettimeofday function can be used */ #undef HAVE_GMP /* defined if the GNU MP bignum library is available */ /* requires and -lgmp */ #undef HAVE_LTDL /* defined if the GNU Libtool shared library support is enabled */ /* requires and -lltdl */ #undef HAVE_DLFCN /* defined if the POSIX shared library support is enabled */ /* requires */ #undef ODBC_DLNAME /* ODBC shared library name if this feature is enabled */ #undef MYSQL_DLNAME /* MySQL shared library name if this feature is enabled */ /* eof */ glpk-4.52.1/config.sub0000755000062000006210000010556212175147600013715 0ustar maomkpasswd#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-10-10' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: glpk-4.52.1/configure0000755000062000006210000144330112175147600013636 0ustar maomkpasswd#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for GLPK 4.52.1. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and bug-glpk@gnu.org $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='GLPK' PACKAGE_TARNAME='glpk' PACKAGE_VERSION='4.52.1' PACKAGE_STRING='GLPK 4.52.1' PACKAGE_BUGREPORT='bug-glpk@gnu.org' PACKAGE_URL='' ac_unique_file="src/glpk.h" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_gmp enable_dl enable_odbc enable_mysql enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures GLPK 4.52.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/glpk] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of GLPK 4.52.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-dl enable shared library support [[default=no]] --enable-odbc enable MathProg ODBC support [[default=no]] --enable-mysql enable MathProg MySQL support [[default=no]] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gmp use GNU MP bignum library [[default=no]] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF GLPK configure 4.52.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------- ## ## Report this to bug-glpk@gnu.org ## ## ------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by GLPK $as_me 4.52.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.12' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='glpk' VERSION='4.52.1' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' ac_config_headers="$ac_config_headers config.h" # Check whether --with-gmp was given. if test "${with_gmp+set}" = set; then : withval=$with_gmp; case $withval in yes | no) ;; *) as_fn_error $? "invalid value \`$withval' for --with-gmp" "$LINENO" 5;; esac else with_gmp=no fi # Check whether --enable-dl was given. if test "${enable_dl+set}" = set; then : enableval=$enable_dl; case $enableval in yes | ltdl | dlfcn | no) ;; *) as_fn_error $? "invalid value \`$enableval' for --enable-dl" "$LINENO" 5;; esac else enable_dl=no fi # Check whether --enable-odbc was given. if test "${enable_odbc+set}" = set; then : enableval=$enable_odbc; case $enableval in yes | unix | no) ;; *) as_fn_error $? "invalid value \`$enableval' for --enable-odbc" "$LINENO" 5;; esac else enable_odbc=no fi # Check whether --enable-mysql was given. if test "${enable_mysql+set}" = set; then : enableval=$enable_mysql; case $enableval in yes | no) ;; *) as_fn_error $? "invalid value \`$enableval' for --enable-mysql" "$LINENO" 5;; esac else enable_mysql=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4' macro_revision='1.3294' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' lt_prog_compiler_pic='-Xcompiler -fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ F* | *Sun*Fortran*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; haiku*) version_type=linux need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exp in -lm" >&5 $as_echo_n "checking for exp in -lm... " >&6; } if ${ac_cv_lib_m_exp+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char exp (); int main () { return exp (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_exp=yes else ac_cv_lib_m_exp=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_exp" >&5 $as_echo "$ac_cv_lib_m_exp" >&6; } if test "x$ac_cv_lib_m_exp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi ac_fn_c_check_header_mongrel "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes; then : $as_echo "#define HAVE_SYS_TIME_H 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" if test "x$ac_cv_func_gettimeofday" = xyes; then : $as_echo "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h fi if test "$with_gmp" = "yes"; then ac_fn_c_check_header_mongrel "$LINENO" "gmp.h" "ac_cv_header_gmp_h" "$ac_includes_default" if test "x$ac_cv_header_gmp_h" = xyes; then : else as_fn_error $? "gmp.h header not found" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use GNU MP bignum library" >&5 $as_echo_n "checking whether to use GNU MP bignum library... " >&6; } if test "$with_gmp" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_GMP 1" >>confdefs.h LIBS="-lgmp $LIBS" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable shared library support" >&5 $as_echo_n "checking whether to enable shared library support... " >&6; } if test "$enable_dl" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ltdl" >&5 $as_echo "ltdl" >&6; } $as_echo "#define HAVE_LTDL 1" >>confdefs.h LIBS="-lltdl $LIBS" elif test "$enable_dl" = "ltdl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ltdl" >&5 $as_echo "ltdl" >&6; } $as_echo "#define HAVE_LTDL 1" >>confdefs.h LIBS="-lltdl $LIBS" elif test "$enable_dl" = "dlfcn"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: dlfcn" >&5 $as_echo "dlfcn" >&6; } $as_echo "#define HAVE_DLFCN 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi case $host_os in darwin* | macosx*) LIBIODBC="libiodbc.dylib" LIBODBC="libodbc.dylib" LIBMYSQL="libmysqlclient.dylib" ;; *) LIBIODBC="libiodbc.so" LIBODBC="libodbc.so" LIBMYSQL="libmysqlclient.so" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MathProg ODBC support" >&5 $as_echo_n "checking whether to enable MathProg ODBC support... " >&6; } if test "$enable_odbc" = "yes"; then if test "$enable_dl" = "no"; then as_fn_error $? "--enable-odbc requires --enable-dl" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cat >>confdefs.h <<_ACEOF #define ODBC_DLNAME "$LIBIODBC" _ACEOF elif test "$enable_odbc" = "unix"; then if test "$enable_dl" = "no"; then as_fn_error $? "--enable-odbc requires --enable-dl" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: unix" >&5 $as_echo "unix" >&6; } cat >>confdefs.h <<_ACEOF #define ODBC_DLNAME "$LIBODBC" _ACEOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable MathProg MySQL support" >&5 $as_echo_n "checking whether to enable MathProg MySQL support... " >&6; } if test "$enable_mysql" = "yes"; then if test "$enable_dl" = "no"; then as_fn_error $? "--enable-mysql requires --enable-dl" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CPPFLAGS="-I/usr/include/mysql $CPPFLAGS" cat >>confdefs.h <<_ACEOF #define MYSQL_DLNAME "$LIBMYSQL" _ACEOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ac_config_files="$ac_config_files src/Makefile examples/Makefile Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by GLPK $as_me 4.52.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ GLPK config.status 4.52.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, # Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi glpk-4.52.1/configure.ac0000644000062000006210000000727112175147600014216 0ustar maomkpasswddnl Process this file with autoconf to produce a configure script AC_INIT([GLPK], [4.52.1], [bug-glpk@gnu.org]) AC_CONFIG_SRCDIR([src/glpk.h]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE AC_CONFIG_HEADERS([config.h]) AC_ARG_WITH(gmp, AC_HELP_STRING([--with-gmp], [use GNU MP bignum library [[default=no]]]), [case $withval in yes | no) ;; *) AC_MSG_ERROR([invalid value `$withval' for --with-gmp]);; esac], [with_gmp=no]) AC_ARG_ENABLE(dl, AC_HELP_STRING([--enable-dl], [enable shared library support [[default=no]]]), [case $enableval in yes | ltdl | dlfcn | no) ;; *) AC_MSG_ERROR([invalid value `$enableval' for --enable-dl]);; esac], [enable_dl=no]) AC_ARG_ENABLE(odbc, AC_HELP_STRING([--enable-odbc], [enable MathProg ODBC support [[default=no]]]), [case $enableval in yes | unix | no) ;; *) AC_MSG_ERROR([invalid value `$enableval' for --enable-odbc]);; esac], [enable_odbc=no]) AC_ARG_ENABLE(mysql, AC_HELP_STRING([--enable-mysql], [enable MathProg MySQL support [[default=no]]]), [case $enableval in yes | no) ;; *) AC_MSG_ERROR([invalid value `$enableval' for --enable-mysql]);; esac], [enable_mysql=no]) dnl Disable unnecessary libtool tests define([AC_LIBTOOL_LANG_CXX_CONFIG], [:]) define([AC_LIBTOOL_LANG_F77_CONFIG], [:]) define([AC_LIBTOOL_LANG_GCJ_CONFIG], [:]) dnl Check for programs AC_PROG_CC AC_PROG_INSTALL AC_PROG_LIBTOOL dnl Check for math library AC_CHECK_LIB([m], [exp]) dnl Check for header AC_CHECK_HEADER([sys/time.h], AC_DEFINE([HAVE_SYS_TIME_H], [1], [N/A])) dnl Check for gettimeofday function AC_CHECK_FUNC([gettimeofday], AC_DEFINE([HAVE_GETTIMEOFDAY], [1], [N/A])) dnl Check for header if test "$with_gmp" = "yes"; then AC_CHECK_HEADER([gmp.h], [], [AC_MSG_ERROR([gmp.h header not found])]) fi AC_MSG_CHECKING([whether to use GNU MP bignum library]) if test "$with_gmp" = "yes"; then AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_GMP], [1], [N/A]) LIBS="-lgmp $LIBS" else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING([whether to enable shared library support]) if test "$enable_dl" = "yes"; then AC_MSG_RESULT([ltdl]) AC_DEFINE([HAVE_LTDL], [1], [N/A]) LIBS="-lltdl $LIBS" elif test "$enable_dl" = "ltdl"; then AC_MSG_RESULT([ltdl]) AC_DEFINE([HAVE_LTDL], [1], [N/A]) LIBS="-lltdl $LIBS" elif test "$enable_dl" = "dlfcn"; then AC_MSG_RESULT([dlfcn]) AC_DEFINE([HAVE_DLFCN], [1], [N/A]) else AC_MSG_RESULT([no]) fi case $host_os in darwin* | macosx*) LIBIODBC="libiodbc.dylib" LIBODBC="libodbc.dylib" LIBMYSQL="libmysqlclient.dylib" ;; *) LIBIODBC="libiodbc.so" LIBODBC="libodbc.so" LIBMYSQL="libmysqlclient.so" ;; esac AC_MSG_CHECKING([whether to enable MathProg ODBC support]) if test "$enable_odbc" = "yes"; then if test "$enable_dl" = "no"; then AC_MSG_ERROR([--enable-odbc requires --enable-dl]) fi AC_MSG_RESULT([yes]) AC_DEFINE_UNQUOTED([ODBC_DLNAME], ["$LIBIODBC"], [N/A]) elif test "$enable_odbc" = "unix"; then if test "$enable_dl" = "no"; then AC_MSG_ERROR([--enable-odbc requires --enable-dl]) fi AC_MSG_RESULT([unix]) AC_DEFINE_UNQUOTED([ODBC_DLNAME], ["$LIBODBC"], [N/A]) else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING([whether to enable MathProg MySQL support]) if test "$enable_mysql" = "yes"; then if test "$enable_dl" = "no"; then AC_MSG_ERROR([--enable-mysql requires --enable-dl]) fi AC_MSG_RESULT([yes]) CPPFLAGS="-I/usr/include/mysql $CPPFLAGS" AC_DEFINE_UNQUOTED([MYSQL_DLNAME], ["$LIBMYSQL"], [N/A]) else AC_MSG_RESULT([no]) fi AC_CONFIG_FILES( [src/Makefile examples/Makefile Makefile]) AC_OUTPUT dnl eof glpk-4.52.1/COPYING0000644000062000006210000010451312175147600012760 0ustar maomkpasswd GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . glpk-4.52.1/depcomp0000755000062000006210000005654612175147600013316 0ustar maomkpasswd#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2012-07-12.20; # UTC # Copyright (C) 1999-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # A tabulation character. tab=' ' # A newline character. nl=' ' if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' "$nl" < "$tmpdepfile" | ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependent.h'. # Do two passes, one to just change these to # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. # However on # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\': # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... # tcc 0.9.26 (FIXME still under development at the moment of writing) # will emit a similar output, but also prepend the continuation lines # with horizontal tabulation characters. "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form 'foo.o: dependent.h', # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. # Do two passes, one to just change these to # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ < "$tmpdepfile" > "$depfile" sed ' s/[ '"$tab"'][ '"$tab"']*/ /g s/^ *// s/ *\\*$// s/^[^:]*: *// /^$/d /:$/d s/$/ :/ ' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. base=`echo "$source" | sed -e 's|^.*/||' -e 's/\.[-_a-zA-Z0-9]*$//'` tmpdepfile="$base.d" # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir="$base.d-lock" trap "echo '$0: caught signal, cleaning up...' >&2; rm -rf $lockdir" 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0 ; do # mkdir is a portable test-and-set. if mkdir $lockdir 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rm -rf $lockdir break else ## the lock is being held by a different process, ## wait until the winning process is done or we timeout while test -d $lockdir && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test "$stat" = 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' "$nl" < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: glpk-4.52.1/doc/0000755000062000006210000000000012175147600012466 5ustar maomkpasswdglpk-4.52.1/doc/cnfsat.pdf0000666000062000006210000016502612175147600014455 0ustar maomkpasswd%PDF-1.5 %äðíø 14 0 obj <> stream xÚÍÛnã¸õ½_á§BFc–7‰T¦[t¶èl·@gw1ykŠBc+‰vyÖ’“Éß÷R¢lÚq&³E‘´x97ž;g¿ÎČߘ ÿ|¶¼Ÿ}{5ûã;1†I‘Ï®nfBX¦Ål‘kV”³«Õ¿²¿¾7_(“gª¾é®¹ÐÕÇfÝôsų'\ÑÙÛÍÇu}?ÿ÷Õ?œ ¬Ì8Y°²œ-TΔö¶]mëG8%‹ìŸÕ/w›mÓúc*:V=HÅ#º¯6¹mwl³½ýsÅBsVØÙB–LkB²»Ýu=!‘\HÏ„fJî̳Re%S¹;%æ !¤Î¾o‘³~»<[í–}³ 4æ3ÁYÉK'©Ü´Šx»º«ý¶"Ú&%+´geO‚O$×·óœg$A7q}x;7Evu=Oá’¥ð›Žä2«pPÙr]u]³ô›û¹4ÙǦ­zsµ¦­Ÿè²Ø|‘s•}×<ÌALuÁ‘Ù·À¼´Ùf]W-»Ùl´Ýºr4-„1ÌÀÕ ÅràæÆSkbj%Óá&“RäL”~ýažçY”}] –Ÿ*Fy“€X°-UðbyĺiÞµ]fï/9Wž½Cá!nÅI4-ÉBŒî"à®z¢ñxꦓ@bO2QF1cc™PPC:Å}sÌS Ž9X4„]7¸Ü‰Ù*&lDf®gD¨ýqššÐ¢³UÓÅ´¨4-¢(YPxÐŒ4S€% c8õUÎŒ8º@²‰CŒ'hëÅ* f"ÖÞû¶¾­™`‡pÇVâ1güõçêþÓº&—':LE4Ë¿<©D<„£?ÿOÒ›s1È„§!-H›ý3ò4¡IFþ2A$tö¥$½˜é!=ØÕ9(RŠ$3¢@¨gr£ÿÿ,~{ŸÅõIÛHe 3Y~¥¢)e5}`MtÛÖ«‹”Ú ËÇH|™®PÊ`Y!0Ðïu¶ÞÜ6Kˆ:‰èîbPºvÓ§kÉ!m»ž§éäXIó‰qž&“t[Y’øÖ¦!Ù'i‡„OOç#åaýf#Ê¡ .}D¶=Alðsšœ<ƒ]‹TtšªL"‡0‡]pýÐÖqå³LÄ¢÷Ó>©‚9J'aê ¾U\0=I=1”.ä.¯8¤WLatc¶»N%ùºˆ²^:Å´Ô§RÀÅÐu˜—ø??µ.žÖõMR_™=¿@I{-Îõ2M£>›ÆHSDJ1vŽù?øÐèô`TóIè‰Ôü ê È=ríRŽ÷Úôd®.¨æ¾æ¡†§ja(e+‹IywTáÄP/ta²ï±²×Âåõ0Lk?pÏ.ï‡ô·ðCNíe­1›ÂfðBëz•*y>:¢]ûœmçfôÕ„Þ»@2ÄMJbqNœncM?NŠSZ×kŒûcÇôÎu¼[÷툪ÞW4R”o¤¨±&š4R|“Â2kãÅÛ/Ì÷¬Ê®hbhñè‚ä[úáÝ }ÔU׬Ÿèw¿±­«+v÷½¡±¢/ý°·Ûêþ¾io‡‰€Ç@*@“7›õzƒ’~ Äûvî(»·°“ï·Bq&f=•€ãåNGÌ"dËsd>î åª^;fÝ2Š‚àNã5¶u·O ŠÜ¦¦¥]mh«~çJbœ{Ä[Àh³§Ë¤«Q£w?Â@”ç ø {çŽpRmDâTû8ì£9A¡guÛ¬%uµeˆÜåI“À&Gùl,£©"G¥aPÑ{UgºÑ8œãÛFÔ§ çXz/–/A F<™ä—‚øM-zZK]Š=îkûLêhŸ©Ã“Ut(Zľ]ûìGzAy&ûà Ô3±Nª¡ÍޝŠÀW;d8]0{ŒîÇQØùM^£ V¥'XœG°T(Ô™.£”Y»dÝ‹'x_’1—®?ÚgäÉt“ç=RA“=º”›úM .£Š¼‹r¯*ä Ëiû¤AÙS€è~û¤¿ ê) ||a;aRbbSyʤÄW‘Bbpõ|$ûOÚ© 3S ‘LæÉæï˜w¦,2]²i‰ýZ6­Úôûƒ.“…"Ô'k ª`?×øzèê<êBÝD1Š¥8îHgq¦ ÃÚ²ê\Ö‰Á^ãÈå„ë'úUÑpƒ…½x”n³ÞØÚº^y ½'34OBÝÍf×®(E“J8e#† ~¼’¿]Í~úÝŒE؉ endstream endobj 25 0 obj <> stream xÚíÛnÛÈõ½_Aô¥TcN9rÈ‹"Í6 §ÝEv㇪bËH”Ä@"’Jâv?¾çÌ^=–lÇ(Z °Î Ïœûò>zÜ á{ZÀè­ÞŸ®¼?¼Ž<²4L½«Ç#–*/À…Ø»ZÿͽH¤_Õ‹@Jéç_²Ãõ>¿ §v—ÓdSÕ‡…ÐþqŸÑÂÒçL,ô°ÊJš¼_"ñÍ;Êoë¬löY›¯-°jTÐý¾B¨Ÿ‹r‹KÂ_Ueï%.·ÍóÅ߯ÞþzŒ¿T,æ^ ãÚðÅžJ<ÍRgb&DKs€Ûc6áõûÏ׈ˆéxyçrt°x8F4LËá–e(""\0.ìE„h€$‚ad‘¢w{¦WŒÞ]†aèbÌø):ˆQjBÇ?e‰°ˆX‘;YžçA‘Ž{&õpϳ^Í\tƒìEtžîû’­îC¶ Í’¤ÇâÞÂM’^¸Ñ9áʧ#’ß—HÀ¯SüG†‹³Sé‰Ñ÷åÛ‰€«%ÊxÁæ´ƒtâÅ"àqì€Ä9 ‡½Ï@©G€’O‡•rë¨ÖÞñ@hío\,¹v6åÒµˆ©Nì/œª”D3Mð€×»ý­ãuD ïDÈBa޽ÊêúÆD! @[šdû=ML¬€È#bßl ¿ÍëCC›l̈ÁFå×Åvg‚J°ËÊ5oеÝÝŸp3ohcUÕuÞ\›hV•ë‰0à4¹®«mvGáÂû}~0”…cã.ÊY(Eœ×Y½kÖ:ã0$&P«äñ&>w«Ž‹F¶vÖs;#]ÌÓs6 ’ù)RC¦“‰k¼Ãï=å'æŠrij 9Ó;ž‚uŸk€÷:‡ (!Y¢ï!…ó+¢ÏLmžý§Øsš)¡3Ü„@,cбûÿáæ?Ü òaA~ ^Zãßæe^g{|À²¦ÉiÖ•2EUÒBµ¡1£áÕ¯ƒw/±Žº"8]80»JŽû¶¡‡ÂB0ñ'³*ß6aFÍ %¶xëMÓ^Ô0–q¥$X ëS¤Ÿí©´—i ¨–ŠXD1æCˆ÷gäåŠ["w|~Ó½*a5?n¶Áúd¼³p®†‰úÆ’M¸tú™8†pÈ’xbyé]ÕØgŒBqj±Þ£ÍX†ü€g©ïæ˜~j†Ew1lŒæCy†®õ4ÏÔ9ži¦øùú•³Hœ2EÑdTƘ 냳²Gåžñf`«fÌ>JçœÉ<0Fce0fÌ, +%³†ïÂC²Pö®'àè g«s:÷ :ºÄéóyŒØ…cßú=bÚÓþÁÅbÅÑ­†³jq|KÊâ®|î€0")êkÙI„ ¸LÐ쮜33uReF!ý¿Êÿß DüÁ%bÙ××ß)O áÒÅ„#sŸF±•p "È~¨¤"þ¼ËëÜ¥ñ†vzÛ‰žÄ´‡ö dq¤)€ÅQâ›^Ýñ°€Z ûPEÕtƒ$ø´ˆ"?«‹ "Usáb Jep@<ìÏîG~BxêþÕ>;6¹}m 8ÿxÌöE‹xßÐê¬ï¸\\8m„+äç}ßÜJ’&NêÙã<$½‘\ø]°#J·ˆÕ‰NÉÈ ›|$Teé‰d*:Œ(&&/ S¿9¾oò––LÊk3m€<RŸ]eR-8rÁ ¬¡ÃEéì3rL~à §¶Ðw¨‚vGpI 꺢µ²jia—¡Ü?-¨ym¶ò­I÷,‚Ø2p:Í„EÚ¥O· Îòx®t6nƒé]?ïÿfZÑ?}V$˜Ä Z!ZC§8G­À´BµB¤Q§¸=h°Ü­<.>D+n§»ÚN:Ù7SÛ]Ö:eäk…–¦ zö—-âH=ŽYÓô1D0‡“Of)Ð-ç’|•s YdÔˆ¢üré 5úT‡”#C"¢ˆD.uŽmxµųԲó,¼£Kܽ }Á¦?èˆp‘¹—r0» å5¸{°CQ*Lå%S&ã.·á\Dþw}û¸YGþË·—4ù©:¶ešŽ&”¤è!6Ø)ÜãÊvmNÿùÊûè1 eÛgO¥X À•Æ{¼Hb>Þ=ï½wÞôyorÁè”&ŸSçÙúpbm0O@}Ó³ÀG§,ðU¹iÐ.î_i0÷™™­‹SSK=´IÍî:k3š™&)Œß^~ÿr!CÿÕ;:NÝÑŽÉØõZL†BìÝMY]7EÏôtÒKE³ VF¶d*åˆøþ âû ѱ4 ˆ%mÿþíML‚`§»¬¶»›2;äËÅ '†·.ý6oVuqmº΄ؔöýñ+Ó1Ž…_“:¹‹Cw¶:#Åå’ÌÃ^)‚O­éxhc#®˜Ä»V\ð¦®ìZFC›iikrµ·àŒTa4R… R¥&F35‰šV΄ÊÐtç%öVŽm«Å ,ú†–úOÊ}6˜‹7Ûø—æëÀí¾ìZørÞ· –XÓ¦Á>ý*¿ÝÐÇ/ßPCý GÈ´É[Ü!<,Ìà’¢—K|Z¡7!¼ufV}Q`IÉW²˜À;ˆ1òÂ7Ú M¾jñC¾P–+Bj±BQì&¯óŽ+bΕà W‚4EjG¬ivÕqÒS:~  4÷›¶ªó5[ äÚ?T­]¦ˆŠ3{ôÀn¡zR? Hºô†Ý_A¼”­Ó}` æ “nÑäœã׆¾<6E†M´`G8Žâ« ÑæFñuÖt¿hø\`AáÜ~Ý9a«> stream xÚXK“ã¶¾çW°r¢ªVXàtN³“ÙªI9Nì‘}ñæQ†1EjIÊãɯO7ºÁ‡†ëÝ’ªðj4úñ¡ÑÍàsüâ —ð‚ò|Øï?Æ:ˆ#QDE°;ÂúY°;üþd‡k×ô›ÿìþtéŒ,NE‘©©r¤ÇÍV%q8<[ìȰ½l¶R‡¶3CÕ64÷²‘yhzDa-KÛ÷Çký'’ik×^‡ªñ–Á þg»Vl¶IV„ÿòî¥ê-ï®"¹tUƒÇ = dølÛumGSg8Öœ¬Skë5Q"M&¦9™R³“aд͖N'c¼1Úh‰¿?þón£âðþ vjÞÿðqût·)ÒpG—®Ý×öŒƒ$<¶ÝÙ ÌT¹(rä(£Hè,PÞñŠàÌD2ØJ)’Â‘íœ ó„„ ‘«°j.W4Pž†Ÿ¢8©-õ«žZCÍ¥6UCÝ»§ûGp`>Òx°,öƒRðÂ#O–-ö÷$A dîí‘ÚÞþŽD‰šh¾^Ü9žø`û²«ö4wø‚x¹n‘Á ʺރ,vSÏií`»sÕ˜ÁhüR ÏÔsàÈ¢Ð6‡m{ÜN[Kdül:SÂfæÿ±²õY:3Ak Q›i¿é¸ÓÛ pÞ;‰šÝÍ«­éB\ëxAg_›æ7êöSÚ¯Cð¾=Ÿmƒ ÈýÎbCE$R ³]èFØ%'‚î§Š\G ÏØ¿žM³í¬9˜½ƒ“85gºð0aö.´{0¦+.g Þtáºó|NMÛy瓈 ç³ ó ïÒ©3ç]àñ*d¤x6¡0Kçlè˜ #Î`<È5¢9¾@@±´­bR’:èá”tz朴åÂl|&í"íí‰/EB¬øžÐ¼qQs[šÞù_.±è}_ÌX™°Ë'§"W¼,Ööou.òb ë¯ö|k¨!8}W ¹s3¶ÿ#_^¸mk̵ВÅݱKdA—YEþZD³0ªÆ›tþÙ¡ùƒ õF&‰â8ùe&gôïÕÝD`F€Ñ  d¿Ø™Þ8̽`I™cËÚ\{¾Ì|AŠ„‚§‚ëdø‘!¸AçØÖŒ†ª9ù)¼Yß­ùï/ì¥æH_î~z¼ûðýà ￿ûù kOÊ-+g©D«èL´þ::c™‰GT!EÁ‡6+Be¨-¿C^Þ8 Ï7öÅI¶ÆÛ#´RþÉ étÀß0k‰ ¨í¤iq«iŽâ8ˆ(¸A‹šñ­ÿU¾”/Žæi¨2£l­é€e÷ŸªOw…TéYZ¨9»ÕËRUš”/F”^ï<Œ]¬Ÿ›ºúÍWi0溆6Qbàq—{“U°fr–Ó~z˜YnLK­ÿ4B[9P«d‘àNó²šPM¯”«ÉãSQõó4—ØŸók¶x& œ9"ÎÅ}ÍL­‹Œ×z¨.õ2ïþZåüð‡9_êÕº$-„òüà?=€åUR•’¨Œ.ƒÊÜÛ€,ñ£Iw ¡%$C‡ªìùÔ÷¸àsô 'wßpðo\+ÛÜFa³m.5t¬ÛézGœÔ3gúüO¹ÏQjþ9 ¬ù)Œ…ü´ñúË@^d™·“û3ˆIØ“µ|æ»øxX®M¹]+eeCíh.´\½8s¹ºÅ‰¾£Á(6œ!¿t\ÅÌÑž÷\‘-Å7I}!6c5•P£ÞRÆD)‰ šñ· Q¬ìÝJZŠV–˜o²Â÷k¶¶-¹æa|„*tð‚t)~UÑÁ9ˆ¡ö—㸞‚ù«°‚VäšJ8¬a€hÕâ{¤Œ'€$"†'Y s~…ÞÍãÜô ?úåP–Ѭ ÷PB¨‹×69åÉ‹™ÊxúôEM·Ä쫺8È ÷§ëédûÁóú¸Ñôî_!¸èH…/Ï•»HïÏ¿\÷uUÖ¯42HÒ±ª¦ÔÄM+7aCZTÌýú< —ïÞ¿?TgSö¢»h÷®ïWìCš¯Š›2Ë×U»"Le""[*ïÃÿòo ê endstream endobj 34 0 obj <> stream xÚµXY“Ü4~çWø ›Z ëðU<…T€„„ž*x=š³{°<ÙlàÇÓ­–Ùq² µ[%©ÝR·úøº5ÞŸ÷"øã^*à?òʽ÷íÊûúO=ÎYÇÞj ßC±<ñV›_}ÁDr.bÿº>¿­¾÷ž®¼?=&óÌ»õTÎdjÙÓÄÛ{±dŠËÚ»ô^/?19e ¹¿Óv¸9‘%ŒËID1ž>$bbD4[SôA(SåÿCŒR£Iªý²m;úöøå³ðòQKE_]{Uë=}­ÓM©­ª 9óPP”£äЉ1‹S+úò®i¦2w>ãæ)ƒÝ!ÏX¬,sÕ€’1ûM Úݼ!Õ×HY¯ß "ÄñÕ«uðÍ¢ ³S¥=õ‰6eWúªm܆x®DÌr5g_ít*û]{ì«F/iž¦2ˆä¿¯ë‚ŒÚæyþâBëãËT÷#&œÕ  `eö9X)ϱÒ*<Çʤ¼  ¤¹q{Ê]ѹ¯Û¦ØëÿK…âÃÒ8COLX:¿Ë–*&RÇ^û¬[•E]ß‘ ¾+S=ƒP‚2'穈ìáð3Øk2ü2GŽ''92ƒ6- û–FŒ5aE’šC%,NÏ#àƒ‰5†¡(Éïot!8Ê#,Ä¥~×;í൦U3ÇBº‹Y(K6få€7”ýË.•Yì °—îu·äÔ4f©úHùÉY>ø¼2t^?<ÁãI³è•û·»ŠŠ(2(ßìÚc½!æÉÇÛ;:« Áº9NÜ|O&±«r<?òy½½#%åºP&#@Ku?ά¨fVT¡«€)K´¤%™¾Cõ–@°-ÌjwÁ´RL¶µIÇ GKçÊ»Ÿ –(t!˜@¶޽«-G@ãY[úzE'"Fk¯„‰HÀ¶Žåi:Á•å“B"Æ¿14»­úΠ–awòŽ¿/›àŠ»«³ë÷Ke8¾„€Iê "žòTN~aÌqoшxi$Ž—FbÙî6FoÜyVu¨ ªP¹_ÆíŽÕ©ÎU“q&vù ¿uiØ=)´[ŒsÛÙ ™cY‚ÖÛc9­Ô´uê_p1ö/° †$TIîÿ4ô/nwÕËòÅô0 '[w}Úib‹ë5>»`§I2,>¡®R¶Rë†4Ð-c7äÖtCÈ•q+°«‚ÒÈOžs¦­ßbÛ¡‰ú‰/8jvl†áìœ|9´Bã‰Ýbg0tiŸûÐ[h^† 7.ÿ}[2G_™ô‰/ÙdÖ–Œf???ÇŸT3™YŒ›®z‹`±È6îL}1Ul žv@°>° @»7š–uëÀbC|WH½£ùËꦶyó§H_GB*…4h\Ø+k·ðŽq?m–þåš§i  â»«1¦m.¨=x¼+ê½î Ë/Måt4‡öw‰¶4®ð5FïÝ]ÓÖíõ]UûÂɰ° 7X3È®™—²<µuŒçLåž„L ì:Ë(Ƚ 5\bÞ²pXϳIzàþ4³ŽRÈ”'Vp/cy’ ¼nbÈê!ßV6Méíd»íQw¸@îcÙ»gé‘Ú-éù Ä$€KŽ¿ÌDî±Õ/èÀ • -'ÔÚNýîÇW?\éÊ–i’dÇ£±QK‰íø‰æKìaÊú¸XmG£†B “M…]ÅB>IX é/é÷%5¸æõÿrt endstream endobj 37 0 obj <> stream xÚíYK“ã¶¾çWð(¥Vñ AfO“x7µ){½Îè–IMq(hD—DÊ$µã±óãÓHPÑÆeS»U£ 4úñõc¢Ÿ"ÅðGZÀÿ8*ÑßÖÑ_>&YçÑzñ„å*ZáB­7ÿ^|ê—+«EÕÑoÑu§ƒÙФß½tÇåJd SVw1WžðØ6{s Ió°\%éâGSöËÿ¬ÿ ð<`AàYÅë¿8ŠÇœÅÊm—M½zÑUmù“‹‚îˆW Þü؇CU?ΰŸõE]{ËJ$1Ërx½dIbϯj “Ò=Û¦=Ø7Kµ¸[p–Ü-ÅßônIE½>i "6uÙ€dôbc:Z)ˆîïŸ?®no–™X¬qA ®gY½v2–HÒÎv¹RZJËñcœ ¯³³]ÑÑà4djšv§²4]·=í÷Ïn¥ÙE±¢öìé ­·˜zótgãRÛœúª6s •™dR:=î÷ Œª+z>£Û•Ìs&t¨ƒÖô§Öªä3¸N©Å§š„Øï*·S™(K]≧ SbÂÓñ¤ÕŸº®à™'. gNŒ49uÆë½¡Ë7¦7í¯ŸZ¸jÿtå_ý©œ¥)Ú!ãÊ^ößyÞ™L7ÿø–<äÃ:ú)b2Ï¢§H·˜µ"À• D¢é™8l¨%’msBÏÀ- .s øÖ<M²Øš¢«À|‡œ è£Ípƒ÷«É…eÓ¶Æ¢^4õýÝ Uq&&>íN’Ã…nbgΞÀ@«1¬ŽÞÓY$ù•Qf¿[?è@Ûƒ‚ÜüІ*#hþüýÇ7·3ZRÉÏ´¤c¯%ÍuC+¡§Ó,²@°g~®º¾£Ò†=sÔ¬“6`0£ »ŽÂ'Y&KE¨—7èäTO´B ‡ƒ€(À-­ÁïÔÆ€™à…"_ÄO( DIœXƒ”§ ^“¯ñ×e8¾?™Žo¶tìCUísHÓVȰ#+=w„àG€sme<ð’½9¼dôTõ»3<¹ràÍBa\Ùìï¿û9 Â.óÇe!6óT3ž„ñç_›_ž†Z‰™à–,¶ÚCèÚòÖðݧ/4cLÝÃ̆- ¸šWuÓÏã ô8X›Ò™´ÔàÁ<Ô0ª·q•së‹4"WTÜGnpßâ}û•gKW Ó†‡Á4'9ZYœ|rˆM‰ãxè uo‹jjÍ %qÎr«“’ã³L –,!‹Áõ…¸ —“ .)>ü% l>ÌCq…7TRúD‚×¢ëcI£$ð“ã2¶¨V–.ö‘,ª}ÕãÏ´è}ÞÝÝL]vsû\7Ç®êf“Y ªÌ-!aÜÃÄ2|ggx)íýùË; Ô ˜ûj'Íôq·|?Î9øÆte[­¹Ì@öyí䢸AS(³ ‚úwÍœ¯ÓÞ|)è[âaÝd†ô•w_Ü­GPŸ׸ÈfMTK›ÃXº0KÃ…@³°ñL‹;ÆpYtCuÅ$.y‡z­:BHy‚ˆ±ñˆ*Wûìì;(ën‹þ½ó+㪰ÛÓCp:8±`ʃÐl=+òÜå‘08P¼c%5›ßÄLk'òÁŽæEaÂ=ªFäÙâÓ6ï°  Ç˼!ØIgЖܦm°˜:ƒâpKx.ŠúyÅŠiÊ ŒxeúkGÀ‹c[LzyÒ q†ô.É.RÙ u‚>ˆÀÕÓŸ›~(T}cl~œ×Ø|³"“q0zªW®çQ=ÖP+l.u3†¦B|Mû‘É[´ŸªÇSë¦^9õ+¡ÇÛõãdª~ä Õo·l¿[Š1=ƒ™×ä;ŸË§g…h˜*àc!¸a€¯6Æ1ZÐÏPeÐáÄï9àú¨$ÇÃlÈlÚÎQ¾ëÙ® š±Ï‚0ž“/dj¨ ¥î ^Õ`yH×°ÚÎþ9& ˨âЀµb"0ô ñdƒD^Cs IOæÖÀ=FpûG®-Û÷.¨ä’M0`çKĺñýʼnÝȉÝÈ vS•i#uºØ¹Äw8ÌeJAHÅý×BªÐPâê1z½e¬˜‚š&!I¶­áX£ý«¢ ÈÒôš(…åk*çjìÎk\0r©ü³ÁU.²ßÀeåÚN>móÅ€)ÓÖDM‚»Ä³úßþk$‚` endstream endobj 40 0 obj <> stream xÚ­XmoÛF þ¾_¡o“±úª{ÑIê°i—Š®m¼a@StŠ-Ûêd)‘ä¤ù÷#wz‰•¸[‹ð‰âñȇ/GÊ»ö¸À÷"ÿ·ÜyÏÞÓ³ÐãK‚Ä[¬=²Dys$ho±úà¿ZÏæJH?-é7/gBûm¶Éj$¥M~Ydø¤ü¦*öm^YæÛ™ˆü´¡‡uµ/WO`­´¿¬ê:k®fsûU¹ÊË ñÜÌÂÐO‹}f÷T뎮ü´ÎS8¨¡s/@H±ß•ÍÅŒŽ^:/ØlöqñXb ’, AuÖÖyvƒše«Ù\JáßæíWÒo·.”_W`FI2žžñd‘Ð,Ò$JÛWŸvùÕ'ÐåÓMZXþ!¢1(À-7sòâÃ\pÁt:Æ,”†ï&Ý "±ôßT-X|(ÖÙÕíYÕU0ö”‰UW›:Ýí ÊRq$Ž;z°^È–ùEÀ•¨—ˆÏ lä«Äd-È€E$ bkèÛ ¦”}Ýl«}±"¡MÚæÍúŽŽm+ûKGrš¢¨P—[ÔÞxT Å”»ôzŸ×Ù.+‘³mžFÈFŒ88›Íà ðOŠ‚MÖ’F…„NKÙÇ”yÈ ^\å_æeZß9 “À(®"Ë_¾&hNÞµÇd{·žÐšÅ“N0%¼'¢€‰°#Þ¹÷ŽRu,xÀ¦…ÿüÏ©PáL…ö|g[U[•Áç_( ÁZ"æ„£‹ aÓÒŸ§ åRö‰1e¨)†*iR阡C6kèÙ_ª;C)Ù°Ü0± XÈÍ+1 †BpY•M[§6qˆ––+ZTàúPûŸ³e›SÕp›($A½Ì]èÑ;9‰É$9ø0B9Íó~7déuÓ±š_“ ¸¨ÓrC "\Ó>8w4$ ¤#‚©ÒÄTb9„}{K"|bÐHw Hn¢Ñ~`w ÊÁ°•¼ÐR øîÓfFï ÖGþ°“šGÂ8^ʇ±Ú'Æ,R8„AÛÉ»çg°ž+!\O=YœL¸,„V4EšŒ&†o¤öñ'cš?B3ae†˜1@ ½¤‘JiìÚÌh²ü"oZw*¸ÅŸtS§WÛCWüí>NHûqâGö(ââ(â Lu|€8=C¸bJãÓ÷'o^žü#X‰{߯€0ì#Á a…Ë[÷‘^BûŽ )ssI¿Pk˦ÄÍ—+e'\ô£ƒs)R;—ÞŠ~Súyñæl~~2‹…¿˜Œ|Üø‡Bã ÖalŸ`Œ\š.ŠÓ³“W¯¿&ªÍ‡“î# >QîÆ]îÊaîJ_öÙ;úÖ²L÷ˆŸ1éÛÁ ]ͰNóœD(ñÐNBhA£0ï~øÍN:÷ endstream endobj 46 0 obj <> stream xÚ•W XS×¶>1sDŒŠ…¶&PÇ:ê“ê­µŠâˆâˆÔA@&™E‘1@’•€Ì2"CQˆ½ˆZm«ÖÚ:Üzõs¨¨¶rqÜÜ÷½`'ß}÷½÷…¾d﬽׿þõ¯µDŒ…#‰¤Ë—,sݲtª«û¢ÍÎ3MßÌÙD²Þ°ˆìK±^g„7DÂØA‚L,Œ²Ë0¢í#LO‹aôÉ<nzN¡Qõ6Œ…HÄÅă“Ó¬NN3]ÃvÇEúDÙOÞñ–½óܹ.Óìg:9͵_â¸Cjﮌ ð QFÑÁöëÃvúEÅÙO~' *j÷60*À~_¤_DŒŸ¯½[Xh”ýjeˆŸýÀ­g üs ÙåaïæëJï9Ìš™.r¶XȸŠÜDË™•bfÝ %daÇÄÓˇ0RfcÃŒdF1<3šy“ÏL`&1“™)Ì4f:3ƒqdœ™YÌlæ?˜EŒ+³˜Y¸1K™eÌrf³ŠqgV3kf-³žÙÀld61žÌff £af bDŒ“Èä0ǘˆv ²´vÐÏb_ñ#‹yY–“-},’L’´³KÙRn÷Ý`çÁ­Vc­TVŸ!µV[ÿ<Ôe襡/¤™Òža«‡n7üì‹Þ#NÚ¬·¹aó½ –öY‚_œ¹Ö•QOúöˆñ©°Ï 㟲h‰VùÇeÐ ±ÁÉ ‘Îí¬‹l6®n=·íÂD"!ÓÉPÙąЛ䅛‚­Öuu_@µõx£¾À%lm¶6@Nn½º&Ì`¥¸ø±¨»ÄxóI—#ýê àxÑ]/Æ=×ù¶]¾¾»‚}| ÁÇŽÛdRá"…L㉠îGK1>écùz É®$bˆn¢\rº²äú«ˆ\Á¶ëÿ½ÐNO%cY“´ÂËh×iG;ôÀQbAA¼R¢ŽQyÄ'§ªæCñž«æorõQk›œˆãö o›NM<~ ehsä.Žjo}…ƒÐÄX„wy´€q^ÛÀ0òXžéÕlÌ+n„®-´ÞGªt|º‡áܯ¿}*ƒÓ?Ǻu_s·\/9±˜ë1ïýcûÕ)§7ªNnöÎioû ²{n!rÉØä®ñÓ$jcµš45¨ ƒÛ› ˆ¢Ä(¬ ~‰"±°ùnãa¡¤V›!‹£N$Æ“îþ5¶ +ß^©Š NÚ÷ˆúêdöUØÖ7—W•iDBhÒUqD×ÿÜVµ4aêu†‰Jq É!ýGP_wÃLY6ü ¬ 3ôú¬.m‹•’KÄÉrºBÒ¤ï†Ö¦_ –n›Æ’ûÂ>9ÒfIöK¤}]‰Fô¬À•èc}‚‚®]Ü—Ü7›¯†ÌhÙ{®ëO-«Yv$•Ì ÈNâƒo‘·PƒnÈ¢­JÓtñòdHmR ™FxOgX³ÊÖ_ h :(ƒŸŠotœ¿|ëiþ)¸8TÙ@ëSò ¸jÐ×È¥}ÏhÊtE8G oàâÖ¾E¼¢·¿ÛA!ÌeqN¦äÚ…1d#râñÏ1¼ÐSØûðyàQÏzŸò-@x ƒã=¼¶.Ûå IOŠd=ý;e²k‹³¨OV}óùþ‡Ôòc…¤^8ÚõN›òÎëϱ?æn_$oÇ¥dQêö©² Xã$8 j‘¡\»Dú‚£Py›œfRâô%ã^þ+£$RcA«—Ãjëñ t˜ÀB „툈MNVRÎL.r¿á{2òc@kxVúùÉ®ÿ eÿ=îò«ðuq[WsЇ‘™ÀB~‰\*Ìy á8—÷¡)k”øk&R9 üMw²èï& ¶EÿÚÛŸB‹Ék VúÂâ7ðmÅB 0ÇÜv° /÷!ØÙ5 l ™Ô[5ÚCÉœ–í·"×-ñn¯‘ ¥nûûÛC(]7GŒ¦ÞshiyõôÜÅ>{€~¤I¯ÎJ‡ »¤--S°Múï µá{3kw³!ã@r ™Ë®ÒÇa5U<•Û>2“,ΞFÜÎ(Ù¢™ ›vÉï ¨g^þrR‡ÐƒVb¡GòD%I©L¡°#tïU DkµáqšXmpQ Iµþ+8|økó5¢ØÝ4Ë#3C³´:¨â„s:kûŸHÊN.»RÈÎ?P€ }ƒlu¦C%uúhnî1 ŒƒÐÝk$l ¤@J '}!þÕ!­CŒÆ¾9|rVK5;üÿ}+¤öW¨Ó»È®– ·Y¨Òée•é+te”6FI”f>„…½Q•j¶ôP£®ÏÐi!šëŸÃJûòh2·b×@’a‡IØëñïJð/ßÝ{†Ì´{d®¼Ú¦’?‘ÅׄnaîÒåàBåDŽ]T7¾I4Äñ¨[Œ6f³­è02^8„ßñøz‹á:œåž¾y—¸Ëú-3ÛCÍþã%7޲#OãÉqhJ¬ o¤Š¶Œ¾|:ÏÜÑV÷KᣢÒÔÌùЪ´ éïÇ„ÁJP]M}ÌŒOëRÝ$Œ#<Œ-ÔºdÎõØ MþBEÅ2ÑØÇ}òo<cŽ°ŠŸ\¥¾E\§áb·¬î{W’1™1 -®2«åèÁ–CN¼LjmJ²b‹mDåûǦИ[àLDrXÖâ]´ÿŒçá´ž¨§Ñ…šª˜ƒ õa°™SļC,d³€ÈRq¢¶ 2i c@E•ŠVU±,tºü¼‚‚¼ƒµµ¶ÞIø8tú´·Wß»?"¢ZJýjJ™gDø•‰ú¾Tùÿ9IK’-Û%y(ʽ‡ã»Ýÿ€LUH¾Ñ?ƒæÿߘxªðà–.æºä‘A&…Œiô©ÃÙQ3ŠÑÇT/x†¼èâ°žX¥»(›âêê+[eP®*Û[`È«ŠÀgm~så;Xšk³¶±r±×ä_ÂéöŠÜNPü,ë”TæBͦýòU:(¡•‘ˆÎóÓ]â‚¶øhQÿ™ÆŸPG,Ó ÂkÜØijÕ ÐZŒ¾}+x²0ÕRÁ~’¾òþŸÛÙÒòÒò’ŠÎMç’ŽS(d½wqŽþˆBðÞãÄðâœ:SÖNW‡¹\Û`]äÎ`/ïä X ;Oí¯â¤‚:­EÓ"jEk\jÊúÌ&A²lhµé‰ª=»—9Òø9N;yQ‡cpLÎEMºœ.j5Zµ:!"8eóÞÚÊÖƒw›½‘¸-!aÉ?8â$tnD.GöG—L'eSHñ©©B øC¶±ÑåÛëÝèAoNœEìɸ'sÐN~:Ê8Oݲ-¬» ŽÉ¶"ýxåêÍ þtÿpÀ‘ŸÊ¡þZÕÚxþbv5´Á‰8ÃvêZ~Z ®¯Çw ¢FzfÊc±°Ãùêl¨•CƒêÖÖeûúƒk© §9ˆ ±æ„SqêÉÞÒâxH“SÿÕi á+–ÇxÑ-´øúyy½…¾Mw¬²¥¼éH•žC±Ö½ÏIñGSwmÄHƒ-{"'ÆaO.2䙤çÓm®õÚlM|rÊ^ˆáv4Ūj)>Ñæß¾Ø‰ˆý'›ð{o} ×߆JÍÙ¦^‹lm™o5aB³¨ñFöfßãh\ÁŸ ?O;-ús_~.‡ÎЖÄüú’š¬R½:¶6 \LÑžC‡ŠÊ+kâš”2øÄÄÄùÔøæm¦ÞÈ6¼»DÁù>í{÷Ä€?(ªwVî‹Ls‚uœÇ•e¸ çÝ={KÖÖGzÕ¬„Y´ƒÚé:ENb+%{®®¸à ‡C²ùÙpíƒàÚýûà¶u+¸Í–Ÿ'^üÏ<ÖÒNÚÖÿ|ëåKP,7Ï ‚•™4«D¸Í”W‡ñ"ÿƒÏi2H6¶,ÞÂiñ'É™~ÁŒÉu*í7^Î,2ßt]>Z¹@Fê^]6OF:¦#†#ûÄæÃ'8Ðϯ1°Í7¹u‡/›qw¦Rä ÕË”…b¼‡m~)Ì/È»f*êášXؾÞ\-ØÂuª2Ò24²‚L´ì÷Ú¯»öÒ‡×Ø’ÂâƒUe8”8Ùæ¤Òb¥å’ca?­ë5úO¡®³È<ʰû ’tû332“hq7y&tw¸òŠ$\xuø¢%}¾ñ¸·¼Å}÷(ä}ÏP½ÞK÷í»·´x%LO÷/ ÿ ™ÿ›Õ—м¿èö™KG«¢çÿ øÿ—eöWüK ¸‚{@à{ÿ·;ü[ ©ª½6÷…T?…: £õÔñ q&.³Ç‘ÑdÌãéèŒ.÷Ÿ ŒèÉZžŒ|Ç,$å-UÇO–éÓ²»4¬Â<Á‹{¨ªñ&%#›Œ8Á`ÍêB¶Iž©¼nÔFŸˆ0¦±ÏÿŽQ6ã!yªñæØAÜ™?1"÷ÏwvÚø£§ºJŽwå¢Íš ®›WÊ ¨ î B¶}²žžg&iñÅhÞƒ³p°l’j/>} {kk ¥mž‡½dï@ Û~%Q,!o¿ ⟵e eûQëg¸ï3±0TXÀ›‹w¥c|J†:I•®+Ù™Me6„L2ZoâðèÆôºtCZO9Jî]'ˆ‘m†U%aÝiZÝÞ_ë6ûkÝÖCEÉ¡rÛ“g6ZçpD!•v8nˆ-óiÌÞ˜¿²`Mœâ®<„JŠ!{‰>B—kjæÍ=…TXN£ÉqA…èŠøÐv1ú›ä•Öîñ¸^)ÑNöšÚUAfvNeä#âm®EU¦N†ñÙEY¹—M÷ Ôdüî»®Ãt?µ:M«¦¾°%£°Áä{$=4,ÔÃìûeÝû'¤'îMO´‹Ùä¶2 ’²õº†Bhå ‘•!Á‘1Þ'”ÉîÀÙ›´’¾èÃ^âð†ÿv±ÒÄBÁ#·WäJÈÖÖh…¢!ÍyÖÖ(ª¶*³²p©°¬³– CFý#>'É endstream endobj 48 0 obj <> stream xÚ­U{XTu>‡9'C2õ”3îº•Ê êªY>º‚‰P¡–š’ Ãp†aÔ p˜™o†ËpŸ ×.i0$¨˜ yÊr+×¶m7˲ìò;øcŸgÏ`ùWûßþq¾ç9çùÎû½ßíýH"0 IrfìÆ¸¸M›GÇ'.]æÿ°"WÞQN–ñü<’,€gEüÃù؃‚%~yÀo¯ÏòÛ? f†m6H’tþ>Sdäò%‘‘Ë¢J­*C–®–<¹w¡déêÕ«Â%Ë"#WKÖçHU{“å’øduº4'Y-¼dK¶(öfHÕZÉ“kÒÕjåÓfIrNÞ…J¶va¸D“¡N—$Jó¤ªiªd£B®–$$çH%Óœ—LÛhEŽ2_-UIâ©R•\à:#2`=O$©¤, ‹“*‘F ü 1›˜CüXBDωMÄf"–ˆ#ž'^ ¶[‰mÄKÄvbnAD q|š ˆ ø@” ê ¬ z(H&&Å:ñuêYê6½‚®¿/†7†ðº×ä#.rpÕLˆø­èo \3|*›H¹ݺ^„ ò´§qúxÀ,ªŽ:¼a`Ý¥¼“ð8qÒ{æðGÖoá ÷à+LÄ: Y|&àø ®4Ÿmyï­ž#ÐgÔÎ ‰°b`¬+N(Äq…é@ ÑÁËû¼C.).‰Ðà$ôEÃæ)w¤-ZNµÁ 8ÕIO9(™±h9›-wYoB_ß7мÀ›M-7Öæü0¢;7P—¹2¯‰ø8´†É÷•nÕï/+I„ q¼¸«íü;í(INŸ„ïhDE~ŒiLÇ<¹bûT¸;›z=…N[&0šïúúÉ ¬Ü¹>ñ9œ„ Bóx’ ™Tíñò\$ÿðdS^oªÒLFÃ~,ú:T—¢È}Î,$pÞj…>ÏqèèRÉ•gÇgç\äЇ(e|¢UÄ?„\ ŒïÕôÞ¤ÆW^·-VîÔµµ·´´Êà×öæq‡è£g¥K¹½Þm\· ÖÒkþ­:Ͼ Ã>çñÊ]=²#@»Ï4~ÂÎßB%æ•ê¤0ÚÄÆŽ0 £2÷ìL9|œŠÖÖ¶ ãäÓ»øÊð‘‡&ã¢N®cäÔû5e;9œKx÷JªD?±ÏÅs¾^ˆ¸ :Ñè¤7Rh¾=ÈKÅ”VpüÏTìÔF(¾Q—Ÿ—ž"ßt.&ìè%.×ûZû\=¾žp%Ù÷×ïÚ§‚Çè[‘Ò‰¢]d÷*½ âç L«œßo»gbñòxýa¡û‡á®2TäJÁd0rWmR'ü¸­çœ”ÅÉÔ ¥_8<ð Táù– ÿ¦àd7Úvês7²ºÉó—Pô¥mfŽeû è/ß{ÿcºJû³z|ÇÀ•þǤ/7衘ÖÙ‹šk¶V‡Î“ξ ©Yº9mé R —nŠYËAâ¡4{IÑ­RáÅCªÃî×vËàezãDôºÿ»ÑXè(;û|Ïöΰ  ´N½½Ä nh©j±7Òßé™åð}lérz»ín ¿€ÇÕœPÇ”}ÊBy޾è.Œ˜ÅQ#osPcèïlm¬Ô‚¾†‚à//¬Û!,³OЄyÓMDÄ8Ú;.â_Då |u¯|`WU†o¬.›6£Ę+úµÁSn*©b§G~ <Þ±»#ÿ\ s(úéÒé ·'°¸èwýv€ ÌÝtjâÓ>4ç&‰Ha„¢ø)¦³ M‘›_ Ìi/lïqt¶²˜Å Â`½S{P¬Žßð<Öãà­;¯Oïn¹m€ã©¾A÷¢<ù£€×‡ XÊjÀÇjj.²¸-´—Ò˜r!'w;¨ƒÈ©s} ì§5­™ÅijƒøêwsõÇìî>ž{¹þL½súÌ6Tƒ.L«3nÖè:b…#~7%dƒbþ­Ôÿ³Î‹@úT©†6ßãy÷BãöÿK™Éhå—MïJ·px^E™ bÞô88|>žçÞZŒÄhÆÍoÑlgâ$& ’šå#ÊaóYxS¸)ç{†=G†šÁ¼©íJíÙ q韻KñÊîB©ÿºÌº›Þ¹*BÏ sÓ÷¯Ù°B¥¹´|ÿAPÒò¶âf—«¡«[éÙîyÄÁBa®DbüÈï$챞‚Ä(Sÿö<$hÎJÙ7Œ´Ã"ô)ÿ 㛞-…Âü²’ìŽìª,AqfÊ6oå ÒûÓ{¯—-9UÜ`ìÐ84䃂ޣze9»^éÏ¿Uî‹Ùbª,#ÐÅ`Ðrx¥ƒµÅÒâ¶Uƒµ©¹×´ýÓÉ3W9Ëì-©•õ(«6×çTE5Â9ºÇ}ôK‘PµÄšm)­†  ëÀæÈΊþˆ=å"o£y­"´†œAó½x>ŠË›ÿ,[i¤5×q…EWÔ£û.\fßÎßJEË“Scà«ö®Æ>zo7ÑÛ|Ô=…¡V&møëjñQýÂóý%œã2/¢ dÝ™í¹ƒEo Ô{áu¯·­¹ý¡wOy/×—õnþQ/é˜\&â@ÿdZ/Y[ü¢2i![n‚mþ 6Õ+¡ÌPV®ÀM¡O Ã†z¡µaž7ÀÍz)…)äY&Øâ÷î‡SÝk¶ƒõ™Õš•ØºuüƒÖ5NÖ½” Äù½ß{y]šï„ G²¬jÁVak¾…úCoá~Û~›±Âê ¢º²Ž)póÑMHa¯q‹qrå1~¿«68x¼9x&;#p•+ø>tuîôç½ endstream endobj 50 0 obj <> stream xÚ•’LSWÇߣ¥<qêÞs¼W³8¬§8¦D¨ba&DŠèh‘þ J‘_Â) ­PAlEq¨A‹ËÔR'³Úi4hæÆ6“©s..˼o¹ÿì!KÔlÿ,¹ùÞ{î=÷œÏ9÷’„PH$´5%a½L'MK[5µ³¢WpÝ%ùs îM’ õã÷º0” È ¹¼hΔÞ{eJòâ?>’$U\ÉòH‰$*N§7Ô¹*£8,;\¼,:zåq”D-^§QÔÙ ­Xª0ª”…‘7òÅ©ºlµÒh‡Å¨ŒFýê¥KM&S¤BS©3ä® _"6©*±LY¨4+sÄñ:­Q¼Y¡QЧ¡#§§8F_dTÄR]ŽÒ åigD1ÄâCBAä?QÄÏ!B –XHĉÍÄ"…H%¶~IøñÛ…ÄOúü¬‚0ÁAÁ„ð}aW É‘¿]sÓz—v—Á°KÓSp|Àu¬ ëæ2ºÈ‹\˜€ÛÄUÐ-¶Öf褺͎2¦¾¡¦¡ªjBðw8§²¶¶ *CÀÜZkÿÝÅÊ`[Ýr¨öNG7 KK• Ž6¿1õÒ›­ÐYe«iÂw‘2¸vMs5PeæÊb–gi©EÃ89céžÚ* ˜CŠ;+Û™F«ÝÚ­ö ‹ç¢ä…vÿäFëÜ.”3Ñ z b’V`!žé[}ëÜÃa´ö 3^‡ƒñüNÄQ F¡o_võ`[u°§Z§¬R%~‘hZüøßÙ>8[åÜD%á´ü„e¡½éÓSNg{ |Ô=äËå±;ÂÙ ð [ò¼QSCÀ¥#7}p9£õnýÇ–ö¢ÓÛ!òµ5Õ 'ŠÁ ”FT^Z­úYì ØUį{ µõð=3B>‹’&ÏôÚU ® (Õó.Çx—›ÿËå¶G^”Æ¿ï{h”~,f`‡²´„:mÙLâ4ÊTú!ìËzn¡w¦ãL½`Jýê¾àqäɼ;+࿽DS?ê{éñ¢n>_ʧÑ\Éo˜À„$ ÏÅóîG<}zÿšÇàíx'øåÁ•«×¯_IŒŒ~÷ ×ç!Q„%ß |´•F³&oüÀ4A345ìËíÝkÊy¨ãȰâP:»dy*u& ßÒ¢fÞ~Ž>}k_(¤á9â[Ï_h ÷ýìöKmЈ¢Š2c`°ŸA®€Ÿ;DK¿ÒÝf.Ãé£]T® :˜«/µ¡ÒÁÅ@k"l¶xfzgy½³™™B³.p×úêߪ¼´§ endstream endobj 51 0 obj <> stream xÚ]PÁj„0½ç+渥”¨…žD躕 Ýv»îB{ŒÉh5 c<ø÷5QöÐC†™É{÷†—õ¡6Ú?‘• zè´Q„£H"´ØkÃÒ ”–~›b•ƒpŒ—GáÞÅ€À_¿¿>Oo÷åñœ&×K•>ÂnE\f‡ms}hæÑãP›ÎBž3~^GO3ìž•mñ.ì>H!iÓÃîZ6qÓLÎýâ€ÆCŠ"Ê¥«%iŽNH$azdy’WUÁШÙÊh;ù#hAîr¿–þeí#oC…õ–TND‹‡x˜.Ño'sÖV|^o¸ endstream endobj 53 0 obj <> stream xÚ­YTT×Ö¾ÃÈÜkÃÈx°ÜÁ»{L4¶ÄÞ{¥ˆém¤Ã SöÌÐ{FfQÁ‚Æ–hxÑÄÞ –—MŒæ\<¼¼ÿ Eó¯——?ëýÏåºk1sîÙ{gïoûŒ€êÖ½nÚ¸jåÒ1ó–­žàhù`ŠÖ½’·Æ[ó(~ €dÅsBþnƒ(JÚ—<©ßúXžß¾ey¾KCÚRÝF©rtœ4ÞÑqâ¼€Àˆàž^¡#ÝF9L˜>}ÚX‡‰ŽŽÓæø¹ïtsõwXæêåîçJþðuXà¶Ó=4Âaä ¯ÐÐÀÞ{/,,l¼«_Èø€`ÏFuÛêå°Ú=Ä=x—û‡ùþ¡Ë]ýÜÚ}ßþœà( uvX°Ã=ØŸøjÓS(¦†PÃ…c„Ž¢3©9Ì2á«-V.ãÈ×=(?Ê_Ð“Š¡Â(šb¨îTªÕ›²¡úP})[JLõ£Xêmêj5âÈNC©aÔ»Ôpj5’E¦ÆSïQŽÔj25…šJÍ vRQs¨¹Ô<êcêj>µ€ZH-¢SK¨¥Ô2j9µ‚ZI­¢VSk¨µÔ:j=µÚHm¢6S[¨JE%P‹­(Õ:+Ø)ø§Õ ¡ƒ°²›¬Û߬G['Y_õ-£mh93‚‰í>±ûéî¯zlê‘ßs`ÏÂ^ƒzÉ{½êíiCÛØ<êÙço­|«¡oXßG¶Ûl£ÄŒx¸8´ÛOÏÒlûÏ·=ÞÙøÎU»1v:ûaöÛúÛ÷/`5 e`Ÿ1ƒ& Štƒ[Èñ’½8¤;”;sø…WÚð·ÀÌ[›QŠAð²y4?¾/ä×òÃXD›qĈZŽ4æty‰qŠˆXfBóÃJËóô%Õ^ûÖp+ÁÙ=Iá_³&%˜±˜Ù€) Í𽉯ÓN2XÈùÒ•šZ£ñ¨ª¦×03½P‡%è:òxó}­¦Q[V×uäû]ôUVµW —,²¦ŸÜ©ÿ‚; eá`Ôt¤*,@® .WÆB<Ä1˜¦mø¦ö|"º¥Ú`K¢Xúhq³øºKÂhH‹Ý.Á{þ½/¼Æ¶ñQjòìÅwUjÄCB·=½W÷9·ªwëC·«äÅx›b‹öìÉß{vmýœñ¸çF,àþB°¯]D ½¬ÝAÏfñ^LÜû³ùßhO¹µø¶Ô…Ö'w;È€‚k†þ„iäif±7 ãñµ†+\”BY|¼"j7ADztœ±i½ò¸G•~u`w\ÆÿòÁۡܬH€- {ñ7Ô_›«Ý"¢C«\õ›€‡»(ÿRÞxþQ/ê úÙýÚ³\ T%•ìPŇ@H³£ “^ɧ¡•´-ò=[{±iéYÍFFpÑ “)ä¸gWamY+)Þ…š¿´­D½¤†+–‡ø74Ž¿Çž 9ìâTXÍé!735U£ÕhH¢j!F!ŸÄyK—ÅÅ ”LbŠ"%ëî5ÔƒCëßþÏ^´i-”šùf”oÔßÝ 0¢seÂÖ¥¨7«œ±ÄÛ ÖÁ†ã>ûNÔ}Ùp³¶¹¸ªEØiÕ:µ\6MØk˜/Ý` –Àî¤Dµríh§.ëcó° rFôÉs_^ƒf¦!êîÇËæ¬Ìk꼪‰Ž£íœ¶Â:fò¥O¹oáìÁšÊ‹+ÎFkpþ´öӿް·”gÀÌ|SWQu†ª8XôÁä ÆåCÖ°5Ïïಢ€ê 5KV/K æýÐ''%p{_õÉ&Æí}ï½vhy´ý?†Ö†·ÃºâWkô‚§g„èœÈ‚´‘¸/²õA«4w?š‹ú ¾9Ù “¦ÐɹÝ0aÁJ,Þˆ­â°¦ÁÌ,ÜûSl}÷¹·8˜Ôd]šäÍÞ(Šl^t,Ü¡Þk‘õ ÔgÊ»‘+r (AUñãÈÓx`wÀ³<ðÇø-lÛá¬ÀøÒz²U“‰iË£=•q8_Q•î>ÔÕ݇*Â>ôeVIJÍuôâÅOfÛc/óÃ`#AO|}ù9"îÜIxfDnal=罉kŽ® *û€)ÂäÅ%XNW½ç‹“5g€yxðƒéøpÓŒµËðZìm'“‘oCñ ž•¡¹ÖÁ¢$¿DçÝщ ‹@Úî½´ì+Ä a{PŸ>7ÚÖ£nSF>šõ\Œ)t½`¹Dà¹3éÔ˜á³VÌò6„—›õ†òc[!š3mΩæÀ§Ò ˆS­ röÛ²S¬NP‡¨!A¨†ÝŒ¸M&KƒîèNÍ‚Qxà|g‰ Ì.ð:[•d6À~¦:Pïâãìøx ›‡æˆq¸³ôÆÐâ|Q3ïJn¼NFÓÙÉ´§J6‡Ûå+: k‚úúpàMû¾ÿÌ<‚ßB`OââIM$Äásm;í|id$ô¬!%ßݺ=pdõ#Zj@ïܵ=öt‹…·ˆåסm,ê9ý¦¸-àåéÅ  ´^^™X êséaNª2%Q¢&¨&)Ãâ7‡-7Ø–¶µ8A§"Ÿ1»!!J‚ÒË¥V—œš•_sò64q[zD¾‡vlbįÀ V„¸†ìðÚsaõ‰È³:µNLe±¤$Òè㕸mÊÅѨ›Dü+b~þ‰%í>óCöÜ}XGêÚñhñq²C·Ù¥¢·ª“¦S/7ìd¢ÝÀÉ·$Ú¿7£öœó‘÷q?<³8H"~…õˆùø1~ÿwò¦xâXȉÛ€Çư- ꉯ²KÁïœ[­ '.}ä[.ʽ:O½G©QC8ÓVô'®Ð)Iu²œÛöÄ.#N£N&ÒŠ$üQºŸ“|òRoVy{oÖZ£ŸÃÖ@IÛ,Ú2P˜Z§™$!Ÿ [ÝÑ#¹à1„_ãxžŒ·“\Ñ|´A“‡¿Åß±cpÿïP.ÊFÿ¼{ ýgàBÞ4oç³RÖ]uRyA]­ÎL ↉…Ä ÞJGBbmZhtºÊæ<[ˆfé~ëGd%_†g‹îLÓ“zó zuz1šS#¨6¢ô”n¶Žoζ!Q8–ZE¹hJ^%…`‚LU±‚Lþ¡ Ak'Ä áÜ,šëghhxÞ®¹Üè!»Ï’j@f¥Âä,m)y9Ï;OiçŸx‚Ö;ÅÝj&4‡¢XÒTV¨'r';©r›¦´êhÉGOï˜(ñ ÅOlT~¢\ê7{gðpf>x|ž#Vš¡¡®¨‘IDï³#è±óv:mÞ^uŒƒOëï¢é©Dí7É ²b~¨yÔÛ¾¼ˆòÑl¾7‹.Ñx˜ÌÚ—¾”ž¸YÒöØHk4é¹¥Œøh^hý¦+$Ó{þò#b‘xÔS,"ýe&¸lŠ`t8ŸEÛi’”š¬üÚSŸ¦—Àa¨*q7m×­†íà¡Záï´Ë×Ý{8gIHML1™Ü ‰'+eFTù¨Æh»ï.Úð(Æ2uGþ,šv§þ—çÕUžÛ•r?ˆe‚ ÃÊLú‚½_Ϊý÷}°Ä[œøî÷t$™¬úW ^™™»AI†•B%÷¿8΃ˆ~ý¤ƒhФ=bi=oß11•‘tç·>eÑhD–µ™þ$!í¨D|”ÿå÷ñc_Ú¿ÚÅ´ÎrÝ5dQöâG"KÔàð>cƒŠ»aW"@%‹ôÛâ$u±g Ùt@y@ö\ùábóþÊ“PõÑf§¬H¢®#:ƒö+Fs ¶ewQ|sûÚ ¥°©hÔ7Æ}À<ÏÄvHpü.Ë%AÅO×=Á}1óÞ0ÜWBbîÿb4¢‘Ía$,ÊLÐ&Yb–«¼†M€Ý° Üö†Öøf¨&£Ã™Ž[ÉÉߤ¨[ó£ûB4ŸÇ"†þîÈ‘C|ë[ãQ¹þ“©ës˜þ_·up‹‹®"‘ÙRêxû´úÌ7{ì±-k »Šæ^­jr>#þU†‚Ñlv2<Û#RMEž1={OY0÷aD¨Õ>ÑÁ q¡ndf ɰ§@_p@YÌ㋯K &ª&xOõ¾ê”BRo) SËI2ˆc"sâò3‹ÒöÄUì Eê,wÝîZéª#óöøùó?’€³Áݸ+6:¼q+¾9îæ°‘>.àÆÌ{ºÙ ¿¿ÁAUÌñeëËVÁrHÔø$ï29Ýaø";|þñhØ_sHÇœÝCÝ`ʺ7’t\÷¶§“Y]Dî…ÈêÛ T•渶ÔÔ¤Ú÷æÚr)ýËW§.œÏZ·šÃ1ô­Û@Ì«÷2h ÷Àì[Sà­_ÓÀyE¤;ƒžÿ>1-!9ÖzÔû¥íÕ—Ÿ4‹£Oøå,v°¬ø"CNR×Ðe£BsR[RUÕac‘"¥–Œ Éü~¶"¸8ÀWh2—‹+EžÁ®†üïøö}Ý5½XÜ,~…<,;µì|=ÃB ´Sü”%\ÑVA9yÉú\(eLú€€ˆ°  §N_ýüÂCR˜­ãÿ`&åK:Ò1¨^ð²Yøò5`•$³Ê÷Ö©ë^öœ¾ðéõÁõk Â>ðix Â/éôf´‘ˆŽNt›ë3/ø÷ÖùÓRÚÝÑZü$¶lûù-L9d4~÷}21ÄñKpà ¡œÑ!_¦Á'"@㸘¹Ë[H§èyéî•[õ“×ÀtúËæ—÷Ä×чè[YÑXò:ãŇßäÀ1þxúi}Ë5˵hÕJuX1ÅцBcvE…o¹ '¾><Ƹ`9™ŸZd[i >‚"Œ¡GÄ-hZÏw¢`³ÑËm&7 'ÙEú$‹ªNîZÝî›b½¦}æ8ÙÊld‹µK‰Ñ%X|Ó¦¦äþ„ªí~Æ5É2ËGö9 k÷·³Ó²yÕ¡8vïþýGKLæêy¯ƒT~ê ¿õÚXËÎŪôXˆ‚¨Ý±Iòe3ífþŸI¼Hµ‡¼¼ }ûjõ"UÔ®­¿±]ºqÅSÌÚÃ=·¬Z©Úö¾´IkÖ˜ÊëU%–ª•êsˆ²2”W~öõµv鲜(‚I||t å*s¯æ”ÖPZ«ÞkYº"´¡åíÄàj(ü†—’#ýFÈO"›Î×äC׉FlÕJ-æÍêüH²»Õª¤¸áXm‡…È ÈT%ÔL5PÄuxÙu¢Gˆ(ÏõB£ÛvI±1ÞòXéÚ€ùKÀҾà ÍÉéÈgLáù¡aÒX?§zÏcÜy8pºä´E¥‚‘ïgÔÑçF!ߟ—ÍȲ““¾,’á)dMý¹¨†”ƒD"\ÑÖ;Þò[H’}LqÝ ÖÁ¢xÜc—3f,BZDH1 ¼BÈ+P:khSHi›WÑí¾Š¾Š²|ø[”´}‚l~&xþìñ3!ræÿÉ–„™ü¤Ò€ƒ´l¯ÞT¡uo—I ~aA!!ú ½eCg#5ðó VªA„·gÓæ{2zõº¨ïÕ›ëÑmš¾Wwt¯ßÿW0Ÿ endstream endobj 55 0 obj <> stream xÚ­X TSgÚN†‹RZ¡™ µs/¥NÕÖ«¿u©m­ £ÁŠR•‘E-„% !!!{Þ$d!a_"a‹È"Š  X…âr\¦ýÛN©•Ú™ÚÎùgþi§ýnzùÏÿ€i;3çLÏÌáär¹߽Ï÷<Ïû¼ï›åïÏb³ÙÁQÛ¢â·E?·5:nçêÈ™¿¼˜ÁX¾¡}åóèE,úI6ý3?šäÐ?õ'?ÞåÿA~?c±Ø[Î\‰Gñ•õùc3×§ð%¤.„åÏfÅ¥¹fedäó[óafzFaøÒ£ËÂWoØðÂòðç##7„oÉIfMÎ N.ÌHËI.Ä_²Ã÷åÍL+”„/}1£°P°qÕ*‘H´29§`ež0ý¥eËÃE™…ᯧ¤ ‹ÓRÃwäå†ïIÎI ŸÃ¾rî×Ö¼AQaš0<:/5M˜‹q±–²W°¶°¶²v°ö°bYûØÉó2ÙÙ¡¿CÏa²æ³‚Y¬Å¬%¬U¬Õ¬µ¬ÿ`½ŠïÞÆÚŽWD±v±v³¢ñʘ™µ¬8Ö~ÖV<ë‹ôc±Yþ¬O؛ؕìk~ ~SœÿDÿ?λƵ¬¸E¬!þ˜HÏ·- ÔÕ=rà‘îàÈàGW=úà±Ä…|ZL3ÉîÆÉwÜt˜==Ùáf ï£Oß½ÏAôbJàneú:dazŽ] {¡ÙSëmè«3áTš,£QS$Û'~-ˆ|h«¡Àuöö÷ÐU¾Éf¶âû\j(!·áÓ¦ßW_GÁÖçõab9¤‚‘WŠ[Ýí }ï2óAH2lI0OIVðwqK .«„:êwãSR*;¦Î—H€¼¡ÓZÓM„[â” …¢Œ„sânò·p=ÓŽ~NÓËKó7ûšØhùµ0j˜Á¬vî¿§š‚»€ž§%ÕÔ˜L`!ì:‹†T°q-Áø1;³™8‡ØÊ×z~1°·[E…úÎs§F8t}ãå×%#Â[Ic2 4:†Â våå Žu°˜'c§5“$“ 'ÔzéðáüÐN/Šƒ¯‰`s…ý1²qÐUÃk+XªÌ6›*ˆªr’L®ÏÊÊÌŠÐÊA¬¨4VR— †QnPTŒßôn>C×kꌦbcrgßí€FûePÍ@3è• º/‹;&ÿ¥P)Œ’r›ÞNuž²xOv{çP¥6•Q¯› ­P °UÔ!]ÅGYÓŸYKM†ÃD`&1Þ˜þ¾VtÝËöý亅îðÐ*. A‹þ„ïGÝ`Ø3úÞ6(¡@ŒY4Ýÿ7üô±œî?s:(Â>cC5ˆö‚£rŽœ…у¼Ê;tñ1÷îÅü݈J—¥%f¤Ç`‡…pqÔaKF¶³ÑáÛ(ñ6Ç7ÿ®Ôâ+WÙÇO½µÍ$ÂkeØø@A¼ûÀ˜À¦wkjuÃ2þ¥R‡¾^â’¹Š ˆÜ¼äùW^éù’„Ö6‹ Ì&óLÞ•ƒç¢Á +gÒøØgzì3Ug#í`2;œ®ªÖ“ÎêÞý7J/á 'Pê3ù'…Þ2Ëòv±5»Rkά-9 gˆ{ïÿfê³ö¨-$äÕº"£Œÿ}£'‚—fzÙ>E/‡¦ÏÞé0;LsÔñå Y4¸š•±ÅL(ò™ÅÕ`¶X:Q6<Ι‡3íÄ£$–‰âcÍÜ®˜I Ì´Åb6›LÎÖóè©öfÄâ÷.} Ô†rƒ»ú¿<£\¹«6ÜU`¥.ŽZ.^º|qÖ×M.%”R¥\)d›õgÑV@ 6ÑŒ‚Á´Cá¦5Ü!ˆu½<ú>úÓ8Ïu¨·¸þù¦syø58ä­Ds‰UIf:Ó¨%BÅYuYXT3ŸYÎ<³nhû»Tèû=p®¹˜¸Œì¼f¯*+zc„%¨Æ;)ñ¢À†³ž‰¡‘3@œóÄ'ã@7j Œ4 #]áFÇβQÀU$¸ÅAW|«y&‹ÙáUj,*RJ£Þ¸TÅ/3*Œ &N¨¹`V+IÐëq¦,¦øF½2ÒˆÎF½ƒüQ z-ù:f8†LƒÌâÌ,B?Ìo~—‚s•݈kosmSGß©> ¯gQ,`äî.&mæP¡¾Ýläw%Oqè(úÞA ¤` ¥.鉶wßpRïnæ1†‡»Û3KÇw~‚ÿèµV•KEê0¡*å–ÏëJ€Ø/£`´íÏ­znŽt‚  µ)Ez¸õY•8ôå·õ½Œœ_ê´%ÿ@‹9%~”ܵ¶"¶…§ÊÞ³)ˆ¿UÍ'Œ yN©3Ä 7ê¾Õ Üh¦‰{iû8H…¤¼N¸e¹ÐøÁI¸ vbèØéÝÌÓÏ0ÛW_X÷ù? h—âW§)èsÚÛ››7€ÖaqÑBù³ŽSÁhn´¢Å^´â×ͳƒÕ5” ¶(j0(î%¿„3蘽Ïãs"†}‚¿rþÍä{¡4ºžæÍR-Á¥ª\Ás{PÉLm´VwU÷Þ@/óXçFâÍ4ϱ™Ì2­r.HL¸€+»Z?ÂåÒ⦨ÈU‹sÖóåÇËð,M‡ñ©-)—>ëBÏV¡¿ÑÒ…<È!+ˆò„Mªš¦öÆrޱÊIÚ5‹-ã>Êx+á£Ði܏߯«¨ƒâ|ÎÀ¾¥˜%ꇯ“­Îs½ÿŽQ¹HBT/ÖI—O/äˤnŽ ÈS·Ër'Buyc¾$[–z¬·øùLÞlž"B¿@Oø6ðÚ‹le‚‚¹SÔÒâq{0luï,û³·~ty3 §õ|£N+‚Rbvh¶jO}wÍ GŽ{“Vf0K5߉O‡·íóÙøÔçãøT d©ùÛó·@<±v,÷29 §:[:öhÄ,ô—I…"'j® ÕÃZIñºË¼¹…ÂÂBävµMÝ’oÉÂ…“—ÀT0û#]$Œ|Ðö¶µÎVûO£Í^'Š"òFî8zqýo+LK˜äÚÑÉ!7½¸IáùÃTîDí•Я¯•—ÆlØ’ˆ~‡e}V »Ðd7y­UmPG4K]’²T;ø3™oâŽõ__xþðß49÷„ð|žú{uîјØÇ¡_ ·¥ºš.rÓ[]¨À\çæ2É®ïüÛ Ü•AAä|ÿš‚‘ïñÿ_&$ endstream endobj 57 0 obj <> stream xÚ¥“klSeÆÏiKy…:”PQΩ(ˆ(0äBŒ@fœ"›0`2FÙ:ÚÎ^vzÖÛnmwi·ÛµëeëØÚ¶›»06˜ˆH” ‹pÔF?!èÄ5ø(FÏ@ˆ&~óËÿä}OÞä÷<ÿç! ‰„ I2k˦]y[ŸÍÍÏmuÎÌÍ‹ÿ­Ã7]³øÇþq’_$â)1ÿ¨„º²Yò§L´ˆ Èy “¸5ofþøÐÌ|ZÒcó I"s ää¬Y™“ó|®Áhc4Õ¬bYé3ŠÕëÖ­}Nñ|NÎ:Å&ŠÑ”*õŠ|%«V锬px[±ÝPªQ±6ŲÕ,k\¿j•ÅbY©Ô™V˜ƒ/=óœÂ¢aÕŠB•IŘUeŠW zVQ Ô©wÙWÞýätÆ*VÅ(ò e*F/ÐÎ^On&Ê ©#YÂ*ÀÎ#$ž%òˆÍÄëDñ±“ØMÌ$!!Zâ*Ù zD÷JŠ%—gµðž,<7È+7ÄxÇ„|À”ÒëM&½>eH¥(áofg/ÞxƒÄ¯qb\â•O1ÇÊ´Æ`LT¦: ³-öû¼^/ ¯·µ–†Mê7´Z‡ZÀƒî@ô›¯ðTÿQw‹xûù%‰ù£üïòÐa_ø  CQˆ‡›ü 4Sàa´ëµ²Å®z°8BÐG'!é–”§ÝµÐÔÒØÒ™}»$Û´<¯hTBQ¤ú´¿µ|€Žõ #vÛžú¼ü‰½_ÓÓðÛTúg”Å×f”\ü*oÂK®õpäÄ4þlZÌ‹ù§äW¤‰$¢N°Ó/H{±´­7öy°ca8ÞÝÕ mÐq[‰Û©†ÄöÔÇû¸£'‹“( l±é–5™=NSf>zEju€µ> qzJºñ6m[nÏÙ ÝÀ€µç¤?< ](ië°Vê«TûN˜Þ¥ÎÀø'=G‡/$ñƒÞv”…rpü ?rüæÜ{çÄxìæ,y¢ök4V­1{*9˜¤6Ü–É;Àé%1ˆ£÷+Æv¯Pe–¸œðQðú‡ú¯Ž uC æF³ÛÙP¹/ƒª÷;+ë´`F{GÔ§®á%ሠ<”ÀÓ\cÛ¢-x½1’¤!Œ%Ï –­,‹|ËûïPÕMcý1ÿ„€¯í6±:Vg‰U'ûûûú©LñkåÖ on‡&¨[x°½«è#ndô惥ãU§¨ËðÃDúçi^”H@ ühRyd÷’Â{ìaðzCñôù“ç…,ÄzÜJXÃmGY·Dw¬!oÎ;×uQ|õ¹§¦‰…fd‹¹º„èõ„Ú^_ÇÁ4÷]v rd[whÀÛÖ54ñý€Þ—ki` :Ce[6¸-. 4/¼ó|‚éÐpìì^>æïœÀ2Lz/ª9HC¡2#µ¹LnXÐÞ#êÓ–†þaZMQÅË;î›N…¹øéãX “èÓÒã©ðfIyQk§gÄbz+ ¬†=¯ÛÙæIåà>(k™ËfS×mro{Þ ×ýyâԨІ®•°=£n—°‰»á ñ­ÿá@þžÌ‚êý.¶µÿ)Ç’§Ý¾çßr&Žc‘ çÒþñ\êoø³†ŠïÀ;mÕšÚ­àþøD´N{ÿ!À/¹ òâ1> 4îú½ÆÙè5ÒQ¼XDu×Gì” ­.uYfMö ©Å)* úª473涃 í<ªúø—ÉìpS.hõ4;ö?YdÒ2;;Óòµ·u †}æà:¯aåµNŽ˜Æ—¦Åø[|FìKN_†¤ ·ÎÐlaÀ„ª£Ö~n¸güôÖ˜†Úê¢z–™ÚÑz²0#gf´Ñ!ðû|á‘Si¡Vñ#®m4¼mµ<£¨ÎW+K„ȳ`îL¸^xõW…jtLeEñ‡–ÔŒ^ö;ÊGËÎúuËÓ3vÓ.hq·4jy¦ @eÕÃ#4K‹ž@YUŸvb'Í(£³©9’µ Ùí²9^ÙÜ¡9_ÌMe2|eÁ_C™- endstream endobj 59 0 obj <> stream xÚ%kHSaÇßãæÙI—¥¹²Û9§L*:0C´²ì*Zõ!šëè¼ÌùÎY²VY4}J*Ó˜sÃ[z(‹¤‹E&T`´E1 “ ¢ë{ìø¡¾üà÷åù?ü(¤T"Š¢Ô»3³²röoJËÈÙð-ùrÍß¾¹³ÁÒJ$­¢¤ÕA«–)W#„¾†øaQ€‹Œñ#ècRRƒË/èt›cuº„4³å„µ ߈ù †||RR¢–OÐé’ø&ÁZ`ЗðzlLzì—bþ€ÙP àü†d#Æ–mqqv»=Vo*5[óS6jy{6ò9B©`-ŽóéæÌgêMx96€4³Éb•Ï0¬%QA›P¼!5Š@KP$Ò :QH‰²P=BÕR3’+ln0º‰¼zD^{(iÅ#…´—Ø5ä1íö‚Ïg'?&=´¼ƒÍÁÊ=rÊaŒ½àæˆßhØ|>ðºÙ0© D©S|ࡈsLAçÂ5­U-l®áP©˜BU+<‡Vf¾N•çrjYc!}¿æ=<|8 ÷ÕëD£JëºÞÅÎLo¿¾ˆTï/‚?+ÈmrLÓØÐ-6º_ö¿èƒ†„®•Ãeu².áȽs†»Ïƒ“ml~ÌlOr"Ñ;Såy¡!/rž†*°2G·“=ÁÅ´Ë^yØY~¾2*€‘ÓiÿfÙ­a¢ w ´Po¿“ÜŸ r…LkÆžf¯•ÃwåâÂv±—¹Óì;±¯Èb>iÐ~Ï 4Y>ûé“ûFb¼cm/ÞÀ83ßÍoËNÍk®héðxÛYè*rÛ.v÷Öܦe¤r»KôŽ S1®Ê¼P^]Y §Ç5¸ñ¿!Y&JGý‡Þ)$vn¥Æµeì)¨®>ã‡æ Q…äöVÁÓ),.¤§j.Aÿ%˜òĪW}7ù[\£Ú.kæƒå«ª°²&)­˜ëj›hY_¯CFBÛ.«Õ#ê…lˆ2Ñ£^@þDþ5'Mð endstream endobj 61 0 obj <> stream xÚ]‘mhSgÇŸ›D}V³ìͰŒÍ{ï¾lj¥FÓ8H`ÃŽÔ¨ºZÐ4½kRÌKon^j’†˜¶Iz®i“ô&1Ú.&M²ÔN×±Mæ´›Ý Â`T„±0ÊBÙðÃ÷Ö«liÁ/ãÀsΧßù©Tˆ ˆ'æƒfãÛ­F“éÀžÕÅ>œz°¼rfô"’^"¤Í ‰TJϫȥvÕ¿jÅf„ôÌ*ï?µÊ{O¯òÕ&”¶g‘Š °÷tR¯­M¯ßet¹X{¯£·X·Ò; †ÝÛé]z½Þï`X»Õâ¤MÎÆ8,\s8EqYí 7@oÙgã8÷Þ;ü~›Åáis±½onÝNûíœ>ÌxÖÇôÐo¹œÝaq0ôšzÛ.‡ÛË1,mrõ0¬!BÙŽìD³A­¨½ƒ¢u D Š›ˆ Šn)¡‘~ñÕoþ#ùg‰»¢R)Ý’þÖN\>›ýð¹Lñ£…05 ƒ‰VàÀ Ã|„?ÎG‡ ÎA…â¡ ÓÉZ2‡ÄGGƒ2~Èèü†‡Ìàƒ#ißWøvêûñº·Èy,³iáøoÔ2ˆèÇéûX#>ŠÖ%ª.jï¿/ÎÞVŠó+*íÅày®ßéqxÏËÕ* R~å¡RûžLŽ„F"pú…ιÞoþüL¤ B,5DF 9”ˆrotw[G"ã5 *™ÉÂŒPj¹ÚÌ]ÝD9?ð ëåcÛ,2=x&Ï’àÓ)¡¾üe­ÑùÃ瀫iÖKÁÀH Ö—Œ…Ìñðò6]<4ÌBsS±9 Å|&ŸJg?/a¯$…\Nt—ÖË'… d‹j÷‡ê'2ê^½ñR˯ëcjµ¸´é?séŽ[ endstream endobj 63 0 obj <> stream xÚuSmlSU¾g-íÝ(…òu{A#La”.#q$:Àp˜R~Œön¥mi»µëÛuëÇJ¨í$ 2ÂW1£ÁÀ/üÑ„ÄüÁ¿sÆ)Ó3’˜›ûž›ó>ïyž÷9ïEœZÍ!„jßoÞѺ»ùímÍ-{ך¦v69'?yòxâÄ ²Œ#Ëy½Š¼¡" ÔƒÔÿ誖rÚ3g*n}m*®žÍ"÷& 3Üs¹„fÍ_^·aóvåÊ/n©Ý.ñtðH²]òx¤ÃÝf»Õ-™eÉýì[²KÉ)ÛœlÃ#Yd›ËiwYm³Ýå6™ÖÕ›L Û\]>·ÍÚ!‹+-uâÚ¦¦ÆUbƒÉÔ$nuHn†tŠÍf¹Cr˜å©2±Åe±I²O\¹©C–»6®YãõzëÍO½ËmÝ\·JôÚäñcÉ#¹{¤ƒâ—Sw›’Xi¿¾²ls9ºº™$±ÙuPr;Y“Õ7—›‡¸Ü§Üg\;:Äz>ƒ¢(†úQœ;Ž%Xf?ׯéª8Ä©¹:n©‘Ý­ÒVí­:§zOuW5IbµìWЫ&V`¿þdŠEøå‹¿¼Þœ42]ªàz…DTaHòpIG5ô=º˜.  t¨¿kÄ£šé|QÃ2*\ x Ö°g‘¦ŸîÔ¿8Ÿ¦ÑϹJäB±"«‘ü¥Ï e†à8Ÿ gB„¢Ñþòu:bð‡cC(é%×iÞ @ø\6›3B6šògÊE7TÙ[ÜGåqÍÑžWZ›¦{ßפRiÈÂp4õyº|ç _¤£Ð|  !éËõ‘Q †r‘‚7CïÂ`6”’0ù4O.жÿ£«·(Ìðgž§"—ÿcù&Íq¼káeÀcÓK6h躄ΧëézÌV¼Åˆ^Ê›4tPí£^Ä3Š?Kø€‚ÈEE0þM>–ìÊþéû$Ý´Eã_±…‚À ºK䦂n*Ä9UBfëñ*ºú6ÃWn§+„²JûŽ'µø-Ü8vW¸ ·B?Øî·Â.èâéSí+'Þ+¢›ä†Š<&?êSùÄ ñ¹P6(ƒÞHä( ”Oh€œ ˆÀÂ`hÊÚ~èOð@ùgCÆŸŠf!Étj„¯%1š,‘öSÄVDØ~G…ÇÉS=(§Å(=”„›  +À´'¾•§G´p:-‡:œRw¼/B/KÁpüvôª5ך 2*+O[µ`†Î«Ò%Çíà%67`s3Ì ‰[Ǿ¼˲çq»®„OvŽõ”œÃ®Ìï__Ÿž«ê([©¢ÊN«õ`9¼‹¢H…“æ +ü ¯%îñ˜©ºcÊù g/Œ&*º+l;÷¯År6¦ê{ÛwÑrnǰ øP˜5ÏÔߊ^ëÌïI†*Ꙫ¶Œ¬³ÔsöØ7á&ÙÚñµø[¦êI 3j¦¢Âë&öë PðzÁç&׿tIžS[د»8§jÔE]uZW“ÐÍTj”™Ê ޽³ðƒyÿGQ–Ù endstream endobj 64 0 obj <> stream xÚ]PÁjÃ0 ½û+tìÃI c)ÒŽÙ=ôèØJfXlã8‡üýj7ô°ƒzzOÒmºSgMúœâa4V\Ü€“±¤¬@÷*g5KOhÓK–3½qÑ ñÚôüöñvmùÇCl¡ÚëîÄ·%âÜÙÑc€~ß.1lpøÔnÀ—„]‚Æ`ì‡kÃ3ÂWïqF¡ uÇ•“”Ó¸x©0H;!aEQkÛš Õÿz»bÕ „³*ŽUæîhR%{Owj á¾7ÿ ;JËÅ盼óI•ã¶mI endstream endobj 66 0 obj <> stream xÚcd`aa`ddä ñ Ñvö Ž´ Øæþó—aYøs>ëY†rŒ?ä™~(0ÿg‘{èÅòŸ‡I–‘UH2üã‘ß@¤:Hø–##¯HcÛÔ‚¢ÌÜÔÔœÔÜÔ¼c=#çü‚Ê¢ÌôŒdMCKKs#KÇÜÔ¢ÌäÄ<ßÄ’ŒÔÜÄ 'G!8?93µ¤RAÃ&£¤¤ÀJ_¿¼¼\/1·X/¿(ÝNSG¡<³$C!(µ8µ¨,5EÁ-?¯DÁ/17Uì=0霟[PZ’Z¤à›Ÿ’Z”t"3ƒƒÐÁËÛ;XY4³Ïýèàûyî{ùNÆ'?¥™ú/½°{Ñ¢Òîjù?ÙªK»KJvÏ–çû¾eË‚…óW}ogþ>÷Gžè„ý“º§r¬É]˜/—ÜÝÑ^û[ø³D{}wGwWwÓÄΩs›{»{»ûº'vOšÃÁ÷3Â{ç÷Nb|²‹ùÇM«‚Øf|—ÿÎñõ»N7ÇwK6¸Äo¶ß¿U+üvúíü]í·üwwùï6Hò–l¿uºs|­û.ÏÁW¼ø§ý¶ßrÓÙ帘§©þçáœÄÃÕÃý“k'÷ι<<@Ìûý¡€ÓÄT endstream endobj 67 0 obj <> stream xÚ]P±jÄ0 Ýý¯”’8ÐÒÁJ®)®)uŽvul%g¸ØÆq†ü}c_¸¡ƒzzOÒSV5ÇÆèÙ—·’c€Aåq¶‹—=ŽÚZ€Ò2ìUÊrŽdÕI¸O1!d¼ýi?ºÇêôþKó§sWÓP8Ü(ÝêнnŽ|N,0F²ïmâü ‡7e{|ˆXëzmF8œ+ž¾8wÅ M€œ”eGo7I«pvB¢fDÂò¼V×%A£þõvE?È‹ð„=¿nÌ¢ 4qw4ª¢¿»=¹x¿íMOHŽârmðþ'g]T¥øñmZ endstream endobj 69 0 obj <> stream xÚcd`aa`ddä ö÷wÑvöu04‰˜Ë|)a]÷s놲Œ?ä˜~È3ÿg‘e``ø+"ñƒÈo RH0ö1°22 J´õÌ..ÍÍM,ÉÌÏKÉ,.ÈI¬400Ö300rÎ/¨,ÊLÏ(QÐHÖT0´´4×Q020°TpÌM-ÊLNÌSðM,ÉHiMNÌQÎOÎL-©TаÉ())°Ò×///×KÌ-ÖË/J·ÓÔQ(Ï,ÉPJ-N-*KMQpËÏ+QðKÌMU€øCB9çç”–¤)øæ§¤åÝÉ$Ú˜Yº~tðɰ.‘ùÕñH†åãnF–O@¶èwÞïWX‹ØR”ݳ疵iþéæøóžíÇÄ/'Mîíëž ÙÝÛÝ×2õOÚOA‰;ؾKu?«Òy°ùQÕ­È%ÕçãÖZq,aûÍû}-«Ìï$¶’î®®ŽÖ®ŽîŠî†KÿfHü™õçsc}w[w—dÔî¹r|åóÙd~WÎgßŵ‹{ó$ æ•ãb©ÌçáüþPó|˜ü endstream endobj 71 0 obj <> stream xÚÎ_HSQÇñs¶ëÝÍnšæèŸÞE››ÅdöÚ´YÊzé!ÈánÛÂëÝ®7—ФEby¨ ÐZ³Ø¬ehD½)¸‡‚¢‚Í—A°ò%(8ÇNy_>ð}ùñƒ€ã„PìíóxüCí^Ÿße´+În4r¹ËUt/ 6™¨d¦;¹&Àza¥Ö°¼Ý°e“¹p ú…‡c¿ÝáèòªÑI- ë¨u¤ 9ÝîîÔåp¸ÑQEÖ"#1ä èaY è›1ŠNª#YŸD­‡ÂºíéìŒÇãö€2nWµÐ‘¶èaä—ÇemB¢c꘎NŸí^U‰ž×e ùÔ ¬MíÀ A=Ø8€€CàéÕš¿™mü\!ëiH}+fš$º•ùTg³NØX‘”øÎÄbXKH¬ÄŠ–„†c± NÙH‘•øÖ²YœII5”à> stream xÚcd`aa`ddäpu òÒvöõõ4 ØNûÝ'Ãrógëi†2Œ?d™~È1ÿg‘{èÅòŸ‡I–á½ ˆ|Ã"_€Hu Á8Qˆ…‘‘£´ªÓÀÀXÏÀÀÈ9¿ ²(3=£DA#YSÁÐÒÒ\GÁÈÀÀRÁ17µ(391OÁ7±$#57±ÈÉQÎOÎL-©TаÉ())°Ò×///×KÌ-ÖË/J·ÓÔQ(Ï,ÉPJ-N-*KMQpËÏ+QðKÌMU»]L:çç”–¤)øæ§¤åŘ tž##ËÜ|?Wÿ_ý]dÁÁùŒß%n,»ÎüýÃOÑÅ•³K ò óŠæÖ,\½då9ÿßEû§NYÜ?¥oJÿÔî9‡#WEªFý–(mëoš)7³»obß”åo,ZÞÍ1R]‰|wykMgKøo‰ú¼îκ̺ܶºî*Žˆé‡>ìý.±°·kz¥\mwW[kEuD’D7GeÓôÅòÝó'Κ±Šƒ¯lÁç©Ó¦}/XÀö;a*»‹ù|ÎI<\=<Üë¸p¯ëçáùþPEÌ¢5 endstream endobj 75 0 obj <> stream xÚcd`aa`ddäõ ð ÷Ðvö Ž4 ضÿóa5ü¹Œõ‡4ÃÆ²L?䘈³È=ôbùÏÃ$ËÀÀð^D¾á‘/@¤:`”b`adä(­ê400Ö300rÎ/¨,ÊLÏ(QÐHÖT0´´4×Q020°TpÌM-ÊLNÌSðM,ÉHÍM,rr‚ó“3SK*4l2JJ ¬ôõËËËõs‹õò‹Òí4uÊ3K2‚R‹S‹ÊRSÜòóJüsSÀnדÎù¹¥%©E ¾ù)©Ey@G1]ǰŒ‰‘‘EëG߯°ï%û¿ þŒaþ¹á{‰èì%ÝK—uWËÿåb«.ê.,\Ò=[ž¯xñOû%l¿§³Ëq1OSýÏÃ9‰‡«‡‡{?×~îý xx€˜÷ûCe endstream endobj 76 0 obj <> stream xÚ]PÁj„0½ç+æ¸K)FK{a„Ú–º~@LFX“0ƃ_ÍÊz˜yóÞ̼ID]ÖÖH¾É© ÆjÂÙ-¤zeiÚ¨pT1«Iz–ˆFúO9!$¢ûMùÔ´ïMÊŸ»k•¾ÆáN¹®!;êºl×9àTÛÁAž3€äg›8ZátÑ®ÇóŽ}‘F2v„S'Úˆ´‹÷7œÐà¬(â¸ô~“rg/’´#²œóòª*Zý¯w(úAýJbùKµ1³Œ¿FîîªÝßÞZˆ¶½ñ ÑѾÜX|üÉ;¿«büž#m@ endstream endobj 78 0 obj <> stream xÚcd`aa`ddäsõqöuÑö vò54‰˜…ü±áTÿ¥ÃúC†á‡,ã9¦òÌ?ÄYd^ ‚Èçü ò±ˆTŒ‹„X9êZ:Ss J*‹SK Œõ Œœó *‹2Ó3J4’5 --ÍuŒ ,sS‹2“ó|K2RsK€œ…àüäÌÔ’J ›Œ’’+}ýòòr½ÄÜb½ü¢t;M…òÌ’ … ÔâÔ¢²Ô·ü¼¿ÄÜTˆóõ ”kiNjÐUŒö@¢‰‘‘eó¾Ÿs;7ÿèßÌø D2ÿ ÿ±Ytæôî‰Ýýó*{:åZº;:+«í<$Ê:žúÍÒÍñÛä·ÔoáßVòݺ›BæçU×tuD”Wvvv7qÔOnž.7©»·{ç%¦4^uø.ÐÍñÝî»Àw¹ïúòÝ/’V,ëé™8¡¿ŸãOØïç¢Qºw/äø®òý;Ów9¹oÝÇý¦6p,Ë]?'²;ˆã·ÊoößL¿åäºýO4Nãà+ŸÿÓqÛï¤é웹6s¯›ÀÃļr\,æóy8¿©¤ÿ endstream endobj 80 0 obj <> stream xÚ•WiT×¶®¶éªB¡Mh+‚IºÑ8 ¨¯Þ8¨áŠ8€6™EE¡{W£L N ‚e*8G1fÅa]ñún”¼¥‰&†û’]í!ï½ÓÍË[o½µòƒÓ«éS{çÛß·÷)cgÇ( uˆOà’WMð ð žìeûÏûA¤ø;Ñš«’ßfäwò»ƒd­Rf÷.Ã(|ß´­ÌPº2=oØVwº }èÄØ)|F6xyMèå5Å7iSVJ\LlšëøH7×É3fL÷pâå5Ãu^BtJ\dD¢k@DZltBDý²Ñ5()2.:-Ëuü±ii›fNš”™™91"!ubRJÌl7×̸´X×ÀèÔ蔌è(×I‰i®K"¢]POøðMJØ”žâ’Hq:z*æ1¾Ê™Å2&P1(zP³Ñ.EiP0ŒšÊŒbF3c˜±Ì8Æ™ÈLb&3Sofó>ãÃø2ó™ÌBfãÏ0K˜¥Ì2f9Ĭ`V2«˜f 3j¥ÂŽÎLgŽ)ܹРš>(Y©TîQöÚU©–«jÙl÷WÀýÄ/±w³7Ø<ðGC† ‡•öc¿o4¿ä` Sá‹ÎNøâñcX‹¦êˆz‡Ð•zÖXO‹0úâý›:RNdï?¾¿Æ¼G4s!ŸO9ÕÐpàÐáºÍ-¡ÚlЭ‹ÍÚQ3žvôŠY´lë«×7¥ñ+“›¿2 {×šÖømE>°˜¾8õèwÿÊMªÄ¼Ï5] €ú Äu¥9'á TìÚWRÆ_#+Ú¼Q1Q+É[ÄaMW×ÕÏ Jg»Iøâbz9ÝG/2ÍL“W ÄÇ&¼+6á‘k ô\£Ømn?~Öh#0€Ó¼¨¿NÇ4G¼º@µ[šOkûÃÉ=È#£Ä4«¿ð?|†Æi¢w¦ŽŽ.c3³€ÎÍÀþü1'ª|#þ4ÝôSú¯šOžºbj¯é†vhßR[+`-ï „!z§u"«$i‘#[_7˜¸ ÿ!À!Q¬ªjm;WR ü—–'2Òoµ¿n+mar*A„Cü,»ŽØÓ;lSÁý§þ†ãõ”ŒÖÍ…UÓ²xͳîß{T´®OüßgçÔrå±ß[akoÌϨ¦4®ÃoTqdækqô“úG—úrš{7ëQý£ÖdÊÚ‰üú¦ÌcÇšjZϯ<¶Z«éôƒÈ´Å´Í„ä[ä·›œN¶GÜÂít¡Ç $ü½ÔHüµ'pH{N&î^!f‹¯æé×ã´ŒeH®Œ-‰>ÐkìpDVoªÞÜ{2ÿÞV^ÓcÉ¿» –ñs'Aºv$$ßÙÞQPU[_ÍPÅÀ -3Ôì£w¥}Åæ®øsP |#N«ƒŽÌ–Ø£´ìQÇâKfURÀA´/þ—„sª½´ƒ%e¯˜[Ÿš´®×iñ}'!c1Hϙƭ?¾ˆáúÇFÌyªÏßÕiýo ³8ô+QI\ÀN8¥ÓtÊTiûä nFð*ŸÙEõ´øô¿lå\¤ÿ Õà6tݧ {û;ª¢V¾ªÄÐD[¾UYURú\$.Ö¸ÚTbN¢ƒ–«‚½Æ½; óÁXX8ÝÓÙ 9U«Ä&›ããÃÌè–[m.‹Ép2n³!Ö‚ ­µùœ¸»þ²±Úöò”eØ]B_ž@,-{† gDÞREéÙñSó‰¦Nã ºg>UR/Ñ[äËrJ¹XvJ«ŠK¯/q©ÆSJJ˜9ÆÇÜ Ûu`*Üa2ÑÉer&¬S]Ø ÆÉôÂf¶Ý'®s¸´odÚÚôµñ çƒËV0ŠyÅå»êª …?‘z8.)Ñ,­¿ª½—¯ù„Wçì‘—•cXMÅ–„–rÒ`d‡´–:8 {ÔÁQ;Ønzµƒ½è –5ÃþŒºå endstream endobj 82 0 obj <> stream xÚX Xg·ž°LFAâ(´þ3tQ[W\«Ö_ŵZ±¶*Z놊¬ IX#ȇEAÖ$È*H¡nUq©V .5*õÖ[í¢ØÚj«VûŸi?î}îƒWïòUïzYr#—ÿ‰Ÿc.o ܨ¿â[“;€Óï*-¡$./=SU2·~s!2gÝ ¶ïÚe\Ô¬Hß™Y•™— Æ=ꃂ (A€ÐÌyY› sÞM——IÀEl‰Š!2?yWʹfQ\Ò–dˆpO…Ð}ö½–¾9c„º'@P}=ÔÓðk2.¥WrND4h±„¸\q%~ÿ‚B†l>Ö{eL\êÖ´¨ˆàb‹¢Kê6¦ Ÿ­Y¯VûÕ¨ê…\Øž¹=‹st‘ÑG]lñF ߨ¬ öS…„l¬Ý\×T±gà&ÉÉô˜&5…&õ‚tƒ/† ¥ Éq)q~–ÅG¦ÇdhÓ!ŒS•¦ e°?÷P×>ÙS!Ê (1‡-ª€Ú=á#z²‡±7ºàÒoìÜmwëÃ!^L ÉHMz{rø:à<Çÿ‰CñíÛ¶‰çàÔªÂÉÙÑY1µÀ5€A/Zʯ3Én™±Ôl{NB¾Ë×"ÑØ®Ó°ÏV¸ŽÅwÐÇã¸ñ8”¸‹DÞ~„—t÷åhš¸Žôú8[‹EÔ˜pÉõ˜?7¯4+þ~`â•Vc’ÈÖoÏ«Ûäe` m„0‡èåŠvÔàù:ˆiØ Æ2á^×í˜u€k0݇Í^‹ßB«|OòÎ@¡½kɶÅjmGÉ‚,Ùc3¤GÛâ4¬æq ûR›1³_bÓÅêi}».¨GFZ¾Œ¥…±&zUÀÞP4"7$[“Ÿ¬ïæ‡['?Â!%:Q¹®aiÁjÊÛéS&ˆðÞáyß…sŠ{9Ô…i\+ÍènF·nn¸½„A‰‰Aâ ù³;'ѽ]·Lþ šèõßx/Q\7c¼…ôÔl-[\ÑM{¾È/¬Ç¼eË|æŸø—€¿ÔÊ)^¶ëw–8ßõðáíŸÑYpJ4H{M²R)¶Óö§†®gu>b€q*9»Å'rZÒZ÷ 6¥!µ$¡q¨äîÖðÂÎOiÂÚKvúC ¸WAä5vç¥IZm‹‡ðßy´Gµ½ÑŠÏ7:Yåâ,2x*¶×[ZšªóV·Óå,: mû%ö+êžtš µø3úüN|ìÕšçoYNP³N ©õ²3Òp[ì÷×(>egb‰†J¤Øè(s¶f'ã÷ÿ1×mÛÖÑF*¿ŠJJEØ‘º3-—s~EvZò´•& ç  ¡!âDr• €€€(’MKL8ÚôÐäzʼ¶ ½Í ­dSÇCŽf4WmìŠÅ¶nKÌæ0D~ué÷ä͵ƒ`†Ò³[(‚ê¼ÌFØ‘™©Ï*ÌÜyÀýÛ‰Y¢â™Fœ?†aÜœóó m#´l?²‡‹Ç…ü;rJí†(ÿèÕœ÷º½Ÿ‰Ðüc#Êá,Mhß1sÍŠXœ,¹ñ8¿~3¬êàóö\6´´­ë+Eó~߃ u”)²¿¢Çüöš¨ˆýVG†päc»VùÙ3'Ï}fƸa³çÏþgÀ£= ¿1ÉZÍÞf+mD_ ÉB lMOŠHÞ¹Ò ¸ 3¯üt´åøªá3H3ÊtT]ï6”Ô´¾«ÉôÈÀ±Äñ—AèŠâÞßJºz¹ÃÿO»üÿûïº}Bk7îuâj)—}!2†U4Õ¬+^KY*6œ(Hß»Cÿ¤aœ†UÕ5ÛÍ’/^=qꬮ¶Ý¿rñÊ…æÅK:Âxû™d§Ì¸›rl .æ eЈìû¿‘þÄaت4œ FJè#w+,AŠQ˜–©Y¾4!Œ6ïéÇb~ä2Ïñ…­gO]ªÎTyovôðºÐ)·Àüà¶-æJ,NVn§#쯠VHÍÛР//®>÷.ļ;uÕ8Ágˆ¼#, ”‘–Á=Æèn+²Sñu½¾Z³f™8:€ÏNoR7÷së5Úkj¢« »sveæn*OÚ \IyAMy䞥b<¬ÈX“P¶ ¸³¦Óž·¶$¨(’S&>&AJ(TåÅy­†¹Ïºûa¿§-?ÐulyÕ–í¾ÆÑÀÍfa $fÅB2ÄÆfè! r² svrè@ÎóC¦<$Bi^]¾¢8ZkC{¿fúÚ!Ú® –)¸„Vfæ-?8ExVFFr¸ð%¨Ö­é¡€Ç²…–t©hº×àlöá×MÇO†} ˆ )®²ìÑcÛY·›]Ñïá3<-Ò+|Ç1äõ…°'-¤O¡{ÔZ˜×YÅ#)Ý®Zc ÓhÂÂŒšêj£±Zp"‘&Úm©é£m8Àbü©d÷ÌøöYͱû¢ÁosÀ&¿ÊöPˆËŠÍÊ̦¹ÛÎU«K´jMtè´ß`?ú/ÐW關׉@Š@*‹öáQnßÐCŠì¡´X2 ·Ç§IoKÍíºÖUO]ºâ&ûí×´£:ßu:œïm5Â>¯¿z>ÖŽõ§B‘ï±¾Õƒ!ý»ª±Ääzò4:X>Š›(“ñéµ\°uø¹¿¶«¢w:]ÐÒ—1œ+W4·í?²¿¼0z¾@tòÈî²_nÓÿ¹%…JNdÇJX·%lCìÞ°Ò à7ƒA© ×pÏü쀪âÚuûñuP´þùÕò¿€SñùÿžËv0@ñMººð—f¬  ñǪGþN_ÕìF¾E\ˆâ×áhƒ6¿ÞGWø’ñ¼—÷õ{?]¼xõÚ…ùž#½§{‰NDeÂQ¦-éž7©Þ,á_hød°ÝK¦D׌P<¨I/ô{žŠÕÿS´Ö²â3ι­øUt²ýrö>ö2ÃK"*€3ê‹«ôq&ŠËáý¨% 8Å7{;Il¬X¼IZ&÷@fadÛ²©q½fÂ8SˆIñS¨s"²UÛBsæÀg\eÝž_…ï P™½93:+zO—ð3wë¾T]zÒȤå]õ$F=þYGu_sâ·[À‡Û¸1ÈSX ‹óU7RJSó7w‰Ð¡4Š3 ›ýO¦WÓœ©ûxOoÞÖQ¸Ë¦?ô2K ÆPz¨,óabôO¼Å>{c4Î:î4vØeÿÖ¯ol+C@P†6ZÈðþh«¸©p¢¢kжtƒ1ÿ®ã3ƒ P \Ï!J©öâ ¤8=9.x Ô× Xþbƒ%yì0sx« ˆÜûw6VsN©'ðºI¶[Úd+Í 1Ôö¡—µ8Õ,‘‘ëD†×í«ŸÛñ¬Õ²('÷ 髸—A9ä×Sãô2£­IV,ÅÛJ«,ö-Ê3¢D"g£Â;Ôc™ØÌ~LŽÛg°©•[Çí:Ÿ–[iÝâ5iIë‰Áe°Ëð¸}sçß4jˆ|ö¸jÅs¤-G»Ü÷Av^©©âNfa¶‘Ëd·-k$½r ¢K¡!»8ÇØÅuY³÷w¼‡ÿÅô´7—p{5){ •UáWb–œ\$ÍÚˆŒ4ˆv4B™ 9³Æ\ÐCwÆú¿„1Êâó¥™y8-Ÿ%QÛå¦Þf“££Ù±ÐÛ.*̱—dì÷_Ù[ò| endstream endobj 84 0 obj <> stream xÚ¥W Pgîf†žAm4&é&‰ºžˆ¢I<¢o"‚žxàpÌpÌÀÜ —(¼ÑAA˜„‘CE1xFC5êÄ{â‘d“h4jŒ«nmþÎþlíö0èŒkv«¶¶ª««þéîÿÿÞ÷¾÷½7$!$Iö [´d΂Ó‚-š`ûaüzœÅø}ž+ÿ:Á¿Aòoºð¬ˆï/~“ È^Âø{oÛýOÛý-áæ™Ñ‡“$­M/òóó÷õó;M™˜¦’ÇÈ4>C¥Ã|ÆL˜ðÞHŸ±~~|¢Tri„Â'8B#‹JˆÐ‹xŸ…J©ó"¢|º0ûvݧ)µš(•O°22J¥°º’L$ˆiäLbL.$#èx±J”*€ö zž„чèKô#âuâmb1˜ø1œð%FãˆñD 1˜NÌ f³ˆÙÂAD01!B‰ùÄBbF,&–C\’p>NdgÉä—×]²]ÚE£De¢ûâÅâ*×\S2ê3ÉdI•„§¥ô±\ÛnKÝöº=îYÜóïî“Ü÷ôrëUÛ럑÷<ékòsÞOÄ¿‡LLé~hÝ ë8|ʉ‚è¨V(ã<õ%Ñ ÔW„ncZãâ¢ã㢛›[ššY÷M¿kŒä)~¤ˆ_õ»;³m'è`+]›Z‘ƪ!/µ0ßüGà€ü (†ZSYÅÖ¡ª¤”öȱð`!YQ‹UÄ'¢S š7õÇbì:ÄAxÞS܉‘ë4±8뙂‘„_üåêÕ‹Ãñ <8÷ø@Àhá)ËS#‰ ¬"t¿ÁT@C›ùyë³ãgH¥3‹µE@§”®«cÛà€©ÖHwŽ+ÉH‚ظ¨àP UÑÍ-IÁ¥læXÈ“÷Ñ«èÂY&¿  2騨ɢ;T‹aÛn·¤j££!9‘ÅZêÓ#HüÓ®ÚÖ}W/Àcõz{â“&½+mέ0ÖW6²`ÊßZXRyèPý  ¿±®ÏÁŒ°i¬´Á‚–XÈk÷»(CŸ0ÏÍX:wAèx. ¦êeÇ@·Iº-Ø´i»N›@OïJ1%©5™rÿ ò¾}ï! ßnºvrëWÐ@ߘúvŽç,Ÿ•P“¶k—ÉXÏ‚aciáÖ– lúòáèµ(³×Fª’ÒÓŠÃ7F¥Ø(‚¬`žYxZ`ôêÑ~L^6A2­Ðgíg‘nP•¥„¸Ø.æfSåf¹DÈäBžY‹ô”Ú“o± J닳“iìßI1(=pÅ$6a¡qñ¢WÕ…¿¿ª8°<°ð^FÒÌËDè ÿg¦ 1× :—’Cn~AO<éH|…ÅÈŸÁ^T=’´ _ýZGmÒl_¡+x.×6+:z]ħ>טÖ¯ËkªW5„½±¿gãÙÈ¿‰ ן~x¸'r¹BH€¢¤|Üëí¢ ÇLøMPñ°žýÈÕÀ÷yÕØS¯ÚÛ€n…Úê.5k-ä7V´Ý*:Í#&ÓNõNÎÔ©M¦^¬”Býï ·Ð84n<Ž_ã°¸³áµ÷$ˆ:)”Óó±»mCi»È¿X‘·u¿ ±@TÏ o* R[mg²»ÅœÅbo‰ èTÐØŸÝ´ääl§'•‘(fHkîÔÆ9Vh U¾[ P)$})Õ i…cNòí "Oq;•¥àw}Etj1á´nwzx¾ÍÅ3ÈtF„Žño2ÙÒìµëãébjýîܦœ– ´b@îî+‡À‡Šš´ºM[ޱæÍU`úÖ‘ØyžT„„Ã0zê¥àGl\‡ŽuòhÚlËq¢Ày&$CêV:àH–¦Ä¤¯‚ @‡®miãàø“=ÈSGÛN>oA.ò鄘&ó_1]ALuXã¡N Rì‘Ù¦„i‡E¢>¨çø'XÌ…CDºLAã¾âÓ§yéô¬qcƒfNüö$k;à‚…¼bEñ÷E|4"S¦AËfCäi 2Ó#fýîÌK·O4ý†úq•P^¬c‘®X—·YÞ+Pß`46|=ÂqÀ<üº?öøu(êÞiz\Á9°ïéÂÎþv<’ÒVKk :½pï»ÃÁ†öÊ}ûèxHÿ˜½î0ûÕTòfÂVMüpfèÅÛ?Y.\;óÉ’°®(˜ó¨—¡›h»`œÑ|ÆXûô f°ÇÈÁ¸'öüëPÔ <|·Î#—ÙBŒêȦ÷ö¤<¤uç™êïÎø.ÃÁ•[?´Uê° wÁg‚ò ¼ ƒz8ÐàG¨k_êÙ͉¦ ÐÕõåÍg'@攉kFsËFHº¬Ëå#Ü1ÄÉ‚v;Ä5„òÀ©çÑÄ/OœG‹Ï“+ µ6Ÿ¡˜sL¾€/s† ‰œ²<ÃÆ°ôPVbhÈlÊkúõÚ[‘˜ÓëkÊ*6•ë¶$™òË®­®ªkÐ6-æ4°z}´BY%/ªmT@ ?Ñ;âªÔy¹I&妢Yƒ„‰Ãÿo!B—ìóÛ™;è<ìr$a–®iïèho?q¢}MXØš5K9žÎÜE$¼/±fȰÀƒí´6<¡ï¢éôs•†Ú23—žÀ†ÃÊô¨X}$yU´ÚÕNÝý]§£ê×ë{/W‡²XçT•Õ`Oέ§$ÊrcáO1fM­R©Ñ(•µ³¹¶ÖÌâìíèkÈw`§C;yxÝ º ¾ÜWº‹ßuòWo¡¡x;­o;üVøÝŽŠ³¢já<9Šgç¨Ç¸è:j¨0·z>. Þâ‡'‹¥Ø ¹v÷§óg/]>€ËÞM5P¸ncATõrH\pZ¦Ÿ’ƒÅmê²ü=ÉæÂgõneÃ2:^!ÁΩ)åtqC©²»ƒúÙh”oÝfþDv Œë~> ôø&u…t—ªdTEÄ–9¥ÐJ×7›ï±÷`³\§Ý¤lpŒ‚…6ŠŸ cøkWäZ›Ñù;ÿ·”}rÓ¤°“ÞwÛ÷8“zçªìÊ—ÎX÷&A›)EÅqE+¤ZaT€ŽºîÍ_ˆŽíz@4õÞ”uò)°»‰E5¯ZÖS£.$Ý`÷B[I{£>ÁU@_Õ Hô1R1ˆDƒ\ÛœŠ²§½¼ê`7Ûwæ}×:{Î|ñÄVÆm”`ƒ„.1ÆUJ9þ¯õ´ï£w ÑßaÚ5IýoÏlgH)œR~Ú6ôa)…S·H,nÖžww«{/ÖMœ¦tïÁ×ôû…mîì endstream endobj 86 0 obj <> stream xÚW TTW¶}eA½Å"Š/bÿä½jœ jPckhEqŒ8àZ2KA12 ÈPU§ŠIÆb* (Fgí˜|ýv›ÄŸ8´~cì$vYëßÂ!öZIþ_©Uë®õÖºçÞ}ö9gŸsE”“%‰\ü·¬Ø¶bítïu›¼ßó‚qþ¿LƒYÎÂPÂë"áa'Æ:½AQ¢¥£ÈJ º:Öÿ~Õ±N"˨ÏGSN"£JÊóôœ;ËÓsŽ·2&9.",\%›4U6ÛËkÁ ÙOO/Ùò¨¸ˆ y´l\%W‘…ÌO¢J–MY®RÅ,zóÍÄÄÄYò¨øYʸ°¥SgÈ#Tá²M!ñ!qûC‚e+•Ñ*ÙzyTˆÌy–cñVFÅ$¨Bâdë”Á!qÑéHj<5ƒšE­­¶‘òí¢äŒÂ)Î9™€Ž¢©‘”+5™šBöÌ$»fSoQó¨êÊ›ú3µ‚ZIùP«¨Õ”/µŽZOm 6RïR~Ôfj µ•ÚFùS;¨ Ã(åDÕˆ&ˆDi¢ÿ–*þ£8ÞérÅdç2Éë’nú-ú3ŽIa¾|¥søìášágG¤ŽøÉeË‘kFJß–š\]]ß{ÕOÐH…Ë`œíhÔWÍfÑã+hß1º%¬dSuäZÒ€ÁR4LòýWí\Î1Ççå( ƒ‰jLi°šjm›{OÆ.[dv^¢ø ÿPÃjNA÷jõ½}Õº~—‰vzµzyô74î+JßËãú_ß% £¥B©ð† -C”5#o³y 7ÙK±]ò𤘘˜Ú˜v®* ÊJ ½^Œr²xXµ~g V«Ñ@.“[”]\zó¯È…C»^û}†Rtoy†Â—@ð­baxýÉ;/ò@7´³ìÆu4ü“ØÎàçÇ›F½ÃˆÕD‰‘ÿY¶)ÞÕßÜÜØØÌIç€õÙQo›Éî¢6±ðõàöÉ{ŠÉuƒ:”RK‡jÕK9•BÒ“ÿ!ô½í„¡HÚ3¯¼“GÚ»ôòÈù¼ Õ(%óÕ‘Ó¸Ù¨PÒf(îãÐh š f¿*Ì16‰t°/ÁŽÒíÂD»hà‘àsW<¸lp1[ %\6h49YþËÜ#í›Î{@oÅ ñ<ˆ÷ ø-äÏW;lýÕ1á¥À”AI–ÑG /svÚW£†­Áó Üe¢¢…¾ŸŸʯ¥±Ï€t/¼±u¢ä{æ îøaY#žoH×çVS…&^:xìƒ"»Ãuâ·p‡½øþ‡új=c§£5Û!Sª$§Ò61’à æ`n6¾…?pGŸÐ†²ë\ƒ]¨ñƒ€?pll ŸRVÿeç¡·÷<ôÊTôRm¡ìO4’"g´×R—õ¸è`H& x<ÿ$ôXŽÂ)G®…´’È^œŽnºK_{ݵ‹…¨ŒUJÔix4öæ-É.mq/Øè΂ò{\‹]®ñ„ €u¿ŒIh’HÿµüÙ‰“ìBÇ ñ`à ÇêuÎO.¿~!ÿ2‹®ÁÅŸ õÏÆK$û!²“±êÉ%w¬.¬Ób`^ò"mréØ9‰¸uÎP©ï?aÔu¸5 NXy¡…Öë‘î'ª0½ «Æ•AaIA #Ü@r±Ã†.`ãï¢ ÄÂt™E²G·¿þfâmÌó¿8ÿ·9Π5è$;”†_KàadÁ‹xèi \B7.‰Q¢0Ÿ]\{ Ž3—Ï^ú’C,œž^鑟¤Ï-¦ŠM<ÚB×Á!G¦êtÙéÉ¥û¶¥Ôm;9“$ë+ <'ñðvßÎÂÜžÝ5¹h„òFR‰¶5B¯k …ŒÏŽežÜRÀ|ËAä¥3BQ:0ip0‘Ç[èD8X΃^_\^Q“™Þzúà Ÿeöƒ¤7¾}ÌÃÀþãñÍ{Ζù ;)D"q§¨ÓŽÊî¢R»£~¼ØŸhI"Np¶I*‘W]šµÐ¥Úš<}&Ä1„¥80ž VH:òÑ0èî&Ká)˜Æ6GHÁ¢/©+(5X¡ˆy]t%ör”+¾×…–׉Ðì§Â×"lb­IÖp.ÒóÔYZ­Cš-•ððQó'z †ü|(d sг3ç/Ã.k,ò®öZ«Õ!|¿Ï P›ÛQ˜¹é«vóèîOwÞG‹¯]µ¹íT£WÙBySX70æ‹ÆÏùóÊÍ´¶‡…Á‰*yÓ0mÇB[w·³`…|”b±ÖÖYºwêx«åDI0§Bæòûh7 µE»,wU¤wxÂ6b¼Æ\æÈ_Àás•6&ëvÚ²¨Ý»v·äà£ÿD3‹’CjsšI™Qh×hұ̷ÜZÑjt•%ЗUµõöW†n8o‘[ö6B$ìÊÙ”¹W±!¤1¾3Íz¨e²6³öÝ'•gIØG a_£±hÔ”ï° ï»Âãc·]è2§¨ôÇ%Ù;ø'÷m¤-íRÛPǽ&›¨íÚ}_,PÂìþ¼Ä4ˆfbë-SµýÇçâ1Óexf¿ŸŠ†#¾,)Wƒ†ShsRT+ýbýYãuMAžŸ÷]à+ଶ3î™sváµ!çÈ æ+n­Â8äÂB2hìW$ÁjŒíŠíÖ¾-ÐWtÆr´¾å˜ý tÁÑýÖòTÐA“ÿ›[xæmR'®²©˜Å£¾õ@#øÿ‚žîñm ¦—9ÛiŸ¬â~^øþeG¥Bq2¼-5‹šn!ÍÇba"Jfë ÁôO¿x v™9¿ŠÇþ0™è©´ÿqCqnQŸ šl]^Ĥ9Ú°öZUmûúu ‹Ñ7²%hÖÝ*œƒ r=ÃHѳ©Ã`!ç+÷ÿ.Fg„‰¬@Îô½þžn®””Ri^f^j)¦ØÚd³µ¦Ör8¤uóÛ^'s˜þ·1㌡Bêh£Î!™‰ô;‡]sLx¯­½ø¹e[EMçÑëmçÅhòaÍ©ö½À<¸úñg<ô+ÛÒ+vôA9ä’FÉŒº8©¡²ªÔT›fâ¢!PS\)f†·Ïü›ÃªhµÊp€ˆª0k²jP(ìbþüÍ&4¹þpæ:Ç’Ž‡6úµ¿ 3 ‘äàACtQ’•Ä«ªÐXRÁ<ÊcçÀ?êy°ÚªuV£ ˜»0M¥‚i³ù^¼”mA®ºE›–Μº¼ï\UéG·ø§³ÚPjˆÓ5zMŒÖ ú²/§hÕËCÕ‰º3?^¾ô=}ñýŠ8œú‹ûü!tvm¦á hR¶«l!ÛaìWø1:‰c¦!aëB.ˆý¢–_q»Ö ëY<ÑàRIΛžŸÜc0éWuÁÐXç›Wx„wû._8Ì6Ç7F)TqÑÑ qö§£ãØAQ—#Ähíoyôïc¢tðáP¥™G;øsüÝúÑzTÎ"êÓ“ÎÕ¯ø5WŸSòn|‰“Û`Û×¹¿1¨<¼a‡\¹5ãý Ž°vlÛÀ¸ÝÐýC‚'½@Žë~ýâçc÷3ä¡×Üz†`ÿ¾Í‚=+Ó”$@n×Òÿo¥j›0m¨À;n‰…$Á¢±¾Ç®ØÍCFj|Ô÷S+rûî;äÊáDìÏn¹Yu$¶Kwz¡ÌÇšO4v¹?YÑ ×ûƒBáݸÝÊ€€DR+ÄI¼ÕŽf˜…×ì)¶Ñ¯¡ú[DSW£¿³mï«ëæÓ ³1…%>sñD˜-ñíéu` Âìãd‰mÛ÷ÑϺS«+E9{ø'á¿å¥Çsž_y|‡°¼’Ù±24I8­Õ}‰gbL) ¦csKTs ·ärÕº!2‰(Žÿ2An¤ÂTµYð¬µBé§Äè¡°èé€ ZHÏÐj³²rrõŠ¢"ÇîûÞñç!²2¶!¡Mq8ûTÖ©ÌjM}JéAs„0s= ›±73ÎjJuEC3K2ÇÐ)UΑ™¥¦¶ ¨¬¢°°ko¯ÆLHrí¾z™‡žDkBCDkXñòÊØÂw*`€iièºÇ! ŠâôS14SÕ´HìÝìhaèÇkè61útH~'¡µJZ· |â4 w7ÑØé†êÌåöKW¸åz¹",lÜ©áP3ý¼S9w½È`A†³s¶¯ñ^˜Û}–C_Òxºƒ½ë ™Ããi4ø‚¼7¼)ñXöQ8 ý M·$ýB šò¢ !ôÌæY:¢6 °‹ê­­BˆÕi‹ ˜±t@-yìѪt»Ã£!ÌñRè#Ýߊ<0r/J=¤)8d(®F¯£î¦Síå펷E”&´J…^é°hÒV€XÈÔióÔp!™öSž]7ø®xpºÍÖp¬Àä° Òha_H9ìºu•1DÒ3µ9šì7q¾»²’wM>䳨 ‚+@³RÑéØÝuº²´uEh@›«NpŸ*rŒ$Õ ÆY ù@| Ú ›P¡-@,þѽ0#?ÓF((+(}„ZÝÿ‰[ 2 ÔFg„üÒ‚RRdG°Ü\õ¥ "Ào’*ú‘Í©„B00–60‘£whurÍ&vݵÚò4ç í·1ak´/Œ‹ƒ” áÞvÚKR•*.95&°+ô4÷è~¯ñZ-,v/³Ô»d \DjþœÃ^-„‘‡°štêƒ8Ë]šP/xW£è²¢z Þ[NÛ‡_a.rq¹Vå2’î´ Îåô`Ìÿmƒ’Æ endstream endobj 88 0 obj <> stream xÚ%MLӆۭΊsþ1~"t%HÆÄD2üIt‚A(8¢`u…±FÇÜ€ ð!ƒc.CH`1°`<E êAbBÄ‹zá&ŒMkzÐ /Oò~‡7Ïû¡†!(Šî+*»QTr帮øz‘6v8ˈ)XëŸÎ]ÂDHA…T‰@H…DŒØ¼Œý•KRù}0Æûcü~ Æ´($ƒ‡ Eq«£W£9©ÖhrulƒÝRk`82³:‹<¡Õæe“¹–iQéjƒ^èÆí¾Žqb<±Ï”ïõ€o(ì_œqÍ.‡BããáðÀ‡ëŒ*¸vGŒsTÞ¯ëí‚f\¿È.m/ðFà"Ú ¯§«¹ÃÀæëàìŸQAht~(è±ÄKaÿX) tPQÕhì|y÷ u`±Ù馭\¸Ó ƒÄ8€Û|Z˜|b¤³^Í]}.\!<þ¯ÎK7øÉ ©àçg•Û¥ŸrÄÃb¢˜&S¿½°Å'ðñ|:ŸFˆ^ѧdªBßT üЬ…W_Í?üùSÃ%0÷DYe¡ñæ-#¸‚ߊö&ÌñºÊË?Hy¿pT¹)›ô‚¬ZT§eÑyn<wò¤ÓÛB4@»Õå¨5I§dŽv°;G`BõEvQŒ@_·Z“+çn¿û¹Â§xÐC8c?ic (}à펇 =\a :/ÏõOe"åÝ=·¾wzP.'â°¼€| ÿ*T endstream endobj 16 0 obj <> stream xÚµZ[o7}ï¯à[–x¿E€øîÔ·ÚNì$̓j«‰€$6l¹È÷ï¿3ä®–»K)›¤‚ ].Éž99+ Ã8“– ˜LYÜ 3Â1å™5†iÁµ±À5Cu°ŽIÇWœi…{PLI&„!i&¤ÐLÜcJ£ÚUð 7jÑ|`Ú0a%Z¡sËt`R ËŒdRãÙh&}‹$îž)³œ)­³PQo SΣí>8æÐ ïÐÉ @ÁÈ*Î\ »gÑR9æ pÃ<ŒuÐë3 ¤ÀcœÅ ÌÐH €Á$²€RÖÀ¬ÕÌZA¤1KˆaœõÈhR=æÉÏ0FMŠ9Ë=…Îɸ{<@¥çÒ3»ð ›sæ%´€U¯Cp³œ`w§hÚ$ó^c* ó@ó0Gw¨‡NAs|ž£Â Jà6 †I4>šá*ŠŒÓUpª6˜ÎßïÞ~™Ó „ÃÛÎÆ»’™T?© ë&*cHŒИ ¤1•QK¨ÖTDŠÏŸOïo¯Ï§ówãÓíÝñÅôë||ðyòaº•n›évðþùó_2x‹¡ #æãHš€.ŽzpMH*jšŠT44 ©h‰þ¶Ùp–ºäi.R1Ð,ü„E™®…q™MµúÌâÌN —¾gŒá§0­´´ ´0<Š’Üí¿˜ïlô ÓÂkÄk'£¼1¹™’·UоÐÙôáöñþzú€]üïn:>E\î§_æ©©~ ÈñøðND¸=qi—ˆ«¶¸4Eq%†‰+ž‰/z? Ã#zËè?f7©¦ª8ð@³UÙlå—ˆëŽxyt-†‰ëï7[Å ¡w…¤­úÆ®‰kÚºãS2x|4½™M6o¿¾#–ö¡ +u[÷ÓÉüöþ »˜^±ÛÇùÝ#°p¡F\„ýMhÁŸ’;Þ<^OïŸÜü;»»ùçóWö×tâ\Iÿ×Ó§IÉìöËöd>}²ýÉs-, óðŒ«_9ÿõi/"¯Œ¶lMæ“O·ÐüÎFÏú¹r889JšŒ¥Ò²kYƒ×!¶ù¨Å£'‘ê¸Å]6>é¹¼ç#œ œÑži݈öã0¢YsÖ'%* – s^ŽôRØF[(¡~Û}¼c‰0D‚Kµµi&P}z ÊU­M?@4d†Žòºéå|K /„4ïy§=Áϯ«¸vj™A8±äÀkÆ1pX­L”LµT#=ãÐQA½2*ÎòR©l¢ÛÇù‚EFè•VÔíÝûÏ}ºZÊÏùµÝ+–½''0ÆP¿xõJE¬ôðoàX´;çÀŒWå=œ-];-Q{*'éeßô‘™l­©ÎäÜC›“sã¬"Ç Yœí刻zäb?eÅHTróœj“¶$m‰öWÚLneŸPÉ‚¦.Éi­±üò²â‘ÕEŠT+»ãÕ,z§È\F”€D}‘ϼ5aMåt­Pp:€óÅÑD[9xÁô§Óµ ‚¦™ˆo}œNå„©ˆNÓSî… §r¿„¸‘*/šXÜŽ¾Í“â4Éi,ÕÏ2¹¸pUÌ“•L´RÕÉJ¤QÔ¦HŠô¥0bâ’i»äŠ¥aôèG·›,ühÒ¢2æ\–óÖ\æî´mDÖKÛÚ ŒädÝk |ž1hK´‘9*Î1‹@í Û¹a~âZ |¨Tùc­]àXU÷sºûóÀ½£0 ëøH„ɪ`ˆ1EŒ(„j§[€®¯´ëäÎÁªz¢pWq?P" „ímêéEQï«â¨ª\XcÕî)x h!òä|jðéT¡håyz÷²UªžõÊ¥À'‘>G+®ŸJÁPL©¤\=½B"ˆÚÄ«¦EݲxÐßøúbvÿ0ßú8¹gBŽ'‹²oN¦Qü`gëíÞ³­£Í+ô¡ªíéÃõýì(½‘/?Z#6íÈïö§³‘ñz;~ñpMÙ² zL}¨¼!ðp€drvýâˇOSÆÇçóéç×ÔÆ»Ÿ&è ‡†GÍ›”oÅ6¤HFþ>¶íÎ>MÉ.TO>OÛè;8—0ã:ÌhŸ1#BÃÌËÝÃÃý}è>ëøpbÔwcMÅ‹Í(AN) Þ÷ñmFrÔà ]BlNˆkùótoûì ª/. ŒˆÁŒ±`Å#RÊáŒô+X Õä„Þ&¤…z5#·¯¾Ì®oo¦X²QIE‘‘ÝÕ$òÕ”Q´ÿæêÏÓÃÈ>ï1$׿3¡Àæä31©é-#£Úå°9Ñ+ã‹hÙÛÞ»Ü>"ú ”¨ÿš’ $é\×¼øŠ—Çe*b{Ę61-ôرfL_$o˜9|qy¼w ÝG%fôZ™q²ÈŒ¬]F÷âŒqmfZè‡1ã»F5ÌÙ³s|rrö’¼Ñ÷h1ëZCΖ⮭ q¼GHh’¡D‡å:œÎãnæ([§'§[{‘ê>!v½~R\AR×+Hôh±¢MK~/Ý`Ë3Z¸ÍbíÑîÛcZ›ço ëÇý/|Á _N‰æEJÛ6R‚<εv$Û¶9ð¡;’ÕùŽdÍr’Læ:oÎ/°ïÅ¡ú®ã×F‘-FlH~ÕÞ€¢Ð¢¨s®ËqfȵêFŸÅa”Ÿ\žìÑP;W7|æßb¨4ÚM\QÑ´¡ÿOÈ9HÓB<7e0492b2c59c3990526f6040dd441244>]/Size 110/W[1 2 2]/Filter/FlateDecode/Length 289>> stream xÚ-ÎÉ.CaÅñïÔÔkj¹fWѪ±Æª™jÖU%6â¬l ‘Ø#"Äð öxIcaã)Ô=9wóËÿÜáËgŒÉå|&h‚$@ I”t.ÒCzI?$q’ £0cXÙmU'“dš$ÉY ‹°²úÄO–É*ì½ð‘b²'¬gy¤K3Ÿ”"æhrb‘2R¸÷o%R•ô·{ÝLZ³ ›Gªjì«jpUÕâd_U‡ÓOU=ίÜ.5pùâÎëÍFÜÚ*w~UîÏT!<ܸ?zÇ7ãÉ»U žwU­xýS…ñ–PEðñ®jÃ×–ªt’n#}d€ ‘a2BÆÈ™"3d–Ì“Y"+dlà7dÌ?(œ/M endstream endobj startxref 59422 %%EOF glpk-4.52.1/doc/cnfsat.tex0000644000062000006210000003311412175147600014470 0ustar maomkpasswd%* cnfsat.tex *% \documentclass[11pt,draft]{article} \usepackage{amssymb} \usepackage{indentfirst} \setlength{\textwidth}{6.5in} \setlength{\textheight}{8.5in} \setlength{\oddsidemargin}{0in} \setlength{\topmargin}{0in} \setlength{\headheight}{0in} \setlength{\headsep}{0in} \setlength{\footskip}{0.5in} \setlength{\parindent}{16pt} \setlength{\parskip}{5pt} \setlength{\topsep}{0pt} \setlength{\partopsep}{0pt} \setlength{\itemsep}{\parskip} \setlength{\parsep}{0pt} \setlength{\leftmargini}{\parindent} \renewcommand{\labelitemi}{---} \def\para#1{\noindent{\bf#1}} \def\synopsis{\para{Synopsis}} \def\description{\para{Description}} \def\returns{\para{Returns}} \newenvironment{retlist} { \def\arraystretch{1.5} \noindent \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} } {\end{tabular}} \begin{document} \title{\bf CNF Satisfiability Problem} \author{Andrew Makhorin {\tt}} \date{August 2011} \maketitle \section{Introduction} The {\it Satisfiability Problem (SAT)} is a classic combinatorial problem. Given a Boolean formula of $n$ variables $$f(x_1,x_2,\dots,x_n),\eqno(1.1)$$ this problem is to find such values of the variables, on which the formula takes on the value {\it true}. The {\it CNF Satisfiability Problem (CNF-SAT)} is a version of the Satisfiability Problem, where the Boolean formula (1.1) is specified in the {\it Conjunctive Normal Form (CNF)}, that means that it is a conjunction of {\it clauses}, where a clause is a disjunction of {\it literals}, and a literal is a variable or its negation. For example: $$(x_1\vee x_2)\;\&\;(\neg x_2\vee x_3\vee\neg x_4)\;\&\;(\neg x_1\vee x_4).\eqno(1.2)$$ Here $x_1$, $x_2$, $x_3$, $x_4$ are Boolean variables to be assigned, $\neg$ means negation (logical {\it not}), $\vee$ means disjunction (logical {\it or}), and $\&$ means conjunction (logical {\it and}). One may note that the formula (1.2) is {\it satisfiable}, because on $x_1$ = {\it true}, $x_2$ = {\it false}, $x_3$ = {\it false}, and $x_4$ = {\it true} it takes on the value {\it true}. If a formula is not satisfiable, it is called {\it unsatisfiable}, that means that it takes on the value {\it false} on any values of its variables. Any CNF-SAT problem can be easily translated to a 0-1 programming problem as follows.\linebreak A Boolean variable $x$ can be modeled by a binary variable in a natural way: $x=1$ means that $x$ takes on the value {\it true}, and $x=0$ means that $x$ takes on the value {\it false}. Then, if a literal is a negated variable, i.e. $t=\neg x$, it can be expressed as $t=1-x$. Since a formula in CNF is a conjunction of clauses, to provide its satisfiability we should require all its clauses to take on the value {\it true}. A particular clause is a disjunction of literals: $$t\vee t'\vee t''\dots ,\eqno(1.3)$$ so it takes on the value {\it true} iff at least one of its literals takes on the value {\it true}, that can be expressed as the following inequality constraint: $$t+t'+t''+\dots\geq 1.\eqno(1.4)$$ Note that no objective function is used in this case, because only a feasible solution needs to be found. For example, the formula (1.2) can be translated to the following constraints: $$\begin{array}{c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c} x_1&+&x_2&&&&&\geq&1\\ &&(1-x_2)&+&x_3&+&(1-x_4)&\geq&1\\ (1-x_1)&&&&&+&x_4&\geq&1\\ \end{array}$$ $$x_1, x_2, x_3, x_4\in\{0,1\}$$ Carrying out all constant terms to the right-hand side gives corresponding 0-1 programming problem in the standard format: $$\begin{array}{r@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }c@{\ }r} x_1&+&x_2&&&&&\geq&1\\ &-&x_2&+&x_3&-&x_4&\geq&-1\\ -x_1&&&&&+&x_4&\geq&0\\ \end{array}$$ $$x_1, x_2, x_3, x_4\in\{0,1\}$$ In general case translation of a CNF-SAT problem results in the following 0-1 programming problem: $$\sum_{j\in J^+_i}x_j-\sum_{j\in J^-_i}x_j\geq 1-|J^-_i|, \ \ \ i=1,\dots,m\eqno(1.5)$$ $$x_j\in\{0,1\},\ \ \ j=1,\dots,n\eqno(1.6)$$ where $n$ is the number of variables, $m$ is the number of clauses (inequality constraints),\linebreak $J^+_i\subseteq\{1,\dots,n\}$ is a subset of variables, whose literals in $i$-th clause do not have negation, and $J^-_i\subseteq\{1,\dots,n\}$ is a subset of variables, whose literals in $i$-th clause are negations of that variables. It is assumed that $J^+_i\cap J^-_i=\varnothing$ for all $i$. \section{GLPK API Routines} \subsection{glp\_read\_cnfsat --- read CNF-SAT problem data in DIMACS format} \synopsis \begin{verbatim} int glp_read_cnfsat(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_read_cnfsat| reads the CNF-SAT problem data from a text file in DIMACS format and automatically translates the data to corresponding 0-1 programming problem instance (1.5)--(1.6). The parameter \verb|P| specifies the problem object, to which the 0-1 programming problem instance should be stored. Note that before reading data the current content of the problem object is completely erased with the routine \verb|glp_erase_prob|. The character string \verb|fname| specifies the name of a text file to be read in. (If the file name ends with the suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine decompresses it ``on the fly''.) \newpage \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \para{DIMACS CNF-SAT problem format}\footnote{This material is based on the paper ``Satisfiability Suggested Format'', which is publicly available at {\tt http://dimacs.rutgers.edu/}.} The DIMACS input file is a plain ASCII text file. It contains lines of several types described below. A line is terminated with an end-of-line character. Fields in each line are separated by at least one blank space. \para{Comment lines.} Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character \verb|c|. \begin{verbatim} c This is a comment line \end{verbatim} \para{Problem line.} There is one problem line per data file. The problem line must appear before any clause lines. It has the following format: \begin{verbatim} p cnf VARIABLES CLAUSES \end{verbatim} \noindent The lower-case character \verb|p| signifies that this is a problem line. The three character problem designator \verb|cnf| identifies the file as containing specification information for the CNF-SAT problem. The \verb|VARIABLES| field contains an integer value specifying $n$, the number of variables in the instance. The \verb|CLAUSES| field contains an integer value specifying $m$, the number of clauses in the instance. \para{Clauses.} The clauses appear immediately after the problem line. The variables are assumed to be numbered from 1 up to $n$. It is not necessary that every variable appears in the instance. Each clause is represented by a sequence of numbers separated by either a space, tab, or new-line character. The non-negated version of a variable $j$ is represented by $j$; the negated version is represented by $-j$. Each clause is terminated by the value 0. Unlike many formats that represent the end of a clause by a new-line character, this format allows clauses to be on multiple lines. \para{Example.} Below here is an example of the data file in DIMACS format corresponding to the CNF-SAT problem (1.2). \begin{footnotesize} \begin{verbatim} c sample.cnf c c This is an example of the CNF-SAT problem data c in DIMACS format. c p cnf 4 3 1 2 0 -4 3 -2 0 -1 4 0 c c eof \end{verbatim} \end{footnotesize} \newpage \subsection{glp\_check\_cnfsat --- check for CNF-SAT problem instance} \synopsis \begin{verbatim} int glp_check_cnfsat(glp\_prob *P); \end{verbatim} \description The routine \verb|glp_check_cnfsat| checks if the specified problem object \verb|P| contains a 0-1 programming problem instance in the format (1.5)--(1.6) and therefore encodes a CNF-SAT problem instance. \returns If the specified problem object has the format (1.5)--(1.6), the routine returns zero, otherwise non-zero. \subsection{glp\_write\_cnfsat --- write CNF-SAT problem data in DIMACS format} \synopsis \begin{verbatim} int glp_write_cnfsat(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_write_cnfsat| automatically translates the specified 0-1 programming problem instance (1.5)--(1.6) to a CNF-SAT problem instance and writes the problem data to a text file in DIMACS format. The parameter \verb|P| is the problem object, which should specify a 0-1 programming problem instance in the format (1.5)--(1.6). The character string \verb|fname| specifies a name of the output text file to be written. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine performs automatic compression on writing that file.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \subsection{glp\_minisat1 --- solve CNF-SAT problem instance with MiniSat solver} \synopsis \begin{verbatim} int glp_minisat1(glp_prob *P); \end{verbatim} \description The routine \verb|glp_minisat1| is a driver to MiniSat, a CNF-SAT solver developed by Niklas E\'en and Niklas S\"orensson, Chalmers University of Technology, Sweden.\footnote{The MiniSat software module is {\it not} part of GLPK, but is used with GLPK and included in the distribution.} \newpage It is assumed that the specified problem object \verb|P| contains a 0-1 programming problem instance in the format (1.5)--(1.6) and therefore encodes a CNF-SAT problem instance. If the problem instance has been successfully solved to the end, the routine \verb|glp_minisat1| returns 0. In this case the routine \verb|glp_mip_status| can be used to determine the solution status: \begin{itemize} \item {\tt GLP\_OPT} means that the solver found an integer feasible solution and therefore the corresponding CNF-SAT instance is satisfiable; \item {\tt GLP\_NOFEAS} means that no integer feasible solution exists and therefore the corresponding CNF-SAT instance is unsatisfiable. \end{itemize} If an integer feasible solution was found, corresponding values of binary variables can be retrieved with the routine \verb|glp_mip_col_val|. \returns \begin{retlist} 0 & The MIP problem instance has been successfully solved. (This code does {\it not} necessarily mean that the solver has found feasible solution. It only means that the solution process was successful.)\\ {\tt GLP\_EDATA} & The specified problem object contains a MIP instance which does {\it not} have the format (1.5)--(1.6).\\ {\tt GLP\_EFAIL} & The solution process was unsuccessful because of the solver failure.\\ \end{retlist} \subsection{glp\_intfeas1 --- solve integer feasibility problem} \synopsis \begin{verbatim} int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound); \end{verbatim} \description The routine \verb|glp_intfeas1| is a tentative implementation of an integer feasibility solver based on a CNF-SAT solver (currently it is MiniSat; see Subsection 2.4). If the parameter \verb|use_bound| is zero, the routine searches for {\it any} integer feasibile solution to the specified integer programming problem. Note that in this case the objective function is ignored. If the parameter \verb|use_bound| is non-zero, the routine searches for an integer feasible solution, which provides a value of the objective function not worse than \verb|obj_bound|. In other word, the parameter \verb|obj_bound| specifies an upper (in case of minimization) or lower (in case of maximization) bound to the objective function. If the specified problem has been successfully solved to the end, the routine \verb|glp_intfeas1| returns 0. In this case the routine \verb|glp_mip_status| can be used to determine the solution status: \begin{itemize} \item {\tt GLP\_FEAS} means that the solver found an integer feasible solution; \item {\tt GLP\_NOFEAS} means that the problem has no integer feasible solution (if {\tt use\_bound} is zero) or it has no integer feasible solution, which is not worse than {\tt obj\_bound} (if {\tt use\_bound} is non-zero). \end{itemize} \newpage If an integer feasible solution was found, corresponding values of variables (columns) can be retrieved with the routine \verb|glp_mip_col_val|. \para{Usage Notes} The integer programming problem specified by the parameter \verb|P| should satisfy to the following requirements: \begin{enumerate} \item All variables (columns) should be either binary ({\tt GLP\_BV}) or fixed at integer values ({\tt GLP\_FX}). \item All constraint and objective coefficients should be integer numbers in the range\linebreak $[-2^{31},\ +2^{31}-1]$. \end{enumerate} Though there are no special requirements to the constraints, currently the routine \verb|glp_intfeas1| is efficient mainly for problems, where most constraints (rows) fall into the following three classes: \begin{enumerate} \item Covering inequalities $$\sum_{j}t_j\geq 1,$$ where $t_j=x_j$ or $t_j=1-x_j$, $x_j$ is a binary variable. \item Packing inequalities $$\sum_{j}t_j\leq 1.$$ \item Partitioning equalities (SOS1 constraints) $$\sum_{j}t_j=1.$$ \end{enumerate} \returns \begin{retlist} 0 & The problem has been successfully solved. (This code does {\it not} necessarily mean that the solver has found an integer feasible solution. It only means that the solution process was successful.) \\ {\tt GLP\_EDATA} & The specified problem object does not satisfy to the requirements listed in Paragraph `Usage Notes'. \\ {\tt GLP\_ERANGE} & An integer overflow occured on translating the specified problem to a CNF-SAT problem. \\ {\tt GLP\_EFAIL} & The solution process was unsuccessful because of the solver failure. \\ \end{retlist} \end{document} glpk-4.52.1/doc/glpk.pdf0000666000062000006210000164561012175147600014137 0ustar maomkpasswd%PDF-1.5 %äðíø 7 0 obj <> stream xÚMÍNÃ0„ï<Åm‰,ÞõO’#Z©-¨T† å§ŠÔ8ÂÐoëp@»‡ÝÑÌ7ð *AÍyF¸óp³ `…Îið=4 * é¹ÿñ&–O/²ÒΉÍC'µiþ·i:¦n‡x¼µXßòݯ2‘jd²…ÈØBeklmáíBRˆ‡C¤ÅcÏÝ©ä*rhLö´ºxûI²+}Ù¹Ül×óõ*ÙŠ¾†)ÎBð_µ2¨»TSƒŽþóöâ~w»ð×9•¹«óég¾X‘ÞËBxðð|õ §mHº endstream endobj 13 0 obj <> stream xÚVM“â6½çWø(ªÀ+YþâÈ&™Ô$™Ô$Ëž’4¶cYÌÖþûíVËØ,s˜‚*äׯ¥þx-“üŸˆ„ÃG$U_ž4§äã6ùð'‚§k¾N¶;0¯rY§¼H¶íßl{Ћ•”’ýòûóo´:«f‘Uì¸( ¦öÁœ13ŒFçq•3»#Ä_wøã3Yž]¬Àù?ÝD®ÓVƒn‰xé[ínœs¦ô~<³´W2åy²)ÿpQDÖ¼8"Oe "%ãœ/!±Æ¥ÀeÆq™M¨œÐ|Z¡œÐjBë ]_QÁ¯¨˜Ní%Ûô­Ó_BÈ«²HsE‘iA]|Rǃu¦G¯ª`?ilÓI÷X)lAY²Å’—ÛœÏ ­(köØ~RÞ4Cô}²CcÑï ùm^ ˜mOÎýà¿xØåŒÝÿº ƒQ)ô?/Ø¦ë® ¼ÆJƒ¸R–Óƒv¯ˆèö~?,j œ(ÃOvçY ÁAë•‹(p2fAV!Ò%}“.I\… EžSý±3}ÜÏ/£ÉìüØÈ±.º´ƒÛJö´¡_ž Á!-°>Ú¼þsHÌ ”‹˜U"ÌRVel¡„J`7Ðà-NêÜU}KpkïÌ TŸž_±Ú½@Ö'¢6öltÜÇýa<ïDÇ]TGì³ ­{5í5€Cܺ¹™²*NÙM{ ª‰£B¤y¦)ÎÙ9Ôp–9‚7>..Σ ™–ÚB|à€€‚#%öŽúJ^Ò]Å«Ûú¢닆]ɾJÁ<¯/>Ÿ°5ÀpYä:’H©OÈ?ÜW¼sGÇY¡‘1^x`¢ /ÄзƇ]îJK³*ùxXì0"ccL¿ºû¾‹ÈQÝ`iåÊ+^´‚ÅKÁPõ9Žß¥ó°=B fjE¶ÆIÃQ8’™º+f¥j ¸Þé<u—’‡}w¿«w ‹17¡  ÐH rƒM{ýuäÐNôÈ!Ìu 7Íg%FtMêÀÅ\Hóà?tŠZ˜X°„¨™ Ÿ hé@Y°jèÔ©~×íò¾v÷ïK(ÞKÐ&µ/ÈÏdž£”äb0Þ AÌT¾Ÿ·÷ÿ2)Ò¬‚×N^Ó‹qdþùÃ7)n:Ó endstream endobj 50 0 obj <> stream xÚí[[sÛ6~ß_ÁGêÁXâ<6n';Ù™´ë}Úì-Ñ6·éRr“îôÇ nG–BÀžNšd5ñD‚|ð ßw.éêç Wù‡+IÌOS­wÕ«ëê¯aH*Y]ßš__é Q]oþ];‡n8ìWÿ¹þ»±“nn´· Q<ÛáÕ•&¼~=¬(®Ó¸º2¯›Çõ¡‡yîw×Þóßû7Óó 1çˆñê s†´tÈMšo§úY ÌÂQa& …8q“¹ ÜR¿yk.…Òúao¶ÝnuÅ•¨‘yišËËéË2Uìˆ*‰Ì»£U/§JÔx~ñTýãõS®$ÆZþ’Àzãb’4G"Äõ$ýkßwަÃ}gß°ú¡]¯ˆ¬ZqQ·wæC-ñ…¢çRV;OÃsž$F8Ä“f¬~5õÝ­ã¦ûÐfºQH\×r2AG2ˆ'ãÛq÷Ðoç¨aXþ¿g0¦õˋˊ¡¡ž‘7ýðÓ̇"Ÿô[Vø<-OZF"$]š#®g|ÕîûµIVŠÖß¼}íÞü8>ú¡Û¿ u°(-uD2D\¼“Ø:~ß ÝÔn]±[›>–ˆú—Qu7Øÿmk»7’ê’W‹å’Ö¹€œÅJ"E9±È½éo¦vúÕ•¹û®Ýt“é9¿Ð§!­h9 ´194ÆH,oßMÓ8yÚaã 41|©i9ÀŠ>ƒl¶Æ)BM»¾ŸL8öímw°¹ Fù¥É(&$­í3! ±ÌòÍ4µ¶bÌ ŠÔý°é>̱!”¾4y*ÒªbYZÆ)3ÛÜáXám8M°e|¼1—$êÿvëƒa‚¨¯rµ?!KiÁ X c:5†Äzx2)¬»ÛÙ6KÖ†'&Å¥š/Öó$³Ã¡«¹mÆ÷g( D_ºÜbBÒÚbULˆ"H¤¨uýõ¼í8tS?NW+³½©ÇÞ}æ ËMü+MP/à -'ÖÅh³›Å‘ƒPÊýÁô“L\B¢˜Ž´²tørΤðtÐså|mšÞƒ?fµÙ~¸w£ UoúÛ_ãiõŽ LÿÎU† Ö”Šžîâp†|·}?WˆjU½¯4F\¸W»J3¤Xo«V?œºFÞÍÌZw‚Ž C ð˜HDTZyö’cý7 “îÉÝ%+™¹ä¾$Bùl–K€ ¤b Åf`If†@nœ‘@r³7Ôþ…”Ø›îPäÀ¡•GŸù?§Ì¢x*‘¦Yx`åá‡v×y™Ä³ß÷wƒûè]=ß »o‡»îÝÊÕè#ɹÙBòÏN:@åÒá b){Ðé˜f7ÎH'¹Y”NÀŽ¢X‡V=$„3ÙIÙ£Kà‚šï“½~hå]<‘=•8–Ø´ö¿XquîóÛÇÁ=`1Ït°êÜ^©xßúÑþËE#(Ò)ß°јæ7Έ&¹YMÀŽrX‡V=/šè"ÈaÙ°ò.6ýt¤û…>.˜‡C¿ëÿ×&q˜é]Ô «ß5˜·öœV°?3áßeeR"ž/ÐŽ™AaÂqãŒv’›v³9%Sû@EÂÆ¶gÍ‚C+>6¢ßïs!#lüQîнík2£õa<éežœmqM?óFðXN¾¡´I‰C¯[Ôùnœ!?¹Y$?`GZÁ“UD_Ûýq)Øø-Œ'žY“ÇÝðqÞŸô°šÒÏŽi@Z1Ó¼1ÝZ s™gÚÎ` Ìýx™iàf©DDìü—Á¡•8 ó3]icÏŠ€jº(õ¬Ä ÛŠpIóÀÍ–»¨R,)¬,+ARª@RXÚ•$åÆI%7‹’ ØQ,‹àÉ*¢›Ìp¦ásˆN4b$‹­"ú³åäìE‰&Ÿ¹Œ€"Êedš3™2“.‘mç`fr㌌’›Eì(Eph% 3Sôrβ`å=Ü ›}yóz”–n惼ñqFPþ’Žb PÊÕÅxx j>kìAó²ºÌŒ&)7Ψ+¹YTWÀŽºY‡V¤ IEô~–Ñ•Gž²`†:•Æ“/P-V7\&Aá¼ ÌÓ•g½,ê)@G¥,bC+U¶ÓNü:ãX)/X£ Y‡ç§ÏêêèxÂܞψp>³v·!:³Ûë>ÝKµ;ô)t÷ÃþÐÂߺÉôõ„«?>%!”‹GÑð¤’W™a‚;©Ç3êInå°£0Á¡•GßµgÐà…Ûƒb%³àÀʃU®ßÂ-Ã(œ©{ضë¨k-‚õxûäo*faLm¥a.~ê?˜.O[È€ŠŸ½æŠ#„CóÂ1$ÐÍ<ÌÈ&úXTŽrXB†F:+™€´°ˆ Œt¬gŠ;Õ ¬\£ÏL^*ôŒTh” yÙƒ˜/ÐH¢»\"ZÛר–׈™A`rqãŒJ’›íØž;ÎáˆiŽÍ¶@Š:´b1»Ì«n ÍÏ'€ëïïÇíG¹LaÏÿ´aèÉsJLHØ,˜«1±Äüð—ßô€O4 endstream endobj 98 0 obj <> stream xÚí\Ks¹¾çWðê`d𞹺*IU*‡ÝoñÆäHK¯Djùð>j|€AÝG¨•-Ñ›²«Hˆ¯gð}h40ÀÌ~šñYãþñ™î3[ÜÍÞ¾›ýíjÆÖ5ÝìÝõLq¦ôìÿƒ™½[þw.˜d\_½1JÍonﯾ÷¯ÙßßÍ~š1Ùµ³ŸggÚŒ¬™ÝÍ:ÅZ‹·³ÿ̾=õ6àcq%Úùƒû°óOœ7œ¶Î©û“˜_o¶á7g{»ZôûÁÕ|¸¿ºý.X®Öá—Ý}¿Ý ¡Ò]¿ß®~¹zcµš³«7ºiÎú€Û }÷Oø²½™àH[æ¾Q’4V÷5o%Ö7 GbM‘XWAr$6óÄ¢Ýf»?å“KO\BæÜÝN švlnBéènüö19ß\‡Ïý@×b³Þí·½cÒé`h˜¼ü)>±„¤jbeËÒcm‘XiYKzl(æ‰EËáö”צcJ"0ç‚Ùp´IÀÛ'ígèf¿‡^æ¼ { Èùõvs¾Ýo7é@ö×øfþqX8bÛÎ<—Ÿ…nB©¥[sfH?n‹t» ŠôãPÌÓ>rtG` 2 Œ6¼ØÜ0R­ü‡»uŽi˜ÖÀ´Òí+¥˜ÐUM±Ñ.>#Å]‘b£üx(Å<Åèc±¹÷#á¯áÚú¸œÐ¹h˜n ðÉ(á{ÖŽÇ_ïÐ8‡cO¼ûB¬c9„ô«7ÂÊÏE±êºg§ŸPYM¿m]W‰ì‹¦È¾³×¤ƒ‡bžýäbØö.‹9e¾cB 2‚©®MŒì4ñÁÙØ{OY׉uuÄzëY· ÿ’‘üÉt#u¶–íNø7ÑÍ‹t» FºC1O7ú€({šiK&-bsa˜)#@?aœõLGoõ °û¼ÌËÔsÃä8uÒ¬êÕ˜{Šù7´•¶ƒËJ‡O«õMhÂíæ°_­70Z¡^Y“½pû“¶lk»žs2ö=Å\×ã¼0Ùu58é|P.LwÑÍÍ05+jÆ NÂöÓ$?îæÁ©•$Ýï^º†á^v¡ÅòðÄ à×ýÝp”ƒ<}¨Nsöm{Y:"š¨’¬K::’>FłВ¬ˆ8©#‡Lt‰'—ó ‚ï>MWÂ'FÝ‘„ÒñPBGÉÀê“ÏAZׇµûËf¬¨‘¯N?(…zù(ã?£~d…~\ AãP(„n²ŠØIYpjèe%Q!yÄ \,WÛ’Žî÷«»Õo=jÆÕˆ„Þ7\÷~`Õ¯ODDõ*2M’ªîÜ€‰ ‹‡¬z6É"‡›ŒxÌúwc˜»KÀe뇮x4p¿~Ô¦õ£Gu¯ÁÙ~ðÓM7k9^Gô8fı­¸¨¡- ¤^RV2IW¨ÊÕ40…rAWè&+­ˆd“§V€^ÔWòµ“÷@¬ÀC\ÖÊäHã²sN`¸ú¥ôe‹È¤«ÖVkOÒ2ÒjYQYc± ¬ä#«+N‚É!£Q„†ué Qq&,w"Ó¥ G£_‘2Å+òí;iŸmÕëÅd… ©V•hf0bÙ²¬| E"” ºÐMNY ;ª&N­LŠ'Y”e’‚ˆi['VF×J+Ä"šs«Î^î*•G½¦¸›Ó%Iµ’âŠèÉ bJøY- I"£€-E(€†Ð“ƒF€Þ{ä_ïÝ85U¦°âø{׉¯e%ŠÈ¥^b®K[ []…Æ\ MÃV(”†n²R‹ØIJYpjèEÅ%QQyÄ <Ü~8gP¼…BʶĘ{µóÍa½tê3ü…†­!›úm Ü iɳ©ØÂÙÑ6_,m‰>²*à$Ÿ25’u‹ðQ;Yxbàgéëp?Ê)¦òT\J~¡¥úL&÷”(±%ÎЖùOâ*?Ëò5 b¡\ºÉê+b'ídÁ© ç’¯Óª<8±ð`uö žþÜ«W_"a«œ!6Ó:JPl¢,6Wƒ“$” bC7Y±Eì$£,8µôœØx”QœXxq´¤ Kƒåt<Óâ¢V½H+œ!®–³ŽD2Y—«aiÚÊq¡›¬¸"v’MœZuåH–À£lòàÄ Àçˆ+7RZ+.CRxï’WKªÓ~{L’”*KÊÕ4^…rARè&+©ˆÄ’§VªòQ!º€Ç7ÄJÅF¹ëÂÄòÁ#C¢»Pÿ}ÃÍb5Ðý¾q¿÷¸¸§¿ì‡í£FèÏ-"¼Ïzɦóô%•·ç˦õºÀݾ¡\Øî‹nr"JØQyp´Jè¥yôKíÉ =üöÇ—ãÓvq;ßeµTYa¿¹–úEöãýž¡%!˜&©|"À×$ A¹ %t“ÕRÄN*É‚S+@¿ë'ÐýöMÑ¥a(¢+@?šî=*&x61æøàšP<Ï¿¬úáýž¡#×XœÄ¤ŠRûñuÊ¡›¬Ž"vRH­zVG =*$ž¬ºÏÄ0[šÒÍ–60ôM]IÁ(?’æEDƒ7'EíÖG©:?ÚÑhØûøö19ï}Fø0{Ü ý6ß‚=‘‚ì‰tcßoß#iH)«»¬‘LÄ.«k6>ú í²¡\è²èf±úÉ}ÇŠ5œÀûI‰hKøÔ ¬ÖËáøL¸<ÁøÈ *è׳‘ö äãýŸA¾5̦®W³[Ñ×ÐtÜåùèÆeIÊõæ©ã€Æxî‚C§KøÔÊvtkÏýà”nÙ‰ ÿ~ Ns†C‚QÚª¯-<`#IU­®aÃCÅ~D_ƒ>ô„rA!覤Ÿ¸ÏâS+y4ì¦Ôªƒ0ÈɤU¡ò‡ÉÀv•ÕG½•t‰'†LÊÛÞöcNüãÍž8¶â"Úîóm={Ø´gð¡Ó©sÔ¤R¾†”$2†r!2¢›ÝÔÔׯ‰uÛ¶æ¦N­}»Z¿Va€)æ{xiF¿¾Þ_áZGZñA¢çu¿ØûåU-ÅwOl”3ä [Ö`÷¬È›¼»–ì‡rAè&+‡ˆˆÎ‚£¢üX/‡£iú©”ê^.F<l…3ø·œ 5‰’«¡h8åÿè&·–°ãWœZ™épPØ3Ázû…6Ÿ-“'(ÛEVåW­f#BÅ Õ*?¡"B¹ t“UDÄN\gÁÑ*¡?Œùg½IÁÍ ØgH k™Å PqÐÁ×Ð4(„rAè&4ûÔÛ<ÜDo×ÊÃS+À?9åOx>:¼ì÷½?æß~m¹;¶…<ã½=¯YFTœLð5š–¾¹g,—^Ý“ÜÖ(Á¥ºœÀs¦Õy|jN„=ž¾ï!HÁØîrY'7^Á:LŸµÐ¬½ßÂôùßßÀbS¿[íè£ÁÃb3iIfÒ¼iôŸ}ºLÚQV¿ZEËŽÉØåìÿ§ËÏÉ6í|hÁºÔj¦Ë¾†%C!” !ÝäæG ;Î|òàÔª+mAwVP>vvEÄ*^ÿ¾ß?uFîª\ô蔸ÄþŽmp†¾Œ›ta¯˜û‚±¡\кÉê+b'ådÁ© OïÚ4ã'D‡ívtb¯ý,måõ -ÝÈ‹ÒÞ»¬>¯[7w˜U1§×¶óCj*” šB7»ýrrÇ ô85³%ìd…à)å oãƒÌ#q»^öÛeHKVëÕ~ÕÃŽ•i‹jÄk%ï÷ ¢;é76G¢+¦ê¾†¤Á#” D£›~ùi‚h1¾"7aûg™MœZz‘iï^«y¿^ Ëønã¶Uıª{u4ãÍÖÓlëÇæHsÅtÜ4†u‚¼]3” ¯×D7‹ñõš¿LPÍY« >çšqYr€VÉC‘ê·«_®‡¿îâãÌÇûuû…žq>áešx˲|´VÀA@1?=òüö/ÿG›¾ endstream endobj 145 0 obj <> stream xÚå\Ks¹¾çWðHÞƒc’Úl9ñVyc§*UÙ(r,Íš¯RkïV~|€Á£›"€Š,KqíVQM7¾&Ð_÷`º13ùeB'ýN4³ÿ7“ùjò§÷“WÚÓ˜ÉûªW“K÷…š¼_ükÊH{aEƦïúÕvÙ}¾¸äœOWÝþfsqÉÚéÂ}!¦Ãæv߯»ýN‹)¹¸”Mó |üûý_'ß½ëú÷ïÃÃõñÊ ©‰ý -­h`¸yj%BN.™ ’FwjB…˜^/·à— á¦|šJ¤p:YMŒ ­ˆârònòã± Ð 6vØÑÿñ»Íò× ¦§ÙôÍ[ïõí°¹Zv+¯ó©ßßø¿ö7]ü÷~5[ú/7ƒÿ\ÜúoÄ¡¡F)Óþ/k s´vyKšDyÂÊkÌ5i¬±ók 6ºÏ³ùþìî×þ3ÓÙ`WÝ®]?¿¸lås%=L\èZ‡HJž—bDz/æ6úu¿?¦”’V2¥’P^€FJ{·šo|íŒõ³eÿ{| €ƒgÂ|³vâ~Ø„@ÚΆ™õx7Ød+Œúþ„¹‰¶ÖŸÊ. ˜(ûS —)“?½˜÷'ظîN¹³!`J¹Ë‹y䤔 wûÙþvwàÐ…sÇÊ^ÿ¼xÝ­»ÁEäèO¤¾ùà?¯f»ôÏ›¥½rZ_šF _ÂÄê}©[¢“+eÙ•V_¢ÐôbÞ•ÉDΓ7:) Œ”<²»:CsECÐÜeJР¤G2tû¡ïl`«˜áyqx½Láˆ#šŠ¯Á‘4¯zŠF˜LQeŽØŽx1ϰ‘#IŽþÏ"#¥=îWŽYb·a»ËéW#¥€ý@šÄ-Ô=$aZ~ýK>LR˜ZÎÐF’6qF—9ã K„óœ9ÎDàH‡,2VòЛ+»prúó1>3cvIøœ‰#”<þ¯Ýs€yê NÚCŽ¿BMîæûoGÛãò¶sù¤}É·Rq=Π5„C^j+8fGP”˜‚\`˜ÉÒ,b' eÁ±V@6αŸN$(J˜Æ\Æ*þ|¬ÅK9*Чq°$§ÿ7÷ì°g0ÍF­ID3D³4âÙ(h–ldY€}rÈXÉÔQ,ÂGîdá‘’]Øü‚=’ˆyÐe2!q&ƃH­&¨åÁË/ÂçvŸÎ‹V°P¬°ñG¨ãê÷Á}œTí‹¢,ÀÔ2’HcG ܆Ә— Ô3YjEìÈš,6R¦ŽZ ?’&oi ÅúÀj,<Ê¡¤§ç¬‚¬>±ÂãnÑ#¿*ŽpÇ”º‚\8 früJØ:y줔°O×”?Ž™°™o àI+¡?Néò‰Éõ€s«0ã3xÄ‘§*Ž¸å© xf²<ŠØ‘"Yl¤°³é ¦«ªOrˆ†»]L¢’,RÉP(=9O%d&„÷f»Ïuô~x]ÙÒ»fë¹xs9[/.ç·§:y­á_êšÙ«N5V]•WŽÇ`Õ½\Xu0“íß%ð؛ˣc­ï—ú 'îmã]§ØÚîû•ýç!n¦<ìÚ ¦Ÿ4œÐ씬v¬Ý.™«Ë޵#4:¦ä‚cÁ̪ߞð« I°©½Q5²޵:´ñRê¼ÛÆ;ñT ^ôÔ“¡ÏtW‡f{†Ÿ… p[ö³Á9ò³— ~3Y?GìäÁ,8Ö è÷·í8 Þ`ÂÞ±»RvÁÒ &ŽÛv§¨‹?$´íjÛÅß¼}Á-b´ g°M¶¤AYÅ”Ùf͵8«x¹À60“e[ÄN<Ê‚ƒVB¿¿»"ˆÁÜF®-HZÉ@–k§.À…oC¿úqðÇ¢¬‰RÕtÓ”(”Ü\E³P#wCÎn^.ð ìdù±“²àX+ Ÿ,‡¸´Ï1º%Ÿ; P@GZŠŸA6\Á­aÉ›%OŸÓ`-*Hj梕.jɨ¯™ÿq±èÝ~!ö ,.è7ôÞ¢Çò ,±ªîã Ó‚ŸV×݉cßË…Ø3sw1¸éÆ›¸'Ê–Ô=UV¨{+™ÁZÁÎLJwœ¾øÝæ?úèýÐÍvýU¿´÷JöÇüöj¼?™E1-ô$u‰ù3x–Mñ7k4ª™ØHãîÄ•À혜þc?ΙÓq’­ Ä·¯Ý(ó¿Kü.é_ftõQoi7ŽÚ1øxÂØõ~‹k‹Ù~‹8³E¿¾~õi°þ8ÇÑÂsŒr´bºú± )w\%,sÍQn7¢AeŸ Þàfœ³N\â•SwÏrÁ‘R_mwwÊųʼn7tEêÄwuÙ;Õ·ïü6ÃÊ=B(®~†éžágÅã‰TççŠSân„B…¦ ü f\0v'mˆÆè”]§<Ö øw]ííÝ-Š#_óèk‘|-¥xvN†‰êêç2¤Öñ(¨srÍËØì|‚8È'ƒ™|0Gð§Yp¤À—Û‡ÅòŸß¾ùσDOë–?ö¦ù¾…)žá[3Þ¦DßVœw#ð‰Ý | f ÑShfá±VÀ¿ãÞúøMþGþ­¨ïIÇÂätõã;ªî`{tlÅQl7‚¡šN ïÜ3Ù Mà!óàH)€;ß=,l¿óöo‡Þd_ºÀ÷€×ðÁL+\ÌÂ+2T’ }?þá¿ D8 endstream endobj 192 0 obj <> stream xÚí\K“Û6¾ï¯`íI: C¼ò˜Tí¦¼›TMßâ=p$Θe½BQ¶³•¿ñè–† ¿FãuÅU4¯|_7”ìŒd…úd’ªE¶Xg?¼Ì¾û'ÏH‘×E½¼Ï8ɹÈnôeörùûŒå$/ç7„p>{Xíæÿyù¯ì/³?²œÕUö.«I.ʱƒ,³uVó¼â®¹Ê~Ë~yìl¬w}7´ ©5ˆ‡&”åE Yð]¿½›ß0Æf™ãm|«ÿ¶j׺ÁgËfhÌÇÝÆ¼þøÓí¿Íßî·ýºÔûZÎòù(ŠOýbGoúõGû¦˜ HÈ\½CC”t×=':‘2gj.)ϱ¼RÅjAéì×íaè6íÞŒYÔ YÍÍü†V³E»ßw›óן›áõm¿µ­µ±X¶+Õ¹,ëÏ45O<Ï0g²ŽÎ³Vå…‹š?/6sZΆqbËÙò°º­’ZýÙDõ²3›Î†P)Ì«~Ô}$›©œ@63Íp6ëÝj"—±¼”LT<Ö"‚ŒŒ,t³ZiíÈÙⱦ²%E8Íë:挬‡woö;”-9rÙ˜¬ÉgÃk›>‡¾ÙìWÍ`R†Ê¬ZÞÛ^A4 eRJòôz¡U4U/¥È D/‹ë¥ä:{½˜fX/à#¤ì¤DöFºo›å„Rªœr„­F­\ÛÁ×6²PÉߨÂ>]G—ã»f³´z±2iOŸ¦½om¬~z½ÀÓõ"«\z¹ð¸\”½@éÅ4Ãrñ.Bjq¸NA`d$ãbñÐVah02а´JV tñú`’]ÛÓÈ0],µz ¯W‹êPP‹i†Õ>BrqÀN Addd¡ÚMÛ[¾¨{\à<)pÌKR?ûUÌBÅR‰'…È+O|ÒžJäG{*ÝŒí©œñØqDÆFúîЭ&2…&|M)T&¥1pdTm×¼¢Œ·ÓíšÞ¤í‡f³°k’û~»hŽ+“/»7sã¹@j¿Ë 3Ȩ¥ÛŽHÜ5â°=ÿApleÑwãú`»öÛÕÛ¹z{œ)v#;ÿ<É_u=›ËÌÉj`jiîÅP%ˆAuH c3"ï#¨ ì)!c#}ß·µ¦›Z­2HƒFFõÑfÅkjôuœŽ÷(\ïQ$Ú£!®U5~˜O-ï^jñÕ0[ß¹ÅYSÛÁ®¦ÔdèeX·yøN—Ä|§÷õ AÅ×YD@óT‰äˆ, 7³¾¢ŠGQ«GÄãØŒÄ£õ°ë»Í\¥¾a"&«¼N(Í ‹ {# ¯4p® z×ì»…ÑV ”DÍW“³¡Qšòñ6Z“ê ˜µc¼€VÉrác&¥:¤{0üØ5í·àfz£¥Bx$Éë§FYðSrÝN‹·ì„[·vR{°öý`>{U® &EÁ¯<–aì^ÉœxÎ*<¤RÏ5DùØŒ0î}DÎ7,´?ºaƒ‘ÿh¶öÕòÍ=ß² Ï#ƒûñ§“N‹"/!Ò 5ºG‘nÛaÞ‘›x"÷\’»ÀVÖG·ÎñoSuÛwÛþÆ.ÇígSyà8Ç—ã)œqò…]`€U™L0á9õü&”VTD®jD˜õøÁnPmj ‚…E=¥rw„IzAFçT^Á™šs%“Ù¥2—¾ ÝCàð5íÉà&œ·=ºËÉaxl%?uèžOèuA5Q¼®Ÿ’nó|«WæéN(‡è¨¬n𲽄Tmá}ác#ã`ÝíΑýó‹Û\s—¬º†r7ƪJ&WŒ8vêºG‰ƒÙ´#ü‚›pÊvà.'Á‘‘?%2·åö’5·¤W¾äF¿€ñ²R“î¯W=ZtÛv„qpIßÝ'æ <¶²ø—Gôù4ÍéóXw£áWuò­£Šäµ vîÊRsS¾Ùî†nݬÜq`³úsßíOKQLˆo` 0™u‘|µÈ¹ >žR¾Ò=(>ÓŽ¸Ixž:þYt­¬¾Ù<¸{k<+í²¸Ý컡{Û zCó§ùðDc­=‰èU^^-í0ì3´KÔ«Èn˜ÊsµYs©«©˜}¿|;/uˆ-ZýpªèìûÛú ƒ;€á/&¾˜0WÝÀO]¦f5ñ¹ýn£uBø¡YhæÞ<¨¨×—„$ÿ¯×â>ÏÍ9?çðÄ¥¾`ˆrFº…òÒÞ$À™aߺ” ’—üh²Õ<'_5-‹¼t ¥dvÝ•=L3œ×ÁÇÝýã|^(£pIQé+Ta`ldÛ÷Ý~8Næc>xÝ.ôsäÝÝŸœï!Þ7‹aÛwÿm`Áå@¯¯Žm?òKÈ–\Â;¶+˜d:=ݦáܸIm™Ù®w‡“[>¸`§\ðŠ?„“‚¥ßö–öO»/ª;`NÆf„ï#‚×GWäƒ)4-›¡]]þø@|ÝXaÜ‹­¶µŸÌâ˹$ågcÖòbyAÜ=/žvµS÷À·õl;Ì-róÐN-˜‹qëé±õÍ FbàØÊ¢ßÝ/NëCßµpý†bØÄ½û Ãʬ¥wM߬ۡí÷zñ\}Ñ`ESÌ)Ṭ=§ §ºº‡gšFÁÉ~ŠQz:^2!t Å 46²Øø4ª·EÉlJÏ&;b³ªÄ—e†u ›´Ê÷l& èøØÇ¶#|‚›`„:l{ApleÑï^û›ÑgCôqÊUùUuk{wXdÊÃæR}}=OW4NR$Ÿp}±6á @÷(Qí¶#ƒ› ÅÛ“ÇV½ßj.ßM܉SéLbŒç"úõ±•õp×mbr_bLâʼ}ïÏ>ÖÆD!žRD0ÎKD¤«'ÎtŠó„iGDn‚"rØ^ApleÑÛ‰ ›Tæ ƒ³"2 ެ,x‚~”ÿÃÚŸSYù¸#+LQÿ˜zî& ¦¬ôOãœ`Ž+t‰³ŽiGnîõUÕãb¦Y+÷:ûs¿ñkÓ/ÑõV”î©`ϰòfáŠ*ª3Ÿ/}ó›2B‘êÁpL›v„"ps—@Ñ-c¾Ó›¥³f`ð—0S—ºäè™!qfj¡³:0cÚfÀíõDR$f©í*Ì2:謼‹ÃñRûÕ+‰k·“ý»ysZ•ü+«S¢9!Eò! (jÝÛhÂÝMÿ­[ïVîá1Þoh§e&ªoUãól yUË‹äŸÄS¦»-)ecAÇߊÃâM;ò«xp£–BÌšéß™¨7à€©÷õ`å](M¬ªY^â¯OX™×,Šî­<úÑ’ÙÆp°Ùö´>ê®Î_Àû”×´>ZX0ôK„¥&Nú0OúŸ-¨=”m;",p–sà%ô€­¬‹ °<º“LYIXËU[±¨ðBÛhŠOhJRq­é ÆIÔ: UE¢ÐWœŠJêºGÓ“iGTnümò‡­£Œœý£U*b.°=—AÐÂÐP۾߭ºE7¬þ´·ÆìsÑé›B®,ïÔC”]Ç0DB’ϲDÉÜ-2žv_÷(q¦0íÇà&cçÁ³t­ª©`>á—ðËÏðë‚^TOYiA£R©4™V)Ý 1žv _÷À÷ül;B+¸ÙõÝ£*‹×ë¥1tleáû¡Ý‘MŸþ î [¯·xîn§îYóò9®+aÉì×…~¼9öêñº‡ÄAmÚöÁÍò0ùè/s‚°ÇŸ`Ë8¶²è)äßÀlZõÌR/ ùü70„ˆÔí^YðœWVßî|~h2•²£P{’PÚ>¾Ç/ûYÂú2 endstream endobj 9 0 obj <> stream xÚÍ\M‹$¹½ûWäѾ¨¥PDH‚e`?X³àò»·Å‡ªžncŒgÌ2ûßû½¬L3¬Ò`L´ða¦*ÕUzʈŠ—YÙ·¼ÝzÙJÛŠÙVú&6¶2¶êu“¼©·MÊf­l"›7Û¤n­MðµŽØ6:>â[ÉŸÁ4eè&}+2|Ì¥9o8–u«@òÜ·*@,²Õ Èâ[U`§bþŒÉ*¾ZðኩvUÅ1Õ7Í@Ö±aHÜê¦hë›Â¢Ë& DZºáS”†ãh˜­0¡vÃQu3B¾aªêXƒ©­û†%©~¾?à5@fã«’q j)›c¥~x$üp$ü ) ~¸~¸’¯øj†ñX]+0¦šÀ0`-ÃL†e7Ç›ÀÀk Ç `'ÎÌÆ1¦àú·°þpÕþàD¹æºõ h¬;¾â^pÌs‰“¥ðŽ3ÚÐ8iÝ“Â) §¶ KÕ*­@›l#‹DHÇ" 4œÄRbÙp Œh¥ë £“Œh|ˆkÙ«Y²ËUh­;Ga­q“ôÆÌ2:G,èé0ap„6ÀáR2À1GÁYt¹ Ì}.ø7Úþ†À¼Aôáã73j™¹0.ËnU娠YX†‚Œ€]Êè.4Ì8&´Œ>ÈnºÖéÆáÔæþŒã=K ÎIÙ¥slÐ@¬ka®ÅÊ1`Yæ˜Ð²Ì±Ý²Â1¥e…cü~¦m-XFLd,ã¬u·Œs!{`?£Ä6`ÑÝ2å˜Ð2ã=ÀÙÀ;Ýó˜cNËœc–qåì‚CnÓ2þÏïW%• L`™s¬Ò2ç˜Ò²–dS;Wƒ8up5]˜—«ÁÕÔÂÕ ©p58“Öýí1® ò –q]¸êÚ¸.CØÈu!¢® í¶ÌuqݾÆ<;&\;,l¤G»eJxÆáø r6Ò/£5ڋІ´c÷`p~ä lä÷…°‘ÇŒZ—_mD^íçÝ™S8Žìá˜Ð²Ì±JËèÒ–1‚¹"ø#¹’s̄eŒ8æA«Œ$$,c„påšñ̙ɱJËè×°uÆ-±Û`<"3aãŒYÔ÷øA–Â2r+׺W°§ì6’p´Ì8¶[æSZÆš±{ÐY62ý#H朤É»ec¬6¤á¹$Aê‚ÄÇv3ÇèAËc­è…cF Çœ6 Çv…c6Â#á'Àj¨-ˆØÈê!´Ì”c´ì¸}ñÅÓ·?|â h¥ñ‡§oÁ»7 J¾y÷îéû_>>ÿøòéç§ï¿ùöé§—|zú?½|ýxùêñòÝß½ûÍg2W1Wÿ—™~úçß^ž¾üðáã§§ÿ~ÿÄ£?üùÃ_ž¾úøËû—_~Θ3ÿñéëŸËãÍ—øÊO¿ÿøÓǧo~›´^ž?ýlÒ³re¡C¥i’²—œòÎH,Hf%)¢{DZž¬HŽÌ8µ¥ÈßqTÓð€SgÑTûSá[ÑqJNH¸Ni©»àØ„££%ÖŸ'÷ã3N¯©¡òGGNÍ=§Mq­6’€uw÷TsÀé³?j©Éc’šœ1ãTI¬;N…oiz›aJOþˆjK!'ç>£dNŽ8V"¼yžpê(Éêƒt°³Hæ¤ó~Æi ƒÜj‡o%‚t^fפ¹ÕÒñÒyq ¤Ó¤S ¾…[É3Øšõx[×v+sù©ÚéÚ©Þ•ˆÈ.sý©àk9ø fo@sÂn<96;P†w%‚àÊ\Ð&'ö06v¥@s Éúƒâ¤Á»A¥e®Abžò#ºÅkÊ!g¨Í0*Iw®…Pv™KHOClŠ6&Áre®AØg§:4‡ÝrR š«6î©ëƒçÐ"¤Þ"ø´Ì…I’ñtC MlÐ\‰ÐŽ¥¦P/©µ¢›KúÍľnrx'!D7×"4Ù‰rÁdš¼…ÍŨTÅëƒèŠÂ;‰ÈW™‹Q‘œØèï@ØFZë¿jÞüìÙ×?ÞýÜÊ.Næú††8åƒZ½µ²‘¹¾9²DhYÀj!}Ü\ßY2p¤éá™ë›#Kê8€¼ á™ë›#KúÁŽ4í! s}sd‰à ï$h®pŽ,i8Ò´…p€Ì%΋¦rp€ ¼‹á€¹ÄyÎ`µxõˆÍŽÌ%ÎzÃëȼ“ˆÍŽÌ%ÎZMvlC¬ƒáZÐ\â¨ðî ÏBru®n¦ŽîþP«¬&í!4÷r!#Iù«ÐnBs¯úÎHÕ qjJzÕ\Ý =wχ`…ž»× r¡$IÓCáIzŸÖ¹i뉗Bv tÝ­FÐ\K‘º%^Øš¤Ò#h®Î¥¡<@F%&‚æê…ÚW{ÊöàS*X¹‡]È}¢‰ß²Õ˜>­íB¸ÊiØ¡Ê14Wû…¦ÔÒ±ÑÒ¬IC‚{.Dàtêhºûˆ ºz»®râ…뇤ÔRÕ û…¦ä©ù¡‘¡ën#‚Që…è§5ñ*ÑC¼ÊI4„è.T?¼º*Yõä#$.d?lèy­z’šŠ†Ý…îÇ ½r: @š/4%¼?4%ª1Œªs1nèýAtÒ©ÇDÊ…x…v¥*™S‰ :½Ðý¸¡÷È(ÈD^è~ØÐ÷rêWhWBbáBöã~þ8Cß"P.4?læ›"º‰f<§s!*ÜÌ·C$Ëp-Gðœö í ­ŠÈ!)¡U±¥’6ôíA¨Ô±J¹Ô9×¢‚½É!’9Z ºý¸£o‡H¦ð.‡Äö…쇽Ê!’Uô+Âs²wôíBK1þ-jÿúƃ•B•¾,ªôu‘Pey‘Pee‘Pe²H¨²ºH¨2]$T™-ªÌ UÖ UÖ U6Þ^¨²Û"¡Êî‹„*{^$TÙûEB•½,ªìu‘Påy‘Påe‘På²H¨òºH¨r]$T¹-ªÜ×UÞ UÞ U> U~[$Tù}‘PåÏ‹„*¿H¨ò—EB•¿.ªZ^$Tµ²F¨j²B¨juºq¹ Êz9õ#p«FÐOÓ ýôsð\sËñÈ.ô£‘Z9õ#ç}P@~¡~üÔ@?!<×.4>•äåÔ@®!<×.4>¾ú©~FÈÝò_±då¸ÉJ@®ÚþãWΛŸV*Ií¶HIj÷EJR{^¤$µ÷‹”¤ö²HIj¯‹”¤ž)I½,R’º,R’z]¤$u]¤$u{{%©û"%©·EJRï‹”¤>)Iý¶HIê÷EJR^¤$õ÷‹”¤þ²HIꯋ”¤1ÿtWAÜg,€·C~à8.~:Õ=ö¯ÖúŸ—¡Š“î[E” ;õÁßÓEÕ_5>ß#i>õkÏ eÝN}ôÂsÃf 0wͧ¾r­ô3|* ;õÐOH«=Ú æ–#¶+˜[jýŒ>ÉýØ©ï€~BxnŒÌÍÇ•<ôkÏÛ ä ;d—úé!¼pŸÀÜ9Ÿúȵ†üòùyªä»SßQôb8ïg¼Žógt9…ˆãe":)9U?ïDjhÄBõuòçm”¤[žÞDIº•èM”¤›Ì@o¢$Ýæbô6JÒm.Fo£$Ýæbôÿ®$Ýæ²ö6JÒm.ko£$Ý>/k%•Ç3½ÀLJî‚Ê“Cp™¹›û)ð ò„<6ä6—5Wóñ¤7°sÈ“nsYsPí§ÀÃK¨!‰ò!O ¸Í•Í:蹞¯¢FTêÛ\Ù Ü_ú)ðÀ»ˆ4ºçÙ!;ÏÞAé 9A÷¹¬™žR%¸ò¤€û\Ö¬‚›õP^Py,äI÷¹¬‘‡Æ8%x';‚û\ÖÐh'ÕSâ»¶¢»ÏeM‡¦~<)À2¼ ‘Ìïs1Ò^:ÇCâ驆Hæ÷¹©·ÔÆ)ñÀ»'ÜçKM“’¹:¯¡†äÑÜc©æäã”xx¿ÑÝçb¤ÒRÑSâáýþ!@s1ÒR“ãf!áýþŒzŸ{¬·Ð’îs‹õZÒýe†y-éþºHKz΋´¤çòßjIÿbE endstream endobj 239 0 obj <> stream xÚí\Ksä¶¾çWÌ‘sšx YWâÚ$®Z;Ê)Κ¡$&ÔpLr´^—|âÕÔP¨Ú‡T»eW0Ûøš@h4=ÜüºA›Lü‡6‹ÿ³Íþ~óæjóÝ_éei™•›«› E)Í7;ùÛ\þД¦h»CˆÒä¶=mÿsõ·Í_®6¿nRR›÷›¥9›:p¶¹ß”4-¨i¶›n~ºÔád´ŽêXµ~¯/°"¹G„¦І¿Þî0Oºóñ°ÝB’?äµZ§ïªýØlsÔ7Õu+:rŠ“t»Ë³,îCWåçôýí‚Yr”²Ùœ!Ä\ÙõöIcbšæÈ‡):䌩š~c:!cpc'/:Òðûn²L}ó´-;a¼œ%ÿ­g6Ūk‘Ô¿dˆí›ú(ÿiÔæ×ŸOš–\Ú–å§2­âS¦å W¶ÙÑ"-ùÔ!ßîJœ'oúê¸ß”Üíªãa÷ýYªÀÉŸß½•äçî<6Çz<ÔCi™¢*C¨±”1œæX=áäC2Œ“·jÚ{eÆÃYب;ŠÇËŠUKçëúXÏ&7õ1öÒŽ‚³4cÆ^ÖëÿkhŽ·j™wz‰í«¶½®öÒ”ÿSßôŠ[b‰ü«u7+f½(S†ì¬÷¬3fz1ï§Å,œXÕÞv}3ÞÝKGŸA´£z¥3í& ¡2v¦QFRäNôT_)VÓd¨«~âôšë±¯%¡‹ò›Ã‰ˆLìÜ"Œ¢-"v îÈOµE¾?÷½ÜŸY¢Y?œ¯O}'vbA{ïã•,‰gL½›D„qôÔ‹x »Å?^ Úãä4EM*vêÚí®Èòoûp´mÜ,¯± %iá–Ó¶ù¹®†î8(ûÜt½Û‹õMÌM/vhìvèÑ×?¯n†bæU¤(çòSÍ+Öéó÷&@Þ‘òüåy¬gÊM9Âyôàâ³pTBôààЪÛ„SÓtÃå‘5+R\l„„²<¥4z?­\pd%É¡ëþ~Zr½B‰¥¥|—}2CºÑ¬1dASjW\LòAöÀ0•¤ÚC:5^Clk"/8”Òè·õx‰ŽÅþ›Ctáô3DR]Æ8ó¼Æ~_Ã̵“ÄFBSbJ&;ò)Ù±§¾×åÜÈ×Pª,ÒÌùA©’ËÍÂQJµ”rj¼”2Ø–,^p'eÑûN®ä÷ ´*eFh 8åEPƒ•²ªqì}¾§:™†©ZãNÔéÔØØ7×çQîŠ8Ï_yÜøÄŒÎ…¢‰†<4"*zàt;uj|䱨†~p(¥Ñï›Ób¦•””± :Òè·ÕiÆ›}wL0;V[ͬ?¾}§ä¦~9á¯Éa¯áºsFyŸ0•û¨ã“jøäÔxùd°-S¼àNÊ¢u^v)/ ÔA„RÔa¥¬ŽC5V3ZÁ]®:Úf_Iw´ÔѳÞ7¿dˆê]õæyùâäFˆ0&˜æ‹ èA¡CRíœ/ ¶¥†Jiô¡ne(rÉž"%*ãgA|'¤á?'¤ ¤•ª¿Aªh ›;ã»ÔÍC#>Šä\? ª`îSþ™(㶆2¹¤-cxcD‡ ºÕ0ÆjñÆ@[*x±¡”¿«Ïý[ˆ©B'"ÄÆAt ¥Ð‡®yš“ mXòÐô–%Îúj:xÙ ßkÉ…JH>c3Œ2KÀ1~9ÇáèÛÌryX1ì)"Ø#z›9ö¨v€=N—>Ûà ¥4ú¾:.DÎEšsˆNPÄ£C)~­naì€>–©¯ê½ô$:»Öܘ¼›æÒ¼+IÎ'URpÔw ³½­>ØKçÜ]:çŒ}j ¹¡®á/Sb)TFPHt€þgjduxù£-1|ÈPˆ<6ï…JU4l4P®Â¯ ¤4œuö|žûQ{r+cI7è½lnûéþ©Ó¾è (þd—SÏ “õ.• 9„²íŽÈ$z0èT;@'§ÆË'ƒm¹â‡R]¬«±ž|ö-HåÍ·ŸS¯nYT4LcsyŸßÐn¸—±Éw’±”jC{¿z~±ùÕ«ü—ú·SÛõ6 êRô%æ_ß}’›DqÊ]c•²ôJO}L6]öà`é¶5¾5f±ÍêñƒC)>‘c)ëA1„—ùŒ2¤4üÐü^ûÒeîßMUàè¯ (ùËã‘î"‰Ér<ŠHæËÐhjXduxI¤-;|ÈPHGç~éÔ¦-ßb댇åîˆZè#êSÚë n* Âc,+ù—¤ŠÙ¦ˆH(sT‰HÒÊä¦â¸¢Ú²85^¶lË/¸“²èÇú·qñ˜Š0„P™y À[)ÓöögÆ¢žV+3“x…dAÙÇ¿ÞiÜØÖ°†e)³¤‰HÎËpfj(cux£-|ÈPÈ\äÕËtɶàÁ´cy±‹çŠ|€¦;a¾„}‚Øñ·ÍNå ‚DdÛ 'rŸs QíEœ/G ¶µ¿ÜIYôóÂ嬇'ó”±…^N”>fIå)³ËØç,SyƒÜ`×P¨à)· ŠH·Ë@S3À«ÃK lyáC†B<ò¦Æ*ÐW0~@H)h… “ªöé8æ2Û>uâS'þy ÁŸA ;Ôü¡J±sAÙwÙ# Òm?…€‡,¶á‡Já<’FN‡¦H@Ò:žø–—J$iu2ÄT%\«¤×„Ârò‰†¶†9ˆ¦¼´Ì‰È¼Ëà¢O5¼qJ¼¼ÑÈ–>h(¤±•Eëa\Ù¼Àà‰.Y¥¸H‰I›ÑÇi3]¤MA‘6OÔ×,UFÑ·Zí°ÜT‹P=zY‹ÏÂ,ë¨ßÊʬëZµ Û©ñ.lƒm­Jit}MeÊý/×7–Åg@‘8 °" ¥™4~b?x”"!¾¼Û“?Và±ûŒr£]è\É.ù˜4›ìÁ9X·Œrj¼Œ2Ø–+^p(¥Ñ«Ãa±¸‘ÏÐÅá8 £)Š-“¤FSô1Œ}Õ@™‚qщê‹Æ `Á4¬á+ÒÒy¬ˆÜœìÁ¡ÇRí¿œ/¿ ¶eŽJiôCÝ.Öd£¢ ÂÉÒøK1›‡`UÛ.9µa=ÕÿÌtrc‘~Ì» òLÌ™z³ÁͰ¯Û¶:Ö*¥YòR£E'±áxŽ3I“éÙì; ~øÇ»¿ëËê£*/ë»ã}=޳ßɇǯ8§úÖ³LiŒ!´³ÉÅ2DÆ1Qw.B°…©¦ßÓ8ͱY8ê —Qä¡> stream xÚí›ÛrÛ6†ïû¼¤f"†‹3/-ÙqÓú”Ø™¶Óö‚–hE E*•Ä3}øHP’-’®Ÿ4É éÿ°À.°r>;àøò8Éÿ¾3š9ƒ çõâ€ï~à\\9M“^_xÝí×ë ;£X;hÔµ„WºëâvÝíábéÅ®~¤4ÿɇpÍ^§“é¨4‚QšŒ§FW"|Ï»_dV ~[d\xÜCÄd}Z³]ÜN¬B[ÁM;¡œjUÏjÍAC×µJ|«$7ÄØÀ/ªˆªJžê熗$Íò2I³Y9iJÛ,¦ #ì;c¬¾RŠRÛD…7b” |j1êâvŒv ©L¬å­¨mß®²Y4K³k]ë2Ö #•HÀŸ™Z‰:°Ÿz²#ìTƒ•(D›¢rŒÑý°‚=3vV" К®m†'[@ÍòL¹Ÿæ*[sí–1¼dé*[ÃôQóºg–V¯.01òË’5³” x eQl Y!iݸRd;V»z®WÒ]/­ƒi¬{åësÛjjŸ¼RžÞâåoõM Öt SÏ /oÆ+[ º©êr`;ÌVÂeß½­×k™Þãélš¯@^4@6-‚'lÙV€ÛØóZ3_¶à²¤#™=‰ûî[íê8Y`÷ðèìWõЏjö«wþèTÌ™. Ó™Œœ£¬áãÖÇ%D®êbep ¸qªó°šx‚xD{ò{ž ¢8Gî~ªvÞ¯Iœ†cáKÏôcTœy6½4!cñ§0»,<_ J–ÁCÎ+]ÁáùfŽxH þ!™‡ÚÛé$· ìG*ôH¬Òê×AuÅ:«UÇZõašüå™,³uÕ‰[òèI‰‹E±àQO߇>*µú!­© êAi ¤¤2›OãD¨ÿ¤ÜÌ{}0Vb ´5,V÷ìŧQž¶ù1¦ß"s+£?š|ñ¦'ùh}‚Ñ‹³Öÿ}‹guîB¸º ×t¡Ó“Yuäu# Ä^: »s²Š­9a_ÝakNXs:Ù;>(ïWÆÓQ˜—W¤£0“Öøx‡£‡HÐ!êúZã Ç{µ­ªkÑߌÅ,¢‘_*žº þИ¬à]0Q^æ/ ”?¯0 O>Ÿ¬"TìV²®L¬º@ýÖL8”éEåǦóóÇ·x="3º+«zV‚–©AåÚ¬öNÖqQ/àâ;e_U…ÖdQ& TŠ¥"38ýp²¿aH|ç©Ý•ŒÕ(jK†R·ÍšL Éœì+ç`O9Ö=‡ímñÛ(¥;*·S©é ´õA8AÔ¤ü ŠdE,©œÏ‹|‹h4½º®Î)ÒKEÀýGÙÏu³éô«eR:síPh•¨]Hà Ìàù‹ ÅÁ·p6MÄ™^­DžÄU×êìâÝŽÕ¹ ŠLŠÎ HUTpŽßž™<˜(Ì—Y´P™d·«Ü ¥Jo ´ÍááÜCÚ]êë¹áÙÑÁïúýèìŽùj#m}@AGëÍrXóIAβ(^Ž¥á ÎwäûÍ!+}`Ô'ê©! ì´qó+®æ#µ '&É|ŸínƒuB¿•hëC ª~µRZÖ †i²È³ÐäM/4mÙIç[T*kS e®Ë°8ç“£Òe2^¬…YÃ3™öÈJ ¬uL -Ób†Å Ÿý0J¢,Œ_­þö`e¯Ö~t9MÂ2‰Ï\¨l®%»Xë —RQæ½ ‹C<9úA)ë'%xtýU=RÑ>ŠtÈçp ^“XkŸžr1Vܰڌ·HåHbãHÊgyqw«Õ ‰JÓÛ@¬ùí4`%º}É ÷<— Q?ŒÓ$*½÷×:Ô’¯ÏÓøKOî)wJ‰­¬9ù É•qõÓ@‰T.仟þa0ç endstream endobj 292 0 obj <> stream xÚí•ßOƒ0Çßý+úØ>ÐõÚBé£?&Q‡NÇŒña?:C‚,²-ÿzË B4ê¦É^f ¹£äàîûéõÐÄìHq{34yDG êœ*Œj¦Q2³¯½ò!@Éôw‰§¤ÄÝ—¥)òQF< <˜Ï–D~&‚ãQaÜj<·–ãé*3 ·2\˜©óÎòÒJõúä>9GݤJä&ªœâás*Rj a;t_†VQ²ò¸¤>¸"(/”Æ'Ä~ 4¦ÄóÛ##õ_ŠþY[|é d[ý-‰²jßQî_õ,µÎà6^ÃSöŽÝöâ7:‚b›Š_ÆÖý"œøqš§ƒÑÒÊîûû×2;ÃÕ( 6Åøê^‘×k–Ží9+»ذø à‡êšxt9t#22¹)ê Û_³tâü^:1ùÂübl6%~ÜW\åÊ#ÃuÌû©}}ð!Ԥà endstream endobj 300 0 obj <> stream xÚíZ[Ü4~çWD'´'éô|b‘SF*ljн3æð5+÷*¬j«Ô&½7íÓ'ý”f¨|ðˆ¡‰LœßúhPJ$uÖýÈã$1iR0d J0…£}$` pì‡Ü÷CØ@DÆGD6»lb"z)¿¢>0ù„ÇW^MàétMØgЄA“'1*¶?*|âªz–ûÈÍqac\Æ*•> {à"NÇÅ÷½Ô®·ô:q¤Îjýȇ#©GlV~oOˆJÛìR<Â]7uQ»TcÝ3ŠÔ¦{»XÂTðg¶n]«ì¯Kò&ú×UÙ´uêæ‡Æ+ Cqazí3Éý®î3§õÅWŒ.4Œð' ±u³t—‰$qGİÿNİÿ#f0ÿƈˆˆæãˆÀ”lûO~>¦ÑVÈ «ÒÑjí狉âbjk˜p‡!ß+Ò].`Aåáâ‡÷`yüPEÂâ´ɯg|²ûŠg~LOqºžìñzž3¾†š7‚¨Yž™—ϰäFƒò3ç)mÙ¼´ÑÔ¢Ôo@… ekÕ•—-gq›;Þ- òMë÷H¼E-•°jE\#ÔÚ,Éwá„)O1"§s´Õó^nšôØ_ ˆ#lÀ‰”8ÏÈ•:/#yl¥ )’hiS1= Œ˜Äªq`ö³€gFìÏ=K 1¦ÇÀxf5›d¸®o¤»‘ŧÌ™É,2¥ga{:@Ÿ'{|œŒWFù)3†çÌp|Èpx¢?±Ûļ»Éêì‰8 gf<ÍÓãsèS;qyhŸãÆÿá ð›Ï‰æí©ýñø‡«²¹ CÒ:³;ðiwŸ9î}›WHûbHûOý{‘#2:o¡4ßîäl?Âl‚°~xµr³±C¶€>s šÕÈ÷X¯iënÝvuZœn¾d¥¾½èW€¶;o\t©ˆ¨xœ„í†~¬Âj»E–¿Ãƒ‹Ìž\u¥9Ü#ÛVt‡ö„Z‰-R>.çàÙ¡ef`˨ôB;.Œ=Æ¡k_W¦8ËVUë<³çB{¬Ê¦ÖCˆŽƒ2ònßêxì…2 †6Ûœ©Ýät]­áÓ*\­š›üªý JWý!Š9²™{Ó‰ÕZMµfZñœ(A -åÇeÕá Ή¹=Äà EÇÔØÉÔ9OêMõ-Q¦Ó'aó Ž@N7 û¶¸ŽÂÜX©žŒZšÐGÄâ|"χÊWâÑù'LÆo<ÌìD¡;Ø\0â9,ša¼º²ñ cÜŸŃw½å5$áø`.a¦ØG ¦DzöœÙùgÍäœ azžoêîöÖF‡;Á9´ÞΦÄÝQ`’ аøµkÀg£JÏ×ͦÉÎÖøP4•}ÂÛÙ¥çŒ›Ææ¬Èêd´ïjPDó~Ø×HYdÔ×[§]ãøA®5Rá!U]gU»2w' ±uÂÔÖq´ÌÞ“ÀÞGe–_ìª òp2vãMÚÖù=À–ài{N2«8.ñ¶6m»uø¶Ë‹Ö6 w]湌'nÔã\†çl«…ãð&ßäEZæò@!(›”EHvf¤j½úŒQv®kì5ŸaJVE·)}&âí’­‰úÝ–­‰Ü͈÷ý9âÌDØØ8®—þr„í¼ÉúÞjx£Ä >½ó1q (X@×¥rG’4ê‡þúÅß”ªéW endstream endobj 303 0 obj <> stream xÚÍXYÛ6~ï¯Ð[e$fÄCW‘¼,ÚmÓ&E‚¸}©û ØòZ,9’µGß9(Y²å]» HçâÌÇ!ÏŽt<øI'Tð÷œÅƹ˜9/.#={±3[9Ò±q¦88³å?îEÙËz2Õ‘ï–+n¯'¾ï&U–|ÌS;µH þø8™ªÈM¹3÷¤)²í%–öf¢7Ísì™n4+Zj1™žç^¤u¶Lëç0Gn^â*X Ì+»²XòÒf»e©U_‡žâV»€fBÐîßÙï`¤µU ß'[ÓÏM‚ZiíîJnÓd1kî•»uZzÆw¶Æ‰†ôÃë”?VeŽº†îMV\Ù9ìÞmYvmY­¸_š¾/µ‚žeÅV•uÁäO¤ô/³‘=“‘ˆµ35Jà@ÓNšÀǾ;ëëuµüÙ°Î T"öA` tàlíûÂëú¹óÁyÏZú#Zúð i9÷B6õpUÒÜfy–Twdª×‘®‚æÛ'¾&šB°2±që2¿¦ZŒ»äuÁ›wÜn«8m¸3w¥óÉWl5žc8˜Õؤa ·äïºiK'dΟ7iÍ}ô/R%h'‘÷¼,“–ÏÐàãªm`õs kël–­OWMSa0Bb)+ºŠ5;Âúšì&Ÿ¯— …©×žŒ²ê|Øk?rë 81­wØ‹A ÔÕðuÊc7Ðn²"Ûd_`Ê‚¢¨ÊŠçò¤º:Ir{Ąà •5"RÆ==J¸Ôÿ¥‹]Ö¥>Þšb<÷› ™#މi„6:xª‹õ¹TÆ}ûQ‡ûDdTŒG|/ZýpqâK±QF`ûŽºWt¬Ã†$PXÊXO|ðÑT4±ÙðÅ&ç¨8f¤š‹²Ûz­Ã { Øâ•KÅ’ÀûC¢‚[ÎS ìÖå&坨UQLAlÑ]ñ™ÔíC²\fèo›“Ü岪=!Ú Ý_N!Æm&¦Wx¥ÅÊ_ß¼ûv_‚ìºn6]Ðá¿hƒŒê‡£ë¤#LyºNÐ.Z•Õ†îyÂÂܹ-«eV ÐQoîn›*¥°„É0Ú…c,<iÌß‚@àÚC°y‘7K:Ȩ‡¬Ü¥ûtxp0ÁÄÂÏÞÎá’MBg(vuÄÞë‰õ5ŒÞÞCÂ÷eÅzø£ëa*íþÖ–øo,¤zŽwòˆ3ÙL‡/J_híN½‚åo†”Ä›QþÞ$œohÙ>¸pŠÎ>K¹–ß ¸@kåÎÖGÖí#-ðN Ó€RiRÔœ!¬³©u"ˆˆôJÆÍ•žŽE€Æ¼nP¨ò?zÉ’ ê§ã—ÑÛ øÍ³W@ЕÞC¯Ý=JÝ£sò#ïQ–âSÒ F5§—¶ûd™ž,5.Ë?¥\sJVx¶]zDl‡‡<ðhÕüBY7ûÒ©KÄ1á¾'p¡Á™ÆÊ3Œ}´•êŒÝ{ô¶é‘wŒ¡%½wŒÃ§¶öF/=Öiì =(šÆ£¿ä*ê­Ÿ,²ôƒ>Èòãzý ëõ¹®Z×G±ˆo9jLCÿÀù„ŽWßÐñÁwâxm?v U*Â]˜Æ§²%}ÿÃÿk8§Ú endstream endobj 310 0 obj <> stream xÚÍioÛ6ôû~…}‘ÚJIQG]ÑÝZ ]= @]²­ÄÊdÉÑѤÝ~üÞã£dÙ¡£Ë‚!FÄãñÝ|­ ‹Y>ü1+âðó­ùÊúyb=þ%°˜ï%~bMN-‘xa`¹¸Z“Å'ûr™Õ™ã Áí´(pØ_)í´ÎÓY‘5¸$`–Ñ ¬J·ÌÎÒ6ÿâðÈΜϓ_óGDP ¸åòÀ ¤¢rÕƒs^!PèqdÙA¦!äOäE¡5@L}.5ÐX"Æ<ÉAlñMÜHd‚öŸ:®ô}7,ð@kvøÿ‹af':ˆ¶ÅŽËÃÈ“ zFjãZ²ûúð° nÚG8Kìv™£øýö˜¾ëº¯XѤYV]± ñÌq•?¨I[§esZÕ«Lï¶•þ.5DÓ¦å"­õ6‚Òhj3M¿ñ+¦Žç¸xädàcž–z±ö?—I/Aož$‡ËÒ&/¾"$³U™Ñh†‚êÕ¼TRוâ{ÑÍóòŒvÒî*/ò´Ö€p‚á6(½„[ˆì  ²tîðÐ^âÌ·«:?ËË´èÉf]Zäíü*ИæH‰,@dœu@%ôÇ‘fc ˜f`ÐkFÝå:SºETEÚ*sàU××ú´*Š y½lž(::>àÍM­Uz•¯òoæ{/äcξ\0öd¬=ð9ê:²™ñbpŽþèß/„ºb+^[7‚© Jgvhä<ôDx#­`D‹›iÉZÜöÑŠ–Kh9|Äá²ÙF°¦+C”>Ïæ-™n˜ÑDÇC8É=:¸6Ê’°ÁB&Ë0/æHÜj™@kë_˜$¸Õ$·‰–D˜P¸‰ô¸(†ZC° #/a2rzð=N窽ÙïVÊ–ü/ÍÆŠ®ÍŠ–EGÀ¿G=ó{ÔsxwzÞ.ó#„Šúj 2ó&“DvÕ•‹†²IuJÛâõÚ„_Q ¸!‰Çº>ñ}¶/ì÷–yFùamÀÈ}Ïï³Ô:Á-¥ó}Â%d6߀ ‚b]G¶­Ù¶ÃÓÑоBZ¸›Ë³‡FcLÃþˆ‚‹ÉqÎ=\³ñª¶l•x1;\³!iVìÕlß©fù½jV|Ÿf£!6íhÖäfû4+´fã}šMîT±âž»nb¸|…ôüxÔ‚˜ -A¸ÖÐ,±0vÁõôÄ” ­éãÄдŽ+zSË¡í¨u°Ø(ÕysœIûÁã¾7„<›pùc^΋n‘ü³¦]ä•·üih"ÁÔr`‘Ïv CäY±þs·!—-¬ •Ú_ª|1u®£û ìà9AkY ¸áËcº@¼F+í<ýÄBb÷??¢…óaáéu2‹ª›¦õÎÉoú{Åúïâ©vß]>öî–Œ»Xìsú  ó:ƒîZÉ3µ§ŽŸ†÷ǾÉZ|R¦«l 5ù#²ð‘…ØEQÍÎOy=B÷áäÝ‹;çÉäM0>Ÿ.'uosX˜ÉÊ]²pl—ñ^‘Gë=¼‡&$3¨, HPˆ?Žõ ¿~Û‡±{t‹½‰.ö°À"¿™Åp?‹É,ŠžÅz‹ÌG,~ÜÄ£¸™G±ŸGÆÆèÑC ªà!Œï²çöºÈ¤ƒxay"‰­KD)£_”V‹#óÂú`½×1RZ‰¡·ÀŒÆ1žº2†œmÇU‚ 7ñ™lâ÷eÇìed`u ½TM릥Q™©Ç2©Ó…ìÓ½¬Iý" _õêÛïÞè…¼ÄÇÍy†u„Œ·ñ¯Rœ}¥Ée·ÎÛþ¬FvüaûËã·¯>Ò°'Œ{iKkÔ²IõÀªQ@ŽÔü/ûWRÒÁÆn”€v+õ‹ðí2Õt]°ÙêI¿¤ÏeÞ.i¤D¹æ˜T|¨ ¼-Ùª!àCjwÀ܃ñôýÿì×Ë endstream endobj 314 0 obj <> stream xÚ¥YkÛ6ý¾¿ÂPT<ŒøÙ¢Z`³ÀbvÓ-¦À™bªØÊŒ¶äHšÔ Úÿ¾—/‰’©±²A‚HâãÞsŸ‡tVVx•¼ÊüMWÛÃ꧛իט­$RB¬nÞÃôNácu³{›´˜~·†o¦’ûýñ®-º»m½¿{WíÚÛdܬ¯8á vÏ\ÿ|wýÆ}¤(Þn×߯»ùçT8› ¯ß=‚‚â}D8žÃc«üPbˆ{¾8‘3bÄSÉ—šÊðl©^¸˜µT.°”ö–Ò9KÕKéÿT’.°Ô g³R°—RæoñovõãŒxœÉ›p§[ô—wÁH3dë‚%Eý~T¯^³•Þ˜*}lÅ)-I"NͶ›‡b}E¥JÚ.ïŠCQ­‰H:·gÁÖŒ!J@§=ÅegØ-Ø6ˆk­è*M´éûâ`?êw€R$ŶCë+iòSQV÷vÒîÞÙÎ ô[¸ÙbÊÖ=«²+óýþ“ý,ÇnM²äÓZÒÄ ×fWBŸ@Jlj"îR¶7<‹ÎS$2o8‰/vAÞ¶å}¥Qj ‡Gûé …|ø·Þ—[;¬¤ú%]mG¬©ð2¸ f»‘Ë5…$9"Î.“”1o ÃtF¹(‚S[+¸óšú©+«"&[¦{G…§Ú]ÙDI¥ Æ®.++¼nvEãÖ΢BGËA}ìÊCù9ïÊÚmàýiË%£³0Æ·)æùýÆ:÷‡¢‰âçaééóü¿~üo7£(£nÕ¡È}¬ù©GåÂ$‰MµI˜tF\ Rªe—rn·k}5…SÑÔº’ÿ0dša,Ì0É0)µ+Π²(Ã$÷ÐùL†eg墻^G¤``Ø ¼ýSŒ)âwŒ(æCà¾uë‰fHÖ´ýp.ÔiC ˜«Ýhñ‚(â¬w„¸àHsãlÄÛ*§‰QÛ¶v·ˆ00¬,*åáœõTé\К˜¯ýÒÛ¦÷iÛ2c£r¾$Hš".‚šøõçˆ!T"5) fzFÞM08—Úù‡ÜAÍ+û|:ºx›¤±I·q¥†6N¨BLͶñ6ZÞ e>=Ú,Œ˜Ø&&A Þ3 üZêkÀmî\²ò¡ÈÓ1yòÔ2ÅÂ5ZᛩHZ[SX<—[â4»üÚ¾) ×”…+[»l¥«V˜  _µ0¬«¶µ¯Ñ²¥)dCüárÕ‚Fó¶B ÃÁ3È‚¸”z ÍeºKNù¸-¶µ)蜶˜Ù²Ù Í6sÍ–+,wYAe㸾¯aÈóé†!á[Ûˆ³hþbÁ8ž*’aÑ3 çLl„ŸCçlô¾ç´8vâ‚coÊÏ(„{tZI$â…ÀÛ …€jﵞ©Pd w§7Î݉À¨u¢æ‘ð.¶18Aôìé'ú°5ÇU:" ­“ÀQx”yzÈ岞 ÏÎhö0›ÜÒÞ(=ÚE{†<CXäqý&FÙàQGVqÞYͽV«4Ü¡s7°·%¸3t·µq¬!°vªq³Éc*/õ ^.f'œ[³žµ1‹ÖÐ¥-¯‡‚Z)?®m0hª3Åà-ÀÓb[zfê}ÝL„ 9Ö1Hs9wu6²DÌ0"űþ6€£‡µl8SýMÔT×¹¿Å(ɤ¤¹¯ô9i™Ifž™¤´l#ýE3IT¡™If’ŽÅ`‰g&x5Ek{f’þƃ±ó$Ì{f‚qÞÀ ¥>5Oä_ëTΠ¸H2tå]Ð_dÖ›6xƳ‘”R¸ŸØQá÷ü4êä¹g²szš4‰vsFK› WÌæ\ª/Ñdv¤6ó#„b R6“Áý•à¯ÏXï¬ÌGéØG›®€¯ª««ÏE£¢xR샧™×]Sϸß,tMWm×äe_̰Èþìhço“úpKÔt­ý¹‚1DFQ5ŽÍBÇjWÝ®uõ+œüâÚàeº¦våÖ¤8O-6¦’"ßê%îk°Áî±¶2ýƒPݘâä©-8³vÁKÞ4¹Öü)^7 I¤2¿å:£øÐܵô·Qd³žˆÛéŸ žEÈ2”úý˜_<ˆ›{™My¸:o=Цܿ{«ìã8=ß?Ùƒ®½{éç¶nš¢=Úò£Ì\XM3{·ãÀJ¬Ü \-4Š210SÞ\p»a s£ ”è-¿±ÿÛ=*"µƒ¯“f³;ÀÒÿüí£ ²7 endstream endobj 317 0 obj <> stream xÚ¥XY“ÛD~çWø™Ä³šCW¨<ÀB¨…% 牥RcK^‹•%£#ÉRüxº§gtx•uïViŽžîžî¯iñç‚/|øã‹HÀ¿¿Øß®¯Ô‚û,ñ“ÅzÛ+œ„‹uú›×´ºÍY¹‘×._ÿÄ<Q>ƒ¹OÄÒ·$c~ÂgRXŠ­.Šf¹1pÛg8ˆ½ºêÚ¼Ìæ˜G s'ïŠã»¢Ò黃nëü㌜8` ·ÔÏuzöù5ß“H<ßмÜU5°Ê«’vuuèk¬jí¾ÎìP×µFV½2`!XJ² 0"s²Qµ\I)èvRJïXW›";àDyÕf¹ ïlÛ2ƃΠ¸Ä,†Ëë ¹| r0B/Õ­¦ÑÞ(ñ~)bϼ êçeà"3EW…^›ÕYJLrZ¨hfõ Çz…c½žãJäé2%~p ÎÀVöXþ,0 Á4|±š ØV©ˆI9¶-aE=‰•@±@ÀÒä‡c‘Í%”#”„Á% #oè©ñ‘xi¿Çݬ¦e´¤y’N‰ç™ÕCÖî+ã‘ÔrÏK"«êtÊNV±žpŒ½ë7´o}DPYqá GfYïQW™ vIâÝú\•©ÝÑ%-VÇ6?è‚& ¸#èIj—[ð³;WXÚ:+²÷K@‡¶¾†Õh?H¶ÑƆ÷tz ‰½èð>þø&çcmŒ#“ðÂyàEœùîÄ xÂbKPmZ—Æã>yÜ÷¶ÕáØµ?8£»_íhÙ:Ë«Ž@ 7%$”®Ü¢yABFžœDP3wÈŒ‹þ*rî*ãî.ÏñX© b0»‘Á¼Q">± Þcb Èk½5Ðd’“9àÙ´u·m»†s ƒüUçüÝ£[`Ut‡²¹]›ˆIàI5Àïh¢§2æF&V\B5q²Ñ ° ð0ú¯9€òð®ê(¥IȘ˜ÇiÜçé>ë§(Er>óE²wY8Ÿõ"W1?Ôyk"ø¶NÀªbªHcÒ¸?Ђ2eªëÔžìZð[B •ƒÂÇÚ…c‡Ñ Ö=hêM ÊWÕ½µ£?R%‹üÞf)¬l»ª(¨H5/̉ï×ÔCpµˆ¡m]A'_a&Êó_,W<ˆÀ×ïñ‚¼—vÍg¾ûeÏ|ß®BžÉts†7o=ÿvÙ'0v0-žåÆþ€¡øß¢©uºy³¾úù›k¤QÞ¯7×o×W7¯éÄ«›·¯¿s'g‰0'þ"Ú—DAôƒF_Óì#ï5Áíõ›b²†, ÃÈmÊÉæ\‹öì¯ò ÀÃ2–X$nÑ©`~þ“$}Ds! ˜ ¦-¡ŠÅ ã‰2]^Ê| å©ÍÞae9ßÂ'”¹ƒÏŠ7%Å÷z²CU?P\H!YŒ.LèDp…Öu[ òsû¿>v$˜ 0Øà>”) Î$CHrðÝ%äâ¼ÈË»OûPû KEÞ×o~¢ÑÑiLâwf[ʆv[w * Ì Ð‰ì3mº\Ŷ¢˜õ‰àŠq>8åžíg”ŠÉpð… øØ¨I³¯º"%i¶­¥‰IWPRBOç–¢7Y´Üöf±ÔÔ¡‡Š©IE¸$—ÜB/F£ËgÏ rŸîjmýÔ5Ä Ö­ñ`ôÍ›+Úµèl>Q(®v˜WÝ+€ƒalhLókд€%!3=9Ÿf;Ý-Ml¶ÞRë5ç /&ÎÎ]S_ÄØE^n‹.ÍæãKìÏ5Ò=™3õó˜W`épÒb€GÔV*aª \ÅÇ~`çÌÒ˜¸'¹2C-Tà5ö$¥!©\\aöQcÛM“Kz >Thµf[ç $Ezš¦ÁÉé8ÌÛ½ÕÃñÿáõ[:sù¸[µJÖ'õ/zÔ—AÓ Åž`ñ%¥ß»í–+ûlÌ=ØvÆ1+ÎÄ)´f.–œsÑ— ]1OAcPV*íBN¹zÈádÈrÔΪ@ ”CÓ†y#5 1ò²fOKFÚJ"iyKOöHçàapu ÊøÈð$ Æû’@YÚ×íéë­t¡î<åv!tïö³6L‹\ ¬®æók$Ø¡SPgi³‰…äyT(Å]kôW»ªºØèú]¹‚Äô¡ûßqc›`z…{ ›mu“XÌ¥‡®\ 0hú/ Ž‹yšjšjfë§+„ŠYÿ•ˆ¯f‡Ô»÷§ ¤Jóþ@J[ ¯óòþ_•G?vÞO ÑÝÔ‹Ë&;â¦V„žøô=y-°kO€ G=£NÀ‡¯دËÊÒMie=4Ðb5$Œjdhj¤yMw´oHuk©÷š>ö1Ý Ï¬îæã­†"d*œÓ CZFmc4y¾Kö-©é1‚¯€“–Ç™q~ÄâSû4sP€·VáÃl{E˜à§ÅV¸|„ƒÞ‡zó)'Pã KSÚîõéÎp8[a¡cïa:ª° z®õ‡7t|ïüAîIq5WX})¥J $QŸçE[\Ñ36;B‹to“ÖIe¾XªQeòè¤;zTYñS%‰®¦_'¡§¾ÃÏ+-Ù2;ƒ•ó93ˆ¡ýžM™}>¡ôX ¦Üøð™Uu¥¸ýL…Ê8êÑ„S6¹+›<¦²9>8”MOq„eÓ}üÁÍ“oT‘èl²“²‰RÛ‰±¦ïU1âb*2WŽô—/þ³%0 endstream endobj 322 0 obj <> stream xÚ•TËŽ›0Ý÷+¼è¤±ƒÍ£»©Ú©E;Ê®íÂ! f€(3_›kSÒFmGAá^Î}@Oˆ¢Èü(J™¹"T´èýmî8¢É£mÆÖIÐvÿ-+}jö!Žã8Ø…˜e§•{g;²48wàNÚÝ+‡7uw Y¨Áú̃>•UøcûÉt¦éª5£ Is3m\Èz8*Hät?Õº».=€¡žeÛ7êÝœüq û]t¡)¡Â,'<Ÿ ½ ±`"(‹ ü°9h½ÙÉaS6ýsB ã\›h×XØÛí•q1%Œ›ÿŒˆxnõAõ†Å4PݾîJ Dwp/t÷=¢¼< Ò.æÀƒgMÑËÂÒ} …d9?¤3ÇK=Yʺ'@ÎõTýVáþáËg°šz7ÈáœVÚº/6¨§S=¨y%lHÏí1bżlÌ*œº*µÍQ°$ êÎ>gÁ¹ªçQ++ä¨0“xsÉ×ËÍÆ/r³€lF ÏZ+áÙøI/Õý\^xv0‘ƒF,òßÉ"B¯JäoB(ÛþUš¸ ³8ðòmõàÞ›½šdÝŒàH`CŸ&ð¯h…»cq œå=ä˱Ç×$d¨W®ïmßóF¢Ïž!øj<Þ;c(ÿünð(%±@8ÏH‹Ýþʶ‰×rŒ´ «œ?b©^Ó›§$¹èMyüïî '[g‘ E¬cˬúqÂ3¨/|è×7?T¥Z4 endstream endobj 325 0 obj <> stream xÚVKoã6¾÷WèEÖªHêYv‹í"í¶­omŒMÇBôpIiSÿû΋~$APĈ†ÃápføÍG&ÿ$*ÉáO%µ†_žl‡äÃ&ùîg•è<«*“lö0½nqlv¦?ìqv~µ6U•êÕß›_ÀºJt‘ÕM-Ö% Z²þ`C·eÛ÷_îP¨Óß§eîFhíÇ ï×$ªÈLQ‰7™ÖäBgjµVJé'7:o{ðR—évW&O¿®ŒJ݈ÿçno*“(•µe½šFÑ«ø-ÓÏݽ·þÄ~Îî =ΫHTžµy‹ëU™µø(³²!ï{¥€?}þò+JšsDÕÎΖUóJ×éé¸ZÃr&w,øX Zd½cõÎý•«btbÕâêàØPb$%ZöNâUõUÀPͬÑ7ûгÃ+i({%FÙj]›6½›Ùu8LK¿ã-ï!&å}Ö¦­3¥“µ2YÉåìÆm¿ì0`S–°)«Ôb…PÓâ·Že8ðàéð€ÊxáĈKŠ*(é;Ö¹ àYÞuÞmçþÄ£I´Ýx«ŸPàñ¦AœOä3ɯsˆU5ÆÄª’l1VS¤û©ï' ö)| ³ëª+(M%ÊÛLqÇ|+ÅY­KÛ|?¾ TS˜Ì\€ª¨½§T¦€¡¾þPïö˜w}®@s.o#] ‚@‘;7C/s°ëè¦%ð»Á#ŸŒS˜‰uÀ`p!؇h>Oò¥PPp~èFâô†})ó#û³÷ãäòéfÁ,ô%*(VöZ˜g &ˆ‰@u•Þ‰v€8ã¼ÝBÈ ·6PÄ Î‡N${FoB¹€>tì¶?Ýì4 4Hq>Œ å¯+hä©ÛEðÜôÀˆËà<·.š”ÛÓÑçQtÓ¿mêݼxHF—9ð1QÜÎÌRÕéæ@¾œž®˜ÐnòÔd¸3ÀïÑ;ªB‡ÐfÙ×Ûp ,ÈK‹ËoJË‹)ažÆz‘Ö%‰&}ÄnÖÂMÐÖÜwÜé×l„&Þ±IX‘ùo;²”¾‘ipî‰w¼ðži?EOpÄ= XK‚Ä]óñBÈ(‡Ø MVÊãadÓètœó Þ vŽ¡¤Çn;<,ÓjcϪ3yÐ(.Y¸kqÉHpo 39h""ÏþôMÿÃPú¤sÿ7&¢ïõÞæ~©žBÕ^õK §z·ÇrÖ50°çy÷¯Ð;Q‹Ÿö¹ŸæœÅÚÖ ‚RΠŠLªÈ„/PDG®s€½Åôt¼æQÚûi`ÉŽüíÆã2³x¾M`1sŒ&Ž¡ÛîÆ CŽV_!IÉQÇÇJ0êÆã·Æä‰¿Ñ'CŒ^¦Aaä¨MÜ „%,Vzä Ñb÷œ"ê…U MgÇÀj†).>"C L wKöæÝWª*»\}F®¾ÍAªw_°{7ã‹ïôöíW“— ½šf¨½õø )UÊŒãa§1vœ×hø5ª.ÈFíõF-l¡äåÍøJ,ð„Ö¥XÌ’úÃXâ—`IhðÂdŸ^ £o„MxÀÝJÑÜ_Ú¨¬¾>ܸŸ»5oÎÔ¥cW„Ûs¸ \7èd]ü‚PU4ýí›ÿAŠ endstream endobj 330 0 obj <> stream xÚ•XKÛ6¾÷Wø(§kF¤¨W‹R  ҦŶõ- ­Äµ•Ê¢+ʉSäÇw†Cê‘(±ƒ]@4‡œÎã›!Wÿ®ø*„?¾Jü‡«ò¸úq»zú3Vœ³<ŽWÛG oxÈòdµ­^‚q&×ÎE<ëºbñàýz¥2¨ÛJ]êv¿~½ýxÈî sdÁc–ËÕFÄ,N-›ßuw,šwF2€âàùËû_iôìþÑ:}îëVš6}Ñõ4,PºHÇcn=vúHËø}[íöy’ BšØêRª“#÷ETsZoD¨²¶Šâ¡6îèUGKÔÅ»®7DØÏþ.õ—¤nU»I`NTx ôãÔ¥=ð®['OÛeÑ׺5ÞzéÄ:áô¤—Wüõ‚…`9w&¼[b’°$õŽ}%>Çbà| %h+ltˆ(¶àë28 ÎbŒbJ„‚… X:cqd÷n×Y >pv\Ö÷º®hj„ ‘€ƒ»NwÆQzš« }Ú¸™RÛF°£­1b² w"Úêãåjêâ¡Qô«×ô­TÙŸ<¸Á˜ V‹rÀKñ…¼ÎXâMV¸S<ê¼ß™ï쎟¶Ò§œyŠþ—LH»¿Òg«r ¸Áúmûúû¿q0·Í(Œí‚£3C9ÿõå¿NŘ³è Ÿ\H»YŽ1¢ ŸO\ˆò}JTµÜpÖ;š1õJ?Ýz·¾QÊ5#½h <U4 ­ýi‹ ‡tªª ‘C[>nÜ®çpÍǪMe3“LFS+ZÅpñ}.¾ÃT+0ÃÞc&³Y„d+ˆØH&_E±(w}‰°]‰ î; ÞßƓ'Qð°ÿ mIÎ"rÔ3Ûˆ@¹“@†RáÁ´›ÎVa½«­?ad4}1²À²$/Ÿ: z‡º5Ø×ëšA\<¼Q8µ¨j’a¦Ž8œ&Á»C]¢¤rí4+èsêô¾+ŽDC3Ä ™ÁRm€@d½HµP-Å'e"únßœþî Zʜɑ|™_÷^òVs°èÔ c‘è³€8A›W—ÐY9xyyOâáæ·÷ž9´„m©\=ˆ@K>+‡BWO*–ûZ{ã}e*H¹ªèú¦ïÎeîœl‡ý•ïTgå3 ª¨lïÄ]Èe³¨Ÿà9 å¨à?ì° ^”²<ŸÔ„¯ÜHF>ú÷'U©GŽöH4Ì3ûµ\00l'þ²Sr> KC3» fàËM’…c/-6„‘‚f\2—Œ‹ëþŒC¨/´j"»5‰±5åÌ*[åˆmEÄcÑ{?[·×äÀ<™æô¨-u6`éÁa(Žm4à€ Gzd2ÞÀ0ÄÈ––BE=šÚÕ»c4PÍAŸ›Š­"¼ïè'tP4(lgcUpI9â¢2@g>-~Öæâ³6‡ìãò&“KßSN2Wu¶öÞ¼0=& yqV·´; F*uþÚc6wR„q Š'꣈|Tqam;f°?Úb !dðd ºÃ±…~»ŽáæÚœé’hƒDJÄ%È: • ~Ì!& +5µé]Ž[@ä*cÒ»K1 ’ÚØ~³”eR V!‹éÊÿá³K]ýœ¬©<‘wwM\ ½ìÒ†¥…ñü5¢R¸TE7Ê×Uënã.õX¹Ä\…á¢tE—\²äÖsk‡ê7‘9o”>~À‰EÆ2ÿ‚#w/8³^É1‹ ½oyÂÙÏï‹C‘šw8Æö7(eIB¾¿$Ú+œª€ú¾Æ*½¯[L}‘çÐ<µFyfË.Z<Œ§-RJÝAáoú•¡½öF–ûKXžA‹ÔG¸{"‹³ÃpewŽá\t\ß­?à7Â’A“F¹,ü ÒÕwïàzlûó¹tû%oS͈¨ä™"F¸wi[ñl×ï¤öêkÄç‰Ì©øðªt¦Ø4LwÙG0)¥Ãµ1Z)eê¶lΕ2× Kø›Ì=ØÜ‚`q–b/xSnMÖvãõäî‚â|©á>ß¹Çp¨»½à†_›$Œñiî&%&kKÝœ­ÂÉIGºY iå*‘Ε©_úÇ7ÿ½,—V endstream endobj 337 0 obj <> stream xÚ½YM“ã¶½çWèHU­`@Ð>ÙUqjsˆ{n™8FâF$~xF©üøt£ÔP+íŵ[%‚l ÆëטÍ6É&†É&ãð?Þ”õæ§§Íw?‹M³<Î7O¯›|³Ã¶Ú<íÿýoû¯§¿nþüôÑ2‘,¡iû²ÝI}1åPý¾åYd¶»4M£×±7mó‰šE³¿9&yçšeÉcÞgÓ²mú¡+ª=èŠGu1tÕ;³ƒÄ0Õœ%©5þµE«·žÌpFvje{ëÆ¾ѱ@Xˆö Žî¡/jÿd²n_¯l^ÛÓ‰¼TÍÁ­|€é¼Œƒé¿¿¥Xž=Ù´íöUSœÈ— ÃXãìa[p3ºOwœjÁ9MûKžÈG{ªJç~ŠÐs”P„Ƴ‹PK¿\JúPt/ì\w¡÷‡®8ý8%~,º¢L×?oï­!‰9úQäN¶º¹œ)P~Þ¯1³n'-¨; ®XGíØìÍx>ÛWd~4Ø·ãËÉК]¼üG=ljx7ûVÈcÆÓW8Û:<˜®* " -!ø§Ñ¸4ð^Yì”!·Ùßxš±üÑ­™m{˜¯O)@AÛQ:÷st[$÷/ÝV&‘Ë¡Œcý²•1Lºw}C—Z2¥aìZtàJdqähÄ4{+*‡|îðSuæÕt¦)mZ£m7‘ ÚÙP¡#¶Ýi`EÇ8d3e*vOê*S{ú‚³ÁùR¦l™”v¢~~kœj YFKKâ`mB1¡ÜÚ~XY»`Z¸Ï|­¿ »ï¥¢ïñ'£Ÿ©õýÔ+Ò”i‹ØƒIç.Bô<“4ÖC‚_ìáÃà(ùÇE Y‹@̲|·£q[{å-Í™ôX\‹fDÓ×Ñ+žMÖ¦“ÓhÚ¥êAMÀ†qB­w´HU]EætÙj}"fpõNDåØAVÅwe)=ÏtANW‹pŠÛlGŸÊê¹kDk7*eÇ+x2ÑL3üvA"H|T§ÖH!ÓLËÒ$³˜S)¤‰"R OðrdŽq¢£óØW¶½Ai=Í…:§¾%»²hèq©ó5öäCÏ>Bâ±{• ÜÊ`«º¯Êš‡Bô´ÍVBˆՅă%HÔrý*¦<®ìÇ2œ´ž£b|¯NUúXa’ݪ€…ÚNVä f€ésân,‡±³á½ÙÙn<˜÷ó ´ Ù{åL¥a¨ WqGgÇÑ‘qPûÍXÙêkIç_ÿâºÃÇê•ǨÅv\h–’&KX2÷Ç®+½’X°ÏÉ æ\XPæ ÔÆ±Wr)ÎY–ùxùb0]5q""ŸÎAëÉ£S׳jÊÓ¸·É®‹Nº ‡|§ÛÀÄ®g6œÏ_‰ˆ$¦*+ÇÑ=å‹ÈŽ'œÉïNlj,o(ÌQ‘;E‹cŠÆôWgŸö±¾8ÌYé|èîæîßXK@o"œål{3:.ëuõó-¶ö]·Ég’•<íÑí?OPÁ9Îa>ø½XK^ð¦¼þðuf–/´ Ïy Í±e}A囵9v±â|ªäély5ÞdÛ´ÍÎÚûd’ŠÉ…^€8غ ’y)¶UÛ+ü 5æã54о¯­nÐ2€E„ÀC®ïâ Í„V3áÃW‹,ëÁ¹íÚ·µëûãß?SŸÎ Vì]¨³¿µƒ™ö4(§Å0ÉžÞ ŸyUÚrñád/i <¾^œÜñ{´wµ¼Ùwc O%{ÆS»°y;·üPl•-dGïQ¸§3¼÷Iw‘\í?.ÇKù¦¾U¿«l.¸a6S²,Ì”,ÿ*vá<&®NUxT½u~\Mw箪íy+ÓÎÅÒÞÆ}elÐÒS•ÚwG– “Á­iª’ÅÑKzHéþjfn0 è ”¸¸Í«êóɼcFYŒÄ¶Xý>]öC»%õ{õ‡ê)öb)V ±gó8{{Û%ìÖºî.šèÖL=Ž‹ ¢ˆqfŸ`îºÞâTÎ5®l§ÜríMÿñ§ÿ×ÄkT endstream endobj 340 0 obj <> stream xÚ¥XKÛ6¾÷Wø(1#>ôê±E¤H‹pOu´,ﲑ%W’“MÐßÎP¯w7i‘¦Èápæ›÷®þ^ÉU ÿä*Sð?^•§ÕÛÕë7f%cQÄÅj{„ã ~¤«íáho{W®7Z%QßÖ—Áµ ~¥‘ëé÷Xž®^ág¹f±‘EmGt—æPíbišê ÖcT´½¯èèp±5­úÁ—žŸ»o×°õ‰?¢†}{â{ÇÀÛ^ó!©ÿÜþì•Ñ"I¼2Aád" ǹH´?Fðàõ›b‡2B&À)޶ÚÎ}±„Cë¨=Ò¯—/‰M´_'2‚÷{Ú?Ù¡sÌw³LµÈ˜/›B‚€¨®ÂKÕ¿êz¢“]T»k@ö–°Ò¤¢(˜ë»ßo=kDÔÙ,ôÙ­éÔŸŽN‘é9å¥ëª…ð”ïiÉ Ã:YG£ÓÆï|&B²(l>âÖµøñ‰>lÃwK°Þ©¡59JÕïÖàL‰IØ™àäÊDÈ$Ë"¸pxìA$“é¨w§s]=l@|fÐg>z´»ž6¼<¸ #œºúéT€{êò*‘ Uwrªþš°²]‰”÷ MoïÓ@4 —Žél]2ýc5ç´tŒc iuU{ÜÉ}qÍî„Gu»¢ôD»ö8x)u|(NízÌMXz@{:ÙQì!yõ`3ˆv“Ê9RÈ6wãÓžó üñ‘òšI&”1dµp’$Ñ_U98‘ÎKk¦0øy‚ÑYôv 2[÷mXÕS*‘&:Ãý¬‚1å…C"òFXÐiÛO)Ȥ±õgrrøbp90ÓÌP”´§3äÿ‚Öþ“x7l%d¦•8$ Àj솼k9™ÂºJŠ^¥/ó\úÒB‡x‡ÔG”ÐÑ9¦„Ž6-ñE„ô…ý­ì¡ ¡TÈZMY_è,2w"¬Œ,8DdÎW× úïÅû>û$û`¾sypµ³ÝgÞ,ú¡»”ÀÈ'#™‚Âr3°ótqbDÉ8 "C i J«®*gA‚;í~°ŽR|…ŠËe½øiKµRê•”D“P,³LÄT-•PB¯7RBzÛ¬µÄ˜wm·Ãk@×Á^쳜ú»SÅ7&óªD$ÙsæU"NF{Œ¯%þ±+f…ßøØÍ‡â\hæP¶„ ÀHªë¹ßµÀPu!W«¢˜9~±gìã˜èºqùÑQF|Ùwð–·R`¶a;C%Sź†a×øåí{tdtù?]À„$ÎIþ‚ÍÓYN½ªå«#ÅC"cŒ#âëAöU£÷=œáBåQ"U¸ˆ¾láþûBs)6(7Ø=†0úçIÒÅD;v ÔÅãÕ ïhô$ùuïÌhGÍgíïÒÉÛ^x\ËàÆ/?>Ñ>ñøJ"ÆòSˆD½PBƒXú\O8Ž·Ü%iH2¡¡ƒJrT§ÕFÅlLñJAt¢?ÉâbCx¶ˆ!ßx3ëû¥Æ¤sç{ <ñÕàñ{xƒ²E }o¾hQ9•!¯<º´—þÛº~ªlT©œ[¿hXy W‘‰B.¢ Öj ÅØëÐðlçlÑ2"'¡œ¦¡ŒZ؇n.wtféîœÉè,K/@%Ìt*´šcÆ 'Ö…|UåÉŽœ~5mz¤Ýš/QÂÐËqïÛp—KܯúêFÅÃ|¼_isCæÓ|íÑ‘Ðqº¿˜ß”ri‰˜{<+’5ȧ¹ÀÀ _`` ·.jl]ðÛ%G_•ó[œ4´8êªÅa`ÍKñ¯íP…éÛ<÷óü_ˆDg^OØ!®j6YÌæöiDÄ1Q+¶ô0ö¡s80ÙÐòoý§†™,þ„x÷ž±f]F¨»ª¶~†aO5$¾\õ¡ðcZO yW[ö{ERÍ»u{>×®´Szýï:{zÔ§i×[GVr}~ó]Å'aðhÚ6¦é ½U¦)&l9Õe€—MÌòH¿ãä3¡ÄôÞòÀ´§© „9öðê °;biûjb*‰ÄÙ9$‰[UQ©ÙnR.ü²¤¿}÷/òì § endstream endobj 343 0 obj <> stream xÚíVMÛ6½÷W=ÉÅš¿ôÞŠ6@‹ H÷T,Ó¶¶ä•äl ôÇwÈ¡$jWk%䨀8ÔÌ›á#ç‰ä0‘˜Ã?$ù‰ü´"¯^'„I*dDV;x½d!Ma¼ý+àT,–Œq¼­«ÍQŸK« ¯uÖå­¬ÜâàTÁ“Ûbwí_ÖÕ˜¤ë§ª÷ö9œ¡Ö YíÞÚ/(‚‡·$Z¬<-e* |¦’Èà†˜6à̶9äÚMOéÍæz2æÆvRu„æ(‚AÍqâ@_HÌ#*™sY Ñ/gÌmUl®N Fdu–ƒÒ4ö€ÀktcVll˃AãQÏ7®çób2i5Dø'kªßŸÿëÎäQNÔxœ¡’“6¢7±zèÇHÎ/¾#½h&)„mIÇï¾yóHì\ª+ì?3h6m w§;c$Cõƒ´ƒjØèݳÒÍýS4îF–ÝòÈny„[n§];›¹]÷!ctD>fŠoóý’¾ `’÷ò*æåm5ÆŒ° nè*‚:¹¼:¸8P{!ãÁýÄÝPQÞC³0¥|ÛóqàŸ­¦ÞõZZ°À…ï.enè¶Ìºþ‡ÌJˆì™­6÷_¥ÊªäæEnñ•íV2uÙÒä3…>|óÓ4>¬’ÏÊLÂG«bÔXÈbÅS¥NcabBcÁÝOcœ„tt¯nÅn!ØèÞÉ2m¿ë.ZEø›4 Òüdó"Ü<ÞoÞX¢G‹ä‰A[F‡ë»ïþä¤f endstream endobj 346 0 obj <> stream xÚÍWÝoÛ6ß_!ìIj–ŸúXŸVl6¬A»úaÀ<ŠÍ$*lÉ•ä|ûãwÇ£dÚQâô!À&Ç;ïî÷£¢/‘ˆ8ü‰(“ðÏ£å&z;^¿*‚ÆDóKXŸ Ί4š¯þŽ%SL'3!¤‰¯ÖÛäŸùïÑ/óèKÄT‘G·‘)X®Ý†,6QªXž Óuô)ú8á`¯ät¶`8L™½áÜ0•Ÿ2¼Wò†›‹d–Êøóë‚&ó‚Lž´hy«ªMf*Óñ¿øc\$n°ˆ—‰âñuY_ÙEB:Ͷ¯6Õײ¯šš´`»]î§ .Lyåûú]¡^ ãÙàYf2çùÓ}Ýl»ªB£Ó†›DÆl1†qÚrÓT«df(“çpÔóæâó9œaáÛ¯ —øðŠUÝÓ•’7“'#/"gF9/?ÛnÙV[éëðP†:TŸ_Ûd&ó,n›]_ÕÖï9ˆŠŒK¨KÔ?:ú„‹´µ×Íͧ.!2¥„t˜öƒóÃÔ $H N}jhW̲d¦e/­;û½7sI¿h6)«Ö¯GcâÏhù&‘Y î•Rñå®v¾\¥À¼ìè·Û¢½Ø.+ð¯íФÈ=Ž%E€ÂmÙ–ÛÛvê¥JYnüLßå‘4~œ²1“*g0 r÷ëÎßÿv6aM+–)omcËÚdz©êñšßL:¡Ç>~úë|”w£FY€úI³Ðè">kzqýuÙ÷šÑ½ªxe/ËݺT†K†YÛ Nt\MÅ ƒ y ¬…az¬æÈ ;d­4?…­{?åjõ\S&ÒÀvÁ™(NÚ´¼í¶A»í0ºAmoi€jbTë’î/&©•ëŒ)”ñ®þòoƒ?©Š2G4C Sž·Ímwûê¶{IìS9 ûRð½Ç¾áÜö3Éò¡…A­›D‚”ñ¡i ° +ˆwЀÄAK¸ÄÁ)B›ºëÛ²ªQÜ;Å—Ñ\ø>ÁnÁò>á0   ÔhžA¹h‘óˆ›Á9R—-ºj)×·(/ðuï%îüÁ²;V:`$líW§V¼’®«®…e ›hÚUU—k’ÖÄ» º‡hÎ[ rïÀVU_x9£n¨æyòU[­ÅTÏ[ë k¡† qhKÚI3ׂ8Ä "—û­«¾*×ë{š^¶ÖâHC¦w.ÅU³«Á<&Ûùª½§ë²#m»Ùö:µ ë# ¼Tp·‡‚ÃúñÙöqí#oè.¡tÒee}­±‰äáuüiû][wÏsèâÉ7GÎä3ÛN0=pkëHÅýëÜŒEƒRÏaÑЂ{<€6möN‹w‰R—I”Ž™D©O¼óÖmÚnYt¼EØ“œ¥%g©9+=ÍY¸C‹=gùù Î ü<ÁY£mO 'lZÞö²YwÄ9ò¨ì6µ×zœ®ä ЕN5ƒ³IºÂ“?ƒ®–/JW˜ü)º’LÓ•»ñ‰¾/Kuš®Ì@iØ4]å…×ó†‡\Ä5»%ô#vJn£u«òè¸K+j\$Œ‚µã®,ä.”4“äœqñh3ÁCF86›©" Š©0óAú€º 3RWá‹®ð(( ê‰cÔ¸¶¡}zæÒBs…öÌÒ êFû¸(`1¥‚€ðK¥õOc$1÷,~>qi1 q¥Ž¸4÷Ä¥åª8ÞYÈ[ Æ<Ý‘àÿž„_mÛxIí=a$$,ðå Km£&ƒóþÿ!,ÍóÅ4vçßz#c¡yŠ›Œ…“IÆrZ—GÛFÆrÛ\ a0¦T‡„ƒØu/‚eÃY^lð¹¥ç«49nž¥špWŠAõãwÿ†tàq endstream endobj 349 0 obj <> stream xÚåYÛŽÛF}߯à#•uØ7^ryñ:l`díÍ$%qfhP¤LR Øßª¾Í™–¨qŒA`ÛÕUÕ§ªOU·ƒ÷ "øCƒ„Áß(Øì‚7Á—×””’LÊàæ¾/iD²8¸Ùþ2ÂI²XRÊdxWí¿ßü|w¼ÏÒà!I…šÄÁ.ˆ9IûZ?o<F!c¤+ú'ŠSJ¸§’ðtNñ(d·Í‚GáÃå4JHâh§ #™UïHýu¾+KžÈðú‘w]yWëß«pƒÖïóú®X-pL(‡(8¤^ÔltíËë$@¥Q†f–Ö“D&ÊÎOǺÙweg¢}s'Ñ„P˜"%‰ô”M¹],¥Û[@ømÛ<¼E“+5²o›µþþÅë+ý£¬{óà lšº3C›û¼5âJÇâk¯çÚ šÉ•/‹nÓ–û¾lj#/\§%É„+~sp²p:ôemÑ™¬2.ã¤(ÿxi™$ŒqN›Èõã®ü°`qX`ÐXvÇÝ üÛTåÆç¥¡Vé »,&ÒH¬BªmöúÙ7øÌB&¥Ø  €p¾é‹¶SÉæAÌgœS[ã¥Ç²$‰ÅgÙß+¥‚D1@Í æ²Þ`3‘3ð0?|,«2o8Àà )¼-óu¥s„š[ý­WAâ"ì`9à|±)WÅVÆÄªŠ~Q9‡ïŠMO”'OBþoÔ i¥µ {€aW¾Å+Äbx[x:/‚I3#ñãϯ^Í(iZíX±Û÷ˆÙQ;ÜõmYß]™PYïmâêmÞþ×fìcÙÄVbÆ]ãj4ñ6ô¹`s$¬1ØÆZ2e‹Ç/S"ŠO/ x˜ÀŠW¯s?9GñF±eﳊ!­xÓTzg$æ£fÅ$ŽçT»RâÓèœ9ìÌ÷“ìnÌ »§Ïcwë’ô½ƒí éýÝ_ÞíÒþvôþî“é}ÈD árÕaÓÚ¼z.½'SzŸBïB­øã<½K’ÎàžTžgwFX:ÃîŽdwôËaw!ÙÈî"£ó»«†Ýñ7²»ØBbøÇO°{’Ùëõ‡³±>O÷ršgßgó|3h6¾yŸa|ÇÎÊt:ŸÑíHÝsý`ÀöÒ3\1cb]o» ùãz.kì׸ÁÃæ€fú{OxœÏ·Ô„úŸ 3"ˆÇàÁŽJí«»zׄ#$O‡Žkdâ4A> stream xÚ½XmÛDþί°øä@½õ¾ÛÐ~à(‡@•hé:åŹs•Ø©ãôzˆÏÌîÚ^_6É•VèN²³;;ï3;~¢wRø£‘fðŸF‹Mtq=½¤<¢”äRFW+ØOhJr]-ÿŒᄦ“„R&ã›õvò×ÕÏÑWÑ»ˆð<‹î"¥ˆTæ„VÑ&Ò)é­£7Ñ뀀žÆÉØíÛ,#©ØæŒPzŽï@ä/êõcšæ„Ë3¥vαö¨ïyµÜM®Eü>¤±Â¼LãÅ„§ñí¬º)¦Kšì7•ݟÃÆõ vO/u„|Ó%%(&‰ÔFÔ›ûªÞîÊŽšúäT’\À¡ŒHaˆß×år’ÈcÑbD€ñRLƒñJ’,ë~ú¶û":"‰9/N´Ç8Ó„æçwD=ãp¼`[ œišq–uOÕóÆxMƒ>¡ÒSœJ8Èϲï¨zöÛ¦ž[·õê‰})«Ö¾¼}¸ÐÞo ·¶¬÷óuaß×óÀâ~>|̧†ž^»ESnÛ²®ÜÎK~u "8SqSïÛ²*Bé%s’åÐ|w ¡¿†(]χäõeä’0G ”;Ëë¦v¦ ÐV¸Ž[Ü»ßNx¸¥Yµ´/àQ–¹J1 õ*X™€†bž h%‰î´JÚ[Ë©/HxŸÆ»¶Ù/Ú}3³ù—pEm“àëËj"ekòwäù9ÏR"O6n*å¼Süæ¿ÿ‹G^\üŸitÈ#DZå3úë…E’ÁÝ­æ_ˆwÏåçqÄ=ÏëöÍóOvÌeùÁsŸá$Œ+lÿp›`óEò»Û¢)BB§”Sºt7Ñ0o cË¡"&¹g»]mB·(gm§¯Éøý¹†ð Eéhfv"ÎncŒ?Ìü#’€±Á¨Œ/ÝÜ…ï·xµâKUÛ烫^¤éø48õãQp’}r¶¯æ9Y–7UÝK2I”Щ»×<¬+´&l4H wÎ"²›ezÚü”éÇ…ýSØ(G€å`ŠÈ¥1…K:HìÇ_$uGjG„³«ÍmX<˜È Ãê F¦1¿ÓÁ€ÙEçg‚q`Á~Wؾ›n>…=WÞÝ–ëâA1œT!χIö˜é¨ÌØàB£DžEýÔ¾(Êê? `(^Ú¶¯mOÖ}ßPoú‡U3ýK3ýÛ…b¶@›/*°c´€óeU¶ålm<ËCpP®ãòwÑÔÆã’s[Çáà Ë08I@»ê¢0jÖ¾£ Ð×ÅhB®–£ ³k ãÏ7X˜5.V)MÐá'?B=þDÏãOxDe=å~žF <1' ¨ž³ƒ—ΰö¨o ºb®¡Ž€<åK ô¼ê=㾨 œT¬,¸ô0ªSÈ~ÁnÑT–ä˜Z”ð!±þí‘Æ²[ÔÕ®ù;Pp›0Œ¥,†•bX}ÜG}Nãõžð\àÈwe衞¿½^ÔÅÊ9×Á\|(Åœ<¦Xៈ¥(} KQ)Ñú–ÒÆR”ƒ)J[0Eû`ŠR®Ù¨Ìï/îãÖ,ì0DÖ/fkÖ[vJIF?SQ¦š8L%qxŠ68’×3ÆS‹­˜î%âïì^UÜù£Íz_øÐKßýEØr $ã.É”æ‡&.uw»f§Åf ÛÅñHåDñÑÕªã/ %]Öš.Ù¤ wR ‡º^à<Š c/0{Óx:ÝÝ–«öK{,sÓ…g”‡„aÄ:p$1óÎ{[í«"9 »˜¹Î(án Þ‘¾þâ_‚ÆÇ endstream endobj 355 0 obj <> stream xÚí˜ÝoÛ6Àß÷WèÑbV?…½uk Ű­ÙËš PlµQa[®$Ç °?~wü(›–ӢÀaHSÔñîÈûàÏN>%4Iá&*ƒÿ4Yn’—×ɋה%”’\ˆäú=¼_Дä2¹^½›e„šÍ”fböa½›ß^ÿ”¼ºN>%„å:9$R!Í %“M¢RÒ?­“·É¯½Œ³Ñ–݉Z­IªµyF(½¤wrŠ7Å©bJÑù ™Òœäì’ê@Êénê9£³Ã|ÁŸý…ÂlÄ nfM¹[Ëòfn'P:õÒõ{;Ù=”v°¬·m×Õ…:+¾7ÕŸÆý¯U‚†Ó]Yx_2A„2¾¼}ÚÖ»¶jýf­ÿá"ªÕÉBô¬kí,$FÄ*R¢3§¿ŠØDyg݃ßÛÔûµSo7aL¬VÞ«t]ƒ„š- Ì®6ž…ßUV˜ñô6(Æ “.RP1Lh­RÚå?®bv2¨zá³,@ÕÅl@²dÚ‰á)Æ4e$õ ƒ•vÖWúªFNÊ‹¾òÀÂ_¹ÛÙ€âñ‰ÕUÇrý4×Ì¿?<” „‹§ù,uEX+4ÃëȪ¼I3-¨l8Ið,¢&£Dòˆ–t¬î+í;”¤ÔÇ«µ.›êÁ檩4YÛäÞ¡XÄ\¨ „†¹&\M´†Yио$®¢ú8‘Óû"Ü8f÷z—û¦)}Á7®^±«Ý›Ê)+‰UjV˜’wz°Êp²××÷³$ì MõìÕ¨˜¹³C[4'ISèÙ££¬VÎ5Û;åÎ:ŽåÐp…~‚Y…³Ûºs3k¨}°tÀ½”+ð€35û£„£4‚¾±(ãK Ã/Å„°ºÂY8½Ó »}²:úΪ´÷ÇÊNVÎQ<Übn3–¹~Òkíµ÷ãqßM±);P¤F4%ZŸÔH˜Yx+µVezuÎF´uæzè‡Uß«Înö¢Ž:Ë$ÀÝÐn.èY[ë\ßüÏßgEÜïŒd¾=üüû›71ƒÐc|õ“1—±v†õ§Øf—a—pÝÓ¶{œÆíÀÌo÷šK_PH9ÝSÈÝ+ï vZ{(æÔCý>“¸ûJ‡ñ¿Üœ«ÒÄ n^&î_…¸Å× nöÅÄÍ´œ"nI Í#È?5‘§P(GÈÆÈ36æZYäV!rãësÈ åà/½Ï@nTÕgœV6㎬‡íÚR6Dàap\šÖsDÜÜv(5îP<$nfoL'nŠßz66ׯGn¸m-rÃà¹A›÷ÈmÁÄŠäîou;>"nï‰[耸ñº÷Ä ãÊ-7Ä­ŸKÜâóˆÐkŒÚfÏQ¬àÏ"nš] îà6$î _/·øâ“ÄjOÜ,çgˆ›Å/·Ò—ˆ›ëËÄ-}Õmb}‡ §lˆ$÷Õ“‹¸5öŽr3q¹ÉóÉvÐgÀÂk²%%nèu“û€D`!q3×HŒZGÜÒ743>!n»³Ô±kg r e€Üð0Fn%²¹-梆¹3±?Ü<å÷q|è;O/óÔ1·™ÀÙ1·¹cn|?n-¨Ðé8Yj¾.2ËÜøÚ2w`U V=sãØOú?sÿ·™›+Þ÷ÌÍ/37.Ézä¶OÓÄY×ÅêDq½X Šó½¿ 9rª{d ØX‹SqOÀ‡‡zýE0ì<@ÖŸùã3ÄGDPݽ³/£ð¶œßâYÜ;pµ‘?VbqÑüÓTÌòI*¶Pgû!:'ÒWJ¶V¿ :O#ý+òÞ5Ucóã|ö‹‹¦)pÝS´<3Æð« ë+Eüw$>àMl¯DõÈ}YøDÏâ–F®v¬‰¨ÂŸŽ01FiÜ‘žÛ¶"- f膇t/—³—åûºq 0Õöƒ}èÕŽnq4ùv"¥ý u°î8‚ ÔGÞ»2ÝZ«–˜»ñÉ_«a©Ž;¨6Ç"¹ûA‚{Ñ_¿ùÞ ] endstream endobj 358 0 obj <> stream xÚå]sã¶ñ½¿‚TkáHâƒ`=}i›Î´“i“Æ}éÉsCKô™g‰tHêîœÉÏ. A ’ÚäÒ—Ž=Xî.ö‹èû(øK£<ƒÿ$Ú¢?ÞEoþ"¢4aERDwQ*Y!¢5.¨èn÷6þSÛôCWÖÍ*ËãaµÎ·-Œ:®6Iª¶uE[=î‰xWûê0_kiž*ü!Á©ˆåÐÕŸ7+šõOíq¿#è¢f7^h¶­º¨v´Zö (^öÕ`g›xu÷78aš{GYÂx‚ÀãÕåÛç{ åË!ÓL s²J°"Qq&¥ûðsqåˆöËî:”/tüØv[âƒ* ÷À¿2‡ç€F«8 !I5KžÛÕ:U*þ=9 ãì–†¦ Ðâ’é|<÷Z¤"þôTuUH¼`:½¢ž±bÔ[O20&Å‹"îZ´¥O8ÉãºÙUŸƒ¢ÖŠ¥NÖ.ÐÑçèlÛýñÐÐoKN&ã²ÙÍ„‹œ%Ü7“s*F²|F–Ç% à'*>ª®ÞâB\I0úý±¢):/0×u•ñD£ÐŒ«1ì„h¤L¨K±[1¥Æxra BÅ›6xdÁY¢ÆLpåÈÛ²!|“ÍÂä4?’áÓgS2øû¿¾þ:”w (¹¸LZýꎪ†”ãÙ ´åGc×iŽúBÀŒqˆ²ÒLÆï÷/î»ï#H¼:ú)Ť¢O”ŽQž°iº¾‹¾ И€,™íЧñSe†çiÂÏ<"i’3.¯’ñÁ,¡Ý„ÊsÿHÜ0, “‹ÍÀîÁ÷‡Š¦6 ñ„b@š0;=Xfo¡l$"ñÏÒ‡ã&“L3ß½6íK_zâqu~)ÏhA*–£€ ŒçH%˜ÝÜ—ÏÌà'(ÈÆF ŠSùë‚ ía/Œ%]ÃîAYì ÐÍtŽÃ ãBs²PÙž›PZÜ_؆Šà~³º )Â16ŠöÏU¿…js¨Û&ì¨sM˜”*¤„Bå8ÔM°RSλAaïŒ`ßë3ã´Ƙ‚Iç¥Æ‘g‰8u ‘²–XªOå@»uu Tƒó¼‰`”Ü„T‹äfÒv 4~V³éÎäaˆ<µ R¥ OÖ깘òïÙ°E‹)šÛØvPÛÁ"œPÉ9TÊ$"üz7×,sÉæ1¨ßæ©Ò›•Ý Ó$dÅT /K!Ì i¥[µꨩjÿºÒÂ䤰RHä™r(¡‹Øb#Nbò -SíÚ¬‘m"&¬¤Ž›ÐÙ@½&zjvB’s!)g†›$“át8Zj¤HÒl!G9“£Ô×i8 ³å%¤á³\ž” …o–î—*5ÝHÜúè¨Ig¹Ñ™2:à ÔŽ(¶ºãv8vPÀ½¢û˜ÏlYK³¹s"~Ô"îŒtæZ,fJÄ$§|%އšiQ`€þϵh% »\ù"þjQK[­KW+¯WT|â…wììvOã®=>Ð gÓ æŠ2[~©¬+& yÂÀ'ŇnÑŠ%îóû+ŸÛ òÐN—gîHâ ñB—y¶33!. s—SoïáÞ€ÂÆÇÙÞÀØ"ø/zæå÷fÐ,ùŸiÓ˜Um ¶´ÁCHäÀsœ©ÛÀ³E·Á',ùt½¸`^æøücÞ콤+¦ž…I©À¬uY™/\–Š®¯)œ‹”SÎ €fÜ¿® îñº"x{tp\~éjS¹À"^Æq©¤){ZpÓýüŸüLSQ¼Í¿›UÚ3J¦Ú ÈÞ%\}µoQëXøÃžIùTB-Š”E·À¦ZGP¯ayo£^<•V…ô/°ï§(V_§ÿ¬ ¥4¡²À hÉ(Š›ýÜÙÑx¿Fëª(Q,áÒ¾3k3ݧípÈ)k¼h`ß5³i%IB†®ñÊpÁÐùäè~Weé.[²_7^pßß2¨Gßœ© ý=Fu6è/(›Âp2šÖ6_º²y_ÝÚœ —4^fÈZ~÷ Õâ™&‰&œ¡…˜ZÞÿw Ús™Ñ±/÷Và††×š±·¢®÷Vð`ÛõVìôroÅ#Ó·Ýp‚ºø(0¡Æ»_q·e‘Aej©z³ŽI:vLŒåæ®lÌýÆ#öUè| ÅÒ?ÓAE>ë£ä,…ÛŽL¬ˆð›m½;)ï[›J6fá¥khû·ßœi Xœ¿¬é‹ ÈW…ß@ðø ÐÞõ!{¿x¿ÓT·ãH_­N;¿zìa™ý\µìVÇzOo8¯ «šj(\uá|‘/.)~õ²¯›gÓÂÞQtÙ×½K'ûGCAÕçz _]{ _ö9'…9_=}/É'£Å÷¥žFÓ'7˜Â#ëμe¦ß®l~ê·ãÎâe¢ ÎºG_¢!‰Øƒ™ >3B mI±mSÛíªŽõ¨ü¨ì·ÕøB¤½g-íR«}²£îÁô¦$zo[€øè> stream xÚÅYYÛ6~ï¯Ð£\¬ñI¡@Šv‹Adß’ ÐÚò® [r$9›úãËámÓö¶9Šà59‡ŸµÉÇ„&™ùGÅÌÿ,Yl’_n’g×”'”’"Ï“›•YŸÓŒ2¹Y¾MᄪٜR–§wëíìýÍŸÉo7ÉÇ„ðB'‰”$—VCÉd“¨ŒŒ£uò&yq0Ê8Ëj}dVk¢òÉlÁˆÒ—ìNBÎp×Î8MúÙœ+‘þ MÞª¡Â>d£Àªk78¿íÚÛuåííl.yúWµl˜Ï®U>²œÎW–“\Y¯o›vÛ×½ßêPE¨QÉs’¡Ê§¶^Îæ9ñᇮ}èßÙÄ‚k?¾ºÂNÝ ØiºÞM-Ú¦Ww›·ïßÍ~ŠEíB šä܆ðkÕ/ºz;ÔmãäEqN ŠßÜÃRfŽp7ÔMåtö¶™$×N î+b_1B…ÅõÞüŒ)̹ Qž蟧ýv67Õ¢~—QQ-qvJ ØóËmÉl.¸N_v˺)׸܀‡ÝfÆtz‹¶ºÞ)®l¨s*‘YNiˆ,géÐBË­ºN+à6 .Òþ¾Ý­—©íº\x¡ºÁ¹uk%%$£,ã òçi¦ï#‡ÊáÒ ]¡i³*6Ò®¢.Ñ:ð` ó!r¢Ù¾‡ûª‹âk¨7ÙËB¯Ù$òs ‡”äÞ]F0;¼ÈCd¾háv‹BŒ”öl.êæFyK†5‘ô€ ÛlDÈ0%2?$Ã̵1Aà ½Á»·\X‡\fÇüÁà€ 3>qaX÷EÚûâ8°$,,:þ‰žPµç˜ ‹ ó¯Î„%›Îõ;1áÅ×e‹¯Æ„…yL>"Ã\+Ͼ´È0Œ¦ô™Aœ ƒú>†™éÕÖ'pcW,L E.|ä2|¤0‚8¶ 4€3 ¨pQ ¶K#W§úW§´£ý›Ó XØÇÇvÆÇFŽ ZLfÊ~R`ÜÄHŽç¬Ð.%¬pZЙ1ެ]Û]a;•c îqÒòa»ê³„ ÂðTLJ3‰|„>l¦Ýq †å‰L¸È„÷62qceÊNý;>¸œU>Áuå¢8Gaþ~Œª3ùDõ.®Îž¨ÞGÕ)}¢ú«NÓoùSêž[íb• #\í“jÀ'hY±4HHƒLkIu‘!©6ãܵҵH®"’ëóIgRL/Ù‰¬ëï“õ>ÊËGÚ¾Ç˱–š÷Î@òó–‘32u12u3LÝtUÈË™«0Ð K;€JÍÏ—_àÕì ¨ï¢¨÷i¹Ùs@ËÍÞ–³Žìñ·M¦H¶÷¥º·ô‰<]˜×Ú0Б¨—‰:¨äÅÈÔÝð> stream xÚTËnÛ0¼÷+x”ŠˆáC¤$ôV´9ôÔ ¾5E Èt¬B–I‰ _.—zØQ"°¾†;CíîG ³?NaÿŒ;òyE.¯¸$œÓL)²ÚØóˆ3ši²Zÿ•T°0â\¨à¡Ú‡?WßÈ×y$Tf)9­©ÒîF¢ÉŽ$ŒŽ«ŠÜë‚ã9L›wæU`Î8e|ŠÌ™¢L½{†òÑ÷msF2‰ƒ?0(Oç¦pV™.¦eðË=nMJô§ðò*!›eÀ tBQ•8º›—ºÙwe7¼%Î/ñ„ò”DÊÞÄ+ÏM¹#…øÎÉ»e·núáôã÷ÛðÓ¢ ŒÈSª¤‹øÅtE[îûÒ¾ññ\€¢Y<‡¯¶Ò mžú²6þΑjS‘ÙÚü±Ì†Ô1°)»Æï"ø´B»O Û°™ÍÆlBuû0²ƒ)Ê[Æc³ÆÝ1i°pßF»¤Q[¥L²é5f9m·EjqI¡J¬¨KrœÆŽÆ~ks†;žµÍÝ÷s{Ù““.ßùYîJHMQ§ :•/.€BxñSµ†¥ î‘ÁkS™Þ¬qq(ûí ù™41|e<æ cý3QåÜ'*¯-£ÈO 3­ÉØÎksÀJòPœœ‘Ä3Fe:+Œz®vI¶_âkêê5šß…ÙûDK­h<Ï3fPJioæý0ƒî—6A6€ÍAéK±…]ôÍ)l4 »{”G8mÍ./ëOŸCe¿SU®éqûŸÚ«­Ç,™ü•ÿ‡¿Ú1I&ƒÅå;Ñ`,x¬¦BÍ¢s›ÛæoÅŸÃ<Ã+›õ”ç}vÉÌ|ìwXª° =uÖï1ÕøÝ¦ÛZ9gª‚깩žoVÛGiâшì!Ça2¥æ…z®¡ƒÃ¶,ÀtÀMÔà&p-o­™Aý/(RQ1X¹/Ï“‡k ˜uTô'j.°;cÁ)×sƒÚ´Æ”õ6O^UG'ƒÙ5í ö™=mœGèH8¶jÙ!jöêãœ+"ˆtœb&ôúÃ_Y WÚ endstream endobj 367 0 obj <> stream xÚ½—m›FÇß÷S ¾‚*Þ°ÀÒ¼j¥¦ºF—Ä•*Õ•Åù8›ÓÀqSõÃgf`Áœ¹FÑé¬fgÿ3ììþØõ>xÔ áz ƒ_èmöÞKïåkéQA¸ˆ½å4/hHR¸¿ýËgD J™ð¯ëêæ!ß žD~·u‘,Ê­y®ŽmQæMð÷ò7ï§¥¥Ü£”¤QdTEHâÔªªt#ûp°½>x„§Ò;yQJ¤PDêí½˜™ØÇï½÷v"@ïd‚lóöLX2’$½°Œ‰œÓí|ŒìÆáL—Âð¹Â”J"霴ãeÄËlŸãˆ ÿ¿Á@<ôMÃÁ­ƒòÇd^¾N<¬Z˜¢ðÂ*³ˆDR)¿ÿTV‡¦UÈíDBáM¥ ºÇ¦*›6XDP£Í.«õÝwP®5ŒìÓXcøVP=ëUðj2'­™E\x—·ÇºlŒ¯pS‰H*\×åÞžñÔN4Óg”4…y¦j?Îr"Hš¨ö¯M**Fú¸H¿*Ê€%~›×º±­tkVêk×\fÚãæ¸ )Ïëð¥þiWlÐe§[aTU‡¬°ášO{´ÀðÁÿê¼1W.NR(!ågK?98÷«;}mwÊÐM ,„þ/ žH¦ܪd8g~ñHGmÝe¾)+Ýš5M±-ó[c…ø/Fým=”µtPÁR¨í7\]M„1|aíB.’„Æ)éøDØ2ÕÍýsCFŠ‹‘øeBÆ&9Åø,ˆ3Æ@ˆL_&VÅt*õ›ãž1’“ŠcÀÄðŒ18YÄcÀËYû"¦„V½ð1g¬Dl§2íq7uŠøc(‚…"T(FcÅÄŒà¥fÅ(0¸y&†Qør¡ûZ†Wüɼ‚Â…é×§Œ„=¯ø<¯8ô—q,óEiå"Rx>Lq]ÂTL1ÕsLáÐNP*$”Ž)…ô²‘ñxÀåpÀÁÁ ¸jZùÉaýÇ!õW«&/›ü[#s7Ö½YX%„1wÉ9{ËUðýÔ+ŸÓÏW×ëß}3ñ¾¾>ܼï>ÏJ³ëÙe÷’¯¦B,tÇqŒþü1²º—¡!IBÞAC<Ḕ$Dr缤ŸçL}œK'&«mŽC—¥­S§\ââ=î'ÎMîy +C°Ù½[¢®0Æ©™FG·µ±™€)"¥Ö®jnª£¬Ñ™„‡ûôˆàsAÅ4=Êã~]W§æùð!¨˜Á‡ÑÃæ8…àb4ÆFhu(ØÙë:×{4ÀQïÝž$VU@O¬‚NNíŒl€\Aá7zã”o À?Zía¦;?ÉÔ%гÁ.½áW]¢ÿ"ºÀLZ×·ß|k9Y- endstream endobj 370 0 obj <> stream xÚÝWÛnÛF}ïWð‘*Ì ÷F.›· u‹ÂhD Ô…!K´Eƒ"^¢ÈÇg†³¼H¢EiÑ¢Hà%¹³gÎ^ÎѬóÑáŽÿ¸ øï;ËófäÒáœEZ;ó{è÷¸Ï¢À™¯þtSLÏ<Î…vÒíì¯ù¯ÎOsç£Ãddœ£#fT3 œHfÂö5uÞ;oGôA6ÉC\Á°63S¸]Œ…ÍfÒwëÍ4çžzlÎC¦Äú Êâ/ó´œy2ÔîjЏ*’ø¦ñ‹B )Àß;øß Í社z“• ÇW—¡ƒè~„ù¼6¡ÐL‡MÂ÷OY¾-“²‘‚!Ö@kæÓ$«fž¦Í»…u¾ÍêÍ-¿i¾l‹üŽú¿¿¾™½¥AÜ0-ÈwqUe5Ì®Y¤†¡ó5¬ƒ0Â-òºJ²ØŽÙ£¬ ‹ºæ É)¶á…eÒ¤¨(—t—uQÄÙL„nE=Í3l‚0¸ ðŒ›€‘¸ ÐnBó1ɨ­Zîå[7^&7>WñŠºqåÒ˜—ǃˆi\$Éð°µfYµû/+¶¿]‡R“ª¡ÕZp†Ö`DÄFïSjëóœ’[‹mµtº²ÈEŽgw¬8?b|“øƒ(› [lâ É!H?ª­¥e^&-n$‹ŒÕVZu-׋Âê¨=ÃE¾»ÅôÇB» ‡NšÉ?¦ëW-òË KrÁLt†a3 ëñ?dX-ëÿŸaôÀTð¼aE‘åã9†HtäЯ ¾yƯ”!¿ÂÄßtãè™ì »‚vŸlkW*ê‡÷v¥ô)»ò"ÎB>\’oö,oBuže¦= Gøª÷,û>áYƒ<'<«Ã&;š€îƒ,òT™ÕÁÛ2geTˆÿ´¥ËKê­ýká¥àR#õø¥«–êiûoÖZê´ub¤ÐBÊc¾0¡} ñ+J„Ë ŠÅeÆË õÁ]f$mâM÷d5#‡æ@³hüà«X0ƒO„\Oeoº–9ܽJêʳU’=ɉˆì)zQNÒdQ> stream xÚŘ]oÛ6†ï÷+tio+~‰T{µ ËŠ!ÅÒÖ ,…áÄJ¢B±\YJ ?~‡_%Ë’“­ZÀ"Ež÷%%>ç(Á×üà ð? ®î‚“EðòÓc”p,®á~ˆ#”ÄÁbý÷Œ †’yˆ1á³›|;ÿ¼ø#øm| MdððI¦'ˆ8¸ bФpÍ<ø¼hY‘›´Ú , ¢ ,c$§â6clز˜Óhö°G Â^lŒ)"SÁÛA6z~9©à³ïæ§L«2Kï•bªz˜–Ç ¯¹õ=iiºÔ|<+êÍZ;|y*=J”\hõG\h½›b»Ëvn9Æ¢? „a8G‘™².êËÜpóð–°Ï˲xXæ—º½-‹Ks÷çóæ"ÛTöâbþzЗÁqªE>¤U]nvv,óýp”0èâÌ0Nakê*Û¤vNg1Aq ï ~/:ž$GðÌàÒú6«œì;‰a߉Ôû®º`ÉD˜}×c‹ë!˜ 3;Ðæ‘¹V·&@¯HWxMpŒáàÉèþ0¾R||TL²¼©ÊÀJ}·1w+ÕßÌD—Õz:º(\9€‡eõ¸M§ÉõåG‘‹âxŒ\PÖïUaÎõ€FÂU©Òƒ—’¨œV¥䣅†êxÄ؆úr®TpóLaï(‰,­MFÄc%®M àHƒ‹Ä‰*-½c½«Êú –¶Êa&Õew„zaºhÔïu‘ÛBo÷jÉýGòûÙùòôÃÀj©#÷w¹LSsu1«7J¢…Wº¾˜7Öx¾2RÙ—?ûóyͦç!ÓÒ~i«ºZoǺøëü_ºðÙî,È'Yxsr„S„môt½ïíXÅÓOG(^D˜}óT¼ì8–GxDÕiò™Î#j ¸syÄ6Çóˆ'3’GšÈ6CL„öFÙØcy¤ î =ÝfÃçSU°Ÿ<žñEÿìd™Pf9T+2óMÿã² Í&q¤ú~6ÉÔÁ‘ØË%Üå.öH÷üúS 9T DéS’ ÷“‹ª4urá®q#7qS “jqé)Á.RÒÄjæ±ñ³>éýQ„H+Œ™974rCßÿôx«*h endstream endobj 376 0 obj <> stream xÚÅXmoÛ6þ¾_!쓼Å,_õ‚}ZÑÛÐëšâ Pl¹QaK®$7k±¿;¾H´M[iaHˆäñ¹#ïîá‘чˆE~X”rø¥Ñr=¿Žž½d"bŒäJE×kŸ3Jò$º^ÝÄœHÂÄlÎWñ»Ínv{ýkôÓuô!""Ï¢Ç(IˆJôŒ4‰¶QJÉÐÚDo£7ƒŒÕñ®ìO`³œÈ|„ÍQb w²ÀËfsÌ#‘“$cSО”ÅÞßÏæ"•ñ?øOÅmÙ·Uùq&h\šP¾ßÖft¿ÛÁ‹ËÖ´q.›}½Òö={™FˆLsÔ5wʸ"*ÕÊÞ~ª›]Wun5Æ@K Ë¢¹R„š)«f¿S”ñÛlò˜t·¿_èö®mîÍèw¿_™ªîÍÇûÅ쇠aF ËpŸQÉe¿oëÎÊJßEré‹^?à¾p·Í¾¯êÒÎ9X„ÊI& þtPØÐ ’2+ÜZ;´‚ÞiÒ»Î3³ëІõòÔìºn7ëLÂ3 ü> X‘Ô9ï ”qö6’¸"%™Í¥d_lʜ癉{eec¸mËngäëUU¿›¡TÜõí~ «.6ØNã3%㢭 ð:j‡hû¹™Á¤Gü‘©µ£…TÄÕÚ€hûp¶ Vì|(:ÓY7¦Ã7ûïu ×pj„q¾ÕÓÚƒà8ØcjV(õ ¿ñüÕÝëÿ lµT$ãv¯Éað3–Dò‘²ä( ¦p>r–iNÖ¨æk9dÇH—¡=)‹©™p}‡ì%àËÓÀ 'aÒ” _ÌêX6†’Ö†’Îò˜³¥\öÕ!¿™ù Ê’eUÖ8ÔÛ)–æ–MÝõ…?Ò—í6Lyƾ¯ <–§ŽcBœ×Ü¿)×ÿ#ëñŒ]d½ŒäG¤çŒ¨Èe€öPCïTé&Îa˜ü¦†Y<8 †zì¢qÑ™0‘„§—™ûLˆZx)ãÈKÊñ’‘X ÛÌ ß ‘# x|4´˜™\?ÙÍ_ÖGKÝm±-!¨BægývÞúŒ¸ÑÊn!½Bæâ#þÈg°’Ðnó!ÆÇÍÔ1®ÇñbÑ=TëþÛÅÌúfmF&œEãõ¾†ž¦¾Ìz‚R’y…ššf=œ’Œ•šm^f=OÍÖ-ŸM@{Rˆ‚ÿOIƒ'™§€q\ë¤_Ì©øLíËY,yŽW’!‹“é,Æ)pPº,¶ÍËY쩹ŲÍÏ hOÊbo‹>P¶¤D0œqF„šD÷Å,§g/n’b lô§\ÜL QL ²ÉI és’Éc¢(ŒøqJØ;6¼Àtµëú.bÕšOw[“°' ÕÒÉ -e–mµÄe¯‡›½‘„%6FpcŠÂep鮦l¯nØm`o…$"±›«¯Á9\Øæ,Iþ%0PÁÓ±›²©@PVªNqaîÜÁdøKך²œ³Ô»¶ZÃÞzÖŸf™tãe[šOj•Û4—¶ \€å2 , À@!ÅY…¡8ãƒÔŘð gÁ3÷Αj)’rÂUèH=Jo¡ë€]IŽtç³[ŒÃ&»Éf÷UO2¼y\^gî¯S¸’DÈq™}ÊÑ%‰°%‰pB±õÍõùw|1Á‹W˜êdÌŒ•°+^V> stream xÚåVIoÜ6¾÷Wè(ÃU”[ÑöPEÓLOÃ5´-CËDÒxš¢?>zÔ23tì^z <0)òíË÷|X@ášÃEü´ ÞýªFIF³`s×±ýH‚Íî:üÓ ‡®é£›Ío@&WdL‘LiJ”I7&ŠE¢Ã®= ec[ËN(Ñ)h°ôÕþöÁ ·u>ÜvíÑ£"ÍHÆuç  i8 ª4¬Ló0<ú4e°Sލ|hÂ&[®@œNÂ’ÅJ®44×á¡¶ÿ'¡éð¢½Çu6mÿcºvቩLmF¾s-‰Ö,A”–ÏhƉΤÒc²"zŠG nÇBˆ¶Õt$#ù/Ì'cåª5á˜%N$a:Šãʦ`bû‘¥Á1H¢’‘ƒŠ 4%óW| >zÌ4NdõB,äRf‹ØLزyEîBäC©\fGÁÉŒ3"Ôk¢WTNvÑV¶dø¯]”-¸®4Ï‘ ¡Á  8Ô ÞŽÙ‡ë6EÛôC—C^a@0·+ÿvy\ç9žÔsET:ªÿô¥i÷}ÙŸ¦Q_Ô+²JWD HaçV+·ãÁ¾kïðúÇ?®p33<”ÍîúÆîÚÃ]epÿœW×7Ûè½× gÐŒ?›¾èÊýP¶ÍÛC¾ByÃfË Ú÷E>¢…¼èPyÖ¡£ O_?ŠÌJ|ò7¤8iH5—‰t 1à l–2±Ê‘¡Îc„ ‚µZÃÄX?±È4J‚%eiØïŽthŠrK™4;<µIçÍ>™bÀƒ¼qdýÐv¦Ÿ%–n-–$áÑ~$¶$ʉ҉SOxhº²ÀƒçH©0¯H™„C‹¬Îm9ô¾èÒS@Ü]³Oˆ…$"YÁ4ÍBÀhsf\’éëʧ‚ë¥|¬˜>2#lÊ£õÔ'‰’tš¶)þ“­É‰Éo°ÕjxÉVER¾Ö‘TÅu] å³M©¾D©˜î¦³UCEHDµ®rª‰”Nä–rémF»˜§ê4Bœ{¤Ð¤Ô>ŒàK”ËMÆŠ‡Í<ŠÓqk;ŠÇ¾‘ØØºšÆnáxÖ肯ïÚ®€#ùfŸ3v>x±Ï¯|âTJtö-7ŪÑM1¹)ünŽ蔜&~#¼¦>`å@¹Ï»¼6ƒ‹ÓYF5<’¥7|fBTäÒïZ¯¡ˆàKݾ gªl€e´í+Ö~¨p®ßÌìiî…T//»ßÿúðÁ£s’±¥G¬º²A™ÇG.ß#yïL(Ún¯yÀó²¹o»:Ÿ‡Úø˜£§9—¦p3ÂëŽx†&]çéz\¿8+¿ßÇõÓרã§oëÓBK­Ò8‘øŠ|"ýøÃWG(X3 endstream endobj 382 0 obj <> stream xÚ•Ù’Û6ò}¿‚Ôf“À#yKm¶6yñf=oQÊÅ¡03LxÈ<,OU>~û(pÄ‘²ËjîFß Ÿ‚8ˆàOd ü‚ª ~¼Þý;b%¤JƒûGØÞÇ‘(>þ&Bïöqœ¨ðýNFáy·—™ Ë«¾™ÛŽáÑ”C…HÏu÷ÄxC?OugÆÝï÷¿ å¨@6±… öI!¤$VúÖLu È{™È°žðW…m¹K²ð…vû$ t¦2ãX/Œ8õü{ˆbEâÊÐï’4<É¥~׌łüñౘžM=X¥•ˆ†å8ÖO9ò÷¹žž|ºÝÞ^(–BkºÐ«ËÇ™w{%E¬AÕˆ÷Ôœ>Žfú8ôçÈrCYE*tlÑQ÷“D¨×á’oRŒEª,úa'vû,×áýs??Á½”ÊÂ’Nå0ÕÕÜ”£F³ðüÎ^©4¬ÊŽ7yH‰–"Ó¾Bû™ #³‹Æe –F%ËœôÍÛóÈ.àX·§Æ.›Í9·f(§ºïøxÿÈ›eÓ0àŒneïx¹îø·*GKŽOæ!\îÉ8¤q*»ŠÌŽÌç }¶¬ O‘Á̽ÓqʺָŒ„vçPq”ÏÉ%xTù'~ÞB·¥ö¼×ô¬pwa=O‰þÍ…æHºßå(@C§­1$ÐH@uj^xc0ǹ2kòaÆöäR–É E‡åéÔÔ•Õ?✆þi([Þ].‚;Õ`Êé5 kç@ۡÞ àÂuw4_À‚Jáù¹¾[#ÿ–VrþR75åü<–Sio5 s5̓#‰ÕVùQÙ0.Dº€¤È6{¨;¤½aX%²+»bD)þô™LI&ä‚(ÐûaœøúR"Nýû£¢ ꔇÀÊg´^ÜÄâ5ýS9@VjAG|l‡®Ÿ_®²×±¼PcË"Ôs¤´†«=ÿ.9àÖ‰—m"`Yao—Ù¬‡Ýl.ä“\qÈ'yj P½äÉÈÓmš é²Úû Ýç"M\C8PáD‘Q Xg‘*Ú&rAi·ò¥Ðù’.Qb{é bè4ê¶Ìòë2Ë¿'s·Áˆ0œÌ‡8CRhˆ"3˜-‚J‹Ì9û– âdñs¯­n‰´°(ݦÓ…Â`¬<ƒOÂÂäžäè,s»ƒÌ‡EÜ|à ÌÙ¨üKeG¢~·]Yç ”*¼‘çƒ\\Éë’ôÀ \øSMœY]^Z2ëÏcÖ£ýmOœ‡É¦WKߦ뮟ŒãXNß/A±Œ!.Ó8 ߣ`EÌ)“k|±˜\Ä„S“˜¼`›ÿ€í=6­Eî5 œ¥?"‹-“E"v6³Ô#W¨¥g ŽŽ/>ÊØ`™=A·ð³It|Éà$zOÒDÊI“@êI¸´Œ‘«HGþ8„G¥¡ç¼„HG mA1˜…ú‹6eFK÷Ð䄸¡p™FBÉk³´‘Y*äJ#‡p³‰‰òÈMcn½îøŠ<üÕëÏ\uä´EKÇ}á—p¸ê¬ó#hOV=õ̸‚ƒ`Ðz€n?`ØsìtGdO[€kæþůãSߊOI¾QX߈3g3„l¹D·ˆm¥ƒe×£Š;e=*ÎBp³@%ÐwËìÛ*Ôo3ú$2‘d·Ò.ØÍ¥ñï¶Î´äù¯–˜æÒt»ê@ö†™äºê¨•ËeêRt¶ïã¹å[÷Q_»Oú­÷ù[œ¸GkOÙZô; GB³Ç-¹·M—ŠD.¯ÓΫáݯk^¸÷îaB¸ãÅGj|0_Jì+ïãy´¥ |œÌ°"ªÞ¬:¼@Ýai+Ìí\¨Ðß‹"ü'`r Q„Ü`×|©Ç‰Æ!²¢päÍržújOsÔ oÍ G›2‘Âg¬º†FnÈ®‰LãØcLÓü–¼ñjpÜîû]]uÃö;nxËî U3¦´¡ Jô¤³Šäo8”«&™Æ'¿I–Ò›¢®t«‰aºº|Ådɰät‹bôܦŒü‰µŽÒùÝŠB¾ž¡pa„Á»9ZòîhÅ­ÏúÖ“‚Ì%v—zðâá£Âf‰) Ì:žêßzVˆ0â_nÅe.2ÇŸòp¾ɇs=r¯WШ–@a†ã&¶¡Å7¿qý\ã•ZÊvB­Å8£ â·z> stream xÚÍ–QoÛ6Çß÷)ø(+Ф$boC[ {ZW¿-C HrL@–\Q®c`~Giɉ§CÐQ¼»ÿ‘Çmò0’‡‘"ƒoJê-ùmEÞbœ0F•”dµ†ù„¥TådÕüeTÒ,NËdôÐíâ¿W¿“+òP®Jr RÑR¸€"'[’sZaØ‘¯äËÙɋܦLôͳÜeAS5çVŒBš+¹g'Ÿ{b΢CœðBDÿ؇ zζói˜¿·öm=ôè«mëj{ÿ© 61J‰—Ê$•…“úzì‡Ñ&,«[ư‚²’$RÒCt?ʼnĽ½[ë¾¹‡Ã­íÆáçÞýqƒF=ôÆû×›jô³¶¾Ûø×K%z=VRÉÞŸí´{ã}Ų4I•Xº®6-¬Ÿ¥°CûI÷a ÎÖÝ—ë¿\Á…üEF󮣯"ᩊ¦ 3Œî«}œåÑ~g%4%ÉŠ¨½×ŸU(.†ÉÃñè°Ñµ Ü`jm¼¯1ú¡oÍ3×Úˆ`ÂDaš0Ní‘‚rÍqkEly4t qa+pÖ·81Ë-È2ª‚ !DôÙ®†ó¨ìSDf_[)[?ÏÂâÐ¥}Ôf278À5€šã¢ç}…™”žŸÃ§ˆse) Œó70y±€Ç×(Ÿu®`Ò„_O¿ðòéë¡{‘r˜Ûo{´ÿ+äåAÎJNUùåPÏÿˆr¡Äk”C'¥xJ¹Ýí ” ʲ§” å¬Õ9Q.”´”Ï(w^k|VøÀöÙýS¾€ÜfÖÆ»ž ·#«‡8KNó3šŸRàÍŒ/2^ªŸÏøédÂÌOF<ËKZ”'ÄÅuÄmœóâ~|ñ…NÓvíÔ>K¯”=osz–B;ò«ù—nE@©iY¹—t6îYÀÙYp‰šüÇÑæ,£¥r1ßÝÌlc-wNó9ßoÅ÷CkêQï&=ôoFXŠ×4_"¼,ô‚†r?颥%&Ô l_ùŽXs7¶ßõ°7Ýê±­&K˜¼·Ìº Ò¼Z2ìKI™\¢k+Çœ/W?áòÊÝþÀÉzl[sF•ˆ¶ívø²ê:`.¡ËuŽCpÿ" ¢Ú?êNW!¨©¦ -3û°lǤP”óó¹KŠ«™e!RPëѸwâ§·]çn1p¯&|W¹‹òˆ/'½¥¤Èñj±óx»‚m±–o‹ hpqv œÏ೺ën‘çs†³ çH—âÑ;5Rmtÿp~ _‡¥õMrˆq\¿üò/©V/a endstream endobj 390 0 obj <> stream xÚµYmÛ6þ~¿BåC̈â«Rô€mŠ^‡´ÙoÝ¢Pdí®6¶äHröÜï ‡”d‡¶ Š5Eg8oÏ ¹ÉÇ„'üÇ“ÿ,©vÉw7ÉË76á’ ©“›;X^óŒ0Þü–æL¯Öœç2}Ûwï·õnµF¥CUn›öž>úî06m=¬~¿ùwòà qä"áœJy–2cº,wLUú]Y­O?Üvã¼|#”Ÿ¸“+VÈd+¦¬ÛýS»ZçEžþøŸ·?ãH¤ãCí7‹Z³,Á¸g¨VЧtâ/EÉ ã)wuÙ$ $î°©.{š{X½ëú]96]Këå~¿mê'èæ#¹AÕµìjÚUnÒçx »ûæžÐohvû¾CšO«Ü¦¤XH³BÀ¯`hF8^3Âá„©ãwØÕ}ŽÀ©<{`»û±©¼AþþõG?èï½ Po´1Ù$k£˜%¯óy3îó["~),t´T¶Cmݨþx›xÔÏ4Óøãø®ÛnAo>o^yçp»T@´’†â'x›g ²uŽÿ7¤ÁëX,q–sïèocL€@…˜ùuµ6éëw`Ñô›¯œ"´§½Mó»#ž(^ÅâŽeÂ/óÛ¹\*0(¨‘aðâÊÓCÝG|æ~FY©&e!È 8fTiðd`T‚| Å „“Y†å:™H@—5@ 9~ÉÙÒ¤]ßÜ7­‹W˜>M œ£Ôx=¦6x’àœ¨ÂZÕ6"Ã0"í_ñ³špŠ UWÞZa-±iÊûÎÛÊL+‡Ñƶ£Uc9$dÆAÉ,ÁÊr× ,rlöávµv!Æ~S ÃôŸŒøsÎØ†cÑÅùÂÞ«µ²i,Ä,ËÍu£[sÉè9 ›®½ÑµvF×GF×z6ºžŒ®½Ñá—Œî†U·=ìZÏê \É´ì›ÊåÒ¾KTËe<™Ðê,¤™k–Ï~ Ê„z¸–ÒáÙ¢~¸Coz¿È?ð!©L¥Ã#<·L ·ùÍÊ 'ìFˆv©Û¯œûxƒ…ñ¡=IK$ñjÍ•fÆž”ëbM€Q ÞOm‰2Œe[Õ$ª†æÎò€_r‰>"‚>°»ê¨~Þf\WMí—"žÉÇpü*Ì\K  ]Ÿžéëý¶¬‚ŸÞ/êgÕõ}=`™4m7Ôn—ý*H3³Ô q¦ÜÌ(ˆ:‰v66WÕ×N}q^}‰d"9[ùE¨K)MŒGÀjqÕU'g=–%—8Œå .c&²²G¬bm·Ù¬÷WwùÔYȨLRõßn„D‘*d©T¾VãÔÔàã,&N†þ[` 7·FqV÷ZÛÏ8à×n&v} ÔAöÏû²÷ÈR„Úölµ¶œC[Ù ¾öx4™ïÕ©Ÿ,}¤w¾÷|ýö'Jmý Xû.ÙwžÒÉ Òrû„%vÞŸ=ÃMM@! 1hthç4“é¦Ë3@ùΗ†Â¦we5vý M(Ñêˆ8߉ÀHóExO7¨c´â˜)×Kp,vOjÍRZU¶¤ã{Š ü(Ò¡i¶ëi‚ ¸lïá`¡ô¥ ¶â§ÙyuƒAC$›¦¯+&¸2!¬‘ ^¿*ºQ˜ºÌ`œÈP!îû+Df© ÁoI?sõ€ÁÇwÕNÊŠ&ClèÌ@JúÈÂ1`ptóš£j¡æè~»ÿlôGo-õ|©XxóˆÛ¢ó ̆ǘ¿¦n{µà‚|’ÙÙ’ ÎÐíB»)¦Õ2Ã|‰Y=ºÅù”o7¡æÜu!—c‡·ãŠ>=а‹/BXÃÓ@îŸ@¹°ícÂÀ×ÉS¢ f%íçî@ElùÂ÷6y—ü‘± òr0JOy[Ž^šy[ðš½Ê{Aåy£gݳÈÿýS‰Ëãzï•È(\ãd$vç‚CŒ¹ÐR-á†wêÒýk/D ¡Íç¶ÛÍÉëËr7Œã­@ëážO]žSdå·î3‚–þùö švô?±éïñ¤8Æ«ob'õbIê÷õPõÍ~ÊÕè‹Â £îE!7Eˆ¾X6ÀuÙêç¦V6]Dj|GÉmæ|ði@§ ¼1öAÂ#‡·)R0™L,õîŒ ]†ïõ£UºS® Èt®§îŽt™õ;<÷ˆË(ðÆÛ §.;¯éJ8¿•þi­øtCü2­áÐ×Óú1’Ö¸ñjZ‹¿œÖ’›Ki­ù|•¿Rä Sú(­‘µKk½HkÉC{Émp/¤µZÚçµMö\ÛdÅõä6L‡äŽqQóÛ…KnÔ2*‚¹¿³’§¹Mé,4^5~qÑÜž RZÈd IÄ-܉¦ïe©û/ë5—‰¼½+­†ëP¡µ7U-Ô(žOýBeéEëÚøªÊÁµ!ø@@3þÝ:Çž&æ¿M¸W„Ń„,€Û‡iº7,®ÌÖ]™Xÿúc÷æts§ë?@è8¹ÞÈ1 ê ö[ %VÃ5FZ÷‰ª¯ËaùÔ®’Þó\&.xÞ<<ô¯ò"Hï_Њ¿óH|qÿàþj0ÐBÕíö‡ÑµÄÃúkk§%OwîZ†û‡ŸªŽÁüè­;·-k-éO0BÒ_þñ'•’s endstream endobj 393 0 obj <> stream xÚµX[o£V~ï¯@}ÂÕú,çºO­º»êu/ñ>5U„1NH1xoi|gΜ8&&Y©J$8·™ïÌÌ73Øûìq/€?îiÿ—í¼ŸWÞË7\zœ³$ ½ÕÖ—<`Iä­6û‚EL-–œ‹Ð¿.÷‹V¿y¯WÞgÉ$öî¼0a±2täí¼H²X»aé]x& ›¬’ë¼; ¦õ 8ŽX<'·ßcÅ6E±XJú_éÑä]Sä_2ðsœQ~S/$÷ïhÐfi™ÓÎmšuuc0½|£=$¨bI:DÈBmt\ÜWõ¾-Z‡ŸPpÍ8 CБM}X£¢Lz·¿¨—f°oê5-ýðþ½Ug_.¯¦0Y æÝ¡©Z»WÁ„,Qã­«¼r$Á‡®¨r{æèQÀ¢¸jŠX¢íÎÆ‚éÂÏM“W ùM8cƒæ#có`ŒV*&8·"•À²b‰€»°ˆ®2‰ÞĈ۳}D‘f°Š¦¤H ;Z^v7Î` ¡MìÀuê->•ß9s¶ûÅRÄ~ž—Wù†fÑ»e¾3–’ð’aü‚lãúпͳŽÔC~JÉ8ï > R°„Jã9ŠzÎqÔɶæj XÀ¿‰«"äLèž«ÑZƒZ/4)¦[3•VzÙ¥ØBÝã@ (Žän벬qרáÇ)KŸíÛ?Þ_]¼¹zûçtG9“%½†!Î(è êíÌ¢ÌÑPøfÝñj Æ’DÅâxýá[qäŸEY¬ÁrH×g!8²„øëi hÈ3ÃǃtýlkýRÓz•§MÞv4IÈmÿhî`]¿µ‡ú•úyÀ/~ÿõýÓ ·ÿû9Xè©.¶Gñ¤ŽÉ^Ø[Ýa€åeieáÝ7ÄþShô…!æè¯˜ÒsôL¸\ˆL0,–€dM©˶&…=8̦í$) ó+—•­5ú´z7eM—¦^À¢¢çÝ ž7*K[{q²% qEÁÌÒÞÚ@¯Û¼u†d7=³ûÜFYÂ&&ôQ_Ò²¼_ÄÒ?ß‘„tŠ¢ïHô|G‚'B1t$v<Ó‘Œôªéž„ÃÉG 8H‘ᬆñ6«â¤-q:ŸÞ˜8©ßЙ„J£¥N;‹â‘ÞdhCÔ&&8¤£™¯ôdü•>V<¡# ±×‹xh,P¦pÓÔKàsdFm{ Ümz œ¢`Փܧ2 %?ŠÎöÔ'¥êòò“ö=–_aŠ©ÏðEžïË4³å_ºÚþàÇ¡ø¸KÀšŠ•+o§>5„†¬ðqªäXéi«ô”Œ€ 'âbÊÃO&CgÂÁØ DnØ£´WK;zƒž$ËK—<&šO9øDž|¸ŒAÁŠXFðˆrdä¶~øî?F¥%Ó endstream endobj 399 0 obj <> stream xÚÍYYoä¸~ϯУ:psÅKGöiÉ,&,fcç) º›¶µ££GRûöǧŠEêhkÇö.6 Ūb‘Uõ;úñ(?eþ“hWGï/¢ï>äWLª4º¸é-OXíý?cÁ²Í–s¡âOŸ7[™éøÚôeOÍ]ÛôCwÜ esK#]{„Ží7ÿºøkô— bÎeÄ9+´öÜUÂÒ"pgÜñ×ñ{³ÛH¹ÍÞ1øîƒŠP•¤À•\³BE[¡™ÎÝê‹M.ãv³Uy÷ƒéjwEÜ[Óí6"‹ï°ŸÍ&ÊúPÙG"¯ípLDïi¶±vßÓœ¡‘ûÖ±©Ê=–M9”¦¢Ž3Ûl žÄ¢ÿáÓç¿èâ­æ–“u¶~?\2´ ìg×¢Zƒ­žÀ˜9÷ö2᪱{ìŠø·â§ õv F{ã VÌ ¦ &ÁàÈì3{0K»*΄òd¦ïËÛQâЮpÕêëÉÁ:‰«õÓÊ3Ov›ãcY•¦{"ƦÙÓ>èú;S]nh l­bӕ溲ýŒ2~¸³%£‰TâÕœYÍ™XJé·HíÚcAçN7‹•ŠÛÆ“ƒÉÜׯWñM[U-.{€ëü'¿%ž=¿ N$‚à{Øžk&Ä<À •æqyC,)¨‰|.¦6CW>:BþZŽq>ÆÌI½¢Ç²h¸õÜwmu¬›~98Š4ÇÛÚ6È|°{GδXRÌK¦$:Œ+Ù(UB¾ŒÃ‘%³ ‚‰°ãž@Ïæs¦B@û®›>I’¬qâÕROúnÅ´9ãÁúöp×]gûƒ‹Tm³§‹ ¤Åo1¢l4EH•pgbœÃëÓÃâce:HJiRÀ¥(Gª†¨+ËÒœyŠ”%‹\T[Ó¸XÊÁöf-K gØc‘Â׎&(¨ò)Þñ¥º8”Ä5zò±¨7 Ï3½©}ËôÏ¥§ß”ÞQ óÒÜ®çë] ºÔnëÉ|Ó-°e¶»Œ§”‚›òaƒéµ£°S·O{;˜²òÙ¦aáV–mÐA­¿ÿàÝ-á¡EšÌr–ÃåJ3á”PLLëqéÚ*¸«Y:_uF Ì­}ƒt!Ëó9ž¼,]b˜­bp)=:“óô®ñ‰ˆ'à$Ô£°9fk$¢PnifD˜…Já@ð,p Üe€ãØ£áÌC9ÜÑŒ;hl¼ûü‘æ°ô$RK€££·ÞV‡+UW]ûp…xbÅy Ê"àŸ¨.ƒ¿Ò S‹Ctûã ÇõhÜc2€-s€û{, ŒÐÎõ0`UÌ—[…ˆ‹¨â"ºÞÂ[Ï5Z 6ìèHI-·åt{@Ý zß~£²Ùaa7‘ôOiÆê!Ã7,‡=Ѐ;6lŒÇæzUù…ÀŠÅE‘°LÏÑìï¯HÖsCgŠ)=¥6̳Œ…;rõË3©Ë0Ô·>ã¦xéçÉÆT•ݯ$Y™°œ{1»nƒ‡Ðßá1® €‚ñ[Ø þË¡xcEæ6"YÂA¥ÄÝ6WP½è¼¹`:Å5p¬™[óc‹7IB‰ç#½@”Œ_ ù¤«ÝÑÁ˜},¥H Cc!å:mE ƒ¥à 5¤àþdI¸Ð¤«èãŒhú–ÆK/|gz¿È—7[¯üdüζ‡¡¬Ëw ï|<.û€ª(jciç‰ZúÎï,Ïcº³¼÷¾FèÚÚÇü]gº3ì›Õ®Ô‚q1–»Â—»pIò¯“E=Dº`¹Â°^D5Â4¨¡B¿ŠÎ£ŸVdŒT£, OyçœI=ãC Î_ä=R¼!·BN}xÆŸ'zà$€—ìe Ù¤þ`¼Óýâ}Ïúþe¼Céw¦¹µ9eÊ)ÄA!×ñ5 yØ"$9ø|@÷þü©i!BŒ§—à8T­H™ Õî[|Ðt~‹LqéFZÐü?ŸQ£lß8pË6߯jK’§<úg ®<Œèbõiä¤Z…º3uÎ$SÞSH{â'‚>€'Ò»T¬}I-I펀j Ç™P£ãäøf±´yšNrÊ=4ËJߺŒïvI•«“q¹Ì}z@PÁ¬ŸÏ#‰ XΖ»k¯.Æ·ãƒÀh©ƒO”§ûP«’éõe½Ä*<Åê{Ö#ŽÈÓ‹Cm¾l¬žé> stream xÚÕXKÛ6¾÷W=ÉEÌH¤¨G÷´)ZE‚uOu±ÐJô®RYrôØdƒþøÎpH™¶”u“6‡bDçI~óÑÞ;/ôø ½„Ãà{ïÅÆ{þ2^²LJo³ƒùu°,ö6åï>g «uréßÕ‡Õ›_¼7Þ;‰,õÞ{2ci¤$±·÷bÁÒÄ~ÖÞµ÷fÁÀQÈéÕ0Sœ†LÈ£âT2‘^R|2Š‹¶ž)ÎbqÔ1‹ãKª)ëô«µH¤ÿ=0 ý²õ‹•üû¼¹SÛŽEèɸoŒ ¬{íØó—‰‡*ƒ ¬­.™L´•ëǦ=ôUoà ÏÜEaÂBZJÐ’‡¶*WkI»¯nÀø Ýê‘C×ÞÒüw¯ŸÑKÕ ôòö|@/[]-:K†Ã”I¡ ÿ ú¢«CÕ6F>rý”,‹\ñͽ‚|¤ÜïÚq¨eÖœ‡ ·,ŠŸcüSC¿dŒG,’f%Öƒ'T^$ ý¬ ¿»N5(0ÐŒ)žlwK^…’³ŒíoÌK–3½î)ÊiÀûŒtc1Œ]Nt- ˜ÁpÃaWRúyWå·5í"ÁýÝ‘ßVkpXÕ6#UÒè-ñH’ ò.ß«Au‹¤)KŒ£:§óP8„jKðý’Žu˜I'nezõúæÅõ‚28¤ Œþ>ÿ}Vg>O©‘Û¼¯Š«EÃ"=7úë«ÿÆhÓ6ëÏ3üÛ’áŒñìh;’ܱI³qØÚÆ÷É6ÉäMIã^ð¥2Ï¡5O«e<à¶H}¨µþ¾Õ›¤›ò K+w'+»€1Æ>mD.ÜY¶#ìÅõQ­*ŸQî†ûª§ÌM‡Þ+³[Õ»±¢Ý\ãAKõAƒy`!»<äLÄ&m—‹ºõÛ¦~4SʼW4ç—LÝ[g Ø1í´´\pðYy_þƒ}evä½åý’‘$bÁ¿ PLF³Å¥C õó¯ÿ‡²Ó¦xÆaxÛŽˆ$&ºLbx$‘˜L,Æ|_ 1Ž~(ç<ØFêèNcäë’îIjÒЗ0|£hê"«hʼ+é«jª¡‚æ¢?^½¦'éXhåÖÐŽôóhÏ|.ðŽ¡¼Ñöæ¤ãkò žŠ§ø„Lq‘C(¬— ’„I+;åº'ÙŠüíÖæý[šÙúCW=@ê±gãÀT ÇJà ©&¾îÚŽæëo`|êthdšðsZ«½A:L/8U t.fùùÏV$Í1ŽâSßq@ïxÚ½¯y]Óª|üPÕUÞ=Ò8àydÙ‰…T@âW<ößÇŠp^Ø+¢Œš£:v¹Õ-ºMðÌûÖô.²…HÔ©³ÞMŸ@µZÛ¤ŒDÑã3In›²jîŽTÃt‰}Uüà¶1áPHͰ.!O$ˆyäe䉀÷§ÎýÉ|_@ÇN^>Ì‘XhæèNÁ¿¨{’štOÈ#?y-#oîÆ:ï>Ñ´`?îÏï%jVBê=WËGH|AEppàÛ`lm}“Ž©w>QsKnmëÜjeZ;mЧ¿!¤˜‚u¾‹Ôоùæo™SÎ endstream endobj 406 0 obj <> stream xÚ…TÛnÛ0 }ßW{™<ÔªeI–´=µ[;¬Ø¥—`/ËP8‰“xpl×vÚØÇO•V`HZäáEä¡Èá$q?Ntêþ ™®Èùˆœ^JÂfKFs³’Ä ÈÈhö“žõQœjMs]ѯ«¾ –*˺ʼBí—kTNò¾ìQµÌ·A‚œOh'\nŠj#%iÞ•ù¤*<0 †¶NÚô}él!VÜB†N›Î• õ¬¬‡•ü]¹{…ë ¦”¿Þ*ºrÅB å‚tš¼^¬«¼cÞëb„}â‚pÎ,xÎ]ce˜öAR¦YÅœ§Š.ªvëô@˜°†<e™‘¯ÈŠd‚N¹#7/Dßc0ô§›"ÉŒÚE6†ûŸÈ{ FcZÒ? ”kcÝÝz:àñ¼ÜL"‘Ðç7¶›6XaÚ ÷=>½Ô|ŠC¾T1e|»çºi·à]k}¸fÜSf¸÷ylJ7l…í½Ÿ¶›{Ÿoìm×LÐøöz½©ˆmD×á~,úiW¶CÙÔÿÒìà#O1£h׬‡².‚ÏQÕ®£Ö:Zþ¨ÊhÍ”Ø]»{L‘× ³ƒ¥r‡í29û¼éP‡¼wžòšÓÖÉo“ÓB[ªb…ß!E0UP<•Ãr&ìFêxs°yµh:‡[áZ¸€Û5„ šD.ï3|§ô–”ȯ6‚îžÛOá£[„¹»ÇˆYMÏpHÒ2‰oØ{ƒãbÏ{Ø>›ÀxV„ÍÒÝù÷ЏAj㣧L ZÇ{±qóË2͘r”Í$ß-4Ï]»è`#8§ %ÞÔÀM3z:MÇãϫֵ½¨Á2ø7Hð‡Nw%Ø7xøZ ËÆŸ½‹b)92 LŸw[™`üì5@2úýöî ÕWͺ«·Çd/?4«HºýˆŒ¤MÅÀYQy†wJâ°¿5€Pà'åÖ¦þ3¥mëmš¦™ŽÝ“sÔ¹C^§©òÄ™Ä]v ½yõ‘°£r endstream endobj 409 0 obj <> stream xÚí]Û6òý~…µ¸˜'~H¤Rôá\.×Ù·Û{Ply­Ô–6’g‹þø›áPeÓö&·ÍnŠb E9Ãáp8ôìÃŒÏbøã3-à?ž-¶³W׳¿ý`f\1©ÒÙõ ºçZú¯Ÿ¨†¼ÛÛ–Yjç™aFG Khõ?* òŽ^ÓWÙMÞ•µëì€EP‘#'°ÕqèYRo×äU»ª›m{0¬nÊÛ²ÂU`s{ßvÅÖõ¬ú»¼Ü”2å›x´¨«f,‰'´•s·{\²$±ôßDœ‰›+XlÊ£¦@.”Õ-}þm_‰¸]ÓDznË¢¹ÆQ[t¸_©°$!ØÇ«$‰ò¦Ì-Y^H^P]Ø'3Ãdn… ›·)– S ãJ:a±¬’fä°]­ñ–Û!5Á KS7× ð›6¿­aÊíp|ô:f*`OôTÒ W£|À˜Å *ãÕ ’ºýº\à®és»3@@JWõfS#Û÷´K„óÒ!ేa®„V!™ϯ¡#Ç2ãÈø>4 ×LõtöÛÀ9ÓØ |3À`–Òqà Ši9 n¢Å„rH>õýb@’b/"É,Ä¿H ‹õl€>¢Tõ“œ¦T3žŒ”þõ;’sC|3Ü_ȘIî(} 7KšR¡£—¡«C±¤_׃™+|æjä*€@Ô“1WœbnˆÒ¹œ¡jâ,Eí«à. ó#ùÖ aœ>‹e£ýýã<ÈÛLÿqt°DKÄ7Ã’g¢0>›ÃÁÃÚ[ª”ßG¥ˆ¯¤RÄŸ*åˆ%O©RÒ‹,I¾}•"þ`*eêCp­Éc” 07%…žÿOc@«©”¥‚|8užaÉY†É/Ôj†ÛxÅö@¾?!°Y@À|<Úðx"èùdç<.õLTžº¨òÔÙóñÇã—xB~=Tª‹úP}=}øökŸý!•§—?Hž<ÂARcÁ`„0L÷V”Q›!žžÍÇÓH÷w€t”ÌUbÐ@KbT©Ø³_M»£x|‚'2S«×.š&{ã‡-¾ "“ ´çewž]Éô„ŒE\¥ðVñô‘ªYûyB8|}±>Ô°DÉ`Uu5äP¡*OCV¨ÅÉý8þÃ#Ñ—Ù˜ F$ò1÷И¦ÈЬ>ÏE¨Åò€˜ûiŠånQ¸ÜÑ¢n»0ó2Τú¢ÀÜdš©ÏèVž/#ƒý(ªuy¾sÜ ÀÀ˜ûº0ÈAÛyÌÁ¥ß¦ÙC—|£Ìšì“pÊÏÝIÊí0ðZ@to¢79޼§®ªî(Ã42aFú®K·Î1ÅÅ3—ѱ—ÛÃf›v„V—v¤ÌÑñ›«ß°”6Wù¦­©›²Dþœ˜r³¯4}Žù)Ç5`âIH2Dú‰7Œ9ÅMÙ•.ýûç/ïÓ§”2´‰Ó%壯\¡„c½ûTnʼ¹'èɕÜVés’CNõ‡+×["Í­JF›²*ò†êÀŸÛ&ßn) &BÕ t–µÙ 2|Ûd±¦d±Ðn®0w=õ]WníV›ÞQ ×v­&Ô(·SC‚øLzu²uŠó¨øTÂaÎ+É-±Šcž³¢J¾±©îó¡÷-xGrJû¦ìºÂA—5’˜ráök`·"N‡Çí0vxú‡Nô/Ù¢yÚÝñæ[žË‹÷Ã(G`½«–-õí×妠>š³³Y`ãÄFõ9[Õ0äâ}±èÊ!s¬vÕÂí€ÁMZR³#}œzÌ1Ãì$™Ð·,º¢±riI¤3ê(?^Ö¢n@šï`%–¸t VåŸ+Ä–~?);ž*9h† `ÿæNRËT[Á™°t9pË!Uj×t ¿-¡jÙ€ÿ¥9|Và4>ì,ŽØg‰·ÄôÄ#BJYÛö²¥òtþToÿÂãMs#-ä稄ñÉ9SÀQÒLöÆ%CY•Ñkäp;UóaË¡ípYæ¶Àöe·Æp½pÆÜNTw±v[PÃÄÜ?ïÐau¾¢8µ| ^œl°»‡ÕÍÀãU\`êðc­Gý…ãXªðBóÐØìË ÍÒiX"]Ù™má±BÓí˜0ÅA#VH3ši5nF*cZD¸*Ü KFÏ7¨ö|{á´“}Â`_Â`/>¹¯åÒŸLÙ«æk·¸‚Ö-ë©P°WÌÄÖ[äÈ‘‘æÀdºÜ–¿Ú6¸4‘Iûfûr*6yskgÇ>;»m>œKFÛüÓÁ\bÔXøÉ´tfW@a!À¨°ðËž ìÌ –©RuwOà€$LñqO —øæª)@Óãõ­Àm[áê>@éßï(8ºxEaã`L`#]þ[l¾EBMÐX}gGÔÔV’ª–ÔVZ3 ‡+S jÊn#Ð'TãO»yñE‹5zÎD*[º[J|“Cµ^íCáìBÇ6÷Æ W§Üå]o§¼so¥$\ŽÄ j§8Åïß_Ü%ÀÉTÀ×hý ´»8PIaC€œŸÄ : ëNGaÕÓQ¨ÁüzÕëvã-¿H3g#ëmãŠÊ|¹,è¼'0§éÍáÛ!lrS ŒÆ;`wNqÎìká¼´(ÄMIè1Hù÷“3ýF&QÀì×ô\ñàYT–‚>” ß%!η°g»ƒ«7ìô‚FNõƒC/@|~ÄèÇ:ßxÊ <™´ÝOçôœø0cV¼Ÿ»rà@†¨¶3°WX,††ÍìíìçÓ|SàW=¯¼Òûð$^`€^z¹oŠ"‚–|L‡™ 5j#/Û 6ž‰â²T2ñ»á‚Æôâ··M¤fÝxV±aãk]Tg¸¡ÉI&ßÄ" ùýP„&¸Ù°ƒ¹óHt¨Ñ1©ÀƒúX‚`. ‚ù ‚°»»£ÛÖÝ__ Ô3‘‚‡I#XI’™ ³ì,å¶ã5òmN4ÿ±*ð`«ØXçEÅží-|»ÇœXŽa l\QÙ¹WÕ„Ë¿©³©9ãPúï’aøyuKæ´”Õ€åØj]Åu´,›ÂYÉø ¶9³‘´LÃ,‹a­ }H»âÆÅH´%K{QØk÷rÑlÆÙ¥Ð0è$’Fl¥Ñ†DÆÁËÂGkZ}€Ö h5Ž FE”ލÐi ˆß#~ëŽé>æƒc¶ÖOB/ÞÅy48cðÍ=‘X8ðªß·Øh¥žzF®§éÇ\œáhI‡¾‘õpNPzµ‘£tÂÐm™›¨x:F%‡?À&kl®îéÃz#¼÷c Á³aé·àçz6¬n×C»s·Ö3u¤c;ú‰ËÂé0¨Q@xã0×Õ Û~¿.ÜiÕz8pçþzÉ€Ö£€õ>T¡õAM“ŒbYÕýJÀôqÞ).Ohr°<¼‰SüQ€Óy;RæRà³0Éç.¤ Æbéîˆ3 >‚IèØ\ Y¤šñlpÝ Ô§¾ÔilF×0Qƒõ÷U… ™‹ #y™XC'ËÁ‰F@rÇVT¡ÔK;GuG3õƒ_Ë]áP¹p,1ì¸èNÈ– çâ™6y •Ño}Ó2Õ(pßóªí£ª6ºmúkÙ¨£_ÙÁÐþ[R.4 $õØŸ2‘®Çh-n'h¡$K-m(–rˆ8÷¢ª~´œòô„0¸ÈyªÈ4Qqúó_þ¼Z» endstream endobj 412 0 obj <> stream xÚÝÉŽãÆõž¯r¢‚ÍâNääöxŒ1Ú3ãLO.Q`T“¥c.2—^|ÞV$µtCç …f-¯êí[­þX©•j•øðóVy½º¹[}÷!\)Ïͼlu·ƒí NâÕ]ñ/§ok³ÞIìÜ~Áoâºö¾25OöºçÁجýع_oà;6…)x½o«q(Û†gúA—2,FáåoÙäm×™|àé®íj¼r¬´=9Ê‘})hk£›Þ.êaýﻟ‰þÀ¢%ýqâ4m³¹×}™óôqEŽîJ ÌàJìäºá­²×>Âø©#LJ½ Z`Žþ(-JŽïÆ&GJß±¸J׸F‹“‡¡¬uUÈ׋ m›¢Äc=ÃèN€ËÍ97-À!ô€øeœ)GüeD™çôš˜Æ¥r±Ì`œ‡ ÎÓL8‡­²Ùz*lÊÁT/¼’#‡{Ý<ÈÕes„K9;2å›`V”¨AÖLkc†²y8g¤A¥G‰Ó™¾ìÝäx>J]×Ö<²ªŠ’#‚{ªJœ­ó‹FÒ^¤iÃ#2ºH…/“ Þ`:ËuoN¶ÉÀá;xd V™âìVWçü,¤“Ñ»Û5þxÇ^¦‚•Rn†gÈÍ²Ì ø¼ï¦®Zo”ò#ç¡:ØS¬Ü KWO«(sÓ¨hU¯âÀM;­V_W¿^@0 ’ »2Ï@£JÉ•T†¤>®ŒX‰ `y–,>•Þ—YV´–Ìã¶ã/I†/e`ÃeÆAl}÷!Y›PéGn”•__šöVq,¹å•¸*é‡r”*ÐyIJûM°oi‚ŒðÖß¾¼ã¸\¿¯óƒ@tWo׿D¦Å™ºQ@(ß›>ïÊÙ:Ã/c¨ŠÜ,\‚ß¡äÂ(sºL£1r戯Øw“ ìáŒ\¸>N]ÏHtë0öÍŸ¢“¨Ô1> ¯¸NªÃª¿¤ù 8mÜB÷=:3)'¢P8Z€3¦ ¸»½¨ t»I´ô Ëï&L=p÷¡+Í#Æ?ÓóÒdi8)ô€l¤JŽ˜ô &ŒÇy‰AŠh…ÕÅyµŒÍ¨l°Ý\WUzÑ’sÀJ"Z®ËòÞœ;úìàçeñëO9 £ÿm‡üAˆn¬†ž7Úó¶>Œƒ¶qÀî5EÚßqæcèQf„{[ —¼ºDç+6ç… õAÚ8â6)ÂQ>`3ð‰Å/ø Â][1¸ $¥Œcˆ‰ÿ\§¾£«‘t öä`  +âéŠ`q…àÀ „ƒ{Ö±X“p4K_÷d¤AK&Šm&ŠAêݘcwÑ·Ü•¨¥s¡ÛŸ{V¹©õ,̳J9O{HD@=ÆÀ,šñM<\ƧÜ$–‹0®\Àå'®Xâ»-YÔ½ jQÀ ø(`г°Z˜A—•Cq‡6繑ÏR ¹j u¤RàhO 2bé¡Ó‡=¯o·?ë>]( «¨`zBzãÔ¹1P¾É³Ûî^°`ŒT–á(?Çp¡ð™­%m-¦Ž>ª2·bH¹è¯yÒïÛ±*x\BQSBíõ_99]ñ¦Õ^æF×XMæÆìÞ–%@hav¼Ÿ1qÅÉ^‚› ‰ªÍA–Wþ’í#á`(Xú ÎÇžDŠÁaŠod•@™±`¥òOꥻe9BÓ˜ç‰èÇûž«¾í %#pŒJc¸)€50æØbN«Ç6>aé­; òABñ´|_NÅs’{Æ¡5À\XÑ…~øåðdPš‹­ó¢ÖZ qD¦ÄéŽwó$`¦ž{ŽXpç’7 éȘ¯ ?®ÈJ¿ô,¬S:x+%ál’¯ÅŸ#ƒp —Ú̉ì,åRžë/!Ì|×··}úv{{ ¡ïfj®œBù» ²`-RžÏöå-6}›bg/C’Í€-Gï^ªâü€ˆ\óTÖôˆ•ùžë+ó ±ªáÌ mSjÑ3à¢- x‹ó«š"¥iªóÜôýn¬°×B€‰C¬«bˆí[ñ#ÜÌ[:^È­W`ÆRž-£xÕD*tF—êS0*[j6&ßHJb4š…©ÐxžOÝ6çoî²pMr|pRWø¶®ðÁÛG,ŒF:`^Ÿº$,"ç£\Ø6Œ.°Í=ca|ÁiUJ—?½2p™D²BñŠu!aº·áÊ Þög'–¼á¡î6‘Ÿn¿üöãÍ÷ïo.I+æo´Ó~&uT̓îYb+†5ˆ/ÜS¿ã…{Ö£„/\™`%gñ Ø÷rǹWú™xÒâø\-Â.U‹1U‹çÙ•/¦ÀI¯©²øS®‚Xˆëc1Yèíxƒ Ú¹[‡áÖÑã3jÝa„À(eñœjur§•å#Œ¥A¾h·4˜ˆ W3Úuš—,­É²¥`ÞÙüH¥J€®,²_36•¯?ýt©„ Mj=üÌšJhM…Ö–¦Fþ‰©ÁŠuà°ÖÐc=ó˜^ÔÈ\ Üh .¿ÄBÎ[S;ïdv6“ƒ£Ã5c¥Eªø8p&Cò·¶û}*NXkOÎ~¥øüéýÿ³˪ÚLô¦‡ÒäWÃ0„‘í' †xÅç‹~-ƒƒžŒ{u”ûüí:©ÓÙ¼ˆÙ07¿¥H=ˆƒ“*ŽñË,í—n˜éñ6ŽC œ¡(:‰$gÒ>‹*˜Œ°¸˜Þs©ÅžŸ›§²‘÷W›è‡ï?Þ¾%¬©P›¥Á¸Ÿ›ŽÀ5ÀØ n¤'WT éê²Á‡^)oF3köÍ’h}!\t5Ÿo~¾½‚åsMÝœP±k<â gPû*:Õ¾²Y ‹Ä4?§{ÙôœÎPrǘ×úùB—XÖÐß¡ÔlùƒÎpK±ç%ž;Ò³’Qt²W <ä´Û„avLnßàšÂä¾úI¶ž`(/¡XãL/¡Xý@eƒÒòaó¸> stream xÚ•XYsÛÈ~ϯ`å%`•‰08ÊCœ¬my-¥Vy S»0±.KÚ_Ÿ¾°­”XÂ=3=}|Ý=›ß6þƃ?“ðó6Åióî~óÝ{?Ùøž›yÙæþó;?tµ¹/ÿãüãÃÝÏßß¾ûáß¶ÿ½ÿHC‹vñˆêþ¨·;åùN¯ó®Ø‰säþ¶óž;çNŸòaìtýƒîNU“º|ƒ©ó°Ý©£‹|ìiÃÀÌÎ-ÌE±ó«.†ê3î*ㇱ‘¶ážlP5܇í«qŽ·Rn¿§êw]…Ÿ:GâΙs3S 23žÏ¼mÇýº:U7óFˆ à ˆ¡‚¬Ð´4qª¦€}{æÈör!?sÊ1¯y°¯NçZ?s§mê—ýÖi/³yïÏUÁ¬š›û7?~S5a”ÕĨš0JP51©; Õ„Q¶TM˜yª!’£4&þ±SÁÊœ‚§Š¬p%}¥ Üt©Q*tôs¡u©ËWßÿþÇ×Ü_ÁÒ4Û4ƒKÓê¥iá¥iÆ4±Q¤e,šlWÐ…tCè¾î†–ó}¼½{ÿÓ·o‡Î‡;þž»ö¡Ö'îTM?äM!$Ì4šÖÐV'²ChÐRa%÷ú¶ű ·'ÃÄväT®ְн³»Öu…g+å€ËÿÃÄ?Þþý5+&>Àèf@ǰ`˜_qChY×BëúQ:_7<ðw¸>Ö¾>MU+&¿¼þÕíýÌ™ðÝXÕîBRŧÀל¢|#ä¥XüÈÍBØ&u#e‰VÎ8“’z?#§0i¼ó»÷™½D‚49?Lü„+¿çnyñ´ÊO–¹ bÞÁ Ïbçf`È à› Kãhî±ËOÜ޹]Þô‡¶;õfFs£íªGpÓšÎÝAæf±-kš ,‹€N/p^T{Ï îÁ*IÎʸµRË5Vø²–¿yÃÔú·âR9y ®&@tþ%o˜úéXMX“§;/¼BC¶›$àÚšPî^2À´j8r‹oYéÐ9éáØÒö¥!#þí“H¡÷n4(-†Àt$u…ùæÃW–­NÐ&v9Êf$%ئÓåX ›Wüsñ-Ô ý¸þ]s‹",6à]‹bâëâŠÐ8GOº©šÍLÌ*-T{’ 5õsŽbÁئ"8KWB ¸8¥oO ˆeÎ>®n)@†Z±öñL€{:0Pó0†V÷ÌÛÃŒl­¦mv ï‚»lM]•ƒXzŒ]â+ç– ,4ñ 'ï@Uà¹f`Y0vù˜V‰nGQ/Qâã+lƒ0°pJ á|)N¹ŽÙA$† 2úO²¾åÑ錢íàÖ[Û”lÕ´ì ûµ‡yë.!ÝŲãÙ™u-ˆdÚ;¾Ÿ‰…GâÜÐoÏx(Ц 2uàA‰¾ÓµÀa£×¢[¤nf¢Öc}þÙ8ç5jÆJÈP<œhFþdHØ.õ!ë ÄÃ⽬z´H4 ËœV7dʼn›ÆKA•¨ÒP@ ¿ºÉ)†±AVEH¶0…Pù3 ¥Á`ý][óÌ98×ÖòHb×3•mõŠ0"c“õÇv¬KÞ|BJ<º×Ãt‰•³ÒÐõè1­¸ý¸rÊ\/¢=ìÈÌìÂ0s“E\ÁkA :c. ¹ü~ÿ·ÅÅ.§‹÷da¶&tybö¼…é!†‚˜Á(µ.3˜7pëéˆÙ$¶=3=3+å¡^ÿ5GǪC10*ßDVh Huý £á¢©Ôù'óO‹?o aßp­C^‰Ø+À‹Ð …Âê /)‡]¢ pdôŒÓsD„Îl×®le;Ál¦Ä÷9òŠ:¢Qä+8GP›"w ÎÀÆ_ïnxh¢ã!L,`[7½6cùÀƒy]óP£ Ý÷y÷ÂãÌRâà  Ž;s£eÚ§ ¹’ÞbÔ41¬;'¾Çp'‚°*g C³†f‚¡™AáÌÆÍ8³k ,‘‹­Sô®åˆ ’âtÞæ*`¤«†8e[}~’eèP RžJ$g⽄ªhOçq0É[YoJ  j\2Ù0¤¬@™wÍâ ô±Q2Q`zâfиÂ>r/šÄDê–¿,®Äˆ‹É¹ŽÀiò”3vŒRz„(¥n²+æÛâ³qNĺb8]ÑE”‹àó 9ü2ÌÏ!8Y„`Ûf"±™h^fÛLdÛLäyÓ´ƒr.ö¹s!¸Û•qpîç‘qvì^s‹uÀ8„7Ï›R#X5êâ$`ÙÙ Új;bê=­Íf-/üÔ”Ñ|΃&ÿòR†žæj©aêJŽ · ßc#À¾%rì¯eìâWÊ.9–N£,TjY,qpYHz DÜfðÒs*<œ¬é5µãOSV”„Nwš›³Š“ù‰ý6‰¬b-+ÿdë.ôp£Öl‰…BÊßÊÐQˆ’H0„ˆ]vƒœÄ©3³€¨È¡eÝr6>ÆÀØ.4б#Ü©b×Ê šL€Þ€’EÕHùŠTsÁ£”ÖÚÈSRMh˜:*ˆLÓ€¼Ykm]ä>­O¼þ-M|¿ò–ë'®Ÿnvˆ#MØúšæívç{P³·¿BQ §ü…?ÏÏÏ2Ãf¼˜|yyáÆÞ)Ër¿]±žœ6›Ïúí[¬œ#ç—µ¬,ô\?”„ 8[3IÚ“)þ„Ť’úÓXJÚoŽ8OÊOˆ+‚8˜¢ Û®òàã«ae°ÎDöU&Ô…AÍ õX|=ÊÁ §ÛØ’§? à4†>W=ó—âÓb9Ô|ûí~öøe½ÚñÜÄa½BœI&odžÅìBœ0 ø/`žô</|é½AËýÝØ€R(3[J‹'‡¯%Ø @¢™Î\­y"$ØRH®Q,… $E>š¡k#nI%˜ò¢î¶N˜º ³|èŠ<©Šqÿ/ÄÌ!8ÇLËêˆwq˜ÒŠ00¤ÿúÃÿ8_ü endstream endobj 418 0 obj <> stream xÚÅX[oÛ6~߯ö2y¨8I$uYŸÒõ:´kêx{Y†@±h[«,)"Õ °¿Ã‹dÚ¡c·Û0$€Iéð\¿s¡¼;/òBø‹¼4†ÿÐ[n½' ï‡ç¹…(so±ò"ŠrâòAâ-Êßý'uѼŸý±ø‰Eˆ#„%?I³eEÃgN_l !W)¬˜^ð¶þ0‹SŸõš¤âæ9+ú¥|±©šµ~µj{ý®ë«mQëõмº­wÜQµÞ |:;ɳÏòjÛÕì“Ò? )Š)؆¥Jo% c#å ÊG;¡˜ØBáÝ(–Z(PìN‘Ï\ÎÍÅJ .X_q—IŒâÔø÷Ú7QjSHk4Á÷A˜Íù™VmŒ“R\Å 47&àý8Á¾2¤‡qÂñè0â·0ÎÖ \^²DL¡yØOã÷õÛ "ÌzQ-g4ò‹8ñË‚o–'Ä2ý”ëþ:Ãua8¹.ŒF×ÁCm<²]ç¹v|¾ï:ùJ»Þí\œ,×Á«Ñu¶0I«‡Œâ¶]A¢ÛŽû xbйoåé,ö»¢/¶ `džßèb£L‰õ¹u_t½-_öÕ-Ø”ùÌu­K á1BãȪ †¾gš¦þ¬IÎJý²jô¯6=ž¢Ÿî\f!¡õy+÷R•Ôok@ˆJöÑ”)ÙÐÀ º]é_¥g:ê)ñië û¢7Àë0ØÀ;å¶)§’°e–>'eÔ^¶‰~XŠ8ð‰ó%cu]×Ý ß.;W‘ (É‹Q@â‘Ìà ’+ºªôÒ˜ú[¾VGž-¼;á<ó>z4‘Ð"¨>$õ¶^¢ˆNûÚ»òÞéž±'Å¢JR%¤fêÆ!Êv‰Y²U1ÔâGg‚RÉQS¾x}yOψ`”ç–¢w‚Ojj“Uß\½¸Ï>¡ÛÜ“ ¥gp·È ÷‹×¯]y–¢(ßU Ø$G ÜJ¾7Œóbmð"=*UT`ë¶jÆ¢Ú¢Ü. mÖàÓ0üæíó箚 „LõQÉkZƒ~%à±kú˜Cʳùü<)¬ïG»Š¦Ô&}”f}c%˜r˘ËMýù Õyû˹6÷¦[}¥Ýîà;$­†zOŽ6íruY»ÒR5+©’l£^£3®gè!ÝdúgéÏ„«y’zvŽ&åhœ!yA É”È$‚‘1£ãþhYTZãËù«7.Gb‚pr˜E4”s“Œ«©{(ìˆM«J¶A—ìÂms^ÂUê_Ù•ÓÉ[!á«0ÜݦÐã‡&¡ƒ*Þš<ýõ«õÈl=ðñ¹õ¨dO‹ËÿHG¦ë*@üÊtÝÊäÆª¨jþÈLç+¡§,í[Ñž;ÑCf:²X,e>œÎÿ´©ÉÄ€{ @8R=-G!žïi;2È7•2 GK‹³¸Ã˜œD§¹[d#÷«gGzZv¯§Q•Ì;ô^?j00¶¦ºØ™9¸¸¹Z<=t\|о«éõµ`Ÿ„žYuhß{=û‚¼énãÒ»dPêÿÉ–‚Ãuuz0äæúÅÊ5; ƃɭ¿]@N Ð!0¿Å9—À 2m…vGd©•clKä ý¯ gª:OzF$:CQ‹Êh:wœb”›7…û~vš¹Ef¸¿¼˜Ÿ p øˆm˜Ìe{áÍÅW}þ¿¤»àþ²èûŠçhwçº"÷ûN9ïe;¨/0ò®h‡Oáà†m,‡ô4E˜Lûcᶨ¨Ño¡Ç¸ï*ÑÏA R³å'•Å,ƒy¤f}Ñ,eã"t¼“D÷4øÕ8’pÊü÷šHµF2~ƒÅmÁᬖÖwb¾¼ÁïÔa=~è’·é,SŸIM+l‘E³6J‰ÍÄg¼.¹rC_Þ´ã4[2=›M wc‰Ûé+Q%ÌHß ½¹Vs†Œ¿ î*–û^ͤ¤ 1Íšà‘ôÝ7¯Eû endstream endobj 421 0 obj <> stream xÚÕ˜moÛ6ÇßïS襌լø §îÕŠ.C‡¬YQ° ƒbÑ13Yr,©Ù€}øÝñ(K¶e»^ƒ CƒJ$äñîÇ¿H{÷øÇ½XÀ_àÍWÞë™÷òŠÇX¤Þláñ¥Ê›bEäÍò_ü¼jï =™†"ô›ª˜ü:ûÁûnæ=zL¦‰÷äÅ’¥Ö>޼•ÇLª®Xx¼÷#sôFÝvØ—Wj×x ¬Á­ŸëEÖÍ+g¸3ž %×Óxd0!XÊ»Á&Ö`Ê•baÏ„…Ò¶Ì&‰ô«Bo²rKV÷ÛZçôÖTøþ|"b©íãw¬ |³ ¦fézÝeµ™S]]mcª’J¦&ƒ¼Í ªYh°…³É4R)¬ô›§¬²…™"™•÷šfk–4Šð×Ù&[éFoÜ‚\î$. ×ódšeÕÂ0RJˆ`“™Wƒ¥¶Ìõ¦n²27å=U™¦Æå¯ÛÍz2‰_Õš¹hc"¦’ 0ÿ¥ì1¡âLÀ(v޵ù4–Ú€%ü³9‰zNx06ZÂ"¹J¢"æ(7K <)iP€„+C_æÞF -p5€PÕX Bz¥K¬ÃD(ÈHµ ~ĘÔfµ.ônªŒ°‰UÒaµ„ t"N60˜Åfœ“ž# ÂQlÔ lä…Ø¤ØTwÇÔE†,IòBåsú"#Tœ¦(žM`¦o^_¸É#ΠGï(‹øYO{³­«?~ûó˜¯1ãÉ>–Œ½£_׿üi9°¹©_˜•±™ ,MRr¢ÉVÜAàCÿAÏd1ò5õY´å% ØRJúodîúñý~±ïÆëúQi£3'•5 Kº…M[§¸$Qݼ"ôM‰î·ú«¹žoP2Ëû„sK¢Ò’7càyeʬÑõ¾¡Î6´?Ý oýu'Œ¦$Ò·Ö$Õ¶_·û°½*‹?Qž™ô4ajø!¥ò9ÒÁ*¢Oiû|¤}’ôÎÑ-§=š9W¿„ôk”—k!·D M|R±bs±‹9'Ì…Øëía>èGV{˜‹ó]§sx9¹² 4åÿsS6Ä8¬|Ÿºã  *¦ä¶|Œœ• sÄõÈ9@\ ùÛw³CÆeÂDƈLVd˜Ëއ–lÛÝz¸ G6ÈÁâ!9X»%”Ü/*ÜñXm3d{ xA“.KE¾ï5iº(déúo)Ú õFãêôH’bÁdtqº¿¿þéPÒCÎ$r™(_tø¬ÄѶ⨦Ì$9~suõ¹¢¾{‡·èÎJ îÏS¯ÖéWGT»–öÛÍ»‘é•ìyþ‹¦Ñefÿö——z{uvéRãî|3æÂ”F·~¨ÞÑ8Œ8’›úxºÚ¤ìþ®–ØßÐ"G’Réû¯þM”"; endstream endobj 425 0 obj <> stream xÚ­WYsÛ6~ï¯à¤¥ÒÂ}$mgšæ˜´Ž­ÄJûPu\Z‚,¦©”í¦ÓÿÞŠRtù¡¶ÇÄñí~ÀÀ"ú‘Ã/‰…?MÑóQ4x¥"‚‘Á&Í`ºï:2M_Þ'‹ef{}¦YLzŒ~4ß@  k$Fs@s&ãY‘eEªø.Íoümµ¹Î"Is×Rñ²,nÊdá‡K›L+?~6ôC0Ù…LóªNò‰m{2Æ„ßÛ©|;¼l—P.’ÚÎÊbѬ¿ß.™!!š%;aX•ßÙ´Qˆk°ˆCQ1»å -–Õ3…¨ À'ÍüËQ0õûסQÞxc0?2ʉ)…”ŽúÌ ¬YÞÉ:± ±É¤%Â*‚-!Ì‘I)W“¬Æ(“Ü}EœLo{>`«©ŸIó´N“Ìw®“*­ž¸¶Œ«"»íÁ×6*X\;:±È]ZÏýxppMºðE\¥Î¹÷ÞÈa™‘¶ž½>ă[ ãñ8¾vÑñ·ëÑxjgÉ*«Ç=·$Æ`ÙvW¦u³.Ö® °àU¹‡Ô…=ìG ŽãtÛ‘õ}}À‘­ÇQë ï6iH rDÑ6â{}¶¨–÷Ä7A×ñãA#XJ¡ öë4Ÿd«©õßUõ4-Ðü‡èÖ!³ôú ¤Ü‡¼É–mà:ê4¯=Ä%Þ8¾-Ò鸷«îð‘è¹r‰ö2|Ö@©F”o‡~þ{ÿqBÈàÚ6²ãxÜ{¶KáP.ͯ —Æñð‰—}}6¼‚̽zñò§_ÂÐù‡³³Ð|ԥߣƒJ!䯚¸î´âƒà®Ô±}k4z^_AÜuøG] ^ÒÔfvmá^XiëU™‡åúùþŽÿÝuhw¶˜m܉ú¹ DzO¼¹-CR¥•O§jîçsIifËEš7ÙèbU/Wµo7g«ÇÌÓ«ë³Þu 4¡¨aȯð=ÄFsgˆæ„ ‡¿Ûá4©ßò”®õgß „ví;ôžz}T¼ú•«]ÔÅõG;©Ó[pï1üìÂ4¥~¾,îªD(â[8—ùzœª|3/òþg[Õ®Fiˆ *í¤(Ýåç$–K•Ý ü©Lª9Xiï–/ÓÏá‚(c›|Äì;êø1.Æd1âC’kÀ°5ÛÇ%q)!± ”œ²#GDÀЖKµf„ôÖl“ïq£œÇJ‰ÃþSÚPA„!'y¦¶O:{îÛbK©ñ±‘Œ .Nº"-Ôƒ(171ÁÇ81å† ,õɰ1B'=À)¶9éaN…´ÄDqÕ˜–ß'Ø¿‡í“攈”)M4?ɉ™„}ʇqÊcœ˜)¨º„Ô'81?ŒóH ˆ!HâcœqîbH<ˆ“âcœ‚jÂ%‘â§AJràdã$TáÄàK¡õÿcÛ‹áèÍÛÏü!tyqöaôæâÜK¼ºøpþbWâ7(½×÷°««BaÛUßÍÍRlßÃP­ïa¸ê?EˆÝ9Õ® YDDC™½îgÑeô.Ô"‚zÞD®r¡à?Òˆ|ñ:òXÙÕD"aK ‡Mx‡ºJ„n½ix1ºïúÅHÛ#ezýbtƒ“$@¡¦&ò³b•O7Ui_!¹s[C•îÛîñÚhg°+,Šü™{ýÀÛÅ®Ÿ(ƒÝ2³zùt0€ÿ(o4¢¢¼dË+Úok÷ ¶Oö¾Z6KA w;¼ÆúpaysŠúî«ÿ¼ôX endstream endobj 428 0 obj <> stream xÚWkoÛ6ý¾_atÀ&w1Ã7©fÐ.ÉÐÍM¼ÖÙ>ÌC&[r¬NO’“`ÿ¾KQ²åÚ¦Ö0Ež{/ïCÔàÏ`ø#Eá?,ÒÁ›éàüZ F>öÓ%,̃LÃ_½«ç ]'ÑpÄ4óèð·é€æ4Èç`¡‘`µÅthN´·Ì“$Rå=ÅÙƒŠZ6N|/ âÌN¯‹ü¡R;]æÉ£±ŠJ»X­|¤ óxbgÀnžD©Œ³² ²EJûÛJ\u•IíǨÝ:CBÔ[æÃ(×›¶{8ÇõVÖ!ìBѬĕùeÞ¦4ûeŒÛýš©p$vTÆFûÙ®§QtF'<³3O«xaHW–Ü(ª†lYä©åØÒ/à- Îâ*nuæA—¨vîjjKø@C,eXºöõüåp$(÷Êõ3욢…yÞËóÚ°” ŸÖØÏãl‘lÂÈZ|]Vaœ£Õ·-p—-‡À$ž‚ÇÉún'g•…˜l™yyΆ‡ÂÃJ@ϽɊƗÉE ¥QÞ…X™.Ö¶ŠôâsbW¿±?ÆdQDAÕ3o6*®æêu;ÿ-ªø1jpï1ü;„iJíz‘?•M&¡ˆ-òd“fÛyB¨²Ã,ÏFEE^f£ô‰ßPF‹¼KkñTÆŒLe/hüªž'Œ m^q¶u,£ ´„P  ìD)‹¾ÂÌÎ> stream xÚÇŽÛFôž¯à‘ –crfØ“l°vìX>eƒ¦F+&,2ËÀŸWf$ªd#xaNyóz•÷Ý‹¼þE^*á/ôÊÆ{µô^¼”E"co¹†û EžxËÕŸ¾™‹ ŠdìßÕÛÅ_Ëß¼7Kï»'Tžy^œ‹LÓƒ4ñ/Q"Kݶö>{ŸÎØY"æ±(ÇE ÒØÿÁŸ¡«ï*ò nµó‘·}÷­6 oª–¿³×E_›ÆŒUIŒ¾x›zH%Ì‘l`éÊXÄ)ÑýüÔvÛ¡œTÌêüM”Š(ó‚8!?©Z ³2¾å[Z"g|ñóÇ+^”];Ì€‡¦ÜZˆmÑ7·‹_Îñh F™ˆ|m†²¯¶cÕµ^Ïù‹E®çàË ªL¥~ßMcÕûæ@¨$`àwbœARKJ"´~24íB¦þXŒÕýBf¾%Z5[0Ïþ®kù¼[ówdî20dյŅЈ¥ ¶›b°¸BöÈ0`ÓM·fEŒ‘Š„Â@Ÿ¿ÁÃÕ"ÐRûHUËcàòÖ¾]0ÐÞUÄ"H£Ü¿¶ ()~~U=C’¸xF½JF"gúu’œj8qê—Ñ:õAF™°. ëµ·7ëÎrRÔ5k@eÉ ´õMÒ»é[T­Ì¸`³Øž€t#§ÁØ“YÌÀ^“­ðÜ)Œw„zj'ðsX›~Öd®ý‡ <¶7L³²x­ö‰hËߦýÁUÉhµ?˜v0W$P8·f%Œ@Áµ¿î 9„²N¤Qõí*ènÃHñ…éû®x=µuõòjTÜÅö.Ø’ÿtVKx-¼™8‰§݈O0}1º•=zÆ aŠä¢ KDª-1wmýd‰í<]0¥´Bô]ÍM ÁôƒÛ °FÍÏX†¨û©§þ,Ó w,T47Ä.sr®c‘ɽÿ¢¶[`/¸:‡_'"I\B¿ÖUs­Ê,DÑ®Î!è’ŽìØü-”£$ÎæÙ,a2·ôÔÒggÊPȈÀBH”ou”R‰ÒQ¶/QxXA(ÚÒðä6^|#O4¦e¨a*K3 ë©&£•?tâDA’'¿–›Ê¾.m"´XWÇ£ã<Ÿ«½Ë±Úvçü/‚ž;S6¹¤`ªG!XˆÁPB>.ùP¹°€3ö18ÚqßóË ‹5F.ÃtPѨà9<˜0Ù °±âL Ç6É Ž ÓSDï$q8Tì` Òª—O±bàèß+^@Y8 <´½’„üÝÍǯo^½|ýêŒwjþÒà@@æT6” !êŠ~´G\áÌ}‰Ül®øÀæÕ²˜ ²ƒ­Új¬¨^¨t\ç4SVç4=Pc4¾o›à–ú”ÄÿÛØtt˜w®·œ$ïXÔÕêÇ®pŸ©|ÁÙ9#îJ^ÞúÅôXÕUÑ?áANM7. q9Æ E¥uçx°_ô[n¤™SÞ kb ¦ö¼¦ÄkbyÕ–Wù›Zû®jÞïÕ†oPm1©M\ê*Ÿ¯?¼»ÄU4h“;ŒÜ¹Šv®BgsWѱ¦Â`œ_bÎ…Ý0 ÏK$å~¦ÅÚPò¯Ž!Û"Kü‘kÞ€pR]›Ww¿`è}‚²µ³5Tx°ßèÂæ$ÞlmssÀz× ¸¼`y<¿º±æbJ™!‡A¢3bS§ôÓOÿùÀUâ endstream endobj 434 0 obj <> stream xÚµWÛnÜ6}ïWèQ[d‘"E*yj`»hÑ:N½}Š CÞåÚ*´ÒF”â¤ÈǗË.^Ùò† ,‡ÎÎgFÁ—‘þÃ'ú? Ö»àÃ*x{‚ãc”2¬¶z}‰#”&Ájó9$H x±Ä˜°ðºØ/þYý¯‚/ŠSÜ,E‚š < vA#Á½XçÁ§ €^ÉäeÞX Ö[‰tÎr¯ä,«Ýz¿XÆœ†?à‡¨<+òÿ¤•U¾Ûò›ªâë"ŽBYÛ=몱©«ÂNì³:ÛÉFÖʸûö„€¥¾tè„!Æ úù÷²Ú«\ù³Y‡‡{0GXKÆPÄ](šÅ’Ù`_‚³—p„ #ÚÃÀâÏÚ‘ÝÅâý”Î$ˆÅÆä‘Të:ß7¹>Õ§CJéP}u£CCÖUÛä¥t{Fn3h¢/ èàÅØéöÑW"L¸‹0Lô~£'xÞÞäkP¹±ëYí¼k•ÜÀˆ„W°üÆ:UÖyÒçtM^I¢óúÆ8¸Ä #ŽõoŒàâhÏnóF#Äqnä6k‹Æ _Œ†YÑJ…Ì΃hymsÐfVÛÊÕ~…óJOŒ«'ÊÈöxz‹jªÚPOæ¥Ë¦RAt.äâž4P2¯¦šº]7m-!ÆŒb'Þ]Ñ{7¼Œ A,nå4I@ÁBï!«a•Û8(ˆ2 › ŸÈ]:âQÞñ}é„ÉÊsŒÔã\Ë F"ˆóm‘ 1kºWr–U“5­²„ãHi1ÞÁ[3âµ,e­3b9i ÷ ~¯2Õ-WE;xÙc>2ÐÏ #‚»=#>ÒA¹´þXBÚ×Õ•#¤³y6¢Æà_R_¼R=š‰¨~·0QBP4d¢ÞÅ ()±S®¥»Š5ÜB ·ÑÃuñÁÇÆÿ‘溭ki¯2Lt™¥.3Fs[Õv{-i×µ7ƒç£¬Gr_D˜Âëc]st ¹³|dâ„ÿʵ#¨LÙßmU8r«ÞMÅé ¸¿þqvùñl5¥DË—£ã“—$àáu”rckÆ!ΟјDÀ«Y^wµ¤óXÕ»ÌÙÔÙ•e€¶±²yÖ0è8W çÜq.,÷žii¹µæLÔ²©si»ÀÇ©o1†@ŽØÔdý“íøÁóÛ¾Îw†ä¦H4òaÌÊÍd¿€ÇíÜ´YqŸÁT·ož`®Ò”Æ÷_ l¾JSJ Q華“gªôç*ÝÙ¶UpÆ´Wê,CŒLc¨‹d`ãÔ´@3Ö{µÎ¾‰öðÃÄ_øü° S•ÜÊŠ'uúñ´>€ ­ÍdÐ]Âç´ñ³ZÂÓ™q·xø©D}K(þ¬+þôeÅÿ TÜݺ{h™iùUÚy^¹5˜wàÕÛÛŒ]6ôŽcò[®5æìÑgpÍ– µ´@…WýôÓÿ‡²„ endstream endobj 437 0 obj <> stream xÚ½VÛnÛ8}߯à£T¬XQIiûÔbãÅ.Šô÷i½0›N(¢«Kœýø/’e[‰â¢]$€EixÎás8è "(„?‚Dÿ!ZÝ¡7sôrF("§Œ¡ù¾$Ä)Góõ¿^„Ìý€ˆy7ÅÖÿoþº˜£/Ó4A;ÄRœÄf‚àèqŠÑ t…>ŒìƒÉlN€“ ±N8N¦pû»n³âV‚º&fñ)èA”¯›¬ñ*˜÷ÍþT²©ryïÓГúMlBÚÚ~Uûk4™§ë¬ÎWö±VEÛäª4b_ÎÒ4aª‰ƒŽ9b˜ Ã|õµTÛ:¯»¥YµÃID`™` ‡vJ^‚Vf·p Ù^jK­oa^m+um^¼_ø¯FuXL’`F æGÙ´UY»ØxHÏpCçŸuFXäU ÖYJ7ç@3qÌàì™óp¬rŒ$$8rñ•ÜúA$”»‘2œ!<“Mâ¢Á3Ú­€†ao3Zûª‚ Šc>Þ°Tj÷H¿ò»}èg俬J8Ÿ¨h «¤S=‘2Ìã“2á¢/aÊ8û>fußÀ]mG²¶bôçö!/ò¬új‡P`ÐiTyf¯ˆ„ù*è:–Óxر¬ò¬1ÐPc»¼ù<¶JÆq*œì|dY ‹Î*@pÖb[ôG¬ñ b®óytõ¾»virxçvÍ<30~ÃÓääzû ŽR•Á#> stream xÚÅWÛŽÛ6}ïWðQ.*FI‘LÞt A‘tݧº0´¶v£À+9ºÄ ÏðfÓ¶,ÙÁ. Êžs8šÃ¡ÐgDP‰þ´zFoçèÕ¡ˆ¬8GóGx“« Í×ÿF)–XÍbBR=m¶³ÿæ¢ßçè3ÂTI´C\aÉÌ‘¡g”Q,…¿Ý {ôa€àäHžŠî X¦Xˆ°Ì°œÂÝÇ8ئžÑ$ÚA“Da`Bq:~rèÛ¦|žÅTð軽4E×”ÅÍYè_˜@@€¹ÑñùƆ~™e$Ê7}a´½ºHã&JÅŽ)å˜ Ãtÿ­ª·mÙú…Xqá"0¥sŽ;e]÷PÁík[B†—M½[j ó˶©ìó_ßÿfeÕ¹ÁböfP™¥!sjhþ.º¾©ZËBE+†Î?š¤(HJß••_ùÑ22‚ õgjâDõ‡âXHÞ8%@!©– ¤šs›jÃ^?Úkçåäý×rSæÍ7{ á,Ê›27éÓ`yÛÖ³8•Ѫ̻bmÃve÷qh"¨[WŠuÝ€²r@9÷ëŒ(¦”êbIE´ÃÇoùÔ˜Tiïxg’dÄšY†yf§dÊ\$øp{©ÌAŽfЛ 3 +ªßòtå°½?Î Õ#CBVÓ a˜£X÷ÖslÜ¥‰w©7MGàR“ºA—2zæR p©†QèQ&¢ETâÏb&a·(ÖýʸâVuÛ-fvlŒ ×Î+¼ÇtFÖª /‹4´¦³¶8X›²‹ÖÊ­ã:O§ÆÓÙ”§ÓLê}lïi2íi=êÎ{ÚÝŽ{: ñôÙ¹u:ˆrØ«z3àçÄ4ó=8! K2‰†9ø¶Ë» ?ƒ‚þ¹²Ouxß;Øaßî`JR½=™BðfôFò¥&¶ï§³/€Ø—›½ñؾ^õ°}Éy“…ª^õMSTºgu–ÓåÚŒÁYåSe,¡]í®V^¡M¿,³¤ü´ëZ€:ö¾1*ôíÁ®ô¢]y†•_æ§+[ð¾r`œ·öúXo6¶3·¯;>Ëô±1x ¼{¿|{?@I}¿[臼-Wv&àÍ •§½»‚£ª«øÝ¢j·Þ²kíþçV;ƒOÑØ˜sþ©ûj}µ¶^D[¿ÝšýÚ cF˜¸MØÝ훢°£EÔWzG×¼™á-Ö¦!–°á\­æþv5‹„°¯¾úÜw¦ m³C—I§»ŒžBؾ˸Ûñ.ÐŒt™=²ëÐA”Ãë2{p¿ÅO ‡aÞÛ]Ùenø´ûßM‡S†¿xlÔ;øuw/×wèÔ±^Âyß¹üqGÓ³¾Cƒ;z|p¤Âž ©?RuÜgèÉ¡ÐL9ÿºƒ°‘¯;‚Y؉në,Ç 礩ÔqÆlYðć~øå[p endstream endobj 443 0 obj <> stream xÚÅWÉnÜF½ç+xl&b»W.È-@ $‡ ŽuóÅiyhÏ2äãSÅjn#zd‚@¦—êªW{1øÈ@ÀŸ ÿ"(NÁ/·Á«×RRòÌÚàöî#)x·ûwLñ”KFR*ËÞÿo~½ >\gipâ˜Ûxx‘ÄÁ)HŸvÇàmðfCÀDãe¼wÝ3¶iÆM6³Í4·ú%¾3‘g\ÔÇgŒ%òHfÎRžÊ—X/¨<ï}ŸÃH'†ýƒ?–5®kJ÷9Ô‚9ºñý©¢Û‘ܲÏa,Y~ìÝíÕë$@¦"C1Ñ(GYn“AÎÛ§ª~lËvT„°-É„Ë4ˆ¬å‚žìëþþ,¹ìì{XîÃn8ylê{ºÿñÏZ”UG‹»ðçMh$F¦hdó—ëú¦j=­Y"²<3KÒÛšDJÖÔ}WV£ê+5lÆÁÖ‚"âõ†Œ Ô5ž¼ñHÞÒ°úZC–†­`;VrÇÃÈè^ìûÂ퉮¨ÛnâZ±úÎ:B¬XÛ5}ì×L›2G#,0Œ ¸Ó¨âÉÛ¶#•°¢Ì»AŠ6ì\v‡-½“˜'™W䯢–'Ú_GÀx)Y|—9¬3ž&s›oHbx'sÓö…4žÅ\Ëã‘ó˜£×Y/¨<ï¾ µd÷ÕþyBkɵZˆÚrý2ü%™Òä(äi•Ö{×¹æ„1»È^ï~Êò¼oËê=]{˜*¬î«½ÛW®m7ÓÉ‹ÇLO¿/ÓeªyFo¦¬3¦¯ÀFwMþô<Ñÿ«¼6"¹–×±äñe^O(·„ÉÓËÄF KYBjõ§P¥hiX»f,–"åñX!>n â&ñ÷˜ö(#§Hr;zê£ûeª˜"¼î<°Ç¦PW\«É·ß/›fÿ¬¬æçƒS5ÔlmÈ©f€-áèNH§ÙÐ`æsE‡“‘±T€à¦í ”y Ý2ÿh! †UuG${·ÒTnC{¯™zÃp:j°|£! j0öºsßÒˆµÁÔáo6 Ãý€Ü—¼èŽO´ùX‘¿*Ü&«ÒcñZJ[Ö1šCì}‚myz<º/tÚÖGÿ‚.q`(†©wXìcï¹¹ØãÌ-4Í£4Cz…¦ÔƒHqÀR¥~ÅÅ67¼#‡ ÍØð¬ö °ù€L•©ÁBxTúgmn‹‹Ò 6\ ÖÕtI!à lµ/°´]Þõ^&Zé§ËÕ”<°œÆ_± Fÿ »úa`¹ÑDSŸïÀVñ0ó<]7[ ¡–¦éÆ—Æ×ÊyŽÀ$QÙnˆšàgâ"? ù“}ᦪ«è>oËb°:kü| ˆüè`AƒU0“µòY¿ädÌ4eX‘r.Û¡ â§ÜQÂâ"{•ô|4‘!›‰|{@Yðã °ØÍy× å ÖEÞúÓ“Ëý4)–Ju‡¼[U ½.M‡|ª0ã-6®÷µÈÀ®váú“héE¥R”ņ&g+GÒ7?ü ;ÛN5 endstream endobj 446 0 obj <> stream xÚÝZ[s¤¸~ϯè¼ÑµFAÌV&UIj3ó°©8Oqp›¶Ùé/ÐcÏîþøœ# !ºíÎl65®i.âHç;·OV?®è*‚t•0ø‹V›ýêO׫?ü%]QA¸«ë-ÜiD28¾ûWÀH¶)e"ø®Zó(芦¬›ðqÂI]êkp’ˆ`_t5Òà/ÄASº²*Úõ¿¯ÿsd+e8I&V!Ëçjžï*+9¦(„2+.Ýõb„+&JIÌaÅ(â&Èw-,€ |ªê5“ÁS…§4È}kH(ýì-N‘7MY4£y#ÿ¼ '¼ôf­§Ì›Bìk}Äá…wESé yu§Ç~, `Ið„ÿÍö°Ók­ðü°46ùNÍ2™’,³pÇjRƒ5 ol)‚mÝèƒ]ÞÜa x;°Ann>6õ}“ï÷euOÖaÌeðÃ'|ÀûÌÊM­\¥í£š°Ø”ùn÷Å\¼‰¨Ü”…Zt§ç³+ù¬5û¢/·yÓJ¡ÈUåã÷pŸs\Úí®Ø·úL!Å9̿ۘà”m½û ‹×ƒZ\»Tk‡[c{£Õ îoó¶CóâÝî!¯´üî¡0ÂÊýã®x6O8µdã°Tù›vX=ò|f{ÕK-´Ð¿~üþƒ¾TjdlÔÀI]Z´ŒB¨„^ÓîP7ŸzÌï¶îqh‰ÅÐ.æ½#,"š¶;^’ž'±ótM^µ`*—ƒCÝ”÷e®§Î´uàvmÖã $&‰ú(|‚µ£NƒFD$NͨÞèe5Z&X¡Ëç1>®/ïÞõQ¢(ü "t”U¹/*Ì\4r&Ë8É\/ûɳ €¯â?údPJbjlú:I–(}$Ñ©m@}"` ÌØyî‡0+DÆ!ûÓi"úU~C}9æøÆ«‰Bn©&ì+hÂ. É;¨L2Ñ?2xç“*û)§ÄãÂ\\\•*Ÿ„ïžÁE,ÇÅ÷¼šÊëÄ‘¼¨õ#ŽdêLsã÷‘ŒÈÌÚæT ²„€ª©‚Z@“¦ÏHª#µ=ÜBeŠƒŠMg’ƒÉ=¶AfØÔU )̤Òv" Åà„1%8?U=&I¢T× …zc8ÅÁvÌœç‹7ǰ˜±¢ 41B¨Â&T‘çTËUa¯U%"|y ÌáÑ<0r90¾0¥£ó!~!Ô^âb¦T9!~ë q™ú0pE@&„â0Š²Î¡iJÅlÄüÚUoaÄUf#æBéý eïWˆ˜#:ðòˆùß(ŠoŠ˜J€Ú©†õ¶‘Ê(ÃO2úyËEU/y¬9‰%¶ù)80D.÷·B[ýz&‹1Ejùÿ_tŸEmäÞ†UÓßd³©ÞOÐZ.WŒâÞþ"¼6>æµUwÒLGƒU]…UqŸw¥ÞëýøçuŒÍ–2¿Ý^:KÆâÞJÚÈ$tÊ$}ÔÅnã ?ÐøˆÅ^XHÌŒB‘?½‹Þ¿]‡)èäY À¥'…¾j9ôÌräx96|†`JN–ê¸JL"æÙèÅ#‡”É+–J…òÃè2î%­{Å€®ví]OES¼óIç’¤½5}]Œô©ÄVPJM3&‚wbRíÄ_M²`{¨àJ]}ë÷S`Fâœ“Ž©¨ðde=Y ˆ6"Ñ–5gW¾°l }çwk•’lX€î€£õê.Á¡Ó;í¯¢»¿¡Á^§{=lÊKݯԮ°Ñ]ÒqØNÈE‚Âòr£È[X:,Qy-ÃàO¬¹í°Â®höú^½Õ¿ÚÁñÂX+íàðȬƒ3ÊxD/m*ˆÉžš™É#ûΚ9A79_âŸÄR•4 Í5tŸm¬h8^`d K³ÅcùNt>˜|I8ØÌÑ1I B!#ÑÑN¸1ý馼Pꇦ ³ -ïŠvâ5Á?[û¶B;ئ«MÞ¾âØç]S>÷ä ËÑóÚ£ö}ÿZÀHc¶15…ˆ›õ/ø‹åA=¶Éû·Úpúä©)»®0ï=–è5ë­OEøæòBê¤SêpȧÜm"?{ì—f½ñõ<Ÿe$»ÙËŽÈj·€ì‰#êsTÜkOÈ«Véú«ó»ÿ¼Iœg]Ƽ$#¬Õ¾Ù²V_©’Æ7%Q¨Jº¤cnæ­ l)¹Ù«/ÅfŽbÍb“cCg°‘˱Il¨ÅÆËÝ»þ‚À)ëʺ<ƒ^}ú|ð‰ðïé”>ü”°?¨éèÛ _ng63Dì\ù8g·ž+`E>¦UêšË¼õƒ‘cv3ÆÆ5K’)3ÐñâæIéÍT'Ëžð┤}^Ú{ó’­›á1MÒŠsÌ+dqŒ›/‡{}È›Cûðó‡ÃCõóõ:åês4øä~Q?vå>ß•^übmuW:$LÐâ| \+1œ+ë9—¥ˆ–³ Ô X›Ÿ\AÁH˜»ÿ/ÕašÅC7n²2%Ë ¦êp‘xL+N]K å\ï&âÔë1‘Xøb¢Øg¶RžÿøÃ )D"M/)¤6âæPGQIæÉ4ð£dœ:¢‰ž%s$(M½ÞŒ ›t5¦ ­%E_ƒò©¢#)µIoèdÎòË$ÆÖÇ… å¿dè\ŽMLáòyhRƇ–¢ÿí‚­–/)±ÌT9ˆ“(ø˜ß7yu_è3ýµß®+weÑ´zèMpwÀïØpÀˆbÊÆ*±ãÝâǃSðÖñ÷%F ¨v³ö2¤0‘êë´gL9Ç&Ø,akóv6t)VÉS=r"OkˆºÒ¤_×ÒØ¤4½ºðôV=æøéÞôÈÑ)Ç1±¸}äjæåšIÝÑt?Šôá?&*šýùZÍ=Ú³WJ Áê ë‡þýwÿ­É×Y endstream endobj 450 0 obj <> stream xÚåÙrÜÆñ=_±•—`-„9p•Ÿ,Ûr1ÅÈrÄø%›rØ! Ç )¥üñéžî$H+yMYåÅÌôt÷ôÝÍÝÇØEðŸØ¥þE»²Ù½¹Ú½~«w" ó(ß]ÝìDæzwÀdwuúgpugö‰ )ª¿dPLA{Ý íŒ$ƒs_5E}8MEMpG&Áhúªëçýï!@4f¼ë`? NŒ} ›×Å`x«cÂÇHèöTµ·Q0M{ÛbM «%k‘±]ýÄïRaÛw­8U™†sQüŒƒcP…&Üâ<³˜pÏ>?f8mŸ[E]Ó!¥Ã¢=Ѧ#÷û€ûª¸®Í`ùzýVDžô•’¡J@GÈá'†ðÕ“„Rññ«-i¨R>?FJlbHÄŒá òÔ2ºJæ¡Ð3.oâš™=îÛÃ]U¢zïðÉ*бPoü`ØÌÂ(õ51‚úU±#°ªóˆb¬FTèg:,;PüXuí@0Ç@†":î³ê¸ui¥‚®ñÒ}ÕMCýy lŠIÆy‹/“ó¡ì4±ÌÐ8Ë•yNÚV†©DšwÄèckÄ=°–Oû1܃ „¥hI.2‰Ãte¡,¸ïºzÂçÓÊŠLi6JØx@j]ÿ«õ °¢àò=A xRSŽRBbβ0Vää()Ä™kv2ú&üð±ð’ÇKcvc•+ ³%gö Áf-g‘ƒ™æ)‹Yï” 5Ç(R[Xt˜*0öÕþ ’Ä·o£¡Nþw”³™¯QJ±‰R¯1jãqOra ÆÄSßHrQæÅ8šæ<tdõ€!Üã-óHCÃçÀ9Øå"LW>F‘* ÌÇ©p^˵IvbÉNL6æ6$+ˆ¦eÝÙ˜ŒW).F..FÁ`ÚÁÜxWŒNíK§ÿm³€é Öqö»±QƒÕ>Bú¦aBý˦ŠT¶›!ž‹Ÿâiü\“‘™jƒŒzD$*ž ²­ÞW•o„>]µ/?âµZèÚô£]ŒÀMhûFpEoh¾9 oÍXñNÍ`ÝfˆMÒPf,Ëfƒ]!Ñcèü/h÷y 7cHÂÁµ›¡GÇRßNÌ7ú r8'ÚvÆî^Y¹Ô$@„1éB[„ìT•Dd¨ÉÚ…`YñoÛµ‡ºjMѣƓ•Fú-‹–>®­“ZÌîŒnçÁC5ÞÑIA?÷{«©blÓ !÷mNKŒå$†wæahÉàOì¹\â(8mH0ÓK¶³ *µ Š@Z&ašøJ<ê4 ŠÉÕš¬û ×~ZÙ§ið«}9ãÊ™—SßÏÙOžTq°‡„l%xæ› 8a¶ë!ê,—7f¤…U½-%auÍ5…e‘‹ÃÈê±5· âû¥„º*@” –ºc3£¾­@(®±ñ½k©l”.(J/«r»Êª6>ozDœaˆùͪ`ÎwÅ@B»¶B3¶¼‚åM7µ§W~f„ÍÙÅ8ã™þ¦ëFCVP¸?g±¾h‡Wg…´òíoÏQ3c{ÏR0·’J¸*Òu0©WÕáÊ¡àn ºê¶"ç‚–tø{.îŒ6®øEÊ7}×, O¬½8Ÿëª,–Êüÿ¶/²êﮨAļ"ÂïÜà}”F*,¨*Cz2në³»öqª<Û=ì ÐÎ4Ý€‚»Ù%*ÌÒy]ï>ì~Ü áA1Ð\>aQ¢ƒßð'¦«ÈÆSصu/†“¾ƒB¢¡UðñE^9‹Ž÷—c@Ô…ÌÔÏÛŽÃ8ŒSËà‡Ïmw8•Ì‚K׉LdXè‹0sb1IîgXXnŽv…üÓÙŸß¿¢ˆ@ƒË3ƒœ‹¾9î¿Úb”©.‘é[3”=\F•odå'­µG;0ÕÖ8Oö‰$Qèª&ÿ%èSºœo§Jmžô§¾Z¼T%Ü⤮ÅI¹£IØÂ¹€„üÍs!#žï$š|8y© §ÒYg¡^µa®.Oƒö˜ZƒHˆ÷h– ,xþØW†Áç‹ÂâTŒA’Sâs uG¥²²ÍòéÉ}¨”Ñ ’àSޝh§„Ô‘XG;<èžz½ßC(¹t‘9 ¢ÆrÖ+:£qv¢c×Óû4‘‘ófÏÛMáZù™ ´èé´5 fæñÆK枈ˆí òE£ÒÐ:æÿe ¢xa*ÈBD½…R½Ì·Ÿ BÉBŒšr@º4å˜â6’±Â†rƒ`.±ÛâÆû——[¡Högb²þ´›Ìb0«´¨ås ^à’¯s8bÙŒà·C¸UJe™ô„ùw*k‡ f±¼Bi¡"{>p)å îDÐC]ÊÆMW/Ð%Y1§3ÓÔ0•¥†› ›c °L@0”æÐ/r…‡%ODë‰ ±y@¸ÄÉ2kn»q«¸…fd%™’{;•Ú¿‰x6 }e„°Ù›š#ÅsM/,«uqôîˆ[Q‚™Û|„¹åÃÇÆ*¸`„]Kä”%7¢§žq½Õßprƒ²Bñz°2ØÍ"øºè C>€ðPõŠtÿýåûŸ¿{ûõÅåfï[Ä“âºsøhùÏ4Sz^—ÀqÓÎFºM_-ôßýðÍO߿Ā-ÄLÏ3š¡¶­÷Ã<±ñºú[CóEeþž\ÇaÏÂ/ÊÅÕåÅß^bêb“×R×US±—šO¥Í_,€‹w®¾~ó±wS¥oéþNd½ÐKVÄ Åþ ‘â)aå :×}ÿ:ˆehw‡Dg–n¬èøU áÏ endstream endobj 455 0 obj <> stream xÚÍYë“ã¶ ÿÞ¿Âß*OÖ¬ø”t™|¸>’iš4Ioû)Ît´–¼Ö>I¾½Ëä/@zØòî&ÝÌtvgL‘ ø$¸z¿â«þø*ð®vÕêÏ·«?}­xÈ’0YÝîaxƒfu›ýü¥©ª¼^KôÝú§Û¯VMh¹f‰ú˜iiéoùz#L´Í©/êÜÍáÓtÌŒ†eþ¾<þ§¨û¼-švÄ™‰iQË… cWIkøÂ O»OÔóa-L·]ÑÔÔÑ쉤·’AãØUZn²SZEQã’asľ q}DPåý¡ÁÉAfeÜpe˜0ð+™ÖV¸»´Ë³õFJàÂøûm~h›¾MÿØÑwŸïç¡.ÞŸrfýíÖ™ã__¹F{Oá`"–DVÇ*a:^mdÂÂØ.¦ÇÉ8ÏMY°‹áLGvÊ?›>G1`O‡´§ÖîÔ¶Nå'ìÒ¤$)£à«o¾ÿQD1j'"íDAOsº¦ü€ŸyK2RUÞ§ºé=£]yÊœUjY|rC•cÜö©W<²ÞçijóîÆ©ÝyÛ õ©ú˜¶}±;•iûÊ«æB%¦Äj“(ô=œûËUJ·ÌHZ 8FEG¿´%£‚ô®Ì©«oè÷Øâîã`—wŽ8Ëë.'ò]Sžªºcë–  ‚8Áæ6ܲØ™&÷um¨­o‹DØìÝÒÇþ›ï@®Š>)á6$½)»!/“”^¦ç£deZÔ÷N½óMAO•Ö“ÁÙ›&æ·!7»ÂyÖçO„ËEüy™ÐZ“hn· 6¡_ï2ô•ÞƒþºÞ‘ g*ðäB§ã`zW”ÀÎî'VZ' ƒ/×±$²®©rjY/§ãÎå•]–>,UQ§=Æ ‰îÉ™&ª þñhU›;O¶^ ½XM[‹»0N•" “‰ ޝÿjÙ¼ö„bB³h%}<¿] â! ÝæŽ$ÚÁ¦¹;pD— p­3uYnÀI³7šgOZÚEÏ´ôH‹–V:´àS` >løpÁ‡=E朮Ør#GÒ{ŒúDÁº@Wq<ŠÎ9Ý®˜Ø‘M`kÝ|ÇŽ?qàç´lÿ}sª3æÌ0M‹CxK†dºNt@¾„þŠyê§þ9‰øÍ`€éîsò8ëÀræÀRLv™¾[{@ƒš‰¢lˆxwQå7Ôì×upÄ” ŒËaÐæN•mßù)•“¤¨÷M[JlGJ¤q¼ ÷¹Ë3('hæñÌ„0fùßüšl²²­ÔËšg¤Ûq˜#9KHý·²’àîtùT>›4ãÔ—8JˆAr{ðóæº‚Š{Ó¹û¦,ÔýšÝ)Њ5õ=d2Ï‘üìì'Œb!Ùº®_A4kîÞbC_ÐÏ~¿ÿœZí±˜G?’ÍG²,s#÷éq6r¿àÒáÔy›¿Z:MJˆþ4 /0œI†D­Efô üŒk”SµOuɬ½YZ+hÇ T°¼–Hf‹EÎDÐð.:߀ÖZiyrã6£O'4 6ÁÛ|×<&aÞþTïFé·tš­”ÚüƒÍÞùB³dž‡>Uñó€?I9UJç[ÐxhèáfÕmp™wåàtï.çÛÅit»^®|’‘·a. ÅŸ»6°L<@ÿ~Å”4«0ŠBþ 'è¨V„ˆ|ßQ®Þ¬~¸Œu²\áñÜß-8@Fðà³ÀQ|®†+z~ÖÎ`XƒV]Œ>_ÊŒèøƒ²±Ä&aþ’ùj8Œ7%Wƒ¹f€œ/X¬A-!“„/w¿èÖjÑ:ùÀ"ðk8àç!YY ðG ä£ëÂá2fI. šEÝÑNr[“`“¼$árö€ÔÚÄÌà“Ã9S ß“ŒÄ5˜%s£õ[¦E#èìÅ‹h \<˜OX'H›Àyˆ*Ÿöˆ4¾¿Ág¤“໚nE¤hŒï‰qÐ{íÁ<¬ÂàoJd³ãöOËŽØ#,"BdlµTþÍ02À„Á›¿¿þ–ƾv4¿âwXœfhU“b(¬´Øã‘¹ò ms|˜ålLȱ ð$¾¦¼ Éˆq=/e^Ó#°d!=ý».‹w¸#Ô—@U‘:«¹øÁ‡}&AF™S‡× G.äz1ÿ„^fxÔynkðÐ/Ã_tè8û冰–åd…¼ÎœI‰'-;ÁÎuIZÌîîçÂ5´%ÕÕ¾e¶¢­ÜCtmC®lâEO©éwxd°|\`Wß:„ˆCãªZyÒþð_è)Åè endstream endobj 459 0 obj <> stream xÚ½WYoÛF~ï¯ Ò*ˆV$—gÒp'@ëC>úPT…Áˆ+‰¯,I=þ{g8»"S–S …“»œùæØ¹Öøl؆¶8ð³ŒenüxmÌÞ†m±ÈŠŒë|žâÂ7®“ßÌ·e1á¶ÙÈ2›Lyè˜U,ã\4B֓߯VwÀj{,r=dïØ¯7i=™:ïøÖ2®6¸tÍDÔK™~„Eh Eg}\‚P'PB5³J­”‚h²Ür̶ }L z6Aܰáø&p§¥œV°ç›¥Ú#ÞºÌnq)$›L]Û7¯òigÞT[Ä™çu¡ÊYféy#³Åjz-WôüBýð õ#3–â f0­®:Ç”E’kÚÏEŽ $~‹D¶FÚÖȬÙ.›ÐéØÃ“uÁ —ã!묺I«fYœ£g3ÏUtl i꺳¸1åsÃŽ.-À›žã™y½îXޝÏãQhÜžÏ â¦gœ¹á[Ìöô23®Œ Ã=‘çt2q;¢«c±ÐQº. ®Vq›5¯GÍ÷(?œÌ)i»œEQ¯¥íè®j¨”ž§Wcûãh?dÁaèžJAœŒ¥]ÀìH»`¢×Hä⩨ëx qÂ9ï|‰„YÍsUJ|q1Kò´ˆ3¢*Û¦jÇi´«½yVßœ¿?¢ž¯Câ¾, (­‘//ŸDR’ PFŠ„^îÐÂX]áFN¨•Eöð5*œŸ°Mæ»~ûðñƒíÑWm¶ƒMï ȺeÖ&[ Ób…j4i©ÎÐݽ˜°½úŒdq)“}YlG>sý>Õú@#•OM%ÎÖÿK"oÕ9z@Ó!™Rõüòݾ\îÑUšB)ô£Ówÿ:ÏeM<¸´”i³ÉiIݿ®G›Ê¾·›2õ§"XÅËXÿè‚æ©Tïœrsv~v<¢{‡ê -HbCKÒɱ€ØJ×XdÀ¸N…R™2ž09¢ÂŨ÷v4øÜ–Mª&ªtPÝÒ®“¶ÊU‰XK!´j€¹˜|¥G‡õˆ«J–(õ>…ìÏRåèYª¸;ª\ýzúiCÈ}ÙÑ"Úv†eäø>ΫLå}½wÌý«o¯Êûú;OÀQs_º)×ûÍöðœsо¸-·ÓÏyUÖñëQYnû.ó›²ZÖ¾Å}–¶T9wx«båƒÑ6]úºwYß¼çÄ–ójR_EX‡¶l»Œ‚wõÆ–ÕÇC¨< a´: Á4ï‚x“5UñàΟ z©é~÷µô_çÏÏŸ=í’;ê²ûy5Ùïvy帳íj‰‹m±yŒÝ2_Uykÿ¼r ùU¹qwp÷«»r×ÿë"»iʪøœ5E¹õŽg2{ö|ìv8ùÙ“¹ ”œŸtß/û¼®\nnMá'‡“]Yl›'ÃzÝÏwM±ðÊÉuî]?V¶©äÃAØ‹ÞE×órjvñH ¡µ›Ëð‡^r»âK5†ÌUÎÌÍË‘YÌ«lwl¶®õ”ññÜy ˦ “È-¸Že ;,ÃÂT Ì#,•šÖ<Æ‚–HÑ*k­–$O‘Ââ)PX¼Ã xKăhU Q K¦º C K¤l``Ù0–ŒcIÁ€#¢¦½Å),ã‚8eÇ’a,Œc9$Í2¤° -İÀK`Eµ¥â’WŠÀÚ–"†¥º Š–ì¼%bX¢ bKǰœû­Ò€– ±ø‘y„NzA,ÇbÜ¢JX ËGIÄ%oYƵ5Âò˯a锨v5%½Õ®¤·ÂR]Œ½ä§.©VTÖÁFh*E.Q¸5õ„¾ø`쀾ڬÀšô¹XéyœK(W`¤Ë¤K(‚ :b\÷,Âq.G$ÜâEç£è–´ð1.|áq.& MIÎiå3ŠËoÉ*΋£Œqaª­BlW|ŠËvqÄxFÅÅ£qÄ8—RÚ¹L NëKR\~“Šr¡ß¤\Šàâºó°Òt‘âò §ãºÇ—Žs¡b.(:Žvà@> ŠËë Æ++7—РݱŒ#v3VñÓDf×øË\Zº]è8Å%;a›ø’ßퟣ*#¸˜µèÄOîºó—ŽëÞP\Щ ÄÅ).éÎ_ZœØ"Å…—¥ã⊠P+Aç£8PÀ_ŒâòÙ,\‚är É9GÓÍØ’‡{}çÐ~› pIŠ‹ƒÖžX'ä`àà»ÁåÏo!.¤¹œIIZ__ÁÅéó„ p)šK*”ö4§¹€æÒãuô .t§éÓ\@s šËüeNq‹4ŽpIšËŽÒG—&óËÅë7ç³þfk>{¿x=ëÛ_Ìß¿ý)p£WÍà*§É«¢¬¦Ý5ŽoW—ëý—;¦¦<¾…mšÃ-ìã=ïð6À¤ˆÉTIã_qÕcÕß¾ù½:+ endstream endobj 465 0 obj <> stream xÚ½WmoÛ6þ¾_¡ò³¢$¾¨ý´!ɰaHÓÅû´†bË Ùr))nŠþøñxÔ‹mÅJ dHóÈãÝÃãÝ££÷Å£^`þ¨'Bóx‹µ÷ëÌ{wI#R’0æÍVf}J’po¶üÇIBÂÉ”ÒùÿæÛÉçÙÞÅÌûâ‘(‘ÞÎc ‘±Ý ¸·öxD¤hÄÜ»ñ> 8蔜µQÕ‘eÉ:ËR™ŒYî”ËÛj±L#ûßá‡Y_*ÍÕ·¬‘'QàW™V…ž‚jàn÷•Eþb¦Q^f•ú•.rœØ¦:]gÆBiÏðîRx HÑÔA aÂBºyÚÛR•Íñý=T*½)c$.> Ã˜Ãæö\·(ãaùge};ù0„Ã¥’°È=ÏÊ…6›•9êÇ} Œ$q_}voòÈ×E]©MæöìgF2 ô÷¡x ¸Sî.¥D'äP¸ ÃDä33!„¿»W P¹ÇõT[x±_—Ù§î&!÷Ÿ`úÕ½[Vh·½n#nÎbœR&àSÈ)Î&€QÈ´qE¡¿SÕ=Œ"™­Ò:‡D‰bÿq˜ŸæuVkê(„çv,hǨr±Â_‹4–CÀ]bÉûyfì‘aPV…†CÃØœÅþ¶fÊJ׋ªÖƒÅáIÿÆž¹,F!¨wÉÆûÐà¶ŒM9ÚLkØÌ™´ƒFq=à<äóý++ñª‚ìWÓ! Z>‹^Àgf‡`=BCyŒÑ:?&ÇŒfölKF(µÝÓr¶Ë*­êé˱Ú»†²´¢IÙÚ6J¨?DNhÈI¾ŽœBÊ¡|Ùi[ÍѲÓVwŽœ®_ÊLe&_7å‹Y)¢ÉIVJˆˆös|¾’VâÂ)ëÌe›¶‰XU0h¯À¸†Ê…¹Ô-u±7‹«¢Þ,qáRö §«·Â"ïøˆcrsûù¡Ò±÷]õ~2 ÷Ë+uU°*ò¼»òýPŽ‚÷ÛŸ×ó¿¯Î/.âÀͨ¡òïhÿuZ^ìÜСr°Ìù³Û€Æ›lùaÖ]àúx={ST…ùð­Óüˆ~¿º¼øåæMA©Í*KKu—g¯Àuõñå¸6…K祭†PL—uš#ž>ºÈϾª²*O3¬éƒH"[†ÇvÙ1¬“G¶ççö¶¿Øîi9ÛÀY¦kx8r@Ӕў$$wÑWs>'ÆCšï5§:«´Ê¡¿ÌpÁ"‰ü‡lQ)lCqÞí®³AFuÞ~€×cj¶&vϲ¨mŠô©½¸{˜?¦ùÿÇí!gc'?àv‡qˆÜM/N[rG ÖCÛŒ¡ŒrÞtÌÞãÍ-@/ˆó«z³ÀBõU¡qp²üa_S`§‹*N ú¦¨ØxQÁwEåä‘¢êù9QT­mW.#¶{Zζ. ¯w5e:î¾Jm·9桯æ\“íõEÇ(ƒŸn–ùPÕT}¾¢œ¯¨(Å$fÏV”.vs€q\Rg8hÛ+õfý“8Ù?qJ‚Ãþ©A=à#a@„E Ù[Ý[ ½ÛJ4m‘¤õW•«T?¡ˆõ©UŠß,c,-Kó- Í3I¥<~@Í>̆>œT„Ðb÷š&5ôÈéúÄióÂÓØQíêÞã$”63xŒyÁD£úé§ÿ”wrÿ endstream endobj 468 0 obj <> stream xÚµ–]o›0†ï÷+| Óp±±­ÝMZ/vµ®¹[¦ˆ&t¥"!å£Y¥ýøcCœ„›VµRl8ç=¯óô=!‚Bø!HPø Ñz‹>-ÐÕ5aˆ¬8G‹{x«-6ß=ŠŽý€ʽŸùÞÿ±ø‚>/ÐÂLIt@\aµ "F[3,E·ÍÑ-º(p ²E²}}!, &ô(,9&|Jød…ËÂgÄ;\ˆ“P`î¨Ðà“òN”Õß4IîLpï·ù(ÓºÌÒg]5ÕO¢ÖBÚÍ1þÙ‰—äMÚz»ºH«†J× ºB”c.ÚB·/»b_eUwcÎM"‰ÎqhR6Es—ƒ n¾¹\òª,+íaÙ>Ù—Åyÿþë³Èvµ],ýƒÖL"1gm™oiÝ”»ÊÆF®#ŽUä†.ôD³]wô“cÄ!fZPÇŸ»¨¡8Ž˜ /­“¶„½iX=ûœ››†­ð–^†Sì‘T±iÖéÆÄ­‹ª^úf]ܛϺsœ4¿²í‰s’™Ò°u(‹(CF,–Í~ æc1š;íŽÔqm'Êj¯‹|fŠ]ß$ŒuSL‰»aV}_fÛ œÁ@³Ý™·:|϶”æYþÏD2¬ä«@ƒ•¶1 ôã›ͦ€&ÑÐëa ½Jô—ÍN‘fÂÐÊ:Z™òªºlÖ{oqmS,œÒS¾ g wä²ý8 Qf»eœPK,dO¨œ&Tg@õ„Úý¡NB{mËÞ„¶eµGíµ{ÆÅÝ0«>cຄηÿÎ'#K5Êç¼ûv|2Æ'ôç|¾>pÃè‚O(a¯V@[ÔÑIÂãÀÕ'ú qýÀ%Ô Ï Âðàá^ôtâ†úœÿcâ>Μ¸C8»9”Êöÿ¶82]ÄezóîÃÞß endstream endobj 471 0 obj <> stream xÚíWMoã6½÷Wè(W$EIìÞ¶í-Úb· ziŠ@±[»¶äÕGÒûã;á>ì0Q|è­HKÔð½!g8oè}ñ¸Á÷Rÿ‘·Ú{﮼7ï3ÇLƉwuŸC1 Ïë¿|Áx„œ‹Øÿ­ü§X¡L•_VŒü®Ø Äþ¡©7M¾ß—Õ†,šºïʪhƒ¿¯~ñ~¼".=ΙVÊÒÄKôHø!Rþfw¦}ñ˜Ô™÷à% S‰™koï¥0sxÛy—ÞGÁhc9Ú¢{›e,J'X ~ð%ÜÉȯêÝ`i&Մ̹„/KÐ3+‹ý¹¬Ö´Å_icqæáÚ_a¶yµ)®²Oú}EßÍLtëÍûÔÀF)ÂC(¦2ÃqùXÕ‡¶<‰Õ|Oϼ0‹͸¯KðJQ¬nÀ¥`¾AÆk3épKß¿ýpAeÕÑçÓ3-xëô•xyÆ”4Ä?íª)]YWÖ>ž»©˜ŽçæWÛ6Cò!휣µ)Í´†lDûÓÕ88´b"¶æ`Ú>C¤ŒÖD»Ýžê;— ô,“ô“ƒT±tøv[‚cmèÛ®éW]ßä;¹”òó¦ÌowÅàONe$/„DÀ´Ã…‚Ü/VåuÄcsÊeìßâ’ñY k‘þ!‡s^tpð] ‘pŠ…õô™ ‚inM¾s€_)ƒÇYúõÃÍ÷:Àdf‘¾’w+È pbˆÌïë¾¥ñùv¼u’Êì”ðç×–Äg+!l0Åç2½{ ÓmYåÍ㸜‘„Ù ¡^]gj±ÐÒÏégH¡c¿«]®é„ÅCn?ïWŠ•˜Œ¶RÛ¤·4T@*ÉbÕÑø`XÞÙ_;þ€ÛW4vŽ)nÏéO5Ë’™ƒî’¥Öèb`³ô»ù090`8… Þê(¾Ѷ&1ægÅ`BtA¿9nË‚§? (åÄ1¾O‹Æ·m~9{Q5…J™H'Ù˲‰S@çÝ´¯/ çŒfãRNB6!k‰¹·=³²ØNñ„U¥é œCw’ñEô¹™…¢ŸMÑ5eqÒYœ#šòÙ¢)#Î$Í%ufsžj¾V!ÿ(@ªöÕê(2ñ¢:fL‹™:nÔ1fé`ÞXO ˆLÚ€à“[ 5gB½,…b.…>V6@=–B9•Bœ‘[·îê–„ÄhÝZ$þ¿£E϶û"cBN…K¾¢ß‡)‘œ~z]èø'š ׈lKÒôÌÊbÈûýþiñݸ;1®æf–¢4ÝBý2w1på&Ð¥Láok|~[£óÒ:ë‰õ ]z^¡‹SÁ¤tºªßßÀàÓ:÷_•5ÉõBÓ?vÔ'>:(0eN‹PS,"ß<œó[ê¤ú`B–ÃŽ›Á“nFæ%®ØXá?lKºUF>ô$> stream xÚ•XYsãÈ ~ϯPå‰J¸ìƒWåm²;©IfÇÞO^âÔT‹jYÌR¤–Çx¼• æaieoÙUê  À€«_WbÁŸX¥þ£Uq\½½[}÷N¨•aÇ«»=ìoDæÉên÷ï@†0Öë2ªÓú?wÿXýp·úuª<[=®’$Œw"MVÇU…ã¬Z}ZýtAÀHÃ2lÆ6ËCOlsÆê%¾3®×JÃñŒ¹Q(ÄÄ]HŠø%ö3*æ¿-ëõF¥:øþÄAkû¶´_×* ,mÔ8 @-¬ÀzK¤Íž~…iŸh\4Õp¬;§îwïÒ Šr½ñ²eÆ©“ýé©nN]ÙùË‘¾óC" E¶ÚÄqÑ‘²î×›˜ìøýK=¿€÷náÔ6[ÚþËíýú¯µ Ž"ÃwFŽ?Û~hGõ\xæzNzwÀ'yÐ6C_Ö–Ï,4Žó0UàÎ)–:^.ÂÄ-ëáôN’ŒàñeŠ/3||»Ç‡ ÷ø@éÜ-Þ]ß02­|]Çq`ÚÒl+ÛݯßઠeŒÄôt•HÜCoxaì´:šö¤´; U20(I)°ÃZ&Aoœ>¸QïhçñÐt¨¼ÒAÕàÑGTÞ“á%²  EÇ·ž¶mÉëð£ˆ$¦,qT³èUà9èЩ2µ¥õ™f…Ý™IÞƒ(™GtK™ ðo;ÜCmqkWvM;š~YÆ´æ¡5§ïÜÿ­qXØ·ME,´±m÷g¢a€DÔI‚Gv2ÏÜ£ã¶åóO¬]CË£–Whãï8>þU7Š{•MAŽ;qð_[ô¨eœ²5´¦Té옿å%½” :aIÇòt)` eLq"c—ôKjœYК¡Ú‘Ô‚Û`u€TpÑòˆIwÁ˜ÃŸÀRQ%2>>­J“àÃ-ý¶¶2ߌ;áæ÷Aé, ÃK”,Mš- ¶;ÌVYì›–Öí7s6=2t®lðŒüýÃí?iô¬þ¥^ -´Ðœ¬1æå›Ñ=ÕlJc?G[%“ø3ƒKð¬ÓŒü‰ý£Âm8à‡_–þt–)T*Ó>xã¦â!µ.6º.fÙ‹©dšºÖš®ñZáã—Gnš—íXôº/#@&…#‹AêÝ›¼8¾½óöVŒŠÒÌU'8à(´5M»¡Àâg?TÕ¯øºf‡5YŒE$nÜ‘0×M­W=Ÿ×1äe_à¡q/–ÌÊ—ÌP„mµÓofW••K àĸl¥ØÿpÓ‘Zö„We8ØSë…4c‰ë¾ÄÆ”«à=3lj§œ¸ÎK!yäï³´J•ÔX­s]JƒÏËŠŠÑw9{øð~}±C£ñùÖ—ÞÞ|þøý¥Tã}â³w½TssÁÓ›¶ö¡£”¦àt…¶ö å“€û†rdF»f¦›é‹’ƒ1 Y|ó"ÚƒK c¦ˆOEÓ¶ËçuÈÔ3ù`bÙüù+>©3™°4ÊdÔ…\ÙÔ›³g÷Á¾5.Ëš ž|†ÕNƒðªäd„Ÿonî^c- ”´ÔÞ8$Wŵ¹ ´NžÙI&O•˜ë;÷©Öêà€Ë2š`ˆ¿ó.Ðñ)„  ›âë•;ðr xü:1 x0Ð,ãKÎø™ÏøŠƒÆ¡äþYqÖ¥©ñ;Šÿ2ñRÌLðñæöݧWÅH)D6Æ I-\[ÄŒžÇ¸Þ~½µàa΋`XÌ>@àdÃ0;˜ åxÝp3×rç-ÛòH鮀³HaŸè D]åh ¤ „{ áéÊ=ýö¾¯ 4u´%7´ÜF{ûøšËº$ÃÛlM_3“È“þô§ÿðX endstream endobj 477 0 obj <> stream xÚ¥koÛFòûý ¡@Q Xr¹|¥ i“§q/¾OçCWŠ”Iª¶ï×ß¼–‹Ž+b„û˜™·7 áÁ?+øóëýâõåâ»·~¼ð=7õÒÅåöW¾vU°¸Ìÿåüz~ñÇ›ßÞÿòöÃòß—P=‚,Aý³Ê®K³\~ìt5~§í²¦ãa·3²f²f½T±³{ Ês®—+•8f[9¿àocÊì.늺ây½y€ëÝ™@š.ßó¤¨àÞj-0»¬%²‘¥À C"¶BuâäǬäÑÆdmÁ À¬­Ë#Þë.W:I³Š—k¸¹ÁaêÜ" u“#¡$-ìkâ'L{“U²Óí²ŽGņ‘0#Z8ÖŽG4k¢Y©4q‹JS§’eXW†‡¦Ø#K8XÂS–%$Ø‹œ¢kå衎X žrá±ZªˆÞ)rêc•›\´µnø‹üœÈšI%áðH*‰„7ðµÜ skE…RîÌ¥Ž;#–’hÌ’JCa ֯Ư–‚´çstò”ZzÆ p²™ÃÑ‘p!÷±pZ¡C¸ærgÁǯÓ}†gîÕá@‡AñqA¥l‘"À—¶ÚþÄÓ¤iŠ´cÈÀrb3œXì q¥<7ÙìÛWgçŸ3ÙË;Ø$_y‹ïµ<’öYwÕ¢;Óì‹*ëL΄åGAÓÕ¸yÈÊ&+J@ä~–50ªóë«‹§Yð<ËBD,Àœì“X€É”ϱ@š?tB²“ÚdW0Œn_xk›É «KÓˆÏé¬Ïa 2¦bÙ4&c‘£>=S—ïÎÏÞ=-¥¦/ªü‘8`2@OÅ¡ôCq ˆÅ V$£²ØwŒZÙƒÄ$LÍÝÚ˜ü)G*ûáòýÓï­¢)ƒ8ïÄÉ„A\«¬Š “Í÷À<ËbYwò±†»#ÃÆƒ½aËÉÁ°q— ûÔ¥LBþç2ÔêKΆqbóäqêMF:Õ»pGíØœÈÓO݈¯}},ÊnUàK$„JXøxÛ©¨ýÐM5àIÜ0é°{N"_eU¾Zññ#_ˆ˜øhÐþïÞ¦¼ž«´<ãõˆ6miCï· =‡è›§Í Ý$ðX!0qÖ1u$xƒŒ§íñâͶÉö<—à °ÑnêfßÚZð’Êõ¢ñËÕM±µ¡àèK KÕ(Áj{[)®<_“‚¥ô€ô¥7G°ÑåÔ`&aè|4ëNÀjþfC››cÁ:R‚)únBBî…8»]a}ŸJ=RÒˆ”4íÓ«SµÄPJq5Òˆ!½eQmyr[t;10˜ÓD°7Ý®&cÈí âe|v$͈‚¼˜ÛÛe"JÌ]¶?”Czœ g§qñ„—uFZ^u_#P﮵‚µÂvÆ&ÅKërÄ&3kyÂvXòMñ¶EC°¿ÝÕä a»Ï$6„W:š– ÈúT!·• 5iPó‚_SŠÓdiüåŠÖ…ἆ·¯µMébPšnM68ï9EÖ猵Þb6º(åÎ0aGNrpä0í…O"JÄO¼ÌÄÚ0ãéd0¤š8»ÎH?±¯³‰Äºn;K®®rṘg5—cÿ:(§Tć ïvÁä3êÄg7’°%â»f\0ƒüÊlmøË÷ ©ªÊÌÅ:ønh=×¶<üQT žñqaìªXQÖ©eHT¶ÐÜl²cÙñFa¿B}^´œ,‚>€8ãD|…vãtêárvÛ) ¾Ær±g_9µÚ’Ïþž/(³"ýlj”WuYØt½3ŸÊ$ñ\?V¯™‘ˆNÝÄŽvWËœI±ž&­é„äzî®Äw- Ì3Þÿ6sO¸A*@W€P‚†ûãIX@® ²v¬nWW?OøÆœÙòÝ~ÅJ(É_Y£àn¯–îLüöÆzù rŒf’#$’#pÔæ·®pfs„çr­?«§‘rµzŽš ï `V"_‰sÛ2þŽ/¢\¥á*~'2•È#‹Öþ$±ÇÖp|ÈÚ–,W® ÷òµçêxâƒøŽx’fia®€ËHæ*G«+”¶Æ2˜ºæ ý‹ÔÀ¤b¨ û …[ûº‘rÓAÓÊuÆ0²ŸwÙ¡ãKcP—×Ó ú3³9¯.ÎNè?øÚö«'Uær E0'ºâ®àèáØ=G7>ôq}¤pç.°:$°ÓeŸ$ÐâLΕµE„µÂ Îl¨U`¥J¦)/nŒøù†Ëx„Ø lQa‘NQhcgÇsqm'* ìõBìƒqŸnSü à<ÊŸÆ©v;„ÛÓ궯ƒKi Í€ ¹hýUÇg75Ù Ô5>ó’8xs9ߔӑïF1±ômUU/Á½CµFõh¨BçGþÜÝÝñà‡fWÿÄÃûû{PÍŠƒ+çp8|Ïã›››¾¤Ðé×íÎ4®ŒÀÝþgÎyhßU6Æusz»¾…ø†ÅV´¬üb¤‘Ó˜Þ±± d$îÑ{÷èlÄ£6ȧæ òcjbò}(•gPõeüé3<¦£>RÖÓ;Jæû.nŽÕz |c}ÅPn`\‹g:ØÓAÊJ‘Òê ™6Ãpah†!ôiía lÃëØêÄï'…ÅåQÓ×7”­ÒÎ=±ÚiÈÏçõ!Ý(zRüéHüÈg+q7TnÎøq()Ì]Ç£ù{#7íõ°îXÅ…t²3çAW´%ö›«%é•÷ˆ^%®Åö%zL@"±ë6â[#Œä§çnñG#"Í­OB¹ÎZ« ^gUì‹ÿ’9aW”´¹ù ~¸¾½à‡¿F?©‚ ÆOºÏîF4}Ítýˆ47¶ :³'… ûhù›ñg[Ö×\¸Åãê‹æd 8€ tÝÉqiÃl¹ëqé'>ˆ€[—êØ$²Ýüçc ™¤¡›¤§h ¹äžå;´F qøÚ_@2‰­áµMSïyqþ1ƒÈUêK|!¢â —Ì£T êùOÂ﫳©ØõlŠŽ1êY䱬zy$›µ 2nÖ ¥pŸŠã¾$_KœçtÂÙCÚĽ9j* ¹Þ¸Ù¦Tì¦jüpÇ!RÌ’ž}+kGáÔŽB+És×®wÇÆ”ïzö†+ÏóæÀ(±ÖzOÄâÿ˜ÌÍPÚòEsž!tuØ×R3øõÐ üÿöGþàã<²ûí¬ºy|à—×ç6ëºY@ ˜,nÁ÷AÑ'Ô±‡‹=,„XÙ…rñañûL’6KY/Þ\|8;Ÿ­8¡RñúŠs9ÃdäFjxTžM+ßó¾F•õ9úÏUC‚¶¥§ŸÕVE”7òFž³mLÖq{Ú—æŽÒ4»(’ÙŠÿå\©=¼núõ FE=Œ@:0ð¥ÈÍ?@ÙÜ%GÂŒH?èÕÎ:•Ñ=ì>#P{œýã—5 f’NÞ ÀêÙ^3–Hr”"àEƹaD¹¡ç;eÑRæä?’I+HabK$çÏ¡Üʃ¿B9WBø« 稉výIŽºË¤½Ê—`ú“ýp š’ßsá³Éº]Í-Gܪò¾ j̆Šfþ)¬oÚ"ùIĆ3=MšÏÃO²“_1û2®kŒüÔhË©‰’«yZE:!Æ"ß‚þþ·ÿLœÞ endstream endobj 480 0 obj <> stream xÚ½XËrÛ6Ý÷+¸$Dù~´«*¶’v[±9ÝÔ EBkФAÒÏäã{ñàCR‰Ç“̈.î98ç°ò¤˜ŠÿLÅ·à¿¡${e)¿.}Å4Ph„J´…Ÿu:ð”(ýGýPšmª )sM·K­bïqƒI­ýýSÑTÓE¡£è–‹\ŸMvY­éŽe²y$®v|˜â:!ÙFÓ-_Å"$Îsþ¨å PÇ2Æ < %CŒ¯6ù ikœò³‚6;Ì>ÿ¹âu™?ÓI˜ M÷ _½{ÙÓ1§QæYÂjÒE¦\—•Q:@Û¶­–[þÉ8úÝÂÀcŽtÌúÉÎh2ð¯+€ Ô²H³â¿Ç#>}&ZÍ ¢_Ô i“¦¾æxûìÐGÝfJü!¯ÖY™T’½r\taH––ÌGNÛé! ËŠFÓ]ËU÷õ›r)O ²Ã@ùª¸,L÷=ä){Å3éŠQ®Ü)_¸Ð†˜€¥Ïñ³„¨e ÀDïA8۸͛ßdŒ¡$ÈÇ#?^­ŽšŽÂ°§h:PŸ=ÁqÄI~¾ûxœØs‘=äõäOæ‚xÞ?®®dŽò‘vÅkBž^ˆV7äÚœ®ëøA¨ƒ®"•Ó¥¥nK"äƒÉ>+b!ײmªV¾ŒÆ85¬ãJ^ß,—z”èzß8^Q ­3€ß¥ÊâÓ$(—··óP0!]]q‘ò’¾Ò²cRŒìÄ–¥sn‘¿œIçæznÍdÏvvÝÎ|ó%HÛ6?Àá¥Ýƒ3“¼IVl)¥&+‹ŽW·÷ú7jvóÐìrìuƒÉ ¡Sú y×a&ãSšï£3Auë¹.¢“íhÈ.úÌTö>lÈ~µøñv³ÞóØú¨‡]Éu%ë¼®­/–wóô—âªÙITcÂIœ#üh½˜ ¼!8NßZº2hv¡À^^²qÒu$þsÙ陸«O?„_ àºê˜5ÆŸ´}U²½ãÚT½íÅxÂö4Êqß×ö=ÓÎÏTÇa‚ëjuÒöCváç©ì£0‘ýô%dÚö+‚ÙŽƒõ8k Ó;ÇG‘óL¿Z­¯o®/çÓ¬¦ï[\u„‚ŽÐÇ€½½¹‰æÁò›<&ôÐý ûÕbÐKHwáŸâVï¨"¼ïÇþwéÙ7‰s8‹¿häùè†éµzò*ñÊÄÛ“&vÁ–0½7±O˜˜FY!àå]LÜ3íÜ9Au&¸Ê/ÓR›9òüñ>/µÀVq\g›,Ïú~‚ªÚ}%=žã6é ÷íÃV‹Îg ‹ªÊ_ú«g¯ç툤8—Z2’r}sÌ×ì¤ë&¡7ê?ÍuJ`[{ -+ !Ô=‡š<« ýòËÿ͈Lb endstream endobj 484 0 obj <> stream xÚÅXÛnã6}ïWð­2Ps%ŠÔ¥}ê-‹-šnv×oMQÐ2cÑÅ‘¨$Fûñ^$K‰½Š‘4‰H3œrÎŒD¡ ~Š üû(+ÐO ôî,ˆQàãÔOÑâ  §͵"B‹ÕŸž,ÕlÎó¶Íì¯Åoè׺A8Lt‡X¥Æ8ŽPÅ4ìÄ}AŸL°7rlD[›ÈïÎèÀŽD˜Q€«M.½•¸âm®¾w†£ˆ”á€9Ë÷¿_¿w7õÚ!…$â4¶8}œ04'¬›+Ù;k?ç2ÂLSLø¤˜¦Æ§Ú*Y•·w„!&Ép5°ËüãÀfÀNǡیõ’BO”|™ {Ï·Û|'˵•ÔÆ¨©·=qs~8ÓÎýåÁœ€¹’ÍKáܶÅÖzöˆñׇ~—…'ÔZá„îkÍŠµ–ÆØ§fU<ŠAÅû¸±ý`*ngÔÇÍeq¨„™ÁÉ%ùðw(Ô,´…,\s¦ïì½,m ™ç²YU®7tUÕϤ£u¿€/gsPiã[A\Î2À·ÉOÆÉ_òqö# ]ÖËt±(òõ†uò±<õVö™™$kUs¤Ù²j¶éiÀBD“P÷f=Öú­&ú¨ô«¢ªwß665…¼«ž%ÖÂe6ÄÞ|¥ú/ÑûÖ¢5W}WB¤&/ÿ{[›†pjŸ*d}Œª$ pî©êä ª’à |]ªöH;N@Ý›õXŸAÕó£ä$^]µåÊ¥‹ÂjÏ?|†8oË[Àð†”Í~*[³êö[C ´ž­Nž`«¶"Áë²µGÚÑpêÐÌa}¶fæ)iŸooÝLûOÃ"oÃÔiH“ô}ð^å7ÇèK}ŠýdO_'OÐW[‘äuéÛ#íx9uhæ°>ƒ¾?çò¦'“•¾(Y³Ä5чžHÄUÕšš‹ªÊ¥8†c6¸¥¾Nœ$bÒ^>z”Ø[…ûÏ=KDÎ2sv(¤©âc2:Iü¸lª¼U°`ʽ`ØÃ2sbÛè⦌À€ÕdºÆ7Â\®µÊ÷ä•Ò+xníMPà[Ö]7Âgm] û`ƒ@-™Zäüžï=ecõ×·û'Ô¥«r%x#!s¨~ø¥²<(+åH`°ór-lwRé^·¼æ…P¶mQïNªMÕÕÍJ(.óîqo*¢n¼°HÕEik8Cû«ÝŽ™eÆâGD÷…$Ƥ—‡´aV'¦Ø ¦°F–D:i£Ö6B N£ÈØB^2`˜o‰¼0›1ïL6.mJÉΫ’gÒŽŒ¿×¤ú ¨Õ_ì0Ög@-_z_c;›€²sÚé—4=<8ÿƒA›¬E‘ÇóuUÃfVìÔÕ•¥½ÍøÖV°ÕëkìÕ|+WùÎ%Ú.lð©®0G×Ä»5) qèq}a=´DÔc:¶Ör{9ÿpaõ < «Õ‰·ê¥,y½³ÚÛƒ¥ÔRm4½ ×” —çf7î‹D3]ûß´pbŒ×ùÎTK ‘ÃÒ´KË“®bŒÒÁµ(ß®˜¹^£º¨Ì©Ÿ†êÆêï6²KWH¡Êøµ–„“4¢Ô«¬c^Ú‚“’]0UYÍÒŠn®üÖDYíÃhc‡Yó%¾$‘‡Gœ7 DWç> stream xÚµX[Û¶~ï¯ú$1+‘”(÷<µ=݃¤IÚn݃B–èµYRtÙ\ÐßÎH–×rw·È H$‡ÃÎ77yï¼Ð àzFÂ?ð²ƒ÷íµ÷ÕUh¼0›`ã]ï¼0í­q"ö®óßü¼¶¥]­#ù}]®þwý_ïûkï'Ô&ñÞ{F‰£7±wðŒJÃÒûÙûqáŒ#ŸQoÿp|¿ºÒ32ˆEFŠ?·»t(û¯™ð„¡ŽD3eh×f‰™1™×Ê­¯Ã(ÒÀ3‘r+?Ù2í‹»•4>h¬C§±mÓ*sÃØ:› 4“­dìï-<ÿ--;Zê÷¼«ÞÂõEþ6;e~·Š´Ÿ–‹ŠÉ›¾8¤% ººú¢®NOXgCÛÚ yöDñòͨÙQ‰(rºµ Û‡”YÅÊ/:zV5B¢h}o[šè÷éH[3–&6ñm×ÓðmU£ïä(½%NÒßÙ´+ŠË¨’X­¥Á´ÿ®iEQ|©iuki¿iQ­`®Q“¶éÁ:q•Rþû¢ß×COƒÜöiQ¢±1T¹m»>­ò¢º%‚¢ïè¥ÚÆiSwV04–}BB'g>q(š >‘Ä"1GŸ á>‘wÆmÚ|6ŸD°À+4"Lîû„Öx½3Ÿ¸F›ËMääðû<ƒªÃKìdu3“»€mµ’þ‹ôÄ$>21—˜Äþ®néeîò#Q;¤Åir£ç8Ä 'ÀCò xË>qt.…þ.-ËŽ^™oI°¦9Bzµ|ã8aí`ø‘j-ÚöPTioÇ¡M[¹ ?¾ž˜ƒt*ë- ¹*nyã@¢1âÌ)N®@©¹ï!ÚG;r U<}7¹†“W›¶†ž­éÉ'=Šÿ‘ÎèÓ·N펇5ÉH\Êzb\ï`Ö¢çŒs8s.ˆÚÌ8±ÄçÁ‹´Ðj_ò¯‰J‰Î(‹Ã“v°ˆ)_¼º>“3T ¥—QÐP‡Â<(èD5 úÃ7¿>Ú{%!|òÞŸ hÆß³y¥³Ùn èŸ3*š;eYt6««¼[´U0„“0ðž*Pi¬e(E‚þq€6Ž/é?£’îŒ]ûî³Ù) ‚àBqÞ¿K¥D°™ßåë¡o0¿he@(ûn°Uöq•Hÿ9e)—%Urï ×&2ìÞ¸q–´¶£Üc³â&µe¢ýwfGMaç(ÃË<⸱…C/D»¢‚Èzàmr,“&;¾šÅE®4ÈlÇacŒÓtå½ûïPc ™jhüj€ÊPþÌá®>lÂànë3Ü$xÄn$`$‡ü‡öÜ(Ä4T÷áÚ=ÜhŽig¸Áá9npvÂŒCŽ»Ò•O–w9´Ä”Ÿ€¤ƒ‚©ÌïKFK–Š¥GAIÞƒ’¤„’Èo0eÉÁ¦®|2ñ(…ñÓœz9¨ s~˜‘t¬ËÚ]š±èÜÓ€’Š p/2›k„ÅØob(ÐÚ¿ÂLSsQw¨[®Ñ¨Ñá^¦³¿Û§ 7FÐ`Ý|‹Õª«ÖЭ¿½ô›7/ˆþ'ºŸî˧zÉ¢H¡!«ÍF¸‰$‡ã÷‘h3E˜%CÄ‚þ¨\h€0TÃv¥qÙÐá2öû±ÎnÒ®£~s¬•õ1?2þ/׀ʆ¥È¶¿cdXU+aÔ¤ød蔺v×Ýá7{³Z´áZBT1‹YxÁ„\ck`2žjl?Pc#Õ†j·®ød/XQ?ÙŠK8šÝÊhA„kxÖªÀøÎ‡Þí@ã %( °ú6¥©hhÒYž2Šá ·¸u™Òõu¸âz6W"A¯—‰ëbÏ”:=ÅàÚ”­X":˜[HœØžº*›w¨˜+t–êBSÛspt4MYd.®O+†Œ?“¤}Êñå5W{YkaÃØ²¥ô˜KM¸îøˆùM`0Æ%hYûÚÄO£Ol¹¸pï[~ÿdÛºúì2!¶i-Æ×%hùOÒÖø³ÙIŽBÌ ë( 1­BŽ(añÄÅ4<#cÁ__]=¶ƒ‹N2â/ÞpÌ!§Œ‚EUƒvýúBväºýþúÕ!åO:ÆVéô©`èο,Ëó¯Å€Cìï ²x ’äE÷OD£]Nƒ}â{Ì6‰õHúã¥ÒáU endstream endobj 490 0 obj <> stream xÚ½WmÛ6 þ¾_áöÐx–å×õÓŠö† ÛõºfŸ–áà$Jã±R¿Üá†ýø‘"íȉ{i‡a¸dIùˆ"2Î'G8ü ' á?p6çÕÒùîF¤Žü<ÈåαŸGÎg¹ýÃ-ëÎ[Äaì®ËºhÊ¿”÷çòg8Y‡ÒЗ ¨Fù•»U»¢¯ºïYp¢>Š}³ä¿Ü‘7Kç“ãËNí ²mœ„ØLY—Ý…ê\øqf©Îc?Wu[Rƒrt‰p7GÒØ8 4YfÏ=Œ™F&8°ÝÐþ´t®hÿX4ÅAuªiùe&¯È0Âï€(Þ?ÕúØ–íÔóéE -DùYlÎ<èrK ®¿GÄ÷¥ÞW4Õx#Üü VÞË9ƒÒ1š^«vÓ””x3iÌ5Š/1ñB»î»²Vs!§~–sN€ÎñYê!Ëžž %ècÌ(ãc\8ùø,@r=îË Šìq?‚\3èæ<2$nw{Þ^7EMçE½]lún`¨}½C 1Èå%ícÙí9µˆ|)›(Õ«^µ”KŽ{=H‡2µ¤i®w8fÀôüæ©]fÎ7ÍÜ¶Ó Ý5Ř5kÅÜ«„qæ‡Â~–ù‰2?ÄÚ®é7]ß(ãîtêîd€›ÐÍ2˜ C"…Ñ« 3¦ÃÈ4Ä2ÒÌ©-9¿ÓÏ3U˜ˆ S¥×™ ÄÑÈT<}ž©,3‡òRs.ý,´4ç© ª+ª-)ÖÝvE×·–Ú¢“˜wfjK` áøëOw¼©«ÞJë)±1 £ôëèH±ŸEÓ~£ qOpˆŽŽ^3Ý})ý¦ Öêö‹yHFò9J?L¬€?Aœ±I?j'”xоÆ^ÄÌæFâñ8Œ äx”o–wº¯·ô9ÿHž4ò±Èô1°Q´LJp!íôÙéªÒ(úØÎö6Þ–á÷Û×oæšО‹iÓ@ää&Øß´Äupµ DT«í|ËB*Ï[–»åbý¬Ë ©0ÕW@¹yóÃûy,Ija!cÂÆ"¸ÅÄq‚ÄvªhKèö°XˆÄÝÓ+yaæ*«Œh/:VÁè¡ßáØ-+ˆ<úªu½°$÷ šiØ ÜýiB Îc«ù‡†;2m<4õ ^4®š}qdÿn{îm;=œS‡‹íÙ]ûyOÞª¢¡2ñò‹£óöíçå<@Z*u  ú;ÜÏÄÇð& nT«3¯\6é§[é¹òž¯BQšá/«± e׫áX…xú|²Ì> stream xÚµ”ÉnÛ0E÷ý .¥¢zá< » Ð’Æ»¦0Yr4Ø Ð/)Ò¶ìÈ‘»(l@¤yyïãÑ3"ÛAŠÚ/F³ú4AWׄ!BÀ&K»ž F¢ÉüGDÁã„*¢_ù:þ9ùŠ>OÐ3f4Ú")AÈn‡’h…†ý,Gwèv `¯ «ìµ­a éÁÖ(ÐbÌ÷ ÆU3m_™ŠöÜ å@Gí{ªà¿‰%ÒøAV4ap¬Ì§ ‚u)ßM[uÐò~A ïK'®ܶ¦l›¬ØüèÒ¾cožÓŸ=¡ HÔU(¤KØÄBøîvÓréŸÍ®‚´ýåYZ½¸© ò*K»†u‚º.ㄪh–¥ÍbîeÛ¬y*šJL„:²:(–kš[{'Î(c›ÅÀÝ1«[–•Õ1}ûrãu™Û¶•ßSb™­Èü³Š¹nw{¤rÐ*`t??‹íA’†À%ƒà=s‚9=êÞ—ûY™ KüÃÞÞ¢å¸}Oì/£×Ñ® ¿:¯OpðꃗhFŸ¥×–p½Oÿ‹^®Ì›ôÚûÄNè ED„ŸÒë,Ž<ÐË•îèå{zÝ nªvfõî¹ù1¾Î!à«÷ø:ÙY|•LC!Oãøzb,ûÄî/ˆeõRzû)”jg•Hîo€”;éí»¿Õxè endstream endobj 496 0 obj <> stream xÚåYKsÛF¾ï¯@í ÌšcÌHN«µ½å8©(±j/Ë” "! +Ð’’üøtO$‡”ìÊmË®â<Ý=_?g}Šx”À?Yÿ“h¹ŽÎ.¢×ïÒˆ+&•‰.®a{ΖÁxõßX0ÎgsÎ…Šÿ¹Z•]Yoòj6—VÇM½íÊMÑÎ~½ø>z{AŒ¸Œ8g™Öž“J˜ÉNŒxéø¦ºï?û1™¥ÑCd ÓÆ}¡²hYø²ŸUÑÇè瀀ÆËXÎ$o ÷sw €'’I1Jà‰eR?'cBå¥ÜÝu„Àô³+–T|]ämyUVe7“Iüôº¾ïÊuî¦<~"še½!@ Á×ïl„¸'J÷b…f:ub?>mêû¶ì©ù”œk–)øH2Tˆ?×åj6×Ç Lo›1#£YšöÓ)S#Q*l8ò!È™fb䜥̨ç8Dž3¼êÍeÆÔ„=W‚¥æ9þ*/ྩ¯sþŠ`*7 ÚºÚ_BKùµU½½ª “JNžŽJ£˜áÏi8¡ò®óÇ}-Bâ”T,‘£8%-SÏ2¡òâJ< 2ŸKnXƧ®4àjuà6e¾È$)`””;g¤ùQ£ŒTÒ=r@œÐœI3ŠZ1›='nBåÅÁ‘³ïB¡×Ór8—t´oŠvÙ”÷¬þ¾üâà™íSd(buÆ„† ‰ôàê—.š.1µ °–Yîióªªg"ZÑÕø›BÖ%!Ø»£­I‚½iš'¢™$!ÇæºnhÐõgXn›¦Ø ‡ŽÚzN®Âµ`ÙÔSª­Ch.¤‰Û®nŠK·f=Oܼ‡ß4.–å"áŠÈ¬‹ÊªX‰ Pÿ¯Xvl6W\Ä‹øÝ,±SPêø ·¤óÍ(õ,š²næ(ÃÆu9莂kÒ±¥)(ÔÄc/'t.E˜ƒÎ¥”ñݦFfœŠ8ïsq6Í“†ñÞ°òfÛÞþþa{»ùýbfM¼]Þ ¿Ô Xo , ¨y¼_¦^  "Øž3[ÌÈB[¬ÕÎûÔè}¨í}ÞäëÐùŸu‡˜*Ay,(v Ö’€‡Û’ÜŽ¦=¸~v[o«¯èkšÀ'fôT\_}Òp¥“ýWÿþáüòãO?tU’YéuýÃË$ÿ˜*ö]P }»'æýùÅËÄœt9t’¯þãûó— _—ÅjWç_¹Œüä@З» †HÈO zÞÄO쮟¨]?c¨Ñî)Gñ)ÍžvžpŒ¹=?|¸¸<PØ$Xáv€ÜËž–ӯŧmÞ§Ñá m×äˆ:¤‘–1ÈdçoǺ²«' ©yö—¨IèÕÛGs¢¤ÝWòì‹•|sK•ŽJŠLV"¯¶¨¢ÈÔ’Ž|_I\$%ß’Œ¾»¸-Û~R± Î74|Ç+±Ÿdh£ÞTOÖPzÊ—«}{©ƒ–Ôa˜ só¢0?èLƒ†ožê¾áa‰0•Z¸ƒÛÞìZÌäÑ3‡(.¢ž~@ÔÍQ$£WwTðˆJW³D-KôW#z,qR;€ðMÑåeÕ§¿âñ¾Ê7y ”sMr|÷ñ0æ¾®«ø¦üŒ‚ _×ý¹+*ö´Vúl…Ùò¦Éï}Í[,ÎrJP7 ZàïlhMBÕàûeG#j„`Ð7ˆnâZ¦v⺮¼åæ—0Õ®ëÜ÷ZH\ÓoU;Å—= Žéa«¥1V|êIþÞ,‡ `û泸„.=à²p žœˆ^… \q2;u`V ʳÌ̸߼L£¹L´kÜ„ÅÛÀîˆNv¬ƒ‹¸¼î[áuAíòXDÝ´ôÝyNSçÖÛª¢E²H=€Sß ÑöæBGuæò]sÌkÝùF®Åé¶Ô}/fß¾(7kº[ª¼¹)ÚÎGÏ•‹P[EÓÔM¸¢—]aG!æÙ¤”èÌã¶ÆlCIÎá ÜÂ$?>DtÐcù}ETKÐo½!ʱ¢øÍÚ³ú<ƒxÈ›2w—Ü Ÿ3OØçMš=”Ý-¡®áÂ)§ w}Gu&u¦«4_e•¦¨ÀU(}¡ešÿ3ËêH½ùe¨6Eòí#ܬóûÁ4A]u¯+*„DFÖadbL±@Í}áÏ\U_RM¾¹ñCî·êÞtÉNÒJÆ„´Ø,ÃgÃ1ýeºð¢)B¼ { ©2Ä p´ÂﻞaªpÐpÃÕßtp„–0)7þ™IeLðC©d|ÀÉÞ3€Ññ¿¼ëàî]³]vÛÆõB*ÙñgôÕ–¨ÉŠ“T2*ÑÛA‘Ô1;ÈÔŒv=<ßh%NØ!eChß™&ÌÔ^aºß)ÎÒ)žaÃXC†_ŠÁ–&k<0­`ýcŒî­ ­Œÿ3K囸 îšáC”ákB9$¤G†ÜoQV‰`ö¤‹ |Ù§ý„8pŽîöb3¥fb&¸; –î>¯OÂÝEDJéFÙ1$`‡ÓOøXÅŸ ÃT Wñ¾W°Ø+`€;uìûˆƒƒpô:†û_®t(ñHƒ‰ñ¤)Lá2óÉcC£–™ó ›Vž2-d îþÜ1>èÂ÷Þµ(.0Ýd&~íwÏê„j­5…ïÖš®¿ Ñ ¨óeGK¿M>¥u°ÅCj´xœ£RCqÄ^ÔÔvÓÊS±Ž¯Bþ¦Ó¿ Õ´€J±¿Üí<éˆYÏ¢?=Û“þü·?t·+Ý endstream endobj 499 0 obj <> stream xÚÝZ_sÛ6¿OÁGjñÀ¦½™ËLoæ®}h¯~;÷–h›µD9$åØßþv± J ¤8n{s“LD ì_,vHô)bQ X¤8üM£Õ6úxýõ*biR¤Etu Ÿ—8ÑÕú?ñÇrµÈXüp×îöÍzñëÕ¿€ZxÔ,O 3t’gfÆÕ}µXfY_§L´]OƒÕ®Y×}½kp(âÕ‚«ø¾‚?à?Õšènðà >ó¸w+ï¾n*šZwôrøz»Ûlv .ãÏus÷‘¥¾Œ:KR’‹„d|vT`…¤PH#Žj$²0ÿ¶¹·L‘d0t×iš™ÁZiþ`ÄD"˜Çé—€Q‹„e#§ïK®Tæ&qYâö!èž4ÑöûuüÃW¡Ex‘À}X¬—ÙÏ?}½0K!4*ŠFå$ççûª­Bëg ŠârÓ‹©Qáë@bb@ä6„Œ»½ œ'J«~×Ò÷Ý-}.÷Ïõ¦.Û>-ò<.Ûº¼ÙTv¥k2\ásw½x´+0ÂO)‘õªV³:䤃œÑ>÷í~ÕïÛrR¸„kA¦Ì’<·._í6ûm3§ÙH '’Ûï(­HI‹°¡A¢²nÐj=¾“ñ¶ìÛú9Y,¥Ì!¸9ÞÞÇaõüØV]W®ØVŸöu[m+Éþ¾ìés¹ÙÐÃc[oÁFc©PDOáCצ`¸ûÝ~ƒéæve_w·/4èwø+­ðëK×W[ziÌŽÒ~Ú—›ºwi Öó4‡¹–‰#·kÁü¶¾«ã,xýãOôö±Ý`[0‘ÈdüφޮÊÎJË ^©¯Rõ\®À\ÅúûmÕ×+÷ÆÆøäÙ‡ŸQ^R‚²êƒŠ¾`r®ÖôâCkØ&UÓÌ);Ǧƒµ? ,¾§‚ÿT­í{ , 7[ö¤>¡]ðÒ·QãH»k<'òÈÔÜ-1ÓÅ;kZÈ4ËŒ)Ok`“qnÕÎX19V˜FW›ƒ £‰NPó­\­`óôM$?Áƒ&šnõ¤/u7°ÃD‚uõH–lÖݱ*f¢.,§Õ Ldi\Ò°­0úmŒ—–›#ÓN0 GûwôŽö=ï;sT"‹I­ÇY]½}ÜT–l&@×ïqïd±I*@v$ê‘2”Ÿê5ÍÜ;š½Ã×îÿª­w­ï>³q–'Cb¸ ‚Ù2aRøU€˜–f‰9|‘„_-`ݱ}Ü÷Uw@ód‚×&Y`b¬s«®^ÆïfêŽÙ~¬#îYS'ÒßaIÎ.8 õÙ:D¿Q¢''Öd™°‘S¨¾Xr)“Túe@ÙØZn]A\lÁÝè  »¦C$³ÆÏܶ†§©{2·Í-øÈ-cõ6z6e{WQÅ)âòÆlgƒPmµ]÷„i¢"ßWm»kG‡«‰Ãe¢™çð’ê›ï¯¢OQ’:ú±ê 8ƒ8TZ2ÚF<å +ÜxýýL5ödeŸŠ¬»-ŸöåiÂÙNKÉS±Ñ›U „Jm_æHŠD`…b+Á”‹Pèå® ¬§óDëK§oÃQ‹âZù~ Ö‰cyw¼~žp®b"a>™Ÿéh 8ÇâCÈãKÏ â9ÏS<·Ÿk ¸Ð*8; àí^ÌyÝ'³eà[¹]üºëˆ!Ù€œ_éøì¬ã3ù Ê,ðpèP}\˜=Zä‰Òà Ï]'ØY@ ^$ó.9ï"Ày¦œ~;ÝC]Ç!˜Òýkz$‰ihlOÇ‹·ÈÉ-TœÙB° .)ôl¿ve¨.T‹ØÈNP®Z yûÏxŽ{lÌí›cƒe —h0Eº> ¦1£ þyÅ¡ÿ¦|öA>y€˜ i62ºu¶_áÖ^»°}ö¼P¤>ŒÁÎÃK&%ü(úFöÛ6´Áä¸Þ+ˆšP-ScÒ=…•° ¡’>T"ýP›GJx"Îc J°·ÄŠÍR˜œ1ÿŒƒr,aŠã žŽ/ŽÅ{:¥ð$Ô¬± ª'΂äÇ Ä_!EB ”N„<Á8¼Ã Ì‚öà O•?ß(®:Ø “± ìàÁ‹ƒ>-rá`’00”a ¥g㥑Xàñt7ñ1?œÊW'Ùx\Z«ÍR@] '™ih…-ã:êO¡¯¨©Áؼ`ë‰]¾„æÁC50çåÒ6 ¹Ž÷¶ïoiLx "âxîäŠZ˜Üõáðà8¨x. üÒá µrïD€V|µÙ¯á¸#‘ƒéH']Ý ìÓÔ}u¤Æõ"Y,s¦¶#4Q™ÓÛÃ|©˜y84ºãÃÇ äágäჃ^ðù·ÃˆÛ­íç·3Œvô;ŠOã)$iW !jü™€tÌ‚tLM@º‚@:¦HǬ³á×"d¸Y ñ¡Ù5ËêHIœk™nÊ•©w]ä¬[»ä´ÇêÜì‚nÄX.ÈBxGâ¬=c@"‡4OÁBZ$å£AR`ÜT•‰kœb" Âuš¶X@r«3¬p¨3íÜx<ƈ+ÀÀ·£xÊÂsX:ŽF†Ñ}ik¾nQ-WuE¨¡-W°|޻ʱî‚uggqÂŽèjƒéÂ{Ÿ÷m*ÝÔ yãw³>~ œU~˜• ƒ‹¡½¦!}&»ÂTM!/}P•r¬m1ÒÎÏE¢©+ü›{“!ÃÃ7jæÍ·C¼®c¹dÚ1³P%-«ÔQ†- ’1¶<ù‰Ë7‘y­õíLMªó ŽÙÿïþc²Ä’1Ó”›-%ΖÂó+Ì!žÄó0é;à ˜w˜¹#×ÇÁåþ™,1uзÔlm‚¸/ìÕsNÐP]ääƒü Û‘Ô¥>¸¼ ú@ÍûªìâM| ÎûÀåダJL%ê\ý µMf Ì3—ÜÌù*°0iÆÅxEìí&¼¡p6†»qh„/mÆU¸7ˆäéžå–o®´¢Zu÷oplo”½U +Y‘ÓÕ#йOþA‰örÙ,rp­`&îè×]+˜ª˜ñ^¯D9wÑ@u¼9uÑ=«T“UC7 ©A-s%ðh /„Ù¥öÅ,êì‘ÙÕ/BÏÔØ9“o;?„¦ÿõ`vº>hš= ~AÖM iI<~ÝÎÖ§ª¦ùÃizh¼öªB#2u•â§n*唩JReo*„^œº©pd¶lš~iÌ03§n¨Ä¥NeÌ¿SÌ@FÏÍ5‡ÊþਙÜsäâMà5 ”.:äøbî¢ÃMCùó×ÜtÌ©ùºÊí‚ÍaÒËÁ%XâX5n*˜¥´”R;ÒŸÿò_ßô1 endstream endobj 502 0 obj <> stream xÚ½ZK“œÈ¾ûWpdbÕµõ$;Âëð®cïjNöøÀÐÌ42 # 5£‹»3« (º‹îÖ#R¨¡*ë‘_¾Eï#QøÃ¢„Ã_ûèo·Ñ÷?ɈQ’Ñ,º}ˆ˜"™Œ68 £Ûí¿ãÛ]y³BÄîê¶ö±h›m5Tmƒ¯2.nxïJøIãÿâ?¥£»Ç‰øÌa¹Û§kCÕ”viÕ¿¾ùÏí/pljÎå’(fÎ}ìò­™úþ'F½ O ¤ù—#X0ÀWnþ/¡ €@qGP6HH2¯ßð$‰ïb{Ç”hq’X`þÚ|ÃIšâ¿Žè‡À)a#w7ã& ’%8 üÉh‚á6tŠ&šE›‰æŽ 8'#T¸s¾ OÌlß6ØðTÉ|©<ïÊ® m&(‘ç¤BI2‚^õ+h‰Ñ|hïo6JÇïÊb¨> Ê˜ñ$~84jÙ«°¢ÄY9r¶v¢=¥ÚÎÝàáüMŠ~A¯ï(ÓEU685ô¯`Pf³zPüÛ臘Ì3(xÙD12ŸÛŸ}>tՋã˛þɰÖö¥5·ÐÝ0A”4; ­EÁÁ¨¼<åÍ­Ü‚Óô°SeQÁ1=žbpý’qQ×à¢VqAËæAËØÑ8¯k»ü.Î/U]åÝG73n«ÅpèòŒÜÐ~¸Q*λ*Ì܆–3:âL83Äy¡>sr³I2ÿ£l÷%˜b7¨q/ó`ºTÌè8ö HôæþŠÔ£êÊ}9šº÷gumA‡±ÛxI=FÉÉ•×UK¯+À,Gÿo,îwí¡ÞÚ+²n›G;‰b2¿;·¶í†]ûبp¢h÷OµwsCó`çrûZCV’wî°Ã}ÿ”¥}Û¢ã—IkàuJkhfh²"C&™vbgà…=qb¡W,9671R$qEJ¨6gÐf£íÁ–ÚV$°©±f\>RŽŒáà€„÷ DNÞÌL6m·Ïëþ”!cT¸3©8ñù’òxg¼Úø‘î©Î›ÒÜŸ3—6˜•ž‘ÂÛ×xFr)¸svÞ‰‚¯ #IÞ„óF†ñóŒ»è=ºê¼›Ø4ÞÀ‹ûλ4ƒ‰‘<9œmå)IŽÜËyâò^›n§rm 9ÃS„êD\„GÁ|xÂûð¯ω‚éŸ`±&¨0¾D$„Y+i»WΑ@ضÙE> HÀϼ â uLª±€Hí%Óñ’IíÆ>½öë`Qh®‚>îëªÕò°¿S:šHÂ}Ž—¥_¢%šd|>åMГ ³¯çÊôÙ&W®C//A5òoƒlWò,ðA³Zò ¿Éë`/Cƒ{E£ cgË…4Ìö†jÀ¾Ôã"ÖÊK±VR¬ä/ÆÚ‘½‡’€å˜Yvý0j>GZ—]µGá¿/ Sžàó3f$.v›Õæù8µËqîƒéÇ­”ÊdÓÜ9«fã|¨Õ`”l$WãrN5®7^µP!È&ŠÕZ}ÖÔë­W®/eœs° óf ‚QÊ?Ù<ÔÂÊ!\Åûd Y2ÇŽxKÛDIcºÖfµöM0bË©<¿‹ý5肸×Ü¥˜ÿßt½.(Óë:Ž|. >3*°…s2U“ËXiŠÀÛ‡I§vƒpµ,LwåöP`Mˆ‹Š¶7…ŒÛyº¨üåiywq×â ÏýJûÊRÌ,¿Ä»Xã‘ZuˆG[Æ$ ¡‹2fâZ$bäM1 ¿s_ßå1ÛHrëêþY㚃hùõ!,Ú™çõ‚pj~žQÁK¼s°j4ëá›;ˆd¸ß‘ˆ•.³kW¥èe=9äÖÖZÅS{oÞnÌî`^.Õpl@ˆ}Aá;JN‚ZiÙ1Âô§&%G'ZÓRØ>\mlMãmŽ[Óv°u¿F{áᨠ15öéC5íK]G²±“±è¨Qf;—ð;wÑ´ÔñÏ-ò¾\nS¾äÅ`ºa·/‡ª°$PA÷n™×]ƒ×g¼¬íe!ݽm1عÂÜuã]Ó^Ø nÆWñ}Þã‘Fz0+<ç ¾¦ñ®EÓ~6jh•Ñ@X5v#Ë>Ý43Ž%¼ÃœBµ9æE' ‡5Æ<}æú•=Ô²m6÷úx¹óu§Œ¹쨂(¥iHŒr‡íÁxÄÈq‰ot¦cgÌ–Î šmoG,1s{íRÃ3µý?Šþ»žÎìÆ4ÌÉÚ» 7ˆ»½ï Žý™o 2î+ìF¾X @og-ëê5#güuX½kÃè“ ªíÙ3œ Ê®j»ëjOý:¤ôν¢µüÈ»<ê¨Cdòb"ú2×õ>ý Ó‘= &&`Wé$Ý6GìqeÙW¨ýëp®Iªü¬á,E¦Ç«†ÙYï–~— %Ãì|6,¿Q6̾(‚jì³¥Ã̦ÃâL:̾4æß&öëÅù+ëJݲÒoáïæú)‹²m V·EïgMwঠ¾Ðnç3—­]g:ù0n²üg§qÖy÷XÚ"¼Å½ñÎ̦[ue›a*Ë®ƒÜd²¨dÑÒDjߢr›„ÿx½ˆÈÒè9bYjJj%%ɲhq  §:zýnÿ‹Ébó™L¡MÙýÀ˜ÓÅ_¥RR¼QâÖr7 aÊk«I¶üj>Öé\žj&*> Ÿ,$Í®]Þ[cÊ3Ýï]0ן‹¡Ch.RËÅj¡°Â(µ¼êŒ7!±oOñ’ØD‰Ë÷Oå®9vÈ7 ›Yäδ2)—X“»O¦ô¹³+åÎ/Ê]\\vVîéµËCr—€¸†ø„T_*yqQò>…˜q> stream xÚåZK“ܸ ¾çW¨rÒÔ®‘")iíä°yÕÆ©TmíܶsÐt«§µVKc=<öþú©G7{^Ž3•¤ã½ǨkÇ¡jJšZõ48ÌËÔu{%tx_5·ß]ýóúo !Ï"有 DÔŒK#bf¨â ÊY&ÌÈÜHÂDú¢‘ìUù\šõÖðœéä+/öº[u¦_9§d: rÅ22|µ·DjI³L+$ØÄqÌÅ "‘°8±DoÉñ>9:8,O «Œ%”ÍR’ò½UÆRXÞ‘¼õ‰-0¥Å¾ñHœ1™Û×^añŽ[‚7þšim_Ã1j¼û•³RvçU¨×ó}Êõ6õ¼Íß“ÎbCñ¶Š1K’µeÖRp–¥VŠú\ °½2R¤+)”GŠÔšWH¯Â ÷˜U3!=ëx­šþ/XõúTì4&ÃoÂcÕTÇê׳ÀæÊ']$4SÖ+Ä3=O]ô¼…Í—±øt*cÄUÌT¶”êµ¢ˆºDžâףׯÕcÑJ!‡‰äÍ… ›•pòo2ê³/yÃñ<Ç{Q|n_$ÿÏv¹JŽþ4Qèšé°Ý_E’ó°hÚ•:ì«[‚+M ´ HOá»w×^ùr»=øÐÏ"Øüé{çUR¦, ¢b Iµo»«H(uí[%‰wlü{Œ]Ú$/ÒôBöÒX ¸ì`<™á¢é’ºË<úö#™JNèjœ9¿i¼ùQIûú[4ïeWz÷ ¹4ý"ËéÚðFÃxQaWîÆ-V<8¶mû†7áߋۮhnKz>¢wŒõPÝÕUÙý =:á5~ªêªè>»ÉÜsàxQ.¦¬tá¼q¦Ä‰ÕÚÀê ,49z}™eáöÑYTœtÂù{?tãv»¢&wÚ„Þ#.g¿ó- wi>9KÄyìÕäZž=cw¤¿PAki½®=…« ¾­– µ}¼B/éªâ¦öú8ÄÍ çÉ#>¾Ž² ‚Tá-Ûc9tÕÂÉg’d8˜fË6>–Ÿîº²ïËÞÑ•4Þ•ƪ+¥ 9Šˆ9ãK?Å€ù3G¶à4EEä= âAIdì0ÐU·Uƒ^…Ãw] Š9ÒµÞ²Ûlm½û-=Ðtœ²eak¡— þG|DA³p¨š[¯ŒȸÅ×M‹ãh©ˆ¤¨[Cm%teú´;JCAHØUóÔÏz…}ÐØ¶èQº”r ^OÀŽ¡Âïh+00±LŸÄrMˆåþ„e{sAú¥Ü©ä|Kû±Ù"ð­eø¬(c·"Þ™Ä×›¢¯¶x i±­Gr|1EN3"g¿žˆ)ÌL›8¬Ï!Wðd¼«‹‰[¶Tu–ݛل¿–]‹úûVÆ9Æf×Cn‘˜Ï[|#‘ÇHGŸŒ¾pÂâ$à¸ÉñÌdióÜ”å®'ÊÁ2¢%Ütlx6Ðð…Éæ†CÛDN 0¾ÖÂÙnÚ$Ì<ÄZòð4on_Æq¸͹¡Ù øt(z;L"ïÈpµìÈxZ¥„„ÀÔß)õt/wÞPåÜV:^˜.Õ Àß°ù+ŸeÍí‡i鳚TäÍÆx]f¢‡ ™¯³>„;Æ‹òì/”œAøÓET³ì¥5äz„‚*Ï_G‘÷Ír鬯HH˜†šS΃(j)}±Y ßêÜtø§"DfâB2Wo΋½ªAR ’âG„€ˆ’=¹‘$™fG{ß•CÙAþ6Y ž1‚ ‚àŒQUd#!Éš˜§´¥x·Œ+HAЈ˜€'÷»¸•LJk]t·eoñG–ù ‚ܘjš‘Ó|Ž)ëbÊ‹f¤ìº¶›cWºTGš3ž®¸R þóuð!`ƒ{0 Ç.>Çk# H$wuðSð#}zZ3_Iâ`ÅI €òÙ?¸HÒ%çsëÍàô(e‰Z7bó‰DbŸãí/‘óTì¼÷M×ÉS§ÏLç&ñ7Þ¹§U‚Z9”àÓÞ WOO2ÏWÉI¸Z™ì%˜!.ët§ÑÔØ*Xœ¢Ï¤K97pÑgdöËуψǦç_Égõ°¤ƒÿ9¯!cK@"÷¼h´šÀz ’œ9›Ö^#; Mê¬ !¼`NEøËrùcÛLQÖE4Žûг=_L!¾üJ„”àÙE‰\˜ž.ÂOú~ú³È¸Í0tg†„ÉWuéúr aÓ°‚wE7ö‡èÝxh"@Þ"ÕKG4íÝP‹áãØ„¾{z”ÜçªÙÖã®ìOä€BDî‡Ã·®‹N¨Q@ÒRYˆ ŠÒ™1_jF²LOêWqhöÕû`ºmI‡=Ôï!Q›†.·T®HðÀ­güi?Ñ*¼?TTs4‹VH¢\×nN[!†Øv>ൻÖPÙÛ²‚ɶ¹& 6%뜎e“ ï:Ô3ÝCi¨jezNY/kåL.ÜÞ?¹´MÀ•xˆVFÚgÙÝÝàÇWrþÎùÒ®¼\tå¡ðëI2ÕØø@•©šåœ‹|zÞÓNÔ%ÔŠpâakŒØhJ1èJ~Ø Qì a«žû‡—`k¢ŸÖ`d¶q«%ª|á[k’ýjûžUYmÛc‰kœþ.(±?îÁæ…­½*{ôÈ),ýl çÀ\–8û"3¸PÛè–ÆŽôÇßü ç]á endstream endobj 510 0 obj <> stream xÚ•VYsÛ6~ï¯àô¥TÇD€gó”ÃɤuS'VžªŽË’ÍŽx¤*;“ß], Q2ÇqÆž°Ü{¿]¬÷Ùã^ÜKü‡^Ùx/—Þ³7Ü!Ké-×ð9Èñâ-«?ýW·E?*½d’ørñ×òWàN<±4K-w —ÜpëM=.dèߓċËwtÐÝv¬[5 çK²šy¤Öi–Rúõ@¿•ITSd¾ªì7DšŒü=ÔK¤¾j«úÎA‡æÐÇ·ö oLÇ NYøƒáÃ˃8JÎ %±AàDèŒÜé‹õ=ÖRGzx”~Ó¼€4%é‘[-l&Ac* †|ÓLœ´3˜I#–p h‹¨ÀôÎÇÐSÊK«l}Fg‰Úª2­â ,è†PX±u·Ùtøq7ü2çZÇ,ÓÞ^\^ƒë×ç¯~›µÀ>%O¿’ tóÎafåmY«v!„ÄQ8Ÿ¥õùù¬'¤yÆ“7ï.ΟæÉZ+åÜh:“ÆJé–܈NÝ`TÕv¿¿¨8Ææªš€ë3­¥©\ÕÞ:luÜwûš¯·ãVÛsÑVôu¸í¶«Ãö-]NTí1…È8 Ý<{ÿéâb. Ár©ÍYB“Æ“ÆC¿ÄØ``%í@FoüŒyšWÔ¶Îöûž"9mŽô¨9¸ŠøcäÅnMÊ ̼ÄÍKb;¢ÒûÃ纅±ÉÐôîTáAÍÔ.LÈÁΊ–¡|:uwõx»ÀÌùä“;¼$þßsy‰3æ"f7_æÞ.óLÇO0#aá‚úo¨q‡´b¶ b‰7÷q#±ìšÐ9¨Êè#â‡ÝmME%¡²¬k0yì½”Bâvù¤3yÎÄÑSU©½[¶j;òV+7ël›Dw|ÿ£×ž÷÷݈ŒfÊ ÎŒ2p‚TD°‹)ñÙ¥+³¡"©Üjm§$î)˜œQÑ þ¦b‡]¨fiŠýUi½0ÕC¬8›{¢+ ¹®Ü3Náœàéèmx¤Ðç"š”Á¨¦îa!²ð€.6»j%üäÙø¨`DµÃSÖ,ê¥ÄõRêwv`éb¤ h;̦yÅ€sØ–%@`½Ýà* ƒè#‹0e"yâª&k‰±üEéÎ ÜÿŒê]=(ã' KÃÍàÁˆ@§Ñ®xZe6­˜ÒÚÍúÂÁuf:ÒåÄ4 ¹íÚ€ÌO—õãÁœ¡ê ‰h»O¹cýðÃÿŽšÏ endstream endobj 517 0 obj <> stream xÚíXYoÛF~ï¯ úRª°6ä<š§&q‚´nê$.P *\–¢l©TíùñÙÙ%—cÉE àr¹sìœßÈûà…^¡sø¼|ã=»òž¼ …†,UÊ»ZÁ÷y°4ò®–¿ù‚…ŒÏæaÈ•³ÞÎ~¿úÁ;¿ò>xL¤‰wç©”%RÄ‘·ñ"Á’ؾ®½÷ÞÛ Ã!#ä®)»â€u*Yš¬Ó”üëáa½Ù¶³¹ˆ•ÿ™$J/·MýçºØÐË2ë2Z•=º|O‹UÝl²N«÷äeì!ï Eas#+¦b-íýǪ޶ekïB º4aÌÂÄ›+Å")«n6WdÝk­Ý5è¼Ð¯¨!}üöòŒýñÕ¦3[y]µ Î·†j›5›3­L 5SR vÈòÛ¬1«*Û‹ÙÓ©ë†<`—X/Š6oÊmWÖ•!î]K%úøÕ-˜^ªÔoê]WV…¡(â,N ñüÈ$â”ÉÈœÕçZbß{_ȳ¸BÏâS{Ƴs~WÓž9Û÷­A(×›ÍÎý…¹ TiªDût0­å+„ðË–žKm*p'Oübi¾a¨ 鿇ñØ/ªeyoc‡õÝ+³hn(šÆŽ™T 9LçZô³)§ˆ"EêDg¤Î6»)#=™ñ e|T<3EñˆŒ-fÆ’À1n€ik“n fW4S1K…& /&""7±'Ú-9!/ѵ…ñOg%QÞƒW\/þ=C÷4-ºÞÈ Ùª^¯küx×~7¥Ú"&nÁ“ë.éøæ—‹‹©kp–Ú››É’TMû9Þ v–£á`+ôÛ®)«›)ñab‹2©µ}B¾àŒG$Ç¢ˆM¯Wõj”5ÜÔK\Q½4»5=óq]©»Âä4(­RJˆ¨×+Ce™º¬zÝç¡Ô•C×[¥•†º Šrè_wewK«vÔÑ=½ü1`ÉàvóiªA³¶'¾"ÉeDÊ!O«®K#>kÛÝ_ðòøì/Ïu³Þl!DÛb©ùÅ:µæ·%y_¥Ÿg­¡è>Ð4yš`g>­kÎEª-çдŸó¶¥èÏv] 9 Ji?Y½ûX›BI|”X­åc踑ü®€d«ÚSƒŽˆ85‹Ú„g“u¤ ìÝ¡Ùt=†—v—ç æj·Æ¦–†éCæ 9 ù© ´³Aј«hŸŠ¦†XV‰ð©Í]ÙZ‰ìÏ$`îm;b<AÄ¢‘'2cÞ¢ilÙÚÀ}°3«Ó v«ºš“øðÜCõ‚ ÄVÖ‹ã°)T2àzó~Ø;rš"[û€ î0 /ÔQæÎ)Ãôv¡½–u ²~yqþ+-/.b|‹?9Äøûåv?€]thäˆÅh‡(fQŠFtÍ7ï®Fy8•¤_6rfRóDײcÌS†ùz»˜T>„®Å¥#BI»#ÜcFÄĘ3ži„sžjàÛ çÐÃ’ã×sáùöžÆ%iÇ¥}NœŽ,ïÁùÿj:’êÈt$Ýé]m 4f7Œú2•aƒDÞÃh½ÌŒF°Ò£‘ìS·05ðÙIðyÕÔ†ÔЙ1IªaLŠ;&™n1ž¸%ΦÔ-~=^¤Âv|`f`J=0ñRÐt9>¯p‰™ïМ yä´ÄÕžh aj\ª~Vâ0û…üXý_Àj ³TŽÕ«%BÈ`µÃaµ`> stream xÚ¥XmÛ6 þ¾_aìËœ¡Q-ɲlìÓ^Ú¢Û­»¶7`À2Ü<ǹóØ©íìîŠýø‘¢d+‰/¹®hË4ERäCêÉDðZÀÿ((6ÁwWÁó—\œ³L©àjßçLfip¨Œ¥±Ù “`$’¥Ú½®ƒ÷ÁÛ £’ur×V}yd:‹Y–¦³ŒEâœéQÉš†çR«ð_z'³Ü¶Í_ërC/˼ÏiUÕôüþòâÅo´¼¸¤çªi7yoâ|þRè$ÊÐëܺŠ)mܾ¨›mWuV™ûÚ\± S–2åªîgsõX‚Åš«s ŽWîÕÏ‚ïÁ))é N3§£éL°ŒŸ3í”Óëíb2n.4Ö`°Î%éœu§4XÇ"Qn¾¾|F‹¢©»ùR1îJÈ”%g5h ž‹í}±µ®·y»9ö^Üæ­UXÕù¦\̾™Â†3õ–ÆôeW´Õ¶¯šÚnˆ§áAêW·€Ø8‘aÛìúª.§0•<]dô!+צà×6=ûöµd:µªF­#ëC?à õCœÄ¦Pbû—ØøÉöƒ‘õ =í®¾¼·×%›ÍS©Â…9 Æ4çJ0…í-¶.ã:N’|:RB É–&{€ ‘†å’d¦iáùívKòzYÝ;hÐÄ{÷Ê.Úª¿ŸÁ¡Ëpl(–¤̸7Ní1SéÞ¦g…·ùMù)ÎÕ¡s®ÒóQ²·-f”[¡4ãâC˜!€2@µ/Û)é‘JÐ@ÌO G$8µHÅU¤-»²ýg&ôP¨-v]éW€áYíú]k×y½¤¯Ým³[[¶ÂôÒÙºâɹÉ'ç«H9ƒÅøæ×‹‹©c˜1F*Œ’C"qj%M„ž º=/0q âa×·U}39Þ#Ž—Ù6ƒa¿L$VçàlùÌéaö›U³¢C÷.*ê1\QYiCO/}Âôy_Ú&)íÇ1´ãë•ÝåŒú¦†Øç<Θ~³B‡A B¥á]Õßâ* »ìNîéåÏI€eŒ»Ê°›SÓO_A?Ì)8´é‚C·UG²¼ëv¾àáñãpxÍf íÊ¥±G#ÍD~[Ae“Є¯Ã"ïìŽÁ቉+#¹ÙÓFî\AÚÏÖú¥Å ×øó]ßÀ´ƒ˜L™\ØxKPÝl ¡#ÄõUïº~ÿÚ‰| ¿+¡×êî)—O, ¸‹Î6ï)Ýa?äiv»¢€0W»5Ž?[OdODzl€s–À T[{ãùcÙ6ˆd™…¿€Óö®êJ‡´ÊºKÜ›- &™b2ÝtÛº¡µãà÷g“ô\C ꦞ“{;§'i´Ò‘ÄVçy4îˆã‘HÛ÷3LÚóÓ–ùò˜IGL Ï80k©Î÷´¬qbc6ޞ¦_]\þt–D;x­‘è!Çú`Z¤XÍ”iuÄ¥¯1¼kŒÌPÔë 29¨¯ÖùM÷¿9žãó(žäâTËBTêuÌp¸©–Ñ#D½Ž¬EâŽâáʉ»›ôlµ8±ç?¿¾¤õ@ÆpÝ6ÖLN[ìeÄGÂgYž ú}¶_ÎRf-Ý1K/Q¦³®9é‚OC0{ÌÈAY’‚ûëçÓŒdûSÈAÇ#׸>Æ„cCñ!O±!é±!:š­ö£lÈ<ǹä0ai:´èˆÓ€è§1ä,§‰¤Ïiô§áœ°Â§¦Ø ±ÈãŒøHD@Ípœ^ììÏUmníøŒop4ãû5ìÅ2›”‰=€Ÿ‘š|Fj1Íg€g«ä“øŒLÝ©=²kp:ðšƒkŸÌÆŸ‘©°C–û|FêÈòcÆ9<Åg#O/ÀgLº¼¬-Ë!¬Î1z.Í!÷‡s«‡/íÏ7ùMŠ;L§ÊáZ©$ÆG,ôì,1ùQ±kÛ’î~ ŸªòHƒñAB@Û8"Aj® þ]6 S$4g]ÃàX?Ø”Ã<:Î! ü™v¢ðãEÄ^ŒéÇ ‘F#5b“SÂY,>‡ êÌÁ';æ‚ ¹ Î¸`ÆÇ­§¸ økõ‰7[Š58$ƒàÀ’AEÝ#ƒYDH„¾#2¨‘ šJI˜ŽÉŠs;—§É`> stream xÚ½Yëoä¶ÿÞ¿b¿uµdI¤^× ÀÕÉ¥×Þ+gZ(­åz•ÓcOÒÆvÐ?>3œ¡D­åó5@ X>†Ãyüf8¤VŸWá*€¿p•Fð¬Šzõ׫Õù«t~ä««L{ØIVWÛ­¿óáOdbýæÃùÛר½k»Z ›_ýÖJgmû¹„õ™ ³þj¯aI -#hŒ‚Ø22ãeO¿Š¦¾}ýöå&J×—^U~ÚDÙš9ÑßìþÝëóñ{nt·¤Q:úyŠBE©ðs±ò¢ØJN‹q/q‰2áƒ"QîË|®ÈuÊJ“ŒeCcÃÞ ?)Ÿ*t¨”¥yyñzãJ¯ ï ?ŽÍnƒ¾G&a0mí¢mÐ"ð)›[«ÊF÷ÔlwôÛ럑Lwª¢»ØF™x«û¢+oŒzKcÜ«Z¤¿ó7žÉúå´µJæ0è®.5Ðêp}W{žÙ3©n¶^»óÌZT4pu,p—½êTœ`³8 Ö¯J]m‘šqÓx­P&käJ+Ì«Ž½>’èoú¨+€¤ÒªçfKë®RÍ'æpP…6"„ëï FDÓvlœÛ²éiŠõEI+»x3RDhõòlÖš¾X-þö·š\[l(F…‘Øu#áÿ‰xKbƒ›Îèœ$–´ Fà—ØCc«5­¨x´Æ­Ž´<¶ªŸ¬o9sÍ3ǘßaxžÑ]:AqfÒ“â• 2áä8*d„­)_< ŒHØrîÅ›———ÔüöõGj||ÿ#]¼íwïßýsÁ›^èG g(ê² 0®‡§b ~h3Ýa)ú"åéž}S”èUk´aoj1•0Vö'1:‡-îó™F~ê² gù™E0™ï±¨"ò“„iŒ„º3É¡ˆÁ.¹º\äŽTPÉpÐ2á”±ÑR®¢‚8ó–Œ4—ß'¤ÑÆþpÚ-é!"áÖ ÕaùF"mRº¶ÖæµVÕdãMÁ‰ 4©bàƒV·ªë¨¬æõ†ºí2âtÊvu¹$YL>%ƒ #ÉŒŸëò^s •dúV?+—C ¿ ±u4Т¨yü !](H[ˆA˾ºü…Ïh!¡Î,¡b³ÝxR¦JSÊÌYi ÛŸp…­p|wl½nzmÜ cpCýãüäPw®Odéunl}2û}u¡€”‘ŽÎm¾Ú¹br®À…£Lò)0I‰µ0ï§îã~êÞÙA"‚ÐÏ¿ $bŠ#“\dˆüœ)ΖX@DŒ9“ò2‡pdáɈ’Ç’8²Vœ'òz”úq>-–™"˜A‚Ÿ›¶ñ}« ÚSFæÆ$E!‡?ob8 «£)W¡ßs5WÀ­ Â%‚N™Ýòƒ“?“l¸Ø”¤§Û¾Á\ŒXÇ¡ÇsG憿èæ*ÀÑ IwNýõæŒhж:Öö¢z‚C„t%ÖЖHrÈà¶ þ/ºk©7çI;-i vLŠ’üžèéžN‡û£ÚsvRAÙ9¨ÆÜ´¥”ëwí íQ7¾&Z>•”O¹9A3 é âËKÝŸ^tŠ¢=rµLuÎR¾ÁšwQm±’LLyëÒǯFw ûÜr€‹ÿò)ŸN [Qæ‘[Qæ¡SQæ‚^6à·ni:Ⲇºñö˜GÎÆ4É¥b.Èo¹}i€.3¡5ÞzsS—óÂ0ùþ”“î#¢O‘I÷p)lÍ*FAÀû\ Ö»¯­ûç F<Þ%½f–cqHÝãÛ÷)IÅý¿]>O{üh·#m8¶¢ç—õó-þO•lù»U²ûÒ1Ãêo­l±Ñj #ÄätZÌ乓ÎG5r.Ge¸a•cePšg-œYHÛgôT/RÌ«7XÏtÃôÞ¢š éÇ9÷·àEP¥Ç¢[âÌ9AAz\Xâ•û™ü+@áXu”Ž5¨h–¡&.T—¯1š…{x9ÏZË—šé¨øÂ3'ætz(w!žÎß-â†fÁÃO‚ѸƼ¶&k{7îO³§Ÿ Î^Év˱c îÿ2ËNó&×룱$ÙΩ­ÞÚ» h7]gá×± ‚ \r9XÒ}c 2—Mˆ\2Lœæ9d‰ ¸\@¶‰”%ŠÆO.pâ…ÊO¨ øi‰ôìlIî3I(›}‘IêËpbòÍŠA#[SþiÁp~á œÏB'˃©$ýó’³½H$~–¸.¯¾ÊåÜ>UUニx\{aq‡á–¼.ÂI¼ë Š—^«&ÿ¸ð!áÅ DŒw§ça Ÿ…Aò{Á ~Žæ‡S„Ü,JúI6ó4TŸW¾€‹ÆÆtœ~­êU˜¥~4ö«Õåê.?bP9O3 H_J$t¤ó¯ŽD›€}ó$1´ ^UàÆ c‚‹Rû4[_\RŸËêðΤ[|û7ßïãg½ˆ>ˆ€E\¤C#Y_ð<¦FæË–pëÉÞ*Xoíoi. 8¶@Wx âÌE[Ž#¿K¬— mŸ"Œ~ÓgåkG/ºÁGô- ~wª(!*è›”Œú¾@½jn5Q˜ˆ€ßéÄT½b‘§ëW›,^›"BbQ÷¼ª§N¯'¼ËÉþQ аiq? ‡ççÛ²VEïwÇíÞ×ÛãùÅ^U•1úó¿X.®31Ý8ç/ÜóKn†G¦—Hru*-éøLl¢ endstream endobj 529 0 obj <> stream xÚÍYK“ã¶¾çWðNe…/>ÆñÅŽSYÇñsnW…#Q;r(qW$½3©üxw£¤ fsqíV @ãëß$ždð'…€ÿY²Þ'_Ü%þ/ž±*«’»mÂ5«T²ÂŽ<¹Ûü+o~¾û¤T T1™ÃJ8ü¿›•”2ÝšcÝî†Q¤ÏÔ·îýp¬wì°O¤ÝUúo»ª·–œUÜ®{Ÿ Ù¹dª²¤]hÇ÷7+øiní^s¤fJÃLèÄyß;™l¶7“pl/T;!€ŠUŠhVä Ë•‘ø%¶Œbvv"O§‹äL¨È"! S|Z#Àa®0gZX$"@)–—vø37?´óJÈ’iÔ~¤‘Û\eéM7>´Íªßmš ÙòÔöbaûÛè JÉŠjqÎ=TæT< UQÄ¡*Pñ+ì/_´ñû¶ÿyðDÔC 9ísÆI Íx:I•“¼” nãvm~ç†Rg õù9+ñËQê"€™á/@µð»Ç&f!XáìÿãßЬ-8ãÂgS®šã5ÏÐÆ`Œžzjú)ÝAﻦÓ2í¦Ô £¿ÞhÖíØÐgO2Íz·}†)Ô9<šQž;œù‘z»wf¡Õc}@%t•bþ`7+ ÝgN(sÉÊé„îÞN¾…ûƒZ›ŽÎÒÓ硨Q»CÖv ÚÒff=ÔÔB˵Í\AÈÏ´ÿ¦ÙÖc;¸‰õÓѪX÷ý¸o,|îľ¡#¤H)ú¨×e>º?î†G÷¿ÍÑ.w%ÐGQB¾zuZàË®÷°½æEnÏ">Î1)¸ˆ¸;¢‹é,ÝãÆcþ«ªé`8„@‘®·­î`‡Övcl‡VÅo²*¶vV‚üE±°EÆÂ67þCx“ŽàM½Fý1¡ü®l{±¦Òú¸«Áiïo€ÃÉÐ’Rh«Š>Ö=5:×cjQ!ׇŽm×ÚX£„c Õ¾ìÌMcý𰱸Úb‘÷ÇTÙÓǺW2ÇÊfè‚I4¾ŽZ„â´ŒâIng!X0Mwà7ß[Oó»qY0á.ž¾=ÿê.ù0Y•ÉG¿\%™Hö‰(áÊ—î»M~J~8ÿL™`eeoHHæ:ýò»o¨±=Ud)ò·ßþ5^Yé©å”–~¾€‰¯X~1ëŠ}ÆOÚg|õ>?ƒû–xÍ–ç¸b÷þ“N¹˜5Ï0Ó®s®‚1þç/2¼¯VëºwýÍ04ÇØíÍ3ɸöEKÏÂ/‚ªwÁT@%|¬ö³@ R ÞA"3ÊAܹڌ ,º¯*Î|Ù‡FŠ hÔf¹"‡PÂ* Ã^QhwGÈBuKær÷í­p|ƒ#öb {ÿ4ï°T*sY~˜Š‹æ@#œfUXÓJ¨'„´Ê"gËñ]IÃV‡æ¦‰­Ub }~)h ÷´0Vµ‹9fz|@þAŒH´ƒ´øõ×ä[(އú°nΔ=ç-¯\Ñm"&Z´j}bûÀ-Ǿ±=Ý¡}&m|擹UÖžeª|Y>‚ˆ§ÿgç&Õ½ÛÅ]€ým¼˜.ñyÀ°¾ê9è hòÁ±{Ç 6ñ§§Y%Øiw%z¹·øu[<\µÅDÝñùÎûÀ¡vÐ)ÇÕmk˼fµ Õ 1½4ppªÃž ÀTi·ßA–Ü`c¼R^ͳì¡yù¶ó­pùöµþ2cÚ^ç8³zu{ÌÛccu¸OGcU én> stream xÚíX_oÛ6ß§0ö$1+Ф(uOYÑݺt[ƒ زŦc¶”JrÓûð;òH™’)Ç}ØžŠMw÷»¿™}˜ÑY ÿÑ™Là_<[îfß_Ïž½¢rFc’Çùìz=£’Ðl¶ÐéìzõWTÌ"ÑooÿÀÅ‹·opñûå›ùß×?îÝ_P’pøF3÷¯7j¾`ŒEÛzžÈèažd‘jË¢uûªëTcY e‰¡DF9ŽË “ö¸½Ÿ/€½Z–71åªEÞݦèôŠÃª´{e¦ðhYãU¸˜.KUÍ“42·’h¥ÚeSÞwuce-+EŒ J"_ÓWóŒE†RÄQ} VJ£÷jÙ•µâ ÷Íc™ÿ˜Œ:-‘ F¢xL2ÔSãplˆ„’˜Z £ÿv…,wšÿ¾íÜã¨\QV¸“ù‚ç™=éEª¶k4–í)±ã)±ð|¹ØÆ¸œkdDˆ)pÓØ‹ÆzH“ƒ«²*¶xbäÜï´ÏÝ"‹æBŸÈ¨¨Âj©îTƒ÷oQÑîପŠ7ŠjåÔ}]²Œ°Ô*³ :«È챑!6ªQ!^,#™<ÁJ[Æoázcô*K£JÅà ^¬eïþÆâ$aÔ7zç÷¾©o·jg£|£¨–6 ¨ ùQ´‡|bÅ­HÀ`uäÀœ† ç‰• Ž—õv¿«p}@~L Ï"Cäyôü6 j(‘¹aÀ £qø¢ýZL„&+2ãyþò¯#™}§î6øs"9I$*7žáå$ÏN{=u«VË•`*”6ê á ZÓH®s=®Œf¾:ÍÌÂäËÂeKÍ êÙÏn¢››vS®»ooæ¸S¯‡†´ Ú‘gj‡Õ€c½¯`§¶(5°hú:W!JSwƒEî ƒ˜—Îõ_[û(ˆyÌ}c·¸Sà¨D]teu·@×åÁŽ<\uÐ|ç¸l÷ÊÙ¹4ÂD…yaë7V®ÆïÑõ#^û¬{œEÏ™÷ 2…"̆ùÑuV×›ù {.XfrszŽÅpÌèqéÍâ)#è£A{׵˶¸ô Ö§6ü¡>Ënûˆtë°h‹]–ÅÈíW¸ëìá´<®~%¹Ow>tõöêÏ¥š!’¸,.E‡fìÙ+ÿ‘Eš‘\ú¼{ÜÍÕV`P·åR«’G•U9ó Ù’PÖ)¡Î³¯Mî ¤6rjÌRÏÈ,‹°ïÌ¢]ÝÚU]Ù[í£¹‡ÕÙJçV–ºÎÌf"½Zã–ô²ŠæáLÚÁìŽ3‹%SÅR»ÏÆ&šZS>XpG>z3¿À£—ûÍÜÅØjÊ$Ôá%+ƒ–¶EµZ±¯Ð¦°qf-ÈÆ~ÁÁ..Ú!•`ë¦Ú]ûÜð{y==ê$©$©­–f°¹ÇÏÕåÏ/…±4ŸÏ )G“Ó˜˜ûÄïGÓUOü?WÕ6^w—®/°îÎzwg#wçSCê[©OÝHsékž8Í Íq ×»|{ƒ¼™ÍÞÚÔ{Óˆ2æG78{Û–w•²_XêiEŸ‡ìû8Þ‡íïz½N4dß…˜/ÌeïÏg=[u4ÙqÞ[åYoƶ`^9ï©÷g=uÈB<…Œ«O7A}ÌL7®üh”Éóæ¹k#ý)6÷¦X}že8MÍ,£)†³Lž;º3w?Åæ8ÅÂgj–ÑIQž=Åj¦g™œdüô›s–±Öègš~Ñ,cëT‹;fø×1öë{Æ{yìDi†ÆUCŸ†Æ¥ƒ= V Ž ¶°HLiÑ„êÃ^ÐøkÝÔ;\Qüè±F!pQ4·%äÒF7ù<îšâ~ã¸_¾{ñÚ<øÚ6BÃîYÛ·¢)A5톓_ñ>hþtÚ4Êúv]­ló5è3Cú ò½Ô#§ñ Ÿ÷ +árÔ| 9øÓ¦ß|ÃÑaÂÒvM‡ ;¶Ÿ†þÔ!4«¢+pKc¸y‚ö-êà®×üÃûŽÍîEc <>b,Ž yÇ·}4;´½Ow¹O7¹"MI’™ÇÔùm%çá¶’?ÕVº ©‚„gÓ]%箫ä}W «²?³r!˜Üu‹ .etiínópæ±:Ø®uG!NýkØ~&0I&>Ru£ú–P?‡@üðæ—Ÿ¥¦Þwz'P™Ø¿EÊ™:Ò_¿ù’a~ endstream endobj 535 0 obj <> stream xÚ•™]oÛ6†ï÷+„]9fùq?.Ó.-²9YŠ8Šfnâ¬Ì8mR´Ø¯EÊŠDS=€²|ô>/ÉW¤l7_Ñðð'#Ã?on|ózÙ¼zkÁ™ã®YÞ…·çí Ý,o?ÎN~¬üãv}4WVÍvw©½]=¯ÒÑ5Þ…Ùæ!{·¸ø#-.^^¤wïv_ýêùèïåïœ@æ -C‘ËÏ­ špÉv»;’zö}óðO{JÏÖ½´ÉNhW©é\…£ÞU8Ž®BÛ¹ G½«ˆˆ®âù§Ç£¹´³õͦ½~ý”Î>V~½H?~Ý}Ú®}ìÓ|ß Åc7V­€RÉ@h/¿}zZߟ¬ù7Õüu¼¸:9,Ú¤"‘Šî&U6©@ÔˆÉTô”É9§d»+>œž,~›”U©è[j4)ÚÕ¿Å¡"Œí³»àÍÕ¤II©ØÕŸO*ê‘¢"»ú³w“Š]®¶]·‘îwwÅñbR³‹ìm7ŸÈ÷vùáèµ»+/OµïGáì´y«I×÷£°¾>=“Ú²¨´¸ìÅ夸‰ïä-­®zu5©#u±W7´:ôêp8;÷£ FT öâH•ê}¬®Î¨R³OÉâôÍŸ…›e•ªùhæ9ãŠ*•}©¥JÕ¾TªúRI•b_Ї“1.ÕûR)(U³/UÓÝõƒ%êKÔ–¨,ñÓÁ*•惶ä/ SÎ6ß©TèBØŠql|ÿZ‡Æ5Ûæ²y¸+!™³Ãý{ ̇¼´È¸“h  MÜt÷\xÆ1Z¢4'™¶š¤h‚kæÔ—ðNpÅ4xŠä ìð:PÓZ)cÞ}n‚bJ`¢” “m¿E¦Š‘÷¹ Š©0Ü C&”·ü"bä}n‚b‚fB˜/wÊôÝ)uŒ¼ÏMPL4Œ›SeÏ+E¦‰™÷¹ Š©mHf 5¹µ1ô>7A1mÛCæË½¢§™.†Þç&(¦uí%‡Ìš{EñzŸ› ˜áS#Ý*˜Çvzh•ˆ™÷¹ )³ºÀ¬Yà•Œ™÷¹ Š)%³²ÀT5C«bæ}n‚b†jc ÌšØ*ˆ™÷¹ Š À ˜5K¼Â˜yŸ› ˜ˆl´"èÿ!#ïsRk¦±À”«­²mä}îBô( ±&A.FÞg(¤µ G#k²‘5“Dà1ð>·@!Û×7A0!|¬W`ö÷æôŽ2æÝç(¤ °€„šnª6ï>÷@!•d H¬è%ĸûÌEÅT)>ývâ~’Œq÷¹ЉÀÔ(?¶~1óîsS#“¶À”[5˜xŸ› ˜F3 fÍc¸xŸ› ˜Ö0Y@æßé”Ècà}îB:Ë„.0k¶1ñ>7A0‘»Ð“³æ)e̼ÏMPLÙNXi*nT1ó>7A1•:‘¹NÌÝð—¡" bÒ}ކ?JiÛ_ÜæºûÎÀô}xÿË]2x endstream endobj 538 0 obj <> stream xÚ…UßÛ6 ~ß_!ìeÊPë,ÉòômØnèÖ¢×^Þš¡õ9Jb ±SÉ^ÚbüHQ¾¸wÅ`J¤ÈäG†}d’¥ð'Y¡à?e͉ý²f7·R3)Ee [ï@ŸÈTT9[oßq-¤ÈW‰”Êðýñ¼úkýûmÍ>2¡«’]˜©D™…EÎN,×¢,¦ã‘ݳ7 ®F1Èŵƒýë*Uuu]U"Ußs}5Š®Ï®X%º0üúP¬ ¢îhOtØÖCMRÛÑ÷÷—w’´ëÝ©À›Û‚¡÷´ÂpIŒ§Œ0Eˆwÿ¹ëϾõS6qþÊkŒHɼí†UbT†µ} ½GT›p&ì*ÿóÝ3¢=@:Ö{/›¾óñº9Ô.>ÙuõÉnVÏ`c‡Kat€ð«õkÏCÛwÑ4›™J#ªln¾>@õ²¢ä®‡¶³ñÍW)BƒeQÐþëÄ"”FdÑ6ØyrÿØ> stream xÚYYsܸ~ϯ`å‰S¥¡I<öM[‰'öFëUž¢TŠBîrÈ1ɑ쟾Àc4–RV™@£4º¿>€ ¾Iÿ$ÈüÅÁîü|¼{Ÿ‰‰´IƒÛÞ&qT@»úw¨#µÙ&‰2á—î4Ö­6[Ùð¡ë¹qì;h¨p熡n™ø¹÷7}'½r$aåšaóŸÛ¿½åM$ITX+»š8J ¿k”о6üØn`òHÛÄauÚu×Ò:ïÞ›% \ ±Qa‚­²‘Íi‘Ÿnþ±¾ ‡Óñ­,ìúq`Ò¸w²F±X£°Q®@šþË¿€57r˜Ãnc“ð©8ùš²}<•î’l©ŠòD޼Ø_>H£µ€u¢"Ãy*Ë¢4ØÂlÐ\5ÏÅi2c¹•ÊÓ(/`N©Œæ\Ë‘Kþô§Æ]¡6b2ŒÊÙ04öÜ×ãèZîÔòŒ‰[oýú‰ŽÐp°~Ù;0Îákž6 eWqÿ¹÷ÜBmSƒm¢u~ºy÷ùãL˶ږM×:œVêE™I¶i »¾¾gSWLÃñ;‚¸ØJMÀœùvïÇëÅPc ÆS]9&”í´"ÐG×?”;"-Ó&—ŒN‹(öÀ–d ,Úé0°”íДc×_6©ÂûŠAiRƒc‰KôÝ4Üu†;¸ËÊôî¿è l&öÈÐ82ö,‚xxÆŽžEŽÌk¢ãá²å蘭¶l¼@2Ñ3V<ÔÕ®Vrý±wãðÒÎw¡ûæv'ŒÝVOöÔóêc%%$yd5ͽeg1+˜²*¿%óÌgdò±CX&Ê/S^ÝîšSå“åà$š• ÏFwÈÏíRï4´ïNMÅm/ÛØfR§4À^×âF ®}ÀÕEš†C H]_¹þ§U&^%Ø£(¢„“G­‹— wÁ|½| Gü6”wˆkˆ¸µ0Jb‡Ï]ÿÇp$ ì,k*p+H'Ó¥&`bx4J‡%lÉ`%fÖX1ëÃ^à W¸·!pâØœ8­*Ç’[ÃØC¡qê½îY’…ò!U¢NQ9ÈÁ6N÷ƒûzšüMkÅ^Ó¹Ò6RŒRõ¦ÎÌ_H}¤çŠõÇsqÂ]ˆjh uôŒ«ê¥žuV¬ô¬ó³N…xÎãµg䱣ܗFd*ìŽH½|ßä*$b":~1ë¡ï¢k–fËt U‚$î]}'†ÔÔÑ}C§EˆÔÆ1•3yZ¬Â±ïÝG戥SŸFg² §ì|Ä” züøÀœ­ÃèQöp:M§ƒÜJÇ¡m($ZžitòálÖ`hJwˆïýìØm×»êuå&Ê­ÐoBhf~ !“z_0Ù=PGÝm.»*% •«®!d xa“J=jÈØ¡ë…";ë !2… ÂôH@*!AÜõ<26H|ñÖVÜwm<@´^D+QÍ9@ðê³Î:?°ŽVÐã*Þ¼ió׺~Gu{´.ý²_ÇQ¬V~­Óµ_CßgSÝ»¹´IÇ´³g'ó¡>… Úœ@‡sé#3d‘+Û‘‰”ee'qxsa­¹êDV(À Xøà00e8M9,_z* WÜ<–Pq:Ÿ jª¢ËûÆ1-Fù ЗrTOhȶ–¶­Ÿ…ªvcTøÏ–9|å‘x7'š{éå¬äÉÏ}½2œ†é6âóI9N@&’îŠ>HvyqYì û6âfæŸOuÃ@¥|h(¨™è ú;ðHwÿ»„†‹èÓ&Ò+ô)Á} BDw?‚þîP ÅÆZ©[·XãÈ  °ÅÒAc•éX,Áê¶&J¾Ç#«ZÉð5´ì…JD>*%ùL¸ƒiåè­yuf2¹ñü`.{°S°—2îÒE>fLÝÿ¢LTmìüºàãó0aâ4²üÈ’¾‰‰óoB)”ç\Aâ"âdÎ ä3fJfJF¬ˆƒ³ÒM±ô?& ÕFf$Ošg0Ó=ÉÙä‹¥k¡ËK6œÔñ·œ°˜Ë¤<½?HôXéK—Î’Ã 4€k@Ôέ2 R`¯‡iÅ)>@á_ÒnÈêÝPÍ×-oT”ò£^ö¶ågæ›no}›ˆ61o%Ÿ"*–Þoc½ò~ìïºcª 1Ï4«{ìê+†éø66k[7³K~AIOëP±5™Ô‹&+䊭9/ g·†,_^i‘AÊ”å†KÊf«Î$z5Åy0Xø‘ieN””˜,„%ªNµ^×èÐß—Rà´Ý…´¢BA*¼ZÁZŸÕ †ÞÇ&øã’àÔÓõ²]ßÊù¶Aáõ8 åŸ+ó·Á93¿ßà{ØT¿:–Âú:ÆæÿçM3I"».”ÎHtÞm§»Þ¤¡ƒƒöû4:ßH}™ÙMX0òHE1àFí3ñ/ÝHO^…dn!©ˆW/ugµ6ô¥® ×' åqÈõ½çÚu}ÏE6½Î!Ty ~à9Óû¦ÉsÆ"é6Ë|Jvïx$ûÁ[ÅCYãK‘†Jñ.¬Ndy+ 40^0¬/"íòænsµ,±ž[>5"óœxatzJÁå\¨[.Qí¥÷\"4Œ>v“|/ÞG}¡§@ýDºÈƒgä´EŒ9û$y©©ß¿¿Êû¾ @=YÎ÷¦ÈdʦËÿú'’4È£"MùGLÆÛ²UlP…JŒ_¡ ±x…‚ŠmVÜÔü#õø’šð [ñËÅÈ$*RR qýùæù5"Nï7¹¥kŽqBKñ×(ì¾¥+yŽ=Š¡ÒDÞãe}Æ oþ驿P©MÞÝ}Æb>äŸæc-ê²WÇOøÀ›q}q®wŸÿÌÌòfWñ(áÐø¤ ÃòÓªn õýi~O¹ÕTŽèߦ†ŽÊ ÏúëŸþðÝH endstream endobj 546 0 obj <> stream xÚVmoÛ6þ¾_Áe_äbbD‘Ô˲X´è–íê}šC±h—ˆ,©”Ütúß{äQ¶9@P$€ørÏñ¹‡Ç;“O„‘þIcøÈzG^,ÉåË”°ˆæQN–Øí$!ËêŸàúK¹ëjµyƶøwùX‹‰5“4€È¨äñºY„"N‚á£îq¤F"NaYájgÚ­)w81ª¬z4ص‹>•ªq^6ÚTåPâ¨WëA·lLë½è¦Û¸XDLÀ‘È—MÃã)§2(-Yµý¯è®­œåõÒ«ó×+?0[Ô‡b4O-^F#ˆ8–cÄü¶8™Š$dDE ˜œŠÜalTŽ[ XI·uoô  6žG¨Ïª’¡*v>´øm÷ƒ‹ÙŽ™IN³1wý™Û”’fÌÛéÝnŒò$Þ¼ûà—Z³+ÇSá:üþï]çXª¦Ò_0€Å‚âæ[ϸoë½½=œidÆQN“t*CçÒ@{–ªè¨±Ó27‡ å>]3IEæ@—Ï¡ŒEùÖCÒ1º¶s<»tx°9Í™³ýI7ëz_)DüÚ•néÇßFCÆh.1¬õíËäœå¶îî&vÇ£u3xž¥nŠàs««b1w÷?H€øYÁs¹õ±ÔÝ•³åŒòlJÔÚ ¦l¼^ͽúÃ%<ºájmÝáîsüXŸkxžƒrŠ Xœñy> stream xÚÅVÛŽÛ6}ïW°Û9ˆ¸"%êÒmûP`¤ÝIë>U…![´MXIÎòï™!)K޵›EP¤°ñrævfHyC àÇHÂáÕžü<'׿$„4 22_ö“˜Ì˼ÛwÅþPÉ™¦¡ÇgÿÎt4B3A³ˆø\P‘‰—5€æu[Õâˆ{ò¤Ã,K»zhô¦)övµ‘EéÐ{=óyꕲ²[­\uJ×vsÝh'‘,Ö!6öŸ§‚)„Þ´ÇRïŽt¯K½»øÿ|áÍÆ2À€š%¨ )åñCNEj´Dƒ0Ê9‘1 aœ Q?Œ©ŒÚÔºQõƺ[]qjô{1R!¬Fšñž>ÙHŸÏü(HNDe¡WTlê¢Sog<ñÕìd¶Þ²o'm“¼E) Å9o n"ç"¡Y(Ö*|óßåúgˆ‡àõ¡û üñDtÛá;$?uÒ^ܽZüþòÕ—Vò­OOYïÙÃ9ó#h’±G˜ªïíýÞ¸n¤tw ØËŽ.ðOÐ/OwíC‰‚Xó1pŽ\hûpùòô¤Ôë³—^Ö7„†YJîQ vC{ÂRèNóŠüE^»®Kè“Ôt’œF‚Rʲó¶Ëbc’‚ã±ÁB›¹ˆ™}„ç¦YâqêÙoæá3“`è=qqÜZâü~«Lã°=—uÏoÙÏì×´8€2úÍ*/UÛ5jéšc¶Ò˜b£\uÛ~qhÔROZc¶QC-çY4]IúPC6¦Ãž÷8ã¶óû+?ŽlW›²úú›1ã;\ endstream endobj 553 0 obj <> stream xÚíXKÛ6¾÷Wè(+F©z+Ú)ÐGßêb¡µåµ[rD¹îùñá %Ê«µ“{+ÀäóàÌðã§õ>y‘¿ÈËbøzëƒ÷ýÒ{ó6’^‰"I¼åÖƒ(Eê-7øRÄ"^Q'þãþ¸øsù“÷ãÒûä YäÞÙK ‘+£¥ÞÁK¥È3;Ý{¼÷3ÆMìäpÜ?3œg",FÃE$ÀÆ Ãã&6\î÷í"‘¿~f?Š Æ£ƒ(–"Loypv±‹óG}™ò?ãOâø,ûŠDýκ²Ñû²o;šŸ2ôÛL”ëÊ„øæmæ¡q8;¸ ¬¿8Ifü}xjÚ£®µ=Åè*E™ˆr/H’ Ôí=/‚ªø-N!ã÷èúã_ùµõfµøn62å"‘ÆÜ•^wõ±¯Û†÷+×{" ån_âá•Lý®=õuc9 9…&+ ñl´Óðæ¼„™ÈSÖ ŒÇ™É¸Fg¥?—ýî·®}¤Üàêy§CÄ"Èå¯ü_ÚžcîweoÜÃRjH)°°kàò´ïëãË+c¿nt_6kŒAJé·[üU\~œQc(·J”=‘þœ"÷y…O•›SmîHX³É¦/ºìž¹ôÅj1S¸Ð-ÂïUêýÅõ’2ê“ÂïØ€™”ôs4Ioë“ØWØÓ˜ù–VùÔÅôÔw,ÛÕkÔÚ‘ŽÞµ§ý†–œ$þIW,/&*H ôéAWŸNUƒæ{Zl¤Ü•WO7 »V‹é广"*ÐO~úFœ;ðGó[ø7ú¹€Ö¶·ë¶]l»«ÊÍ úe"ÉëQ‰4ºiÞÝfc'´ÛT{Â4†Aã–±ÙLÑÁðRQWkS.`Ü" æ_ƒ±T")ŒNÝôb0ÆûC ¬.A‡w4^CǰâzWv¼aÛ”‡Šw †õÇúøš0çÙ5…v 匎gœ…ÑTÄ1kàNM>„<¦48·¥IŽõ„sǧ‰n$ÀPì³pSöåDËÈ3¾ò^ù8Oàcp…¶€ë¶Eø‹¡•HÆs¸¡)@ëщʕ¿íÚÉKÖ«þîI° #µ¯xßy×êŠäXGÕzâKùoÙ•kƒn¸¦û®nç’/óBD6—¦;fç"µâPE«nÛvjç@A³dɶøê˜"ŒoË48‡¨¯ ŠüÑ„•GömÁ}õÝÅF ¤}Åpg¬n0V'Âæ—:BÛîý|¨0Ã3YͤІ·k.§`ÙæKˆ6Kúš'å#¼ë .ç»- SŠWëæxêIFÍAb¸ïæA+ëÆXSVcèm¬ÈæLÛÈ3I­¬i›àŸªkï¸é!%ñ¤ÈÆM¡¬›B9nŠ„ì€°i{ÆâRÉKÈp¦:6fj1Ìšöª :Ia®ÎrÙ5Øó €~CÚñXM:v55\µÁ\¨/w Í!PD ï´&¾ƒñËns­| ÄÆ¬Ñµ6}'£mT3³K¼ÌÔ×òlYXÒƒ‘TpÇóÉ%€>­‘ˆmO{¼ÍQ4jì '{lHS ÔÿW<͹Ö­Ì)§cv>”¦!yÕum÷ŒæÐy‡2M®µCâÔÐ×ÉŠ |·,R·ÉŒ+2ÄódÈñs… ¶™æÜ°=ìl_%CƒuK7n˜· ö¹‰¿†*¯C€@h|aÿ‘ÿ¼&בð6^ûd„Ú&s\ÇäsŽêD"I§T]púsežXÄÉÍS‚«D$P0 iX!('"£šmÓ}%ö«$0yß™aHua$ /!j$R%¾…/"ÆÇ”N(EtB ¬f‚²M CPÌ—\mû2¡¬fÃ&çÜ$®v”ºØuAJï˜î8ß½†pâ+B.BšóÅ:ù²–æ£2£J uðUËŸ:ÞŸúLcÚÆ’–ÿ_”ñ¯·^ù‹2éNhO°¤üí˜ÇvëûoþêÐa‹ endstream endobj 556 0 obj <> stream xÚåWÝ“›6ï_Á#îhÞ:m:×I“Kã>õ:7Ëw4€à8éäïJ»áãì\;yêØ3ècµßúi×yÀI8ü}§¨ÖγAèËâØYï`ß |– g½ýà gñÊ »wU»úsý‹óÓÚyï°0Kƒg,ÌD8µ#B–&ã´rÞ:oLD$¤n«ŒÓ„ùÙÄ8 ð¸Àx""Æw²‘]>È•&‘ûYâÙbì÷4¨|¹»•¨Ë³‰£ÀÙ#Ö$,H/Ž™GÊfXy1:òl¾5¹1+C—7¸ÿ­~‡ãB5=+îóŽvM^Ë›Õó%UIn²84r”}Ñ•íPª†è#[͘e‘M¾ÖáàŠN퇲‘tff[œè°ûèäkddƒãþ,&½¢ÿõ@ûŸ'Æÿf¾ïËæ‡å@Ä[˳Ъ“[¢jN8j/öU$F%/ d |C¦ót9¬@¢êÞõm^H¶òD(À|ªIèªÖh¤µ5õZ-'É£e˜%n^U¸ñaÇnÞ•ù¦’=„1 B c—ƒŽÀqWóf‹gÕ+Ü¿d1”4Éñ ü(‹½¢mðQûÈh_hÂ{ ŸÔ}| dÈ0ŒÜmÙ·U® >áN?€Ïk9ÉÁC‡û™ MÛÉBn%rÀ‹¡}¬*T锑p\ºqËÒ–6.„9pìI¦ÜÞ¬˜1Âʸhʸ0HµEÂ…,Ï‹Avz)qÝhüéýò}g”UæB,d^ÈYM¯ã™º²(oü Ò ¨e¢Aæf¤vøÕ÷ÑÌ÷C»p<È4ÒL*©=ÉwP¸ˆÆ£ ½}²í”‘¿Ýƒ“)#£”‰ÈŽéÆ ÙI ÓR8îÕ¾ÚâþíúrdYE‘{µ[r!÷3–%—]ÈG»‘˜¸¼úýåË&œ³lŒ%ß1ÁŽN²gÌ"U'G =ê²É+¶€<,àv‚ý&‡}×ô_‚~W:öÙø.À@QÖL(£–™pû}QȾßí+s[ƒéÔˆ8!ñæÌß²Sj|÷5w‡²—¸³tX@Ú”SÀ³“Öe׌8fQ Jåwä+„ÐRݨÆCUfØI!Ày6b¥®ÄåJ@Ÿã© ù…ZÀ’s¦8ò_ãó¼-*â½Ù—Õö÷€,å{0‘¥â"›ŒÀßÌŠ ”h†z¯’5NJxò¦ ÚcשúIåÈQ4Ô#éÓêž„L`yôA•ÛyEbÔ½Õšž«IôZjv®¿f!Æé¹BDøÚóBd2bIŠ?"•Ú ðëëgôxƒ¬FêwŸp½lvª«Ç«û*ØÂPéÁTg’±ªðèv¦p/¹]v˜rhý˜.§/°’éql^Qýmð‹’4Ñü££SbC«’XDüÈ×/zàzÁ?1KBÚfÈñ•ä¨GNšÑK¾¡-ãs,…&…¡dÝwÝT*ø¦œÅj ÑU ªèñH°0±=¤v'€?ÙØelŒÑF,;Ô¤{Ihw(‡û“è\A½ËÂÐJ$Ãê±$J}dG/ÐPÄ,š4¹  ú·”æÔ’s@¼ /𶨈w«KWõƒ) a8o­ZƒY·ŸÞd=Ô"(db±Üeµ¤| ¤Ñò‘0øª(%ä¹v+cÉ)ÊÍZ9_g(T[dác}¹¶gO 35 £6 Pùu ab_Ã¥+/oÉ#‰ q""Ï A§,´ÁuþhE0oßÇ ž ciƒ#ì Œ€½&®¬á@ì‚õšªtYáö¬ß1“³Æ hvªª”žHÑ{i·k„úõQ‡#;7 ¥l¡'ª¥nŠ å®?BYrs 9Z]P2낲lfȳÒCÏÆ§6LjÑåP6>ŒZëc¶Àê´5™šÈñ¡Ô¾z´=§—úò8D¢ÿ~±%9uåÏ/¯oß¾^jM¢pzò>S#•÷àŽ±û5žx¾$Åó'b®®×_&† {Ù•ªó0,ªœúþo„ÿzuýeÂëòãøTŽzÜ™¦Û’»Ø^‰Äûÿé®âÿÖ]ÍâTóóD„O]ޤo¾ù]­ endstream endobj 559 0 obj <> stream xÚ…RÍnœ0¾÷)æUí`Œ±QnU©½EáÖD+Ê’. ¬‰ÍEêÃwlC`µ+E 16ßߨ¯À Á‡LñM îák 7wŒc´ÊgüOXB‹Êý¯ˆÓ”ª˜0–ŠèO7ÄOåOø^Â+P^(˜@Tež sè!çTÉeÙÁÜ_1XA³I?tÂJÒ¤X… FQãá4 ?›¦¹Pf ýÙ*͘¤J|¤½AÍâÓ‹bÂeýsÜ|5–ÂTGÛU£6a=Å<‰´AfU‡d7wœ&6‹.d±IÒÛ<¼õ`[»ô¢mIHa ˆ4 ”¿ºÝÇD„+Ûáéî\´ üè·\¬øìÊÇøöj– ËÜë~klmÚalõqÆgÛ‚Ù^úSHÒÈèÓØ—~ϲãüp#çða¯™$ Íó™à€6XT]Šq1í›^›·÷¿:&©Šêjlö3P»/_ gw…ë)Nåû]јdœG?FŸ ›uÓÀ©ÌRuÖ "fI…eHųH£‹ {¦±údêÆ~ ëéÐÖÎé0SL ;¶Í£“õ¡Qç·Cº¦øÒ)n®ÁéÙlÏ-M•KJòLù¸*[ ÷Ÿþ„. endstream endobj 562 0 obj <> stream xÚÍVÝoã6 ß_áGg¨UëÖ…½ [\o×·u8¸ŽÓxKìœì®ëpüHQŠÆm²> `J¢HŠ?2úñ(…´€UÛèÇ›èòªˆ¸bRåÑÍ Žž2ôò÷X2¹H8*¾¶ÝݦÞ.©³¸ï6CÓµ´²u¹lÚûËGÛ ðõ›p´u¿øãæ—èçÒÃeÄ93Yæ©”å&(bÜ©ÊâûÍ.Üú1iŠè1Ê +”» L´rÉ –›èsôiFÁÈä•ìlÓ.$‡#ñF2ÍGñF3­N‰™¼xð ½ý}Ð5‘weßTs¾küwoZ ^Æ-¯:»-ÉÔË+aPRƒŠ¯Yd,+œæÏOm·ë›gΞÞášñ"J ÅèFÓ‹$#gAåÃ0ìÖ/»;:üþú‚ˆªk{¡Z—ÖŸ®Úr[ß.~˜³Ñ+äË¤ÓøSÝW¶Ù¹§¿šÚ—1£¦ì7kpƒÉß9x˜+È#ä?xÚ§Èÿýœ2n˜–þâUÖÖíBä°¡BДÎ'AÃU·¢oÙÒÍ_¯i½£AŸq?®á6H[“4„›‚k\2Ì#Ì›Ý":®«æ6åª^šÇw Ø{B:ó6Â&rq¹‡Cmç¼ÂÁ‰šû×]ÏÊv¢Ì€EÛµ ™òZ“™`bìRât—Âé¤Mùõ‰>5уõ¸G¥LЉp-;;)|Â%æÛ”Söz—ZÙÎw~‚¤fÛSPù¿Û“09SÇý -|íIJýj{J—ϘÁ”ð¬ÈÖ“ðYL+ Júø¸åãâhØHb#E SÌ´ܽCø~"õXŒTOªÀIhRP;ømýB‚\ãÅ P—:ÀwGPçV…vJµêbžÇÖ•Gò$‡``ÚÕ¢>û §GÈ0R9é}í7—“È“ªqœõBʱ›bÝÐñR”S™çÅi)ãâ8ýÑ›ß?T€áÔOŸ£ "à1u0>•Ì™ñQž1ÅÃl:ÆÓúÔ?ê¡Éú ΣtcX*NJŸpé·Ïñ.yÏÅGÒø|Tìãã>çÞÝünô‰ù=ççÖ¤NÀ?Ø;ñCÐs8¾›|?¾ÃÙd|7M»°[ú%M»° wð Û~Øj?ÃC"+ùú õ4ŽbD“W¡“ËàüÆ(¥¸;ÌŽS¼«Ü ä Á‘v_ýelË -ü‹VͰ>È<QþD{¨Þƒä,ð)© ß9ð„b¡OrE%\dõÓwÿ.‹‚î endstream endobj 565 0 obj <> stream xÚíY[oÛ6~߯Ð#=Äœx¥{XÑdèPd)’>5…¡(J­@W’›èßáE2ÓŽ›íaEŠ ižóñ\©£às@‚þH )ü‡AV¯.‚ßNd@Bœ„Ipqçj×ÐIQæ³9‹ºiÚ*íg/þzîÐ{b,˜Þs±T[(C—!á¥gmžöùµY\ͨD÷jNQ?P·Íº/êÜJ .$ÂÆ€L±ÿT®wmÑç‹®)=x¤ÄÉ@[t†wj†U™µ™öù×ÞEy¤Ý-‹L[pYS«UÛºpoš²lÔû¢þ¤aÌ)g †…0Âk£³¢©_h‚ã £íéÙ$&q0Ro«fsHj½%t®]&Яysu»ø’–ÛZMô|4tíbÕ•³¼^§¥ZnmĆbvq®¦œ«)çÊÃ9›Bʦ2$~$˹žr®§œë™[l\øn™·ù‹ÁÃÑ1’U¾p`˜×ý³NÃ8ÒÞ´®f4†˜Ã„sƒ@Ã4ª«}0Cuä§ÂÌšr]éêKÔõí:ë×-øà^˜r3| tëÞÛXÙ Ð`âA¨Ú¼¶œ#áUÚA`ëg5Ö*&M̲Øu²KäƒÊ1åÁŸoÏïO_Ÿx` ±QéïF,9òñ£ÀP8 OŽÿ8÷ðƒ¤ÇÅ”ÝÉÏøætÇfdÊ‘Y˶>ÎLâˆ8œOÿ>”3E|—ተL\½þ~Ë«hþi÷Öî&âÝÂõ@ K¶Ëö $%!ÐmžõÅ•/s#ÒŽ@i¹Îýò OÇíl+|5AUW €#_šp }ŠQGõB¥DÄÇT’HK÷r6'Q„^¨Aša\½4ƒ¯à0†c:"Õ ÚJè›Ñ9Ü$&8Löœt7wÞ/7Å î?öò†8âßT¯Î÷…ý£áä²:}{+zPdž¾?€; Õɬø£ÑèrT·yØT6yþYþï`ˆ]žAl*BØÄ» ä >Õ¾.Ï@ûCàO(ß—‘ð´áÆÀŽ8QYIwpx$11Ý6†æp*B…ê,Û>˜%qpˆD[‹GZCUA“㺠΃w#Õ(¯ž1‚ú- ”1âHH$–üQ #Õ(¡X©†¦è›tÔL­è¼-šv¾‚ßj8@à¼äz4˜CÔ«>Ž!œt'~mQE¬ñœß×ͪx¬õ)àT4¶-SÛÒTM^%¾_À±.íR¿÷ÁÃ_ÏŽlS¯©;»![¦­}zS§U¾I~ro§ïuÞe-ȇõ¶Ã}Ýjp)œfõxŽÍê¡Vhƒu†½m3”­Û67Mhe·DG-´- íJ·è”AáÚi©ƒ…n‹³Ô®ßžÙ Ò2¯ŽLG{ÓûÖ圆£I97 ’­ÒT |Ç—³!%ù;á ž)ôÎpïÄ …‰úAêî}"‡–=ÌÆ–=' vÓåæwexÃC§µgi™“î¬×ÍL éúvhÝ?¬à“c ×îä9Õûî˜ð`8 LŽþn Gk“CÑ¥‰«MJ&Qmùٛͷ{¯Í•®b¸˜¯(ÌùŠâ¦Ø}_Q¤ŽÍ3vú6®W_UiQ—ÂöG•Û‹n¼è§uZÞC˜æã‰A ‘yÄM ˆ£ôÝ/ÿ¾È|d endstream endobj 568 0 obj <> stream xÚÍWIsÛ6¾÷WðHuL”X¸¥·Në™ö’¦Ñ-öxhв˜rQ*Š;ùñ}À)P¢%9¹dì>€ß[ð–÷É£^ÔKü‡^Ñx¿-½_n†$ 3o¹†×^ÄÞrõÁÿ§ìw²U‹ûå_ŒF$MIÄ ôÏõ"àqæ·>K);©@NB¶XâÅNÊru£÷2¿ß””Ý®¯Ú‘Ò:4oþ+eGAqÿ-Àå¾RVg^y+«vŽz«Ÿ·N((6¥RùSi gà$ŠÌòv0Î0`Ñvm€¡h­?–˜3Ê=JI¦5MÒ’˜Ä™±Â \”²Èª·ƒÖ'ð,õö^”‘T‘ys’&òöÞ{ïf@Ö‰,óÕ‰å,$œ,g‚ðè’åÈZ®¶½NgäŇñd$È.§~_ʪ“Áö¨ßÙ= ¾êj(G×"|-»¥¾übmÞ…TÔ¥í'·í‹H”˜8Þ?·ÝVUjšuW‡&„¦P?’ÄÆÞ‚Ÿóþ €ÓÜ™ÕVvøîç¿oP(ºVY|±É¥}»nó¦¼[ü:äàqìúßKUHð¡}vH„/uß²,ûu&§‚ö`1t”ƻǘ±Ÿ@S Õ0…ÆíŒu‚Eg÷4 qê¤áX'-åøÀriÉ–ËÈûM§¬¨3d]Y—J»Iý²¨´J¹²&l¾ø€Gųž+f‡l›K0ñÎ¥# eöŒ¦43yàŒ°ÄbìA»‰áëò×eƒM'ÄþDzè‰4dDDn©n)%*Œ¡ Ñòº“MÞ£yUÚÍ•ÓèkˆÑÄ™Ò3ÎIÂÚïeÕ—/_èˆKæš•3¡Sçtë+èü­ _íŠ8s’áÐî1Yj¢¼APçpöÕ4ÊâÄÑÈ£ñeÕˆ‘Híú“:~L’O¹T,s¬g ÙEëÊZ?¦Sôö-|jzúZ6µq¼žMy(H²éØŠ?òò0¹@§"¹v¤2Щ)´Žm¦¾¹À DªßœeZÆnAßTÔr»ÄBÂÆH+áȳz{¤;¸ªp¨{W©ìÀ0¯ÙáYqžg© ¤óDËR‹‘s!Ô`ˆÄåÆÂܽÀç£IÊ@x•Ðñå…Žð_\í«~sD´çX’ƺm®úBÆéPgIRDBéÇ$Éãq9ö[™|§ã·èê™aN¹@. …½éæôz‡­@6éõ#6^YLã€íÛ:¯ZídŒQêd™ì7•i› „cF ÔÔQ¸ë®®;ýr_µO8BLðÉü´˜3Î7IQÄ”Dø“¨A^C~ ]‹ªÏ-ýu>çõ)DoVÍz8ù°Úåµ^ž "ÆÇK¦š©©fÆT1uZ|‡Skªšjïg }Jî{èôòÍÐAáÑoÎÖÌu±a¿pB|㜙&Ø5 `AË6Ò½zéÞ]°Øß+¤Ã;?ß}©ê*—Ïøúó"~.«.ˆêð¥šDPË¿c˜³¨ð@L¯³€oEƒ! JÕË]¤}ôr˜CÓNHXêÄ"5‘¤É}÷Óÿ›f&« endstream endobj 571 0 obj <> stream xÚåXKoÜ6¾÷Wè¨-¼¬ø¥½‰ mì4ÛSŠ–¶å®¤¤µ›¢?¾3$¥¥l®¸=l€ g†ß<—ÑLjF üÑH1øO¢²Ž~\EßSÑ„äI­.áûi´Z¿‹û¡ïW?‘ðhXJ¤J$©úÅ’s×'"îÛÍn¨ÚWÜpØõv~;^34QDRÇí§_Î.~ýòÕq@ª”„fŽîˑڡíBŒ¹ 2óøžž­\'ÇŒ«<_¼1\²TPF$7'Ú7·Åæ_>ÈÂK)ã]Õí‚¥±¶ Þ.`·ØìtX¾åé‰ï.¶]U¿«Þ‡à¢{#ì %i:*8Ÿ•ïqaJÚ.4%¹rt/Kš¦ñ÷8(;L«v¨’8'›45ÝCLÄxOÀÙlN(90/ƒzQJRúÈýËñúËáÚâßµhŒ»Öç”ÐtÿzWl¾øñž_~B S_>7ૃà³µôÀ/­ïßü[ðoç3Bå~"ÙÛ9 >÷|_<Ã÷C÷ƒLJïÃ_BÞ®›C®è‹9úÆõ¿ôG×Ïpýس0öÄP¿Z¹ªÌÁŽ$$]UæŠdÔœãânE™Œ¯6ÛñØÇˆð<‹î"™[kÁ pƒ:J!ÂÕ´ÞDo£7•“Ž×,8‡rP€zrE”xR‚Gå$ÔÕP2þÛw]5h;ýõäÌN¼†V•'ÝŠsBÄ—mWOýÊÌ`&‰TFîÛOM»íÁÖ3Ägm‰Ân<´·ºVÍUÛB޹§.@ýs·4%>~{vd'eÛôî@y]tîëeSÔzß_Ì´œDŽAöR÷eWmÍå:•$ŸÅäʸ,„K×`…r ³±)šÝ# @e—¥5†ÁÐPi\X)pa–Å/‰Ë?›¿KÖR:è+Ý٠ߌ ƒÇŒŽ—3¶ŠÈ®1³,¾»®JdzíxZ{-)´‚"GGÂDcÕ-&ŠX—ÕyB…^/–"IACØû„siã7·FíõS _°u¤ª3äY0ˆ§æîÈño-ûƒþs°3Th£‘Š ¸PÛ;=Ðì SÎLÅ¡Ÿ)JÔ¶ «ÀPW!]™„é˜ÄŒ{…:öŒ¤ÂS˜qHÎAaÉà I¢||mhÙõÀïNûyjú;í@î4n¦˜¥ÖGü”*¹ïÞ?ÃQ“ü^¯=Ú·Y[X\U³q*€Â.§WýÔÚM±ùI„‚“¥9¦6ïÚ¿éa×5ýçDæ z{šÇ"fÔ]×v&š’¸5ž[–»®Ókô{•;„€pDÈPvN ùò—îZ‚¿"x| äÝ]Õ»3áÓ™Ýù¢ñT±ÓZ÷}q¥Ç³w˜\ hÖ£uG5`Ñ´ÍÒªòXíâ"'b_»²§kž`^írë'j—'§ÓÅúaÙJgó\.ŸdîQ‰pÙ2«Z—][Û™M 8³‰!X®¬Àg”+…YÊ*ø¿¬V’=Q­„ð’ÀxP`ûb…d½eníϰrö€à)ì†3 ÌœYÌÜ¥kœÚt'*Ǻ·IΫ9¸;%:IM$Ú`8“M[Èîµ>P~$Û¿tÊèœy¿°ld·÷^b\-õžRóä`cu™fè*žEŽ™yK™'é ›6±Ã²ï> stream xÚ­V]oÛ6}߯à£F"øcDsøH¾&?-É«3&c4UŠ,ïa=dMc²¼û*hºã*øTm×Ë_ÉÛ%ùL¨H²#*¥‰´tLÖ$4Ñã´"—äƒÇÁd48Ùµe_@§’¦é¦4âß‚žŒèu¹Y„B«àoü +;|÷˺¦ÚöeSã¬o†oñ¥ÇÑUÄd…ü^ibÀ£Ôx w\Q¥­»Ë§ºÙte7º{˜¦,!¡R4Â-e n†÷ÆÒ»ÒWvºi›[\üþâySwÆ|•µÃê}­‹«ÅkÉÁ#K¨Ö㛢ËÛrcŒöÒ%¨h*]óå Æ ÚÂT˜Jišp¨c?;‡ÇŽ)ä7š2ß!|~xoÛ¶¨\=®ØL™•)Sff2e¾Ù0µ 3öCÂ쯻UÓ C#•Ý€ÅÁ“ ÈK³¥¸³lC¦ ÆL5U4o ™'¨ãÆÐB›¬À¾h}IbÊÆ€ØäxÁËÁ†.B)%ÄÚP3èãÌ8ÏLm Ü\É= êe ¸µ¾ö$êP„wP©ÅéX‘c¹fk_ Ê™›u·Ol·ëÈÚ -Z4÷£,xì:T³« Û~)«2kŸpùq¡dµev[Ýt£Ì†ÈÀ¡é½H¢IXþ=ͤ~-.e×·ÛšêàYšó¾ º-*Ç&….S>1u^FœaÛ =`·9pøhHÊG•ÿù·‹›?Þ¿y{æ!/‚}¸~@gìīبÀ³·?^zð@G¤šãñ£x.Á÷çGc±9¢<²æ½…¦1sÏ/–>¢‚j>‡UÇ2ÊÍãfÔ‡CXá/?àkžU*x(ò¾|4ýP`Ö¡¬TUÛÂï1÷¨#¥¯å¥šžD'¾.Šiü|Ѧ:¢Âu0 \ß©ì^ÃC=ŽƒSóѳOŒkÚ«'B¸Lm|úu˜}—z¸Àu‰gŽ$ÌÓ—ÃñÒâÅr¤Óˆ&Ê 8jìà øƒgB™r®ÿ—€û”QDSn_pþ‚€ûޤ¦Gè>à(¬tvKÏÄž¥FÖb‰Wt’ަ¾ûE±„Ä endstream endobj 577 0 obj <> stream xÚ¥ÛnÛÈõ½_!ô‰ÚZÎ}Ø¢`‹Ý&»qŸâ  ¥‘Í-E*$ÇA?¾çÌ9ËEË ŠgæÌ¹_Ç«O+¹ŠáŸ\¥ þÇ«íaõ÷ëÕ«×ÙJ¡M²ºÞÃñFÆ"‡ïÝûH ³ÞH©Lôv­ã¨éúMsìËCQ­7:5QQÕcWv¸²QÛœú²vÝúÃõ?W?]n©WRŠÜZFnb‘ä¹½îªc¸õi%tž­V6™ñL¾:¬-²4,«Õ»Õo F &rlËz­eÔŸ¡ÏµHåˆ>OEj^B?1ú¶¨ï‹ÿ_ú)zu®îʾü\ö¨ÁÇE½¹#|Ȩi‰ËW¯ÓÚ Î‘æ†‰*+l找{¬›#Þ&`9…–Vä,3aµ.k`Ä>§âD€+l2#Ôp,¤åÕTSü#L6è÷\·Y.L6àÍ•Èå xG˜l¢Ø›E®¥½•½´à¼/áŸÆ›[TŒ‰~x{ETU¹š·¶MÝõOOË®ÿáé}UÜuWž×þ€–Ô݈ hL´½/Zºñþ.îfý×%£K —§vü‡ë¶m Á×Ô o.™ýúÞOÙ<å’¯€-Ìzþèmù‘]úœF˜088¬J#×î›ö€^œÄSG‡£G¢>qtX5{ÝžÚÖÕÖóÁTàô¶èÊ-íwMu$ÞÈT 9ÓkQ\EmÙcâw¢«\Oˆã¶2•ù(ó¦þ÷~­’èt(êMëŠ]q[ùë2BÙ †íFÉK÷¥§›XšÊ3è8Žî›Îš– ʧlmQpð‚bÛ»ÖKOeêz0Ãë?Ÿè_[y¿Y0ÊDž3ŒXoŒ1Ñ øM_”•=im¢ÝÄ‹`C“Ià×s‡¤¦”Ô„ÀÏiÛŸZG€Þ–ð{W~F½9GE·^·®jP¸q³&“#b{î—pÿ 8¸ ¹¤©bqÉßSaS†èØ·%Ãgc`»„Á]?•vrØ¿¯¶àhV Æ· ö!+ÉìŒ}eâ¨hÛ‚üüœ}v°}@¶Ä‚µí9þ•Áb°+k \øX9Ö â[Ž<†Ú;,GÇÌù°€c‹w½Ã&›*€BŒ|u;ôi‚|3ò1’Ož§±É¤HõÌ{ï›SµCdv$„‹cÑuÎ$>òð·j<¶mþØ-hRšËÍeU¡ƒ¼—®–Ðäbž XÈ{…ÙÝè£H&)ý «% FŠÄ|ŸKá-b}Ùç5æx‚ø¼$£Þ3¡ŠÍäOöms •KÚ_à‚ϪH,tHñ‡edÐRëöè…l 2ˆ—|êÁ/1A¦šS'éè^ôºÌ7žx¾Í„ºÄ§*¸Í_Ї5 Ž„—×`›ü›ñ-1$G?]´],¬™+åÃD®8N¯¨;|¸w­[¦á`.ñ©±GŒ‡Ú¸€CÉ1s>Çi¤h³Ôºî(®¨]ÅäI掗"s¡ozŸ32³dT<°”²2;MY™á”•ÙIÊÊ,•èÌrí̬ïÚ*w`LØÀÙè·í1}¥ß¤zgqä|[´Ïú†³Ú|VËzV>uÔùºGàâÞ̰YtÔ#K%•Ï'x̤¾øó±&uz?#+qF…~ ´€ª÷u?NÉÑâ|Rkö‹ç" î–”y´œ‹2!C¶ú¢L£ÝC²J€‡û’:Zn lð‹df.ÕP©aô 5½=H_7¬ŽSG²çÐu «¨§mÁ< õ‡¡ïX‹c4r0•Ù©oüëß¿ü²Ô”ùÁ†˜¼Y_±Cø<8õ›Ð¦{ã3#Cw­§½,®à€Ý¤ªfLGîÂøÍèù‹½ÞMþ£)áhòñˆ<ý¿z7У…©hI+VÈ©åP×¹ö3JAͪ¥”ØÇÓž£­ Úž%nÔöíþ£gmIÕàµ&T=ˆQ@ÕCCÖÀ‚¥S®ðñD¸µkH½-}ÂOÐ#Ä"8žzÆQ2É„dôdÒ07Äéă+î™Ø«Mb(¦Ç¬Õ G&KXÏø…ÓŽ?J£_ÞÒÆê_K’n]×axzøŽ~½Ô¹÷Šž;¼3f¨‘–à@)L‰ûÒ, ´’¨+ÇÊ}áESÑ”é)Ùï2w@t®˜$›uÎ$*x¸O*sûú Q= gR¹â$KÎ$–^oˆÂ${üî OÕÝ·¼ÜüŒîfcöøhB9þ{ÄMG‹î´EsìOzZ’„«ò’¾T¬„þždd„N‡–¤ñÔ)iúáâ nÊÎy>ØÉmLO¢`F=h”Hôü!‡ôìÚ¶á¦é"wóÜnFÒ¸[7õfÌÙsÄSþ8VÏLó{«â.6Ü—}å[¬ó#ús<^…ñ…7ɉcsþ†§c ÇÕì9  })gB>€bpƒÐþíÉoQ‰Hèèúêp2„®øúžš™t› Ðäi²ÅæžÚÚz^Oš'ýÉ ¯om¹‘À¼àû±OLÜóïæmò»ÓmýÅV77?-áýõí;>÷¯k~Ѿï&oT7:Yà>›uO™™ÙÿLþz(qX° ‡"4µ¸jC¯,7]ʆ¦‹¾Ÿ<î0Dɧ¨úb+¬”ÿsÃKïIy6MiÄ÷”HŠb0Åô‡3çÁÊÿéÆn ×¢¬ñ)ÒKwçj×B£A‚ÕØåMܨ¬é¹”2TbY‰¾Â&v ‡I"ͧs‚JÐ}8Ýy_Ä+#Éé­ë‹þ÷ô;ºq†nLl'vb¡Äè™yŠ*¢V¡"jÌ´£ÿ`˜ìy—~x'À,ß(ûp|úRVe]$.?¯!b‹¶ÄÇgÔ||šàuŸNþÙDñL§¸t"LËsŸ_ 9‹ö™ G„¢ÍÛòL­2|ôD°·‹#¢r÷T µJ±¹+Rl2°"ÄKh œåòåI"”Y@bžÅág«4”Šd62%œ[Èh:‰Æß4 Ëž$HïY¸ÞŽ9lh‚ ±BÌ\ãCèÚñß…l.rõÔ0Â=b†¹¢®‚Rã|dšÓg†³?¶œÍˆ½Eš¼Ù¨—´Þa2Òp\o‚§ƒÀÏÂÃþt°œÌX> stream xÚ¥WßoÛF ~ß_¡Gƒ¸#ï÷€=8[Zxsܬv ëœÔ ¼Ævg8-úßOòYR›nsÈæñx?~¼;X(þÃÂÿ«ânSmÆ…¢tH•µú]Ê@íÕø”•Sò9_?¼@SˆÎ‹{ €ÖðïbñîÑËéÕog¥%32`¨úfG¥<æ³ùd1y3Y܈a<Oo擹üz}qõêõâìÏů…%D¼xñjù°:ã%¼a=Z¦á’"‰Ï~wû¸ÚüxV’Šqt5ÏjWÅØTíÕí_«»ÃúãŠÝP™8z3ž^_Èâ?Ƀ¢B申bx;ºœÌÖ›§ÍÛ³: À´2ÖAg;HðwŸäËv¹a¼äªŒ2 =0M’θ‚°>|®G‚¥ÓÀüqy÷>%:Ý}Zí%ÜíîiûNÂŽCaœ…ÆÎI ýw»Õ}•§UÍŽ>.ŸVòuyçt½YÖÛa–Áœ´Ëåþa½]>&`×> ³ \“Æ~¹åzuP‰± Áóö«å{ ña·Þhûõ’k(8 óL&ÇQÖI­Ì>Iaís`è9SÍÑšÙ5ÕàIƒ=Ž‚ZÔVyx¦ 3çóZ+¦•{*t4Ô‡ÔÐYN¶÷µÕxP>)F Fd{k”ªúȀݴÔMm²\Jß”Z!ϳ€Þìï‡Qä¨Ccºî™.Zï1óž&¡ífr1ý¥—ÒlžZ8¯,;DNÆŸ¤w‚îè-Š1ZP.8#Óïr–³âÝì ç“™N ƒ®Síj§R{ ’bi+m|±ÈüŒã‚Š,{Õ þ|ÊÂh æû–^ô•5“9š÷ž¦ºN}U¹¥•˜EðÍÞe-„¨ÐIm™*ݧJ+Þ££–*“¨bО&°.îªâf–’#p1úÐh%òXv(šnµtÀª‰2‘¡/ñÛiÌ.}A3ro±ÅÛør•&‡yé²5„`œï÷)0yØfÁCyË”,šÎÄèÁc¿3óP}©Ð>B „ºhÖæ¦5Þ$‘êzûõ1´Ú†@Îú„@+&tÏèÏüOýéêN¡õWõwÜ»úhUkŒ4¼ýÐ Ê,#ƒ|Œ»ˆ}ò$NêpîQb’m_}Gò¤y]"ïå·¨¹tNQ쫯ºDDߦ>bcÈw›Ž ††FnBíŒÖmØèOˆÏié/™Ï†Om®­ò‚¯D.Êãs'ZgéTô}Ýy¡n<íënšŽ¾–ü‹£!óNGƒáE}0d—Óv*Y>:ZÉñ¾¤Y§›õ@§Ê¬ÁƒTBñ*|•&$Ñ8Ÿ$¼ Œu.ö4–BT¢æ“a¢êhö„'ئ86ç¤ç©ZYé*¡à±ßÉÀD’ÊöfÒ³\gU²8Y7¿s§ó®¼¾p4|püòã:|],ŠßåÆÕÒ*Vï4D¬å÷"D¸Ø:÷ çý endstream endobj 583 0 obj <> stream xÚ–ÛnÛF†ïû¼¤Pp»;;³‡½µP+Ën¤š^ÈŽl¨µ$Wôí;Ë!iŠ"]'²’ËåÌ?ß°Ù?™É4ÿ™Ìÿëìv›=¯¡ Yá ¤Õô\È‹rW½§H›ª=Ë쇟 fAEç²å0„üœ-?ý‘ÿ2»þmT`Ž !ÝQ^Èe1™/¦Ëéûéòƒ,ŒçãÙ‡Åt!Oo'×Wo—£?—¿f^°ódñzu¿± 9”o‹êuFE=‡ýÍÃzûã¨c~=ÏË­šµéZÚÕÍ_ëÛãæóš·1?ž½›ˆóŸäÑ)0ÎiG²ð1¿œÎ7Û§íÇQiР2•gSï•ì|³xÚîä~·Ú&Éšt¾8ÊwÆ+&%“ŠÍñßò£dJ× …Ýí~}WÆLùlÿe}³7û§Ý'1g"3dnÀZ’S­Qþyõð´–ÛÕQ®³ÍvsÜìî2hPhÚü.W‡ûÍnõP%ãÝãc0ÒÊÙJÀaµãÔuTÉ¢ÄvsX¯þûÍîXK;lVœNÑŒ°­£(ZÑúUÅÖ\{^ýßRÉ蛾ì.•âÁ*:‘nDõÅtnÊ žiÕiœÏÊ%ôJûjIuá)mµÖg«Ò4Na½R@PГx!eën*¸s¬ãÆÇB p#kŠ(°.ê&zåO²¯€êï¸O´VZ×R ÷c…µ*ò" òu1|?ÝÝU^­Ft$Óõj#•5÷ÜØÐƒ3`‹Êžc¹w«V‚:¼ Xàj‡ôÝ4Œ‡&ntˆ Qn†ºEeè„Z;+ÖX…V;×ã>g+÷V3rT¹¿œW؇ÛSÉ6Øì06Œš“ Þô`3>ɯØI6([có\?ÎXƒçº ÅÐ`‹†éíOuA#£|hS;S…e¤üù¼aÕCÃJ«à(=W©¢sZRdØÐÂhþà½í£ÏÍ ´8Pg{ŠÌèc‹¡GúzZ¾K ¸È qt}´Ð¥¬h1U§îö9-jhÑ·Í0V1Ø’­X8àôäm<›%ÊXBlpYœøgév˜6HŽ¿ã$冇å#÷Òƒ˜‚Ä®Ûö“ntBŒO—Ãõ1rnRœ×WÒûŠ!fY78ïûê+„@5°U`°±:…Í^®¯öœ*ãïf8iE|Ïðv­á¥=Ï›áá%æ×b:›¾¹šã®S佃böucßpSƒ×Ñöã1_Ïp Ö§‚èÌ’¯bv2Ö¨jñzww¡s¾A攓ç62ÔQ‘m#›ðñ«„¶¿“­‡õãþ GÏÉ2û]Îí˜%:¦s;cEÄg ¥…ÍæïþÊ´»ð endstream endobj 586 0 obj <> stream xÚ•YK“ã4¾ó+rtЉ±^~À‰¥X ŠGÁ'ÂÁ“(³Ž=ØÎÎŧ[-Ù’ã ÙÚ­Š,µZÝ_?¥Yý½b«þ±UÆá²ÚVoîW_¼-V,‰‹¤XÝ`yƒéê~ÿGôntWíÖ¡²¨jmw*‡ªmÖÞÿûXæmd*.$lÎc%ÌæŸÛØÒIŒ‹8•p RT=pÎy45 ºvÍÓè?XÔvø+¢][ŸO ´Ý¾jÊšš5Ï¢óiÍóèa½±îˆªjˆ`äûÔµµ>Ñl ÄJEéÝèàÑotlOç–¾Ê_ï‰á¡k-7ft܈"V9h/b¥ŒnCë@J|DÌ «ýiÃ…–H¢²ÙÓ€`èí¬‘×d„%+#ŒüðâšHy3amdJQ¥@¦ç#œ²ÄKä1“¯¨ê3§*¶À‚³Üêº40bN@ÁJÔéþ)¶c²:ÚÁ¸Ê2L´Ð,ƒ)ÀŒ5yQĬðÍiÍ |3r4áMHÏÑ„u´Ô:Ú-ó[ ®¯¸Ššò¤t—EÌ…;ŒÙ£™ˆú—ª@êµµ‰ZƉ••}_=6Æ;€œÁÌÚýcìAHH‘Fß‚eá¢CeO³M{í4Ë`? Ê£m¤®Éæ›T¡•=|w­1ÑPV„-ê²yßßÜ76E¼‚œX0;ž¦¤°ãifµB‚ ;œGì‚ýä:o5Nä oËãòŒ;‚(gq®‚ŒBP‚c9(­C†È‰OBîݰc*N ßÏ&?ÊáÜ“»Sôx‹“— ÿw~Èø#§íÓP(L7Pb}ùrIö ‰å ÿæÝÿÿ/±mÚfSî†ê §É½¶~è4ôúæ¶NþíúÎBYö&F-¾ºM²Ÿ\’,JH&³àÐŸËºðØœ“’áܱÄUóHßÕЃÚnS®uÕãÑlÝMÖ¹¾ÚkÚàã 35ÓYAp#ZVo$°Ö£*ÇgUåʬ\ˆ ‘ Ѫm%‡„K©–›èÊ£öì2é$ÉW·õ¿/c*¹‡)ö LÕ¦J²›}SœŸžŒ¨Pø&@³ P˜³€Â(Øn]&5€Ê\€ªt¨HoÔÊxf€¦üt4oŒy܌ئˆí,’2Š$qIÜÁ¥°ÚÊîÒçm¡õvYpá ž&¡àª€vHã(eN4Ì$âI°4ñȶѹñª ­÷Û5Q _ÛèžR3lÚ•½&’“.;9Ë&)íÁ”K{ä,Â÷—mδ.°?Sž”Ñ^?bg^:‰n1÷׈F5¼,wEtäÉÔ9o¡¥AAâÐX£Ë×gMt¦L<4ÏçU]•Ý‹OÞU%tE4ãy†eÑÑøÐy7œ;êîÍVéoM`+ÁnUÆ&¢à>l³v,(.rõÆÂX—»÷ hAÄòìZm Ђ#}´PœWËe'âç{ _ÿåÐ Q<™yø‹z ]«Ë––jYvé_‹¼€ÇºG 3Dlº«´_/gúÈ ÒoC‹ÂŒ¯Ñv½¬‰èéôSÙ=š+ß‚:yœæAKÇ]Óí¬ÞŸwÔ°aŠê¡TE8[RL˜2ã—¢ùxŸ¡WòtæÐH‚¿¾ú[Éeœ¿n763œÿ*¶áøtÁƒ¡›¾²EÕ¼•¥^z#¢Ê)7¯I2šÆkÅŒBýr ÷½VB¯9žd;ZœœNÃ/“¶dØÝãü„¡%¤ iôd_AðIÏdI˜k›ú…Fc> wÏ"w”žÐ&Aþ?⪤W¨¥cÖ°·7Z§aø¨"Ç“¥;~Ó,]@9ð:Cjé]yÆn סDø}¸ÙÈ€“j:ñ’5}Øþ{䣌{ÊPGÔ&ñ™‚Å^»/Œùv» 1‹ôQ›&I„=Sx ¥õÖ&²y=õú¡Ë›Ï{/áº4o=Ð 5Ú±-»Á>º˜òÆ#^@–fn$<•¡ÑSfŒT™nÌ̓GšÞW¶-=—0ëæ)uGuÚ:t*]†"1Ö—–VjPÀJB')G W`M©¤íšØµ>Ò$Ò[V{½ë4×<Þ]Ú–’(D/q‡A¯Á·ìdm`ÄѸ©¥ßªqGзÑobZ„hªÌ‹\ĉÑ;`¡g’̺‘q›Ï1i⽿ÔË$ªÂóŒ­$µ7Î"lÐ{í:å€ s€(ØÈÆÜ ihž >ãäZÊ‚…™]&:ëÞî±@Hyâ.ZÅ‚§Zå¤Q®ÖåÞ¼0#ÌfÌ ÚWÆÇ¬r^0âš}Añƒà i}ð11©Dùà ÉÞú¡&.pdCÜŒq0Åì…üøEÈsŠ!ÁÙÎàlã…[fF‡žÖ:}²oðA÷Ð)ÈܾhKãM†¼kæ ïÎk £ï2=h ò©-í j˜Úèþ¢ø$£twö¯M1*­ú¹‚ ¡1]u´1H¾°ƒ#L¤‘ãu M}{²¬\šTóŽÅÛJ6b¾½§¿…½BŽºA÷ž áHýì?Ýþ6‘ endstream endobj 589 0 obj <> stream xÚ¥ZëܶÿÞ¿â¾E‹zŠ"õHÑMÑW)ŠÜ·\€êvµw²µÒEÛ—¿¾ó¢Di¥8…aÃËÇp8g~3òݯwÑ‚?Ñ]ªá¯º;]ᄌûös©0WùÝæØIîÎ?ÃKyøåáŸ@’{$Q C‚ººVCÕ<ŽFåÁÇ¢«Š§Ú­ñÙf:Œ2YÔ•Åé Óà¥ìÇ8˃jÆcP·Ÿ: ÊŽ[ù__G<ÀH®‚'ê·cs–å*2]?¼CiŒÌ–—¶+™¼hp×7á gÆOE_˜äãÁÚ@NÑŸ¤£ó€Z¢Ðfð‡Ö:õtå“0Õ©buôØÖÁeìx FŸ·hžIW8Ò^øULôMÛEIŒ“äž$¦¥Ay*Æ^ÖÐ!>UÜõxÆ®+é´Ï ãž›Ÿp¸ë3Jùçq´WÔX¦ƒ×®º5·«æR'<-¨íáÅQñ5T¼á;ÔdO~z©øðØE«ž[/…»Ï¦§5&à)¿¨ëòÌímŒ-Ø {zê6 Jü§ø€wHV¡DÆ)ZjY)'ù±J·[!·m¢(LìÍm£ÄîE¬µÅP4÷ž[ª¥ÿ$‹2¹#˜FKOgK_,ŽiqʋҩÎ#_—H~já–{Ù¦9÷"RË¿çòÔá…‘ÁAŸ NJÙàn Áx71™Ylx}ÇÞ{ä¾HÍ[‹€A߀á­ôH„Òã.U3Kã(=ÍóîÆ.8îKÒ"æ•…6¦CÝ7@j”°0`,MQ¿Ñ»À^WŠÎ»˜e=’—‚u$‚‰ÜzµÁ,_, …î¬ ñµ˜$•ÕJ|î~ª¨á6;3roÓHÉ:pòþVžÅÉù¦K£—[Çh@=çÉÚ΂ïæø S™H¦+„æÊze!»R‹Ž-“ž)>݆—±r ¾¸¬eŸÿÊ3ŒRÿ +Æî ÿ µQ àG­¶Ažr3Ѝ9Š|ŠMÀŽþ>ÙQŠv„Ú"ýęś'ϪùBu"/"›Ò‰ ZP¼/½«AÂËØÀHÛ0?~XÇJHY HW5+†“ptS ™‹¦ÿ~zç7HAJVÞ*þÊÕ`óuDZEq:;ÅoÐg¤)ß5nß¿]QXöñm-ϯ'ÌrߎšâJ&Ÿ³†ðwõVÙ"ÁÉÏᩦ8º|ŽÂKlG/Õ†l;ÚÙNìÛŽÞ±«Bë¼ø¿&)P;¿Bò4Œß|´î/âïMfëèOWç‹—j@>ì0±‚pÕ0¡¸\YÖvߎDܙ̌ )®<×opĈ3¬‰§ã#íöñ 4¿âé0ëSËo¸¨š~k ŠÂ(öur¼o.Ìu‚Ì\޽%uƹPýy‡‘óHH$l á±G?&9Îz.ý‡„Ê–¢'x·ÏÅõ]¯ ÷ô%ŹÜ¼Ü#€»ûŒÝ=r­xÑÉ[>(î¦A' ”¶ùéžé Oá:þ9·#ݱ¯Îä 2Ro?t…ÂÓeÏf&lbIPî8wt>FYFyn½÷ xÅ.ä1èªçzjÇ6Eà€ÒÉ 8šÂÑN| ¶&µ´¥lÍö $íëÀ°;}[ì±ç‡,\Sþ::BŒìô+€n8ÖA*^û8bpþ^ÃÓN&ŠØd!3.æW@ë.”?ÄÚAOêd7oü¬cë¬Vù&™f¡v^ã» ›CËt¬³4ÚfêTˆþ²ÁÄ™{?ÚnŠ%³ïú‚*Qiüˤ$§¸kY4rV‚¹Ò‹Špáþ$eˆ†·r%Aéö±æL`Ç8dfn€--îúŽñåA|^-÷A!}qÀÅxÉÕŠËaU='âp±ƒâ8ëŽÐQ ÝxÆ®¨xáØÉ¥‚ïïŒ1`˜1‘çps^d°|‰Ñ2ãŶE\íC0’ã<6or¥ÛÏg ¸Ì¨˜°Z€¼NÌïnËû$\ßòγ0IµJv`4'K:ÅŠ°U!’Ê%7À—oBóÜò®ÒmÚi§”˜2 ¥ÜâK=†|K—>ž…5ÏxRø)5ƒ’ùZ·Ýl]5eÑaXŽ)þ$‰Ø\âòh¸ ;ŽM5ðÐ ¯èEœŽÍ8ùkèLÉê†lî ©è]øËºò<žJàÔö²Ýcp-ºçª¡»KÔ|Ï”:Ûörk$Sâv›:™eê´Ìµ•û?A¶^9¼ÛÔO¢Ü¹ñ÷é}‰)8ž–Nš€Š0%§LNrªÊ†Ò ä1ð* ÉD8Xõq‘xwmš4ÜD?I‰÷‚ÅDÒ“¤Zs>†¿l,8°qCÈëÔòu;¡é1 Ç—ü㛈3+·÷¯c5È®}…Áɦ÷Ižm¥`œ[ç@ ubX™'ދ¾ZÉÉtõ°’@OòDç#Rá§ê²8÷¦e.à3*¶™I3GºÜÞz¢Š|“1“ØhÌ76º0lß=vÜÑ1š•|ªî»Åø¹ª«‚»ñ»jz%0ïÁx×G®¯ ÓéåƒÑ«‹eh!®0Ô”ŽmÑ |À«e–oú?£²Ýk‚)Æh¹Ÿûc÷\u%¹Œ])j€½7α÷Æ–§&ªâ.s7dO¹Α÷ÆÄÜzÛ»í<ã>¤a•]‡M\ Y˜]&™¤±¨÷ÁŒž› „mŸ  pn¤›Å»TŠw™W¼£¼A¢ÎL{ˆãn°&›û2[oá8×=¦NÐ;—Qn5 €¥îmíED΢|r%:bWÂD^YGP"¢àäÛ‹€8Êpƒ.òß(ί lÏ{:l¶a§Sy @¥qPÓ0~I®ÂÀcÇ žœã³1$]ÏM®ö¡‹¬eÀÁÕe庾¤=‚öÔJfƒ,¥O!‘ñ„ÊÍ„ÊorfL§1IÅž{|$ûO »3¢×ñ„èµCô:öN A!Ðú@ζ|Ey´–Ê&Œ÷ÕsCÙG„áLAÄD ¸Éúæ¼6ù¼@gõáÅ0DÁ¶y“o~³ënqê‘/.nê·?˜üuÞä'“¡ëù\žwCݽçeÙqOˆÆDjYÀÆkÕ¸<=w™~ö³ŒFjQ¥ÐsYm±¥œÝXôŽëc­ÈéÕ:üàpùœQgÖK5³©ÐðŽs0. Â𲀘1ÒÀ ¶ªÌ/>g;Åg­óÐ&ëºë©-/ÿgZQ q¹ýf:–Ù=‹¢©¢‘<\åaºÐÎ\U¤!RUÄö\U¤ï17UE¿êᣑ˜jé~íO'Ù\`ýªŸù#U?óå¢ßnÍ/޳Ðèħæšv¤èçêk‚õ7DˆÛE?\ÈÉ ý·<êªE H¨‘@²Â… í¾hÝNa+åâÀ·œÉl0ª¦ypOÈÐØí×hö¼áoª¸ìÖâCJ]ÑÏX/¶ëb«ànp7~ÁF½‚±«² š)Š[žœiÐO¯j%&_ÖJÈÝ‹ÀNág*àx%:«œtù‚ÿ|"«¦ù<-¶kÊç©´‚‰ î3öïnO0;ÒL‹?§šŠ‘Ϫ&“ˆ†Í$‹¾Ön{L‹h¦áµ¾ÇtŸjq|ñ=gÄcâ\?TuÍÍù˜Yì9OÜ¡ÚÀ j«ÎhçOH_(3F®Niß ÂØ=÷G¥ÔVÚ®æÿWŠ@¶Çß¹þŠ?Ù6CãU_w8:™£81fr\%5S”®šsu*8îPwõI|áb7ãN”š¯:Hð‡Ûÿº£u†W{LLF¤¹q¤ÿùÓÿþ»* endstream endobj 592 0 obj <> stream xÚZKä¶¾çW r‰™–%‘"%çd1°c#ÈÜ<¢éÖìhÝ-M$õή}êEŠT«w /Ü|Kd±ê«çîwù]ÿåw¶€ÙÝá|÷ýÃÝ7?Ôwy–ÖY}÷ð Ó{옻‡ã/ÉÚ~êæîc7ÞíUi“¦oNŸ§nÂ^• Ïòûô¡Ý•YrÒ‡LrÀþ°+ó¤}ÌrsèÚ~ž„ÇÌ«ž¤™º¯øØŒ]ótj§Ý¯ÿ„Mé`Sy™Ö6V¥º =ì*ì÷Z—Éën_TI;>ãGl2ùmï ›|f²eëZ›ˆ™¶ýˆ4íè¨.ŸºS×p×$É8ì “¼=îxž—™dšÇËa¾ŒÍɆÓåÜ3M>îJ`Æ'â•óKK'ۻè´,é0ãp™»¾ÅcTÀ¸QRØ>àÖ^šþ}׿ç‘ÎM O»=|áC‹2ÇÒr »`i8¡#‡™§ºž—>Å0¿ào»™ } û,j8ÉOÃ,›™_𙩹àDx<ÙQ3òù²ðhý€—m |üpºÛ£ëñ/Ê„[ÇQ¦Lž/=í©šþè×-\¡¬nNoxΆn{â•/Ô^•ãõ{ w¹|Íø¯YG±)¼)Å;-u‘<¼lœhõ8á)+1’[+ dñ†›ÀOÃ%œà¢'ž#!„Äc˪<ŒÂî0Œc;É`”uóÀ¿Çö0¶`?ýû{¸¹¬ñ„§ö0¸Á©XÌÖÆl¯·&Ÿb£é|…a]æ Iâ8IÒ†’„K#Ë@Œh„Èf¥ß°îÔ6lj›xÌ-"åw1¶ÇËUŠÈ†ižâ]öC¿"€¹:X¤¿¸/“Óõ“Ãäã,G)°˜†!æÆöÜt½tŽ4l=£”ÈÔ±ÇPO¡;¼ÎÝÙ-y{é½?}¢tÆê„üN§-Ór§Û«¼\[¤Ê5XrûéоÎL€Šú‰>’›˜õé£ D%Äì½™zêÞ÷$%Ń;Ò=ÎÕI÷ÌìYçòàV°ƒ‡áÖ tÓpn¿x˜¢ä›óû-JÚ¯^ഀ΄âf´Æž,¯Š´TðüÀ©;ƒG`]|͆«±uª¬,Ýgí#Œ+„à'ÅìïQÍsT¹iœ^T³tBÀaÒÌŒùƒÂäi c@µiÕetɵ‰å‚á=" 丞"Ý{ˆ¼HO>_Æå#±…á]Víð¹¾ÂgFÌúbÞ_ßïÃÁ¡¹LèU·|ë\—¾„Èø´ÊœñáÜÂÈp9eF˜¢FÑ<Û#¶º~±Hì?’èÄþw Ë–u™§b;·ÿ½Fu›¯ÏFËÒ¨ôe Q/Í+*„¨ 37å5µ*oij !Sº§‘¢&ü_óÚŒ‚ía0Õõ󆾖yZhYJ[yÿm¼ÿmàfÓñÎ ž@ác¢X"Ó·¨[µà>LŸ¿µhYÌÙ´ÈC¹‰³ \g"LƒÂÔå–·ÓeMn@›,ðv<Ž*Šã¬88°áŠp|Óá*êˆËåÕ…“HùdJ>xé-lZl¦>"odq')›ôÕ™½3n9´`ȵEì)èàãá¥v¶pþZ.!ªÐû#uû©9̧Ï_K•Rf‘–6”Ãôô> stream xÚÍYKsÛ6¾÷Wpz)9©P¼ÎôàtšN3=¤±zªz`$Úb+’.I9n¦?¾ ,(’6¬‡íx:ñ„ ±Ø÷.>@Áß (ücæðGƒe¼™ß½e§D)Ì/az–š—`¾ú=üa]wyÍ„R¡Œþ˜¿jpIt¢u /©¥>_ÝdÕ2_!ùùûŸÍ@‡êmWTyk—ÿ8G‘IÀ$R9&œ&„sËEÍã2|“-#Aÿ®šz[­œt0JRšš…,&©„Å)®ý­-ª+#•†7×a¾ìêß³j…ƒ2ëšâÇUÝe]QW­yea·Îñû/ïñÃuSÜä%~\„Œ°Eô¯yŠE„‹°ÍÝ¢ ¼z3ÑÓ~rƒæ ë/’˜$ šÄ±µD ÌZß²4%ZO–}‹>¿Î®òäKÁ ƒ‰|zP¼”‚@àÆ«Ð4\fhþ¬§a¢'ùÍL@€NȰ·Û<"ÌZ|^Ö›Mm‚ö©=³LDJD—%$Æè–EU”Åg˃ƒçmh[™ÝÚï æ£ã$QŒÀh¤ÊgO*Ì5Óß{¹0sG°ì  ŠHjëj€ÃÈîc ¸£§¸½ÏAnŒ% ké¯#v¯¼jˆÝU“MÕ4B¤¥ ¾šJ¡2ØÑ,Bá”5PΙ‡ ðnš¹°Ì$DR™¼¡fÒLµ[ÈŠ8ÿ„ÊÁ$èj|n ad.¼K¨Ï®ÉŠÊ$G×zÍÖ”ðxã}N,ÅÚ)Iã`Gq0Î=R ­I6ã $KAO=z²¹ÏÇØN±ïA½˜LBÓI[ôk}‰¾¾‰ YSdÐêüÞU”ã]J$*¼¹o·ÀôÙÙ{7ž&g¬†^P.½â8a½‡Ê3 Úzù,š°˜As1Ñf$QGzæâ¥OK;îzæÕ^lY¹;#Ñ wêßÝN,$šéD‡óµQEJÀFöÚY…Ÿì»,Sš×EeK0Ÿ€Ä ¬%mŽÃé­™åän(k|««åE3Ñ­³G›<[µŽs½“€ƒá:ܨa £c›†_&l˜³./s6ùeœuÎæº_¹[¼Tõ¤¿~õíà.: endstream endobj 606 0 obj <> stream xÚÕZݓ۶ï_¡Gjj¡ÄA0™>Ø3i'Œ§±ï­×ZâÝ1‘È Iå|ù뻋HP‚>ξ¤íØs¤@Øïßî‚‹_|‘Â?¾ÈüOëÝâÝÍâ/S ž²"-7w Y0­+Ћ›Í¿’]ÝÔ»ú·j¹’R$·IÛáJvåg;~»\þûæ° Oƒex&X*`ɲ̮ó››nfXf€ |ü×åJä9¬ŸºyY0O(f27ñ§Øvši힯#û(–K÷x"dÀŠœ 2ngÜœØ`±§|Žò2’ðç¨DàŽÐÈy@CŽâbZÚidžKœ<ιMdl#P`áöù&²Šd©—…rÂX)n©_‰•†úý§å*Ë’Ÿªõ€ú–ÉÐÒu[7Uél`Ý6ýЕu³y2ôv1®a«"Ôüm#„îUú}DåfÔøJ0½4M£‚U¸M}U 7GÊ? D¹ 1Å%ùÜH‰ ^dÁÊ_«‹,¦ ÒsÙlÈù@%Â$í¾Ùô$ÿöŽtòëTUvuùi[õQåœ*e‘¹f^Ž·©PÑu8ºÀ\VY\Vç–nÎ>få VùZRÕ£T3«þôPuÕ7ñÐÅ 'ù£ˆ[9,–g "FÓC¯/쌑Â]¦ã”Sá/?»‰ 6ùaG3¸Ž3@hÖ¬jgfÃCE'<lËûÁ.¦Q€~mhl¢ÔejôàÕ¯l , ç ˆ+·[OúÌ#¾%àR0ž…š£ 8‰”Ð&?6b 8$¥—¤úbI~¥³Kb”I‹_ÛÀ_Óz¾nmô©nS®×uåB>‰ö»—X|ø»»éî)µNh޹â d,|z_¼?NG¼3êî,š¨óhRühr¤\z¡£QŽxMo”ûû]Õ Õ2K“MdñL2ãU<ÇÖ©g’XK³àUĬ)°—‹Rý½ÍqW]ýù%æT(tS0 ‰bÀeDÔœâÁ=cf†ƒ*Šƒc»Où¶ÇaWb‚óª±=¾‰þŠØþ‘¶->x²O»h&$ǹ¨¸âB2%CLØÇÑÞ¼í÷Q ~e‹Ø_L)âÁ B¼ìóÿ>Øï Ž:"ö ‚Y -àÝ3ÌÖ:Ù Ö©¦ê¶¡‘²‰xñþ‡ÂDc€ˆðe_¯ñgžôívoW‰à‰f…÷¡ûªÝU×@²£Ájw¦ 1ÝzP€±,©-q¹SLê˵»µRÀ×·[º ¨Qo`,— °ÞƒˆQhA­`‰È}¬€·Õõ˜%XéäNäp}À‡ÏH*:ìã¶l*·ÀºíºªwL4›º¹w cm™aaΑ‹h}y8Hɱµ° \ELÈ‹¹†”‘^ÒL¢0Ì…Trã÷¢ÍÕÈ-‰6—sÑ’(ýŠ“(J«ÐÔk ò€R‚~2Žy¥“²œŸ÷¶ó˜³+ãï›Ñˆºê®í*ÿ5£¹÷GsvJ㟜‘ÛAgäöÁ“WcVÓK¦‡þJ#GËFh€Ñyþ•ÌŸãî”ëåQ½¨RÆgý«[ËP&¿o. H®âT¤ÀgذKúl(ÓX³ŒB˜q®"ב¹kÇØpOëfS¹Àwc”€yÕ/ûr ¡Ìº"ü.;Gw¹µª*Q;Ïþá(7.&LÊ,GïÚA]µr‘œR©©’:¡^kÀÕG¢€Á²¡HîÄ@4Pôjûªq Ñ·;µÄÕ\`àY•’Y‰OºÜu•c|´-F&|ÍÆ œD*ôR, L×)ŽìÂÖ:UÉÛíðÐîï\ê¶w¹üš§O8’9@‡‰MK× «4  fhëægC/Ã!¿¥p³©%@³®¦Åa­|߯òG› RÍ]ÝøÍ­·íªŽ¶N+Û}ÕÏ GJÍó~šsçϱJš{ïDã8 ˜óÉF¹ŽŒüP¹Ã‘Û4ÍBœqÀäѪ||ìÚGØp|€¦À1”Îá.êƒÌÛûcIÖvNP§Êual‹ó©×1R67v2{²H2jìêaê³›YíqD:¸"κ3£Ë0¹ˆ½¸ØH§…ÞE‹}µâ¶‚½Ô+§uÞÇ7,ͶêÑ2QSm™“fê2•Ȫž‹LÓOË›¨dòð!*‹ É¿(‹P¦cTk<úBYä3YÌì°`ãyÆ·±õ´…ÂW:$ʉäxöý4¢ïÁâÒJåÚcw'D’M]7•v®®lµ45>TF±Æ}`RGµ|´ÅÑs®=z§ÓÑ™ÍèÔ1:C„ Z³ ´Bz£ÅÙsذ+[§{pEq5Ë'zp9¿Øƒ»^ýW6e•íö8CYÌÊ-×.s»Ðë´Ç:-°æPÊ)§EÚ®¾¯›rëª`§`åûq*už¤Eòƒ×ûç~¨vîe·ÿøY€ŽÕVZŒUìQr2BÅ :» ‘cðØRº¼â®ÝºÊ§'¯¶•)T b_퀈Ÿ= R×…n².°ç|ôÁ‰:ù½É©8ìõ’/æ¬Ëðh«Ù‚¯o. ÷]ô Š)}åç;ï£|úè Ž9 ¼\êeÐy)Ð/ ¬¯˜FÄmSãþ$©(n¦’¯†›æ7ev€›<7,¿îk ?΂¬+øt,žGlþï„‹ËŸ§TÏŠ±ôþjÅNñßÝ,~Y0 õ„!=Óö˥݂›œ‰ñ÷vñqñ£ëÐg @g<ü'®%³<óÇ·ã×4Wƒl xŸì|æØ”µ˜ºÿ„µ. a1e¼Â^¦s†Ïzµå¤r_8ä_8(N_8á†Ð ;ƒ»î?×Ûºìži)[}p 4甂ŸœäøwvD}’Ç"e©+>¨·l|D•löÝXfàdÔœ  *JT‚;9©Þ[»Ó°Ñ<°vØ!°öÙJ}nì!z†4–5Ȭœ![è=³ŽÅ}S¾G|ôûO!+ôUœQÓ‘ýt Hö6%‚»®l~vÍFy‚ýhÌño(ÓÝ±}å:0öXvC½ÞoËÎ=pª@s¢8H‡” zõ0ƒHQÛ‚ Y¯°­AêZõ&¼õŽé“±' Çfåœg4+yɬ´ó›·±-hÌ‹aÖä›ÌÀLfbÛšUDÅB3éCm}:´­åZ-†Z-(âÃ3MpÅÚ½áiêË¡îñ¨¨Ú¸¥œdݱ†m|.¶ s˜ô±í23åi…–Óg©!Ÿâê¿ñ‹6“ý¼ÙmõVZ‘C¹ŸúãŸþ9²S endstream endobj 611 0 obj <> stream xÚÝÛrÛÆõ½_ÁGpbnö†`Oâ™:ã:í$­Þ¢<À$¢!A -;ãï9{v¹ )Kñt:Ö—]ž=÷+ffbÆáŸ˜eþøl¹™½¾š}ÿFÏg/fW·3‘²BÏøÂÌ®n~MþQîÚúÓü·«¿ÃNÁƒ­*g!â®×nÔf>OJæQBµÊOh¯íô›ÿÓ^Å´´W‰ µ/mµÜ•Ó ›eL˜Sú*˜Ñçô•#whOãì°<è«’<ÔWä§ÇÜékæô_‘¾Ò¢ÓW|@}Åë ¯`ç`;Óúª”<ÒW¥zµ°÷1}Å÷¨¯xE'àtV)}¨³ˆ‡wL9K•ÅâÍTh× èÚõœj‡Áív½Þ"F;nUî^Fùô‘¯ÁþyÒ«xLVdÎCr;™É']_Á²Y¿á» ¢W?ð·Eô,ÃDœUTÁÄpØ_QÊY£gKg¾ŠA23~04)£ /#Ô`S‚ƒ4œÅK–§ Hœqi×@·ÚêvÛV/¢hK ‹g “Ú2¦˜Ž?œ)Ë™Âq&jŠ©L1ʵœéâ ÊL<9ËåL³ô„PM=õD,SÀ%Ã*C~ZŠ‘2`˳æ—RîýÓ“¥,bR&½Z¡éí;ðLšS\¨‚ƒU¶»²FšçÖv- »Ü­“Í‹Ä=ÑNë.`ÏMµ«ÚMÝT´¼ŽIö›ªµþö‘ÿXï+Ä:5¸zS„ŨX¸aÚ'§4pÚ  zÉÁ6Ë®ÛoÐõä& æÚ™E¹‹¸C…¸ê“¸ ‘1-/Àµ8åFűٙõ«\èOäå5xnïF«º¥Ûr¹«?¢„Üþ÷äâ÷ÍóÛ ! Ä-ðÜW}Ñ»§!7åožˆ›½[ˆ›z7)¸(0ÂQRhr¥1¿!šýY¿‘[¿‘ª¸[Ï3Æ‹ç2x9mða® ©syO)GU¶˜(Š"ôÀ^½Á£gÐ. …×} ÷ñDPä}:òÆ b‰#Ú†MK÷2@uÈ qýoW®ú×£j(€4’ T‹Â¦@øk=üxw\AÉL£_$f,ø#›nQkCõ® |ÆÛƮɮÞT”;Uã϶qÙ™;mÐÜcß1‹æ>’Û°6ÞªÇÆ[k>Öb–š³¬8é±Ô3ĺ\†úTÕW½ê+ƒnf!ÓÞŸAΜ'ÝçnWÙ¤Ú鸲A 5¿£kõa_“7_cÛ\Y¸ÀæÔÞÞ‚J{HÍáΪé*ÿÎZýLCÞ­há¦BÞT‡@ÊK÷}ž=”g•…™ºÊÀ$.‹w¹~G‹„–ñMÒÝ—KwëxÜ·õ¦\)fÖ^ºäC Õ/ðÚÕÝ­/·ý?Ų©³Õ^‘¼½uUÐrKk\‘ÇUë€;Îï]å!™¶Nç˜5¬éÆ$ÜŽã/¼ Ãu[usãã¢ýuéy\ 9 (XEnPjbí÷cŒ:(Ùv5Æc|ª#ô8g©äÅfC‰h©Yå*{t¦7š3ï|‘£…@½ªÚ‡º‹Víà«‹‰ƒêæÌQ³úèÒM¡ÖC/ªr xÞVm‡¼ÇºÖrë†VœÀ]iùú“cýË‘Úàx0fà]ÈÁÀ‰ì¶O½RBNä+X«7TêHÚ—§Ò—§es3¼ùO¸äV@¼?ýLWàõ¶ýL÷]i Cð\{‚QnÇ¿Y•ÝlïwH»ûµ£ÇÚ… z9Ü|xxkà‘»Ý6•¥`ÐD¼í™x8îLF퉣¶@GFOv®½/Ñ„»-6ÖÒ³äËÂaO &oñ„WM¹Û·–RxxÀŸ•è>‡%î[U¨ÊôPÒåÎe¶ !KDÚX7j'ðݘ7·>­ß…»åÙwUŸYÓÊ»²Ýw«/ïö«æËv:öK$âw‹PKMwHÏé85bnjDçdÛÄ#äŽS`[¡ë¥t»œjörPSõõü ^×ãþ×"æ§ô­£¬ÿÕÐ÷òò¬LC!w e ° +=Ÿ•qÎ dªÈ0t“OŠgÕÒwÖÞF2ÿ‚IŸÕÿÔVÊÉü_è¡G÷CÌÃ1Ñw­ç˜èƒiÜc’>q5}Dͳå<Úç<ŠLAUkú¿Ë¿!´Üëq½Š`˜¶€rôp%¢|î¹q¶“wÍeËe¦×Xaâ¦uäëÒ~ÇןCI²ô}”iZÍúS-1¯=m\wúbòè ý$Ū%¶wx¬„ÖX=zMˆKÇ+é2rŽ”übñj)™4¡üŸj+iÜŽÁd„Õ€¡ºŽ0ÊýAºzbˆÕw+?Åm+»„gÛ>Z0Ã龃 1S )´uÆCëàQ†3æšHà Àè ÆE}MÊ´éã‹Üö½b ÛÔ96±tÒÄAè 9ðùÂ¬Ž ©7õ%FMÇ9 yF?¸|²<²Iy¤XE zFùYyäç¨fyè³òÐç4äXå§cy¤8¼}&yä}p5Êú¢À Î×Ó!àD¨QLÈÀb¦|çä÷h¼I.Ì_"-éƒCBÉe£ 8™'qq}|1ö1ÄÌ}ß×F¯è™2 -Úr•’_ƜӶv"˜ƒ•ŽæÿJûè9éŸ,Hëib€¥À>ð(Ù_3a r9á÷Òa2p!p1tÉü彌}È¢Ìà"¾ûª IŽóL®˜ž?à 8ÚVYø}D4'Ç™w1ȃf ñ¹~ÿEHj4d‘2 Óƒ–~‹c~ Ƴž¼ÞXÂNìN ³ÏÆ1JgÅÔöAð›Ó4¡vS…2Ê~>dÖç>•¢þÈr‡ýí>AÀ?•wmÙÜU$7íÝÕ÷뺢YP†S`Z­>샆¶ß£öJEî›à¯¢ ŒÈ¬ÍïN†Ç|2<Žç;~Ю`†ñ¨Œ)ó7.ŽÜøctô¤ïybHzNbžl gòÍ)•S”6Ñ€eô@èo8¼H©9רuJÃtvá€;´Nhç0p¬Ÿ6öã‰À:•Ôd¸Š:ƒ]Ԝڎ°Ž6,7¼%6̤¹¦9ÍU/4׃ìþ`訳… Œž²Wˆ>¹º¬…¢Ïe]ú©æªÏšëY%N¿5-òZk=Î[þ,k½€P£ô±ÖªFÖª5Y«Öf2–ê¯0V­5…R€„RFB)¼¤P 7û{÷•€{ !õhiÐRiF“¥L#c$Ûí?”ø0cªÈg8÷H Žñc¿*‘ýózöïÙ/®SŸ£ ô‹¶Ò7e8Î}?A{ ”ç…1.wN ÃVØ4³®PK?µ®ÝœEË`rTøÉ‘vŸ“jÿ­¼øñ§ŸßÑ+û±ˆjØ’žy‰/4†ÿE†ÿ “è é‡uv†£&ø\6„Ì{‹­ÛUÞß×ök—ïa\©ÅhH§ýðn¶ýZÉÜÒ›’ýTNK6Âü­tn?1š"X‘û­¿üå¿v,†’ endstream endobj 616 0 obj <> stream xÚÝ\K“ã¶¾çW¨râ”W âÅu|ˆ]±klj“É)“Wá-Q³”´ÿútãE€EÍJvÙ)o•$°‰~h`^¼]Eÿ‘…¤ð¯X¬6‹/oøš-H‘WEµ¸}³ <¯Øb‰bq{ÿŸì«mwßîÛmw³,Ë2»ËÊœ°»ó«Ýá'ËöÍÍoÿsUá\„æDGœç©o7õÚR…K–3f‰î²mß>´]½vvwûfc¸lߘ±æí¡^·û*³8B³Õ¶Ûíûºín¨Èö;3ˆ¢ò»›\ó\&rAáSå¼kƤՌ#_&™Ö ?§4SyI¬Ð÷‡¤^”¡ ‰Óù 8s¬> ´ E~³T‚g¯ö†¾‡Ú¾ÙZ”K?ôõ}Û˜WbNô%áUN |‚=¸–gûúfÉyöC³Ú·ïðU˜ŒV*{sèVÖ×E‘í·8Ze@lHp°6cë¶kêÞ|_m78Çkð›y§B)ða·íÁï;ógÔ3?6fài]w}xßÜ„uͽãj,ƒ“ù7äàô," m™ˆyê·¯×ÍÆ„‚ ñT ø©·sé@¶¤q¼² ^K¯h?÷ÐݛߓÑ*\´sâI'J`8ëqåŶԫz×ÄÙ³©?´›ö'íªI%uLO&à …LàžÔ(#k¥¹“Êp‡Ñ©\#9w±ºá$ÛnžÀ™M·¯{ÌB®ëÕH8cHUdžãqjÁséÒÒŒ••N3Æ¥Ù øIIöF›Æ›z…Ú=QƒðÒêÔ‡íziÒV¨\Œ­”ªR;‹*“}Xí½ |òî²îÛÕŠLŠPfªòŠ[™?8 ò¼’ø\ä´ž¹TšâÇ„Ú<zOñ³¤Þ™šÐiZd £j½E½ß߀ÇÝÓ­ý<<=éHhz§Eøº†Ãn?<5Xj=V7ëOM¿5$†^Ïf1¼ÈË(Ëm@ú¸]m{ð‘  {0ãßÖ€“݃M#Õzß>­Û¦wùw—¥ìN <íòTPž²|)µå¥&J®qÖò†Œu4 Ë) &I¹OåR “l½ÜÉh‘¹8Khaòó øå>Qf>VÜ@ ÔÀÄŒu  ‘5vݦœæ\…Xò ADUÙ7ßþã¯ð­‚åÄGèÖ<м3ƒ–*‹œÎ™J™uÊ¿jÞVÓéY¡KWj—*‚Køå×L­O´f‚ûúØIè2—ìªÐ—à"sæò<5|+\-ûÈ-IF&2¯ª,Ýç‰yX®ŠÓÔûàá__!²—Á‡tfê%cÜd‡‡ÄMJvàŸ%%†on1L­–§.Üš¡“´÷pë*¿æÞ×XlMjo»$â¾LŠU**êfFχÛ4R> Î¸ŠÈ©ô爪g¥ÿÏ ïÍì)>¡¡ü˜šð³„¾0ùyBæQ´‚Ë<ÉçÉZ«Ì¥_@³25K•;({™´náÞ§…tÉ`Y€D ¢åýcë!J)]Tr ðz­ƒ¾×‰òR•þmÑ+«ì]ŒFQ6°!`í’xuÝJ *TNXvû:+P–¹"ay\wÝvŸ²#ÏK‡Lë¦Ö6&UÁ6¦„‚zƒËïëöရS[0¨É0ñqKõª>ì,µ-øöf–Q±¨çsÕeÛ¬2õ£4¤”ÕãÎ @}—°¯"¸·ï)€A®ŒÅó£¶Ç%…½¯%2¶¢4ÛÕKºo7YVþ|kOYþùýÒ?˜sH'#—ÈqˆýJK!†·ñŇã³*`±Å˜—KcÁÝ6– üªË*ê°×Q¦±D)„¦_ù³œbêŸI±)3½’‹KÜXì ´·¸h2¾VѾP!%3iH¹Þüè­§pà㬣zŸn¾òD© Ïk}wãB™e÷í]Aʦ÷'E8¸kºåfcš×tªËu1°xaÈB¸¥ú¼ìè ¦l{{ŠpØØÚáеoÍú£=g°g>öü!¨±zxãO%¦Žnþ½3[<&z3m¥w銧ȟµè§ý^KŸ1_$†?9ïZø v´ú÷ñQá ÔŽ68àÁ7ën˜Ò¸~¼ïÛý¾éìv¹$¸4„Ýh¿ +ØèlG#Š>8Òëfê<† òÝ]X7ûõ \™¨ú}ªÂ¥Ö-ôõÎ °¶kÆî¥À· X¨Ôâý‚ w%lÁ‰\lŒ@²ëÅ¿ßSS`H:x»tÄG˜ 8 Ëù²„5[™ï¿G'‡£#ˆP:RVX{ ýÀIŽD+±ü[Ûù#¹#6TrD¨8ɦ4e}Ä&8ù;bãmëØ„Æ.ŒMÁc{DhÄþ€Ü LøûeàÃlBɰ̅— (UõB3N;ÄqyhÊ!NÏ'½ä°³Ê  øQui)€ µt§µJ‹w -͹›ÛZ°ç+DJV1+PÒ œT’4—ôWäʹÓ·éSæ^¾éc³Ï®ñðã\3¨)×@Õ.Èãïú® µ, ‘óKüÀI-ËBá+®€fÙi()aK(#%ÝÀi%Õ…ì¯Ø•GYÆ®™e??þùÕÔyf´Š…=`^=óГOªZ¦˜È÷õ1Ÿr¶|vîtaÀü¹”÷:òáÈMž@Ï<†‡94ðÜçÁÀsˆÑa R ÎcÁY~œ‚í8á´Ç„“]»µŒbg¾qÔ¯ë]»J‘%ÿð¨rªæå„*'ðE¨xŽÅ¾KÞÈÀ›ÑW·˜ "9ºm·tv,ËùþȪĦäsÍø] 9¨g¯rUT÷s Ý›_â­HI]¨Æ.¼ ¨xÜ Ní­fü´zà×XáLúf >k»°y.©¾°1·ŽÞ|Ö»v ¯x^èÖ‡à6iÜç@‚ÎúOO¢¯”{w®˜»‹>ÑZð•¿ç(ý=GF]ëëú ¯‰S9øi"g 8Õ nå\ÒAÎ(HŠçIƒ:³‹bE)Qtã,Šâo£¢ ÷ TÓóŒ¿[Kä/ÑãmãKôCëª]”)^|À$v·&p…‡uýküÞo7£…;}Çzøßà“÷îöLŽMÝÂ6u›¥€ÈBÄÁ•©©F×Óò*QwVhþ`{c `Nzƒ wÁþ”Þ»™&Û^˜+-oÓ546‰yš»¢$É:Ú¯z³WÚ&öÕ²¶]á.+Æ¡Á…½&$–þúM꾟¤W5I²Ž`+á+ÕÔ n? (¸ }öä –@ÿ;<×á Ø@`髳›jE¡°È.¸ZôBØÝÔƒKAL¿r·~ ß> stream xÚÍZÝoã6¿¿B2³â§¨}èÝC‡z—·¦Š­$ZØVÖRº—ÿþfHJ¢dJ–wQì"¶EŠœÎÇof}‰h”À?¥ þ'Ñf}¸¾ÿ("š,É¢Û^ãÝnëjµæœÇûKã—]S>ï^ËÃ#>dñýjÍt\5OvN]n‹¿Š¸z°îbN»[Ù_÷+¦âWûî>oŽåÿܬ$‘ö½ÇòOܨ¨Xýqû¯ˆJM„ŒÖLª =8õ.6ƒß¤‰G6eD0 gýê&Ho<#,sßnÆp­$¸’ Rº©?» ¾€4c‡3·È“d) Âü‘fÂmhEÖí”»„ÓÀ.I¸Û廎^¤¦¶¬Ý%LnÂO°Vš:9&9qÞoüy‚zåÆ7­IÙ¼täYéôÂù!°[ @ÁBkd$uB x2îˆ\ ɈèÚÇ•æñ±Ú[…EUά&‹¸l¬æ>T»]…ûµ¶š§¼±ªË˜å²oªºb^u³ªK§3T$ÅÍéÐ^›tüû_š¤Ù·çË·“ž7+äYæZͳ3þ8]Ã(Î9ùˆ±|ÀÚÂâ‘$mõøC@&¥­!ç»6Â5í§}MÄ6mšêh÷°1 b„=)ãÏ0䢕}qSáaÇÅ]BÕ¦,H^S·Î£.Š~{àónÕ ô}9pÌ Kô“Σ³T!2‚%j"³+pŠ+• Tl°ÊZÚí(Ñjá:ŸBtk’¤ãDó–hÒJe˜ãzB«2J$‹úéž,†ÖŸø¢zÂqcŽ‘}À¦¿Ä8Ê¡bÌÄHŸQ5{ª~ qªÀ¹¥×² 9¶ žà(Ž}ƒ(B«Ã¥Gqú¼r m›$àÚ)%è2“`bøaÌCµæÑ<ðyÈåÆûIÝOXì°õžËŒ—–¾ÊãÝ»"ß¶ˆ¦rX\PÂù‹£š +ï jé|P“׃—ÓØ[øØ›NGp*O‘·G²~glfr¨„ë•ð\¤ŸÜ'=£ì}o7c±ð‚èï2p³ÜýŒåBÏË%}—0qëœP.Jç‚Ñ€*"ôµ¢šFI­7ÇüP?Ûü¼îÅTÂÎ;pcü€j}D—Ž ¼øZ7Å> `TŠ>ÕuÀ@¼î£ö‡SÑk¢pîJAÙ¯3ŒÂkš:é:]Åx Ž«èñ RÝ&¿ðÿï‘Uìª#<æ èŒáë§Ð=·ÈWÍã.(:ù^Ñu]äFFþ!õBû»D7³ ä`©@7*®caú$ð¯¶6òïü"î#š’X-W®Z^Ç:È^ÂÐG&óD§^Ù6ÓÓX+Ó§K ΄YiYI”AFÁSu3  ršã±0@"+.à¡Ià³øò’ïÊÝëe|Sj€e—ÝáCIJ]0ïÁÄõ¡:n#ã“àËSŽïî°Ž ÞÏv#zÊS¬Gy‰T]>L¢$âÛ§Òù­|T—&ªÝŸê äjâX7Öéafe‰\n¤»ŠÑ”güåÖõVþóO÷åøh»+”öDD‚p\f3ä§ýËø^ûÊà|9L›â)C0:«1ª/ô‡4…¢ð†Ù͆¸ÏúZ¬¯I²Xs%ÔùQ¾+1@ƒí!ûTÅ8Yìâ§+ )œû ;0 ÏO¡dÅ+uO‘¤û ,{~^öz$ûÙ¾Ò¹È÷»s½šMgéa5áçj›)Vàº)?NU¯éµXÊ˲a^ÖoÚr4x™Ð®Ï)Yª\›Ê9«,\äéó·bSùuNOžKU×—«"“A“ö% ̲S\ O’†Å†ÆJꢾÇiÞ”‘¼ÀPr%yý¼ÎX3½‚9Óåú±À3Ù–áÙÊÜráÊO"»,Îü½€z»¼­!pçË¿!©áuv%‡Ë“éBØmëêv9$µG¿låºu¹Ët§r`ã<‡ÄòuW`?òhvv™Q¦%.R½É',ð"ì a†8%Ą΋î°|¬± ñ”~5¢ÓAܶÚÚKÂ)I=j×åþyW¸›M ¶qò—6¤º&°-³R†]`×pA€tc OÂSœmð8Sºõ¿ÙÊkøBy_ÈøBý—ûBøÆ/ ÎonPÊQÄ£&kË×—ˆ÷ŒsŠM—^ÞkqlÚ‹—ãÆÃðNFŸ¢·—86÷­‰dƒ£ÈúÀt\É<¾¤ñöe³’Ì}‡%d RÁªnêPvëÝ l·ôoMßZzý[[³ÀžVƒ5‘¶ ûó½­¨ ¨îJNÚ{eænKî.Ôy¹õn—Ù hí}—C[}ÁrnßF®«Í1Bs¬è÷æÆ'`rãä¦;Є´?÷+GÀÃk#Â6uº¬¯-çLÞè¦VHÛÒ—D¦þ©ÐÁtÖ –%Ý[vÄ\1€§Å——ÒªÊ/ 踱ãMå>ÍR0±[ š¨a*i8‚*€ŸM·kq¨‹öYÞt ½ÚgNå°ù‡?·…Á.Åx‘|_8­•Øéð mÊHQ«úðéú‹^µOY²¸bÎfaVýœo ÿEfg <\w*k’¢”go·ª>WFõSzÐðšê¼)ë‡WGXe·ë–D#d¼n!YÿúàVÙWǢ꫑G÷ØÛ‹#ø—ÛèKDx¦£¯xwZ%ŽìÁ!Šê~ï¢ÿF¿¹ÚžŒ@´©n¯Cœ¤[”ÑÕÍ\F!äeJÙz¶é˜*ÊFɼåR,.r¢OÂ#ø¾n’$©ÇGÕo£1ˆ¯»EöE~0…\/Õò©‚p0®jù› ) í'M{£'zàË8¬_¾,½4°B”ÔïƒKË0O”÷â"1È‘3äs(À¶°]$<2PßF“˜F®•°¡•:šaîoÿø?R‚g endstream endobj 626 0 obj <> stream xÚÍYKÛ6¾÷W=ÉhÌŠ/‰lÑK€¦hÒlOuZ›^+µ¥­$g³A|‡R›^oÒ (Ô|Œ†Ãá7‡³É_ M2ø&ƒY²>$/o’o_‰„fDg:¹ÙÂôÒvòäfó{ÚlKžË´Üï±±9–¾õ~!EZ¶Uy»7Ýâ›_@Í&Š´"B‚:«g•1d`i¢ +‘^Àj$×Nèµ—˜ZCÉd2ˆ¬ÒвXJ‘¥­Ù×fƒÖ¬›®[ÁóFl"ú%É‹`ãUue_uÛGìôýÍÓ~gª‡nK¦ÒæXK×]ß–U½`E FÀ ˜J½iu`cµj{ã¬Y2*H!À œH9ú\ó´«îêîëïKÁXÚƒ£¨Ä6¬ã±Yz“¬ïíÿÌjñ¾ËŠQ|Ý´­éîA°H›zSÕw8~[vÕÚ/Øì}ÕÔØ«ìN´H×pö&¸NO\ÇeAXpâBP–nÍBf)h½õ[T‰,*%‘jêA&ÖWË ’q¿†à:ý¹‡oiÛ£*…c4mgÈ:Æùqƒ3ý®ô²¥;ÚGìøå¡µ5~a'>ñÌ ²š¯ÇE œCfW)'T:º5ÑçKÜÃdÿN®prœC¯iC ÆŽ ð Ž®ËÎ`Ëá få‡êP},­±«q«€“µ¡"’»E¬›Óðy „˜ÁŽÝøþÛÝp—§N.xÍN8è9Íá~o¦¶r}Ù>¢d·/×vÿÖ¦ëphm‘‰N<Ãi»#«¦êð·Ü?ØÏJw&þCçîUF…Gê2lhðÚÜt/šRÖ±Œ(å%B¬ñ…ÓF÷ýxãyõן|£½Cf¥t`;šå$› M t²?¶ßÝ“19K–мX1°óÂr `íL“#Ÿm žO-ÓW-cˆ•O-«º˜ƒé@¿Í}_ vÎ}Ì5aÁÇÕ7T:z…í4µEšm…©ª÷ýï[§wþ™ Sž1RÐ|à¾ÀÀðÐ^—Ç*!xú[ƒ‹I¹Õá×BÎ!ÎK¸ ‡q r˜füÆáCÏ"œHï&Á+V‹¿æ/ÄåÍΛq0e$>„6Ÿ\‰6ò/]‰TH¢ô—¢²þÂé,/*0/ªH’"?Ñ3¹ÞánUîzGÓßEV„«dœ¶S7õ2ºqÈ1ã@7–õì ±c>Üï\ƒ#ÆÓôóÛf¿w—åƒõ ò…†@˧ $£àÈw×\9¯Š¥msÀåía w׆3,|/ Ñ3ö†ðüV,q~õr¡Hy-û=2©‡#‹)¡D†3]Ÿä , úoÜ<äp¿»—1…Yˆ,'ñ!–Ü11Iî^FŒºS»o¢fCë³Í~Óè|ù´ÙüZNš¡?Çp:7Ü®"œDSáòÂA付!è`ÍIHÑbø˜qu± €Ú•DÀQ7÷öxÛõU׊—“ErF¤ðz®ûôeܧz†­1…ÄH1z” e›C8ªÅŒÉ™íæ\Àl{^FØC®S—½ØDŸ³IBV[i]Rb¿ñ´ù5ŒÌÓwfÝW˜f£¿ìµ9ÏàñÊr”Ó6Ç»]„ÎÄÜ€xä MÀq R拯á¶x2ð¡ìJñðÜ»ùâ4ð¹n„‘3è21¼ü²,‡"\ù½èÁ,EÍšê TÉ ^ŒŸå äõÞµ*Oȱ¨ºóŽ6Æg(@ŽÁ«,úÅhا{ü2i .ÿlÖ’Ï ­'9‹G8k ȉB*NÝ—Is’ ¼£F¸‹øÓÝGç[—g„Í­ž‚äs.›'V¾|K+ǑΞt}é|†ôMè|¬sDu°ç3ø¿À×s.E~`|0 H›%[€±/°ó­ÊË Àsðôú|!w$'x:½WI>9×OB‹¡ç‹Ä=ríúv• )=F”0ùI»½žRþ·¹Ùuž‚dlÃ+ò¥G8A^÷“ü_ú霙žÌa¸‹Š„S‹ä/’ÇŠÓIý]…MáCÌÙá³1Øf°INÝøöX¯‡jÐJ*ôñÜr¨¬›zã݃ebí’Z_gQê¤R9$»j–ì†Ä>z_2Kîÿæ:ËÔbT$®Ô%‚”¨êÙK6m*HêÁ·X6nw§õcÂ*Æäý°>¶­/‚â{câŸP´³Å‘ù?ˆM7Íб´>Õîï+.Ò³àɧO5*ïï±âS¶$œðÄ®¥ е¹™œ×3/ZE©C‡/}[sž–]w<S<X ð‹Ûî} ½p¢Ðœü=z»² ªÝ6퇆Hv1®Æ4åÃ÷ðx)èìÏhÓ= ÷ݽ@­B²@f³#õzÜUS»?†Oè½?0þàrrdæÓ9§KËæËžx.iÍh}óÕ?0<à endstream endobj 224 0 obj <> stream xÚí\ËŽ·Ýç+j™l8¼¼¼|†?àÀ@†íà…¬é‚ R`(@ò÷9§ªœaµz4ÍéÙ^HÍæTó÷qxyÉb:ù)›Ä>Ó„ßó¤ÂïeŠßëdx&¨Ÿþ•)kÄg˜ŠV|êT#¿G´YÅX“& Æš<‰&Ö”IbBMô“XFM “¤XPÐI²) h§kÐNM¬AÏ|bMF3k ûɶ^Pcžµ¨1Á¿Êš0…TYƒ/ųxÕ³Æ&õš„± k0èXS&ÕÀš:iÄØBò“:’Lk¤™]@ç´°yŒM+ ɦèñ`HiŠ’X“!ÆÌÈS3kêcAMöS´‚üRaM˜b®¬Ñ)VÏš8™÷¬±É„úACÉy2‚°XUô…áN–¨$ÀX¦–J˜¬PM VŠ ÀÉsÈ%OI8dˆ/Q¡T¨šC®Ðyäѹd2$›† ùM)ÓV|œRÉ,¤)û ”蔡øÙŒò,Hˆ6Cû)ǹ€g Qô 'Êö—3L†ÒÏ…ÅHr…H&W<Ƥè\ ž5ÆçÑ2Œ­@Ð(¤©„À~—ãÔˆ_Ñ¢Ã.ÇŽ]a-Õ³øs•ÄBš*%¡ènh¹Rï Vš¨Bƒ5Ãúª…FíÔJŒ_¼‡í)º)^2K°hOÉ)D ×@W"†³aŠzñ 毕ŽS”&ÄçhGZÑþŒ_À‚E@Ñ£e¡þ"ŒYàG0?ûÄÇ. ¶%|Ž…ÏUàRB<a0óŸ^ KÒv~¿>¡“øœÁ/¢ò9>G 0DàÒ‘C#Z’P!žHÇ…5Àð#ýÖ!ñWHI”¶Ïþ1RðBb íi a,¢5°„_ÌÎÑz¬¬C¯"&Â.$Ò "¿PBˉnbðþbÔG2hÀà,Üà0Å™nÙJŒ-°• y’‚%{p¢A6°/˜ŸŽA‡ÊÙ3ÒÿIºÙfn@¯àZ@£Žr†$mfÙ’YB{†ŠÚ+Ð+JøE!ÏQ;R”ã°™ŽÑsÚ‚”ÄÞSGhDH2(Œß¨£R1£Žª‡uT…ã Ž*iÛ¨#˜$JÔQ¥t@L,l ™¡-~“šá$s©…DXÙJ79Ò{²Þ  Ú žì‘Hœð·L‚C‰#LðL"FÒùù‚±&Ò)ü­ÿ8ù%–À‘ÂI1 gJ7‘da¤G>—”%>W ÏÄÉÝ(áa ¿œ*¿øâæ§ÿý{sóå»wï?ÜüøŸ_>ðÛßþñîŸ7_½ÿõvóëkIØÿ|óõkY _â'?ÞüõýOïo¾ùóÛð—W¯n~ؼýð¶à’rr..C+FF ær±Ÿ_½úÓ¥@ÚysÞ$Áa>ï%Î.Žš!¸Â¥2Ⱥa¦tâóTÌRF¥(Eg´qeqVÊ Ü™8øÁdÅy­#€J¤ÙEÌ3PŒ.Á© Ž8p=’'x HF½éŒD‚…È'KôK'9°§«^g p «ª#€Þö@9843P®NKtÛÁЊ_³˜Cì2hÓE0- þua Õm{ —ýÂ@˜¯\Bu·¾ycá³¼1}ÿî?0²­n¾ÅÓ‰%´ñý¯ïßþ¸ùðúæûo¾½ùióß7ßýëÍß7_/_-ßè²t]ξ:Ì’œÏ#<ò¶ŸØR5ÐÊâ‘XH8„G#€ú‰ q¡«qq”TŠCD1(ö@©8­; ŒÑ…ŽrÛOlX›9®îf $ëž@ýĆèÕ…ºx$ÖDÈ ~bC,å¸Öš4:„¯#€ú‰ ŸC ¹a aDLp[{ ï—‘3Ï.å1Áí›A´óuÂRßay6¨ŸÙ,«ãša*ÞYô¶ ‚-d–0¢!ÔÏl¦†-„OŒhõ3GVw\g£ C(¨ŸÙ°JuqÇuXŹ˜GPÐÆwñЮԅ‚ÌctC¸n#=Ø[ãBAXÉ;Âu›Ð%PP](bsXÒìv\ÁÞ!  Mìü(ÂÒrY˜!jrEFPÐÆú!Nº0CD]H#˜a“z Ä i‡ƒ8eˆ»nr£¥:ÙÅ@ZA@Cb Mé%ØŽé´`lCb MíR@T·&ÐÑõë,E”w1F7„é6¿ô@ˆê.R„)u Ó½íàMº‹4`tCb ÍíJ&#ªÛ'`@@Cb M?pwØ1‚»u ÓmûL¢„÷ Ðë¦Ûö³QwKÝ'`0º0‚é¶Òç+%dÝçEÀ@CÔOFÔ-;0wmûµQ@Œâ>ÿÂtÛ•¤˜Û×}þƒÂtÛ~.Ä÷ùÐÕÞ6­ä_@@;¦ƒi ¦A@Û~6Ä1îó/  !ж¬ä_@@uŸÁè†0ݶÏú ™¯_ò/Þ!ôzQi‘í›®ËO“ÙöóÚÓ¤E¶ý¼ö4i‘ímô$i‘í¦z’´ÈvÛC‚Ír—wÉVd‡ø÷žýî­öhÉŸj¿û–dŠKCi_8ú7èm)Ö‰3ú\ä6WÍ»²p‹eWÆôUëRæÎî%½:öaßÒ=ÜëD/õX}ìå5½\ü1¨Ü˜¯Î’L•kîºG,5NóÒ))7òˆ éveAÙë1¥¯ÙDÓrÓ#nê­Ûº7ŽƒÖ®š¦>²WäN‡Í©;@PiÊ Ø‚õzœŽ’êxöe‡eˆÃ¸N¬øÁsøÆZ¯Y×ÖÁÅ®êJ¡1ˆäÙ/îßxn¤Cj:§àüYÇb¥y5vÄ¢mð\Ú¬ƒ\×E׺q#Æ5Òz‰ –îèaÌâxÎ@rrôsu(ƒ•V€Ôø$P i‰<"å*Tš`'¥ÌÕ4«2UXQ¼ãœ»X½/Ÿ˜S†of¹Ç3ãÇ/nö{#”Öì/ŽV^º֮»}n¸'b–.W{vìãyó2U¿\ÓýÝzâçfûýêíž4ý‰[Ü}d•·"³—§áËÖmMp„@å9…脇]kp'Ôcu!ׇùßú¼ÛŠ´pGèã‹ÜV(¨Æ.û9õûyM5ÕcV;˜wEê²­ õð¼d¶2ïíŽ9MÖ‚a_ò Âq|Ýd˜ø#Ϭy8"T¶ùÈy7wcÀYûGYà‰i·!œÆFŸßæ®KÚ¬8Ërj${7¿†˜ãt—r:ÕœØ *ÔrNõWÍà—Äå‘Ü*GÁ.h„·>s^<>»Ådžsx®#L©xWüUã… ýä¼¥OeZûz²Œåj/hט¯¸ùáúËóõM†óéú'¢ÔïÖíÄ^ȚЮK4ÖL­â,§=Ñ„`ãîñÌeXÇmõ ÁZ«ÜJ/|ó׉ð !>“]Âj'Bö&Âu—Iâ¸ï/ˆ`˜2× Iðý9MÎx>(gÄ^$¿?«ÿÆR=WN™]/ªKõ·øëzm¹Ë_6¥Ý|åèË—ˆïÕ%Ÿ$¹§[p užõ¾i§QîùdIÆóSÕ)jo£ŒC¾jp$³Þ£6;v¶wzÔà?|òy=Ëos^Ÿ‡=ã|¿„b]§óË·ÌhhtðË!Õ]t±+æ¯Ä(ÌÑéc#¼œÜЊ`ù.VÎvlòÅ9—ÞËõ€µ“+ßý*>=ŽJáá¤ùô6/«`Γ:¦ WmðÙgzçÍ:{0eÊ“·ãÌT?‹„áŠìø& òZ‡ìxÌ'y¥mEv{°½ìæ3EfŸI²õx‚—ý¯¼cæ¨yÇ[TÖÜÕ)®%áó)îvrii}5<²ú8·»øÍ •Äüàp«A¾á¹ss×µå7-ÓfyÓU†Þå Ï&Dò‡H.ÞªÞ…ÊÌx }НZ‚ú=íˆÿÈŒü&Ùœ5’ÕSCÑÚƒô«ÈO7õ<ϪðQ›‹3§Â”‘Çû_B[''ŒTË£NB<Ù¦ñãÇ3æàrDdRx1k Ž·,ò\ör·!ÖµCîiÞpõ¼ÃLXóíIïa=(/p>{´öÂÌuC‚ãkjª¼Gm>/¨üïuå 'ˆ‡€_U[޹çùZ“Tx€Ÿ_:2¾®6äM?ñÇ÷Õ¢W7³ÊŽ@F¦"xí'¢t¸ÿìã9¿‡ÝýµŽÚÒà‰(( àô;ÿ LÅìì'0urõ7‹D|c‘7=Ì—µÌ—ÎÇ W-$'c¶;¥qíÝ|Ù-Ðfuv³àÓ|gBªö‰ºiuЪ©M ß\¸L¡‘»Î[%±"6 >;^t«9åS_Ï8Ç30Ó8%±û&{]qÏ»ñ-¾õÄ»C ªôfÞº\`¶j—xu+—s¹ò»¢»#.¾žç{Ñ=—¥5§2¨ž§ƒahYç·öyãvŠ˜êüwŽäxxByµBH4˜´+LýÝA{øŽË‰üB£ÊÖÛÏšõuuoŸoùD|áïÓi¶Ö9Þ¨Kúõÿ0Ö endstream endobj 633 0 obj <> stream xÚ•Ù’ÛÆñ=_G01G˜ ª<ةȥX•ÈÞ} S. .aá P«uåãÓ== ° µ®Ý*ÌÙÓ÷ÅàsÀƒþxø‚Cüp¼y—\1©tp„í-Xã‡ÿ„Š‰Í–s¡Â7[™Äá>ïËž†]{ʦè7ÿ½ÿgð{ÅeÀ9ËâØÂRÓ™ƒÅ¸‡ÕÙÝú0™¥ÁSg,Uæ‚Ê‚:Ð’¥‰›VÁ]ðóÊÓ!ûÈþøn¢™ÐÜ4b"ûÜé…[|-ûÁÒý?ú62 O|Dø —TXik8/¸uÌCÛ•¿çCÙ6´d"ÂoÞ%²=Êðù­}_Ä,NÍûwÏM{FX3^ûwxÂx 7£e3l¶1ñú×ýñWzlg¦ç®ÝÓæŸ?î6o×0°àxÊbiàýR —®qØ*ÿå˜eÊ?úØ ’”؀˕dK6àî±ího<¸t]ÑlD i˜÷}»Ù 8TæCñ@‹OåpZÀèÏæTq(wWî R^55LˆÃߊÃ`ÈÚ:J$C5ðÄ®•¼y <Ñ€tAÓÒí#¾_60/«^Áem©ƒ­C[Ÿ/ƒ¡»ÿ–bn‘…=kJ–¹3¹ÊH³, Ñ™‰rEIÆ8·g;+/¿i›íïE×2¢S¦1ÓÜ'ôßHÔSÙ£ÞJi1š8Rªp7לÈׄ¿·u ‚”@ê«4çC—±¶À`NŒÀ4 Ì,œ,ÓQÐŽy‘ÿX°–#õ’Û³kØÒ‡Bq¯@T}#]hÖ‚_‘vÿÐV—ºé Íeø¾!œüðñ§‰H‚ù¸±z±ß€š8'’†u>tå×5¼4gÊ©Ékx –Øm žÏéÓ¾ä!²U\³df¨9}Ù<^ªôX€¯³8ÀX†í‘ÖŒ¸ÌB÷Pt«’ˆºáë’È&¢Á:D,çSÛßr’Þ8´à¬y·h”ƒ–6ÑShiæ—¯eUæÝ3íHß´û¡»@ój·±Æ,Lg´“1w%3JQ)â@êo˜p t/ úœî7`òÏ8“Ûª"ÝFÒR— `U¸ýüWçÞ)Jÿò£tÖáCäfY‚ìqÊ" !"›§`Í£é:Þ´—fZ¤,ÁÀ"¦…¹µ WÕœ µÐ¦x®M£Ùü¶ªŽL»ý­ {4"`ÿV$Iø7ü¤WЉ¥ ïWðÉ0\:t¶BðpEѺG`±£ìûÌR {3; bd=/C¤$÷WÈc²'Þ®<º«M€pŠ›cOVÖ€IÎô‚ö9/¥ò-[¦NóÒðÒXÍ¢©3]£éÎÎÞ0]Ȳ^oºRfÎtìhº4Y˜®Á ¥KžµâòÌúÞ®j…RL‰„„.õ¼¹8 I]⛹5tåcÙäͧ‡íLzXe e²`ÌÂL¸ÓKÐ%±„ññD#–´½%ñ!‹u<²XG‹ ÚKâa1œœ¼­/x 1F\³À,šx¹n‚qâ™ Èó† fòµ&è„&Y¢}¡UW6ßÃA~yÄTeeœ±J} &W$~ðE~°” x)Á…’Eã‘kÎ4¾•ƒxoü劊Œ/|CGvOK¦*c_KÔš–(«%p2¯*Z˜EP³c“¢-Ï `ôå1‹§[)"Ô-5ê--!,™0_’#8nÏÍ œ*&Ô*Æ›U#|øæt×fú] mŠM;£ÃCPGúz/]qxJjÝrx DÞ”øù:‰½u®0¼x½’€ (RoDV0.1Kô²Ø°)Ó¾†Üfr+€¡xHâÛ¦0ÆüÎLê?êÍ磞š“žšÉROaÑè)|17µùNçÚ 6ß#……ÄKê« ©Ø"ßÃ{/*”w›³\Ô 5ªx{éi¡+ò¾5¸ƒ¾–}ëÜ…`˜ì1Í Å¡è{Âö ]ðíÛêËÆRaXÞÙ­ç~(jûU½èz] ÁsF· ƒ”¥Î·˜W@Fƒ$ÒÛg,Štø¥|°È 'Heš°tVDž mmß—û²šÈ•sÑXüÀ¨¬ÏP×Ù*ß™lSflÖJÃÈK1{ŸwªöºJl܇»¦íq•l‹ß.Žx2ºðᔸÄB]r©-]q…tho-+T¢t–S=±¸†RÌDºÀR—b¡H×…óéT€-9GÀWhR袶Œ ¡sçnâc,¯ÔŸPXŒ!qV~.{X+º6æ%‚18úX'°êD¯Sé)I¢ðµ¢.:›u Ó%±Ö>v€,GœÍÀk H¿1À\€ÊÕܽÑÇs‰xޤʠ(D!Æf —Í:!ƘCmÃB¼3š6ŸõF·mØ!cÖ ±ö=Ÿ%°ÿÉXzq¶àÉipÅÔÑ‹ÔE>]~‹š7-•¨“«‰ëNé©;E¥iGƒ@4ôUW¼àÝ©½TXyƒGhÚ«tô_Æpp”7–/x€¨…ȃi. mtÞ^e‰l¨™áõ*n »ý ŠròÆåÚ¦ aÁѵE)¢¢ *˜¬·üœN!>äúu›>|súS|ÂIb‚.RÜB”S>ȳW]b¼€ãl|`|}‘»cÄ©GT›TêËôBc‘< %©œ¯,ʶ¤|°¶Z+†Ûmp¢¸5I …Uùż¨ÌF;‘‹n.òX‹ðΖs{ÊʨQŠ hx¶’M‚“ï?¾§m7T"+wm,‹ÙÞþÖ­È+ůù-ä—ëÉãf~>WàȲq´ï±ËkšPÙ³Î?Ù@Œ³þÒY;8bùÎ'È·º¸)”é¯íâ*/ѺZÙ(å7k—^ »Kîw tÍÃx¡å"Ñ5è®A8× Vüÿó CGCpH Ä8÷\‰°³$¥Ø_8cʼyߊÎj8’ióc7An«ñ—™Ìå_1å_ «5Ñ ° ùBeŠð¿…]½»ì{p.XÝh¬ùoB¦¨âÙ£ŠñÕÖÚìÆM9»ö¡s΋?ò~cWÁ”éo?YœÎn±[} ·ˆ ÆV+'áÎþü§ÿëE6p endstream endobj 637 0 obj <> stream xÚ­Xێܸ}ÏWy’7W¤îÈS¼^‚õîzò” Žš=#¯.½¤ä™YäãSÅ"uénÏxƒÀ7/E²XuXuJÁobøÇƒBÀ_Ô]ðú&øî-OÎY•eÁÍæw>cUº¿±÷®ªPÓØôÊ­Ùèœs–à6”ßhy倢d¥p²ÎÀ†ýIÎÂiŸYØÎMs³|=i­úHá¸Ù›Ò˜!Ú‰2¬9ªƒUhdzœ‰~†€Mšñ$‰ÛædשºÙÇ<…¥v-Þª;ihŸ…ŸU=2ïQ‚÷/ï\Cß9äYUXç‚eáÇ<<žóe9®t‹®9FÀƒà+Ïp>_—_Ú fiŠ{c¨wÔCG­ýð Ç:yxÿgÚF}AkªžzÍÑí4Ò¯zlÌh^a' Ѽ88zmäéÔ6õJ0Ù–7=]c¶|'ñ¨'Í“p2¸IžºÝ ñ êx3!V°»=~"Õ®Á.eiædQóí¶%è‚ëS½E¡ynQ’­VòðDŰQ?Œn§~kÙ¶ËÞdP%/È©Õç™;&Ëù·¿,h¬=ßÂuv%`•K\œà«G-Iî…ý+ÁxWU>mH¬¥¼|! ”å3ºVk]+{׆(ÈዥЄ—wKSV$Û¨ú¶cßéл`HÑáH¿£×}Zc³̶¹'öaËv9„‹“n:Ù’¼Ïlã(@ ™ë0É–Z_¢ 1)³Ø•ø¯cé/jœt ž1çvl oŸ‘<*¡yŽJº—†ÜzKqK¹q3Õµ2æ8µíøHÀ®yqç¢. E¦wÿøéÓ¯ÿöæõ5Àm5L—w“fð®GÝ×BÃÊOþRy¨4M wñ×9›ûPNMÛHýDä-h˜QO5X^¶ûÈ^#^ RG7⺡Ò8KÒsÞ$Ù)š“æl꺮˜%Ž$ œ{pëšþlýó™åk^J/}|ÿã»—½´ÅÑì%ÔÈÝÚ4ýÝÔJí"dÆ3]Ó9\€$Y âLÝÀâ7cêû?¾ùhÛ´í®úCƒ/AYLá¬}Ñ)bn4õNèwùÃFâ .‚=îÛÒ¶3Î v`¢œIkò2iÅq¹°V×¶®Î¹=^l]µÉW[—Vª·^I¹­§fïð ‰2¬Xq”ÄὂþŠC)åÏoâÈvˆ"ŠÙ#(RAwsä*ë”D6]þ16€U’ê’Nc˜Nö¼ÿO=¨_pé÷G “ãE¼¼ä0DvJ3!­ ûy2#I¬8nAœZ §+€ÓÙ8›/QõY¾q–Ä ]¹à.) dó«hª5€|§áïJ˜X0àtýÐõ “®ã”•‡Lu‰“Êã¤Ê6­"œÀÅ<4aDŽôÛ*i\sèk:‹/gø‹[åôÊo›„ÐýŽ4!?tè)gõœûÿyŠ2 o ›W8NÎJÏõˆµÄéR ]Xg;%{CMÀ 6$£8²uœÀ8†}­ ŽÉ ¡Ð0aCöwÊmи=ÝÑÙrtê¯#‡P¾ÙÚ`o£2 >Ç=ÊîÔªWÔ£hË}AaS³¨@7¥gêÂ]†ô4Lƒ{<Òl§Æû¨'}‰R”!æ2{õ@s³ V°ˆ0}×ЅͲæiQ¹hc³&v/ÐØx>{ ì â–;B††<|íæ»®ä…·–•"|ß_^’¸õ%ÔÒ(×ZFxÇóÅñüsÂ×ßÜË‹3m°4Ÿw.(¡ü6(¹1Ë£V»ñç¢ÓæF¤:~¤¯ ÌÔˆ¾¸s-ñM§`˜©K-O€gë§ýÁ•T3C0ÞaÚD­jE£³äŒÊ˸XWÚX·¦'©…T23d¥- žÉ½Ýj” ™¥½>àyÒð2Ï qWÜ@ÝþD`6d£¬édïÀŸBVDc?1çwÔ²Ñ&d]¹&9λ‚oûÃn€@”ЀÒzЈÛB¤Hù´x)Ú‚BM0æ)À­w—Pw±¢ÁÚõËz«)ÙØ/GÐõ9@„s3dQê²0»w‹pžT„ÁçRjÄ7ÿÖ~õ™‚ÔI\TÁSàB~¦y ˆ…¡SÆêî7©Ìø2Só™÷¸” BÈ@Ú>¸¯\zl”al ›ãgd’’½˜ûk&™¦¢´D’Á/Èä¬JÎ>m‘l"UžÓ‡0–ŸËñcíê3ƒÅ|ì¶ß,pÀa@¸êL`Ž -íÑ£VÂáQ$.˜ ÌÅ>žÔ™n+Ì•f¥-ÍptSI┈ù\"¢[„ýŠâ¦ à”Ú¯ªÍ«‹·5ÄÚ÷ˆ-’©<%vËãÄËþü§ÿÙ0­ endstream endobj 640 0 obj <> stream xÚÅXÛnã6}ïWû$1+^$QèÛn»ÚE±‹MŸš"m:V+[^IŽ»E?¾3R·(vzŠ05‘ùœ9Tð)àAfVïuh‡Ó>YU –¦Ýª:aúÊ¢ ­¹Ú®ÁË2Ã?é§6m]˜Ç…ŒBt]ªºàÁä4x ZÃ@ò°­«’Ôyï1#—EÔ[Òö"f±¶ûü|¨Ž¸þÈÇÃWxʸÆÔLsûÎcU@Èbòó=xåOqgŸŽuµ¢¹/ßßôJtL+ûöw‹¯çŒó[ÿ¤Ýé‰PíiŸ–„/ºNÝÒñ¥¢ƒ ÊxPtÞü™õSÅ"éT}X #Mƒ›(ëy‘8Ï£ ÷¼=9$û® &«òÚš—„§sEE”P%ØÆÇü°ñ…æŽ ÍeŠEIå…Ceuã3†ÓLµ¼i*ûîºÈ»¢;íŽÞèVi¨ìͺ¸‹¸òŠØÒ¸µ1ŽÃ_ͺ¥ê|Š7§ºÝ ð…áã^ÈËzŸ«-þ:ãq0r'j Ù*X÷á “¡Y8.nr.ÖË,!ìl •f«5m}Z·§Ú@ …Ї1D£:s;ëæ6F°d™Æ Ó~fk‘0h+´5E¶*ÈmH¥Ã¶b™ß.4x­&iŽ?"^”6Dö©¯+@ã/…Ýáæ½A|‰·2–ø²hŒ!ƒ ÷fbødó E‰Ý`’çh@s¡6A?qF‡IÌï®Ý4§UI as€C« Ó–Ž€Ú¼q¤‚t8ÕT6Uc%±s¾¯Nu”8_'/D%hs™?yãö@ÇŸ‘TËmUn0eÒ4|[ÔM{Cá° T‰<$D”ìÍËDzX{¼Tüä8‘œ‰l j¹GœCqH€aÁ£ ^ù‚W<µþP<£:O=l‚â°ÎQÁ¡#̬ÐÐÏôzAè`êC^’ä»wï 7œgv•ŠF°ËµgöÑðˆ²6_Dg’I¢ª1¢>ƒzÔ€C sCãqj ÄºÂ7.ŽŸö„ÊV] ®ð8ÅÆ*8Œ®Is®¨°­ÜD›Ö°P^nš©ÞÞKÀ°ôççóè âùÂŒÏçØóÎL'Ç Hç¶ èjÚl\$,²€ˆ‚œ ÑɦÚû}†9†S}Ž]f“R€ùºã“ñu>‰oÝ3J÷|…SöiæX%G’Ò¯­c&õÕµZní'ìr¼Ò»ì?ç–´ÿ? —2…ÔÊfÈes\‚‰xïøx¦pùr§‡<ór/ëèGŸÓ m1Ne1a™q¿‡;éi’Žâh…ÓŸiÚ± ‡£(!E=8ÎÒñN DQ2,y °IF¤5F¤-œâ ‡ÓnŽ€.áp8I8»Ä”¢¢(êh•§¥ž¢>úëtõGs†5@gÔµbêâ*NÜÖq2i_ 1j_ ÐìªS¹¡±»P{ņ:L 2âoîÞ¹¿2Ž˜x-‹™öj7t6B0Ï`£«3’ ;}žÍ¤cÏÑØÁ°§±zHcU,ˆÆêÈÒXai,Jíñ倯¢pDcqšb } ®t+‘h¦äuWÓdHcqoôôœãÎ9*ŠX<¢¥wwožï-¯i ¨—¶kŸ/Q èzÑõp“+®OpI‡ùíæ.t?ÂÌl˜ Æý†?þôîÝ܆pµá}¢áZ…ÛvEðèÛ='BŸ|FÞ‹Fåƒ _ðJm°3Ú!4|"¡@“ù”v¦¨Éé³ÍO¥ûÕWñíþ ãm€\¡‰‰èÁš®â ÷$‘“ƒ&||PPp7ïĦKä¥v"´b<}q?IüwE·¶˜°«Ä’Hö^HGÜÞÑ®ˆwh&¡t‡ß@Pu¤?AÒ‚!|â³½Á«XotËG‘[@Ó¹TÉôèâ'T™6ª—]œº«6#þ{»säžôéƒid‰'5RN¼…«ÜÆþ7úœYã´½ÚìàáUQ-µ\¸²ßŒ¾­®ó“­ áŠFDþ+-¬~²˜æ…µïó®}GFÛ M^Óì;—UƒÎ+š®õ´ ï°ßõE5þÖ1çZ•`Rü­¶3æÖc̰jËÄS)¯ûá‹¿Ž™3ð endstream endobj 643 0 obj <> stream xÚÍYësܶÿÞ¿‚Ÿ:‘_o ú½ñúU&WåÏ/ÿ7Ê_™l°Å¦IÂ@Z7šÒÑ ·„kꡌ?_võtû_žðò_ÿ'¼¬¨ÛÈ}ç@|Èñ°”&žŸîK`•)”¶bÐ8J0Ñyì¢b–ñ}ÔŸvØ„¥±å3I…/ŒN Ü«Øíê s?"±)±øŠ’H˜’¿º(Íù »¿)—ÕKðC8dzô”j¬ Ó¹$¤›Q‘Ì=F^pìø[L«kÉø¢×¶<',m×®?è¾.¢ö dËAm b ÷Ç ¸Ò‹É*à\™×Çu‰»È†+ìDY´Å÷ÐŽÏQhðÙ9-£¡K“ý0ZjÕ “I~y73’œ"¥3ÙnÃÙÑotv€üøâ€ýêÛ‡¦î œEó•}Övƒ;4U«7Sï!â4vpšª -]ì‡LY¢ß›U›nº­µkCž¹~ 8ÂàD.ÀóÓ”ÅÒÍOy¾ãJdzÀ ÇöÙö×£±ˆqŸï ájó}\‘ú¾k¼Ð5wTWló…”›ðEÿ£!bJy¬Æ Í|r}™ñëØà÷ .÷ÉùÏÞàØ%ÃÜÂyTù‘yB ·ÙHöEAð—#GŠ%Ÿi¶G‘XÔóƒø2!(jADbû$؈CEè÷vQð}ªœEsF›f¤,Oñ{b’8G‹›þƒïæLÇCªÉY5±,º Ãt;'…åQèø~%4¼P­á¦”ËÊPÆÁjÐYÛPÿIÛ8Ä)Ô@»{5Zå À¢í£ä –ªƒ[ÀL“¤6Ã$ôbÅmUW×ét½HðºH]u nîŽóƒ7Aÿ¦+Yn‘bT:ï& Kf%þâE@rŽÏ½APîƒìy•A£„vƒþ*“,Mádµ`KÕQjS‡ˆ7s Vq±ž“_SMg2UXißì%ÿX…ÍRå+±é 0+íÿ4à6Ôdº3œËŽÍ-#ã`dÊÊ– CÝ’kÛàäÄ—¾Ö­õFPvQ‚`Z‚è »2,[€\[­7fSçRWÁðá³k‡j£{4Î &@ºéÓLÍ ; +WÐ×£Mq{æ»íXqÆ jï=ÙK`úšœPþâì GPÂ%¢{Ï–ˆ/cï–ò )9•³îÒ€q¬Â­É3äÀ¦ÖÚO›÷ŒdaÁ3"Ø\ Žñ*PúOß®×àS¯Í‹3|¥naÞz!hÐEog£àÜížåY2²9ÌtBÀíNdß»©Ý°ƒÿ:ææwHzØ9ó~ó‡_[  endstream endobj 646 0 obj <> stream xÚÍZYÛÈ~ϯà#…X û$¹ÙU]Ý<¤ÖÈ$@° «b±ºªëøŠ}ŒX”Â,Ê8üŸF›côÃ]ô‡W,‹XšiÝí"¦’BFk\ÐÑÝöqU÷«µâ*î†ýaõÏ»¿Àrö€,©€-ÒÞÇ[³+‡Cÿ#\°–*aÚQþù§¿[’ï¢Q"Šy Ácó @aä‹i› «ºJ•]xê±ütÍS³19+Íoù+P r”‡¶ù/úëïYú<ý¹üTKÈ~\3+&¢~Os›É5Ÿ_Èn¾óÔ ³ ÑOÜ0Í×8Áð†õû`†w“¾Ñ£õnEáIØ Ì1zJ¹+Èò”í©jú}:Tp…WåF¨È¡‚J¹TâÙg—Õ y \ðÀµ1xä ðkGˆ’"]×ÝP(«Ú$$ézs¢-Ç|·ƒá —ôg<àŸ¤Èȱ:·õ±*¬Ð4Fª?½¿dÄ ‹X<¿³lèÞò„çÑHt?î¡b ½RÌ2qXn”ûÌ\BMb{½¶8”íƒé|žŠ$×Ë Ï,,Œ©úÅߥÏH,ÍÜÎ>£ŠÉýƒ7K$ÂïCÅOSi‹YäŒÁÔþÒ+‹Ež@fyé¶Pìa‰cp йááÀÍeü@½óbÜ¥Ø@nx:“„Dã$܉Yææu`IF"ªUs_ç£`RÌÍ{6ªssÌwF6>a[&.™â~ã¶ ÐÄëÆlïW˜¨´:çcõ¥3º€³ËâCJ²/gJßÒ­W‡Ãö¶êßl¿.{}ˆzwYd*€ž`=pý1HÉÔ8¿–»fT*{ÊLéT“ßÎ]°4½Ra7ûcò,‹­q‡#Ft‡$1gh (·¤Jz ]²[ª+gY "Ëv4¹ñÎèŒfqÓŽ›¿6@cú’VîS&ïCàÈ#•O `›w“Ï«]u»ÚU³|†æãfO2nÊ1Óägµå²8ÔR ‹ù±´ æ•'œ?»/£ ª|åŠ ¾/“¥£/àØÓÔ‹LOýŠŒ @Üz¬lY22ƒÁ«U.â¦mÁùÿ}gÇÇCå8õ†4RWC¾³Î$æ•™6\#+ã‹FLý²kdÁ¨©Ÿý ˆ9¶ vM8;±B<[y3!¨ñ‚Xħn/^‹ñÏ®VG/]ßÐ’­vPÐMÙ:Òb¬›)ªÚ>OÓ~ Æƒ€„ж¥­¥»„òàK— Û Ÿv8Ø )ÇÛN64îíÖ= qŒµy¤K†v|ï©WeÝñ7ûoû‚ö¨ÐÁÑŒ½ãz,Çš¿°Í7j.{>PÔÆ&`ãÚ Ôð;» ¸eUßy"×ÇׇÄßs!…¿*½+;áSJiÍÂöݷÔᴽSD8nB)4½R(ÿ_ôt¸Ô»ˆó*Mø"ο¥J‡n”½äScÁÞô4ä}…ÂlG¼¿ê”M=yPá ­.+1¹é÷Wzæ €‘ËEÜÀ_vÙÂâÅ3a…}ÅÚ1.°)ÖòY¬åH]ë¡Ht6÷*þR‰¡•ÏB«ô¡÷ÎBëZ+LR—;ë9HvËí“Ä^-Šf˜ÚÒöœ•mU>PªÆõyG$h¡|º’·áËÌðo¨ëŽ…ÉHbQ…ºœ/Òèõ^¤7Jxû&'c×eæZ,8ºÖbÉ34Ùxi/;Ÿ2ÇBc-Á}86(˜²÷Ó/\í}ÎȤ8sÿy‰ûÙT¢¤,ÔàIT1A÷û8À™çò¯ “T|5°ó¶„šq†,Ä$¥ÕZø=edqKˆ?9äß|†âÚfR.÷±åC@…pìâ 2,%½Ô5ð’G‘Â}Â+ä•ðBXTb÷ër³ZÅáÎ7,ÁS’´W!‰”<ÉäIÜü$‘Ôþù¿„$2á27(Þ‰$Áy;~’)Ômõ––é£S\êÄg'Pð5\!ñ»ÇÓ¸‚OŸ;1IžÎq…•£¬i0¢wã £üb-Н®„ý÷N™}sg)O¹”§}ÊÓSÊÓ³”§cO/4Á‹LðbÆì;;<1´ÄKñyw×ÎÓ¡äršÊÉõe%ê*L•ý ÷ÉBkØ&Õ8Ø_¸…5ÀÄésÛ’ð®,öÍ nØN}`,¦þÆ7ì*Á üJ’ÂÃŒà†]šƒ rðàtÅpC€³pÔ[Ò‡¹žÃLžÁ |€à†5»["¸\\Û—Ñ¿„µªû¨ c!ÙB2Br_ž çaªHÝ»&2YraòÚa+ DŽ D\!Òƒq „Ès!…<!ùóAÈ2²‡{ŠåìZ‰?Î#%±¬ðókÝSÉ‹û…¸úb®|D–ßÙCq]apÖñ ŒÂºt vJÁ‘Át6\ÃÄÊfG6 +×ÄÁ°`gÇ:þ[†p.î½lM‰6WÔ±…¥º©×ø‰ª³ëÚÅ˱qïêíß0 ?OLgf%DzÕÿ‘ÒˆñéFdÖ4¥˜Qºþ9:šTÄÚµy·ÃÆ äö;Ãî_6"¹ÏLöU;ziWŒ­ZŽýlÏ‘Mšè `#4u=u\:ê¸vÔ•”ôåVgÞMµ^¸©v~鲡_ûU:ó=b¤ô×ÈŠô늱4~I3ºTsv[|ñªC1¥úTPm ê~Æ{–xO´Îµ„Ú «¡µ–¹+s´§ýåwÿ±ç- endstream endobj 653 0 obj <> stream xÚ½ZÝsÛ¸ï_¡GªµpÄ7Ø›>4mÓ»{h{±ßêN†–i›‰%ú(9NnúÇw ’  ŠÒ%ÓIfL‹Åb±?ìjñË‚/røÇVÀÿ|±Þ,Þ\-¾{Ëå‚sVh½¸ºƒï+ž³Â,®nÿ)&˜Y®8:»|Zþçê§Åß®¿,˜,Üâe¡ 攟`Íb³0’9Û —‹Ÿ Da‘ûjÿбÌÚ±3ÌÍñíiÛ›‡ª¼]®¤ÕÙéO[íÛºú´”yVá•í*útSîê=â´ª¥çz{×´›r_7[/âwoíWÈ \qEK Í´õK^~Ù6OÈ(l‡„Œ§pË8LÑšå4¥Þî—+Mê}šxïžöç¶¹¡¿ÿ×=ô䯗ߧD pÇ´ô üµÚ­Ûú)Ú‚ŠåѬP1ùjD¨&x,×'°è,u“·`Ú…ÏAØz—äc™.aà#™íDY‘A>®ë²ýBç'©¢“œdR3Ü0sξêÃlñíTs½ Ê >ÂûààwÖŽ,|¼H®˜›Qœ ŸÉ“VÊ(´·ÈGÿ ˶/õ®B)l‘Õè&vÊL1ìý˜'¸YOp_ã ãfð„ «âLv:þö&>²*Øônß>¯Aßå#ÌÊLš•ðúœ± Áxq PÌÄ1'Î`‘J8&’b4dá<2+;cV`àÇŒ¤]ÖùÄêùŒêEo—ëuöCÕV)NR£¹E2Ó± f6ž33²ñ>û@:³Ùóf èÆç/EàCsG¹§mâÁŠY¹½MoÏ:r ðÔ“>qœAd¶nŸ7Û0­ÞÒÇ~z”*%¥J3™*W\X 4QüK³Ù@VÇpsRÖ¼l6Õ¾ÞT˜ø ÐAa²òéé±^w^€\÷m¹¡Á¦ÄM~¡9Û Ó<¾Þ7ôæã¶A\ñB£—ÈÇ@þ@æ­ïë-z Ž®ãHïÞfƒ¯† ²ê„ïÏý ¿sÔ-€AlÖ 'É• ÿ–Ds_Bé*Ô<=^‚˜z&­p ™rOóý‰óîÈàaWn:òh¯$5Qùãçr˜V>ßãQu±rÚœò›[7[PAY, º¶þL¶‘à`´ü˜LûbˆQ+!Ä¢†ØòÇîC×Åwí}¸Òð> ˆ¤É„rÝ%ˆ‹a6Nìæ¸Q|vŸV€÷wùD$-Sد錮}Äe˜ Ó>gΜˆ‘ÿÑQ¸‘4p™L Ç„–©l¼³K’éOèÍíT§¸ tòi]€•Ìé"F7ï’ºÐ(þ¬.T¤‹Ë”ÔñcR#Ü-c]\Lh@ðo¥õ4 »ε†a]ðð%0öN6Bp :;ç9çYË×xŽúíž3þTOêuõ}B¡­ŒÇ 2g2\ã¦ÐD'ùU÷bDŠÃ½ØÇPªø@©`½Çâ„Te=Üáõ¢ï.’‰Jûò3| ¦sgËɳm³]eÕ3²ZÁ ~²JߥÁ'\—Dzªb$« ²\Î^#Ø„Ò+%cä…ÑôøJtY  \½½§WX‘Ö«[zn«öâŒhà‹ö(Dgß\¦“à(í[‹gÓ N?/è³c}†ýujÎÐi/¾K*¥ÔçU—å#Ä:ÀR(¨Ö+!^P(A¡ˆcI¡+çÞëåÚ’†¡ìÖnüíc€;òï0#_ÇÕ/>æ²n6ô©:܉d~ÏÂ¥À{Bff Û+QOõ¯~ùë%Á­D•Ô ¹CÌl$U$´›´J•–yçþÊÚœ›¬H8æ }Â+AZ`",ï»ä%¿§ÉkÔdiÈ"Î(¦*(BV^¢ ж£ºœYÃq†@ä¢z¦ë"Ç?MŒ°„¿#"×ÓX[|­éØÙ£Ð³¦£‹Û)ŽØÎéÙá2i<ü,ÛùxÞvU˜™JP(íŠqNÊW·n é«!Q©T·!ƒ½‰#…$>ØBº¦O§•´‚ŒÓ¨É1q¼¤ÕŸq½;ØïLK°¨z$^WBúÉ™gþÃÖKßf;hb* ^×71í|'衉IÙ&æ°È‘&fǘº…Çù4Ä”%óìåkžŒG¼9žÉ󈈸ßÔÛ¹) À±† ¯>wQú{¤ƒšªö‘Ø1uçuL‚%žn™¶ÍË{ÜÊ|×´>µkzF׎ /Jë˜B¤é‹Ä‡R§šz¨ÞöMS\‚´­t8‰Ô­Ï`8Ïô%l'ˆwH¥ú« °=(GÂljv#Èÿ_íF7Ûnt}TSvªÝØC°# 1{¼Ý(Ì,&zj6 Áª«¶³tÓ×…»IØãÜíHÅÍèªÄíÁI+Žul*ãב­’6ÀåS¦”ér”û&™a”Ä {ÞBæð}#.uÒڞУ’C¹µN¶¹ä Ä©}剶¦ Êt>mûŸ3P­¾t!ÃÏ\÷s2úñBÌ#ñãe¢Ž D™ ºoOãe7‰a7ÒÄH@ÙN3 ë‘€!$€ÜÑß ô5íœ~Ô«è"@,IÉßtØœ·÷®“îRŽ{ôòÕ¯-†šy_&¹8(ð'áüZµ {•¸™h[`K’¶³˜ Ã8ÎÚB[a K ãúa}h Æð @}¥5åß.ö«Pß<Û4­?lìËúÑ Ù*¼½|¾ÙUt¿:Rûˆ×T†)=ZT1ž®~ÄÓ´óI"švAâ<•÷Õ9ëc.²#F…™_¾P¾„ÍêÚ“±òWÈÈ胺ΔòMαb2 Í£jˆÔ‚ª!á1TáFwRÑÝ.05Q §ÖáoÜÕÊ›ÐÞÄOûAŽÛAŒÞ= ïžè\I7Ê>¤ã{ô[‡žzš´ïá‡w$½Q›X…6±ê€¾ŠÛÄX’ ä°>ö`!¨poÏmGûóïþr ó} endstream endobj 656 0 obj <> stream xÚíYÉrÜȽû+pDÛìrí(„‡¡í ‡-¼‰ E/ ©àh’šðÇ;³,Íj493¶ç0!…°eeeåòòe+ù1a …?,É8ü¥ÉfŸ\^%þ>K%9Í“«ø¼Ä\m?¦­÷û¢Z–víâÓÕ?AVŽd™"¹yC”°òWwÅb©”J›úЕUá×°ñZ“Á6(»»ÿ|[tŸ›úñ󺬶‘=òŒèÜ‹—­Ó¾ªÜµ¬á4Bˆ"ê÷¶èÔå°ÇטÕЩ½7îÚÔøí±½ˆæºÐÔ6ÖÁc1OÃ4c Tî-Ðl°ÀX 2g¦Î¸º„j‰k ÿpöXRá .z ÏM4 ŒÁVôІ-'…ÏS¤Eóí1àKUWK ÉÖˆàX=ô{Æ1ÇZr*\Sê}öSÑÔ$Òéè¸sý¯F޹N÷ûÈñ9¢øOÑ €;ö²xéÀ2—#?{`‰ÙÆ,ó;ŠÿÂ…ñ Õ û%??°à> ,îñÌÀ2lrÓ5«jBÿ¡‹ÍMÝìݸ{Äi`ÕlÝ<€kZü¾ê°"#\:ìózŽ/¤åO¸æ¡.·É·–žd÷Ûú`AïŸ>~z)Åÿ[Ñnšò~tŒóà'é<øøAow¬>ÔÀÂï}‡BŸ¶nëthœÖé’>s:¼ÓP ß_½ÿî_–ᢒA fƒÎI´õÎ%žWÛ…´ßÚ®ØG»/€_¦y Ž¥=É?‚Êî/'è’ 4aQ ì·”$›¡$0@…ª½ŒâÕ)Žpß8•è ¼6å“{ýœ\€'Wð¹_ÞúȼÈ<ØœTž\ÅÌûzÔyŠójNÙéêÆ“Jè5†dy àÌ¡úZ92ƒ#"°p‹Ež¹‡M½¿?À‰£¦2dèl&j@~øØR\%&–Úç`XSÞÞY†»¼óðÈÓ¶Ü­D8 W>.·*7€xfÜ|sö<ãe Eð¶€€ø­ûì ÜPÒc_žji>ø¦ö®>ì¶NýÚÑo·E Ê ÿÁ±}šî|¦Ùn£TÀ…jyúÈ>Evç|†XJ\§#ŽøK´érƒ¿ýûóúO 0§k”šÍO ýŒf3Ç0ÃOpv°05 i7Æå¼.žî&ª†”€·6­—¦‡¡½r¿–IÀ­Ä|÷'¬&f%«}á}Êì´:ò©M,¤ÇÉ(O…AÈo³DAž& ëÕyÂ×G'^ÁÜf?ƒ,(žá ëß W£SŒ+а÷vǹBOný”¸‚Ež•ýýè«_ßñÇ—#€t^ö„ÁB“% R K,pÚø+Ða`D¨)axöSž!†'"üO×UL‘Fæ´ìeNW6Ï7Ä<Ùýö&¡ ž2I gGdãìi䔸€-Ãií$“é /ª'!xo#åFÝb×°/kµŒ z3Zk^@2¨œ#ICå¾{ò“õäu;òƒúÕó_–,‚ (¾ € lHœgC™AŽyEóá'„3 ƒû/êÃ)ŒFü¿N}Ęúˆ“G,Rl©¥ÃDFM}÷‡ÿKýŽ! endstream endobj 659 0 obj <> stream xÚ­VßÛ6 ~ß_aìÉ.šeI¶ƒ=ív]±¡h¯»¼ÕÅÁç(‰6ÿH-»¹ûãG‰’ã¤ÆnCX¦(’â÷‘tð) A ?d üã j‚ÛMðã¯< 1YÇë`³ ¨ k¬Œ 6Ûá»6Z1¶e%Y8ô_ðuèàÉãp8HôÝ8¨V¢TÖ²q4nw;wîàT>›]Y ]}ÜüQÐxF’’&¬ áÉiÌãÌ Ëݶ>tc½EóOÑ*ÉCçBƒqé6T‹²º³U9¨®ÕÞu6ϧ„¦ÎöóúqÁ{’5u*7Æ0 I´¢iŠÌ?n–$9‰Åd¿yÙ¾Ù_ñ”“uÈ0"„Ý8d/—’Çgît³`LdÜí+ƒON.yZÔÆ&‚$™dF=jXA¡ïŒÆIÃEž#?@,ŸÕpeêL Z0´Ó½¤GOÆÝYú=˜D0ŸÃ¥+Ædºa{DR6Òå”R“‰YN-=2ObÕ^m°L( @m4w`{•%$ÁSœ$„R€œ&"Ü×GìS@Ø:NAš‘Ú€|d1™Þêà!x¿à`Òq>N£aÙ7ߨ¦1#°˜ŒÓø•¼d~¦åŒGHOÆÃ¿ÍC„EcëÑŠÇã÷¸ñæŸO¥V¾€æô^yÓPÂ"·¦¾´ÝÑkOé¼(ºŒP¸¥)a©ƒ è$0Ÿ'ãq<öåØwO¸õÃ}ý´‚3—–kwRW½:T—ØâšÞ¤¾1\áÀOá…2NI|•Íb\0Ÿæ$ñ ŤJ t5z°yåžúfalž˜`»ÜAXíII±ÓUªˆ)7]ÎHMj ¶ðÅfI„B¡`ÔªÝ#ó)Ï¿è&ÕØ÷®&MÇC9ŒÚ–,ca©µÚ·ØM9vú^àtÚ-.ª®›ÖI ºðœÒ7(ôÊñYժĩÂÏôÐÕ0öeïŸ#»½*ázºˆ°0`³íŒ‰°séém!Y Œªêq‹J!Ææh°Ýãë®4½F}éãÈ~Ä¥³lÊ¡Wϸ.Bµs|nqÈHLÛ99ôH=‘ÍAf"X94ÜE&0Α1ÀT5> S~¶#Џ½‡õֵ󉛸ð™ºB] ¸˜ûÝ\[“ƒìÕ:ŸÜ_™M'<*†d¡ââ9 H@n®üR-‰Ibµb»Ÿù!¿ñ.¿…Ž…‡Ò‘ÉÍwé«Jj½ëÚ1èèfTL#·d©p¡çÙ0FûúÍýã«ÛŸïn⽊Žó‰\œ9k/S`«ËZmí·AæiUB=¡žû çq‹Z)Ž[ذðq1ÁËâ¢\@€Ââ\.Ed¯ÏÙ„á¸âAr ¹§&›!n¦#£¾ÚZŽ4=Õ.Ûj¯ÎOÝÉž9w§G)9£ôðÛÛ×/£ä8ï¢8W*›nmúàX—=JOj8\ÅÊaÜÂMºþ/W¦µB¯ÕÀÈÿí/ïÞÞýѪº^U]»U¦äÖ¯"¾À¸áÜ }ÛuJ/Àå Ø¦\+†|ìåå¿ú"Ïá’)Ç™Nãµ×}ÿÝ?ð3Ÿ endstream endobj 662 0 obj <> stream xÚÅË’Û6ò¾_¡ËVQ !$»|°w“Ã\I<7ËåâHt†¶DNHjl§öã·Ô€zÄönÙU"°»ÑïÇ,þXÐE ÿèB2øŸ.6ûÅË›Å?«„‹|qó¶W4%ž·oX]®(e"y]íïwåçåŠË,é‹Û]YìKÛúª.»åÛ›/~º±)_PJt–9"%¹ö 5@³ä÷ݽÿêáZ->-2M”0½Ø/rN”ô¯»Åëůã!‡¤|Xæ,)v +ID]S"ÎB9èpýG€)œÏؙҌdù9ÐÁ)»m–œ&Ÿµ"ùåð¦ÙßúÒ³{ÉS yïrWN%ƒäýø³\ (S¨Vƒep½þR7÷]u$¹ð#* U‹•Ä~QÕýr•Yɽ+ŠÝ;@ø®m>­ÍÊ}ÛÜÚýüòÄ> _|<^¨êí›·nqÛ€nû Pß¼]/ŸEï`顊dÜô¯²Û´Õ}_5µ;/Bò3¢ExüÆð‰Jë¾™Ü0 ³xþøš:#©tÇ :‹£ð¨–LÁ‹õƒ‡Í¡mËOôv¡ ††/ë¤+ÍWyòúpÛ•›áÖÀP  ~9AÅRÀÈîò\%ï›v;$)§ ¶Ùz¹^ºŸîªÍ’åɾ¦°ïˆ^/훨ìî—+¦’¦Þvvµoð—%]³/íÊmÑ ³ø°Ì€mUÁâ¦ù^&å¦Z§T”[{î}qïÜÑû¢-öe_¶^@iÀñ4¼çǘHV"’ʰ`·³Wêž.WBð¤BIpžP H0Pæ ¬S&bT ½Swæc†&ivf½ªÝ~b¯aT{FóGŒ†gÑÇØR1ò%ƶœ¤žšUgA‡ÏÕ®*Ú/mˆË‘TÔ[» a劜º#úBíöý`iT"T.¯`çw’R«j£L&Ê_§Žò8ˑӹ Z†*m…¬Ô dxÆ‹@ÈJ¢ÍÎ:™¶<Á EÔÈŒ4a§—©çzi5èéúö°é-_Oy¨2"…èvW¶ec–žF LR~ß3``—ñ¢ãé 7÷Ú:]8àœšû7ª°³Ÿy“Ô¬4%L…Ò¨R†*i©{iœÚ4»Ã¾6~J@P´‹ƒ¡;§:MXÅ@»+÷ös³ä‚¾-saι‰Î>¾/6}ÓV&j˜mPèzkÈåçªx™¸iˆ5Α1†6¤ônd/€Ã·Üî±s×¼™ˆx³mé¾±q/ì˜T7õjø”Ol¼|D¶Ì ŽÄk}ö‡ F#4ÊðæDªY?©Kò'ž£PåœfDz3;Ìå~/#È$ªÓpâñ# ÂV%£^GÐÅpâù9Ï·NyÃ#e¥Ã F”w4Bà#q†ÁeNó‹üzdc~Ñ9~Ñ(Ói>R:çè5ývübq~‰ ø%¾?¿²à,ίì ~AFóÜþÈäi.ý†:oLðMwà(gëNe‚Ñ¡ób^:HI±]‚Ï6Æg†½¡jã7 f{bÒ…¨êßíº±¢Ã¾l1PAZ‚v-Ë„[ÿY‚ù˜7oÒX ;gÛ)Žú£’,MÃü7¥Aþ [&u‡ÅCÝ´[p¼îLw_´û1Eo×ýñ]cî³1yykH1©ÆÊ»fômDÐ\žÝ‚TžñtScÝ…veÃ!4ñ§‚êiê_O6ò¾=©Pà’N¤ƒˆæ(Έb* EK94¢úêU§Ü}Y*a÷™‹š@•NÒX'"•$Ó‘>‚œie0À(F¯èFÔÑ\OŠáÔéš);aÔx`°¼éÔP"V?ˆíPÐÁn[‚¨K«+–榵<ŠÄ—hPTÎÕ”?(@!G£gBYϰµÏH þÚÀ(4øš¶°mÃïó|ÔäX@ÖcærgÀ< —JK„Ã{‡­+ëÎ-§h[~Žwrt¤5Ù0|äYR‘ËvšO@Ý›©G3‹öIažŠmY7½oOXòA…^žN»5]útW™RœªÀh¥ F­N·Î††Ô`ßšájüŠœ‘ü¼s­¸¡?5ÓÇDáxdÈ™4°è´õfX‚)W±s» /Æ»Sã]áòoÈÉ)IéÄBLãû¡jÝî‹ítõ3nÑÞ¾ø&öKê ƒÄzI"³‘4´­ßŒyv—Ddzj$’§8“»f$2ˆºP2Êyì#Å£éÓè¼¥vƒ i@³q{ðÛûKÄÝlØIY˜àê‘Û˵u{’Ž=±QòPrã„u¾QuÜ sþËtƧM=1ú¯(_0u§ÙI†a–‰Ät 0n:ÏÞ˜Fÿ1:P–6{ä§È¯ ”ë…ÍÎà‹)s”vžÆ2;©®Ìu.þŽ9¾¬”Ÿè@DêÐ}‚À_øX‚99XKÛõèbµ†—|¸F‘Jóó±³ÅTWôÇä·,ã)â¤që#¤ØÎI¿ªï˜åcß±rSFï0pàhRt$‡ÎÏ ‡9£»„ö¾ ;‘¶•›7®Ó4³ pD(M‚Pû»Å‘ÜÞ0Ûx‚œ©1Gªâ]M·ë¢Á5&³Ãl®)á|Zžü¥nØ7ì¶òÙËq „É'ÖöCÇþ<2PEÑÄÓ@zQ)/å¬ê€CÁF—;Aœ CLR:Úæ\³Ò¯ukU(6˜™8B ÜTœS2ŸNPûÉà9e…EPVážÜ<û‰=ÔcµV¬09A›ìLo‡Ÿj«³QÐÏÏM‰ËÇH2’*ÀG ûÍähóHó4Ô° Ä{6 Šò©1]ýëôµõ½‘Q=ÀTHÔ3¤‹*7 CòäU<Ë1æ„’ ˆqÞœõ7W]”Å.z3ÇÌñžsºÆÍö‘ŽÄ|’WËUÆgºÐ¹§lómh6¦(§®&NÄ‘\ŽÝ­/d®~…Ò<9@¦í³ob]œŸBª‘³,yÝØsÖ/i1&øâc-¶{:»ôòæ·¯Ü7]jnû¢Šöú™ÖX,\Gòè7µ›-k1ÒWÕc¡‹í¨˜_ä9zÑ0ÊÎ)5÷x±õ>j°®OçÚ×|BËßc ’_0ùdL>éy+þF|¥¢Om…p}fþÃ27ҭ—>~Ö“¸í&éGõO,➪v†ù~ÑùJ§¶Þ ðOL¶…b:>§ oðtq vÜù¯åùc1_àîçb᜶y)^ å$FÕôfâ!Æ:o/÷•6ˆ—„LñÎ4ùiœëˆ=U#1þa‹"E6|>ãŽ?¹Ý“IýlòÇ¥‚™éÍ®ra¥OiêÏþú·ÿ(‘Ã× endstream endobj 665 0 obj <> stream xÚíË’ã¶ñž¯Ð‘JFÞ íòÁNœC.;;·ÕÖgÄÙ¡WÇ$5;ëÊǧ”@I[›¬íªÔLAênt7úÉÅ/ ¶ ðdžÃ?]ÜïßÝ.þú¹`”´XÜ>Àò _ôâvó:ûðXµÕòÍí?a£Ñ.A‰°7ý6PR\Ή1‡hiwüìwÄx a‹aCÝ¥Àˆ*$B@é–WýãrÅe‘Ý7ÛÃncE³æÁÍíʾ­_Ò;:GŒ‚q¢__g‚ëå ÕXSß/¹É<޵Ǽ^:Ú¶êžà%Ïšý¦sõ[Ý7ûÕ]Ùûú¼T2+Ûº¼ÛV8“¸¹\¢ OÎË)Û5áÒ²½˜=PN¨Y ;€Ú 2™—$"…G쎕Ô!¬˜ JÙ…ÛG{96Tívè˾nönŋƎה*T;s誛)ß•µÿ‰ã¡ïÜóÒ‚îÝb½ßÔ÷UR›¸QDœS'Cò  NsôTNÚ‹¸søM[¿«÷åÖmiÚ}±,á¹ LÇ,±$vHóüÀåNaQâ³<¼ÔÛºl?â+hÅ~ãæ»¾=Ü÷‡á{¬3Á÷·î:3±`ŒˆÒÞgà wèAp„/WŒq•½Û>…_ý² ¢Èª ¹´?€‹·[hAr^·‹W‹ŸÆMIõ¼Ô<ó<ˆ¡ç†ÈzÁˆ¼}Üä¡÷åÝ `û!3¦ˆÒ—@G»{G˜h{{œPYWïž¶Õ‹ßæåi·®³®òÔ¿:Ü­ÜÝfF  ŒîvWÝ;Ã&•WÁË\g·|[$L)ëI_/­3‘¹‰‰[‰T&r&Æ;DŸ]³«Ü(2Wø:u+Ø;¤ê¾^S&Á¸âQh|ˆ;$l¢ÂñJQ™=•m¹«úªMÙU¸¡&ØÍ÷ 1”‚P¿Z® ð£~p`™ß­âÀBªƒÃ¥\&½¶õä}8mö)0v)åÂËê–ñ¦H=r#â2¾—ÕÈeœ™‰fàh:?Ï(‡3(‚Èx\ƒD=YÖAX¬)¬+vG汈wé8'wé/`Ò(KJ‡s´à8+N9‘#\|ŒË䦀Rû$¯•Å+sî ƒÓK$ŽÄ+·Ñ ®¤c4&4)Š3ç/ˆàÃñ)£Þ\§œë¥Õ¤'ŽÎ#e‘9›ç™Dœc¸DKC°ná#Ç\ä')t>Ì¥ÂPøÁ=ÛfÉ!†ÆØVQ‡S–%ÿ~Fˆ0b"" ; ƒ="8GÂÌ ^d\N~~b)í6t³Ûjç¡ÇÕÙÏ`ö pDrçäpê'衼ï›68 šÛ@9å3Ÿ_}4Œ1ó]o<«^ê®w‘]äNåèN!ø Žé+ÆìWºÇ‘Ǹ–pk^¿ñ'±~wnuS9WSYWƒ›,ðìÚ{ŠIZƒ›&þ'e›Â±n¤sô²xç gN\°°ã¤}.ƒŒFÿÞ¨¯œŒ ÔqRN—p¦Ž 1Z¥—Øåéû.™çðú®wWî<¶®Úw~²ìE›êe®â*‹ë:¶y¯²šTX²czÊæÏÜ$c&8ƒ>_“æŠMµoú`îy‘Øb Ïò“ L}x¬1àÀᙎ6S6a¤g³‰¨ªÏ ŽGD¨é#Bpª/ÁË/ä*?_±DáydÉ™4·Ù´rhY‚M¸rëWA_¬egEŠwƒŸå‚áÇ‘Ájlwë¹nÝö£+²F®÷o¯ŸÞTX×Ü×èÖK’èˆÒØËþË^ÄîêF¨0ôl#”bþúF¨ÅÜN(™@9a'ÆQžtGÿ`Џ1‰4Û¢6<ûpˆt¡ßPß!g‘ÅÃÙ©ÅÚÞ =?Ÿh¦}ÕŠ£|(ŽÃ!r0]8_{;èˆÄo(‚éJ»yÊÇ6CÚ|wÍ/9`6ÆüÏåv†»MJ¡À0Áõb±®ü­Ù!»Ð!\¥[ß‚M:nl=OhlH^D‰ ZgÆ‹(ÐÂÙ²sχf»u 4Wö}ZçðÀ»ÒvýÍØ² Æ‰²jTÝ£ª¼ïQe?’—ü† !jÄÈ‹­…R‰+J g› àÓ†®›3i".8‡Á¡³æ‡ËÐA’3=!ðÑîr=ÙQ&ˆ±¡=BiÜsƒ]÷e¢p_n¤} P0<—çX>nòyH:·í¢Ó‰ãÖ§ËN’}:7ö7¯ë„’ƒ rgÀ´5`6ž:þ,ÏZŠ&Ý…ÿQ|–Ù/‡$X8ÿUØ‘O˜˜4áT¬—·«î%JƒÐÒÍ„tü†âšï&1‡OÑ:(,ª¥2(ƒûŠåÆmê1~‡L« ÕÝÂ}ö$‰b¡Û-O¹h —>•,®‰?ÌÚäô91AhÕ):Eè§¢K~ ؅~>Ƥ¡Âæü@ pæ‹ÔK,]LE7`üádº‰ƒE¥âò‘ùðÈ©ïŽuâ¨G@b3ñõä#¼‰Óç6‡]ién/˜ƒ°÷§?ýÛºð‹ endstream endobj 668 0 obj <> stream xÚÕZK“Û¸¾çWð*k!Ä“¤·öT²‡¼ÙõÜ,—‹#q<Ü’H™¤<3©üøtãA‚(jÖ›J¥ì*`n »¿˜èKD£þÑ(eð?‰¶‡è¯wÑŸMHžäÑݼ^cCEw»ñÓcÙ–«wÿ!šxRœš, 0(ÉS|-I’Á8D -ñ«•ðõäD©h¨ºʈ²JBCH*Íëuÿ¸Z‹ŒÇ§ºêW,_°Éâ¯+¦ârÛ7훂,%4µC¼»4##©úߘ±mö§Cmž›üñ¡èÛê9¨=³ÃWA%aܾßÄœä›Y­³\Äï3xÿXmmsê«Ú6Ž«5Ëâ²}hÚƒ1mÍ© <¯p"¥ðÇ»_þònµæ<‰ûiÜ·EÝáGÁÙ&ŠˆœÎg=¢y4H¥‰1µwÕá¸/Ÿmoq¿·ýΩø¼Iq©› AIJvAGí?€‹Ò¼4U¢1Öï O.5 ’¦ž¾*¬¥£ÂÍÊVÔ;ópêÊκÝy×-…u;àö?õE_5h7ËýM´æ #ó—¼"qnбÆpúºÒãõØÉ``óÉ4ªzWmË™Ÿáövv¥}ëô5mõ¹ª‹½kíÆF­“²øÞÚ×Y±ó[œž«}U´/ØÎC<îúö´íO­éëJÂ۶­Ñ=¯¿ß™TH9DÉÑ:¦Œ0ãØö„¯Ö”2ÞÝW_"‡,zŠdN2¡?Hdtˆ'Yêšûè}ôs@Á(d•LÇž2-4ŒO™",_RàIY °v°ApíRÿ¤§U7Ëçã¾ÚVýþÅ´;ØNðM¹­6 åÎôâ@ dV5õVuí´2Id¦µ¾©›cgÓãàkÿ#šbE÷*ÂMñ©jØnÒxûÓ0ÅOmó´Ñ]Ƕ¹7úçó0|²/ëó.ا>ÚÎ]sÒYŸ¿û7«ïƒ†ØIeDšàû[ÙmÛê¨ã)˜fsá‹ßa@2>fU$¾™’LÚ(¸°4Tqr’»\ïâÜäg­©7*EÜ«¼qiÜæì+:#Õß0CyB¥ÞKðÙ'H¬33„틘ú‰å©Âʆ±W>oË£ÍGzºEïžJ¶“ìbò‚poƒ‹Jà•MµÔÛ© >ÙÏÖvýk^wÇ¢íJ—P â“Â+jì˜R͵-ÊÙr(,2Áƽ·=6§ÏøÖfس)îaeŠÖt¡ÝoÃÙ ¼Î‘TOö9X˜[ÊÂX¿6… ²›Ô+jëÕóeÑƒì ¼A—j 0ävßÑP¤q’ŠQÇwaœ1ʲ%ì·ZÂo·„ÍX"_aÉ[(AJ?Á,D]B¹Ý1>xŸ°:4„DÄûû9&ô½too˜À÷Á,ĸs l`Šc3¡˜Éˆ{[é´)ZØßq0®XH,L~…h5¯úG÷­ÍoABB€=vumÒF¢ öŒ¤hK£uÛ˜ ÙIm«Rƒ©ÞÄO(c‹ò vb¾ Ï*×°H×¶€øæ-ð ;=¬§A®HI&µÈ_¤n&Íÿ„å)(¤Ño¯%°¥AärÀ½ºa &î‹m¹3ÏUm~÷ÆØ­$]sP‘á‚:€nôcÀ.,!€v -ÁĘšåZoB* êséiÌÒ!¢Ü>Äe$F„#2'o›+ŸÌu˜òâ\QÃÌ\…DB7Ñ1Izþ"Áýbda¸ÀhLS‹Ä?ÙX • ôÞîxŸ–MY™·Ï¹˜Ùç³hK#;ÿX–ñf4ÂC÷ÒõåÁ˜¡gª}µYAHñ„Å)!V²“G+ë~Ú÷…Û3ºËyšoÙ$«=ÃRzvø2ìy~æÄ`¯–€= œEÑ˳(1Áö"ˆ…=J ƒf&o@ùìie†åmجB3µb~¦ÀܽƒÙE|“GØÿGØ·{Ä'é·…ãO1ú"€ô,þ+fs¾JJÄ5RB„B¾ÀJ(Yt^¶xV-³‘&œã™-”_y*ë­îà3UYç»dîlxÕ°º×H~¶èõlÙë¯6Ñ+qhàfZ,¸«&þá0ž¬cϤ©ã:­ƒÉ8>eÌÙ˜ù…€2d3¿¸ BÞÑUÕ“3>–M|ë•Í+܆I<æ­zódʘT#ÊÂÞ®oZ„ø<”2®“d‡É)ÙÁ¶¦–Ry ?|ÙQÙpGpS ozÆw<«¥W¼ ~“ÃöÍü’;žJ* •¸Çd ‘¯d1<¥¯` ¸›²˜?iŒËÿ¡hìëh OÙ׺F¹üÉZž¬7ë“&Áë2v›@úrD7L9%yóÈxh>^ÿÁFÉ#ŽT eBzá°-_ÕÙ•ïÕüOÃjhf¡„Ÿ (f†%Ž%˜ /Á|Ž…½3á¥%5gîÂ:Π«`l<µÖ’c­±>Ãsx{¹Î¸B¸´+ŸR¿kúÒé(z§u¼$L|Ët†ÂOר^œ^»ÛMÕxoTÎhF²ë–pN8¿m°œ9m4¿ðÃù­pS»ãÀ³[@Ζs¯„þ¢c¢»ý 0ϯ^æ„¿â& ÂóA;™ÊôÐ(Š™6|Ä3xN£=å8mÚÏæ…Þ΀ ½ƒhÍ0癉×Äý‰<褳¶À&㕸Z|þ×|ÌœŸ!— ?Í)Ò‘ßϦl¹H2¯„…–'ÿ6júÇSÏ볺µýRÊœìÏø}EI€ endstream endobj 671 0 obj <> stream xÚíZKÛȾçWð¶RÖêmö“tË"ÙCI6;7Ë08ÚÃ…DŽIjí òãSÕÕ$›RS’1`1lVw=ººª¾¢’÷IšpøK+àŸ'»Còã]òÃO©LÒ”åZ'woáý&å,7ÉÝë•b’©õ&M…^½Û?­_ßý-ùë]ò>a2Ï’‰ÎY¦Ük’Cb$Ëìð¸O~I~Ž0˜ˆ<“¾-êîmÓΖO…`BOë§Â0‘_cPy»f¿ÞH«VÿÁ‹8ºÇòãÓ¾ÚUýþ™ž»'¸¦«rWmyªÊ…EއÚÉøÃO6ÁÕyŽü6C¡™¶Žá/ÏuóÔUÝ  NJ-K³d£5ã4¥ªûõF“ߌ¾®[7ôÔ6÷DðǾ ›qʾ¬O‡ªúáÕk?øÐï÷%ÝÿVì_½Þ®ÿÕƒdJ3¦¥“é/e·k«§¾j½U¨‚f¹ Éï‰rÕ6ǾªK?g¦·¶,ÓàdH¦i„Iž³<õô°-®ÊÉ;âÔKµêŠƒgÞ Yd…“ÛQõ7H(¸`Æ"–`³7}q¿ !8‡a=Z2t@˜õ¡êÁi€OùqW’ýÜcÿXôÃ]‰7jp+lèzOÁh!çˆðÜÊ];¯h঎càÌ0½ðÔÅ0©h;¿òok4ç®oZæôŠo¨²élQeE„5Žªàý¡ÀÅŸiú¨>ôÍñÝãZ˜UÜIˆSªž®œX­'/†õÑ<îJb‰UÓV諸Ø{¡ž»¾<Ьæ­Óh3¨4nMùþXì '%J]w`ãªÆ±¾{9ø]]†<íòq ‚XÊrëÂ(˜!Ó¥±ãÞŽ$ŽrÒèKä|Å9ͬ ¹¤±52$iFYÅ’¬‡s>–©ÜKñ}T…±u\áû¨*œI¿ÆKÈ!ÆÐÅ®^ÆÔjà¸d˜ìvÜ+­Piš_ÇhfÔW´Zl¾ÎO˜E:&ì5‹~ž Â%³òTK8ñn‰à˜\wpñM\üîà †ùÝÁ'\wp(T¥vÊІ;»|É ã)2f±TW-®fž)uáL ‹ž˜M„f3.ñ}]Šj’ávE>çÀ©ovàÀjòv«ÕñÂ×øz–ùìC¥.ëyÙ;lLÀp  ÍϵœWÁB®ËÀKW?bYM¦X”ñ S@U„˜,ä)°V”XI?Vûªh±²39Ô·êß¶*ýt/¢¦ýæfQ¾dó~¨‘EÔ¹¡=îúc[ìI­™H’­¶«§¶ìÊÚ•Ñ®ô‡Áª&zÂpƒ˜q_èÁÁG½ú þí:j Wè,VÌ].xu.BÁÀ†^p*¶ÇxTCøç¯ÄQÍ€’¢R ›3uó1Ž{§Û’ÌÁH:ÍìªÒco„>!2ÆO],äî|Œ^ Û(ÉÑ1 öDUp1DÇǶÁÇôˆ¿Ú¡àCQ#fâbå&e[íN‚w´+ûã@ XÉ]ë¦Þü»lš¸ iì8 3EÚë&¾6ˆýƒ@„󸇛v7¹2© ãiè¹ÀÌ=R*àOeVOûbç–€{<1xÝ“²;×2èb]TÁ6¥ 6WÒ×=¤brØëˆDì©ËPŒò•zc»žë€Ã¾¬c<4gf*¸Í±†`jØløÜ&«œÉ:Š|UVä° «Ò,s³¬.©8ú ÑÂr‘Õ@-®§ÈCgÅpìÖï=~ ûyïFt>Ñ­ð:ù9E–˜Ÿ/6D\Ä˦’{8v¥¦°7C3ïc¸Ž½ãzÙYïÝÙ-¶;¶­õDr_tƒ .è#“öÁ)šù6RæB+$‰n¡âOWwApõ݆¼£¡þ±u ÿPÒY C¿Ÿ8æ¬hÔÎ ²áÎ ¿-õˆ`Ùêí ßYwÌi34¡àåØI¢‚<·,5¡ |o)l½}¹)w¢ëL¹ÓwÕꇽ¼®°àS[ñJZ:`˜sÐ_Ý–l×Z(W@m âJ­7P¼j·”Y¹£ø1–E–ŒÛõyù£†E.w½Äµ¦@Ê´øß@é-—<&÷M­’^ž½™ÂŽàQ_´ÙÕÈnÝñºâÖ¤9nÑ_Dæ'{Ñ=•!NÿƇIœïáån€¸Ö øÊ{ÀÇpC¹mö¤°ã†5‘^AKÍm2ÉÅ¢Óxè.§²_h J},ëT!ذB€<¼„'ó©òºÔ Xv¸ãjò“Q,Ÿ”ñv]”Ðe#|3eað/÷j–Àãø <`hƒD]N0©¼‡|è;šS±e]±e°Ø¢Å%ËEx>‡ò˃–Ž’›+_BÂ;’͈©DÃÑ®oZ¬`ðň”ðÙΜ!%a†"†>£ Žt¬ q…O@J&gW’½ê¶"p[)ÔºìŽû¾ðõ£\}+Ç")¥¯×1PŸä' nçè»(2XÆ@<ÿT ôÙÂz 6"¬gB Ì®Vƒè9Ä B®PQ@*XžÁ¥4]‰¾æËá71>.%mF’ÕI‘Y,Bl”Θšõº:Ñ™?ÖpGeðÂ…$˜P™Îb.¾³2µç.ïhƯê°V[BD¬]¡¯‘»ÿô TÓ *`·uš¯þÞôåÀÂ7uxxz¦øáÁ@¸ŽñYöë0 »ðó@¯Q~¼ú Šá¹õ_Ë£?G0,è;Ät>añ]XηKÊ Úa'êø¹œž¦gàùöœèi¦n„0ÌÎ>«T ¨”šŒ„q<õA¾‰––ñ‹ H21œ†CYÔ”8Â^ïI«Äó¹…Dˆ¦ÙTAijÞXš‚4 H9¥È+‹Å¿jŒ?q©ãAšèÞkmêÒw-N~Õ#…E邜ù/w ºÛÒ“çÒ“õÃ-¿èI9ÇäEÚ™(óð bË)À}o–Ã=çÆ*8âÑôÂÎÀãÚñ€#rßWšxãÎÆŸ ÉuÖy "‘³ß÷ Q÷«ªOÌê9Þ‡µÀàS¯m)'¦XY+¶9vò56ûõÚÜ·1*ó?C‘íÏø/úÐO endstream endobj 674 0 obj <> stream xÚÕYYoäÆ~ϯà[8±†fŸ$×È‹“H` >ôf-§%Ñæ1&9+)ÈOUW7©¥‘à;Xayt³ªºÎ¯j¢_#¥ðE‡¿4ªÚèëËèËo˜ˆK ¥¢ËXß³4)ttyø)–‰HÔnÏWñmsÜ}¼üWôËè×(EÝGªHri?ÈtÔFZ$yæ›èÇèûƒe“crêöå‚'ªX(:Ñüåe“£¨åc¯1¸ý¼S2.‡)ŒÞýÒ•GÉ4M„ó¨¿rhRd6£%Í”èÜîø:äõ,áy4o9ç˜Ý¼D n½D‘—8Ž}ë4ÜõÝ~¶³ØHš †òm¥^ËT`¦å«øþè‚DwdÚzô<'r…ÎTfµ—µ· z·ª»'Žý’3]í>Xy¤¶‡æ2aÚÉT?ê÷¼ö‹µŸ9åÓŽ«'Âf"Ò¡@caB柷ü5¨s–(îDýu¼Ï^²øCˆ¢ÄÀ¦Ý_É©DäÞD©HCrgY@î'êËä"wÈö¹Är¶ò¾?Š!øÿ©!ø[ ±×:‘r­zS“¸ÚŠûì)|̱€†~?ò—lØþAlÈÆ6\Ëå¹7T`oq&˜8T|–àPôò¥èIÉçr&¥°)¯Ká»ÁDНú޶c~…Ê6<â#‹§ž–'"'fÄDô:O¯FÇaO9%»}–‰øßáî°Dã.›¹OPÏs[Æ#9y°Ìâ•JÃ0Dfׂڣ–Š š¿ämEÂõoªœÙ¦p¾ên„0ê¨3Öj´ðÁ©ÁšÅÄ ÃÀñ)+ãl1ƒs5>!@ìÆ8e2Mr„³ôR¾Ü^ i'äÍ닎/B,x¶„r€F ÄC*„ô÷wfp§ë½ýña¶fUxl Fðµ ¦ÐØÄ¤/Æõ^T—›¶â`D *ËÓCÝÔ%:4>nÜÖX»-.âª"ì®¹àØ‘¾, f|N{.r{b`>1˜-Õo¦Îb©ïF‚ýPšHåÖת§áTM§4ðDWà+Šå6¯ØGMòu€V=4#̾;Ø>FÚbÈÿ˜›ÜÑ5é·®j—m‚zeD~Oö¬ƒ±œ-¹sŽÂB­¢dœ£$´QïÞ…P£½„Øç¾% %cï‰Âg ‡7D!Ó§gCIQ`>[Yª†û1x*tgµ~€Onå¼c+74l‘û‘Ál°?t›¶1(»[úØø£<Òý ö]1¢žoŸÔÏ{3”]åØ^Åc[6 ­¹ 7ÖSýUlqOªníyl»\ØøÏŠ˜Í¹¬˜sÏMêHøAâJ“+̯ßÑ ŠP@¸¿_hìHþÓhaÜ]“(ö~š3D c“!f”g{ëÞ~©A| $ÎåéìLžØíÌ;þì\ãþ®myÛÕÓé`¨µ÷Ó¨L£”]0K+d_ó —úôiuÂ…e!ÔZ9úè-<Žô¼j¨eH¦·Qo¯â²ím™„åÉ54áà uðt²».Þ‚õ ¥‰w"ÁB½ :̼—úéŒ "ôc¦À“½Ñ †fhˆ¸,4}õîz:: èÓ¸0Y"쟃ª;&œ ô"†^”s|K<ßÑõöQúYƒ¡pm"óѧtßÙCƒes1Ïç£Îhú©MŸwËôr®b6¯ÇY¨•p}¿à÷‡xáÑ'€ÜiÎ3I`f¾™‰þ`çu㛇åB¾:,×i‹w Ëgœ–Áä9—™‡ /æE"|®9Bþ}=–ÑH2'­.ôõ¸SçÐ|‚—çÐL$€ç̬øÚ©¬;èÂ%K­ð«‰Þ›Æ´Ë˜^P´AnÁßqD–Ï;µA²)æÉlÊe0‘ò¥#\t¯ž >þ*IÎfã½R"þç ÖÒ‹¸<ü ˆ ¾ÉçH†]«Ÿ#àÉÆ*ʇ |~²_RÆb.íƒxÛ€åî0Çëà3Ê:|)ôueVe7ÃØÍÏmy0O~ÙÚ%` ¶LgÃøo}‹Ölé¡^eÔ£ôü%”šÕ€Ï"Sµ”½‚Lñ.[C,¡žŽí‘¿­åÀß‚h¯ßãÃj|ÀI§Ëþº;ž&º\@¯²pN,Ý›%¥O¢¨ê[øÞJ˜~›’èK–>ܼ’ë˜PK~Àdg ¾?Måõ'$Ö툶…øSº¯GtÄŽõD\I|ç™ÖoìÛß ìžCõ曳£È€Û'u/Éœ-x!Ùü̼…Ó¶äﵤIcÒïýþOÿ¦¦ü¿ endstream endobj 677 0 obj <> stream xÚÕËŽä¶ñž¯Ð-êx›¢$¹äa AØñÜÜ‹…VÒìh­–Ú’zgÖÈǧŠEJT§{FÁ¶ù(Vë]TôKÄ£þñ(ð—DÕ1úÓ]ôõw\Fœ³"M£»{Øßó„:º«Š“Lïöœ‹4þÐvoïþýõ.ú%b²È£Ç(-X®ÌLGÇHK–gnÚE?F?¬@–H}.»g˜ó‚+âB²BÞB¼YÄãÜLón/³4þýœà‡ÇÍx?ŒGZ1ÄÍh,çv ¡9‡}ý]!¾¤@{KA¤,Í …?÷Ãij'Ç>1åŸáãy´OS–Б¶–R’ç;¤þΰy0óÓ8¼§Ý?|ÿ† |×ôv©úi¾Ømûú§·Ï÷ëáü¾khü©ìYåIÎr²’,U>[*®ÛñÍó³Íi:ì¾ É„ ÿåÏ_š©Ûˆ²·ÐÊ—FÊ EàÒ€ß=™ëxÎsÛ7öÌF„š3^€]"üVh ¹bÊ‚²Ef•=!•,ž9«vXrj‡Ek.°xžÚþ-–=-5O§®­Ú¹ûLóÉ¢¯ÚCÂUS[lÃéèpoÜs¸A*}iRÆS{í@H娬í&ž9ªÝŸìñ)`®ãÜnâÇ €‚„–æ2øÛ3TÜ7U3M@ E‡ §±™¬- ÜÌ¡ž¶Œ¨paÑ*®­j£ÕÃŽöëæDºìëÉYýÐï­q! \U¹«N¡»îUÁD᛹»1‡|ÊÌ83è LâŸ!ÆP¹@|"Å…bEá+",\ˆM$Ü?±€[ 'ýD&†/Ü*–e†[º-‡8hL¤Fð[Dª p*Ô N!é•Ó¯‚ÿ‰ˆÿ‰ˆß.‘o Òš~²Å0/òw÷ú"‹—Ê¢)nÞ°úŸX¼$à>ÄÆ–ÕÈö2)X¦LU•p/U$~€‰‰í‰M¼ù&_À.-ܵápüLËó@ËóŠ’ê ³Úöe9NóD9³Ý^ë4þ×X·=&7„2˜Ïs“þ°´˜,ñ{ ±DÌÛÙ+’4{I{ ’ëþ¡n«OßT_ê©ïc‰ÈWíA¶…+nèÀ0þr¹ªJIÀ±)øÊq,Q🃷’‚åžç¨‰d¥V.[¾9|åû’ѶC¦^7­š)æËþ5_Ø5 ~¦ñÒ~ÙŒD-Ó>+ð‰ãY‡ ˆ G•ÇfnÆ«™BñXhÇ0«‹Ç\¤Ð‰À9è ¨}„ÝÖþz] Bß°~«õág‰ºÚû,Qw•”á…Ò9é£äOä‰>y̳”bJ‰ø+îZ°Dn¢lSöØÖHMm_¨DQkIöô¾EÅò7‹Ñ4JrÞl:[¯ lGZ¢D9œûÜF€ÄLOî›úlü'Õ€6îl[«¾¨Mß&©2¿}5b×Âù!>¶}{l5.oÿ^K,Ê=Á Ø Ás=®„Äãå“wܽù¤›a=Õ’$(5åú^N”¬*ÈKªÐÅu‹ÑâÕž.¥©ÿ€Š+.œOÖÈíE7ŠPŠ€ö„X«¤ƒ‘ *s¤×Þú²CO~&z³Š’Æ_Qz#ék?*Mnø¿ieH2Íi ù¿`ÎÊM% ñiËü¾7G†‡„Þ5cÙW–ì!žŽe×ў͌S;·Ÿ0–!Œ*Be 9Oâ‰bô.—&mdEÌ—X,9P@øJu$ÝígS^C§YêLª· ¸ÇŽø?OF¥)&KÊÏKbI Jå¾V—Á<É öîçö²ØÌøÕôsƒœK¯Ìþýd_ê†Érq,?ôí|®kIJ;‡êƒÉ=•ˆöš]е˺‹¥’N’U8jέL}ç^¦@Xïý§þû­âò8 ;àd¦ë"žç®¶ÁÊÜK#¯í"ôEÝr½|Oð™Î‹ž7š‰åQ C„¥dƒ±{¯Ã¨ ¸Ëg’òPæXʘ ;¨ŸñpƒOvxØ>¼Â>=¼B“0S‰‘+ÓÉåJĪ> stream xÚíYYÔF~ϯð£ÖûðÑŠòDxˆ‚°‘"e#äõ°3öb{våǧªw{§ç  DJHã¶«ªËu|]þ6zÑ(…4*üO£å&z|=zZFT.òè|š ×W¿Å‚ˆEB)ñ‹Oãn“îfl6Õz‘ðBÄU[­? Í€«,î»íØ´õ°øýüÇè‡sm›òˆR"³Ì)É¥5N¨2ŸÅoÖ7Vë]D¸,£»(“¤JAÈh圔…]®£WÑËÀNÈl¢<üXï§iIhᬃ„Ñcæ=)cÿ^ÆÝ¶½Ò1øSÿØmõb96· «uÔP‡y:ÝJÿ¶]›\VC³ÔËÛEÎâªoªËµöÿÑÓ"Âܤ}I¬3,#Y©œyõ¡ín0³øJ´ ´Œ’R­qÛ5àD¦3ðÚxýú}»P·núîR ¯«Ö®Ú¾oÖ ÔΗ°Õ,{~º0Lƒñ²ëûZ¾ˆ»öJÞï; ûÝ™–®¦¢»›—$/ùkÃü6`,[*ÑÙ#q¡$cb+]·b∫!íÔUT$RÊYb°M†±ß.Çm¯@Ý6bž‡ ÈÀz»i/º& ~=ïÆZk×Õh¯j“¾-¤¯ÅTÚž×£V˜¦$7(´¬˜î4-hÎè3-X©sÆm•ÍA?\®t}󱲆ùÌ0ë÷Í0êWIý·ø¹¶ëÑ„EŸ÷Þ`·¯+4 è5y8¹²êÖk]™¦R¹ 7,H†g.ÜVëmMÉãÉlw£LR½#^lšV0¸Ð}fp™ª÷`’9aƒºElêžá cQãî²r×Zn2`B—ÃØ¬Í¶}½©šÖÜ¿é­?,^Õ oÏû$ãD”~Û{©ÔI2½¯óŒX)‰°­””d{ÊÒOraœdD¤äSA…»ª¶ª¬ÑÙ\¹Tºá·jÍï»ÊÈÀ›6ÛO¥4%ìXJœË ˆ-¬_Ú¢#z«Ð{!ÆÐÒ2M©ö˜íñ˜«±õT{ðFòhæX§ó6ð…ïìŸYgö`ƒóqVá~å)4J¥—8?±œÆÍh.ü²c0(ã„Ñ#háÃÊÞq °T•7臫mϵÊU½ì±ù…Œ¦±åÕ;Z¸¿ñ¥:jëIÑÌ{W3§—kV¡’§©‰Ù~<³Iù.¨ÏÈtÖêpè7$…F\wôïk¹|Ž«êPª-@˜vO÷õ5W_+÷à›…á[ÐYg—¶³e¼©Þ¸„…ß ¤ûYZárž;Xë\Mðjø ¿ìüÝ,|Ã¥…oxìàîOð ×;ðͳ/ßÿøÞÞ˜)þob7ûŠÝÿCìõ9vƒ ¼p1ƒPX;ì.̸j ÂÃî‚;ì†k‡Ý Ò´v»Râ÷úŸíll¦æI1ˆÝâdìfŸ…Ý¿v³ÏÄîX ÷ñÏrïC}ùQÀä}ô4„ç‡_†9‡˜ûxÛgMÌ'¹±ÅlH— ‡òÒ}ˆ±\Ææ;Ü#@ðn5ìCz›ãç¿<{vô½ÕvM«mÎæ¦ÜL¾P"˜æ»Ö¯oûùÕ´«®ßx߃öS±íFûÜõ¶GöÒ¼\"³ay^vÏ Ð,ŽèÕëcL¯Ûç(Õk7˜XÜÃ;øbf‹e§èÞzµŸìEº¦À?jMú¦–ôµªPù²O|x4}Ôªÿ ÷+JŽ'Å~öwÙÕ«“È_ŲMò*…¹-HMe $"ÕT†s‚G•1îøÛÄÒÈ)) ?9×,­´ÜåÅÑÉ<§“ZNïÓiðµ¥ÀžìRÉJÕLx=Z{‡©d€}ÆO¦’9 ¨¡’Ñtˆî)ÒÌY Ó |ЉàüÇ=:Ô|à׫‹M€³®$<£ú¨ŸRjɼ{'Çt@œÆ$³ÿÊó•Iþ’L2d<ÿOPÉö€šO7jÊMr¡O'Js+ûò›¿ÅLÂ- endstream endobj 683 0 obj <> stream xÚíYëã4ÿÎ_Ñ©vbÇq’|àH  X$$!oê^s´IÉc÷×3ã±]§›îíÁNÝéâÇx<ãùÍ«·øcÁ üa‹œÃßdQí¯®Ÿ~%,‰Ë¤\\o,‹K±Xá‚\\¯‰~Ðý¸úå*MÓ¨ÝÐwØjˆH5j÷Ø×v{«–<î–¼ˆô„06ín×âî}ݼ¦¥½V Lâå¯×߀,ÄH@„"ÎR#BÕê ³T¡¬ióH‘E\Ð…‚gѾnê½ÚÑän™e‘ÚšˆP \öÄíírot5Ôw(¥%¬Úå •¹I˜¬jÝàÖp {"Ô@4÷ÛºZrmqšyÞªž„Ê¢~¨wV’NïUÝØõõ¢^+QÆœÎiœeFŸ†ã·;ûzªY»÷DFgŽÃ€:ξ ã…}šÕ¯®~ûöóŸg^®™%CsôîTíëíwòB’ Ìç_ˆ¶¶ª'&MK<, <:»TïëaVþ“,ÎXˆƒ;ÕÍÁ€Ë¸(¤ÒáN‚©»uÝ pb¤÷ø/¨ƒJt–jC_ÕØïøPïjÕ=Òô&b4Z'j €õ¸{Æ Ë8s8½Y:¹èÛÝX cçD¼‰ænÈe\>wãG.@3ÁŸ—8Ï ŒüRÏo†c1sÍ ‰85NÍ }¢²ˆgÍ@žœ´«ÀþáXÙ¶½Z޳+½¦õªí·¬*´çV°É¨¦XUDou×õ­h;6ö4`UtŽr«™Nß"¯GZ0Øìi¼;ܧ#k]uèžÈÌI£Sj3RñÆaòÐa¤s’Sûi‚ë[½Ž1àˆèëͬŸ€ ‡®³‘’#ågóÑ"füñ"‹ Gv9ÇGÆÒÝsÞ[3z+(ÚëÁž–"F2x)0^MBõY‹Xòðš¢D€ ›pjœ¾+Ê$"tš!‘‰ê–ÌFÆ gšÕ[µßõU£!žÇt€©#q)#Ç”[F>8´FPˆÆñ„ði<%q&'¹ÁçÒ¡Áòè gEÈÙxÍaáL¼Æ-ïJ45ØGž>“"ß “"Ñ1\…†âEŽz“,$‚Ü3â jI2xWÖÝvt<£w]o5EŸUÊd 2¯äk” rd>rؘŸfG:ãïÖù² \™Í@VϨ.r´Öó.Àã’…Ñø[߯ڽ¶YÓF”º «áBV z5v³¥yž'±˜<‡-GR™œÞ+¨¬-&hÁV0Ú´]EdÌeÕ$|*{Ú=•|â;YIn ;VDʺɑ] [§;U!ë ¢ gÐk+B¢ãH:Ÿšî^$#-po§ƒÒ´w»–ÌUj@‡’â÷w±õ-%aL¦€ê`@¯z\"0ŒE?nÛq·¦óM;<‘¡mžf‰µ†×@÷ä…}bL#/ü+áfhoÚó)ÎR º~Ü=®Mêx\{)ŽÁÍÌ:+Sýºi;¿ÚãzóT­Å*3¬õ°ÈÒ4ÛtÚŒ$øÎظ*,7b뵉¥|R$ÌM[Ä¢ƒjàil,+}Ó÷Î%ÄHH®_[ú½²))·êp ÕÚ%kᨱw’âÈ;áuO¢}Ê=¢!N臺úKrT“'`1ÌX¨^ϦepcÉ|49›ë&ù”»|V!WÁâ4}¿æÊÕ9ñÒ8uéþâeUÃ|bOÇdpÒóñùžÏžÆi·Ž ƒ½z°Ž “°çcäb“!åIÏ„g{¾”QÏgóáÏÓEºž†Çž&“ž/Éÿ¡žïâcéùFç`±áãÿ7|ÿ™†/ã¾áeP¶ÁÄ–mfYÑÏ-¦(…mø`Ç6|¢œ6|0?6|0QnuÚð'ßðeIÐðeÝ üˆ>þw¾‹Öðñ§á›Õ8Yp ÏXØïq0©)‰2WÁÀ•DžÔ—DÙII”MJ"˜aç€WÕØÝiµ–%¾ßã²Ón‘|<ì÷‡~PÕ°{´M_'bRR5'¿¨öjo«ÿ{ä­°z$\ÙÎñä5á-SùâZBY'šþ¢ Z[ºV?T’QÛL:>büžè§ÙDžúÇ3Ù$õp9úÁdÅ Û<Äŵ¹FÈè :x¨ªgß ‡Àý}éÈÙ˼w³8g‰À\ïbr. ¼§.üCèÂça^V“sÁRÖÃp’Gý¢dU£OPØÏϙDžËEßýtuõN©ÍuÆD8#¥%žÄùÄÓL1nC7´Y=0m³öqò¶Û«#ök_õXäö6J„Ö/¯Ÿþ7 ç&°®¤(ÌŒåŽöûOþïm– endstream endobj 687 0 obj <> stream xÚ•WYÛ6~ï¯òPÐAÌŠ)É úÐm‘¶’¬ûT Y–WB¬#’'ÿ¾s:ÖnÚ`™sÏØûè)χ?åÅüû^Vy/·Þ¿(/ðe…Þö×ë n¼íá/ñªHÛ!ïVë0Š„Yý½ý ¨#/Ð2NbKm`³!ê—]ZgÅ:­ëWç™~zû±xßœ‡²Î{ùyË'žÒ2Ô‘… üDa©Vk¥-^׫ÐC׎/çl(›z¢BO)¹1ÆÁ„1ìŒ2âϾ¬$6b(r^déé´O³U¨Ä<Ñ¢c9­®ÚS¾ÜøDVFn4 iߊŠÄ¯¼ýWo^¿ÅE,úæôiÄ‚Œ§ŒØ§}~`žHǾG»!1Û.#ÛÁy•h æa¤»ô jà¢mOe–’eˆµíš‡.­x34¤ÍÚ* BiØ:Øö”ÁÆ‚™Aü³EÓ´hü YÞ÷rµÖ:ÝËžIù«D: )îÀ§{þÂë*OkKÜùkRâÜçÝúï|¥G^ç@øÀ'Ö)ϘçR”l.RËŸkÄ„ÁpáL”н.ýûtàï§•1"íÊæl‘Zr@S‚¥À’tX5F8}Û…@˜žš®ŠJ’¬Î‰4áB:‰鬓h DØ$¢M{Š$wò·°—tx2W !ú¢9ŸL´'Ú×. Ó×¼qö™aÆä^>ŒP¤ýDt; Ž‹PN5°@ßòÃY‰>æ}îÒ—«Ñû_í¢{° Jn¨À(?–¼‚Íb~DMÜÈèxâyªÆR%À¤• 41}jJPÃ@86Íý>ívâáÔÞ]žóñÓí3^L”OËúØìV/nÔ‚µ}aòä¥È;W5²„PM‰è¹k4()QlI0‚‰-Øz~`xô ^bÐÝ…d‡t° ýÐA‰<ß–EåÖ¾4ê-62 ,˜%ˆ6³¤£—]ház -|ÿLqŠ+¬DzÞ÷ùÇsÎ*ð†{Ïd®:&–FÍ£év] ÅhŒcšå|d“¥Ç ¡ŠÙ[ê'FÆN/tî-_D“…¨š(¾ÀÏòôåÀ›kÇЩÍS"oì—«ôãÖ²”lc0Ì'Ç”õдà ùÀJA<º†,§#ÙB–Ó6GgaŸ¨RW±ÛPA³ã­’P4¶‘a6U”ÅLb—cô ß•r‹4®’Q¸&‡>¾ãrF¦°h¸˜J б¨DXTðj,*Ä7v=ƒ¥“#óWêûõ¨ÄñÕßwyÚÛß3K3%Zúf,‡¼ÏºÒvZ,ÙhÌ:€Ê7&£5ÛÙ­°7Fþ¢7 ~9¬Úò§üÉ쯎œ·e} &@#SVvZ›ÎåàGO†›Ä»``D¾’Ú« õBßrÛ“wç½³©j<°LœP¦Rk¤IPóŨǴ‘—ÈMD¿U$Íhá‡_Í~é@ÔP’ôÄ¡Áô®÷CÎ\ k™0 ÐW^ sg0îçÏ0gDV ÈD÷ö\ZTžŸ¶䤑Vä>M3nÛÌ5Es:ÐTçh[Z NÇG]S«)N‘M ¶[Œ8wëHóïX¥Gûî»Ô9Ó endstream endobj 692 0 obj <> stream xÚµXmoÛ6þ¾_aìËä.fEŠÔK‡ah»¶ËÖµYãoóÉ6ck•%W/IÛaÿ}w<Ò–l)(0 Š<Þ ï¹ç(O>LøÄ‡?>‰üû“Õnòl>yüRN¸Ï?™Ìoay†/ád¾þÝ[¥yž6I{?êýt&"Ok˜„a¬¼²À§ô𭦉J§õɤ4z–éj ›ßÓLU¶MVØå]Š+ŸèmÄž®nËjG3…^éºN++®š¬,j2×”ÖØMUæGÛÌ6ñL)O]æ-nžÎ‚ ðö•Ùì¡vf„¹b‰„ 1SÙ0Ç$燰p¼¢mk]_ÀDÀ½ûmfbÛâºëU¥kŠ£,Ö´ •\xwS¥¼´Êʶ¦:Ó2ÿC¯! å­ÝDæ…·¬Ò‚LÌÒb=[µV0Í7e•5ÛÉg»}®g&”™‹åüNÓið(ˆ/Ãcˆl–pðëå à˜îPTW`à¯QóªÊ–ƒ5I;=×í²Ö+{¼ »X¼3‡VÓ2ä“T'ÆûAÿ,D¾>O£µŸ—(}?–º)8‡$p.›¢4!$ÂB—’Àºs”]“N?´é 1¸9u;‹²¡A8æ`ni!Œ;((kËš `Ée-e 9RoË6·ŠjLâ§‘Vºi+ _D”yk0 üÝüá»ðÖ%7,A [[ÑRz/§±ðJ+¥?¦Ÿ'Æô‹9QN¸Aø,"_îÊ \VS[Þ,ÓjámòýMSiÓÊ{4¿ “„©¬¸-Óó”þ ‚*Fr‡ ’a¯Œï³fµ%2š•õ %qáÍÓ¾é,p_Au¦µõïÕë«›Ëgïž¾yþÓ“ƒ¡¨kˆQ|=oúH£ï¿³ÉŠOº‹'–®_¼~ñ|N–Îdÿ›¥µ¾MÛ¼Ñýø)wU€™42E€@†¶ÃÊ®ÉÙㇽ9;µÎå · áù†~¯g%úlT*è2¼ê3<ͤöyoê#·Ûݬ))x–Ë&ͬŽN÷ÁWpµK6¦O Ôº&7ÂÇé2¯­ e8B„Áå£äÓ«K°Úkz;2sLÌœXf6:3#i7 Ó}£+€Z¼ô&Ý9Øuði a}qnŒÕ•%ã1 µ¹%>úÓ¦µÇ!*b" ¸ÕUî@ú¥b±°bß°>%ÎY‚§h()H|&è¾¢gêœlŸ™óƒîÜ=¿HvZæ(è„b*²ýßœœÀ:´6_z›ŒøÕ®¥V„NW#:V4EYÙwš3öjü‘4£Îcg7¯5‰›ŽOkÚt|ÓÙCÓÙ‡¡–'­é—ѦÁìÉ$•#ÇúÞe‘5YšgŸ©$ÎÏÔ§]–kÝ8Pø]í1‹(^åÅg*±ëO¾·ª+ Y[Û! ŠÉЮ_¹u¸³$ÂU¤/R`þ€zÉ"“Ø xØÑw&)à¡+=äJ3ùP¬œq·n²,ýÃe¶Ÿ‘°ÄÕ^Šï0¹¡ôò¬n†J*aŠ[ñ…—1m2YPHNûÌÈ ì­-Mïu»J]âêÅôb0“‘:ºÿ…'ÝuÎFOº?9Ve@4iN8—¾`"é’‘E³a~t³{S’ŽªNð¾¹@Žc5pXýl€~\€@á$z²ä·}=˜Ðã+`/' ¸ï"ïÛü‰€ùµÉ‡tIƃcjñó ÉÞÜ?p„ùIèí²"ÛÙR…;­UƒQB“öãÿ'ÌÁòU4 ß÷‡b‚…âKbL?vb¼ š-FýH=¦ê…)GœI%X›»™rØ QŽLb‹»Xµ;PéÃ5~Î îÝ¥y«´GÑsøé |[¿!8”âg)ÄØîݧ3½/ÎÒ³¥]µOî3J 7ôÎŽ7y¹„‚3cº^”­ù¨õéjˆáàP僧ÜâF°8èàæÂ–|(QI§·zèÉvè©yWUèý¥‰ÁlÕ›Ïo¼´öu$®ücÁ °p„ÀÂQ3cvj©3.!­=ʶ©^#ÏNð%1Á$×–ÕÃ}–]6Añ‡Û¬tÅàÊTD}ø*Wƒ? '»uÈ‹½u¼zKÏù[bÞ„Ù\ª>Ýæ¬A8u¬^ ±?²‡‰;x(n@«è4opÕvG‰¿M½w ð’öàtâ ])1Á}ÏOÏËøª­*û Mÿ¾Û'As/ž…P^¦ðÄÉþöÕ¿¬ ; endstream endobj 695 0 obj <> stream xÚÅZKs㸾çW¨r¢ªÆ ñ75‡ì&›ÚÔl2É:§U´D¹¡I/Egæ×§¤@I¶Ç›²« ÐÝèþú¬~]‘Ud¥(üg«íýêÛëÕ¾ÏW$Kó,_]ß®ˆHs¾ºÂru½û9aéúŠË,ù©­?V͇õ*y÷uÒ­E–”uñ©è«¶Yÿçúo0¦Ë`* f¦Â)ÖT%¥H²`$Õ)Ïa<|ïP¹Ri®°&!+æ‰z÷>²¡)—««aР‘±äñ®Úâªwö±ÚÛ_Ãüv#ùðÌ“ö6FaYÊgÔ…kyÔu§¦ØÖ)Ó!û?Äg†9É7=Ç·L¡1ò}W8›Öþ>tÕ}Q[önËb_ÝÔ¥íÙ·õÁ³Î’þ®tBøë?ì›k÷«SL 9OïÊ>ÊTž á˜úrÌ”ÀÞ§1u³¾¢:)Bm£}èGÖZ#DòK¹í+§gfÐÇ5¼-êƒ{¼m»(É’§Z¿l#f è„F©J3ñ4M¸\hbj¼<Ú&£"ºÕõìJ7kÁ“rßÇÖ© Þ$÷USÝW_Œ=mÖ(pšÄå­Õ+pË—¸¯DH¸’\Íõ,Înžr5aw³v ³`0Sl½¢„¥D…šÀºþi-H²Û »ÙÔÅ—Ï¿·(»E”m›}ßᨢjúý9¨½À.? ]¦”·K23K53KšåÆ´Qºý) ã#9A‚'¶wE™Db»Ò6 Û¤Žo·Fâ í5…Ñ{|)`Ë«´Ä=#”dx ì÷ò:ûF¹o$ÀpoU³­»rçŸì¢Fjø¢íªUc§RÉ?¼·¯ºðú>&¶+ï­nk(»@¿QßRÉMwO<úN£©s›ÒºMjedдjë¢G&p§‹þ"?íh£^?ƒm;­‘ü‚Çn¿Ø9´ûSº'ó”œöì¾ÛÏÜìâ^’Å>ç¸; gôßÐÀ ·ÿµ6ŽÉØ;x‰&ÿÁÚ{]õŸŸiï4ƒ*/]B§Òµã—(û ÖaÄ`îœfIa>¢(ºª- qž…!'¹ ¹pdWþz¨:T|‚Ý0¿ƒgÇg9凲3s+mìªX”:Íè“1-Rá¡&~zL‘Ù)è‚Ñêej «ð²±ôûPØ&–1’mì/šŸ Д6p'ÒŒ˜iž Å ­’¼‰Å1ç9jÑ%Q“_{;ù4l0¡…ÛN þšŽª×†7Æ ©‹¯kÛÔÓ •KsêÂhì-ìWNÃû¾ì¦£rì·É ÞÛßÛöÐì9àÓŸú¶s;ÎAýµÙq»áFUp{·íýƒY¸mœ›Ú;hßÇ-))c'#²IœAõbT˜…ûÿÍÛè>*òKW{ð/Ás<&#LÌàY.ÄdÛCß»<ÔESž Ã0Ø`óÁ6 ß§ƒ7´ùc.w©vî›y|Á2º”ÐP.Q2å¬Öëgzâõ3:x}ä¡ز$(ƒ¼X­sDFãªHÊi¸<3§üOñýY~™ˆ¦Úå#~~ÆùkƒfF(§\ßZßÞlïPÎNÊ’ÚÈüŒ¦Ä›ìÍdÆ+žåÉG‡LQkrÀxhÀLhÀ”§,_ #Ð]Ãæ[Õ•„!ø±ü8<Èè¤"£mx€#ÇðŸ0<ÀÞ1ñσÌïŒ{¼k÷å°¤Køã1s–Rò<Ý;r3d9j0Ù)C(\Ž@;È×LÇ|që¶+¶èA¼ã¯šghZ¼¸N (¿ƒ‰Zškóþ»®¨Áä‡%Mùˆ žì7'!›I錺`³¦Ôý9F\f>Èí÷­%a Þ”òØø_‡He×>¢»–Ò˜afÌ0²ŠÐ©!—ŠI}’ºú¤ùÝ•6mª¶6%¤Æ$¨E5GÚ¡ëœo·/NK —ÃP6’/ÎöÉgdUF*ÁÕÚ–NI$fÏÆ@‡U)h,ðcLƒÏÖp1h±Ÿ,V!êÐä…) ScŠbL@r@ð©ÛÒ-~ƒBú1SeöÝ!hŒ@žjþäÀþ)Ù…qaC8º­CqùJ@‚µI¾_CHØv~sŠû¯LæD­sDê¯Ìȼb¤IoMH¢›®Æ2Ô7‘©`O*áo\œ+8NèîPs0 ‰ 26UA,NÄUèË\á)ÁŒ*ØÌŠ"»Õïѽ¾é† p‡U]‡ô–1-adT‚›Ó:¹Ë,g%[?¨MÇTTµó·˜¸*ˆ‡6kðMB<À3*ÜÞAãÀËsý;ðòàå'^xÀ¸?; ïàä4¤£XÍàð;Ãwì2!õ ¾ãˆsøP}¾Hà^É À+å^¹ú$6êé}\{SÒ)œÁ%Œg¸M/301ƒxX=€xXûÄnzáÅoˆðeÜzy€ðJX„§áÍî ¯õÂçYÊ_áA»&¶°„ðJ¾Â×IÍé^gáóR©Ê_ä B@t¶ï|(éETÀQÓ™’þŸà½¼ÞùïR˜Êe˜®ÆŸtʽ–¿‹#ôÈ„[f“,Ì4ì廘ÅcqÁv7º‹xÞKδ‡ùÈçb,¼ü¼†„S%· %0Οš´LfP©ÔOû#,&Ul.°)¦ŽäThY8×ß"(‡d*¨Tuå½±Ík—®g™¯‘Á‘IãȠ猷WËËu,·»îÛ®½·‹ «áX¬®öñ‚'MsvZ!½×Â2ƒ©lV¹rÅ&@MF3Ô¹ÝÇO?…}^öJRFƒÍóäÎK‚+®³D©°ÞÐ;N«µ€‹äÚ]!™Ÿˆó„Æ«¯Š £ÀC»ÙûîÐ\Pû×\íÐØ¬JíT•€!K*A˜LÕI c‘Ü àìáþÚã{wÖ;”‹B¦! m›Ò†Š³úŒ«[ãÖllÏ—sdë‰%K¥Õ2^üJÙüZNÈ\žR«&ÆâÔ^ccrˆ/ BÄ­æÞ«u{cæ4BðÔÂÙñ¥Œg]Aè•§`Î=.©ÅÃ~Æð‡8~ñôB‘Óˆõ@Ïw@yJü×öÔŽÚYˆQ,A^\âæ¨…eWÆ´ŒÛÕ³(áœzM™R¾ûÄÍ$©¿ÎÍ$5½™dâ5Ó¶Øû“3È©ù$[jo-fßbbÁ-¦P$¹]øóD"ô(þÛ^Öò!¬‰­ŠOÞ¸»>Âîg ?‚Pë†rs03âôµ©Yj96ªU˜BFä«3Œ·³g#šÕÉæÊ3±‡âgC"{4+“¢±¼ ىͱëøJô¤„+|¿™IÞŽšA©½Ó49ÁpWGÈôd³³±Ð/hX臱C¡rÿ—›rjæò¯*vÄI³1] „i&Ý8aç·¿Ö÷Ñà‚¾vŸmÖÔ¹ 1>z&|çߪcå óÙI޹A]…œcU©lö®i+Øj›ú³ë7¾°ˆ`‚ÃMߕ´½½Ã"?cc;veå˜~EUŠ¥Ä+ñ¶hŒqÖ»"Œl¯‰vôûm/€0ð P nüBˆáU`u¦“¿·}é ù¶¤ÏÇ’¾¸rAÈQIßÕ²¤p[/šr[î÷EW¡€'§£JwSWÎnêJÞnÁG£@ð­«Ud!WÝüÖù4&¯sð/×öÆüĨÀÜýJr{|EhæÇþówÿ‰A}Á endstream endobj 701 0 obj <> stream xÚÕYmsܶþÞ_ÁoáMM–x#€¤nk'–Ó´SÛú©îL¨;JÇé‘THžgúã» €$ÈãéN’홌=sÄb±À¾=»€‚Ÿ$ð’Âÿ$X—ÁËËàT:Ö) .¯*TÌy‘$–Áåæßáë‹Wß­h’$á_^¼üvE|ýùOÏÿ¸")|)ýõ7«ÿ\þRHNbh#b%ƒˆÅ’!/ÕãN!2¦)pñ˜Z¶Â°ñ8%ÁSœ¤Ñc|âqò–ÖÒ‡¬}äY>‹K{ˆ/¬“±"ADyœ¤†¬ 9¢qÊ35# $ê%¢ZZ~ç‘$iÌ5ÌÉXÛÀû—e h ÈÓˆç0Ê/´úmì#?í>SL‹ˆ 1@OÄTœðÕˆÖú¨&„‡j/—PB(øÑ1±[½O’Ô0B(jENÏ$ˇ0[29G2¨AÒXØݧŠ$cR Ž9õ˜Õĩ×èT…æ~J Jýôí’·‰ à#qj¹ZemªIú7ÀÅÒ8AxKb&fX˜.äq¢þtœ’cxF ×PßõÙËd¯&3"_">‘Óé—ÚèüåôÓí>Í#)b)!Bœ#f gùÅ$c 3Äüd=bÐ%8¥Za©G8M—òóÁô@ð;¦“øÈRƒdÔt‘úYx_]?è*¸͘ш`c#ƒr$À¯–Á.ø1xçškOAÑ„P³YÂxø=#ÒÏÌ9õ.W±äåâxÈÌP–µ¿[˜¯,sêíój1|SåÁȺwpÕØ.¦b™œ>ˆû1óBNCÝ×Ú¶Bó4!÷iÚAõ[b¤gœ¥¢ ð’:;¡5]òz ¼ «F.éƒ÷Ó«dl>p_NIU|&õ1gµà +¼ubsÁ[!x†¿¼G¬×Ö`8«‘nZ|GØ­tœ¾ô‘pLºÙ› ˆ„rr8rÀ²´Ç=ŒgÜ3E9¦j9‹£jÂdêkiÆÇ”t’ý±ð«ß$<‰–±Âòƒ+Kß/Õ‹q‰ÝI¹2&ÌkôÿºG"&é ™N|+“'b~rÒÔôÀÃ1~8ˆM¨•_ßì+\éáwæ2˜dn’!3€ºJ‡ñÌe0©SO²7^”l¶•0©¦ÇÌ Ž‘zÌýxÆ ô|±µ&ûG|šRë–&{ÒøñºŠ²ûö=K«óòÃ?Ó1Cãö+ŬÛÖe¾éCÿÐ%œ†Dë”}‚¾(nâUÄ9‰û}Q­ ñ0ÿ%+ow9XX_Ûßn›ÛÙ6Ïš5ª¼Å1 »&ÏãɾÚßW`'Ý#ë÷Õ¸[š„—+™†ySUÖuµ hJBØ9ü¹^J}N9~í]váfîi v¶-ÛÕJ€rm·°îcú.Çút£"üý‚“ ý–dIG8¶óïÃmšÒpµ¹ý2MIŠeñ«QþýÊÍ5‹JBW!ÉgÑòP=bR6é0YRj. È1‰S‘†eö‹§â3$jHFÙ✿s}›b®ŒõïS·M}µËË%‹`0÷>xÛ3Á v$µ]`² ‚²×|DZÍZ fVµýhvùMÞ A…×yÖW6)tØÖ»=*eB™…o@§æ®hsT‘§"OÂ]~ÊQ >"Ð.k»º\63.3"!-ðæi»üÖ¦¦°?EkÔe*›ï ¿íŠ nóxÜÓ»ž¥ùàC¾ÇTC4<ÑL޾¸+ºíâ>›Öû’[m14]Ša*ÝÀõü¤ˆ3 %=™lP¢¨·™Ù/ß¼])N!Z-ØW£k î1,6f´X1[E„]çHá0˜ƒÁ’ ^>‚_iÂÞT6š—uxÕdÕC}[T7H’C\iýú€ ?ʪM´ÞwV\¶»pé¶åŒí}ÃØî¯úH²YáÒnS|(6}Ä»°­mÜ;ƸïpönEUX÷&´ýçk÷ÑÜ8£ŽQˆ/ˆ|ж8wÐq1®»9,™pK2T´L¬ò;8¢ž-¤<'²ÉÎXÝu .ê쇱"üf»›Û5묲3W+€ÁÐ hòÛ&oùŒm€Õ`­¿ÍuÝ”³}Ür8¬¬;×DNÏ4XB‡wÛb(éÂ! öÎlvUl„MÊ;‘è›-ÿ" ³f% l—:—'†:7‘Åð†b®@ !Úl¤]á¨ÞW›%ôøX› *Až‰$µÍŒð›‰"Ŭ™ÍM"™™Þí¶Æü¸s0LµÉ̈Ê\]?_ØOINÃWY/šCªbiïnrË„Gá=à"Á? òÛ£ ˺†4jo­?«MëÖv]æ–Q…)”‰Hœ6è ÙjíçOÃa¾²Â2gÚÄ×ì§QæW¶ ”ð£­&c´Â̾µé ûXÕ&h?–õ¾Ý}ÄîÔ‚]ŸÊcOçŠÏë¿¿ý›ýʳ±µd¾Évßfè–«þ`Ѫ/]Ó–•A’ìvµ ‡rHÚ7ö«í²Nß~}´wŽðe ýðç¬ÿjw=^Ä@ŒÞ¼B<•‚,Ù,á54Épɲ¡l¡‘ŽÙ»j˜‰™qz¬…®e7uРómc—¬ó¼õÍ)}ïÿØzZß‘×3?©ªHñÑÄW•äEwyv=óÿ3;öaÊx®Ø¹þÄ5p}ÃîÎTÜ).ÏTУx>©¸Ç[õ×ÁÓÊCJÙ’òÇTNûËÖ §óm^-¹Ö­½²õ™ƒÐÎE½»&ž4¾-Ë3M0ò:ñî›ÓF cå8˃ßÏ3‚“X9XêU·PÙÝ#¢'X$ûÊ ›¬ÃãÀ%µíšýºÛ7nbR˜mrùë&%'lI/sðõ_tižß¶¶}«+“²0áe1ꮆ´vCN#àÅ€;Ò#ÅŠÖu¡oªu+‹P{ÌĽŸÙÅEç_=˜¦¬GXÞØÍ¯›ºœÝLœMàËYëFoåøàƒ ^Ì=J¸ÃʘcÿQTøÊ£Ü%‹´Àdzi·gYÓûÀÔu†ÐuDBÑ! (aY£»)Kۼʼá︭ý4Êšó™Â.×ú].2 u '‡ª‰3Cß‹ƒÂʨçè¶Yå¾\ë ­ù|'ãXJÂïë'·^hÀWTLŽ ÑfãÆêN’¾)n÷kdÀÈ…þ®¨.êa`\̙à ¸ŠÏ™mJ‚ñE ×0r”r{±!”ô¼ï~÷PϽ endstream endobj 704 0 obj <> stream xÚY[sã¶~ï¯Ð#5c³$äô©ÉlZ·ÛÌ6užâÎEA2kŠTHj½ûï{n AYÞv’±€Cà8—ï|Àn~ߤ›þK7VÁÿɦ>m~xÜüñ'³I“¸LÊÍãa“fqi6÷(È7ûߢ\Ó·÷&O¢zpÕäöØI#WÕ[e£gèeeÔõÛ{UD{ÇûϘžE0ºj˜Çã‡Á9n5#¨Æ±9v¬=‰*î›qjºzbá™ÖèÇfj¾ .¯¡ÃÎäŽn}Vmëáþýø78eœòÞSÇYFÇ/»ó°Í`ë»Ö`¡ÒFÐO"wp$w]M?ü©»œvÔDûʆ:‹‹ ,ŠïpÓiôúÜøó«ÜF§ ;ß°SD;ø¡Ó`ç2âÖY¬rbÙ(¬Îç¶©«©é;œ‡þ8T'îL=ÿŽl*W7Y£’ÑÕ05õ¥­xß÷²ÕÀäIKžTš=©´xè¹l›&Ñ£— ìý~â±A0à׺G;²Qßí)œHS/¿¬&‰ú¡96]Õ²&®˜Ç&dª"Åcßr ÁTI¡„òª}E1˜¸ˆ¾˜(IɇGΞToÒ4.QÛ5`QRœÅil¶÷iª²èÇ Ø ÛâI@‰5o|ÀÄÑ©²8cUlélÉz0ÞYè¾b€¼âî?>q#z¤X<ƒÈÊ¥÷Þ,º¶”èÀ‰~B˜ç¤‰¢…Cí:å0­MÊ`Øÿ »’å( ú?2’@ã/?ýçÍGBq>ʲè?ŽÀO‘6µe•¶qb%5íù3*¹áNLeØÓ–×›ž+Ñ øÒã._GÿÅqc•8Òg'Y@*. 6!Õ—‘l¯ýùÓ7†þ˜çFî¡Ktù[×nY3I£îÅXÞE:Éy&Å5L§ªÛWÞÅAjl a*ë,z8¬&Yœ>ñy6È ²|×O<1 pN§“ìq|/ÓT˜èZ~Äù1?ÒWÈ\ l“1Tê¥ÞVïz: <ÝtSžnø:³±ò!ñ'Ô›’=»áµžJi>•âPÅߪ“¾ØÃ$Q˜Ô&VEh‚U˜"Êì.M;1®ì¤$h­<(ñ \ùSÊgTgš´ÿÜOˆeæc•Z$ʃtéÊÌ( $„_.?8ÞoÇ”fQBÛÁqaLàˆI×xÐþ20g—‡ É Ÿ¥dPP߆‡CªM}قŪ¡é/# ΗÁS'¢'Š cÊecصÑÇO,\[}¥ÄÁ§ÆÚy&7ú vCÕ1†Á)h0`ÿTÇO[ê@.v{^ÕñJ÷šÏ4(ÈXo’à*Ÿ”•ºU$œOØ|Z ¸¸F~˜&ÉLä—ë" p¿†^GÁBC ³ož’TÓ¦ wz™EpCÓ—úŒZ¯¿=êO0äE(Àîku:·˜P¶€ e ÎÀÎ3u¾l¹Âã¤j¿oÐg¸¦a¢…ø•\˜aý¥Ûüx'1ƒiP4C€õ‘爓´—S7.›ÈyÉBÆp6‡AÕÑo·AMóèñ éG®)üðÃ莧¥3K;Å_Nô¬P¿®P0³×{”É=ÏåUlä,³HDo޳P <Lû+ÛŽü!‹Ç‚Ø£,Ð߯„ŒÐâpÁ/ †.›®°BÛdA!”!Œ_iÓ¡žÅ26½P+ ¿`ž©n¼ž”˦Öaù”Çɽ¨Á ø³›*¬­¦´ìN¾ÎFŽ-Î~h,x 5Þ†ÃÖ”ç1¡Ç…–ü€,Èœn–"·Ô3‰;¶PpÁÐÜ÷üËU<7A°óv@®ÃÍcd]øUxKn„·À¨Õjêzµµr_àòÀLØ ¼{#ßšÑõqšš8"ö½ƒá®x†Ü9¨‚úð}²®è)5ÓõLèú#Ç^ 3qãŒôCÿ¶ÿ/g{óT*¶¥ V^` ‚‹f¿ÍÔmÕ&S$ä9ò{=GÎ<_Ð9‰oltn«Î‰ ß4`c‰’S%~ÉhùRö±-N*$•AMHAî3“‰Ç¼/+ü[r}¥Ð´åL|C*ó™Îk“‹5 qt<ŠÁ€ÃW‚plÌ©cæ{!vd&8ŒÉü’ù:ãP0gkD8«“´®¨ó­ñnl‘ÅWH!!C‰®"_4B`ñê7fwaGÜEòÅ]–Üeè£ý¶ÖÅHòhsÍ£WÃÂãß`'ÞºXê¢ÖàyDWlÁ9I«Ÿ%Ü`'êÒ¿Õð¥¿Å[$=•IP<‡døZ]R¶^i[˜×Ê;ÃËèBlŸoï¡öÛ•»øú”ì#¨â€ýäu³Ti¬ÿ묹c)‡ L7Ž 5Þ$ Í ~8­C€û>0™¬ŒÓr¦\€éW}72&C&”‚ )'½õq.Ò]Uã£Ã ?:¬¯Kï —]^pÇ^ å…ïµÐé–,„/KÊDÄ߿ڬݬå\‹ QâoÜ|L*d‰Xco½îÞÑ¿¸ß/P4m½zh„o'Ô§pðyqû]t¡´7à~WÉb T€Q†‘9R<ÅôÌ­Ékáã°°žYnÝk‰K¯ôüüð¯?üøxcÏy›¹nxYЮïøee‹µÜÌ´²±AB(²ëØ€:àÛ>'|r þ¹ƒ€†á®1ɸ®—:½Ú „HÈDoò2’ ï̉G)UsͺòKn¿È lî {^J*ݨZúÂqýs,Šªzy‹Æm3ж=¹Ò» ´€^35ŽÏðé¸Á >=ÎoÔè.Ö'†½J˜é”Â1ÿë‘$|kúñ3ãs×ïo"ER,Ocwœ8T3a¥óÁfÑßÙ/Ç>´­˜¿V6t'¸pÙª·¼0æ´|§¬*öüú n<Wåž%¬®;H¯é RXš<€èJ"ïØ»kv,¾ »7õU|qw…o×x¡‡ J'y&ªèÌ/PŒj´Ë‹à À©c“w @œh“'àüïa°·öзün°Àw¦ùß5VábµüÃÆnú k?ßâ«IœxŽ»®rfÅ„ÁõjsŸæË©R~ì?ÿð_³ë¥ endstream endobj 709 0 obj <> stream xÚíYÝ㸠ï_aôÉ6>Û’üñx-ö¶[\oçææÐ‡N1ð$šÄ»ŽõÇdçþú’"eˉç£÷R´(v°‘(Š’¨)’ö¾z‘¿ÈKcø ½ÍÁûÓ÷ÝÒ‹Â sïæÁ‹TKo„Ä»ÙþÿYeÂoVk!#_;VM«±ûýžŦ/WqêkâªÊ®§‘[¿ t°ZË4ºàªAfœù[Ýoóp&ö¾-ê Nد‹z»¾öÔo†zË|­Ö·«³9›¢ªî 3ë -Ó6C_ÖzõÏ›¿Â©øp"PÊîP ë°ŠØ:”"‹ÒNîÌìï~ˆRWQ¡¢ Ô‰rvÕñ®lº»Zëïêf«yÆL³aÄÜpœ%‰qÄÑ™Àc«Ÿ˜§H™?àqWÞZÄq&pÞ,P°]믃6·—úдԀEŽ-^1(Pw]YϺeÝ-EɹÒb•Ô/»‰Mo‰v*û=µz+¥ÕE×ÔDÜXl,ªIÊ ·zúðãÕÝÇ«ë÷Wןöœ$TÌY>Ð:¼ ,2´­®q×=tÃ=¨á¾ÒbØtñ д ›ÏƒÑ!@åÞlT뚺®ô¦7§„ÞCÛHŒ(1·Ð7Û °5Ï*ûŽ?^1 uU|+ú²áEJ¯žÚ5ÉܒЧUœøº'L\ÜÛÇ-IØîH6U#ð‘d¶‰ù•Æ©œ®‡Ñl4!!º8h¸kÌh‘:²È2t4öù‚îe T÷2¡*¿˜S=cÈ}¹Û›Ùº6‹ ènÐc°ÂŒ‹Á[2ûCÍ=®”ò‹¶,`!ËÔÒo« J||Nž¼‡“¶0\Œ¨ÒÔÛ·EI´nÉPÃ×M”("ÿD®uK€x«Æyv~©yê\* #¬," Ûd§qžóMÉÚ©a}ÙNE-ÇN¯?ýýÃûŸ–í4víe#úi½ ýØoxœ7”Ï Ãæª‚8sÑ1Sn,Û4ȱå2v]“ŠSX­!zsìËCQ•ýhY.Ë5\ M%þgíX;rÜÀЫ»e7[»ïuK„~_Ô¶¥gñwÂ'lL) #ŒÇÀ±ï¯>2Ó „ÈýÒy÷Aewmsê– % RÁ¬ï–„­e¯cêžEvºG‘wuqXŒ$¢ ‘/‰M‚4wvhÅÝ£+\7íÂ0ùlȓљÜCad/ˆÍÔôî³ØŸDiÁ"0èÛ&”“bŠ Gƒn©*«ŠZsÝ®Ù{„2g ¤‡MF1ÜõÚ £üø‹€ & ˆ|“,ò?³ƒxà)l£`ü@Š=Ç’"^„l hîÈe4rÙHò|ûf¨8°˜¢–V÷C{éhÊOMë$h}û¢Ç:úƒõz4LdÁÃ#Ãh0Hœ ‡Ðuâ/ê]‡ŽÜ›‚ÙűÀûÎ Á½CÈ&unç´ï—lLª@º@ÛКûÏw°å×€¶ûGA¨ÎÄ¡=Ûòð{Ìë9yÛaqsûz£¼MS½mëT£ÇžÊv£aŒ”Æœ–O䢌2ܲžUİTd}æ¿“µCßÙ 749|£4ÅYÅ Ñt»ø=ïˆ 3sù¯=$›¡ÿïΤÿüëÍ>“þÿ3ò?úŒÈ$¹ÈÿN—±qæŠ§à‹±¨NrLú„"¢$Ânî²ۼˆÅ•Š|]÷ 0§(4¼€$ ¿µºz l¸ìé—’>d²¹Ã\`ðåÂüP5éX,•?éwk 7à»M5Ó' 0üaˆ|úÓÞí–jžÎ$27 L%) :%#&o"©^‚ì¦^r©5Î>ÍF­õ=YSÿXT°…[)|{À4V ²Ï²î—òöÐå³Äb¡žàæÚøÅ`ल_œ•»'ƒa›&"WŸK[x1µ*.™;aþöñŠßÂcõÔ7œ³o œ Ÿ%â@Ôå«q[‡R ƒØÌùž/14*;¬lC¿¨`%NÉ;c¦kfrýíÄ€V²öÆÈWxlšyB)ž:ðˆxÄOvÝ2ÓKé&s3Ë?¦e?m\D\攡­ö…j|¦øâ3•§Aš¾­Þ›2fÎ[¿Óš¤\a7ew<‡&7G¤ØÌ,0“cðäl÷ïôýYRæû¼þ®jîÉÌWðGrcâš*—S…_5fæÆò›( l¼*·ÁL ® ÆÛe€˜DfF Q> stream xÚ•X[Û6~ï¯ð£ ÔªDQ·Ç¦h³³h“l0À>ì,²MÕ‘EG—Lgýž%Êv²³H0¦Ïõ#W_Vñ*‚ñ*Wð?ZíN«w÷«Ÿ~Ó«8 ˨\ÝVq–zµAB¶ºßÿ+¸?šõ&)ÒÀGÓá0 ^Ö**üóÊsuÏ¿ƒe†j¿çÁn†º}âsSµFè¶í‡®ª[2\¬†Öÿ¾ÿ;hVz𩼠Uú£V w½ÑÈ\§Q`×iØFùÇIò0IdÍ ½,AoÚ¬7ïfÿSÕ IÞ$‰ S4N¦)‰\žA'yprßðköH+‚­X çñlDìmóu­²Àt —Î’ «ØÀ89«Ge°¯;³šW¡[7/Rvc×™å ,¿·çÎns ×›<-ƒ;4ë^ÖT=Û7òRÜ]EЙaìZ:{â퉃]Õ4Ûj‡‡zFJtvÓ™ ¾ù„ÌÕ€ò°Æ>÷øÁº§ã¥tô,ÎøÈšŒ¤Ji0GÏæ!г]mØà¼‰óâÕùÄ£ Lr|(:O0f{ž]N2²Y4Ù›÷K ÏÞ$FûΞEŽdÌÅ–™·e»Ÿä·<âS›î`»S}ŠÎlìy¨Oõª¡¶m(!Ÿ{!üE˜&ÄÿÙ|MO‘ž “Û®jwë$ŽÎT·‹À$†ŠÚÿÂ÷¥ï{˜Æslý8~©ôqé¬Xb€U½m…ÕÒ‰÷.åcÿ,J'!Œ8ßÿþéñîÝçŸ?üò·:gY¨Rá¬,û÷On¿¦ú‹ ÆßVæE¡ráVNu•†ªX¤úäh°¡ÒÔä(®*•hÏ<6ÎS1:¹«jê=ÿÊsT.aN"ÐøQv£CaT&P„ÏUßóˆâ¶Û×-© ´ÕxZKðäÔp‚4Ç_Ò SÒ"Tß±gû<Î÷ÊSQ„q!Eç©9?Ö¶$Ç3ØãFiаˆ=D’eló,¯ÔìhVfêÓ[²°,}[HDªE“¥;7l”¼ÿx Àȃ(™ íæ0ø¶2/êè[ð “ü›ð Ï—ð¾§<¥¬‘"š><ÎÁÝ‘~½ÞF‹¼~K§.¬ pßtà3Ëþ>6È‹ làÖ\è¡Ücl@÷(ÄIéá.JŠ}D¤²Ò=³I€p†›M݃աØ¡r¢¹‚!PC8‘-áÒ§ãŠÂ.F—ð.Ý=Ê©qu:é„ÁÍ´ÀÀ]žâáÿ‚]ÕIäe•†tÛÙ“CÆ»Cƒò6:Óa¹¨;Njg_Þ$tÎ)ÑnÓóRÛm¾#wê;›LçÁ;Ú¡@ÜËH¼Ç>ìdoHIzº‰ƒ=Ý`@¯ðÛñ¢Ÿäq' žLk:þEg'ñ©¢8LRß3ø†Üòƒj¿¯VJ½§Ðzé§4_Vû¹Žc/˜+Ð7ZŸŽð©À@¶; žhªGª2¦eÞ ^#›‡‘X£äGËßT%q°³wWÙS]EºÄ÷¥ÜºÿFf³Gðñ¤nùwzŒÁW÷|Cp”F|‰¡'¯«àÌEWAݵ‹å=…ÜIpô´P¢š×5àzç•vÇ{,db«PEFÎf¬Gò<‡Ùu‘Ÿ[ãtù™a¶J¥á5¥‘KÑ|Åi»r{P™¹‚O}οíP‘úœÒsŸ£ýsÜ¿1“HZ#‹³ ©¤y¡>•S»øÕ¹úq:E¢®ú9„îÂ,D1ÁýJ€Ø²i³¾öß t­\+¸Uûár£ß„ÆÛº¢Dzî·ížÊ-PlKŸZž®pP·“•Kg$ÇN’ 'k¼K[žœÎË›;»×Y³°Xܰú£A¨­«¤ñÕ‡×7ÉÚÂÎX“sÙοÞ_¿Â+•†…ZAU-H™XiÇûþ ojµ endstream endobj 715 0 obj <> stream xÚ¥WÛrÛ6}ïWð‘ìTqá­~ª]Åq'uY™>Ô%A2‰”I0Ïôã»À‚$3²=#\{9»ØzõBø£^Âà?ô¦+ï|ì½{ŸzT.bo<‡í IãÙß~DX0 ” ÿýu9¼>Å>؆BxÂÉB–²ÎáÃðËèd[2=T'¢Z¶Çºpñe|"ÓV‚Áùè·ë‹§80©ó/å‘5p~u}ùÆ´×NA“FëE©-*¹À¶}šWm9#ÉŒeálÃfìu6Ó'(ÛÒ™¿ÂgŽ„¶ÑÝ1ÄaÝŽ”Õ½ê…nrÂSG9 "è«Ú]1«^wä;K˜ùTßú=.Üö%˜èÐjÿ…æÔËCàÂä8.ä‚Á6 ƒ¾ÒëÐ0Ë?Ί¿ËfZkSRoeFÇ™1$I¼ÇŒ£=6²ˆÄ7NóÕÛ‹ '‰%Ïëj…"˜ XÚ'¾îˆ!¾Ä¼VâÈ¡9ØVþÚì"3&Œpî2£Í·pó-L¾£ÈäØš§;lÍË¡ ~ͰD&z÷w7Jÿ¼ºÁ\éoZ@Ö4CdW uŠ6GªºXe¾üžW1V!îæµ/t¸:Äðep!=”É(" u3Yªj­úZY¨‹‹9굘 @¥ÛXQÈ„[e¥p A;ƒ!e~ê§¢±j +Ñ1¥¢ç¶EÖ (ÝÛ.0˜g–ºPLÚb©ºwÍ´Z €‹]¿Iϵ Oyg²äpR§GÜ&A¢lÿ¥©Mäø³6«Ú€¦WCsô®B‡ØB½êT<îbeë­/£¤;l®w£oÑŒ0êrQ­V² 8xò6ƒ”ûæ.CL•¦}dþ·üÍë¢jÜ,JàñUn™$rì0•yU€€í&™S<0)ÊFëÛ­Ì~wIÝî’v],Û’‡=ŒõgƒØ”߯¢ˆ²Ý{¬îü‚Hh )³½£Wªšë?äÀäcm¾&zˉ×Å™SOß©#‘”Y±»´ùÐCûÕªÜ,Õ¬úöÊ¥Û牗™F¨­Y®‘¼èb‚Q§5êÙR¶W¾Ôv­QoêÊ7¿¢1%‰ÞÔ©~mûáŽs=ÐË~(Xhš›Þ2ýP°šè9¼$bæFïvHýñ¦v?âL:HÛ!¹s½õö>záúa÷ŒqA`ÌÔÐ øEÏÎNöóOÿkž endstream endobj 718 0 obj <> stream xÚµXëoÛ6ÿ¾¿BØ—É[ÍŠ¤¨G‹~X_A†t}İÍC [Œ£M¶\‰N–¡üކE3‹’hüã×±§%©Æš¶`L°óÛMµmŠÎU¨ ËDcBE ËuUä“©ÀØ]€›/êêæBÏÍUK‰ûßÏá¢Ø(»xÔs¢†Î0OžŽªŒð4!‚ø—²YÖÅV{ÀÒ‡®¶‚¤¡K>»ÒnKpÓNi"ÏÀĈÆ!E5ý¾M#©Ð©†äµËë ‹}p9ÅÃø°ó^]¶:®âQ ó ¥#¨\gnOÕUk“¾A\k>*´8õ—»º–M¡¢Ù-¦Fò”ó˜0íVNt‚Ìm]-J¹BÎýl“ã¢QUmôæ¡–k·‹ > ¶Uï–jWz—°¤Ž{ïpkne–ìÜ\K­¿6—³ûÛ¬ÎÖº*ÆðhDXAw`±ˆˆÐ’l'S€¨À(ùª±P±žŠ¢½œµZÜku”ö£S¶a½Êš_¹Y•%†¸Ø¬P±y@CYæÍ“1P(ð„DÐYH0¬]å•òZ–# ®iç»EŸA¤™Lf—øš)|ºaWT}:j"½6Â_Ö2S2'“iÈ#îŸ^ŽfŠNÔzã.…9´Î¶Nž!T Ó…ÒV‘ØUDhE¢N(N™#—,€¾FUõ¦˜°³ÎêHU«‹: N¹̯àãÈÿK.•ÝÍša˜Ý&/,îiDŒF½L'Ú¨j«F¼ÝB´=¨ªu RŽÕªDÔÞàs%7²Î”N1´=ŽuR:¶Ïçeöïí·˜”Uý¸ëËR65¡*Ëlc²Ú@udvŸ†Ì'£•ŠÍZ'+f+:ûXºv•ØÇ*Äò= ZD¶­•¤“³w^_|xu2æëˆDm³ø„µ\íʬ3öéha¢ŒCijÿíaN ¾òÅ/³‡!:Á ûàò=prøHhÿ.¡8Y–˜fº—À õ—†–îDx ¨j¨}(V·'i¾ÂÒeø0ªîÖ¨†…i÷ºðõF[©z­*ûDp~_¥r}ƒÛ»2@oÑ׆Û’„¤-uÖX UÓÂuŽ•êúçƒc¹=é uŠ4ÑŽrÑòaï ¢Šw3|ôLúêïƒâ¶m¦kÉBoÝâV‡ÕTåµF“Úé<Ð##£—ëÌaµÎîuÖf®ƒ#îÉ=]â OÞœ>,OªuUß~g¯1ëâ™w÷í¹2Ƕ³Ï«¥7§¦C‡a“w…öÙ:¼xûëgë°4.¿ÖõðŶ¿8{ÿÀ>Rw²³Ž g½)1Œ) y7&†ÇÇDÍ×÷nN´ïGEçžI±“m§À#²*+{]lGŘĎl âð¨p—ÌJ_eÛÁ¤¸¬Ö[4ì\(K8Ô¯õp(‘êÍé;ÜÒ|£ã!"|ÉxUjÓ#¯vpÇNˆà† =ÿÏ©Ý?õAúb¯…[=ÇZ8P·uëæ!T‡e®;¤þ£ÃŒb&PšfîgeSáÇeV–2·Xé`b„··»|—•…Òý”Fþ¸n‚’¨½ÃMËÝêª×OF ½³÷b­^VõÚœ•evG3ÛnmŽ XA?þ<³ûbpÓ%Ü‹ G±$h‡ò…lÔA1ÆL¶ ¸®²êˆÁT°îƒ[GƒK¶C5îVéPGš’6âó ÆgÍ~´W :J&\Çö¨’™Ur±ÉÇ”4•8nDx˜³t«Ib"à*/¡_õžqûî€D¶L)#œ~E€hH¨@9T£3P6d݇;mwÈ,þÛÓí{uA¶À8½—ÏÏ ˆ3öÄŒÉq2kÀ«wç§goôÑA½0óëÇ4 ±"(‹ZÚ÷ßü"\¬ endstream endobj 721 0 obj <> stream xÚµXQoã¸~ï¯ÐK¹X³")‘Š>ô®Ûb‹½Ã]7ê"e&V–¼’¼¹ýñá2e+N¶½"L‘CÎpøÍÌGF_"%ðÇ#-à?‰ª}ôÝMôû¿¤OX‘ÑÍ ¯ñCE7»Æ¦7«Ýü „¸¤¤`.†B[3Œ·ûúàäÂŲ„¥^¬VëTðx|0ÔØ®Ö"a2}ÖíJèx4÷¦§Ž;Sõ¶qÒC×ǺkÝXwlwØ0àºÊþÝ’©"åLéÐÖ-LýßlÝÄ÷M·-›ÍÊ.´–:·I–e¤¤uŒ&2O³øÃÝj-¥ŒÛŽ~q¯ÊïUJì‡O{•2ʺ¦¥Oçl>árf\Þ¿V,ÏÝÆîË¥c ËE°ukƒ©1vK«‚S¥tSþüÝÇÛþô……Ó„Aƒ¤˜WÇŒ ð]Î2iÅþnÆcß ‹ñŒi(zóàüÕwà®v¨ ,ðvÞ7‡Ûº«·ËŽÈ üDC°äâ¹ÊX6Ûã÷Ý~§(`ß²Qu¡]yíÊž,4´;@³£ÖØÑÈ@vìÝD·#9–M=â’OØ‘ÅÝ Œ^k~« Tœ‚WÏÀ«HmømMa‚‘+EF‘ ­ÜŽ©J0{¼™Ðèc½/útÀ××U–ÅesœÌ°Í÷áÿì%ŠH³BÛ°Gk¤Ox›$‘K¸`¢°z©»®'ËOÖõõ}ÝzóèP qè;ðËž>ÊæW®`£O-ÐÔf Ñºm8‹û²½_„4d | Q+ø”Õ¬äû›èKÄd‘G/$Ëú[0Øï:4ãrêh¢OÑÏ”ÿgˇb² õ§„™Í³†ð s“ˆtÉûœ#ô¯;?ÅRræüPf¶HTéT-:DhÍD8Dä æu‡„bÎ!ËÕní%Ñ3”L]ª®ÊÁ¥ªÎU‚}ÝÖûú¹D¿£üaAEÅï”s^B׉æ[‘ S!ì÷«8©ül×ÿ'¼ ¿œ/¦Ã½ê‹P*? ‰À_ƒ@ùË*—‰•ƒ<$Eù÷—Co†? Â6¦Š bCr6ùà­Ø@ð÷@Ùµ¯ Ñ&Lkò¨í§ˆE·8åélÆ•Â+•b<{så]Ë\ WËÃCwlv3êã‡iôØŒõÒ玪°7ÛïMdSÌ»¬N© OÑ@öÚ¬ÞQçãCç3joîàžÚVîÓf·ã~u"”~a©8I-Y¢œWo±,_bÖR Œö¸3 ÃCýl[ÊæùÌ3mÚz‡âF>S²uÚ ›m3K¹ÉE(2ͯ:ÊÛ}×`GʾܛÑô‹÷¾"?¥ÚÞZîh¸nóå0™½4Ö«k8$L‰Îí¬}É¡PƒõäÑu¦ .:¿p’ÔîJcÀ™Æn+Ï(ì³>m%ÏÐÿlúÎͱA¿Uo $l àW×C1=XM]»›úOàE”;þöB6å©ÝMÙ ^ˆZDœïõ÷èϵ‡‘}¤¬›ÙµòßÔ› ‚@•Š¿òh ²oÊËœI~ñnJp›JÄhþæÜÓ u—r¯L(69Úq ¸óV8cî^‹eÝ·öy8v—“[á™Æ?vãtÌåH'Qß-ëD1ýz2‘x3%©?Ò‰»ÝŒç5ÐÓ#K—SúFzçBäÜu׉]';õ:±Ã!±s߯»@Ïb7­í(Û+kRníÁ4¦Z¸Ð9Éy°><ÜÌ‹´.» Ž–¨9rçôR;LMš þbÚ“ ä2øÄfˆÒ1Û%ʾB‡Åv– óË¿ùeP±´8c~>JÉp¬¿ õ“ÿ5õË’äjŠ‘§Géã—Ôð” ÿŽ[•ø^§òg ½Mcë7親€­Ñ›9½_‡DÃMÙ–>ÉàŠS|┺uyŸf·3W>5”ÏÁzXeØ%w˜\vvO·Þ¢ÍüõãO·>½ÿøþû›…}«|J<¤@NðÄ6:ÂþV§‡ÑLˆy%Ï4÷|‘ìšø"~R±·Jt§Šg¹9}9+ú‹ [ú­Ò&Þ© S˜œÈñ …ßs JƒÇ+¥ÿœ~“¯Ìnž7g¯ÿ„97•R$r¡½ìÏ¿ùH ¤À endstream endobj 724 0 obj <> stream xÚµ]Û6òý~…å"fEQ¤¤ëÓåÚ^{(Ò4ÙLäYðÈœe‰9ªà(Á²ÔMÁëà·%R5݈³ˆ%â,aIv ñdïõÐ~™ÃLM¨9—,Ë/áö ,ò®9l¶"•áô9µÍFDáCµÓ¸ ÀÐWMMÛwÍPïhx»<üL@ÈbÕõUiøüöÇ4@ QŽ4·Žh,™L ÑןëæÔU£¾ˆQÿO%HÉ":RÕýf+É~7 ê$yÌ]›•¾Õšö¿¹zFƒ²©;{f× ·»ÿéí»ëÍw«|Mž1) ÍïuW¶ÕÉHOð‰Ï¢dyâƒ_íDœEaÛ€ÆjmÏÌä’Ë2pN„_J²B#OXj¡Ë¢Fìô¾ÓPÓ¤,½£ñ]ÛiÔ;N†N·Û¾ŽxR;0U´Ö¡Ù—®Cò¢G“ŽÍ]â.˜®oZ÷íš "GFì¦Ö$ e ªg®›LÁn{²#[©b"ÿ–z¥û¡S÷ÙâÅXY8“@eçGmùìs2/|‹²Ô§^ïžÑt<&§Ä"zZ$§K±µ"Ž~×m/I’ðW Ü>V¶|Tt oäìHÍj—–Æ U«iPÙVBÏ,“ ‘/HõM½%Þfî¢?‰S…µºkP²Ë ž^‡bçZΙeÄmû ¸=(‹ Ô/º”ÈÜråLð‹Ø}0‹þ¶-ê[Ž=µ¶_)±[Á»v>ÐNug· Û´,'Ì ¡ëi°Î…M]VX'kÛÞ½«|„½Ûj[Lß~÷_mlÆ3ïÿj#ó´<°v[ñ)߯팻"aÛ£–ÕËþrºWû¢t*ǼaŽ'M%“‹eB·õ[é&ÿã­#’ñÑivëïÖ¡‹á+¡➊¶8êÞšm!p IÅù¤±8ȽG‘póF˜!|dqOKdUõ®* jçVÀéL Ävíí(ÌE ܳµ‚ú`J_Úªõ§Þ=!p¦Öˆ^ä°eËÂA/›p]´ÄÌ¿Wcr©SŒËï_Ü<õ•ÀŒ™pÏ8 È1w éc½µ:ÈÂýwkd·„gA÷ÍË¿Kw89ŠêI_üúŠCg•z¯kݺ§Kâc|óì5©»®>z^ÑÌ|îÇ,¶ Ê$ÁãÌÁþö¯?P:‡… endstream endobj 727 0 obj <> stream xÚÅXßÛ6 ~ß_áGgh4K²,yCö«@‡ukѼ-Cáĺ‹7ÇNmçrì)ʱ8m0Ü–LŠ"?~¢èDðÇ-à? ¶ûà‡UðÍ+ðˆ¥Q¬î@¼ÄI¬ò?ÂëýÞV Éî]ü¹útã‘.W,Aß0%þïÕb)£4Ü4Yµ]îŠêž^u;Kƒ¶." mƒs6v_£*¼4¡m/´·Ç¦@¿#õlۨߛ;nM½)ížæwM#y0˜.1aY´—T¹ß¦±Yg)Æe–dJ¹°:\|BÿjTaeO8£Ý[’¬CS:Æ)JYœ´h,¯OÕrLə޽úumFD̯q<,7ÍBqPÝîì\rT¸öÚëÅ Šó´+(/ämÖX?Ès›SH]ퟔÚÊK껉DôÀ&,wÀ²Å2–*ü­î,¡)€BMàÜe€ùŰ2¯Ñ ã™cÐCÔ(ZR åôr³X"WîêÆ/?Ûq°ô܃˜c®pJeÖv43 É„òSQ–4ò[nclÑ8ªÉÖÌɯÎÇʹ ´‹Wc¼8Mˆ‡ø~bƒ“6~U‘ãQÐaWl³’d˜-QpÊœŒÆƒ“˜@óTt;ÙÇ­=tE]õ&\ZpŸêÖAp™Wbðœ/œ5އAÖМ¬ŽL02gy4>)†{Ê>öb(U,Õ(L˜à KÌ¿fH3 '¦×@Ò#Fä“„£ Yd€¾Z!ívuk+š;ò£·ç$ôÑ€û:¬+gÒ8ZâûÆÊlkó>FÐyòn©ñÉU‚%©l3xÌL|y:Ž<d_•×Q$¯Ñ2jñ 4j²ƒ–`#¢LngÁ3Êûð‚'1Z1 ˆÃÎd‰{¼&’_éAVÖçêë6)1Tæ!`‰ÿD Ã1¥Θqê`ó›©Ó0ê3—ßÈœúdæäófÎ~.sP¢äÉ6vÎ]™2•> stream xÚ½XKÛ6¾÷Wè(kF|èÕœ´AÛ[߲űéX€,9’6› úã;ä %J–åm `’Îûñqƒ/"øÇƒTÀÿ(Ø‚·›àÕ»,àŠI•›|^óˆå°Þ c&WkÎ… 7G½ZË4[½mv+…G³Wa×hú¢¿Ëº)ªÏ¸mêÇ®¨t»úsó{ðË%qpÎò8&Q*bIîD1n…Åáçòìn} ˜Ì³à)ˆs–){AåÁ)H$ËR·-ƒÁû )êö‚q,<Æ™b*»Åx "ÆÖ SÎ<ʘÈÖ`“âoŠ˜·ÅwÎþ ]»×nNà\ }Ãú€¿Ýb´Œž¯Þ¥‰s”™k'TÄ,άÐÏU}n‹IøüKÛõ¶Ùî +l*à}wû±i4Þ·ª‡$Kø•ÌdÜ`RbÁ/&°ÁBaR ›@?Íùä‘6 3΂‰”œéå‹“#e­¼ÊÈ~<­D~{ÒP7¨˜Ó¬.¾"Mj Ë DÚ;$,˜f«µRjAÊÔí”Y´Ýë9¬Ñ0ÏÕÿä²ÄÅýDYøTíqQTçûžYO¥ÆS/´§»n™ãdvWwÛ—W IÈØ žÕ®|Üã@1¬Žu«‘+ Á¤Tü†õ`¸²²Pƒ#íÕmÙèíþ7>ÕD${äxh꓃%¼Vн•_&&÷)•6G8,Σ%ûx‚î ²Õäÿ§£®ôW£2-Â-A?¡Æ}4p»=ŸÑ„mÓsœ”&M^?ÌV†s¬f¤³]”èoÆñL‰úd8EŠ(!!°8C_9™qÓνPfxF‹/2–8š»9. S.ªò…<®¦)ŒØQÙy[üÁÔ´uî@ÏׯU7¦‘ðhðÉ®†m‰ª¢µçC*'£ª©ñ %,lð¯kI¤ËD‘ÄmŒdn$bI´¿’<9 0©çMèoŠx›þ6ƒ”r– ;ç8£n°÷Ɉ¿©#À;{@󈉚,Ðuˆ‹°;ž€VûøéÜÔŸJ}šGK$öŸ£% H;ÇêëñŒƒF«‡ªÞÏÀ¥—‚?t÷ØTíËN-hbtz-ç„DãDß*VF× Ó ®ßÙ-ŸŸ æƒiDÞEÞÏE[^BånÖ%&df?„Œ9œ£˜áœ_cÙ¾ÝßÖ6tãb:öGâÌ—Ø[qXéÖ S¢Óß ÜM¸9ãÆ9Æ|×M½\ÿÐc*ûú—·ëßÜ€ ÷õOûõïÉY¨ÿž7Uö Þñ®ô·î²þá$ÚÀCºšØÝ`ï“9þ¦þùú·JØ>i᣼QøJIœÙÂ7ê\)üéÛçüt ¸C°è‡¾ë ‘w=ƒP¹Q{žaŸ±Ü²ÀÎ両٠b¡éäb˜õºÒtÒlÚu<ƒ”ßuÌù<å„þ¹0 €Äìûˆ«¦íæ~‚ˆÇW;ޤŽãçT!õéÜ™ëÏ«L†Ô¨Œ/ÇThñ2Æó}q3¸ñrpù$ºØù¸òÃ\ÐÑÉ:Úz ( 2é]qxü| u-@ª!V®Æ!à~Ÿ¾£1%0“¼Z -bÿm¶»­}]÷xÉ2´m82K8|lOÅaknŠ úËŒ‘Z,jšDbH¢t”Dp’ÈØ^)GPhü©(eHæbâRrU“ì,‡©æRP¾4ß`­rD·x`Ę_+Æ,ü¡®òÌŠ¥/ ‘ÔÍ Üã_M]Õeý¹ØÁSŠE™b‰UDOÿ\‰Ë¶>ÊzBLº'Ê›¹#‡–tnôNïéïšk%RS>¦_ˆ*s½êíœ$x"$®Âsx´¤(78¿Û®³uÏTxvî5J¯ã<>æ$äÜðºŽÙ c ]F/6˜‘@¶NJ.#Gûþ‡¿óŒÄÚ endstream endobj 733 0 obj <> stream xÚÅXI¯Û6¾÷Wè(Ï W‰BO Рí-o}Ń9 KŽ$'HÑß%Q¶žõR-²ˆËlœ~3tô)‡?"J%üåÑþ½ÙD¯Þ  Á2c¢Íöׂ³,‰6‡?bÃÓ«µÒÄÊóêÏÍoÑÏ›èSÄTf£/‘ɘՎ!M¢S”(fÓ~ZFï£w3 F"¯¤¨ÛÁ–3¶ši»$x$ò‚ÏMþùF²¢…0ÌÈ%Ù•^Õ«µñ!‡Ojâ¿ésÈ»¼9•_E ŠúÒÒl»ïŠÏ+Åc·«ãö²;7õ®ÌOÎÊWoÓåó 5®{•>©SùþkUŸÛbð™2‰” p1ŒKQu«µ¡è=£ŸÐ¢§ª>än©kòœ~Ü<Ð``9?®~š5Œ”ËŒrJ~Ï»KSµžV‡ö–éô×#zMÅÝÇœçm³=¡Ó<·à»L*ÈHÌñ–e~·hIÜ_yS?àÐŽ*šúÒaD¼‚ð,™dI¯àÆCsçá%Ö34þØá4¬ó&¯ö^yµ’i|9­¤w«5Œá¤n£>=2¢¢µÌ2Ê_Å0ç@A¹m!J)Ÿ9Èsd[­µ6ñ/5î~A5óøó@¬Å‘¾d \È•Òä4XÉOçÙ¿®¬ŠH:rJEÇÍÌ™»Y½Ys?²â*´UÝ‘à Æ…_:9/;oe{Oƒ öÅñëèäÛèè碣‡è´õÉ“NB€J†À?Úeü¦Í‚|Îé|!‡ ç`,º–(£¢£°RÆÂÎ7W2I\”Føj ƒ1œ\hÄ?iø¤Ú!Ö±€ÇXà€ ;\wE–±”ô8ÚV§;¥Ú‹êç·^*^lüŽ'õÖâÂ(ñ0À£¯}ݽ·*ÎlÀÛdo‘Ce#ÞúùÞzîàí Û#é‚ì€ÊËñöѨ°LŽ*â袊€Ê«(!@E^Ò šÝIssÇÄ‘iö™ètü ÈÕðM²yÈÅKùzóò¿~'êuÍ=@”Ò×·ÑîÙ×[2rŒ©Î{X,,}Ó[Ò:AkoÜ\c¥H¬[Ï;Ák3‹×ôP€ÇtÓílß%0µž/)Æ m´Å j¢SÙƒ¤ŒwͶ¢Žu ¸±F3/ÕÁÓAP¡_5‰€Š±é™,Âé4%Á BW¥"æÎ‰ue…#LBBd$¤7'-"šy÷$ر tóVh¯^´¡xºÖþqB¯ôòà\^üN]å Êà=Œ3`7Æ¥Ëg ›¡Úçç 蹃qƒl^ ²ªAö2Æ *<²,¨¨;§¡O3óR#ÃàIEó@ÊwE=“p&ÈÐC}ý3À·Cµÿ'ð©ôðá äðíw]_šÞŸê›M”tëÉý0§'›"Ì®ƒTöº·TIÜï ½eê{K•ÌüJbåÐTjßT‚ºŸ˜FUÁogdNBMý$5˜Ò²ôe€9mkB" )¯Íu¢é1"”èißýðDî endstream endobj 736 0 obj <> stream xÚÛ®ã4ð¯ÈcÔäâ$Žxb Ý…eû€DÑQÚº­!±»IzΞÏŒÇIÓìE¨•ì±Çs¿%x$A ¿$(SøÇÁ® ž­ƒož—A³*®‚õ®WÁzÿgø½i[©£, ‡>úký àr7ÉYÅ_°<³øë“ŒVYQ…‰Viîêà2·4½'ø`:Bì/Ûsg¶lý$ž1¨X–ƒLHü¼ AÅòÔ]«)аÖÄD–Q*BÙÑÕ&l•V­z_ÊèMD"XQàÁå|¶RJvýî5¤ ŠÊs&X3–çV«[Z–¡Ò(Á Ò¡9ªE“àmoš &h0N»ÊWŸs–eN¿á¤–|Æ,QIÛÃr´Áª0|È~¸áÄ ¾Ç![yê|ˆ…æx`¿&{tQ™‡ÿÒ²‰NÓ T+ëTa>¯pÿ †íPÞÔÊkÁ†H»1(wêLõc>y­FÙR­´¢½yÔæÜ«~îrÿQR²Ìf£'Jïœ\~®¹Û‚4wÚìåÆQE„/×›èÛE9ˆæ5£~—Ã¥ÓŸ?¦U YÍMË¥¢—®ÜÜH¹Ä$ŽY1V±ÎÉb™¸É@ÀéAB‡Ù9жšK‹…i;Ítxa´Nk/_‘âÕµ_GسÇ“é])KÊüɨ繜ü; KÛŽYŽÔ†oBÅ$4(Sf%¤q7…ycW㤄;”W¿æ»›ŽÖ¦îŽŸC`VÖ™ßÀ¨Äüä ÌTÓ;´ij:Pé¥Òµ™‚wÊiÙžêß" ݳ }Œ‹99oÞËΰ…Œ)¦øÿÿ áé8«“mÒj>ߤÕÜ[[oÁŠ_?-®_<]ú‚@Dë‰lþðm/]bk¿,o‚\£®-lwý€°.1n=9;_|<~ù³k³.ºç]döAåG¤Áª€RŒ<“,q_ñí¾. endstream endobj 740 0 obj <> stream xÚåYÝ“¤¸ Ï_Á#šöá ÜV^rÉ]e³uŸsU©Ülm1ÝÌ4zÞÉ\ådÙ`hÏÇ%yKíÔ¶,É–ô“äŽ>E©õYáÜÒ®Y¨¬–çà•H¡eHH™vAou1BF'ÍDdd1DXƒ,h DƒÀ0ˆÈÁ W0˜#YiYÔÃ4dW‚Ÿ ¿5k«Þ¨ '–3ç º¨i¤J‰ÂàîéãԔƃp¼k‡±/kÃrÄíÈÅ.šG¢+÷ûjO¯cGÏzdÏÆ:×› „‰—c¨9Öéó…XŸ…<뎱 ãç{DĶ~à‰fY6sÆ€‘³GDœûn1ø@¡k#¥Q¼N–™ÃÛý A-ž j#ý?ˆiî”ñpTƒºúîá2¦¯èÅì¾ÊÞζ屲Ç4å0¬ïšòQC!XÁ}מˆšª½”6ÍÖíþ—÷—óûî|ÛXm?—ÍD2­ONÇ™VÅýax®¶áÍà?Uî¯Ocݵ¯‡,¬ç!+‘+Ȳ&ˆÈ <«Äy±îád¦ÚÕ7 WÕ }âýHnžÀ åã Ã͆è ”õK‚»”PÍb³0¥ tÂÐÞ_'×näÐ J‡ì3Bbeu:Ø¥w]ÓÐæ,cCý±¿t'œûfÌÈÐŒ+( ÿÍ‘AáÄŠ ‰˜’’iÒþ££(& 9§q¹>eÚÙå­›M<%2¦Ež.2²]ˆC¦AI¦ÕRŸ ÔuE4‘üó’‰fB†˜øç4ˆ‰0$7‰tÛI}G£ÜÏÒÂR‰ÔP%~¼Â¨ Iȱ&‚èæÊ‰¡Ýpd–2Iàuû&àï[Y!…s‘š%ÄíáPõUˆ„mg+,“=ËjŒ¥ÀðHã¡éÛ$WxÄÔ»j Ù›¸ë÷u[64gsufrµ†\=˜°Qé´<û¼ƒr‚ÖmRH}]êXô[i/òŒ îB;èYÀ²ji35{GÙW¤ËE ),1/ô®¶•AX1¤GžžÝ_ïxKõÀåVêAœ/Ž ¾á¨ÔóGŹÆÄAGu”$…oh,q&(®ïf·ÛCÙZ¨ê}å€ 0 €8ØðTöäF[™­` TÒx³é‘æÅ¸Î. Œ º¥dU5½6Ú៩§Ãž) ]tb •¶³á ÆÙ»Ø³/ž ŠÙa ÝÎ!&4Nù"¼¾sÙR‰`g;àŒ4@ ?àø"ÉM\3@èmÆÑ˜ÍùØ©MÓ}Cõ@å–=§ÀŒº*è–i†ò¹z‚ce6žjd‹ƒª‡0°'@¹¿9»ÍÀ¾ÍÁÉT ¯z.»ëÀNF:Øš)nódÕÒ#\”Á3?ƒ›n?´ ý_V`Ú‰bªÒ³Âó ÐBng¼Þë–ž U ÁÁ•Â> stream xÚYÝsã6¿¿Bo•{6WÔW{÷ÐÛÛKï&“k·Þ§ÍNF±›]}¸’o:ýã  $ËÊ&ÓÙPAHàGØùÍñþùNÀÏٔοÖΛÿHÇ÷DæeÎúÁñ#‘Ig…„ØYo?ºë½Z¬Â0ty“—ªSÍâÓú0ËOFÓ)b”Ž3š}Ë,cÁ'RËÑ« uÕFßz¾T--ÐÙ•½Û/‚ØíVû¼Ú"-p[½Uvao¬o‹(e¹÷3ë‚bvX˜áUS€¶òS…fà‡¢€UénŽ]§«v"÷Pä•¢ÏM]µ]“ëj$n×3ôÌ é\ÇŽgšíÕô· ZÞ(ž¶U•Ùm~KÔ{”üDß P74«n¶ºÊY„YýX.@ê=ÈN\Õ´4â/¡M#7àV,V~œœ5±»œ³ßÊ:<QDÎÑ¿/V2tÕŒ1ýLDlL\ „žöª™uL˜Š4¶þ6"å¬È 2d>Û‰2¶hìE›F‘Ñi$)úªˆ…x@ÖʹõaóQº7êÄ"/\¥ìÍ‹Òsã ;¸Ý/ábõDAçÓªÔI66£Ño|ªI?¼Hgú--ž‰c»¤ã>øÆz¿'Æï1û=”ý"‡F=êúØOÔ·*Ëå~A<íF«š•Úà0\·Ú öÒø~{ãëò^uǦš»äö0õ¬&z2v›ú7KÍÅŽ(¾=»âp§ëö6p×Ô§™%RÙHÊÀ | ™ ¶Ãugî  é°í¬†ýÝÇß}C?3 ­eìK÷ ®V âxìúÓ^“9ÉØú<¾ÑÍY Ÿfø"GÊOË‹¾y÷%/ÙùÝšâ»?å–RÝß|‹×Cº;U©&ïöÀ”†“Pp¯7 vŒa¾3âýDøéxß_>êOÄõwj¾|üuJøÌ„ü“ZŸšoß°1§2é'ˆ¶ïìÀ%¬üÞêm×ñ@=e8òÈ¡Æ(=Òãl]m?úŸhÖZ/©}Ì Šì/¼ïçeç2~ɾ.Cö2ÂsŸG2Â×è1¹_·àj¥–$óæÃõ5Ë[¿ÿï7W×ïîÞ~X3Éã6ä´篫ëŸî>ü´ì¸]|ÿÒy}[—%DøÐÇØôŠ€òÖF )Šo)~^„9)qoÚ½€Î7B&Éi&>â˃0O‚‚^Ð=A˜^jÅ3‡%ë ÃñtqÚcöÕŒioù]º›@fõ›Y÷‡¦¾/T‰‰C¦n‹ŠÂZ«èsdš˜2D°M^Ñ(GEêìŠú>/L^ÞR{‰Ê`$Œ}L-Èd›ÿqÁp¡!ƒ¬d¸?Öh¼Æ^õhþ6¬%X h®´IN…Y׉·,—×b®ÊCG¯МßF¡èÿp4ƒÌ¤,!·Ð'¾ÎÐYž†‡“KótתâÆLÌÁm ˼`ȯ,¹ éÈ|ëúó‚"ö¯ê²nž¾iY9Ö¬Ô_Ôv. S4ß¡vÍÀèÕ–|„¹ÚÛÅ’ÏYEÄ30‡±r Õè$ãg –9^È'Zn¸}ˆêëj5ã‚´…Žï‹ 57)SÂh„Ûˆ„!¼é|ȲÐí´ßf©sr¢L¤àDée"˜҉C‘&}¿p~q~žYÃr ëP¸zBŽe§RÈôEÙ–k½UÅ…lß$Ž„û^l õ Ò{¶A|S/BÏ=Ñ{úz$7 bGüÃñáŒ{G4oϽìarM‹p³²ÊÖ%P—_žªúÐêöyLΨWF€Ë)¨<Öšá¬El`0BlH@ÔÆ€uÝã1³zuõк‡RÿVí¦ÑŒ¯~ÊIÿ«O¹Øi4yʱâ3Kdp–l‰¸T§ÚÙJB,’¾B0‡‡Db¥¬àÍ:ô0Û!ÄH¿1øybnÄOÇ) "£ ¨~2Itü ¼T$òü ¨®Kø¬r4.JyÂ¥n½@ζ‚É–Çó$¯ÿ—‹/C :35æ:«Ã\XH¦ ¦c¦i dfAä ŽýZQê/UHs q&â³ÚÍë^á7䦯”ò%\¦!kÊ0ÐË©¹0Lá¨c&+f;² º2´Bå>¦ô¼0ü¶†ÃëËHiø\ù0åê²›Ü>fêHC*P8Æœ3ck¿x’ñY°”Jq0:*r™âf<£ŒPmd$u²êŒf¶ÜŠm«wÕ€ÔO8 D¦cI‘Ë0y7)ÚÔÞYm±×ϵ¥›5BF«ÏÕÙàZFîµêr„‡LŠŠ8˾&dËuö±v±—‡úˆÐ'ñ/Ô˜¹YI"<ò™ ‰$髼3óã¡^÷BÅý¥é›™éÉ0=çêê42xXá¼1W"±Æ$|§ŒyðN!å¢ ¤r öyŸo¢ µEèÌYñY^ÀmHkš_3ðC2½QýO!&ÜlSpîŽÒXdâ¢@ß✗%)%ƒÔ¢ Irþº!Þ •TAÞ‹ªÀ›ˆ@ËÕP ˆS|ÙÇæeÝdNÄcaÆ3cÌ@,˜ÛZ#fô€ýª§\7Á)Z[Åóé"À8?66¼M°Ø=ü³>ƃ<«p{Ü`O½•wdžõa ¶â=¿tÑ•‹/KUrÖ½(/ƒ€¼K2šJËûóßþñ±{ endstream endobj 747 0 obj <> stream xÚVQoã6 ~߯0ödÕ²lËÁ€= »=ìípy[…—¨p¶å“œæ:ìÇ%×M\ÜР–Eò#E~¤œ|Kx’ÃOd¿<9ôÉo»äþ2á9ÛæÛd÷â ¾ÔÉîøWÚÇl#x‘vj¢ÅÁ n²­²B¦Söe÷'Øó|ÐHV5ƒö…¥ƒ†Á“ħ6+šô¡Âs0ØÀŽRy;*p¬Ž,Û”B¦»SÜo'e*ÚxH§“¢m«zROÿ7l‘K&ŠX»wÅdÄwk5+ã±«Çæ"¢CVW XE„ã –åQÜZå6e%XY@É«*9§Ÿ…u"Ô…ÆõÐvøR¦> ç“ ‡ì[GjüŽž)Rýá]„}«ÜH%:Lš ×½dH™‡Wl[B4 «„f‡2¶u™îs^z¼º u‚ÅUa¼âdHÈ@/ WæÖœ'=¨˜N¹L§¬ˆ)êÆmÜ =a¼Æ9˜ŒÆt´òÉÀžü9è°°ÄiÉx³<ø“÷Ä€ÍËIwŠÂÞÏDÇNÿ£öéd•Úgòk< l¬º½¢0YߑջØûì—·ù çl‹¡ËK_±’•Ù†s‹fß&`,]’ Ä÷6ÇgŸÔ‚5r~ï’Ïɧ³Öìâ¼ÁnrV.±›‡é°g­ûÐa^£sH"— xΑU?‚ŸµføûÁ3øí&«ô_zø®9ôȰá$LÏ.è¼ö0}ƒôÑúv‘qšÉ@N\ £âÕÑm#mBpE…—-Æöùe0£Óîýv Œ*Ššq¢Ô³oú%|=ˆ°È¢@ò]äÒu$¨s_ÿ®ÜÁêÑ_Ê·sööŠ˜¯ì÷g9p¯’W£ü5Ô5/9\Çqœ÷íW? }cÌß”nXЕfüUèë {ª'¹/dDŸñs‚*‹Zßµ{ݶ~p^‚Ÿ=:ðBšÍ›{zìÚAÑè|{:œÊóTOìMY—'-€ˆ\—Ä.ª¨ûé§ÿ¨ß‘d endstream endobj 750 0 obj <> stream xÚ•VÛŽÛ6}ïWy)]ĬHŠ…>õŽ6m‘‹ÔEª•é5 ÝBIN]ôã;¼hWöj× v“âÌ™™3Ã#¡ˆ¢þ(Êü'¨¬Ñ7ô屄HÉÑfÇëÜmÐf÷;þöPtƒ¶«5—ËÕ›ŸÁZ"–’LeÑZÀ&÷Ö¿š¾ÔUU4ºûàóõËŸÜ"ïÛq0î=Æ÷›W!šžÊˆÄEóP’ÐÕšR–âyù 2u³â >Û6µ[S<¸ƒÛ%lÊ¥$bçì&ð/ðmÕMná¹B‘ȉJƒG&P$'Pí´¯Ðôj!ÆÌ*Æ1€«”(1WЍü*øÌ*‚ŽC. )*óûǹcxˆÝÌMHžä.Êz #ˆP>Ê›SÓv½¹ vîC3B¸(Fˆ¾ˆÀí{—Ò{Ý·øØšÝvõÕR؈AÜC|§ûÒšn0míÓyHAòtn¾9¸‚s>MBô9ËSR ‚³Ÿ'¶€Ÿq’°hzO©›è<ÅCˆu7˜eòž\¦ð@Vk üÖÚº¨ªÓ…kÑu•) _žÐÙvíYS‘Ná—}k‹:\¦]»ž±Ï®TÓq¡õ.¬†6ü–4>9˜h¹yâ&@•ÅØëpn"Údï0&ÜbÚò-c1ðȧîDÿmBSÛˆ)@L†O¾Êd^_~×<²0!ɼۯõ0Ú¦_hœ×$ñçÙƒ>N¬CÀ~,KÝ÷û± S¹kÀCzŽ }g]v0,Æ¡«•ÕÅî°ïçfwÒc×ÓÛ&4Ö[°èG X–&$2„ƒZ×­=M÷ê"ÿÔ #é:?­¦ç0nkÓ܆Jk7ˆÞéj»"Oªnª(Ùê²ëªë!Ô½ZÏì$Þƒ´/É jB#AÏÞ’wÏHdŠÈ4Ú8A¦ *Ó6¦ðç.Ô¤Tty» m™øyL¹¿(­ö…ĵö2¼°ŒµÓ¶ßFm}v9¨÷î‰ÜhË)¹w×’ó=JeJòlÞ£ £<¦ë¤Í4>SœóLAsÉL÷ÁÞÊuWÁûn©I w_8±I)¡r©K>Ne4:—¹³^ÂW »2 ŸL”ËÉöÕgÿ%ÇôY endstream endobj 753 0 obj <> stream xÚíXKãD¾ó+|tЦ×ýòCÜX IJscÐÈã8³Žµ; ƒøñTuµvÆ™ ‡•8 Éý¨®ª®×WàSÀƒþxø‚b|}¼½á2àœeZ·kØ_òˆeqp»ú-Œgr±ä\èð±Þ-~¿ý!øö6ø0™¥Á1ÐK•=ÄÁ6ˆ%K“aZ‚÷3NDNȺ+ËgœÓ˜ùÈ9‹˜Î®q>9Îe³<<,–2QáßøÑ$ÍŽ¾ûé—i„tQx¨º¶ÙÒcz{“È-ÊýÒñšéÄòÿðÔ´»¾êíI%ÿ OOƒ¥Ö,¢#UcKMæ¼G]îËæpÚju·øjNªcÁS¦¥eñMÙ]µ3UÛ8zåKÔ,S>ùíî«»voª¦tg&jÆMYz_±þ‰dR8R$둹óºvRʾÝwŰ¾ïË" Ÿp9ÓãªSÊQß…ÛrÛvOÄê¡nK‘†žüØ¿U%ÃÒìna5[rÍ™ð•-¨ÒqSYò xV‚Z:[ʰØw¸VÄ¡©Ÿh¯7*»Uƒ_…Ú2Ëù™n»-ܦ"4hSä»]]¹õ…]Øuíc—oi²"ýñv8mZã%Å2jé[XûëÊ‘;ÓÀµe¦À|–U‘ƒŽ´ïâ7õŒèŒBº6Éë#š$_ƒ'dÎÇ4€Iæq¸oІ£'^fá÷-î‘KyÀaÙ¡n< «5q ³ ωY`çd˜¸Ó Ñnòž–We]šAø¨œ|¨Ë­½ZD·RöV-XDëð²0½Óä[sÉ·0r†Ã‰ ûAóÜîŠ1Þpó,Þˆ`ˆØAîô”áºíhÓÝÝÆ7e×äNƒºzèr"­ïÉ¢ix³çÔnKÿ–ä»®Ìû¶qN»d_íÛW‡ÛÜ¥êuĘÏôš¡7ȯ=}`wg˜T†ƒ“(?À[‘Ûx„•!‚~ÓîkçF×3grÇ+'NY"]Å¡ì„Ê’lšžÆ%ºÙä†F9å´K-ÜjçTÉS╵O0™8Rróa¡Áºuµ‚ˆè]É!qjŒ\+ÛFkLÑJ+g•j¬F*,ÿ¬zÃf± ÐÞÅ-;kúeÁÄ"b‚[²È$Ã=!:·U3Ä(Óï Hô~½¯ ƒ–@ŠÇ¡Ô#=Ÿ/éî^ºÐ‚KØàïÂT”j´sR r—§Rh+oe*0à_%à›éY["2Îb9ö%êz_‚'”<5&n~¥3ñä캊Úõ¤‡8v•qMÄqÁP9€)âÝÞÐØf~ÉØõœC‘ÐR¤ÿ®¥R³„*!6§¦u6ë»°€²ázb“w4úr½5ohÈûœ‡È²—:ðô’Ž”žKþë=4õĘ a9óÓ.l+o×ÖDÕàú8'+ÉD6t1[3#‚_ -zúÒ*›Ç0ØåPx¸:§[Þ¬hÃF‰ÃdØ@ëxE® å$‚°P id#ÈÖ´¡¸¹PºÐ¤ÜÚê- æËÃ$‡Åœ¦]¹«ó¢ÜRÚk×ôµ¢ª7p‘¼[Ñìí®÷MáEÁĦê´*ÄEÊäTB­¥-õ(ghE¢¨â"–U}ÒèHÁÏŠƒ¦`G˜ß¡mq%>%¡‘‘…5箸:EUíw-šP5¶¨ªm£8gK^לñ!¼¨‡Ð¾ƒà"ÊÝdßÑeZ'q)ã„EÙ4”FÈÛ4‡E6%b›5¦é<›@°»'³™„žššþÜõø2J½k#ç{8pCc/æØq„­3n›¶ý8ÇNÒôeøP1 F2‡¾*o&'øpó+ðáÉ9ü‡ñCÊHgðãðZ9ä÷u5PäÝãçD)ä4Iýˆ9\λùúx‚¬Í c¬ð0žà .¼„' ¸‚' ÷ðä\e% |<‘ž,˜ÿÐGÕ]ÄU¹rU J˜Žý*0”NLñ0¬ƒæ &Ð). »Çy}Sáj[Ò¦ 4°i90u`K ¥,žA0%<ƒ7?-Ú–?Ï XSN.xËïèó2‚)ÍÆåR/ÂÔð;J!L¹·.:Sâ„ÙŸSÎ! ž[Îë„áëöT®a6B˜R‘ËX={¦þÃ0õ†Éeã,Õ¯Í%•L0ŒÞà4p†:†%>†¥ç×þÃf0l’Pä!#—±¢ªÍe2оÿ┡ÆV endstream endobj 756 0 obj <> stream xÚµXÝoÛ6ß_¡G©¨‘"õ±`/Ú¡[Эkö4…*˱P[r%;i·îß”(Ev’CƒŠ¤Ž÷}¿;Ùûäq/„ÜKü…^±ó¾¿ñ.®xäqÎ2¥¼›5¼_ðe±w³úÃgq°à\(ÿv»þ¼ùÉ{uã}òX”¥Þ½§2–J}!‰½G,Mìvë½óÞΈŒCÙîpÎKÔÀ9‹Y’>Æy 2œ›ã!XD‰ò¿Ò£¬óÛòbUuø¤3”^Õù–vpc—P›‹«ÄCVa†¼†¹PL%šù»/u³ïªÎªNú¸wxÂ8\QŠ…t¥ªAE¾|‚߃¼åp¼Þæ·ËàrN¼áÅS¦"Í뇲+Új¨šÚÐKW´b™“HÀ«ª¾…eûpS?›Êßçm¾+A1:_†\å·šT®êÒÈÙ+¸D%C-Ð5qFÁ„cæ)…¥#þn‚dN‡(iŇ(-¢c¸ä¨4p746ö[9$¶öJ­n!Φ#œF8 àõ3•žÅY*¸y߉8vú9$s1nÁbÆg"bÂ’t¦ úG·‘81] Sßá™ö]ª}‡[£4Çá¿>Ðie8à2{qÝ6;Z嵡².¦–…¦µæ »/9—k¸sœk$¾D‰™¿© ¼±-Á7]‡fàZGžÕÁìû÷*a68²omÙ¨O'ƒ£°&æ|)Xj[y^¯æ¸Úlžë’I+|”Ph[NÇ9Yœ>]·Ê¸$7žhóº³n¡mú`˜!‰™à®ß'¹‚Q…ô­0–˜EÓ¶egxÙé ÏuÑ %†O(»ààÜŒ¦,}*È/.1”Ž8ŠÚåò/¸ ¡èt!ÒÈìÕX-Ì:éš¡ÊW« ¡ÍVºH¡v”ëô}»Ë5þ7¹I:c%.œzÁíP/q’ÚX‹³±rˆŸÉ¡ÚÙ(МÍÆÖ)Œ^Gáë×Gn¼G·ƒFK +ЉÐ3ò¢Ï¡ÂÉ8Ù to_bŠ„nQ % ”êë½^içÃí|x3Ä6÷mu"Ú…4Y£†‡gþëõ佋OjÄicÇ%ÜüU¶Ñ·¿üB²QºÈh Ó5j‰HÙ±?Jã…™r3‡8þžÑä§yËÕ5@V>szyìŽöÍ=ªžëÞrI¡k€G{_u-C€ÂõDaÇ[x>²°uF\ðBÈF¯›za\ˆ-­nNOÔÔÞªn®!žjvAù†å±6­}2¸ºº;Óµù’Ñ þ°1qô³ P—<Ú4³ì<ÐsÄËÇ9´_sݦ9nûqÀd?n †:0‹§y7ûñÆ,µ¥ÿæ÷ëëy¡ï;ÌÌL'£Œ>µyþês¾ÛoËñ€*fâØŒý2æ–Bs€r‡ÙQó(§ÏEûŠ Ð÷߈çÀ÷êõõ+C·nZ}GdL³ªH™îkȽnéwF.Ü´cíèçÊs¢á—é'¼þ±÷¨ß)$´™ª&cÇ6Ägl8¡2#Šþñ€Ûäÿ›§×/èÙ–«ª- ãí¡6qgkSktñÐ÷ÏUóϨ‚Ë]º#6ÖçhrÚ)§"dóu\Š¥Â[Ä’¾Àx”ZÚ·ßü Ä.q endstream endobj 759 0 obj <> stream xÚÅVKoÜ6¾÷Wð¨-²ŒH‘”„ÞŠ6‡ÞÒì­[´–¶è‰²³@|‡êå]¯›AaËÇÇ™á73ŸH¾Fbøc$åð“¢&?Èû,!ŒÑ\Jr¸‡ý=‹i®ÈáôG¤(£ÙnÏ—ÑCÕíþ<üF~=/„&yFž‰Ìi&üT‘š¨„fé4­È'òñŠƒœ´ÝnŸ°È4æsN3µ˜ÏÍò·Ì/ `ÞöSý…?ƒÕ½Åa®Áó¹lÜ‚l_—®p»m7ZÕû)q&ãÜùØ'\R™z'ŸÎMÛ å0]ãZŸa)eÙKIcC¤Gˆ©ÂFñ¨{ýxßèÚw?] &Xf•‰·ü‹оìlÙ6/ÖHš‹5üðèz¸pÙ˜pf=$:Ï¡6~ïû)§‰PÏõ€ÖÙ\Md'q¤+ÇsÂ#;°¢–ý¸Óâšnp¾ìÁqó5 Ž1•y‡ËÏí€ñí™È(w5—PW$˜£ÓÁ’¨ðw€*äYdŠÒY1'\½Ûñ4:ã8„™D…[„Üè§mïîu…9µ¢&>|¯pÆ3ª’€¡×rÌ¡Ôü æ¬ýnìØ7ÃcÐÁ<¦Ü£b¿ýÏ­±›^ûâ€ÐE4ŒEa†á~¬°ºö€v´À¶|Ó9‹|“³d•13««ÞèS 8+Ÿ\˜ÞðV|ëmlô]XÇöÁš5—î0ùtÛ/”ƒ§tV¶ümesä¢l8}CÙ'E5•à U“j1 õ!ó·L¯@é+ªæeô?Šš ¢–}›¨q%hÆ.UÍßeí©-OßS¿¸ÊoêW¶4á&²k–ÒE¿€4¾)|·`'· ¿<ç’tcW² ô妗-·•‹«]ožÊvªs. 5­¥kêáо‹BÍB*n1‘§4gÿ\ÉÕÔ÷@Xèy§„ÚâhÝtiÿoÉÚÓ˜}«j=; Ö´aÕÈÌ鶺¸ã³¼°ø†¾(åE@Äðaå @Ö2}Mhqcú¾í±ËƒœÊ¡«ô>¯g\Ÿ!2ª3ýtC7'*lX7_M1®Zo“S à_<{„”cÌN ‰ðá½úê©í;RJ¿§zè¼=ÂóUÏ §—Æ%|êÓ€;FeÝU¦†>…‚²îA! ×]e9oj]ôíq‡“û¶¯µ €rtðШ dÉÏY4bº-;ÅŽ'ƒb$Ò=&VŠäúú¶šªùµ×ŠJi:?Vj{@Ï7"üKKEÏ}iï9I !Y|H­kÏZÄð\ƒU0ˆµ‰Öš°t×8ƒUuÞœp~ý­3águéùµÖõí0¸mÝÍã ê9ƒ³Jàg%ù„ýøÃ߯n™ endstream endobj 762 0 obj <> stream xÚµXYä¶~ϯУzá¦ÅCWæ-±8Y1°½íäøhPyÀ4ù·÷ÿü‡SŽE%e/Çô ü8AXH)×DSÎr4°iÄ(À(ó%È»\ZH.—P·[ºjÅD’Þ4AÁ|}I…H–l9al ˆ‰4‘±©:§Óå:bVçñ`4[ÒÛÞQ@á]z‡ø‚Þ;äÒ;ìèÞ1Ë ˆ¾eÌh@jáÌÅòâ-Þ!q?£y<™¾ÑùVq½iCB!Yá›…ó™! ØÄd†Ù3î»ToÛÌ© [Êl©_8 ¬¶Î…\œ‹çJçܽkqiÉŠ0 ­¥¡>Õt·sîBè-an-™Q#@}¢;"‹­:ZÂ-Ù_€ÑDooº;ÙÂæ­»·þ0Lsó©¦?»+±Jñ 0°·¯JaÚ¼Šd 57¨/ЮCí0w­r\9)TÖ×4TYï\QNE¾ZÔP‰Ìï§"‡Ï#¡ñ4瞃òÙüv£§CAO4Wt[¨ ™ã dÍøÐÔ¢My|À‡%åÖ€´«1nª™ˆª1µKf%ÞLý°Uº Ñ— "#T-˜Ó½rP‹LR„TZ}€.5ºøÃG's·ýÚ#ÑnBÒû–À{’E2ýÌ8WW=jJëÞQ¸ëÖÊHp¼ºE„UVDo®²ºY^ä\u "LMÕ¢Âò\Vïbxkëé׿‹‰»m¼jy)²¹Þ¤\=”A®Öe¾¢­ÁJÊ í3UPž¨ÄÓþø§ÿ<í8´ endstream endobj 765 0 obj <> stream xÚíXKoã6¾÷W¨7¹¨Yñ!ŠêÞúÚÅ¢ÛMOMQв’kK^INšE|g8¤¶âäÒ½´H‘Cr8ïùÌèCÄ£þx” øO¢b}s}õƒŠxÂò$®n"ž²\Ek$èèjû{|uWu«µ42n›c_Õ%NTˆ–¦myØÙ¢Ü—õJdqOkÍ }û;¨ëm½µí–fßÒêͱ.úª©W\ýÂðl"0(0б·»]Sø=S¥aiê7wâyìJ?Ú¬„Žq,b`A7ÿøú—ŸÖŽéZJÅTšKä‡ÜPYÔRòø¦iq âícm÷UA“}¹oÚG£x«5è^XT†­ÖJ)0^é—‡]EKD8´Ímk÷ž‘E«9N ʾd ©2t )z»;üù¤EtÂLî7‚“@•Îî‰ÿZ%†™tªñáØœMW2Ïy*C›ÁÜÒmþµìmÝ-bhØJf0f¡ý4gB½H=ÎRî7¶^ÇÜÒ50qSQ$–-QûÆI”|t7Îw&.ðÈ{Ïmˆ¶/·àOÍ“øj…aMnÚ² <)òSFÎÌ"TÏ‹|!/™#ÕLæs¸ÛΡr¦BP\ÇuÓãá†IÆÁ 3Nª‹Ç•`"˜÷‰K…`yØòùõŠB}*»žÂmãÌPÒ}˜Nß_QÅá2âœåhŠ*`i¨ÞhÆW«5ç"EÍùÄD‘Ö,ÕtDëhe §»è]ôváŽq“¿¦ ÿB¾a2giü7}–׫WKòîC2~WvE[&ð|î*þ\î3 ÖâBîé7úR [é‚YÆužFŸàoB¡ÅÊþivš¥î‘Hf„¿.(›N“ŒeAšë$K< SA34òR6dLe~ËÆÕq/}ïšú+GžÇošÞ—]iRÆÓy=°ý×nñÌúÓ S—ªéïhz°ÐõÇ«úçÙI%&š+p8"ž”q¤åðém…mBA®ØvSõ­¥CY¼µ½…tR)w~ SUçIUO»ª`ç|Ú’uÎD ¬½ 锳<”ñªØXÓ+AÑš1D…žFŦª-¡ ,Û¦{µ"í&$Tƒüj² Ní´ÂÖ®K¸õà'›ñD: fš]ÍãÞs™ `9>FV™b†Ÿ`äàæë)n>ôí¿ ˆ/G¡#0¸…i2B¨m9}BpBÀÒg@90>C9#È ¹»%*æ®;1âŒ3˜QBL¶¤6–LŠLüpW¹®rG×< {ÛyIÚò¾jŽÝÎã™Býã³&>UŒçcOᾃÉË?88H%Ò>†d¡<6í"/ÉÄKê'("ÎÇçéA½S€0J=ˆVOõ˜•—ì/ü]{³ñ‡³¢à~•b;®¶dÄëñÝ‹i3µÿ¼à ¥/Tž'ZLÐüÍo¯_?SÚ¨d­µÁÆt†¶¤â“—D˜¢õk§hKª„^÷Æ…Á¤>+áê3/£­”IóL}ÖLËÙS"0õÀFC‚@|€è1²;Dh>û•ç`„€>8@!aÆÌÆñ9R0qõÏÍÞqÿ£½.¾!‚Pé š£9?"<ââE~Üý~Ì~B힇FŠ¿Â×ZQ±çЇ½o?û®mÎü endstream endobj 768 0 obj <> stream xÚ­V[oÜD~çWX•@6êN=w[4ˆášÁ/Š&øa¼yGy@)I¥ Ö×°¿¢1IU°Þü*B UÑŠR&Ûzý¹þ%x»>„§Ið(E¤²ZM cr˜ÕÁÇàƒƒŒóєͳi Ò³Ys’¦ç {RÎônÈoÊhŵÿ6È¡q^»~ヘ «öºë›|¬ºÖõ挽85V“ &‰ÔÖÅÇ}Ûm‡j˜RÀ°|%ª M‚•”$F•û®ÚD+‰½„@.m8qýÛ¢Ûµãkœx«Û2¿s«Cõ¹¼œ6ÆnÌëÅ £‘Eß-æ‚qÑ„Hnãú±оÚz¹ ? IRዯoMͤ ûn7VmétŽrW1ÞÄVþ(Ù:!\8Ù¾ÜF+–„]?Ɖ‡®qîüÙ­ü ew#Î!šºúì t×ø1b=7ÆWÓáMØŠJA_nâ·a’ÃR–‚¦ý,óºîŠ…¥ž_/Y‚–PÏPñ2Cày»Y²È¢RÏäu_._H’Lž €G°ðç£:+V¦J…ÃØõåÇc‡ß¾PÇŠ(?líZYTYLŤõVPo[fÆ"–YXßE×÷¥SìÚMÕÞD+!Y¸Íû¼)Dzpž…äa‡Øý"‡,‚ðuš†ß·®±BÒYUмu!Bœ ˆ9/^³š/¶œk¸'dÿúûÅÅBM#)›d⨜߇۪0u¸5Óâðx*H¬|à-U„sñèpŽíoÛ(}"Ká?9Ìxã,$Á—Ád‘ñcê»kÌSFšê¿ö¸@±ƒÈ­ÔXïqÉàyŠˆ#ì_Ùí$,ŒÖݰûŠ»[K¸ÈÍ·9Ô^Ç.x¸Vƒ¢ÞGNP½3»*5,8NÁàtA=S¯Ùk_æ6‘[Ä~ ws[ØèIÕVc•{lÚ úáþtñÛ{ܪ««>LJ+MuUx_­Ü­•Rrtšú®m\^û’| P»Û@QLDæéâœY¸Û¶Ú3?–ƒ[?dFÿÏO!D“”ùyÁ“‰yA¸>BL‘#)'„€Ø „(OÍ?]JÏë1Bìëñ#y‚X³djrÑŒ02!¤?`$ÑD§>HžbÄO)öáñö¯¼ÙÖå1×A|K9a¦àè§~~3“a¯LGX '¶âx(^‚ÛXÐu¾úzƒú$Œ@¢¸ƒ!‹pž÷¥£B@j·fRƒ¨,k_9o6žÉÝ!G\˜C¡›É°>O† ¼jvÓçé°çæ>|°<ñÐ3¶}1g½®šj<¢ÄÃJŒÿ/âE4;Á†­C ãü,‰ÿšÄ2ÉŸ#±2!,}Dbý¢‘X fÓá¶2ƒ1/ðœ?óiæx©øfœ›ÓŽ óªÎ¯j§ ï=îoömÞ@ƒÞ…i¯#‘…Õx;qYJ„ôOüáî~ŽÔu§¹Ë9ÅAáYúbZkN3¾/çLžê÷hySÞäÈôá"Gø<¦lÀƒá U"±jT°IöÃWÿ¸ï endstream endobj 774 0 obj <> stream xÚ­WÛnÜ6}ïWè­\ K‹"uKû’¶Ià¶(Üb$ˆTÞåîªÖŠ %Ùq¾¾3œÑ^l§‰Ñ†9$‡Ãùœ‘£‘ŠbøQQžÀo-wÑ‹è쥊’Xf™ŽkØž—8‰«wây×Íæ:¶]ÕAÊrñ|ö~ñ œÉ¢ÄȼÈùL “2œ9oû¡jšºÝàL¼úíâW:êZßÎJ%Üèiÿ'·ëÆÁú`÷Å‚‘2R›Œ­'q!“„ I5›+•ñ³›´Û¶qÕŠn˶…T¬ê~ðõÕ8ÔáZX*À¿‰T,˸ÄT*K·”RëpÉ­˜¼¸gÅäåÞJ˜¸5/’~)v®褷KÛÎ’L„y.nP¶¾gCùóä(”ºj9Krq=K3QmʲbW³yR^]»±]1˜vr!ùÏW,ø ‡9?z3z5UR…÷n‡¡{vv¶:¹iGéüæ Æ³MÓ]ŸŒ¢=6uâ½LK£Í½»©+‹-¾Œ¿§iXŸ€1ѱ,Ž ¯ÿL]2} ¥/ï%‰çèm´8çcJË4 Ǫ¦wPÚ¡u:Åp°ïZÞÃPãHÉ \H*»Ú{çûïq–‰ÞÚ'¹G²LàI™‘YzÈÛÛÛ½‡:o»à²í°k¾è%'R•'6Á3Ɣ⢱Uo öØóC*rÒtêà%z*iQ¯iì‚¿\ß×W•á$W<$åÊ›Z ‹\ìªëP44ëG¤ÜX “–¦ÚÁ¥{uJSÅâäÒ4ÙV8ƒÊ,¦KVo$N±+Z«{Ò®ÛÌÕrx`*­%u¸Î‘O¦§í]‚¶s¶I¦|Ðbé¼·=û§e6ƒõ¿˜¬N®L,s á ÁéëÍ#Œ–$²T¬ò-ÙºŒ•iø¾ŠRU ?r®VÝn¿ÙÔ׈˜Ï ÛºvBÒ§¨r© VuRÈ‚êkÓÁ+Ò$óùõõúŽfX­s ÷BB`äæÓg^0gƒ‡Ô8‡4JJÃáGi'ëªnz¹0—UÈS\ÙÇ*)5",¶.ØIïåª„È Ž·ÆÚ[¾£¯šzI2åæÝ¬0â;l’ŠœI-^»¦¡¨‡¢å 3¾8>NÁqµì8üÀ ÃW¸=/¥Iî»ýÚÞõÖƒói§H ÝF¶v˜” QÝMZHËB½(TñU!Ù§ ¼¸åŒ²sN*=å7øÍÛ›ÚýI’ÉëøFçRsÃO¸á¿n±1BÏ¿þßÚ½9´{mÔD# =hÁÚÄâ’J‚( æÄ* í‡g¿¿&¡wë!„ÿTÞ^ÎèP Øß#Ä uKã0¡Y;¿cûë#T¦dêŠAø€t[SþÊϰÏb.޵˜FjO±90,¶Õήe8“eΔjø|Ë%üˆ‹ô@@¡²¬Z7æ\f «¾y,\ S›ö'ìä#À¾âJSñwè5°qò™¥ãDÒwøi7éäT„§`TšcߣÛÞ> †®×:Ï-œ´Ä›@¦4}­Ðpó3]ñ< ä_!|G#¶÷Ê[^$âIî•n­¬éû¼:l‘£âFv|ÃÒu¨p‡³øpÕ *<¼Œ3êñL Dþ ¡>œçšÎRhôÄß+àÝåàü«®¹¤±Ý—i8¹WÛ㪠–Mß_°-`e_ˆ¨¶û«H8%òÜÍŒöežN!½èß$¨"ÜOiüá¨=ri˜;mï©,àË/3E0¦Œžtÿøæ¼P›Æ endstream endobj 780 0 obj <> stream xÚÅYëܶÿÞ¿b¿Y œt"EI«)P»±‘6NœäЦ¨ ”+qwk¥­>ßßÎP;í9.P6°#>†óüÍ·ù÷FlBø'6©„ÿá&?o^Þmn_ï6B‘J6w˜öEd@ÿðþD[_©¼WMý>ê8´e}ÜúQ{ýÉqÑù6 ½ÛDzúh¶ÿ¼û30UäfÈTÄA¦6¾Ì‚("Ƈ޴[_¥ÊjÜ/Sïƒå¬ÒÈÓuáætkçNåÇqÖž«àÜ7ß½û ­+Ê®oËýЗMM#¸«hGwj†ŠYæ£"†˜²jÈÔˆTãÆêá³è" âØŠ^&€ Jyz蛳îË\WÕ˜"Ù†)¯ìiäдD°Düu©tSçÀžâÙ1Ùç{˜²\w‘w³ØrÔ'~ºžm.Ò¹Ñeì$8æÅº[€ }ÃX¯Ñ û­/w`ÛÖä}Ó>¬‘ÅL™Ã±º|ð þ¾rʈ.Zf‹´CýèÈ…oЈ]Þ–—ž `‚#Yë›; Û¥¶i v?ƒ{Lp Ü¥åõT _rað;Š‚Èûךš`Élç,ù ÛX`”кÈ=eªŠŒ´áï{s¾ô‡tC¿ÇÁt<”7-Úv~ÜÆ±§+˜%¦6¨¦‰¶lžé:`ìæbgêÂÔ8!~¦•ΣÙ1ÐûÊ2¡7t¦ ªàlWB€<çK A ៤‰÷mO3°žwö§¦34¸§úÍ[£{^£égÕâäA±)ßêæPVkWq°3‹¿²¦£ ÁʉuY„1àÖ.HyÝ Ì’G#–¬&GLúXí¬ÖQ’n]CëH¥Ž>0~+CKViÈxKÁéŠbrRÌÔ+uY£Œ#ìñÔy<ñ¬œ©W©.ÑqÕ!ó^—5‹ôå¤H‚pˆ_JÆ“v xjúq1¤‹i ×õY°SK}»^÷°O•N!<çù#±Êhf?A:Š¥kµ(‚DÉ¿„ç@†ž@^mÆ”ñ´4 Ùæy" Qd6·Ç„M6npcj N^Wá5¯‡"PÙÒ ¹ÎOk!@dÎ<üÙÀ½Ó(åÇ-ævç&ùäÖtCÕó(†3–nœHdFÖ€¡ŽAÂæ;Œ+Í˽«„¹bn“Ê5ýŒÁ]ÁÑ(±´BÕ×€4êÊ‹±8,£ßŽ!(®©ÍÐ_.»ï–CEuä ›\‰ raöÃñȼÔàßEˆ¿ùßo©Pal=*ì? 5‹ÆëG*(dòËk òëõÌ|‹E!ô'TÀk“Ðf/þœKkÈ¡·} hþ·Si½s%/-;úmI\¬Àˆ¬< íà2yèèä®9;5‘Í]qà@w™,ç e 7+Ý–²¸DMÝŽJ½ûq•¦KÞZ4 ª‘…Þ·[l-šúï¹Çq€ 0‰;®¡ßÎ'‰é ­v"¢ê±äf–¬û TSÑotšF1’¨ [@ï}ÙŸ(DmòÚf¬‡\Ómñ8Ðä*U6Ãs®[‡¡` _˜·õPUŸ«=¿§Ž“ÓFyæ“>_*sóÌ1iŒ½Xø¤óc¸Iübïö™óE$f8æR¨Ý<—^BFKpUa€>âÐã˜G â–š2§) WHt'ݦ?bT˜¶Ãòˆ[9qÆâ*tÏ@ª*÷­nùØûƒu:ÓÐ0cRQ)R¸8}-öë j<Ä$Òtbù@_¶ê!±§ZOi e®vëÀàÈ­ÁŬÌF¤ÏËÃÁ§¯ô¼r߇œÇÑgáž:-A¢æx”yÍ…ÔŽ¸¼zVœ`eùÂôùê³—™BZʵ0Œ‹F>³™"ÎBŒ1 A ˜ßÔy3PËe+ ]Ú8Ÿ1yEä퇲*Øêî¶ÄLv” eëéJäSé§µd_ Ω Â\O3(‹é¶I=W8º‚ñ¢nzwï»P°4­qñÙÏñhº+×;zPœ4‘»WO}4FÞIw4ËBEÚ芾Ц³:zb¨à‚oE€V´²æ¸Ç–6I,àäˆø¡m5¡§ŠÎ<å +8Ìžf#GGÁwý;l–‚BSã̬ó¹>¹ÏB[É©×ÔÅØ¶ŒyWÜÙM~ÄûB »n êêêM9â>ò}¬0þñ|YÃ^!§ü›™¦.0çb¼ùþ¯D¼}G3ûòHÍÅ™LåbœûËz-XÈeœNÄð9×N&‰wX{òžÖt%V¡OüÑTŒãôöÂ_› vàÄ„• ”YÎ%ƳœÄàn‹à;›ô¸£ä“È.BnžÅs:©‘¥Ž¤XH‰Œ/Ò¸Œ· —E0´°,|Ÿ[ŠJ±Œ K*íÖ‰¸Y¼(‹G\A }fê0Ô9ehÇå†õ PÌ}=½JÈQ”šÚ×»ð/·0g”mÈq͉ƒÃ>vØž‚9ÉK¾‚]–×xìÔ¼ÃE bÖ‹Fwž€,³âøŒÅçƒ1‡ŒY´]ŠZF³'q/^x^ïJ=§þô†‰ö¸RŒ¢h Lˆ—TåÔ÷—¯no!A€ i·CäÅl=™\0YMvÛ&Éd™îX~Q}.ßïÆÇ?Š0îžiô’$ÙØ"ŒÇ|]õ«ga‹-ºßÇÒËÔª·.ý5¶W!ëiáz¸VãÞc¬¼ß® õ·æBÕ!¯ÿgR½ûáçoa¹Vy5=\Øû­Äà·ÔT” í¦A¨²tª†{¿•h[``‹Ä‚H¯x¨õh\U•5=ÒO[”÷ß^¾"Šž€ËÛ‡ŸüŽÆfÍÕS„› §í˜ËïîÓ×!A¡¨”\BNòSCÎ Hn°䆔Ü`G o¹œ5Áˆ®ˆý"BœÙÆ2– >ÇÎáþþ>8Öà ¾[;Y­ký=È~ R÷MSÝ‚0 Èç!DD© ŸX…A(ŸÁ!¡Ï«ßûü¿ì8PŸ§ù¢-§hc`µ…;²tBP»¼"Æü5øJ2CP?ºF.tûz¨ËOÿ¯éN°q ‰$H“µ®JÌ»*ù¨«‚kc«ëî\ö½UWº×Dñý²G0 ânjÚõV÷§wms¤/Û…ì õ*Ú×ÀFhó5yßñ©té–^k*÷*4¶×Øò¬ƒƒÎs3ë€Om3ùY ½üSÐÜHRÚç ?7##¡”[ûãïþvœ? endstream endobj 783 0 obj <> stream xÚíYYoÜF~ß_1Øs³Õd7¯~°å8Q ;Êz¼Àb §g†‡ó°¢¿U]ÍkÔ#[Ú O L_¬®»¾j->/¼‡Þ"òá?_dûÅ›Õâì\xœ%躪D¢îþ¾ù\X¨zžÏd`È~¯ÏË]¯9鼿ÿøË¥QÑx`]ç_–~ä¨úQØ%ž¡_ä7§ø‹ýA:R¹ð#y"Ί¼n½&iQTÈÊÙlë´löyÛ’°²&ãÈüKµúü‡ª¤4¶1*ÌöƒQi^Á‡Aàü®²Vß;i¹6ýÀ°VEÚæU™'¼¹I°²>Ðïþ#vŒ|¿¢Ô/<É„ ñ&eØsùšÉ¥ ójÈ ‡Q`„…Á!Í–‚;·ËÐw€c[‘è~ÂòCUïÁ/ïQ/IÂ{ô¹ª#½g©Ñh¦ï4Z½vnº¼XCLµ-4`³Ûej4‰\º§±öçûàÜáK ¿Oýn¦‹¹ŠM”%’I_ó¾Oom2ºÞq<^´tI­Òµq”ßlV”I“]Þñ üxxA䶪TuÚª5M§"[oŠ$ zȪr“o1^x,ó«(žQÙ”"ê ˜°!»€%i¯T™jš´¾§éïÕ‰dÐ_‚BNµ³±Øý%Ûà íKZšì‹Ñ/tF3¶Îׯæƒ]³gÛ€ù}¶=aEß²‘üË2[Zçﺠ­á›ów—¯øh!,z½£"-D|oäíòí)*à*‘êÅ­–¿=o¾îÆ~À÷F¸ž_¹?û47׿r«›3–“u.„ü%’`­IŸ’Àž°¨S&ü¦ô³Î¯¹'T=fßDÂb ¥ÒΦ®öG¤«RÑx3*ê@IQ>=ÕT]©žE“jÁ½¤ç îeOÑ{ÜíàG† €ˆŒ82-#¯÷¿J¨6´ow?ȰIð$÷CZí.mi„Šj[UöäE±Ï‚žÈ¿¯^¯~´]³PÎ/šú9('ànÌPÄI—šKuq;-&æÑÄdK7ä bñ˜³µ¡­WXÕ+Ž®v%Ô8œáŒÑ±$çÎÝN!,Àámô:NL6¢íR8Ѐ'Ô€‡À}¥Æ8ÑÉRrÏQ¨¬k RÐ*úÝVtÀœäNÝ•´2\aUˆˆæGOOáH°ÉêüК„,g±7UŠý>ÆÅ7Þ61ƒˆ tmµ¸—é:KÒ!gR*ôkG Lù¨¯ÉpjˆÖHŒÑJS4¢³ÁÂ4Ch+xÂ. ÀùÐŽ8pu3g¡OãDb¤H©¿ÐGø‰ )fðhÆNxt8‰ V×J HÊâ€U«½¢€‹¦zôB>!ø¡ .)«Ö,”´@ÐŒcÁæÔX|n>؆ëŠREǨÍq` c˜ƒþÒäcðö8™:)\¬YN®©Î]®ÑŒj5¤GZè¯ †Ã€^˜!^¦1 ï+ŸT >©ÚsQSÍ UA”â™ðÅ5»ã‰EÏ^Z¾vwÄeuÀ.Ê´qÌ„ÿ”8vݦÎÀ8¯Þ^üË´¤Äxa°9%HtÕh€ÛÉù|D­}#6À´©‹ˆÁEÀá'å¼9‚vƒ‰ô±ÁDä/sâÿ¨bÔiî›V!b•^®ò¹Ëu·I§1G×tЗ꣤_sTÇÜè–ú h‰n5èÀ‰)×@…9,Ù †Ì Ÿ‘È %ò> ¬äÓâ†J\‚Š“ÜÄ. nKz@Õ%“6Ý; œÿh×Ñ.áløhkž1hÙž`¢Éè ZksT;ÞE¤è¨«6š7rDàzïFwt4nTÿ–!u…ÞÓ(/‡R•Èd*J{Ù—¼®JÝ÷ƒÑPR8ŸÆž”üî ø]©\ôðá¡§Ù©¢xI'm-¬Ôö˜z7h¹+*€ðžQ§prŸow:?ÓtŽ“qa.~UÆïÛt€vxTpß {èo²°ËOæ™7ßXrî䟷Òû±À©Àk뻼Q<\‚ã Xéðmf0(Xžüó [TñqØÒ{çä1u¦J1 Ûñõ_ޝÿö¬&L‰b½ž›w‚Žî+é_ºc¬†«Gq^>ôk´ÊXéÉ ?ûË?þÇ´a endstream endobj 786 0 obj <> stream xÚ­WY£F~ϯàm@÷ÐMÓ@¤<Ì^É&›h£8Q6R0n<ì`˜p̬ÿ}ªºÛ°žÍF¶DŸu×WÕÎ?w|øq'ð÷lë¼X:7oxäpŸ%~â,s‡‡,‘Δ³\ÿé¾zýæ7ï¯åpPŽÎɄɨᑗuõÁçrÓ7iWÔ•·‚À­pÜ^ãLº…]íî4 òºÙÒÖß–ú±‘Ï¢ÀÒ_¼ÊëÚ[„"„á*m&ÄQŠ)i3oÁ•¢O4̮؛…ˆ‹è³00·ß½}qIßwŪI›B·V§š)‹êžVžŠî¤¸ÊpYô„³k žJÓ|°9}AÑvºÂµ®ÜщÁj8NéóèÆiÙkº¥“Ö);fÕäñƒì¤å„‚ÀªÚÛÖ†¥dI46é£I»¦HW¥Å³§;m+ú²Ùª4WÔ¢ŸŒâ\!XÂG¹‡Ä4Û°Ë€—„ø=Æ ë\Å›ª7Dü±fóG/&rŒ—·y‡ &D2Ü2nTXÉD¸iBW½­qãÛM›Æ£¸ùÐÔ›&ÝÒPÊöY8ø§Ãõ „TîGu´³GCœäM½=!ÚÖ}“Ùñºhà^Ýì, ŠËébnk…å\2â¤r•:­f #åU»4G,NƒkTÂ1êÃЬ£ÑtÌAMOž 2rT”€`ÖhÈòµe:M?L äµó¢œ¢.Cì¯Ga­ølIñ呸 ‚©ëÛ¯ª)<›Jû¶³]Æyã1)P1?8+îk®9߯>&âÞ·S’£ÃGù²Ä¨”|ð&ŽgJ7"ü™4; $_´ô…>vML°‘Ã/¹—v'¢¨ÿPž€Ü¾ Â8¥Ï>£ kˆåAœËP™ö]\Š+È#•Hl„Ї da|T+SjÀß•¦ô´6(Š|ÔŸ°OC&vö)`[aÈÒôwmU˜yÃŽìó% úÖv¾©… Y¥ŸP6„ZäøH“öðÞÎ?W€DÌ|õÅVýÌCDŠß©ô‰ìCä÷ªø_ž"'/Ç‚¸:´ÇÑÐÃÀ¾>"Û(+l”Õð´‹#û~ ‚qœ;XØ;§;ÕvGc†3ThŽ®µ;hkìâC™fº½ž)-GfßœÁðæ”gO¡hÿ žÿ’1~`Kޝw"& JRWÁ¥ÎþúÍ¿ý\—à endstream endobj 793 0 obj <> stream xÚ•XmoÜFþ~¿bQˆ—h^%õ[Ò‹ ß5mzñ·ÛN^ɶ½l%mmþñG9ZÉ–/=$°f9$‡ä<äpfóûFnbø'7‰‚ÿñæÐl>\mÞ]ÈŠ…szsuÓ» l®ŠEïÇíNÇQÙÕŒ\}Øþûêï ã6ʈ$MXÆÂÌË|úü9]t±UYÔmµŒú&½ØÇ+Z0ÝH#´q,¬âT(å¥?¹ÝI©LtQ=”hJ,«„ÁÅ6SQ7©{wa62Yœ¡"iEf@Y&´öº®îÊíÎ8Cò8¸éæ¦P,þùú[ŽÄGdÞ1ÇBf SkaÉ=y–FA–YØg"óB‰°Ö U­_µ[•D#„]c‹hpè¶;•FEÕÞáçÏï>]~ƱŽ}w]— Mù˜‹í.Õ)x4³gž;†SSòÄA@‹wÁ,©ƒU(ƒöœê|¬ºB¬!º7øÕÓòZ›óò8±¤ûí~õ~ˆCYó—òàµýï Ϧ’D¤fA3Y|;Ì*“¹™Ô[²å˜ß–ÿÇêZi‘ÉÅêñ7GEªæBû­`Lf3¾–©HSˆz*¬žå‡M¢},M]®Ùø\Š'ä S9w,Fޏ—f—ïïªîäýæ!äŠ]õr)Òp—ó’]XìÅ:šGANOª^çì<ywúC>pnÕåvóv]û‚QÞVmëíCZÕÔ§¦%!Iñ LÑùÛ2Š/ ÃÙ4Ï}vß;sá´ÜZ7@·¨þ¨|½c‰#£pð§ £™Ê=â².†gÆ¢Ä*' @NC‰MÉ›‹ DHž qææ$õœd" $mâ9—ñ$9'Y Y¤mª£‰ê‚e¿o„ÎÒÍýÆ9CtµQLl6&–"s¡Þ|ÙüöÒ&¡ôh¨" eÎ~ã rÒ%*ROheš¦‘}’èƒN“HÚ'Ec`°OÚñØÄO&ᱟ•ÐxŽ©»pa)q“I ÓÙ(“‰I£_ò‡NÆa¨­Ž~9ùÓâšQ¨¯3x\[L6$ÂÑ ÿk;«hX­û±:ÀÔÓ¶¼D’ކ®)—Ð z“û*FXât ¾îˆgP^‹)ìÑàPTû’§!` 8-J UuÃúûÎ×Ðá-ý¤ ¸si2“©:úÅá,ìB¾Ng䔺u‡<÷áèX˜ù¾®nÏy§8çϬ:r×øó)×>cçxq!àÉnÁ„Uåf íoƒŽjøf(ß×õµS{u$ß•_» ¯Ô„50ÛH + #Í_ §ñé‡ÜÃ]wª™´¬P0yÓw $qœŽ¼XGä”~æýu5öyÿÈz|ùÊûüàKêzÞGåáp‘å¾ïØO.Ìô«€ŠÛи°y‘Ž›­U+V†]DXØuXX¼¾<3¶¥o¸ÍÞ†³ÞÄp'˜ïíd”N2¨¤lV[’]P l*£÷m8Å“ôì7õÎûÒSr¥ñ³#¤|Å&_ñዽ’g\Ôg^ÏWdöÙ‡ª±À­â<9ïÔÐ3¡ìè`I×TТ˜BÐXM°×Y"¤z { 7t®¯pq÷J¦ |öúK~Id `ÊÿI;¨¹üüÈ9Œjé³ -œxV}žUß$œÝÀ7U_ÔÙ¯#‹J<ï’ñ¡È&"YBpUø9k¥…\Ë Dø6_ƒ-¤Ú.__ˆ×A­Éœã¬‚2¼©îüü£mnÜéôH¢mF—a¼›áU¼(©[«;¾sÄäñ‚2sñ›h×(øHôËŸhAàx_.æ_y1¬x“w%üáS¸àªuÛçMC]° ÃX6Üš>ÞÞiÃ;hø¯¶©ø˜ÉÙB#.‚’ƒ€ƒé¥Æ>£%ÝágÓ éÅßkÕ°P¦ þqx2¢ñþÀ ª5ÅÜýkPÓx7½&ÀÏã©õ\w>G€Ï?`‰n?ÄD¥ŠÓx籌xP so߯>ïJÿÌ,Ïrç7”Üïq‘ïü"ñl+Ö£ øÖ‡é9fÓ3f‘-ç‹È~_ûG!û`ïBon&ð;ñ껄RÖ? :“R¹‚ 9óþö—ÿ¢ëà endstream endobj 798 0 obj <> stream xÚ¥XYsÛ6~ï¯àCgBu,” Á«}ŠçèÄvc;Ó‡º3¥%H愇BR±Ýéï.vÁC²k%{DX`w¿= ç³#þ¤ûðï9‹Ò9¾r~|­é‰ÔK«•#C‘*gŽ‘sµüÃ}·šÍÏw3z,²fI£Û¬ÅAàv·šIÚN7yû‰Þþšýyõ+œ.ãññ~ ‚„À£`Š1ÿPÄ/¿ sòŠž=›E]lËŠxË#|&°˜³4ƒ€4ƒôU›/u£—VL¢´Õe©«™»¯Wö€uUÃ.aÄœK /€g ÂÐx¬ñÜE7_Ñ“ä„Áµ'UÓvô²˜ù@Öd À§X±Ý ºXÒK@Ú+7d&íΞe]YCã&êG±@òH2¸ß?ƒ=+•E/ÜËß’«¦.‰ß®8°@¦"PcÀ¬€ =ÑC¹ºb½k†‘íKYÇO ‰ÂµL`—dž ¬!`bHëá‰#Õéo—þójoëmÁÛ¯95#‹Q°!òj P#ù]^­­ AèŸ ó“«ý› å;ó8Ryþy’’EHÏ^žžX9–ù"ëêf@ïçg8¦‰ˆ‚Ã8¤¨ÚùÌOÜß/­8«ƒ8K_ ÆzD»ÌºlP ÐnfsF/òÕCxSc¸Ý±Ÿ^Ïé´Ú±½ž=+¡‚X‰”p ýåüýÇÓ³Ëo6‰ŒÀ´ÉlÚáÜÉqsí(ÛE·m2Žò/³0„x˳›BJf64§(Ú9à»b'Zä~ü¬ž 8Tz žíÅÛo‡Ö—Rø؈ö+|._ßíç·Œ˜ïšú0Îkjן;”ëÃÄh/^ž½9ù`…‘ðÕ\Ú¯+«ÖšÝpe%[Ö[ð»ù¡¯·ÕR?êxÏc'">0½ŒhÏ?ž½úvÌœ&>ŒëˆöpÌ:ô®\‰\‹]›hí´ŽNC\MCüY ]‹ŒÓíÉÙ+´ÔËY¢Ü«YÀè©R!¸IGzô©É“/õ,”î¢Ë¡ï·,A"¼{өдðX7õvCCƒ<-Â8Ä^¢íÜIVÑs,*ï´<`ÃMm·‹…ÖËþXîKùÀ95Fa ÒtÜYFa̘ÌC™º¯9;¯ï³rShlË¢»0Ù-Ç@ØjÂÊ,³–-½Ãä¿vÕÆý¤6ŒHm°Ú¼Ø¼I“·¡Š0ò]e 2´Dí-Ø•ížXzöaÈ÷G´ŸòÙÑNA"vÔ%Ö<ÁV´¾,3”à‘¢Ån(ó®³Ý¡uðÄ‘ º×ˆýQù‰ Q…?›Ké+°Oê»ÆSbÅ]dâ4š­ÌºG\ÛfèŒé¸×³8rtqM?à,’SØMŽ;~ÍúØïeL® ϼÜÜ_в&‡Ê_ m4-ùLorò´€E‡·kÓßë¥i`‚d‚ËdÆPÞMÎpòÎŒsÑ B-}~^¼áA³&°¡›E£^* 03ÎID2vãÆõ~BÅÒvCgugl’‚jFNÑw ø;†«OœP +¶dj-™Šâ¾ºZè†iëª@GJ<Ϭ¯çÈGšQp¼ÀÌÝm^ô‚ñÀfgÝoÚ‹§¡@ì}üµY©wj(cßÝŸ4÷z¹S,XWÓða¨¯Ø©=þ?(Ïaç]M3Ys“C Ò<”…®Öˆ1Ž«š•+rÈ$š5Â/\|&%}Ër”õ'ŸÔô£Ðw_çºÀb¢<2>-8~Ž™F!#Ž0Z®jZÙÀÇ.väª"i|—ú‰ºÍMv…<ª|ÏÍ…6\ùëéø ‚9”†«ÌA¾Î+Z´Ï¬"àö—êó<"×÷ ½1!åMe¢)yÔ‡ ]˜`¹KÝ9lÍU ¼ÝP}¡7EV}:¢P#ÿ†É}úÄÒ·zˆ+á+_aÀHgdÚd®iƒ­8]é}=m蕵-AF(´¨‚Âÿ–JŸ1«9züâ‡#p$=° ÷‚ö–gçÚHõY€/¦w#–z”žiˆ—ÏŽÒĹCýÂ8‘Lbá÷ï…sé|à ÈqB÷zBA>“ÈöµÁ¤œÊÈID™r*#Bû¦žð.ÿ˜Úü$ésŽï‡Ì,`¡¡h,jn/–8ŸýØ ƒ›V&ã>ešz/˜“5+þîø”2^Ì*~/ 4«¬Ëm”VõË¡pât4.¤GŠÑM"0ܱRöV¾{½K™ÿqD@p¹½>úTMïóÊB¸xíž_¾¿žÙúƒÄöîDMÌá{æˆ$9Î A/‚W~0É`¸´Ff„&²7¹ÆË”o ‹².†S¶ˆª€¯Œ•õ]Xeß…©Rg·Í抖NM”H™¡‘ "~“M>"Ûð²Ó`‰'?n|? ¸¤ÈU¥J,í‡ïþÙ¤õ» endstream endobj 802 0 obj <> stream xÚíZëÛÆÿÞ¿‚( „‚­ ÷Ň›|p×h›Ø‰}@?TÊ“öND)òLR>èß™]>tÔIÉ]¯Z$0÷5³;3¿™í\ð!àAÿñ ð¬wÁwÁ×RXeÁÅUÀ5ËT°Ä8¸Øü=|ÿy·Ix¹X¿uY¬K™É°Êw¦Å¦ ‹Š¾«ˆ+Snܨx¾Xª( ¥ý¦a^mhBÓg—#ÛÏÄ ¹§¡¡™²®®MCÝ6wÜSú¬‘j›7ùº3M»øùâ/Á« 'Ö»×®Ñ\“`DeY‚rI­˜æÁ2±Béi®ïêAÆ’é‰"œ2´úØ·SDݹ“ÕNt9è¹/{ðÑ–…éU‡f³1ÈPªð²Ì«¶ÌRyý§LKKóf¿3Õz…Z…y¹·ª‡¾U=|GªOx¨èC†Fìú¡FYìŠÎn¤]Mƒ\Ð÷@ÁvMÏi$: “èH3ÝΘfHP«/\¯{%[•)öøD‘œ ·º¢Q“Ó¡±'ÂMÞå4ߘuÝlh }k6 ©tø²ò²ºÛZÐÉ Ç”ÅuU7HŒ§Æ'ýó0LA[C äРš°3Ñ( ÕŽ ÷'Piì·uH»*MÃʬMÛæMQ~¸Óù°'=+G©W ¢+ÚƒSmê²ÌÝ Z†–­Â?¬à¤Zh€VyÄRw`*»jê©Ænªó[Õ®,Æ`Ö-‹UÎ,¨ˆ£¦XµÅÆ4ÞOro?½ÛP`vtžÜsX ¼ÜzwpŤŠÑ»Ñz*f"³²}Ç@‡œ ¾yùÃ+D°ÏÚ뼫ê®ó†0<-EÆ$!áÂJ˜ˆž“˜rÄɶÚm½/m[zW¡Nç™ô0š’— ¿N†?üø~ (=qh>­Í£®oº¢®ò’¼êÇì »µÏñTqx»-¼ƒ‰˜‘;7`9³1Ô±±—[Ègµ@‡h1釩åµ`GÇqdć·h溷OÆ¡:‘LI°© —¸ó]C Í’Ä-9`ŽÛ–û]Õº¨eLŒ5Áÿ¥ì<¼zß4õeiv„N¼üª¯è=G¥‹>3\dÏEY÷µ.2Xn8Äøþä÷'@tïN _(ÎRîЯúß-d¾]HþÍâI…­Yãæ÷#_¯3àçz‹ÿX.:í¹À ¨Çv—75o‹nKô¤µ8š8t2ϱ9$RŒ`Óð¸Å‰c¸ÉÅïÞÂigp³TŽpƒ<‘¹…Š’ÎŽ½Æ!ÉÚ€säf{5\X[Ü…•$½‹ÇÎÅïâñ¡VlÐ*L·7„€ua±Öu]9ê¦FÊ[ê¬l`íô2TÞÈÐÆâñž˜€W XxY–ý|kŽ„ ùJ ÔÜZ¨~\¸'ÅàAWp_ÐÙŠêÚ5»¼;¢¹Ì’E½ûÏØ\ßO5ë rì *ä4¶3¹·$d¡ÝÁ 6hù¹uWñ Ã}5J›÷ä@«Å w:=:]‹Á‘KÉ‘VQq/f4Æ¢`J8A¾A¾IøÉ¯}¢Ë–hP‹‰]1£‘˜)ô+¾ÛŒs¦ýfùÝ]l8½»É(áyRG?+B«ô fëY¶ØÝÝ"a*s[<ãs1J²D {<›•Zü^9ã“rúCˆ'S<‚œ/ ÞCµŸ$|1ݹö[>‚Úª9)"ìñ43G¯ýì‘Äñp€oæô0ò‚g3Λ2uruDKté…‚3ƒëˆ¯ŽsBÚ÷ÿÕF :°[•ð#ÄSän·Ú¥úæÃž˜¬ïv°ùÉ %¶s‘/¨Üs#Ÿ|ÊÈÇÿÑO½ü"ßùrŠ'ó7ù’G‰|ò‘#ß4lÅɰÿ*ê”#\ÞÝC±8=ám’Élا€ö§Ç/ˆ€¯¿xݘ¼óD‚S, QPߣê̪ZNT­g›<Û¤÷]¸òd• ò¡Tžtùà* ä¨<%§:_Nñr>a•gÐGBÀ¯J“áÇRG~ê˜ýÒÔqœâ¬Àùê œ¿.2fªhOÿDøOùô©Ðÿ3¾ßlƧïWé$|Ù>¢iÆ—f|SuC‹X’Ž÷ÝnMcf¹Ù%Kñ“IèñŒ%er”±Ø¢˜XCRš‡Mq½µ¤å– h0†5'¶X¦Q¾©;Cë)èá´­6Æøx‹½éS*móé&ëºiŒ{¡­«}éÄébwSëΖõ »1x+_,Uº\&5åûOEYä V^2éjÁM‘_bÅGdXñ™…^ÆÒ3R¾û¨Ù4wOš¨ƒ |s¶ÕCq°cÝšñáʽ;™-ûd ‚˜Õý,]8L™LÎ* ”Ee°ºˆkð™Øîk_“}C«üeD/Ô‘`ñ¤ž3<ɺ猵Oä'U”iñQºâ£r‹zòášk÷CZŽ…Ý±±Ž> stream xÚÍÉŽã6ö>_!ÌIÊŒ¸ˆsK‚Î2˜t’®Ì!•ƒZR•5%G’»º‚||Þã#%ÊVõ‚\6 .o_ýñ(2ÿ$*Ñ×wÑߪˆ'Ì$&º{ˆxÊŒŠö¸ £»ê×øîPïöRÊø>áªn«‘fò¿*V74OÝ·è*ÚÐn>¸ã]?ÑÆy¬«¬ŒÇCnݹ·»½Èâš&õñ4í`ú¼ËeÌv¿Ýý èßóœ¥Ò÷ú|¬‡¦,Z"~·KÓ¸hÏ5)xÜ?à.j@×wû?ê¡§ÙÐ<û´?)pdl*8}ñ-OÁ™²ÌÀõxï[‚d&Ã}Åt¤1­,Dã BÙj–›h†˜™JéÜ2 “ñD³²±"w MGßÉê˜zóý­ƒ¯Ë©éÝö=Lk{÷^hÉ$$Yš:ª­hÛ™~ºß±Ý^e"þÊJGɸêÏoÛzOÄô箲w+D:Ýc]Ýï°ì»q ¥7ÐÌ,üÀÄò“­øUË|‰¼ùêõw¯n®™%ØXXJ>Ì ‚¼º#›Î#®˜TåÇŒ5k<ö5Kw{Î…Š¿ùéßÿùñ5Þ˜¥ó×Zs! “2ðˆD’, '^8žŠa¢áS3h4yMWýNý@ëe1TèI\ÄO‡¦Ü dn¥ RieÆñ„`ýPy£Ìêçh d¶žàk&÷J€!óP¾VAÒ+H¢ÖÛó±sþÏÿÌHà>`Ì>ùª(‘P [%y\S#žXÖh„˜ñk1«Ä,‚ÄÕYv²¶‘Vû®vƒÁa²6°C³%Œk õk„ 0鲩;”Ú´éëŠkfr'´âÚ×!d¡¯ÿoËl8Ëäâí`¬Wª4aJ„‚.Ú7±#w B«siltÅÑmLãÆkãÆEV£7«d $q.§ó`Ã$Ì)LMÞ>â1i\€MPÊXÓtg/Ý9¤‡åönçü›çVWÞùзÎ3›îMFÀÒp,¦¬æ2Í8+£4ÐŒ«"碶rH~`B9DcQ[9ÄÞ Ñ}¹'‚>×ö‡«}H4F±£(Áqx ¥éÐŒ˜ýâ*·EªÈ#¶PÓèaè·[jŽÇºjŠ©nŸÉ¾¼dgMœ†º¬†Ô ½VÑ¡­G∠ÒGȨÕgéHÒÑkIY„3)8-Z~,)苪óõEµDœ7xê'4µÿÞ:-SpxIÒð€8˜(ú\¤Ô‘V úX§ “ ‡([HÐÔ:@NþŽËð‚@6¼äaxÁ­è"EÊ’ôïE—Œ‰l .7àR—1lèE‚Çæ©-ÊÚÉÊØqbÍE¦Š%«*¡ì‡¡vÚì;o7*Ô¡XÜŽ õC£´ jG•%qJ‹ÚͱTÄAB-øSžJëO¸ 4?_@bæÓD»>à8ÈšDIá`jØ©héT4­Þß{&·] -÷Ï+݃86uÿÏ9ì]˜õ8;À¥÷ª­õ\b)Eõ¬R®TW…AŒš÷xïC–­lV{ØMºG,ópw¤ *TœPîD—ÀS°°£m[z>¦É ³‚M20:]W_‚¥/Ô3,ëˆwMåe¦3_:ey\žÁPg-d:¸ _ÒœXÒL6ªkwÅ$\â×+á{®Òœ«^¡³¨ßO4ò:µõ}?W&õ;ÖÃͪîX¸Õƒ>Ð×Y¡-¬Ïz­ã`©;×¥²aRF±ç*äPzÜ”;Vxèæ+ž,KÐÉŒ?78_™ó7¶*Tö‚ýÑžMöB™þW‘¡r— a0K'³TÔ† \E€þn 9¤;À–ÐB\cÌȶ­ØµÖy·‰Gi-ŠpåÈÜÒöÇfšlÔ²-p;¡>\œÖõNák(k9¡žÜõõûSÛ”ÍÔ>_&à‡çYUÇvEJåLj×i×Q_ù©-‘ }jè°Òa¯ƒˆœßá2µC8¢€¦“°B`×)#ÂäfwVí®Ì8¬´^j‡’„iîr/{ÍœŒû>ß5‡›ªw™³l#ªÍ]‘üxWij¹+2sWd\Wäù€ºšd‰õûÒ™Ra]Gd\Gd.:"€¸|ìÀµ;dš3¡?á±C¾øØ i4CPo)» Ì ì’^¤Þ|çÃãõ›ši¦#Hó†e¹3Wµ À³[Ç´BrÃc7N‹n'(’‹Çú3(‚ N¥€YHÿ(À•ù8AœåbuŠÞ`”ríuÛc½.ÔÕÜ~ÁâÁJ%.ø€|ÕrÉUË Ëóÿ§ž+Šuœ`Ï•‹ ÇÍ‚>®Ê)Yâ %€üú9O䉵pÚ½GÂÊÏüÊÉ¥ô—•Îùló|:E+L5SĆþ¨Ê¥H˜0pH'L{5·ÿ0“oB¤0”EãØ^I»DpìØÞ_³tÀ¡µ’¥ér…@˜ÊÃ&Ò.¬{Fõé=#Èâ÷8Í£'Ôxj–æÑ1â9t,ó¼n£_œ€Sèw º'¤Á”B €½0Áê(gFÛìÅ5Kap–øäž‡º˜Î¶3>‡æTÇ,=œ@{ÄfTžÍ ¸â‹6j ¹KŽFòÃÎJ,ø]•£¾¥‹PÃ-Ö㺵¹44¶44Tª„žÀÍ\Œ"ª¾}Gº0aM"XžêOCÿÊV*î *3Om›òÜ® $`ƒ^pœ¬žo…'À=ö"à¡ën]K¬sfjC›VgyšxØ_þñïšKË endstream endobj 813 0 obj <> stream xÚÝYÝoܸï_!ôI‹Ëò$~IJч;4ÉÝ¡½Ø@ê>(»²-@»òIÚ8.îï g(J+­Cƒ¢(bd%rÈþ83üqý¥QÿÒ(“ð—D»Côíuôõ[¥‰(’"º¾R# m±ÁF×ûÄ×÷Õf«”Šo’TWÍž^þè¸ØleW»ÚõöÔZ’L×n ï‘^ŽåçÙW({¬x¦úHƒ¯ç=Žúi#óøïWÔÒW»¡nbóÏëÀþm𠣂qDGã´,bM?θ|jJ–ÔÙÕw÷¨hØÞ—Ç=uõõ¾r:¾~›&SLòB( šQå/Š"Ã~-lV «DÍSXs‘Øh”¸m;Ò8ý…Çê¼?Þ·=/ŒpC‘º_]ÛŽ0bï8ã EØmeІ*aŒ³ã/ïßq_ïì,‹Û#ýÒ~dÖ™fÝ6f&ÐÌ'µŠ•²BŸ•ºˆU†‰žÌ(ɬ† è¨çƒÃ£=á6âû á;YD6ñEXD{ëíÊfž_ˆ$gËß­ØUˆ\sw€ÁÆÕͶMåàZ Ýéb+^0ÐíŒJ3af›3 yÁd¥„²lÒ_W-VY°87Ž,† sf@„•!Ä?Q`êøãƘ¸lNYàž†ê,Â/ š§¢HÙˆ7ë6ÚªÎFòÙ7ל´Þ¿ã‡îŽÒVšŽ^%­èÚFz·ÉÂ`ww1ÓeF€{†dbÇÐÁxË’ØÐe x°üÞUôÐ>`r*±ÙæFÅßßR3€ôt&yê«=o=éíïÛSÃSï ø0'•.šÁ’’e*èÙSÓCYwÔzsãñwä3÷è@˜:~;Ïs¸•˜çþH›¶ÜÓ~LÔï¿»òžàrüÐv´%^Ó˜†¿i„Å“6´Ò†1l4k3^<ìN]WÑ¢iR q§”§aœpOqvÍE@#‹-€£iÄ:Œd«†#¬ú4Ð©Õ Ø7IO)Ia¨i¦i»½K Ú…Œûå}DS´¤ZÇ£:>ñELJ҅ Ùã╟÷¶kgs̵úƒô<Ùôä t&ûÑàçg²œŸÉ ‡xvü¼ÿØ"‰Z9˰۩O¼zh ’)Ðêâ [!8pòÎ/{jÿWÕµ=nŒ2Ü÷î"áàößÇMpx àÃË>)¥êapqîk3€ß‚â:ÉÔ½ï3ÏÑ9´ÔY}zhê]=4Oç\ëöiŒÙØ$]~Ë£T ¥-æ7Ø_™‘ÑŽ|+²Í6M%€ùÍïÞ\ÑIèñ\¦e†ABzžP-%U/§û/>Bñy(»ëážžh?%nð¾Þ•Úо+;‡—4À|ê‚áFHJˆÖ%ÄžZo†Ã ¼zíÐѰîñ(g{—KT™È=S© `_9W‹ðWèeÍépäK³\ÿM ã}9àÙ kÀEÒ“soé34DíQ»F¯¡µ=ò8ÂÏ‘2K9§¥†®<Þ‘´áœ ûöô¡©¶Žä’E6C‡g ºÿê‚ÿ×¢ÂÒ>}+u>Ò'‹r`·îª‘Ì—٠߯ò…B=OhØÒ5Zd:ذ¾5QqXªÈÂ¥â«t-]©™Ž¯V×™&úŸ®SþÖ)¿À:_CÒ·–~²øõz¢OWù`;®ÍÙQ~AdÖÆß{\‰¶\Øì÷EÛiÕF³æ Ó)àB–EZÁÉ,">É ÈMVgK1 'Ϥóâ]:‘gwépÝ;¿K3•¡«ê«Õ}4˜q^FèYƒÒƒ˜pÒÍÙ›£™Y¡9î2|Ó ¤Ýû‚± Žg,ÏxïñsæU>Íß¶žvQу®A‡rà" $ÜÅó2Ó¢–ÎÉ‘Z\Dï¯Ð9zj4BÌV‡wz?mr_*p)¸ˆÍð"égYàÂVÄÂX_p3†Naãù†az@Ráó;.ÛZ!«Ü*¸tçäÁù‹·m©s¼YL8¶Ô¤‰»0“yu¿X«}#!…œ;W1²ESøÙ°"3]‘»÷9¨øÅ&jÃ÷¤)¨‡j_—CÕ0¹èª]Uq}LŒN)Ïèp/|öý †_`†ÿû•T¥ìÔ8‹•TüYq4E9°WÙ¤d´–]­Ö§×n­2X¨È $3Iã°§Ø»¶ÂÒ p\²‹ãŒCýfC’Ìa­2Ö7_Ñ—^ñÑÍ>¸ÄaÏù¢ˆâ”2ϼj¾ãÏùÇÿ]ýÉ{‡ Þ1¯=­pφ}NõIBVàAø8êêñ]’.™sp Ä¬ò„"³Ñ!‡à»ÇŸÇôí:µ'ÔÁõª6`È)o˜¦2Ó:¢ã<ÅYåIç•§Œ*O²ÈüÌ…¯¹Ç[ìK&u™ÓGlGø›)>7S”ë8,ŸPŽ’êl¯Úœâ¼Š¥¨Eðø4–}fñé-žη෠×q@{~°ç7YZ)Jå\”òû„ã­:í=Ç*OO­çü*WÌò3¦“O‰WaóÇ[õ¾ªîPy¿ìg¼rXÿÚŸÇ¿FByôˆ 4ØF‡(Í3!Ç÷&ºŠ~áCÞ/²Ü¥k)4è7™*—ÔIÖ«.¬¥ÔŽôd _KÿÞm³ñ.@Y6Ç# [ëžÃ'&3…(ü5ëGß?Q¶/?jž°Ê4ÈJJ<þcØq‘JHXç|~¢ .7@ŸGªŠ6O‹¸–’ÛËÐ=Å{ lÖ¸Ü9(»rs7ˆþ‡ lnÙ‘ RSWÃÌã«1 Yd›Ç÷=CË‘_¸È'‚™}ÌeŽ¥¥Oõ$Äÿ}eYÒq‡ïö¸ÅÅìèÎÒE2¼ÎÌXà%±I*͇}ØÓñmU'çÛð2VD]§6耳«ãO-µ0n¾Š->ñ• ö§H6ý†Á3»xÎLÐÀ‡<ýíg.bü7Xý2Fº»€Ù%Œù·,«¶ÍGþ ªÃ'>!ìÆC×B6:è%aþPvC½;5eGÍ~ ô±!™­ž|ÑdB³à‘ÇçÕá—Fä¬Î©pcR/ûËþ ¼ l endstream endobj 817 0 obj <> stream xÚíYY“ܶ~ϯ`å‰SÖ ÄÅÃy²YvJ—wWU©Êäšáì25C®HŽVJùǧ »Ëñ›k·Š$Ðh|} Lô1âQ<Êü'Ñö=¿‰þò½ŠxФˆnöð–±BGë‚©<ºÙý+¾jW"Vk)e<¬D¹_­áQ­Ö<)Òøº¾mh¶Ý¯þ}ó`Èc¡˜°-2ë`E†ÓŠ2Zs–*CQ[Š&ͤŒF’W-¢x@XU‡;‹ø ÊãöÔì,¨÷÷÷fˆ¤O€ü_ÜD#&‹ñø& ¾q‹ô?!ü”Gˆ=c ó ø‡o µ ·A;jMŽó;[HLð'-Tü‚\ ÛI,³ÍZV"ÈU¨ßC‹3Ñ“)…ÓÍ Œ£!8òBº!·ÙÓÑ()*ç÷ÿz÷r8OëŽá·ž¹ÁZŠ‚%%eš2åÃ]ÕUA{s–ý¦Í2†¶)zˆS*K|äqWßÞaBÖw%æ?œêë]…oYÜÛ<¸­7 WÕŽF놞Ã%»úáÚÒWÛ¡nb½‰ë`J "Ýÿ]¢,nÚ!Œú ë$®Âåè·mƒ’vN¬²7[­e|×ÿoÕµ›Õ³ q<&¿¥<ÉX²@)éÑ•Í-êXªøÓJë¸<œ*šémåYˆj[K‘eàåê»7/_\Ó¤5s5Œ)KÀ×£#”…Ö˜…Ês–C9Ä…ŠŸ¿}ÿæïÈ$Ó£…ƒu½58¶¤’æÆ€àÅ´^$ž‡ÀDמ;;1”Ý@¯õpG$ ÕͮޖCÛÑç¶ìŒU! <ÜÕ[t`»Œjܹ¬›Þç/Pó¥žw¡€§=er‹÷\D U›‹e5é`­tŽÑÀs—QùÛöp:6Ö¢üç”4oõÄs¦IO/ÊQ€¤ˆw倯çÜIoƬð´¢$“FaÐÓ(_º~OämSÑô&>¸ò7£êv4J…ÉÓXõnV4òÁøÆø½w¤#Ã~èNÛáÔ•Ò†nT¹mW—UÛ«—ÍŠ­ÖJéø»ÃaôÚÞªÎj¼µ`UxW"ìO¦t_øù¾=XÉêæÖ uÇrxDç7n¡ïXæ“v5EÚƒ4?{ýb‰ßNœµ=߆¼/ñ¡½z>\ðBž÷3±=,éÙë¯Á¬N\¼½Þ¿»l¯Ó£ Ñ…}ÿÏË6B…~®¬âÀwÔÒwR—NÑ£tQµ³Á´úx*›Õ¥à¯.¿ïªêqäM{†êb¯¼ ÛcyÊM®Ñô%D.m6G8>O=Ö Zª©É·ÿ|± ï^ý:A7©“bN¡æ1 Sâ(ÂýáÔ»S>¢O z6F¯9\›Â2/ À‡ÀGŒµ™ÉÜðhÊcEdížFlðÎQ5Ç€†Ád°#dfºg¹zi_º[{…ÀÇÂB@牥¬ÔŠ)Š´Å´ÞžßΕ³4ÅE9S”ä1Ë<þqOP†»ºLƒ êñž ¾Êeül–^ó¹ixæ‹5iĨÙᘲľk‹ˆ^Õ®.‡êð…î»j[ÁÅw5¦éåè¯pôúþË)øÏ‚»|*¸—~F·.JF$•q'¶E˜ŠÿööÕû×o®máæWaIÀÙ ”:Ê–GçΣ%-˜©†ÇZј· óÂøXN-,næ§‘Â_3CÅé±C4²ê,cÆ@y´kÃù3åž…X@ŸäʳpÒâx#AÙK=‘1í¢M8-ÍXQ‘—*wË·,òuùYîù˜2ÆôÂj}Û´«ÝÇ4v,éŒyÙ:R{¬‡áb·¶›èût‘ ©mÂXÛ;.]ð ô1ôÚ-f‘ àËTÓéE°ÓŤ.D§3[RêÜ* ^¶§®«L²ˆdæ¬:Ÿ˜AêÜ©óP÷:‘ÀÆ•?àóB¤P®r›ê3€6ý8f´m ˆ‹gjñ¼¬K¥lþ*´u!5ö(˜Íp9&[ ü@®âÄ׈©Ë£‰Ñ•pÆVú¢‹D–²û:[ŽÂ h˜| Îlø29üƒˆ\Ä×3;@µMøt>².ñQ,‹;±0¾álï&#ììþýS›œÉT6ËžgêxòPÇcÓt<6±‹)˜ÆªÞÏ8P;®g…+¸3˜#¶ ãÂ;4= ÐavÕçûC½­“Ïû½+e΂Ãs\  bWûòt0D*8èæ˜ÂðÔª*Ækë̈ßÅõ¦;„5 f›¶Y7Õ-¨œŽæ3®™É?i¶lÜ`-^©Ðê%õô¢’yÌF.Î2IÄÜŒ‰ß™ ¨Ï~õI°"^ òb¼n;œ_èH¼^Ÿ]Î~˜] eÁndëDžA ÃHADãt#eBŒyK”HªNáÙ·Æ­Ï­ ¸™'$rÞχ.÷x6ÝO"—_Üå+À×WƒMÊ¢`<÷Ý’¯;t=Ï®8EÞa¬bqô±ÛW.Áäî—ƒþ\smô´<ùòzS9‰ª†Tg ζq¥í² óc`:礽4‚ÙQÞµÖš«”ÍN’ØßžýÀ aS ÞR#žgLŒßþ›Qd9ý¶É”B¢ M=ëLˆ6rV¤æÆ¯¿¡áJÎe‹£#w_•àwåàÒØ1줭2,ZLv†j¡¥§ÑFÚØ±#.Ñ'†Õ …Ëø©WQXöFwÈ“¶I]Ô‡·×ï®igÔõÁD¸"›²záguW]S¹¬ÚÃ'²´Ý€ Bš@¯I"vEJÐe=´@e7ÔÛÓ¡ìhx&‡óÊçX)ép!]8¶}µ¸ žu‹B³¬ÚŸò¹Žö§?ýzä£ endstream endobj 820 0 obj <> stream xÚíZYoÛF~ï¯à#‰„ì^¼RôÁisµNêÆ P î-Qє蒔¢?¾3»K‘JV’íP†U ÀkvæãÌ7Wvþv¨Càubÿ‰3ž;ÏGÎ÷/iìP¤$uFS‡†A*oDÎhò§{ü›÷×èëRpB”@7µ¡¤'ÃhÀ¹‘)Z°¤1>æ‹ÀN %ñÉb% sVMi³Byg¥þÒJPºÃŠxÚYù¡ÕÑwŠ“ ä 'ÁŠ}8À+Ë/ñF Ç+<Yß+/ÿ¸W|ι{îù,qËffƒ/ânÉÔÉ“ ±`tk,ăĂíŽE²+”Ó ŽÖ‚ñþ±%n¸Á+g„jQÃx@Z™{‡ðÎé¤èùÄl%ÌØ²ÁÅ3óxCŒB¦}·ŠÑÛ7‡#šbëK'$k¥óäøñ”ίŠuË»@=1ÒÝ2òUD(E`A¢_üyz>¥L¸/Þýìqây©pG^ÊáÌç±påb"ÇYSVxºã¬šØ}…-š¥èT<šåž/8UzY Úz¥W€¡ž^Á™Ö«ÎêY¹,̹®ÈFS£U2·ÈêæóUåT ½=9Õ7Î…Ypææ×ãü¢Ñ"åE#ËEVå|ž/b£ÞËo§ h$¡z4R?Õk¯frì±ÈÁ%¥î<Ã…7úbZE‰¯ôµÆK™Ý €ŠÏ¼À󣄂Ãd­ÅÍKQÞ¹ï–d&Ÿ©¿B›å*,kT„¬r`Ž,ÁãIDFHkgJ»r‡à©NÜÎe±œ/LϤÿF[¹Æ@¹H ×(1d;½€ÕÌÍÇrz#5µJˆvÄÜOù¸‘—ÈÅ\3pº\Œ1b·¡Ýˆ1ÌE_2Á]9¿ÐM½®å9Òob’á1¿¾(äX6ž®Q6Ö¨ŒäÌ,AlaÔbC!mg…M]aCÐâ@±¹ü'kqw"«|Ü]ÊÅg·vúi"K„ îëCÄ!+4Žê)ºRL‚”ö,#èõ¢xEÝjYQôÞYÖùDŸ#—nôªI>Í–Eó ™ŸtúOU·º µrÐBA[z½³1Å™F?nðÅnLÖ1ÿk9É«i¦ë±Ï£4ˆûþÊà9í#ƒ ¬¼ÍôVñ ×ã‰]<ñêÌ•ò<7.ôR²¶ÔÀî,"þªÊkÃF¨}*6 ˜-¯e!³êF‹]z¡p³JfÀÖ3ï©zGÒ=]b¬@¼W-»ù57.NûM†Ql|<— äfî…Ôµ•r]q½@Îr=w®æ«ã“_Áh”¸YQcÏŠR83¼«õó²½$G!ý £Ùd t2)ÿæÕ\‹¨`ÁQ»oØ<KzGÍuÏBêVòãLL¦ÒR!­lسMgZã÷;^÷19ݪ÷¯OõI­³}kmä1P7lk#mñuéš›š8ÕGÕÖðÄ´µ­¥PªÓ˜qBŲnª¬10¯fY£Ï ra,ÀiYÍÛ§û>m³omÿ¢Öp,ª-|¸Pðáx|¢Õ\T%ðzþLág$ k“犙¶/–8ˆñõx;)]‚ÆÐÅ.•gi󸂵¤ÿѪ“vLfë‹Ý¨O¸U@Úh‰sÙ6(øŽmç?HS5òc[ÐÐYI<±ÚéMv»€&ƒe{JãA€òýe÷šô€ ;Ðh@ á @ýetЬ°U8ÐÎ_ oL“v©¥Eƒš6xªëvF½ìº“©Ž¥.v…\äYÕv“Ö_©gxë§$|µÂ7)©R|£ œÌu…³uj!Ñ·8¨€«/ØÙ$vÖ'±Ùñ fü;Ùa{´“ôìð-\ÒŽx ;áýí$»R+Þ–Z} &3|.½á¢ÚÞƒ>^܇«whÆ_Qè û]š±(Û?P6Pþ˜=:@¾>ŒGHø»Ýc3ÞŽ@윭ÅΊó“çÇÔý°ç‚s8Óx Óÿ@Ÿ)ûŸþÉ¡Lÿ$:éÿÖÇç$QÃv—îoaÀ ‰uqÐ|g‡’ïâPòÂN¾vL¾³Aó}M‹Ïb¦¶Û@ÚÈ™Ì{õ-ó ˜õwÜ¥ ÷Ä] nb Çm‹Ž(GÇ{¦HL„"ñ¡ c 9â‡Rœòèþ‡±4¾Ï0¦³:õü0vß<öŽð`›=Ñ¡lö$ƒlMð½oMPöm³çÿ²Ùsû‚c6{ÚßÌ×ê ñOàüÈüE y+ûûwÿZ¸\ endstream endobj 823 0 obj <> stream xÚÅ—msâ6Çß÷Sø¥}ë´zÖLû"—’  ×B®Ó)}á€3ñŒWLî®ß¾’%ƒ æÁ®N&ÁZé¿«ëÕ:ø'€›$1¿8˜<FÁûFë`ôPÄöN£é_a2›F1¥4|ˆb¢ÂùËlZ¸ù£û?“—oYž%‹í[/)–‹—Éòe‘äãÈ|‰¸±/²ä!O‹èïѯÆ7àšs €˜ b"vXQfinüãpêÕ&™˜q9ûgç‡`Œm¼D„د൒"U­cÂ#!ˆŸóͪ)Ò²œÀÖ¬œ Ž¢2Xͨ¹ªÇqå=™ÀdbP1fþ D„ךâ&aêÕ~r4n¢¨; ÊÔèêml‡ ØG•c¤è¹©’“©Ö<¾ +EZŠõ:Š% ïO£j¿té§€MV°XYcœÜ„§Ï –ž#]Õ%Òµo``Þž®¬â ø»%,;WyA®·oçJ¿c å$¾‡*=¶ @U H68Bs… 1~Ä^ªý^õ,c) òíP ŠñÛY}мZ2oo U#ܦF$¹=€5FJÍ×ûCU{BAƒ=`k|Mn‹[°F1—a·I¦ÖQnéÞÞ m±-2 Ò´F—I,Á˜hû8”fBç4œÌŸ?çé2uwýC÷aŒåå ¿>e“ˆÈðÉÞ’°ø\6pé$³“L÷U.˜&ËÄ}zœ/ܺåSæé·Äzq7n…ÅÓܪ~9Yצ¹tcc£áƒ°¾ÅÒI,Ýógî&š]<§3;°ôÏ%GÚ>—q^n7Ïf©ï7+ÇöÎ,MS×nÚ}Å"[fóY1ŽP)չΘ¬…°8±‰McIJéwØ_°ºÈꢫ‹­.¾º„(}àz£üŽPÆ…TCûOu9·ñÁUßõk‚¯ªÆÇÞ•;ãr°æü÷»?†¥…! uÃÀÖ#¦ÃOW½ûÎvÐoþ³Ûéý²mîyóMg·íú~·­?Øc»Ý¶Ýz›)£[@ªuCWâ×;½¾ëÝ÷Ž({ÕŒºǘI„«:°f"9¢ÕólN¹òå¸d5.&9ìÑäŸUT&Nu–([1jÞnTíS©zd`Š’P›n¢ÞÞSÜ ’¬å<ÉWrd—œ‡»!'ñZÎÞ)G¶ 7é’£éªKÐÅì]ÞŠ.;D—¶¢ËÑtyE—KäEè’CtU+º°–ó¸6åÞ%çé5d”›M¢úUj²£á‘ÿ'5É©~#<ÉÛÀ²??Cæ‰óVMhó\«7UMñ,]IM8D·-á€=8†Ý^÷únàׯ9ø´ôô2Ç=¹ÛZ½¯Üx56¯‰Š˜®Ì4óîe’Usûá?2+׌ endstream endobj 830 0 obj <> stream xÚÕXÝsä¶ ï_±o§±‘"%nÞìœÏqkï¥þÈL&«³5Ù•\I›wúÇ @}ÛN¯Ó‡ÜÝÜRàÈÅ?rÂ_¹Hü ›ýâôvñÝ'©V¬âxqûØÇ2„Åíö×àúÇ›å?nÿºVØhÄŽ£& „Ä_.Î.?:ª‰…^1U…a(Bü³<–&ÑÁ§3Ò©!yNìg ãXÚH˜U¹î'–B±„)½Z³R%"¿²~GëÍÅXkDÇ Ǿ:'#V­@Ï œ\’¡ÊGEš¡R…f%ƒ`ž¬ÏÏ^ ôú|hoxg‡ºIaûZN?ß­?Ò Z$²Ïºûiyl”N×¥‡ôjO/Ör#5t‡#>Ô8£GM1 Œ”‰ˆf_~žÓ-ÒßfÑD}Oϼ=úulNô˜7ì™èI¾Í/3‰ô‚SMgë'·'Ž{vKIÁ.¤‘öIA¦!m¸5„Tx ¨¹ºøD€ü/YÚª¬v*¾û¤¨;\¡°˜jP`DDîß>e EÁÕO74øRVû´Á±ž«r©’à÷| Ú€¢‚¿¿â%Ü8]*¼Ô­äòÐq ¿ÛÃ&/;N4ÙcV‘–ß—Æi•§»¬Hó2 ÙéL‚9{áœÃi…‰z®È(¸¥®ê†>zö!¯éw_ú)Y‘UéŽ>Òb‹<¤u¶%ZYÐï¡&`X?ƒS6È6¹ܧÕoè•sIª`“V[^êb}ûùí8'V»0`·#öFBjl÷¦F—â‘ò¸SkˆZFƒç]ºqÃ8/è— ~ø|ywµ¾!jmš¼,d›(æ¸Åzh&Èà"^Ý6ߤÛ`4^¢nÒªiw¢5¼ülCØá' «òðLCâ$~s0u Ý›rwØõýòhy ‰…ãâd ØDQ(½öÎÜn6DÏË{3Z=ÎDÑ÷D¿r<\;&îSÜ“Bè¦$ŸR{à¦ÕCÞTiõBŸŽ{Ø#ÜÈø˜8c"¿W‘ßìn‚Ûl2ÎcÄN  uÅO©;ĸ2On—ªÓ}6=öi=š¶M›”X­Zˆàˆù7(Ÿ³¨±¹>çAõHY¬Ÿˆ"̉ 8R$Ög²NEç¤%b9;" žÓÇì¿X^‡P{£"©“w××J õÅî—||uh„4ӄĘÉv>nòˆB©ØtB5 bŽ~ÅbEÙÐà@™y~nýTv<~ TDÙþ¹!TZ¼š%;£èC‘ú¾ÖžUÀ­A&ÑÚ€îœ},Z\ ÎÈÀÒî|XõÇ-þ€¥m± B)‚*¡Lú¥0Ñ"Œ¸*¸:¹þÛÙõ‡™’©W /M»‡Ô²Ù¶\È &T ”Tå3¤ë JEXóÇî€:w´R¡ïŽî @–ƒC1¯å+†õ×”„câŽ.­ŸÏ¹ªVs®áS×ÈWÞ¦ôŠùž¬Dhú³ÆÕޝOùÝ{‚O“xD<æ"ÇX‡2ÓÕ  ¸ü¿Ãšab_ލ¹®¦ÑæÃà­ÍWÖ m{‚ÚñÊæ'³Bç"„tŒ DYwiiãм•­9-ô¨Yõ¨>ôŠU¯ô±Æ—.YÀØa¥í¢õ@ZPkkšÒõ@@~84DÝ—«s Œ¹ˆyVà am‰ÕåÞφީƤÇÁëJw»U|­IŠÜ1ÈnMÙf›ôßù†hˆ€$ñÀÛvg b r¥ †év›cmr¾%GÜ9,K:„%–ÁX ä¸v5Ø ¦Ô 3»öÏæ-Q] At™ >äp1WS' G¯¾ú>¢Ýw¾9RþãŠû¿WbÂÝ®zÚXûK…}·b‚Ã{KOìÛJ±2F5P$zýîÕC³ï—ßÏõc\aØ5]^ÌߤO ÿæóQòuÇ£½«‹x⫞›?ôí.KkIÀ`Ç b*u­ŠøS±)+¸Âq†)8é8:BžÆ°ïMuØÀeNnw:æ·QÕ‡¶×ÔNkwY»s½Ö`'ú‚”)‘J%)é×°8ˆPŸ [QD8OînyZ™à7hÌ!h‰‚++jž¼æ ¥ÌEYÔ9S„qŠ_ Ã6¹†´¡z«_š9ÉíÙÓÃÖCûÓ¶Ë©ÞQ†SÍžpk?W|b+"ßRð;ÆŠÌï{ìVécÊ·Älj;S]]¸›E|,’U‡xm!‰>s<0àvÕO¹°s+2ׇܑ;~àŽ¤š¿:¸»‰î4â‰sp':í!Žp'|+×Åw[Þ¿F:œc¥aœC5nûRK%0šX¸í•´¨ŸÀõª'üÒÅmܘq®ÍÊáIÍ“—òè°çH¡˜ûf`Wœç×ùó‚œÇþß ?ýyäJõ@AÓ™îZŽc@ŒöˆÁÜdü5FGv˜npFùiBG*#<â'”ížtwtF8LžE¸ŒßF¸Ö-µò×üД™Í×¼ùÚß•`С¸êp£ó:u4‚:0êlDÞÔ4iR5Õ¨2*Öÿʪ’Åéj‹k4õæƒ3b“¡BKe ŸxÊ‚_tîÁ3÷âRóãQ}h;¹Ñ{QøÀP¡µñëOUè²}*h0zaqvì^ø© FÙ. Þîô> stream xÚåXßSÛF~ï_¡7¤Éèr¿¥ë4&4MlSc¦â>©Û¢6¤iÿúîéNæ\Î\úÐdíz¿Ýýövo‰~H„á‡D…_].¢Ãqôò F «h|RýBFã«ñër¹ž]«$eŒÅ·¿æáºœÏË„fñ³å'óªø:]ÜÌ­¼¼6ûïNôoVåżX|›ü2þ! e’#Á*Ål9[Ìþ**áË7;)…(e†„¨”Ï­Ö–ÛQ ±iù«$¥Y3Ÿ1"‘ʬÞ×Z¢ß‚X"ªƒGÒ¸E)¡9Ê€j8ßP~ݨö§%“.ÕON ùÓâã¸S-ñ–+}~ÄŃ«€·†k;!J'ÜY òa•Àºz±¿C:Œ!Ò:—˜ì̆¯Â™By¾×“Ï=(ÖÚÐÝë Âtyešø…Îe\Þ™Ï|sø’@ÏŸ®fS˜ÿ¦ ‰8©lðöÓ”#^û:ÁÔ_W juBÕ°=Í·LÔÁ¨|ç¿Zl@^„ýôÕÃ(çVŽŸæîïïLÙÖE‚òò$U„Å=«9¬Çqß•wëIbæ;¡ aæ^Ìòç`‘þç,Òç`‘îƒEQ³h/SŧbÕNŸxúØÿã²}ÐGôqqÙcÏßGXùîÞB!<¢wسêKãzñ¼,W«b}³&ËåÕfû쟜š‡ &Ül¡<^L5ÀŸúa_­¾ô¹Þ9>'TÆ…ú[³­Íž å0õ¤k'R•sƒ^ÿ¸Ò”°=Û(O{ýSŠiõÖY©GßN+ Gqƒ>pe7\ìŠÞZшdÔ•‰m³uóÈ×Ãgýq®9s…?0ž!\_„,~vê}Ö!kÝ¿ù +& endstream endobj 836 0 obj <> stream xÚVËvÚ0Ý÷+´”Vô–Õ’¦'1”˜6‡ž.œ@NC Òäï«—ÁÛXH3£;wîèað€ÍE̓Ûhgà䔂‘Ædw€¤9ˆ­A‚lüf÷“(fZ§|F“—|¶xpgyD|µo¢˜&0xnçf¦àx2öó¿ÓÕý|½òçiÖØ•g'fØM;Þ<Ë—¿­u²|òˆë§éã/¿~U0ñYæëDZŸ¯"*áëÂX ·ègöÅðe0$„+cxnbƒwó¥x43xއùršß<øÅ'§—Ñ‘ÄÈfQ^Š£!Òʺ%¢6’ÌEÐQÖ4ALMDîh3Z0à»õXjNÑ…S/ló¡ÇÓ'š#"ù³VÁŸ#Ŷü?ºˆnæ÷á¦<-¥Ã æq–¶.».RšV„ôW­Ë¾(vV·Í|½ïWÎc’‘òþK#3᎜—]gÁ5 >ÚàóÅÆoS~ê] /SO‡$(aeçµOÆÂ*”ò'N'o¢›öŒ „RÄ ˆñºÌT˜æè÷àÙ¼ØÀöÑY:­%.Ðcâà±Ö•ìã-}®ßicU‚}ú¬‰¾j ÏÑžìiO’ö²Š}-þ¨ZÉP…v6Î5ÿ_yÍŠ‚ o¨Ÿ¢.iRwÛ;eº@ËèƒÏ5[Þ8È¡Â{aAÉût!9¡úd„Û«Ñî ÓÎÛK&¼ý(”ÃvÚñY$±Òãò‘,gÙôˆpsí¨xÑk‚¢•7E ”}³ŽõPöý¨‡ ÷ ·\ ¯<×uµôƒJêûh>ZYkç*¿V” ”˜Ü’'~W UÄ~ýðª–Z endstream endobj 843 0 obj <> stream xÚ•XKÛ6¾÷WèVˆYñ¡WoiiRtÓì¡@·ÙæÚjôp$¹»[ôÇw†3”äõnÒ"AD“œ¿™ù8Lô9RQ T”iøGÛ&úá:úîŠt,ÓÔD×·°¼.ðGt½û]¼<Wk ×îª{¥™xµúãú'I#me–g,“ÀÂ˼ºzÿú7Ü›Š÷W$óf::ü§oÊÑ+x}M¦óHYilÊjtœK­IT«µRÚŠ«ÞÕ§cÃ6R±,â%T" R…4Æ ]Üjmµ^à½Àïm·´N@üú#ú=CàÈŸJ-MÚ‘ MÍÒ(È2gY%3…B™L/T d¿jW:#`év8£Ð#±íVkXÛUíž&Þ_}÷ó[öûØw›Ú5ôcWŽ¥\­3¥ÅÛ‘õ$SÒϾC3w뮯[Üy·×Á7e‚k ÉÚ#ÆC•Ãpjܦ¬ß‹êNu9V]‹“Zt·´üE‰É_üq#”T7«ðknV´ûF ÎÑúG·õÚ¾•%¦Èd– h¦¨È¯ÇÅ*8ûRè;[îÝÿ0n­‘¹>3Ý6‡Y ݬ$…Äšëf­r™˜³òQ†Ê¾7±²µ£1¿%}ŽuYa(”…0ß—ûïúj„”caþ^ذœ YÖdâu¹]éTpI/×UËj}ÜfGph6jESb¢A™‰²9 ±€28Š:÷`‚Yˆ²ÝÑšû }rýlGžÂ9& ÝvuMÌ3\å”8ѱ«š¦éÐÚß)´ÁçL0T0"hÑ®ªëo-ÙÍ2,7 r@IXã3>ä:2Z=t4š‚…ûCjNÅ÷2R'±¯ ¨Ö)©qŒá7p5ú„¿7”ë^Î'OÂG#yuÂ*w´f á€1ù(Ã÷P…±Ÿ<Üw+‹®ß , É2<4¸mƒ¿DWW[RÞ–@Ù~K.<â@á=,>[ƒÃXRd†Äå;WWM…•ÆÜÈðY±Á$gSqyϾ‡áV‡vÃÙg‹9;ïe9™¤áMãérÁw€ÉqôŒñ¥Äôeì‹”=óÕe¹ xÖ¨lyµ@+f€6,ÑFSµ€ÉßtEJ¦Áy¿pjü| ¨yž!Ï|°À¼)ïŸÑ… Oé*ïŸÓ5œ6ÂÍ ”£äÍÇ*‡Óö€‹–*ô±æAŽÍ$“: “aNÉdÒÃ…¥óÔC3{°éN-‡xiØOs1úé…ÈÞµ®/ë ž.Ü„…ç¨ÚÑí™—ºxþR,<§kSµeÿpyœ®Ü¥ªMõ·n!1Ƈ'üº½@ÅRÖ;J‰x©È1Šç峿 ]0V]SùLÉþ ÙaA´<Ŷ\(¦Á½Žñ:ÞýpÙ½ó¢ÙBtϸå+©6}=Ñ·‚í#G`$1³#¥7Üç¨M Zk¤½\Œlÿe;÷gˆ<¢C¼& …»ßºãÈXUs®¥Êføç¸<î࣋¹)|BO†·îyu6 ñÔV¦ti>¡Jçø’ˆÏã~®Lë9Ñ|¿œªÀ†të¦:bª‰Ó@u©æ'—ž ÆÔ¶#)ÞïGZ(ùËÒD»ò¾j[4F¥߽Α ¦ŸzP¤Yêy1Î2ÐëçHš"îüëx&‹šHåÀ7ág}Œ>0 'ЗYîÑÔÒB$)¤zrþꢽi”Ë"õ/F•"ž°7—*€&Φ†øN¯û÷íDœÂÍ÷f•«»#!½£MÝ8g|âŒ{x૊<þv ]Ôñ@'ë¹øå8"íûGÓ êß¶[Ÿí {ž´Áâñ4’ÜÒ[|(ãÐ1]è¼ÜNÍaˆa({Ãclß—MÃ[íÃ0ºÍÃý²Ýi ½¬+[êòØÁwòÆÔ,f¢íx‚Ú2lg ‡x 1çh@yVŸŠŸ¯>Ò )}1ÕútªeÂÛØ<~ÓþMëW°Ëôß¾M‡ ccKývŽÝU[1ËPkEo¿É[ÚM–ÀŸƒƒª-\T~Ë‚dd l—Øf<Ž8>5e §&‡|$π莜\þÿR.޼sö¯øàˆpa×z4m¨P˜ºuåxêi?¿­™—Cä,3J„ÈÁܲ岊ÙöTÍ‘ûÏœ ÅÍ>ûgåZüøþêMñÁ’%'Þ½ áe Ô˜œ?Àž+âTQˬ=ù®-§…¢0 Ï0k&Ê~S=Þã´Ãµûñ ÏŒžÓ¬§ýujé©§’<ìýðÍ¿¶‰âþ endstream endobj 847 0 obj <> stream xÚµÙrä¶ñ=_ÁœË)‹0€‡¼»Ž7q\N\‰ë)Q*†f03ŒyÌ’œ•ä8ùöt£›× %M*•’JF£ïrÞ;ãÃOà$!üúκtÞÝ8ÿ.s_d~æÜl@‰L:.ÄÎÍæ¯î·åÝJn]äë•'ÃÌ­tiÚÕßn~Gåähê‹4üxJ7€ƒÀ=¶fƒ³Ðíjó©Vaâvùö‘`º½¡­únå)åþì»üÃ*Œ]»î»Ûc+uuŸQè®ëªíš–ܺMß÷ííÊÂù®®øê+%¤\ßL¹—Å"I€ÏH(e)¾´Å±¬à¸€S©r?+Š•ÉÄmKÄ ÄÁ_’.“ìÔ²‹“µnyÖšªÍG6"=¸WjÄ÷H«Àåù± ÇA¡Àp b¾¤8ìu…øŽ¥iˆ 8އ÷ºÑkÏræO™êLCü~~êÿóà»ÏÁ‹—¦™zÛ3Ï›Î+ŒXà_ng9]’}/U “=ã16¬N¬ Q™ƒ”6\°ŠcKWôûºmÁ>’‚ûé4%ýÖ9 ì‹ÜÎB‘õÔyv,½çbú쳜3ìPÔ|õ5edÁB¡h¾Pú$¶ôy¹Ì R)2*´¯ÏÍê£ó¥Y}/íÒk(CT¢Ü×oxòæõù¹·¼÷vz{ôæ¢Bf"p0•ÐÝq2Fï”93¢>Ø:‘Ök»Ï¢ÂIkËœyÅ3j©yÌ©c+Ð-S &^’„ì·Z]Ùò?¬«Ã±ùfF$FX­â¬×÷÷ ˆ1½0kó¢êè]¡«ï—Ì0ŠÇ´B,ú>T{•‡^•£E­õPò@pZ£@g \’Š<9Ú/Àö‹;Üiû»mŒ)ÞvÝ0æå¡™éÏCzÝ軼€2qDjåéSWnc8då,žJ˺C³;‰ *ÂwÆ–VèÙ)Ô¯$ƒNx_‹ =>Øã`fëA5{uÇû¦0¥’®l›ºä=M¡¾j ¶¡i¾e”¶B±Xs>mkìúÌlg£Ñà©qé¸&ßÔ§Õú-e´ity( G´ŽA'Œ`¬ Åï­èïñŠºa[c–úâ|±ƒz¦)À× ääÌ ‡¼7õiÉÖ©HOõt\ËO:´Y@2„¨q:S¼äÇ'A™ž ìI Ÿôq·Ü¡¯ –ò²Êqå“—f2ž=Y›õ%WJ‚öe7Ž ¬7î0¡^xY¨„ /¼m„Ý™Ê4º¸’Y_·ñã õ1ØAæ•­¤È`-ImoßC›©T#ÝL³c4-ÅΚÙíêEžd,y!O#¬©6‹>4dR$ioømß+×åIÇÚæä=r»>¶'™ÿ$•Ï$fT§\ Í!R TÈ,™ûoDé6¥û'Ðõ†ùþäÔð!)O ¹4G‘„–Ӄ˔Mã¹_áúˆ¿fèa’¨í¨ÚŽögjÆoh—ä‚‹”cSŠ8) ÍB÷K†æ»°ÏžZhâ©çØ5DâyHнî[&qmÓ¦iOÊT,ÒËü= &yCZ{1F.=/Dá3±‰®Ü_òþ…ýûu_?§³î<°àÙÎÒ6o~.ñ"È/íŸÅʼBFê˜R?Œ;'·I…O2aØ»\-¶Š6¨”ˆj»dŽþØV\/öãã%‹ˆ“Öë’{™aQA‘rM/—×ôryM‹§ì~ïe©sˆý+âÒ ÒD„Ãwá|ë|ø‚N'ÃA"¬Xg݃À³8æ× ºZ¿øêë?à“ø‹UsêÞ·ômStÚ? ñÿÂñØŠ-¿È, (¦g~.4TŠÖˆhR>%Cù)r+IOÊzØo~òŸTz endstream endobj 850 0 obj <> stream xÚ­]oä¶ñ½¿bßN‹dy?DÉ×ëC rŠ ¨ŸZ¨¬¥½Jv¥‹¤½[÷×w†CJ”–ë… S$‡Ãá|Ïxóû&Û¤ð“m4‡ßtSŸ6½ß¼ýQn²”•i¹¹‚íNòÍýþ_É—ƒéÍöß÷ ,  gˆ ažÜ~ˆ¾´Ûn†íN"©pÉðrÚò™žx-’ºk‡±²Ë£Å´¹d¢Á ¦”Å1ª …Hö¦íF3ÐNÁèd¢V2ˆä ³‡4ËëÆ´(ê1úœLxQ|‰2´X¨ Á`UH[Ò^…`Ù©p*4ÃÞ*nßTGÃèÁ™æLâƒaïøgx™'­©Í0TýË¶à ˆH©"nÆT‘—jREœià<_¶Í¼RW-!@š‹Äa9Xþ40ÉÙì ™?T vª,Ø íŽæ2Òþ±i!P¼yhz³§G¦áóîíòÒq ¿K8Ž~k%ÔÜÒ™áë …a¡?áZu¤YÕîéãT!_^èäü\lÙv'¥J>¶3¼ÕÕàô„\ŒÕñ§ê|×zôŸ˜s.™œLýñט÷Ó,+ÄB:©ð€þ¹`‰êV„ÄD€ò"pê˹b¹^«/=Óx¥Gõ5¶3TÈ~p =\h’eHo»Ì‚iµ²H'ÓïW—ÛìË>ÏÃÀíx~&ð‡&µàt™¹·lºÏ[qªQ6 Ý)äè:zG­§*BOå½áÚQ ÅÕóŠ×Ù’íW  7HŽ.xÃ?"îMj«–CŒÀ"Åv‰ÇâÔG–ó`UÐYÕ“Ú¹wü.ÐQ*ï(Ú®zC½©»ç¶ù/GÓ&3Ò92í\“=Õú[0xêzwAk̾}3N8)æ,_XöBä{SŠý,XJJìÔçÒ½{˜ØøÓÔ¬‚—¹T§OG¯KùÚf/Hcöñw–€î)—Z}ð6ÌdLpKÖß›¶9á®’ÒpGÃŽ†KFãw4p·Ê@À,·.Ð’•¥6âòȇíb碖ÓÜO-û¡“ .zqK³K±xg±É i¹Ë¹¨fxô’²ŒËäf}N¤ÉˆbÐâcDSI†r³ jI¡(e±ˆPÏZôˆ`QÒf9èâpkŽ4 Q•®=0I¡Bé‚£Ò*K>Ž‹-3д¢axFs"TÝÓ€e~?WÇfô†NìämçÜDs¿ŸûýÕ³ohúýaʾBpB11 uûP +Oí•CnŸ]¬éúÓ+*ÍS…™èNÀÃRÒéáüˆ %MqfýöÇrUTL|¨·*M,©[`,;ù](LX©m¶³õ=žÉ"Hw(ÃÜ÷[1óˆ"‚ûa© 1ƒdyNƒNXŒš Jñuïä7©9E©Q,4ª¸ªËB"D6'Õ5Þú×k{=©R­õ°6˜@Þ'š˜ýÚgÐíïчëInËjoMCtwÄØ»Åì §w‘»dÊd¹»œò}È9ª~lê3D[f!VNö >ÍCÃú¡ªñ$¦2MC49¢Áµeª/SN©>~L¹¯L³)B 6ÕÇãþš%Ž'ªÊ^èÅSür©~:¥ú»\–ÉOdÃXG˜ÏöoɇÌàÿ!î“®xG–Â[²[çŠ3žŸ»[&+Zó…>jú2—Ú|é›\|* 3TØúª f84^>€œ÷uÏ:• Z1º·ëTuÊö¹6C[å¿YR_,»~OÚ­²¢œ-0ð‹rö‹‹¢_3î-áOîEÊŠEmú!â×Cv8rЉÄO@ÓæxqóW oÁ$820HLñþ>šõ¾Å9]>Õd†DÊÅñ}½¨ÀîÖÎ×î²b‘âr¦s(Í02ᕅׄ’äÀÿ<éFé}í]L€%Óâx{êýµJý…Ö82 X~# DXn‘¥…)¯ÈzMÖ»¨P˸í´tj "-X©BÁÝnße(âôé.K=NΕ‹hÿŽOE3w 5~iÊñVP^2)_-<§°²¦æV³ŽÿA³nê ÞlÖMßҬ˙ү–Œü{—Í:ΗÍ:»âú|nÍQ/UÌB¬ng…Ñê7.ÌòÅ7ôéäõé|í%ƒ>ÝT~ÆiQp™gÜc¼çñžaß<lÜÞ¨8ÅÔ¸Ùû~ ×¹õy놙pé1ªýŠ i¦ ¯cØiƒÊ "ŒëD‚cƒÆE³£wE+÷• ~¸ÆË­ºë{3|">·{ëâí}çKsl°—i§!±6ä®)aqúnže‡èhBU²±PEÐÍSeÐ6Y8ñcó[Ð Š7úÄÜ7éYÛÆ*V¸&×é«zóZ«ïÜ"Eû˜iºúý·¾ÖEµ¦(6«=Áøý?8—2ˆ¼p¬¦š 4«i‹²ä‹üÛ¸¸>ë-¥,õjns,îôOÍÓdox1ØmPŒPäôòk[«tV¨xŞ襪Çã‹ËhKðOÙ²/¼JíDr2Uë9ewM»Êò|cøÿÒr}WPs‡¢r~pÎÑP«Ã2{¡X‚8ß@rO_–§ö—?ýÀÁ4 endstream endobj 854 0 obj <> stream xÚ½XÝÛ6 ß_á·9X£Z²,Ûí6`+ºÏ>´ë= XL—诉ÚN¯×¿~¤H9vâ»­Ã0ôPÉÅ/‘?R‰ÞE2JàŸŒrI´ÚGß^E¿Ó‘LD™”ÑÕM$3Qêh‰ &ºZÿsÓ»v±L“,î·'&ÞUµ³-ÍošvOÛMÍÛÍ ýM³Û5 •Ç·U½!âµÛUû Xw·í‰¸ª×ÕÊö®;c²jê®omU##O«ãÎÕoïqùØõÄîz±TEì¿_ýưM©È2oSw€í¦l=[õ[>S“Í¡¯š:ÔU›Z°I‰ªÛôƒkÙ¨A03qìþ°ãMŸþfíNC»#M:·BÁ›Ï¯(U§š Y`\g”^×Çë?áØb™©,¾jüÑ*D?ä颸“4~ACJƒåÕ%ªÉç5 ~”"óR’±„;5áË_6=[ÕÎê‡Ä-ƒ¼åÅÁþ¶!š`œ~È8^e›Í ý’…~!/M*¹Ë&¬²‡ÜÅœ’KFR䬯™ºÝÌrÏóüÁë˜É P­ÆqúzÛw˜eI×Mïh ¸ˆ«0v<îO›®«®w¼¡Ñ}8´vðÑÚzã<çr&ª“Ð=c6Ï^¾xþ+M_¼¤KŠíÅb©S?·«…2ñö(‡ÌV&äâü¼Pø5LDœ„ÂÀ”þkNÚG ‡°V-Ðâ9–ž*@ÒPÑ®m†‰ÛhOGŒ*VÛ{;wÓ/ óp1ïÑeøÒªÊÌC‡*M|»‰[Zîè~BAëhÕ-—^ük‚*5{¡9z±@bäÅZ:½&ç3ã‘ Çãe1«fÕÈ4\d¯ÚªïïØŽ.åÔVvOf5.  òqý/ªÿÝ‹c6ÐÛ›¹ó0“LÐÏœ7§Þè+L‡õdŸ=»H¤e·ˆP&‘XÿöÐRæB ß»èuôŠo)ƒ$)1A º¡·ÒH=áÙE­n±4†3!ƒ×‚‘jÒZÅß¿xù3Í*|xìùiÙëZbmãæ—è:Gå¥õ?UÁÂäâô4ìùŒ¯pz\áàã ”ã3$L±ïa/HÓ wÚPMOe¢@Oi id }õÙ_Èv’@ endstream endobj 858 0 obj <> stream xÚÅXmoÛ6þ¾_¡o•Ñš_DIi;`º®{Ú5ß¶SÆ*K©ì4É~ýîx¤$ÚŒlņ}<ò^ùðŽÉ§„'üãI!à/KV›äÕiòõ÷*᫲*9½HxÎ*•,‘ “ÓóßÒwÝBé®^íšUݶw‹¥”"]õÝv7Ô M"M¦çæ÷Œ«®Ù50I¤UÝÑà²^~^ˆ25´Cßšê/ð«ÒÝ¥#\ômÛã¾7M·&Ò¶¹õsÃf{²øãôÇäõ)©Ï³¹þYÅt™,EÉre ¸µÌÀVÌØ*V–à œÿæ¥gÈB?À€8ZÇ0÷“ʘôóÛ«ÅíZ5h¿q¦×ôq–àf ËÏ,{ÝÇ$/uΤ†H–çüÀ‚‚qîä¿xЂۘ’qýYðP ¶àúŸÅÀeßõ•›è÷ÿ}ÿʼd⨜¡»Ë½PN®¨Áøhûe‚µ°ÂMh~ ±f\<&I‘tkÎ I>/ò<­Ûkóe¿Œ‰è–çL•Gu³ í4Ri=4õYK[-y±E¤-˜v›K3D5–œñc'¹b¹OÄ%g™õJÆÓíÝŽ¡,Ò¾mVDîê!>‹½@qüä8RóY ÎÛt¶„´,Ñ*ÁYæ#øôžjV‰yÉ%*È6PYVÞšÊ SIÅ) (~á·;»÷FS¨ãZNØÑ8Q5éHÔe/tåx ad#P~¹ÐUÙÌ!B tÆÌ'ó`FÛã#"6Õ†û%á<ŽÌÊñ…*ÔyÒJy•©Òõu‹GIŽ´- æžÇœÎÁ¤ÁÐ\×wËάë]óÙ9Ï€\‰´a jY‹×"¥IZû—zZ¼W¡SÈœ~й5óãïis—ƒ3ntá)Þ Pûš{+mr™D—m yoôÄþu>/Í•“îÖô›f·óQiºqÏ9븉J·f…:Ü’ŒW¸ 2•šÛzsÕšÕ‹Ù«û†j Ë~Y0AÈôj*]ÜääN‹ÑË\äXwÙoÍÃß<ËìÒ,X†Ôp™8ä:{ÄN·‚&ÏS.$S¹Ž0Jâko}™p8ùJ£ñ°B*üe—|ÇòÅ’s¡Ò7¦3CÝB>Ë"ÇhJ8¨fmKQ®öƒ©³¦«‡;;_oc7XT^Ô)ÝT2]’”Ò©ë $¤ÐF/I 5I²3tìWwçÆ-Úõôõ@â–÷'}ÿp ‘Ò=©æª¯ÃÿÃ#æ4+ejO=O¿µØ‘WþHáp¦òˆ 0˜PÑ’­±0èŒ!¥ÃÖGxªð»ªý®¶ð€ï/oßÑàjèÁ”ÍÖj"Ò·£"w“äY®¨©-Æ"ôüÙ¢wtÀl1x½ÝȺ6«û{Û¨pV;„°Ùƒgzÿض5@Çx‡'Ïöð<|>Å€ YgÃ1“7O:Ü;L:4hlmÆô–ó¤óϲ^ØR‘ KðÍÁÁ×vÿ…bÿ-¢œßÍP‹ è4”(±C#J5h/¨ê1Ʊbš,=‰÷#º‚™¦ggû!`4%û!,‘ÜÖeØGóD‚¿-_u âËCŸG;+YaåˆlUvVºåª A`X±ŒDoш‰cÁõ¸}D®fÛpËljCAj?EÊb¢³hc(Å’>ÅÄ “Ò1僭]žï?ÒП¬ m>Fë»B'#GÖX±þÈݘÚþê}Dã—MÝÇhšé±ÑqE<´\£i™K"Ž ÇIðë9}bþ…ëÇ+Â|É©©é+×õ ·ÏEÜ åè†2ÆÂáŸYSùHè¾µ[fnhÐ6Ýx'ÓÃê¯oÜ`X;<˜K<9xRVË|Z ׇϱBA 丮w2ÍÜ®ÌÕŽ4p`U:#Œ+li=lσÆß\6sga]H^u²ƒÊÅ8Ç(çÃLë›3Çkâ£ÕõÎö¬ýpN°ûg´¯.«éxÌïàp|%{â.§ø~‚¾ƒ›ãäÃÛõéÝCÿþ€ì|S9kÓž0÷O “7;:ãxÕmÀj¨aÇßmò!yï’)OQð¤[S”B&ÛßÉD¼¡ÒÚ¹¼^.¦¢M*‘¾ùùÝO4j°ß÷ÒïîzeÛ'wÍßÖÐ þ`@$`r}8%1¹ìªÝ„,Uê$_µõÊ6À@²|~àž”D@Â$bYÁÙ9ÞPK­û¸ž÷ýWkñ4 endstream endobj 863 0 obj <> stream xÚµV[ÛD~çWø §m†¹x|©h%Z-PTP¡y@"H8ÉlÖ¬cÛÙm÷×sΜÇNâ-­„v¥™9÷ïÜœàŸ@þDHøçÁz¼Zß|‚³ŒgÁâ:šeQ0GB,6„o®gs•ÆaŽGÞÍ´ó¦ÈW¥qŒý~6—ihò¦%JQ‘lwcè²5•iò’¸u3âZq‡ÙËÑakÖ]QWÏfóˆó°èH¾pÖó¶=ìÌÆ©é\AIxî.±ÖgýÏÅOÍ!TLk‹p‰Íæ±:“t¦NA#c (4È, ¬Š*o>qˆ(!D¨Ò÷ˆˆWdÿÜÖ0oùÀóÊ‚äC|à Ì#¥Oà åþ¦ní5Ë¥ïgèÜÉS(õ¡ÚÐãFÑÓÔtˉ‡Ÿ—†ÞT¯÷ªu…'Z†Ëð—ºs¾»›¼s.®úäÚ+:F~Žó¤J<ƒ^[ÕºXrÙTÕ– N*ȼY=ª=,H'?Ò„Ëßã9s—¾ªGOÏðð»öß¾1wE}hKTQê(¥N0’—b[ÕÙ°åÌÚös2­¬ýM/éU1b…æC¾Û—މÀ“`wÔ_JIå¹usµ %#’á–I˜HqËH&%­™ê8¢žÛ#ò<rDŒˆ¨ôÈkˆˆ©(F§(˜ö_³x6BFá•­k¢ÃÛ™â¡ùx?S¶Ôƺ¸eÆålA­.ì0ÔÅä7"þåLŒ°Ç K3ÕMuÑ à÷_“%[®û\Wã|Ø}cQÀ¥ó!½}Gì»Ùp°ÞtDÜ¡CÛ‘¨[6[Û¢À­Ý™»5û¼É;CIJ¨Ü-÷>+D Îýšå‚q9,˜)ÍÎPüˆF ˜}óamöl‚u½³ü¸ç“}`­Ê¼º¥+zo¡…ᡆ(@üº.q{Ű½ì»è´æ"ü®ìnêÃö†,t76› ~‹ê£¢i·•á¬÷ØÄy‰#©íÒ>߬nNÚ®©«­ŸËÆ’I[";(ëò°ñ3Ö¹Ó͘'EeƒÓ—í‘v–Iêz9ñ½ÜO*ô³T8_¿{{õ;]­ñÄ÷Äã ¶‚Ì2‹Ïœ ž¨)øqE ãé#É9¶wZ÷d«iŒÛg5m.ÐÁ¼‘œS9Ùwvæ*|¦6H~ïV¶Kýàùíwi¶ç?y ‘JrJÄûŠ qTF½ *R°8©=£¢íó­ù ×Z±$ÙZ}Ò{™Ð#­q—ˆ(Háç›ïIF}²\>€6ÙÃ<±r>Y.}k®ŒÖãÏEUìŠM'äðGá]^ÌsRg\Ñ>g‚nO='í9rÌIÏQ'Ùs¢Žî9Ús0:%Y¦‡Ñ1éâ€(wcÊEÔe±v]2Æ“!ø÷‡ÕßÐF”«E}9 Sn 2>Åî)òŒ¢Î(Ñe„M –¤ä•VÎ’UB‘G(ôéx;kJÎ9•™`©"½Æ*JÃ6Lïi£©2r9UÆN4©ó‰2òÉ2ú–a×Ðôú·ˆ]Þ‹'‘¯=òGXO"O'‘O60¿ùEpXX1]×]uD'¿ ®â Ðêj³ß—!âà #(Äí Q B´‰PœÁf£L<¥ †{æZù‘â GyÙð©’ÉHùTŽ:ѤÎ': K逗/ˆ)ôt´…xîRðX~ãÏop!ÿÏÑöÀ§Fûe¿Ö4}õFßg©Y Û:ŽèÃ'âþ«úëWÿ'“#¦ endstream endobj 866 0 obj <> stream xÚmRÍjÃ0 ¾ï)tL;âIŠ'e»ºÃnƒÜ–¶f…@›PBߎØKVl°áû“„à ha{ŽØWðôJ Uæ9T' ­ˆ!eR%CÕ|$CË»MJb$QÈ›TX’ï¶#ÿ{ôÂ< ¼BŠ€dK„¢›^i""3òY½AƪH mµ®8…S_çÛeéQÿÚs{ì;§g±}Ú ŒÒçÛ &¢Ó Ū|ïä8ûþÖ5ƒCµQhþFÇ'žœpÅãÈ_–¸îG[dÁS )Žº#Ô+¡™„ÿRã˜g5…§¾ã>ºfŽƒªëí(ÔÉOòÛºv´CåwL؇å¸cÌ¢ »d¹.|ñ¹ž¹ï¿Œî–þ endstream endobj 869 0 obj <> stream xÚ­WÛnÛ8}߯У Dªîô¡È¦t7)¼° ,P÷¶h›(%jE©±÷ëw(m9² /R$‡šÛ9ÃáH±þ±|˃ßJøõ¬Uiý>·Þ|ô­Às“$´ækP;¹ÚXóâ›}_×'ôlZlR’Úï'ßç€Ob‘›f)úİÉ{ŸYKªÂ!\TTy$öãôÍÓç©öž þ“6"²|Ïͽ\…ðc7,'ñÜÀïÃÌ·ÊÝÏìOÓ?µT“Õ$Hí“8±É¦W§6«V¼+¨T»ÜnW݈MCJÌ䧃Tç»a U𠝥àg…‘¦ht1Ï~Þ²ÀV§`R¯D/ò„7<8ðVJà­\iãNœ(̸«¬Nû.”ÞñC7Žût»Ñ©´°œ8AfS½a•Š!3[üPi¡±½nDï˜êRôDY4½á¬ÂÇ­ÐkC ê `%†%§ˆ¡ -9äíW$ösЦ$mÏÆòjÀ)šVá ÃXÀ~¯ä ?YUÚ0Äú$ŠžÒèc„çãN;÷,Ôã熵hÁZ©•¢k™¨ôcÅN­¤ÒZѵu×¢ŽîPZx~Ä©‹Ç?lE$sã°'òUªv;ÓJصGËËí”a/}Ce>Tº^ˆjQ+ºÄCû°ŒF¹ÆèôÎ!ŠÎ†VZi²)é9|¹ç‡pãzŽÄÍü!×O´¢ áPÉ,4¸{Ïs+'¥J]?³`˜@˜¬÷wœ²Ö¾0Ùu?ÆA|èG%úQmTªuÍvmŸ¦3|vlFãZÒqÖ ¥¯Î 1Χíå…]Ð5éx»˜\ÆÁëWAx˜>~øÛØÞÆ|óÊ”zß’ ”Û[S•¢ \‹êV·´z‘õËW,5Âd¸±j3ž:œT›ÎÜ×sðJÓ<ú2Üé- >"1º!‰Aˆ#“¤+=~Ô¦ŸTJÐ÷‚ ¤#ë~hˆ@`SɃLä3å\—EšjqêÇÍL¯A?„p¡I†(±ß/&oÇdÙzTPùr)´´5ÔGpÃ;ÈÐŽm*ÑÀ¸Ô ûKb²ædS‘$5§}âe^9Jnů(Ò#ãxÁÐ[:Îgè´ZÚ”L5äÅÛ+©ª? ïèø"³ŠµŒpö/&®%í á4Ðô¦ª®\R¤¶éß­aÚI®øˆâ™[ŽÃ™òÈš®Øš™(G¸ ¸v{º¥Ú\mµ—|ùèÌîç¯L™feÍénœŽÏ-4gÚnEñ?^ݪ¹&š+ &š‘`æž&3¯n}ãO>ž†gA»YÿEúËÉObcû×oÿF‰«º endstream endobj 872 0 obj <> stream xÚµW[£6~ï¯à­µ°\B’UŸv¦;£¶³íT“J•š>0‰µÆfm“K}/„„[¶»U"Æç|ŸÏç“8¾üÎ2”ßI ç~í¼y –Nà{oý·Î:w‚¥¬·^X8ë쯙ËîÜ8Œg9€~¯]—A]¾ºû{ý³TyR•D^+ çœâJ JŒ£Å•õÄ€ØAƒ*¨ÝAŒ$ôõ€ÄNúm,)Ù@í¥’zƒÛ¥äº"mº¾Z–‹¨@ÿÅqX{DÁqDtnDy 0ì ëeÅ»d4ÁÐØe3Ë`*,6wÃtКÛjLÖ3¤•8V¢¬ÄMn?0$`Ÿßíó:"–"$–hNYÄ ÏÃÏøÿD{+àQÜDÖe€l!ÿlZp$Љ“^àGFƒ%eb‚s'QúÍl¢Ž£¢Äð¨)Á§±øF&^ éI*ùÖæì•‘%hi×òæÈ)%ÉAx;*Ø„ÏG•¢”€ ¸ÉIÀètÓ·d[].²ÍD§V`<ÓdS8|$Ý·ÖZõS/kµutõT‘³„=n#Ù [¢Ey¡Z+"/ÔçIŽŽÐTî/¯4ñ/wÈ„]“)ò9„$Â0Ÿ^“py­1 |ÿ?xxy~ÿ§¾}~™4ȶ‹ýÞxz~ùe2%ùW„üñ§ïŒ¡~}t_ß­§`º²wJK“Â4·U˜Éö °Ymõ©¿.ä®i;( ÞMnÄeÁ·EcgK¯ÚlN«Ó7`çxDáµopå°Â•p¸¨‹AO{Ë€1v³¯äÍc{˜sí4·òâH!Ö­¢YTÿ¨os Êì袖hYßëø~=<%Î}ß‹¬Óª¼k·ç?4¿ïôå‘2¹p×TVos†ª”•¯Ç'IŒK§ aÈѹj[?˜ª9=¥Év’Økº«˜¬º÷ˆ‹÷€ ˆ¹û$[X2Åœczh˜ËnÛÌG¹nÙWàú„örd0Ó­¨ü2Ê×Áú^¸lG×o&nTq™Q8ƒ)ÚøÁ<Õ‹u.ªk=§G«ùyÔP"²eÞEÁÌ îc¡û±Ælr˜)dæw,Wñ¦^© úHíáæ¦ ;«F•«×ª‡ç‘(’Æ&`öC‡È¡Ïj6ùÚ.x[T Ò# Èö# ò- )œ½ÉN JF€îÑ19}ËqÕʽ½íà|>N¾dphű)¨ìíyÕW¤.Á‡1cSWã: øeÓ–ZõGæ˜Idƒå¨Ëå{YMÏì'`º#èSûÍo3cÞJŒ0Œ½U踋ùJa‹…Ýûû7ÿC›a· endstream endobj 875 0 obj <> stream xÚµWKsÛ6¾÷Wpr‰t BRÖÓS_nÓ©Ó´Ñ-ÊWj Жúë»$š’HHδcÏûí ß®‚Ç "ü‹ƒE‚ÿQ@‹à‡Uðî.^q4¹nƒÕ&ˆ“x„õÆU Æá,™”&<#23«7ö:âáY—’QÆ·ÍùÐ*ãéd6³r²÷¨ÿ•HÉÔ[³ÐÏ",‰Rf%‰fÂ~¥ÍÛz”Á†T¹^‡A¹¸ë÷êy¨” DîÁ1O O¬oÖèkU€õ7 %¹=ˆæ¹]’=ù²"³>paƒ×cÖ™Ú«ö„j_YQæ°7‹ôNXƒS¢À¾ nžF—ñK2½CqF‡=ÚÓЇsl³Ý¨Ù0Nò)ç_]‹ ßÝuïD'Ñ$Yàs9™M˜?JÌ>G•Óåt¤J|&# lÅ7ÔljaŸ;¨_nFŒ§1ÖŠdB†õ‰x$ì^-Œêh×KñŸWžë™ÜN¦ÉK%gž$p¢+é± ɶu`°\Lüe†&õ]O—åǧþ±š·q,gEU˜E[ p Æe”xaHYJ±gÑp-Òõ\ ÅŽþ•Ñý‡OVüúrI¢Å$z)—‚õ9E;XæHˆä¶`×°u»OxMHš;2"ö‰G5㕨T£6êw]«ÏV²¶¹MMãIWOYIÅß?ùÒµaRõÐN* §»cV1¢Ãž ƒääZŒFò[ l¬›ë0jQë‘DÒ¢q7ú2L&µ(ü0RÜA…Ͷ&BÜóüI2H[jm;ÏJ9’XOÚ¯¸v%—bÜ5ìJfaKU&h”£×£‚X»S87¯õ¦²áÛ›®]Ûé¯;?å³=Û¨Ë }ИŸ‡3ã3(õî¬$‰ž‚¤¯I%ì0ŽàSœ_Ê×5dd¢ë0ÿ†¦0O32ìN_ËEfqŸ™sóÅ‚\ж݋ŠgßX”x‡EéjZÚšÛüƒØþáA¬p8¦ØÚ%ûÎõK(sB­Ê-phgÅ»ëßè=8N‚~¢?T£^/«¢§î°Ùæj8¸¥,gúàZž¸¶ÀêžmÏ}ᜇÉÜ4s§ßtõV»½(ý”‚l¼¬‹š6œy­£ëHÇ Ænl“™zïø )•c…óÈ­­(¦à,\&—n0ù¥‘z«Ü˜²‡¬'Ë´ÒÊÓ—˜¼sÿᯖj0d} ñîºAÓI…«kjÊÈ{;r£9{¬à’f+u¡î«G[;=5Âf+Eƒ}!/·ÄV¶îû¦ÀKý«U³§6"öP÷4Ô ÜòXé:gŠôò0Wyë×Q~Ïï¦HÅ1îïÂÏ߯Îù¢!J³úõ)½ß£eŸ‰îHO»7a7If“e„ó›eƒÏNöÏïþàɯ$ endstream endobj 882 0 obj <> stream xÚ”mo›0ÇßïSX}ÒpÛªmR۵Ѷ¤ÊÚLš´ì Nê-à”­Û§ŸíƒB¤ªU¢ä|æwüÎgô€äëO€x¨¿>Zæèb†N¯Ž'~‚f+pÄÈ3ŽͲŽç©Å¯E‘¹ ™³P1ÃÀ÷4k²Mº‘õ_XkïÞ兀9wrYÈ\þKk©Š¹Û*J÷çì³.ƒ`]†̘ÍþêÃÑPéãA¨ZuEÕb-JX¬DZÉ…´%šDþ0ǶT‹È» iU5¹¨`éy¦Ü*­ux#<½¦XÅ„èÿ3bƒ]»11¯ãBœLTËRnMyàP+ø¯ï…1¨3™Þg¥Ê<­Á®D»{¾ÝjÖÜE&mþ«YÛÃÛQk”kèâ°®…8‘Ç"Ì[ÖE¯6ÂcšÈ7@š·PÍ6]‹—äNBñaœ€òg³?Á>ª°Õxa҉׾œŽ¯¾ƒo<ÝgM;Ö¤e¿œuLqB‘ÇB[àåó¬èO¯ykîçXü~šœ»úU/ï`C_8ÞRU5¬æ~À”!óǬyYiwškÑ(â™KÒ8š|'$×!S{ÊAÅmÿX×?Öö/îúÇmÿ˜éŸ!vÏŒÊt{¦-Ò¸5T TùT·Jc-Duz¢¶',îSÛž\æ‡ýÑ£p8€ú¨›Œh c=Í×7ÿÕ\Ôï endstream endobj 885 0 obj <> stream xÚWYoã6~ï¯0úD±V¢(YÂ>y³IšÖɺ¶ÓEÐôA±é˜ˆ—’“M}ç }ä@‹]Däp8Ùùæpïï^Ô á_ÔJøöUï˼÷é<êÉ0HÓ¸7_Áñ ÇMo¾üSŒ6›þ …®—æ¬Ò¡8ëÿ5ÿî¤=©‚a6twØätçìG§m]”ÈžŠY³êú2Ïý8þ±šO®øFb¹-uË”›V/YÉeMZ@®ÌƒŒå^Œ'¿9ݪ…Aæ¨;J‚\þ,ˆ3⃻ #Ýšå|‘V›bÑ—©xì'©(ôŽÏ:ÎÂ/¶î%¹h›ÊÑô]HG»†`—Ìü½LT`ìw6å¢4mçe™š¿ÝÚ¸Sò/H!ÿdÝÀÅA’A×M╊ábÑù•n‰¨^éÄC|;*?t”RAž€OQfÝtïøP Ǧ°NW³â/úñ„uÞo»½*¢°Çôlº5ÓØñÄV»CS/Êí’Y9ÄYãlO“ ’‡Æ/ÁÖ€>ÓÔì ³9ƒ6‹‚X¥€qgœQER‰ÑÕ×wÌdXÅ1CX1Äà~&…¶-(b‚ ä ®rqÚl0Ö/Ö<¬1Þì»HÅAšõ¼ …Ó”hÄA÷žå.Œ’÷ ¬•;·Ë0¢ÒLÜ“J~ÊÜT xuOÌôµ@â“iOx?Ám[à;™yê˜G•n»†¥d±pW(6¸¸, °šyé[xq¼Ã%Äæ˜£“!ŽÅ”ü2Â:–b à´O˜jz8ƒ‡Çˆ² a§|Õíš øãôÞ³S¼dàiñ›@Q¡O«;^ \ñkM­ת±¼ØX=hìR[S?¸›uL&\Wä;ic¿Ö5ü=]7g/N—;ß8-Å¢k¬ù§@kN>ÈçmKªÑq\£`Ql6–"óÃÀ±2µ©¸­Ø¯Ký`5*±·î— ·[Wÿéî1˜W·úÿ¸zÎu*Ï ŠÝÛÂ"öò\01+~Kþ¶~†´†Òþ‚´fË"EÍÌVïrZó‘éøø =Šk_ÕÌÊkí˜y[ƒÝLbïáBÛÊ= £ïÏÞwÿÅ5+N hºmI¬/t­-ÕvØL¶÷%$39wѦhù»A†vMu¶÷ˆt|f¢Ü›€xŽå„=äÙÛvTâiÀ"ÂËgì ‰Ð; yÂ;®&¹†¸7Db™Ãà“͇hr>ñHaêÀî«|p³µŒª†rï®ïT{kà¨,ºÛOaŒ}©ä.K~Ëß}Ô—Ì…ÕFºêO‹u㺡§ã{IDÇ7ž V¤Ü:#ôžÕ¶kerkBê÷Ëù/ßnæ¼]ß²ˆïý( Åh:]Ïo?la ʉÃXh¶ÑJçãÊOµ) !xž©ìZ‹ÎÃöà 5ðSl€ãêlŠÔÓ_@/ßÑ—ËñåüÖ1Y–y~9¿>›ÍøÆ9ò›2Lj&tuŠç—§7cX¾Åäf:ù6; 8l3­_ƒñ¸Øá‰;üÃf‡dÚáVJUc]Zê®0eû$nñ¥X ‘-ø´\òz] ÊžúD%±,,´q=ƒ)W‘…k¾L¤a¨d.ÈéÍ!¢7¼9x°3вÁú‰t7´‘†³÷aá`MÕ €/ C¥p*Š ¹¡£è0¢v‡üL ”¨NoË2—šÂ8»œü$ÚÉŠ`í±¤ nÎüÎÍŠ A®²¡lj,eâKÝßu¥#Ä\8ª¡„ÜzèêÊÍlôA\'\ *ÓºqI¥ÜT&pœÞÍ.j((+`8 dú·+Xªà€"͵ä¹)Ρ5‚ÊÝrõ_ù %ºú²V¯Îî@_LƵd×|Ÿ ¦2S¾ød‰+O°x3žð ÂEŽ}Ý¥Á¤^¾’0zêc1eqoJ(j ä…ÕÑÐrÈ ÝüÁЯ Üöâ÷-¦_­¢ã.¡È´‚†4(!à]£!Q ¼7œù@^r£]l+Ía"ðáY䊗<è !æ#wfí "uXA<[O3­WzÄÌ…Ž›ÌРܵz6WTylñþ-ñ»²ß š§¦ÖM„ JK™{añ^,÷Ò‘ã ‡†Ê_L)„êmáê€çæÈíîŽÓ¢@ŸHw}Î'Pð3F%~V‡¿vŽ~¦É$ÈàWRªø÷N”æž÷÷Ÿþá* endstream endobj 890 0 obj <> stream xÚíX[oã¶~ï¯0ú$YJ–Ú'o6ISx“ÔqÚM‰¶‰ÕÅåääüúÎ…´åKÐíSQ Ø`M ‡ÃÎÌ7CþøþùƒqÞ ¯çƒÑ¥øž›zé`¾€é3üˆóâ7§k†gA;þŽB-Þ0vº•ä™g§0ŸY]ðÀ®,”îZõ¼édOð«'ϲ8)Diþ]¶Y= @–,>àþ‰³n›!èñ¢ »t«Èy³Æ©·V-WCÖÑ’¬¸©Êe­å‡áïóÉÌÐ"2“´Ã¥á`ò2Œ„“©2{V¥êPàÎNÝt†'ki œVv™ªII¢[iOà ØÙnu{[‰¾ñHE+2Í›.Pš9U—8— ò#7`TâF!5ùüÉði«Ý0ŠØ®Rò›º-KÎÊN¶uf ,ñÀr©¿çϼ©QB—寄¹Ë¿ŸX²ÝgÑ´<(ð\JÍú.ǽ(;;V÷e‡½ÍÞháÅÜíìÊ Ú%‡­?ÞÛÄs}’µêºõw£Ñëë«›+-ÝÍ¢te±µRˬÍW#½ÎZ-GYUì¶@éFp2ð…ŠØæƒŸº‚#å †ðçüv '<ºüŒÍäQ‚Z¶Ï|©óó0 Ùj§J„ÀcÈFþq(“ø´ð‚òyåfϨª¡ë…ƒ3ËAÐ â^ ²øišœžÇ[{Î\UM·¢ÝY« ø8½ ã¤,ybFJBXh^0ƒ3n_b#óÀóÀä ¿ïúORç­Zwx'Ô=Œ”¼)Áqß Ï¢ØƒdƒXK}'[6ÄÎÿTÅœzN¥jU¡*›Š¹ ¹l¥ä1ˆÙTfuÓB¨z‰_¤Á²iU·ªÀVáÅ& múÀ¿ HàøF*ÓšfAªoãz‹-ú­ª$@`² lP”"Ⱥƒ ÐÆÏWˆÄùiÆä½­Ì\)3Ýñ´þc0d)NP0…· 5áGc&ÌN²[\Ñf`?Å -3™ g `\U|DL©ôò x¤YÓÊa0Ëò¿ƒUpìÒ8È¥"J­KÇ[—Š(Ùw)¬KqÅδ޺‘É‹H?_5¥Ô_ÞøëÀ—$æ+|‰Z— soÛ6pâ­þšàžS=ƒ<ÊÌJ2Ј~¹ÚÁ _1áSuZ– ³°5ÄûN.ð,q|mÒxšµá–ƒ«uø5iÏä'§Ø'`5#}fphŸ†Þ9Á‡Z16ðÙª*DLâïe ¾(2Ø}œD|Hî»RŒw5ç ÉËfMM †2©šç!Ï¡¦p´ÖË(äñèÇfex¯TÉœ²ÅþAŒ#çWi‚ð8Cî† t 34ãü°ö_誱㛥I“Ûì SfªXš"{C*e%sLIÓ1iÚ´oX#þ2ºL_óuÑEE: QÏmÖbO“¦Ü!Àï€cêèfѡկhD´"ôÁ[¨Û†E䌽)dz¿ËÃ)Õñ LjÁ3Ýõ2 »kÇ̶ISÓá@¶•Q CÃΪ«Äeèk¦Rkã+YË–Ž>î6Ï%e-2™ã¢j´àw zEpŸÏXIPMhY' ^¢7ø„€|pBL%ž,"¯bãGŽTAÈ6úM­3ÅmBàúFMâ¶wåi±Ow“Â:¦å–®¡Zú4´1i­)Äd³º§Ê,‹^¸"Ø…K ¸¡Äß× æÂ”à †)¬lNZ:áŠèxÅ«¢>(&ïøc£åbSb«%6`ê/×ónæü1¹yd¿ }ú‘Ùlr3üþ(DØLöå„^èÀÀèõsÆôÕÕºTžmÃ[º`ÆÐˆüäàø|1Cêù°/ÁÇëéõüÑ0µ,óòz~sqÏ+.‘ÿvÆf°ÿϯϦ0<Æ™‡ÙÝíý…é¶ï¥<Ž lãÆ»øŽmü#Ó6þw½:4M+OtíGòˆš"@} gZ<^ee/Cv¢r‰h3$cµ`ÉMËD‚~ ’98 sP¤5‡ˆÖœ°æàÄÖœÈʆª?Ð ¼SÑTúä0aM耚x^Øü}Hn(:(ÚóéB‹“¬&zpèt ȼ$4v®ëÜ5ò#+ ¦¬þRRÕò°x–Kµ C«lLq ¹ÄùØèÅEÌç ûÒ 7€î\y¸Ÿ¼ã×;ƒJi¾‘Àí‡Ë´•^òÙfÔK¾—c£Y0Ï7V"áð‡ ò4cˆÍUçM?iVü‡!‡´oñe-æ8Ü2½º›¾×h¼$‚´ O08ùf ûfD=Ü ¨3-$Lv÷éÞ;nG-[Ÿ˜¥¢B_ý:@üvGû˜`Õ'^+2BàtvŸ¼œù@.¸Ðæ›Jš »¹¦@1x½šàù{/ˆTU`þÔ–¦´Ýt™Ž‹ÌØ <~¶Î=‹wº„'eÍ=?^{Ð9¥eÚ‡(œòåN:rôj¨'ìÂø§œÁ§ÃÍžÚÓtÁmN ÝÔ9›@î·è•ð0­ŽÌúïíßûÀÆ:ol¥n̕ؼ¶Åý×¶p÷Úž|mÓÒ^©^Û‚½×¶Ø¾¶ÿÜk[ìÅ®ÿ­÷6~¹9ùäÖ¿¶Aä&ì ~¤{vÍOßü c\w endstream endobj 894 0 obj <> stream xÚ­ÛrêFò}¿‚:/UFÖAò„±°•pq„œ³§Öû ¤f@D#qöç·{zF€Ê©Ô–)k4}¾M·Z¿·ì–v+pàgµ²Më!iÝz-Û3]¯ÛJ–îØ–Ù‡uþ/#4ÝvǶϘð-Ÿ§uûßÉÏ@àµÇê+§oº®$Pha»ãº®ñÍ6³}GoÃr×vã½â«5.ˆ›íf×ni™ៈ踦å¶:åͲý+Š€$ßuű,_Iò¯E*h=/+¶¢ÜšŠ>8•bû}ÓvàÙ3}’ôÈDVñ]ÍËí5¾Ù÷Nѵ‘:žm\àÓ1Rzl¶I .jžÑßì ¶aÛ¶Ó5êTÊ„åò„Ð6†ëìv þ1íÎížk$ô"Êâ”Uô¾Hˉ 1uŒzÍÔ™ÚNÏ(eͪ´GëèÓ¸¦ïËÓeZgˆ»Fû9†Èpo Z“=—e¥©¨iõ0|Á…g¤Ûœv²"Ý EP°´ÚòíŠP2ˆuVnѯ<«5yZ¼ .®yÊ:5ú˜gàSö=þy!#m¸dm«Kn²à„¬bZÏ ŒU•ne²És|cY1F0é! !k¤ÕŠ)”º$‘¾“„]»d• ‘`øEr²rK3•D¤EÔk­ (—5"Hߥ»á52{Ââ\JÎxZ3¹é¹ÚÚ˸ š¸sû6¦•W0Aˆo1¸ü4ÿ ùÓ[ûŽTÇóJ¶ ¢HJå[Úi¨?Ú×ër_JÅD]ãA“;y*ëô@|›ûœbL|¤„—‚oxsL#)M‰Áã@ù’Š"–€4æ†4º#à9_®Óì2ò/íö ÈàµzË9ê½Ø×,,£ñÊ9À1÷”.ž!XQÐ ÔàÒæ°FŸ»®¯Nmww–YêT@°“zc`×çrBñ,‰ä°.7Š˜¤ø×<™Êár +ÖìL¤‡tqBQª’ vhw|ßøÓÙLd:,då(ŠR–"U dÈ9úRüHÃÇôMd ƒäHò|’þj-÷ýƧä}HÚÞ–PsUêJÛ!XÇü<+ Gš®!Ö)º — ÂU¥CF&Ëõ›RNãj×Êt®«ý¢s#qE­ —¹!ÅÊJÚ„ÌF!âÞó†éžCÀïþl”|nÛ¶e bµÍñé/12šá¿ß¢Çð‘ Ÿsö ݸÆç(yž½&D¥™Åƒiò…0g# ¦_hñK4}¼£eøÏ[ç‰Ã9Š ,cÓ3š¼Œ£P’âÛt8~}Œ¦OøjRØŸÎÔbM¢Dê àdF›trXœ*…ZÒˆž“0î\ôðp±@ ¢q”|ÁªçöŒQ”L¥®žÛ7F„¨0B´÷"ibyCGÃ×ñ@_^ã—Ù<$¤Áô‘ÓÙ4šŽb8X8 §‰y©G4¥€˜ÎÈûáo€G[óçÁxL»tRØ  _ÁGñœ6¤=á9œ½|‰£§ç„žgãÇPã<„´9ŽcŨ9›ëÚÒ›—¢‰ôOÏxD±ƒÉ#ñ‰ (WöhJÐæÄ÷ÏÏá( Ï~¢ Ã$šM¿ígÓ$–&WŠm2‹Uäø®TÂñ=¥†ÁçhÞpGsTø2Šå‘'†{MåH='TŸ Æ4Tê!=¦A¤7pw%¶0m•„®«¬Ü8Ñ5^ç!e¸†h Âò1ŒAå9!Ptœžåø_öOƒoí®k¤¼HÂ6øý]Ò„‰šâ'µ¨V4/ؘ¹>ôùÄm]×»ï™ 3ƒÊ ÷§0»Šû˜ èÿ²õý¨¬ ž0¸Êsq:[H¡(ouu4qû–i÷Õlâ©ÙäÏ‚/þj0‘84“PH¥£Ü6ÓWWëðâ¡ÅÆäÿ3¢øjD±û}ÿ¿Že[¤ÅÏ,ÝvŠr¿#EžÀ!Å;iÜtÒ“´úJàA^°êÆã Œ¿?Ä(KYµp¦ôX±­œ$l·¯Ôõ$[{çi­³r³ƒžNYc•V²©2±æþ²ÿ±t¯ca#$Ù力–]¯+–æ„"Ò%“ô>µçR—SõËeO‘åÇßVClÒ™q¥U•/Ô!8 ZPÝýG>]Í'ÉB$èí͈Ùï{&jB\ÒÝÕ·ÜèiO¼µ ×îûAitppÇQÒ· ¢µÔ :9ñc[-3äkÖ\›×»]³«Çä·&/e?lí¯ðïÂŒ®hˆ»ý]Üs†‰ãG3.Jǰ¾"ʶ,Ì¢SaÎw [ýÉwçr®&ˆ géùs‚LÖÔjëžuÍ¡¡»ŠšSžSã?¤¢ÃŲÎôN¦—¦Å.ÍÁ0ßÿ!s‡ 4/ôä§Nœzj.¯ä|ŠЦO¦–іж%=<…,u9p?z2¶nÌ‘{аRmgÓöâËšª<]ªm>4³/UžnÒ•žoÒŠ Õíƒ*DNzÙæ+Á±ËåŠT|_›{1àû*‰á>è 3Î÷…±˜m1Õà'˜K*!’`ëb—»”å¾{t&Š8­’Ø“3®¸ûpè©*-j¦&K^À©ØqL=GÁïE3éâ×9¶u›±Íý8¶yzl Nƶ“éýÖàfchöúªj{}ˆk¾’_ ¼9ö”³½ÞµÔòcÓ–ó{Mo0Ÿ‚Š/8¾b˜?L»ú'À$úŽ¯åžøoðEqêiN=üNÅ7Z—Tmžª²¾•/T¥G ïI|» ÜNY´$pÃÞsllŽ£ƒíœ> stream xÚe’ËnÛ0E÷ý .) ¢Ä‡îÎ’²h¡]ÑmÑ6QŠrI*FúõåˆR­ °apsï<ÐDQ?5,~KtÐC‡Š'hIvåu'D+²(‡Dºþ'f$ËEUâ½ Ê©>Ë9¯°'wTéý–±+çõh}Ê ™|€HàC–³/ÅW#µ5ïÔxî÷,îS¥\ô~:Búò5…Òöÿ¹õkÇÒþ`ÐÞ©«S^Y`„Õqdÿê^bcKœTÕܨ£mÏ .3‰ãÑ鳶ҤȧÀüH§ÈŒ[i-©øLã0-!pwÑ> £MF%bàž»g«±:HSÃEqªí2­,ºï€ã“‡ô’³`ï«á¸×>8}˜BÜM2ÌNxµuü¢¤ÍÍ8]“äYj÷µŒºÛ–¾Â¾æª}o”›‹Š§fs=¹ Œˆv+Ú¿eu´¨> stream xÚ…YYÛÈ~ϯЛ)`¤á}8A€l²^ìÂHx’EɇlI„ERËcÆBþ|¾:š¤ŽAàÙGuwuÕWWkõÛÊ[¹øç­W?<­?Å+?Ü&i²zÚaz“EÛ8\=•ÿv~úë?Ö› ŽŸLcºüHÄù2¾«BÚŸ«Â4½Yÿçé—ÕO²]à®ÒmÇ´—¤Û0Ym¼ÈÛ†oúÏu–:¦ë«¶ÁYàô?£oèü26FG\7¹ØÚ‹[GÛ,ÄΉ· bÞùÏíií§Î¹«ö‡µŸ9¯ £m®¶~Â4=~òýy§¿âÕÆ’<»^¤Tçù[?ƒ|ˆ„Û¡ï|Z§‘Ó#½¯ín Þ迼ãQhB§›2péü¹)¶ö”pqJ˜mS=å‡a8}||Üõ»mÛíÿøe‘y[?åµ?¾ ¦;“ Z¨›9U¯ç:§õ†gëjL)cC+4I1qÎÔÃ%.«~誗qЭ^‰Èt/¸S-¤XX= Ý Õp°G)<\â,ðUŒµiˆÏ„âE¶ê‚Fy³¯š½²®3¼úM+ê`=rà[çÇc«òÏSn/–B¸Û Œæ~ncÑø—Îäõ:𜗣¹§y‘.Œ$õ™þé ú ƒ…`t2L|ž® 惹|vÀ̓ÌX¡Ín|Ìò"ʶºž–È`¾* típ0Jù­jJ=Ž•¡7ZÙvßúí$9¾Ù|¥l:·—žŒFÝöÄXfYH—,`^X@ò€æ©Ë‹¡*X,™/FAÇS×—–¦¯ö ÃT CŒù7F°n?[{–-Î|¡±“‰³lk]Þ*·‡ éÞk-l&´2Ä–ÃéÌòv½I<ßùá,ãE+°íòž †é¼†1Á ‹ êXLP{Âuü•MS’$˜‹VföcÞå:« ΧÞtq¢–U‰^|a!‘Xë)ÉèΉ½3õa:h¤®£Žƒüs/SŒÌäò9uí¾Ëëÿ²ˆÑ¯gM¸YÞg‹Å·3u^ñ^©(IZý­¯LRfù©]:öà ŠˆâÌù•Ü.Oª¢' v´r8ùz ÔwÁÎûÂ1ƒ|d£ócÝ ±r?ZX9F'+G{¶rtä h¨Í`!K#‚U4®/ÿ{ *2Lç§ÓQ|)uŽ}«éWÐpÖ½Õà0ná*9š¼7åí½Õ+[—0™^ìÎ䮥ÊÇáвìÃ(qþ%RSÇ•7êÓÀò´N†˜]ôfz>ýÃLD\‹O²¦9ù¥_ˆˆ™°j¨:ý‰ã‡É骮„¢Qt¹î£¤ÓÜd±‰ú.jtfgºN# „“?yèFñ†‡O”M¢ÀÍþÆ—ÂàŒ t,2hïϳ;u­ÏCcòy÷’H.Ób†©§¦4óAZgVù(‡œ¨_9øÉˆ`t³s Gø^Ätô§޶ØŠ4Œï,Nx¶Ñ'¶n´Ûë”F-¶$=¹ÚÝaû­êÏkÆC"W»AìLÅÐWaªWës"âlì n'¸C£Ô.³@ÃŒS4öfFe¿;ù*JeG¹c#Y$Tœ£Äž•ýõŠé€e0¡ Q&îÄnL[Åí ¬â~wÅ«žÑ˜7i°vn¤uab‹ôÀÂÆ_°‹üÖ´Â÷.¦&ó.[»…±Ù ¼H³ïß±Û'v°’8%vS Ôɬ&;™’T.œx`oªVšl ‡B,â †ï©3¢w ‡Bư‚]Çq£%Ñ@GlÖ40Aˆ:z Z2³ Ûu2ž÷ßtmvµV™9v®»÷ŒXRªpqÜFìy”lÁç´ì•B7Y åЕc¤0ݳê3òê½dïÏÕKu¬1YœÃHÆwÖ _Ø8&'G›á•E3§×&Îü)Fß; ^V»³R o!ùÛ‹0¡$¸v1X„™9SVï5§³¢÷wð'¡$Ï1ßóútäÛÓt‹Ð÷JÉRL4iÅDív'4ý(I“ôrù¨­=H@x; Ç´ヤwž²â‹O¤F®}cÙš„úÈ©¨3RúÀgä½Ý¦‘e’剄î£N²Âš ÚÙ8Gu‘ç5·<+Ù^zâ ˆbŽëN7ášjþœвzÍyÓ ÔsТž-ÚÒnNǘ3­§›£êÄe·Ü½rïDÎ"sÕQƒ}¸l©$n`W(8æ.WxågisuÐÒb°žZ¶P:÷¶"›ãYZìN—ë+-ÉÄ$ìî‚ö/êÝŽ­-Ðé ±Ž;°a"Ð…’RãËgiLþ–:‹ä+ˆ,Hÿ­ºßd÷­Lõƒ9õIl!‚¼÷¼:@îHÚ¶j\x%?ìÌ,¦7%ムß+ȤJyv|>¬üÙõ)jƒeÚà/²ØÏËZy_½J*w©eß9š½­ÐÕÏtuÕë;T¨•'6(ôIJ¹L”âüÑ–äµ&âÿ0Y 7ê®|R(t!ÛòVéd†ã67$ÿþ +U½R±„©?oÅ FÌ¿£tœ:æûé(õÔ ¹e:]XédÓÊRtÍ€¤& ñ_¼Ú.šr[=^+ž­0šA(xã¦Rå} v¦‰ 5&0œÔÁ(Œf™5J諎ãKMƓΪ¦B£{_ջʑ䖘®óNN+-þe|NóÊaO`Ï»SsM~ |9šZÃß[uTTJ‰¡™ÂÚ ÐÓ$¥JÛ˜vìm¹eq«BR³ÙÉ eLˆ¥·¼ë;>èk[Oï2¯•d¢™o_kü»¯5¾d[R8b%ëPר¢¿$)ïÑ‘ÜÎql¤1å“’0¨¯VIôδӇžƒY¾K%WïR8«*•‚\ùÃ;á2?Bxãþp) &ç,rÜåÅ€@Ö©ßã¬ÓekU¯È~ŸÈ»MíèyÁ>sâÖgnж>!? 'G±®x蜟V1— ¦LZüfcI§éyÄdœ]&”Tó1‰{ÏJ#Üòiš?#Ô൅`°‘If³a›È‘ó TDÀê,Š‘!Îd—çãÈür3ÜS,u,8RQfÏ@áå%<|9æGáû%ü>ôp{û·C%' Ä¢–Œ$‰ü¨7¬Ž,¡¼M“J­…!Ki_>‚†Ð|rèŒÒ ä_™<2û·éÍ2áD>u¦:‡/m'±ñ+K—f)SnAA!®-KÔ† äÑ÷ЦêÓôÞÃè ˜ÝËÓÜæ4vZÚõäW;Æd–é¯O©¢7M…›¹N–­’OÆaô„¥„­|ç*¾­J!Òwj}¾ÄÚsñU¸"A¸ýêäûýÞ´‰CùEÏKKû÷ßýZú endstream endobj 905 0 obj <> stream xÚZYsÛÈ~ϯ`é%P¥àø¸ñz§lï&VžÂ<Œ€91.ÉÜ_Ÿ¾f0©Í–]…9{z¦¯¯›Úüº‰6!ü‹6E ÿÃMÕnþú°ùËOQ¾)ïwy¾yx‚é»(„Îæ¡þwP«î ‡Û»$Œ‚é¨&nÔ¤»Û¸ ¦Â@Nѵ¬ëù«øó4h­88 ýaP-WýÜȆV}Cbši9DïÃ(ÑÕdžoã"ÐÍ™§Èi0zRÃù¶Ì‚ûÛ»4ƒl˹§A?=`qL–y3n± #GÍc~ù$œŽã<èñö?___® È• ¾r ü«®ëi2 oï„èÌ#=졇€‘Aw5="´ùðÔ íúîßéžXˆ²û] lÐÙxX6éÊŒrФ‡väqÕÕI­þé}\2çïÿùù+ì-Òà‡/?b#ÞýüåÇþòuE£Øà»‡;§ƒÑ}¾#"!9‹¢àGT‰´ãû1kÕ•‡‹£û"¡ûýÈyÿd*ÝúÆÊäIãZN¬5Ãè®›ðxÿ$ëŽòò¾ü‹G>èNªáÑ_æÇÆT«ÃîJ9Yî÷ïPepÌáHz#BlFa¤ÕÊ ÐÊÍ-¾kŒ³b£H¢”V_²Èóúz=ð/ÚðÍtµÀ—K‚$ÚßÈJ`|œ+9 o²zÔ­A›«ÉjV«ÆoãÕ‹’ÚÆ»8ø…uý†{öé±=õüUäNÎØ‰.ï¬ÍS/8\r¯áW®™ÆÌVFdIêØr‚7”·]˜´;T]ƒ/pT• ï÷g:{¾á»ÞY+uÎb¿—ÃôxóÊ,÷{4Ü“±^Sæ[%·ÆÎʉ€|̳©gÐ “¼v?Tg~Sž \º q†é®„“1?opl‡Ž?Ë[âBѹ \ìÔó‚J•{OCßr y!:µ:M¼E5ÍzBòžËsMç˜ÂÕOj<’ýáØ Í.ËãÇ׋7qâ—Z3¢-£Bg±Sÿ,D3élKsbƒm2 øÚEú»ª&nº'‘ÐS”âœa´fn&GÅÊmGÚEà¥(> }þx"Bÿfg=otÃ4,_Ži­»ÃeÜò϶ºÓyž¥óà~ÿ¨\Ä’£’ÅÕÙ#hÚJî ½ûÁR¬(F<£Œô`iÛc­î/>N›Å3¹ø8w—¯‚Nv ›‹Q¨5{ì ݵÀhºWąʯål'/à"6ÔB?ZN^’åÀgyAìÉM°I–ßZ¾âÖÀ‘͸+Ï!Ρ=à³·¬ü8ÙÏ2~©Å´„Ž&è„ä:è5°wæIîÔ|΄A©õÃÆ2jôçj0.ʼ"»[l3|€1ÝÚ¡nŃñ´x\l¬–—¶ÊÄÉã½ IîR0¬JŸdF×Õ,ÖƒÊ0‰úÊ’mOódµÜ‘¦”äâÀ…9ÐfðI`É,@ž8P¾¶æl—£fÄÀ&ÓUÍ\ë‘{vèò FíÀžEȸž9Ü-’ÅÎxµ¿%rÑâ‡Jt‰dEY(ÓØ§e%ÃiÔæ‹«ž„l_Å#€fì[mñàÌ’,mCŒµB؈°pO%þÅuè¦ù?Qznq{’¢ QÀÇ3UXk}AQ.@W!Lá¹>˜>­Ä‚x ¥;|"!cï㉌§·+|»ÁóIJ0 £Í³EW° Ä [Q5ò(ø ¾ì #2ü–€«,‹,Ž2ƒÁ"É¡ŸÇ•÷òT3=°ÃǃwÚ¾&Ù ¨›xº'Kׂ9å~Òï< f´Çdõ¥º÷–sïPióõUyNdr;»¤À%Oª’I°’Ûþyä‘ýþ‡çrdޏï“> –Ææ—~,5b,%æì¿±¡¿OÎ!1Ö:Û~ÙbOñgu×θ‘–€ª½'ø˜NÎ#/™çÁ³ [$tž´š ÄŽÓHÞÑþ–×÷ÇIøõ_—V«ô€}mž¡ÀàEPŠ…ÍÔ0D1v9Z„1Ñ8+šdÚÈzP¦ëB ƒ’G«Œ Q)ÇD~<Äùýâ×#±8±/;\.œ1™Â;’6Â!Ù /Eò3µ®Éc&qäí·x~änKþS˜&Ñ—ªÎödÍ ÏA£Ú•Z=@Vùè±#+ €§Çžb¯¡kÃà³Ñ/ÜRüY@5.#ƒ%pÌÄw^Â’ÇYðÑÍkn8ócÛB'ž^9fWÚ£MܲLj>ì0ôµ­â$PP;}O”WlýÛg ®¦ƒÊæ«tü¼õFcÏn ’5`23éÖH$f‰šžlf~´þª`ïÌÝÿ^Ñ )óûœSÿHŠ_ûy —*“à %jý‡Šœ¾–ˆG!‚½J¢7bBì“9`LéC\ºÐ†“¥w¢ ˜€±hyŠ GÜJ/ÝZî$ pÃ> ˜…JÏ+Ì„™J‚¹àÏdœø¯Æ|&&Ä»á2ןÓUgí $‰+û*(¾ÄE úC9Ck_'…0”â}|ôÕü†×8”±ó„e¯"MR„xil 5*b·±‡×Ê+C¥˜W‡×\gÒÒ}tˆ„kšð Ð ·KìþñWäÜ^‡à&9†1Ûî\ ½R£ö}D¹¾,nŒ’%TK’„©z?xŽ dTͬǠô§e¤‰žBu‡Y´0ÓwÚrC‰‡‹kyßK1½I-ç´ý5Ü]K!¶é‘Í"Š[│@ÇàÜ-¸Z–~¯$šRiåëy$·‚½OæqPio¸OÅ*mò—³ ÆÒ©ÇW‘4¸-.wÛJÅ •2£m-´Ê…ºÈ4M)eÄÉcßèí’ñ óÂðM3¾‰-‰)|éXüfœŠžÄ䆖Ô8N­ÆR²„‘¼¾QqàçŽÙ6áóY±; uÕï‚’ŽöîPŒÍƒGJ]`ÅËѸ8'¬±E“tÞ -æÀIFÖ§%oV8(¶Ò¥}ðˆO—!¤¬ëÕÈý¾CÄ»¼Hr›G̓ì]#ë]Õ§[F“°ÔgûÂr),Ä2VyÁ€iO—,ã”âÏâçpÝÇu8‹õò‘÷Ö— mÇ5õå`ÅeE"—"»šAÂ4gA™(4N¶t]d¬a@Ûyws1§PÏ0¼f)ûï¬p%]Ør)Ýo)®ŽN·l 8›Êçëñ`¤]iR`¹–)°GCʦ֒Bp·5âêùÐéf+: Y&ÿ¨ÁKFò'4™ º‚T›QÙpÇ‘h¸-Çá¾°8ãJÖËà ¤¸ Åca{¡#ñ•ÈG;®|À0«AA&½‘õûní²6ÌWõ“×¥@|%ÓØìqv3û“n³ó¯Ù#ä×$WŠGÞûHƒóÌE…R/rš^3àýt6K2 æwA™Ò+ªF«u5×Ü`†! F¼d^8ª¸ïym¤j4V–|öq™Ç~ZZO‹¶ú‡©^Š]ስ!G¡ ÏiMN—QÙÆôsÒ¤·o† émVŠjf˜grÀÏ2)Yçk…€¾½%)¬ãwͬ €kek›Ï²å4M–Þï 2q”¥¾jI`Rσ ü‰>ßó õCßX¾úñŠ¢/…)ô?IüM’.´i)8oÅM k~w®…ªòÝì±#žp‰ y‚ l;p±õËF¡ˆ­¹;̓øœÑ‚Q>»o„Ú«\L¸V軸8ÿŠž&¹o¨spÏ;¤IÆ©2޳)Q벎dHÓaÚº'Ôh¶˜¤×§u~)§ ,'—|r¾œLL” `‹PX"B{]RpW@bòÓ-s¯ø5…Ž`i\µïpIñÒ0öê>Ü[…W\\{?"óö»C#¿V…™šWHÑ>Œƒ†öj»•PÐŽXMæÉ~püªwÁ6,}G]¶mhŒGÅ?¦„˜Ú‹*ò'4ês§ZS‰j…Xé8àÉ‚q~\ì_uØÔ#\•sBAþ¸s•jxGÀk›Cg9ã¿þ(å·;½½r׫¥„G/¹”à`Z.Šá+¨i Y-:ãÿe‚ lRâG’’t3Ý—ŸY—êªÖ-6°ÝÒßþ+ùáýˆŽú=¾ñö ×ÕŠÔ«VÄqv_Æ›»<å¿”ˆŠÔ®ýÇŸþ ¯ø endstream endobj 908 0 obj <> stream xÚYY¹~ϯò²à™4»[}dŸv,ÀI6ÙIAœªÅ‘÷¡íóóïS–4ŽacÄ£X,V«>Vo~Ù¨MÿÔ¦Lá²iºÍ÷O›ßý ŠMõXÅæéy£öu¾yP lžŽÿÙ>Íî!+ËíûaÍtÙ=¤õvè¶?áxµýiXÆÆp»7æÈÔý0óí›v9ʼîwi¹}ϲºØÎg-„ËdƉ› ÐQc4'Ó›QÏný2žm£Ûö•‡žÇ¡ã-‡ùlF¼èqžvÿ}ú3œäú@Ã3Ðä)ìŒLó,:Xã|°Gbã¸ÐOP °¹«÷jNÏÃȃšû/;Üjüă¶çÑɯH·Í@ ÒÙ‰Eo07éάٲÈ|bë–<{R£u“ÍCQ¹#¤»‡½RÛïõdàPeÛw™Úš±³Ód‡~bFw$UeFl¾k[X¼/¶£=ѼóÄýӈ殶3ù ,ý‘ ´š3ZlcúÉpGÒ¸YË*¤•B2Ò ´È¢ðÛ r/¤Þμtè¯Vþ8À¿{½"Ÿ<^mnÁ¢Ÿ‘ØêCkÞp¦Ë8 ˜Ÿí‘MÜ.I½fÍÒC»AϘQ¥Ø¯d+˜èÌ VÈó=8iÆ‚F€Òüzimcgrw˜ÔUŒðy%)—‘·^úÖvÖoÊí­ÉƒóÀ¿ãÒ3 /ïÒw­8Ú:mÂÝÓAaÛ§åÞéÏr¾ 8<,óe™¹Í·[°QO—;šÀ»AîÏh#32×½·äK=T†#­´ŠHØ}å6{’z½‘0}ûÊ-ûÌ¿óZÎwxÖz{²Ì»—mg¿/…ª&ГÞÅaÓÅ4Ûy™ ,ÉS…‡ËÓôVâÅâ:ñùu¢ ÓëàÌ%+Ñxa3t—öÎõYBnª(«MÜä´Vù\YʲbØ¿k“³Üt¹[ž¼dF«¥'ynçÙR´93yÐHƒ—iÄ…=æqh£Të/>Ì –•<‰¶èHÈr‘4ÆGÑnT@ñIE:Ï•bm`ãö‚C¢Š/x"Þ€Äá~cbåÍgîñmWr]UäV»Š0ôžO%±FœEϺ}F³C[`Ì-éÑŽ¦™­ã#QKÅÚ#%nu£ gy‚¦ î2t±³=ØÙCV‚zaLK£¯±ƒ»^صaÂaÞ/0Å/‘Oï2Ѓà7ñ]"ÜiìÈÍÑ´|UÏö”âÏ0'Šy#¼÷.[{—äða^Ä'É=°‡ñÆŽÍÒ´ê>[!ˆ¸ˆàÎ,)(`QÔÈ‹˜»@ÿbË@Ù`î@Ü´ƒä²‡¼(¶?-ŽÜ"4m?ÂóåAÐß¶_è¸Ço¶;WÁŽJXm.DŠ8»ÃÝ0pÞI¯ù¿ˆïÓ"{LI À¼6ãn$2 üâKën0'²3°ýºàÂïUºýaaý zßõ»,ÙÎöá=™`™ñ3þå(@÷A#—¯z:üãL]Þf( x{Ó™4Å0ØœaLÇ+øÕÇ-ò÷šÞ›´Ä@bÉPœHxt‚Ê>÷C;œðIÉÃÑÓ2 {ç4Ì‹‘ é ÂrzФ ž|^ZLdmë"ÞG(¸ÑÉ'º4ø>4á¶!Æi±UŠéD©s]øùO?þ‡î0 ˜GQDDF¶ÇáÂÎìz^›&Üÿø…Ì=yXؽ® |&QÞã¡ ž­Q[Â/t†Ü«7=ú2<–çÑ:oŸç+âg.ɱ$(Î]‚= mý “`ŒŽ3ã{ÂO_•Çü‹£„aç&â”™ƒ³n«2 P­¨VÊ£ ¤ÚBö)óP%¤u¡JXòÓ‡–/1Þ6&¤½AZ·Rü€Àe>±ÁZH¦vé„b]ÀÅ„Lï…ò„ ÓÅ6˰L¯±rEp‹_|ƾœ›» ¬šÎÜ!ü ¿F»`Ä/®Rpb'¦Ügnša”1‰ŽÐ x:¥,¾\ý¢pƒRÄj$¡R2¬:Ñþ¨”Àrõ •r4[y8­ž¾¬®“é]=›g¯^(œBG*õ"l?¯‚ŽYi°àÃPÚ¡ˆÆÂé}.É•+®G‰7ãäQÅäáÂÍúñ2»Ú¾/tþŸ:VšFu,,’ßêñd¸ïOÍÕ5ÛÐx&Ź É¿ÑÔ³+Üíp/Ñ>RÛJ³èò¥é¥,§Õr°¨^HÉ\äš–‹`—qŽ%NoMçʃwKäsüÖyvyDKߘ/Æð¼®3ÖøþË1ü/$­rI& ßaà…#Aþë¿m„À®"g*.´I`W| µúº«zâ œ1èVοTˆP5ç×0½UâæÀ ‰did Áå *ìÖ»Ùþj7úÆôåOfSôMËÇîú×u|E#D‡èÕ›msWi&WQ$3ºþÓ ecæUHX ÉËèž÷¿¿…õÇ/z:›{ŸæP‰>Êÿz‘;ÛKüa™WÑ0¤ˆÕ·º™ÁHöîš»ìL‘2D@ÿQQûÊ‹á ~UÝ}¸ög<àSx£ò‡šºŽÎˆÃáŒØ“3bóêŒi]†3"Fìðq™y„>ËÔ ËwGÅOx‰# _njÁ i]…¨™R‰ TjˆŠòâ}w|qåo%q@kò©ùËbGÓ­ ¹¶ËtåÔñ’Ê©Þö÷Ü[¬/Ð÷ãÇ€;p›(ÅrúrŽ,Jþíi§A{b¹ÑÀN°"öü×…U5Õ½ZFÃTÑó‹’üå‚¿cÁÏËyhÍmÉ“­†­«MWôä IßÒ“'WíŒ,–Ó,‰û–0ùT‰$ôU‹ä¹ofŸ !Ááwµ*qßÕT WBj'L§¨Î>ˆt4áÄxúÖ³wp€× ÀVÈÞªX~pr ßa-8²«j·)ÆAÚ¡—Î(«™ÇøÀ¥§¹„˜G 1M÷Uºy(òŠ” Ê½£ýûoþI¹)Q endstream endobj 911 0 obj <> stream xÚ•ËŽã¸ñž¯hÌ%j {"‰’,'§Í" L°&ÙÉ!HçÀ–h›YòRÒÎô~}êEŠ’íI‚nÀd±X$‹õ¦~~ÈRøËv9ü§ÍùáŸ~÷CV=Ôï÷UõðéÃÏY ‡Oí?“/y îóÓã³*T¢ûE¢»Žv¹qÑnŸ¸íÌQ»¶3£Œ þ= Hî ÓšNæMˆ9ãi4ˆðù±Ü%úhÚ÷ÏE•&ŸNVýhÓ‚}´¿ ¶™^?‘Çg„º³G;ô œd°‹ À¸áOÉ„lÿø¯O^óA÷ˆBûÍ“&:nÂLØêc¾‡±ºJžú:OBjb@ Ëo5‡­Na) û ·³­ž #Œ31âĽ'‚©þ}£½ÏŒyÒLÑ’%£‹ºÝ£;Óá[ËsìôžÎ›•ï÷œ™~ðÌíË#ðNõáÀ¿Ä/lЩ‰_E]¢#ƒñ4»d2N7®±O cÌ#ò«¨wr`@9èÆ ¸”y–¼öž‘ÏØžÇ‰{­/æã"ß].n¸8K¼BÀ l7ÿ2Lp¿ã€lY“´íp¯°>±“mt <ú³?{¸ïn8:}ePeÑîã"ÆúX ›NzâixûákG@|(Y r(D–C¡hÁÖ߈õ3Š_VF½ÞÐÂY©JÎú3¢F€óžÃ–®d|îÂw¨†yÒ ç‹íôD"XT¬ÖEVša>‡;ÁI‹jQÏN'F¦Q!ַܰ}k.¬6ÐbštjäI±‡þÉ‚a2'H¸€W/?0 ëZY¸×Óì®% ¤C›¯X 8+ w–òa³L” ‰K€‘½,Ð2Ða`o‘4Ñx‹Ðà-0Ç_mH1¯`ÌN !«ÀÇL÷ inhàÑÃàÎ ÑüÓiw$Ãà…å™¶U£¸Æ £Cï'^ ]çÐÍg!P`2åõ×PuŒÓàÀRsÉáˆ÷ä,A6V0r6­iõ4MȘ°'B‹äñåEè>&óŽ!VdcÓb1D;%@a_gƹ›lô3.È·7g'¼®é†}'TÕ¢9ЛÕr‹|üvöle7SÁ¾›†½\%ÇG<Ñ]hòŠ` E¸·Ì_æ·cXØIó•ÅŸM|/ÛùÂv%¦ªb±íì— Â«.þCLýêèú¦›Å¯(Ù¢ÚÑÃOPj/åJÅö{Vfjÿëo»äûÄM+oš²žÉ+<ˆ•ÑÅÁC‡/r_ˆŽÛ_ MŠ@Ö‡haOÌ€?}â¸g÷€|H÷>î)Ó÷•"®T{” ß_T P9\„ˆTF¹þ ÌpCB©’÷`ÝydúëˆJlKž½ß1ñ<‚g#Ÿ­ÀßiNî4C¿X•7æ¯æŸ+{#7Qoo¢J)þmš)Ü"ÞA+Ü`S˜3˜V·âU…nì¼âc&º™Ø"´}‘DB¿|’ p¼EÛòöJïÕ. Spf7w/1 ŽPä>NSÀ*6¢`$ŸÑ­~í$`ú~p ô,è )|O0#Üàø³rì) 9+Fu?f"Âøb5Æëeî2ÁŒæ*Û™jŠª2E’_5ÂŨõ Yß vmÆTy^$†Ý3€ÌFkÙ“(œ³cPÉ…lÒÛh œ²œnŽæÌ¼žJ^`Øæ$. ùçÖÑ\µ±öakÿòøtçŽÁh‚ÙÓ½e [ÿŒm1jÕí+k®p^Ò¬øê©«ØrA·ÈtÖGVU)›äÑÂÍá¬%3Sí‚ñ¯PU¸1‡)Ä“â.¢ÀïùÚ°²¬êþhîÄU¯, )‹‚ÞØ½‡8c# )‹Â^D!•Û%ƒÌ€­(ÔA²YK\°¾NXw+ éVÒxîn5w+ éÿ' 9Är¯b ó=Å1ù^%_œ ãñ®\Q ¯R…™SE™O ËÂ)huð·3zœxâtrÆ0”l‘Ñèeq„ì6VÔrO-§H‹¨ È¢/S%çÕekŒ1^HF°)~‰v/£,p€ ‡ã|‘wÂ+‘À, …’;ªåŽröæ¡CÎd{v”0‰’dI2JcÉïÅŒe= *ÛÃ8ü÷k^`íR²<–B7V1 ½$J6‚µG¾x'‡aç…xl½÷^Õ¯´)¨½*„%à_¸ AŽÆpƒÕ´ŽÕTâ#´ #WUr|J¾x“Ï(¥‚|"U¶±§@¯Ù3T3ÅáÂ+…C¬`ˆpÉÈ]q@ŒRáÏF©(£´X ña2±¤­a­ÄYöŽe(ŸœÊ#ÑÁ˜8oç«;zzï{Ñ5ãù:O|Èîm]–ÁØCÜs|m± |nJSÏáÐ( r¢A 1/IN2‡E*“cè00,À"[Üÿÿ6ÜpÂRh2‹„IÑ6e+šã%ôW¥ò„37ÌÈî8ƒ†œÊ®JW>:r8ŽE¥àÀ0vX9 •¯b’pʼn¢íäY¥×ô‚ýEh0r8B©§âð·l[™æÞÑìkGÀǂ߾ô¿ÄòtjZ¥(( vQ‰§eàГÄa‹NÝ4“ÄÒ‡­%J|άpci´.¨~WîK+®5Ä óñtg‚òü@ šüíeO‡ÙIñ,_Û•ç ’Ð[â*\Dz˜v_ žCÞ°LQ˜-XfÑÈ0N·ÓØ|æ¾£Ò[ÚMðÅWƒsÔ„`‘R¤{’ÑM¦·h JEµçhFEÌÏ7vG´ë-íÛ*HÒV±_¬J6ñ»ØÄM¼”‘Õ.ýo©J¥*qš_¾°Ã#œ·T~íÖ²ô®¦ó„•{þK2HmÔ‰ÁÌ%*£|WpÑéP»­“)›Ò¾ÈT‡A×¥á(*%à»V«%Ôƒm0pÐíìd¹„í·e‚,6 ³–wM–IBïxÕÄ5”"2ôÅ_%æ€WÝXW)4Ž|!aŸ_@§L u˜cªÉnÁ‹XuG!x³²¢¿Å¯a0ÈEÀ4òÒH²ãÕÈC7–ŠeÌëÚß^ä° zfV¨ =zII7ä;†vvÆW\ôæËŽ> V¶[ê/‡iÁ­/”@r²EÀÊe¡¿C;xÛÔQ”7Lgoîø0C1ùûMÕ¨ÈýkU¾[ÛÄñ½5‰5ßI d Ÿ†g‰XÙÒ‚<:Ýò‡ItQo$ ’ŒÛKM>uÊÕ"#÷EðhÕžExïÊ"iö!KVÝÉ,*›'`¾ä—­ ºÐãD"«¼™•÷«þ•‰U."s4=Ø#y·ºÌ sìnò/`Ü—ÄÄe¢/ÍÁÐ*€¡ª½ÿ*•ïjy="AÄn0SD!xØ|'JK€Ø0 øœ'Nä!#w®­Ð¸‹¿æ+G¨~=t°Ö»u#ÿ)¢­…˜æ½þô6Næ|çæ´¯N»7ôóO(ÊÃ_¡–—e.ÿ_ºô[ŒÈf•hHî%GkJ‘ƒ®¯=ãÕ"â——¿óë/´?FY÷;q,C¾~@S¸~€Mí‰ÀfÇùÌëôý*c½~,±©{¡í«Ÿ ¶$.8ä(&´€ÜàsÕ)š·!û¾};=¨<'X.åœ[_©õÄiI)ÌôÙ† $.ëž p:!r™øHî”22B-}LµZþZü<—씄Û~/žú<•Á¯áü[oVø·ý~¯(O“–lˆé:XCÑzŸ|è9 m –Ùm/fÌxsÈÕD€mêŽ9¿âˆ,IÀ¬1ì`˜_§ÃÜ º¦"âŽ'ªa3¨v@+‡.| AKöü{Ð!%d›`F®+¼ñ㘦¼Può…àXê«)ªËk~œ²ÍÜi'ýÕq²þ2!>žû|,$«µYDO†Úwžô¼ ¶§… ‹ø…ËQ¸Ð ”15&ʤ¸q‹ +`u³éô(¥R2ºûu¥Rj¶ñÇA1*ÛK,Nzš}Át;¸bôùÓ¢ãbzù2e•{áˆíe`y”_M¸·D7Í4‡oçH!wÌÁ¢‘ø*Ö¥Á`!4RŠd¯1HKθph¦j"’㘠LW¼IÛ»øŽ‘7º­ ¹éÎ5:@â;A|ª|QÔ2 _ˬν)¤µ|- ôäÛÞÉRTP°XqÅ…|×K[3¾0‚¼¢øß?/ÛFˆ°'ͽÿ¸¬^ÕLHTîÌ|ÉM ¨à"\×ÁÙ`1á*Ùéuä^»=_†œÇ 8Θ¿wœãˡ˜Ó…ÏiêÌ%†‹@ç”­2m?âI¡õq}…ñþŽ>ˆð~‹>½˜NrþÞª wÖ˜"~Õ3 :ûkØÑ>ùÌ¡c°IC0Dz·ÝŸ]ê^øP¾å…Œ)º:=¥nS‚>˜f¦ïÒ‚Ù¾çt¸ðó%M’ïr¸Ÿr±=½U´OWß÷¥ò>ÉIÌWl}\‹3@|å*¬°Ý×íOfx0cÏ _‘fü} ~s+"DxH+…_=ù^&f)Ò¡÷=þB.ů‚`#U#Èd?à×gsˆÏ¥QOSÊíºuP'²>>Ì=…ÞaG¼õ;ºïc¹¡ë¨qýP%’> r=õ‘Ïõä£å¸tpñ7“ø­\ðºþ9tò­cîÓÿ¡ @Vw×x)¥'Ç%nÆäLàgÝn>)¢OFò¼|_çÏUQC²]åqÿú›ÿyCÃç endstream endobj 914 0 obj <> stream xÚ…Ùnä¸ñ=_ÑØ'5àqtÙ§ÙÀ›M²qqh‰v+£–zuŒgòõ©“¢ÔÝYØ€x‹ÅºYìÃχèÂ_t(bøõùðÝÓá׈òCùXåùáéõeUzø…0pxjþ|ÿzü—QðõÁ°`' ê¡Çîçc\ö+˜¿q0¼?dEð[χQZ›®ûʰ¯ ±Lv‡Îpÿï“îÿ—Q]êYaúFi³Ç?ý³ç±¢TV´ý,(à€„ª®—ÏTT™xâbÆY@^e†»óhúÉèÁa •ïû©­‘Û'ìD ­Û·n=󸢻ÐÎÃ4Ùir¸ø 0Ë|p»—+:a 1#*b„2y4¾Úq´‚nˆ-¡Ï˜Da0‚<.­í…HÂ3áWä52±v^ÚRKŠĚDKÁ ÷Q¸_pk›íx–aØéÍŒM'æ9<~Ob}g¬BW´å4Q5ñD”žÌsvlÿk›çãÎäë™~;ÀáE݆¾Ay_1àoÃ2Ö_î-KôªùIT‰æcËi>®=ãÊešþ…YÆp¦®‡óÅô-c+aVØJl|ßO3Ø‚Q”8<=ÓÀãñCšVÁwËÌV"FûóÒŽöìI¬‚uÂNþy3:o? L^ærAÃKrИWê-X+éüèCh†„‹«z¥=GF·cÃÐd)qÉ3P5›¶Ÿ¸ÃG óÒv­Iß–ÏÎPg±lrVðo.©Eí-w‰gy©{b!8´±+ù?‹â¦q`¿˜ó¥³¨Ei"˜RòûÀ$@ã&žak°=wåD/uyñO¸øÏz>>ÒÖê‘èƒÛ?‘E§ùF޹‰4#þÄi\àè·ÚF ·Ê‚ ž²0ȪÔ%¹#`Û×ÝÂx rg¿´¹8͹¥ÏboV8Ò²`Z.bqã|Ç ƒh>·51:Θ¿fQµÀ¼X=Ê‘}åŽ {K1äh>=p”­QuJÜòì ½L°Bþþ‰ï$ÅI+¼“ ýUú˜ò ð7$k›¦E~e<« ìó<1¢›×š8z,XÏŸŸ7ëáhrèñÜRÞ<}ƒÃàˆ;(=ÄÍcJŠLŸ)ÅjÚÛä*b—dAëˆVýdyúE˜ýâ'fRó¥¶$R½ŽÃYö² pr¯Ûœ•¢<ÄOÅèy FË&´ÄËtËK€Üó‚GåØÐ2Š3>pC¬¿2ð¸¸7H€$ÐëˆSo£9óät’ -òÌWƒ®°yá^n÷a Ï­ër.+8X[Ú)Ë5)ixŽl'+TÐ<È–ƒÎ[nØ/ó*Õ̹‘ ™ ºB€0]Û0¬¦öY±eô;Šzï3!Jáåš |þC_ƒãÿu ãT;.1OÕ wÇ,åRXê-„ÿSêŽË¤Œ8, ÏÀݱááÉ<ˆˆ7.×[襇Åy@¼:J~>ìòô\ÐîNt'ˆþƒ’–$Œ¼OíJ¶óLÂ*Eüð]ƒ"@€.´B zFÃLÓ.Û·‚©¶#^V¥c&{Â9³Åü~•]œ®9÷ëWž•p’¹Kããó¼GÿfÔ[~_)Z<óSšSû"ŠƒàqFK¬ßÜ ãœ…‹ œåøÌѾQ 'Oe2ÓÔ 1­>KòäG`x\¥¼ƒßרpP !,ŸŠiQ·Œ£N0÷„×aÇO®âÆ®€¹QgsÄùIÜ·(õΔî3H-ŽÏò âiÔü°1j‡wQ·ân¶|__+hhÔ7»³æÞœ÷CÙé0NþEX][gù­[teÝÖ¹4[wNE5§…ø8­ÄÒmœœ5t…ãzeÁ£i,ÉŽ=œá²ÑœqŽk8[o=7éüâªíô°­HévÕ™éÿv+Ê€=Y±õdxåƒúM]¡Ø•ÖW¹8U_yï«/Ê7¾¨X«¶UæÂ¿»ôûi`À5Ûe$Å®4™ƒÙ-Òç[×x©×\YkúNÉp¦Éã@‹#!¶Ôsá»Ö‰¾GNËYk ¥v a¹0/Ujlì«ÔqJ“îê€KoacOÄø&{›Æ«G¦ ½ìÁ ‰® ÖÙÔEyznhgzT58Ý»Ì}ì$s–ü.‰ñå£ÿ°¹¹ÜâmƯe \‹ITBÚFä€òÄGå¥Ä»1e…wU#سG¾V˜tÜ/»a&µ"·aç²ÞÌ=ÎJmZjVîñYßM³bOí‹£Ü+Ö` `Uw !:¦0dÀï­ŸD* 1a¨i+´¼*\è=óŽ:ªâ«-¤&ÁãW×Mô~bâ=ñº+e¹âSœLn )\ŸÄˆÓŒ#~E!aÒɇ¯d_†›çE®d›dU#ìl„`òa'îÒû+N DPU Мñx‚¢Üü•Ðî¸Cr‘WÙJ£¥ƒ£Ê¦ˆ+ªø5ü¹®[ßÁSùq­×l³->¶áÈý<ùJ’ÓBëëö¨ "`ŠœYaÚY.Þ¨Éà}[Iåç&å/)%¨w^žÁIm^¤ÚŸè«n²+ %¡ C¶Ž@òë‰DªÑ4ÉÁ š+1I"7¢„uš¸’ z$«„¹÷—ēСE\ü64ú•j¥ñ^LôΓ&r‘}`­Ü”TœRb„BDr/x>°n:çˆKÜu×£Þ¤™¨}&”˜ž¹Å¡&æx’lJÕ8ì*~Øéœ÷AÊïæ`º3% ’=¬O3ß©Þ–T×·6UIcTêˆR*£¿1\~(ó`û8–zcqœ=–ñáCž–DkT û×_ýLïO endstream endobj 917 0 obj <> stream xÚ•YKoãȾçWs Œ’âó8Iv± 6ÁfãKçЖZVg(RCRãõþúTÕWÝlZöb‚1†ÝÕïz~UÚ|Ùd›”þe›:§¿t³;mþx¿ùÃ÷õ&KïÚ´ÝÜhø–;Õæ~ÿ魯»¹-³,¹¿iËÄŽ'×›Ù ýÝÍîÿJë²jÓÐÔŠ×eå][lnóì®ÞÊÚÝ4e2\nn·Û,9™›¼I^Ðé‡ó8œÍ“™-wódñ= 7·4{ï/ |voò•ÿ³£Ý31MžoòšV~FÏþ²³çYWMøÚ_Σ¦î%ÊK¾º=¶È’K¿·#šóÑéªÝÎö“%å6ùÔóšbæÙžèf­¾{áÙ0íøì&zT^WÉ<à½5¯ky+“å­­¾• nƾ÷¿ÊûÜþ#ó¤IL¿Çø³ë:Ì0—y8‘\v¦ë^08«¬ô/²ÇEŽ,“Ñ=™‡³ž Ï—ËqlíŸòCâú]wÙ»þI½ÒÓ{Ñyr¦3¥?£ßa› ½§Ñgá|±p¾ØÒÑ“èã´³ ­9ј1Ùk!ˆYöp}ô’ßìÑR6±ª5ÄÅ"%&óN¤Ò/Lm‹dg ?˜é†yË´¯nèŒFt¹‘UMˆ¢|’}~D Ë·íÖ³KãpÂ$=“¤wę́΢mT+¼$òqèÀ-Z‚ã‹d´®¿}G§Ù€ÑUI47ܬýŸèY¢2M•Ðý·5Ë£#KÁ<Ñ4n\ 3×a+ŠèrÍf}Mפ)dzôt7‹íÅ{>¤YÃ¥ôUÏŽ¸G;vÇÛ:öHéMWúxçAšÞâæËI"úÆë[S¼z4·É—gДƒqݤËȇÁ=5E¤E*i¼¬BDôŽ„Î˜†“NI÷HöOÖôzâytƒÞ‡o“*E¯:ÅL(a”‡†•{ÃÚ’~OS侯ÌåoÃh½‡ma+9]R_Ç¢ªMæ49¯Öd&ÄšÌä7x›“äöåd>>ܲ7ᾪ@Ë23¼á¿òà¿Ø ÓBãXì‚eåe´~7 Rüö•°‘ÈJ¤mŠo°Ü¯|1ßX8wž±F8.¾c!÷ iÈ ¿í„©q]aŒ<ÂK £Î¨Çꘂ¤<ŽåX­(´2v:(ºa ôÄçã€ëOôGî·Ò¦ÔÜ»æ!ˆìϪñ¬à¸¥LFÇ¿V¬T^Kfº ª’®ô—¨±«¯®öŠß$uá$ÎÒòÀ=hth”ÔxÛ‘Èc‚Ë‘Ð;r%y\Y6%§úåb:øÿBc=Ok¹+Á›Þ>cƉeE˜‡œˆ9)ú! gGg:Ð>z zRhèw÷oøœzy.7nÁÚ106ýÎ"„ü]^BŸí—‹šæH‡P³M~07¤_ñI¨ú“hÇÿüÙå1è²ë¸1†ó²†ÕìܹíÝS¡Pê¸ßa„[VGÚ¬žnÔK™}*bè# ÿ4„7O úiÖ§~G ÛŒ/ôž¥ðŽ•°N³×eÈW¼ÕÃ4ö,:&ù õ€þwä÷F°šhÓÐYQÑLs˜,_v$n|¹Xˆ1ËÉ—I—ç^ßíx;· †D‰hl&>Ü4A“˜2à»âàê žaLìÜg™‚ô†){¼ÀNïKQ‰s§VA³"—몔^_£ôZ\àQžÅ›HZ…-(Òô¾ÅšÂ­ )ÜAžçËkƒ]s'øÏ&2xe”¥qwÐãŒôý¨HÛ땉^æôâªl“û£•›f”JŠQOè¸þÀZ Co Þ‹Ñ/o¢K¿`¹ì sâ¶2‰Z‹ÖkŒ– ^’G5|Jô`H€V3®pf° ѾŠÊXó*U/²€>¢»D ê¸~O ì¬þ0Š¥¼gì» UzqŸZ¨¤/€wq¯ny~ÓYnÓê®$Ù­Â[ú”ÎÛ«/ô¿Hþ<°|¦BÐï?ù³Ý9ò”=Ìßæ/¿3;~.'¹”nëHk™L–¿pô4ƒy»´ ¯i,æuÈFjñ”¸Ÿf:¼Íº~ ³¼7˜Vg-‰,u4øKÝÀbÚ@ÚJḋg#¡à·¦ˆªnÙMËE›u=„‡Щ‹šTá&xëÒ¦ Arêÿ¥€‰ H›¼!0%‚"é—JUÝ `ñlÄz¾œà3ÈP24¢"RRÃöÔÜA9jv'ÊyEY¯<ÅcT) eŽ<Âl¤µÏn>†kõ~•~WÞ&šïº™uáTqùp3ˆ’§¨Ð×àMˆë#RžBùhãqè°©Xo¡K†ñÉôîW‰,†¼b¤!a,è›S £Paá-¦ÉÎz#¿íÐÛ¿DÙA‰”ÅC}u{¸¨´•ûÀU­îSä@"›nÐz½tº…ç , Xnnû†¡D ©É|)%ד ý~ÂÈ™o¹®áa«ë1Óµ$˜iÆÔ£ÙcSÙ\:%=-¨½YRµ&N-%¢—)ÜuI©)Q¿ó#ŸU-)Sä¡Ù@èqõndqÞŸnk‚Ýcä~ è<áŸw:‹êeQĽmðÒË„êÛhD؆o`ÛG%½Þýjñ…v”®åB:°3ºí“×3ÄÉ]½~U#hÒl;Œ>Œ^9¾Åo“ðNÆÖòZ}7ñÌ€€‰YyU«és¸Œ@•Üá7Îã±­0#x:Ûù/–<=¶jÔ[µ~¸Yçüô 0T‚²È_C«ÆÈmP89Êéá+ŸûA¯ïåíO º—¡ #8®N\UPèláyŠÈË5[˜`ðé]&ëwDÅø…Ý”é`ZQ-ªVoQ.Њx)3 –¥[üœ…ƒ²â€oÌ8¾çêw&(‡¸)ºR£±/ÔiœÐ·‘†PG£;ƒnGqIPõ:êxŸÏýø—!|v#Yñí®3î„Ê9Їʋ·!?J§¹>ZMi”T5ž§‹›Q•—xhŸÂ)ܤ¡øv]æ~õK‹?š6ø|BaF¨<ü{Ügù¨U†iiO¶ë||%[ U àå(˜ÚˆºÉ¯2J‚N±:Ìa~øQGëõŠPXä-‹}‘ÃÿÜãæßÄïešÝepY¦øý'†ß ®˜} ÿħ•„¢Úq„ŒGFME¡L­àToþjPD¿ÑÐTß ùîHÀøW«[\©”Ky§ `¯Šs™Jyàt)ª˜‘•2²ôwŠ~ ¥«€| §ùÅ;üM9­U=šÉîåGКFŨK€œÊÝË´úÅo¿VEÎ-ìþ•R¼b´uÒ„+ €Œ=ràüðö Ñõ¾5K–‚–‡ÈHQJoFµO†ÄŒ¦êG$àF§Ízz¥ÓÑF£÷> stream xÚ…ÙŽä¶ñ=_Ñð‹ÕÀ̤uKN`¹?éüñ‡0;Oe–ž/‡0}*“ÃcxÀá¹þO𽪎Q\É) ª¾;Fy0 æežú¯ƒêgqœï8èg(þéúîQ©šy4ŸqZ?<Šƒ7šúÍÔ6ô$*ª™ŽQ¼?^­y·›š4‚Ç©t7jÞfîjM§‚Ó\¶9ó·#¯Óããñ¿Ï…»n¯)wÏHJT_‘aÛÔª}D1Wàž˜àzÃN,i«5i`mv­5<Ǽâ=îLj‘>XŽb«ZÝÁ¯Êt£ ØfËÞXö‘¡¡Á¦åâzq FËfŠœH V„r%ðA× _ü 8‹ƒO³ÔFVºygÃÍ@y:^&$ת\Xñ±Dœ ñµ`ùŸûTYÜ]W3Y@ø¥Ÿ™O¸Åe³Èñû#Gg" øP|ÍÃ4ê¥A2y*º›çë:s­“IÒE|cwRdÞ¢HŽB¸N†HˆrUë,æ{„D"ÄåÓl[×ë§«Èß~œÁ+öóëÕÞ‚0nó 0•dÁW+ÖW»Ó¹NOâÆJbð2‚p4|¦@5ð˜Í8æÃŸƒVµa™ƒë¬*ð8†yc²%òqxJÝ1ÔS¼(h‘þLŠ #mÊç <ù³Ró($™Að±¯ñ¢ˆÜóï …=Ž;wÇ \QÐ…£¢€³DxüT8 !pü­õmd.¯  _Ò_dÉUÖÊ¡: >™v‡ä›=RqŽ '/öx¬Œ?€'Ÿ%3oÈ^¶Ó¨Ì½ûÄ›û<Ü3Åtœh(þiU×qh#w1šÑ÷±9ÿtåY áè~›ÍàÜâ(™Í…gEŸa§Ï¸¼çyý6¨7$×Ñ=÷={!+!ÁaoþÔ³•,HWæfìIžî¯{>ÿmãŲÌz1Œ5YábCFÎY‰ëªÉ¨3¥„°Ê:ÇF×dúš¹¢ô!Ýœ'FcG“Y­…ž›Ìc{‚7\;pq¼ÙB«ê—iôâw×wî|JIJ/8ú˜øÌ’;WŠ;$ï$E¸f4fЈÂö $üÂÚ1‘^ŒhXµýÊa >LjÃ矛ڮálBvíd7>2x¦~Ô’£î;ÇE£$» ¼j²Yïr¨ÕTä©JnU¦AEÇÞÒ뙚ø†ÆhëT(æÚfÓ)¨XcêC<2%‚Ü<Ьœ½D’›EˆHnQÖÞiÈé$k†Å€­B3h—1*‡½PgâgÈQê1 mEÁpÚgµ4üR$BVHnÆSĘjFÙ~ØK  °2ì0 D”$ #Ì)÷‹²ð^ù"/q°¨À]æÉC!±òÐ^A-­ z&bc,l„ ×Xàþ’P§)>k"a" ¹l¨ Rn—Õ8(Ê®…!b¢c0á4“Ϲ €6°- ÉŠvR•SEL4V§ÖC¦V`i¾SÐqmæ;†sžvˆÔ"õ³\N÷JsK‡‹M6ðTªå4—þC¾ŠÒEpIâB®;Ô>½ÂÑc†ByH ÓÙ5r—¢ö8ö»R`ô ô܈⌠c™\îDž&vƾ]«ð‹Øãæ K+ Àr›îßJwL2›~å±wEøô¯Ckìè;‹,«È9÷»ÙÊBü/áÏf¡IxwÜX‡DbEŠ¿JÂØ¯@!ß„pÛ"E”…)«¥r9üôôQ–V/’¹¹…®õ†¼ÓÑ Ї¼kïNh³;\ÅqR$±:ÏÖõ~-Ï=ÅP¥÷O.t :„œjžH}<ŸÉˆ+w{ò ΢¢ðH[OÉ:³¸˜ÍÜè¦%ñž¬ÖÐä6†œ’Õá“L‡ñ(ib»<ùú{¢\ÛŽ~ÈAJpyŠÜ<_áM‰JÙdÔóñæä(|^èÞ€ •p«î ”¶RÚv cˆ”Ç€ cʽt‚ó‚ÖsE>·LÝîUßÞ nGR£=±š>´ƒIÑl‚gá·³pÝäÂ6MÃýÔ,ò »µDuYhÐÛMÈ‘eÑÖ% ]®û|¼uáz*–IAÍ^˜qFƽä ;ùÆìyETÜg„ÿPƒsrcD§SþA–ñSÑ]FQ’ìð—£TRžl”bðx¥D ?]ÏØ/˜†ùƒkðô¦WžÚ§G¢SèÖLº¸‹‚= (ªyfyÎ)¹?MD¸ƒ„Ÿµ¾à¼T:­;ÀMãy[¿µÊZägþÛŠjRŸÅ;m6¯¨ÛÔ6Þà²Ü©²ø÷­Þ†è¾±x¾懸ü€8•ø‚…Xð”³dÃèéø˜†!Ž#Â/ó0hÞ–@òO¼Éø-8‚ Z×}Ëûì>õEáS»&26”\¶5rÃŒrüà×)E8ê¥uüëLןÁÅk–ÎY¿Å¤g|Ùâ6œõ ]£K.ÛÕB4+êm•…ȿܣ”ªM%˸ºâI{‰’M .¶›„~6‰Éi¿3FÝó<åaø*N½œt „Ö»"ŠÄ®lÅLœøp[p–—$„;º•êÜæÛ$‘•Ýkãð¸j™¯<çˆ÷‚d¹¿dâïNwÄB‘†»¹Í¤:ÝÏcCðÌKY«iÌ«õÕ°YF”Û›F¹çV")Áªä%ÓA²ÖÒAmÈ:§›½PTI!¥µ'FýÛ¬»Jºgž»Ï=Ù„;+¶} š¤ª*&8àÑ6!Ëÿáh ë uD[ã¾^ʹ÷zÏ‚µž?Ù«î… +\ä(í…õ »®ê›FWöDü3ô|%LþÉ&ï¸"Чà†Émú8Üm<IâÐ%’"Òº–!^k¨¼g!.¹ÊÚŸ‡‚]û°z%Ü5‚II¬¢?p´åö0¨¤5ŸNgq=‡©ž[×§å°¡ð÷¾e` w)Ô’xÑÕ¥žçÍ’Ð{zðÚ{ƒ¾ œƒÀÀ¶±ÕÌhÂ;øZs„™»4"Ë”¯††¤Œžb ±„†_G©`$çZ²IðãO¿2ä;þ ‰"?êÊö†q~¦ç%žX•©ÿ'l@.Áöé:‚“W›ÂŽ/–ç%,˜X3?yµöâ—ð¾¼çƒrÕŠ·íV¤x÷Ž´¤fkL÷Iê19¤–HïÅt²Þ¹ Û¼^§ÅRM}Lì;In«½fwìþF¥æ9× ]rù ÆŒ·Ï)Ò9a‡'@˜_SN€±çj©!Ä5§¼|ËÓëýRÇ1¤vçwirœÛ¿))vŸ¶7% 5ûEó°ª!vˆN,¨³y<3ZèŸ{Mp¶“Ëe lbSÛ®ˆ\üçÌœþ.¡„ ½ ¥~s(ªj™šß»£Ãüè%C˜sÇ ~ù± ~, #’S˜ï½ Aœ¦k/ y¸9Œ‘Žù*}Áûèª0˜ ãn¶Ë*=t,ް°E”‡½¼=‡»‘ôþY9qb‘Ô÷}ío#EËQÑ”ìîT‰Ëµ„±ö|‰çù¢(}*¢Ãc–ìûòÒâþëÿK4‚å endstream endobj 923 0 obj <> stream xÚ•X]s²J¾ß_a›ÅªÄW/‰’„=F}A““ÚìQ©Bp“Íþúíîg@Œ¾§ÎV¬0ÓÝ3ÓÓOÏLçßA§OƒŽ­Ó¯ßYï:7ËÎ[»3è÷FýQgùFìkîXåæŸÚÀìu¯‡ƒÄIoº×†chÝÑP‹‹2ɳ’)º–¿ñ×ÔªmRBfš¬ã¬Œ{Ý-ÿA+ ¬ŽC“Z¼Â`Ø™k}г Ye¹»×úh¤Ýv¡VĪæoUWw´Ï®>Ò¢¢-“²MTÑúLs´]ÔÕmí ýá5MÊ-©ÑïÓdJoe›yvB⃗h6ÃÈfˆSÕjÝÍVªgq¥`/x5j·è¼ùN¶}­vz´g•ìbe©\}‰Â6&#†‡5ë²…¡ íõTAf}&i Þ+­HLLU&»$ p’L÷I‘TßÖÜÆÚqg<…™?ØŽXëŠ(#C{=Te;lc–Û$/ý[kWQ’ž®m6´H)ö8 -ìÏÔI‰ü5w¼7ÓÐØ?L]çÙ:.²TR><Ú‹[™£¶‰@(öµ÷,EŽ@Ý$e•dïŠú€ÖÚ9Ë:ZƄÎcOY¹ ?™öHóß0ÌHcEþ^D;tÊ=G¯ÙDf¬©¶Qu¢mŽŒ•¡sa-ɵáIxþ"¦$\mK©cÛWi4áJ:\¹Ý„+w^^ÄæÔŠ2•F<]U±¢·tø Ìh¿OÙ±ÅÕôM*ŽÇ¢H>?@t+¹ùÁ{‹¿)šï‘ÂÒ~Ã÷-OÓœG|Â5myRhw!’(­yÝÇÌ&©ê<¡õZ  „ÕŽ –Äý£;ßãÉq•£~3K”5Éà4–º4PQ=ñkm`b©,l£“zv õ˜J2æõzm# Å”–¡fµÌVPRg“#(Kt³¼Bã¬o_ Døœn„æm¬åˆµ8W )&±ÌãÂ?n4áÇêÔáGm~-v¿-´LƒäÜAŠç✼TÓMogÙq±â*˜iy‚º'ÌRÀ§å iÕGy‚„/yâ žÄv N"ˆz"œ"l@yåÿ|ºŽ2Ð74pƒø¹%£ÒNmG{;T‡B-ù­nØuôë„R…)GW9ýR´ 3XƒËt¬C†¥¨à²o §Þe36mæï¬Œ1„?Ö`–¥Ð.ø©À]‰­×ñ¾Š¨ º-6¢îiœò:*•wQ¦æK¿0ct¨¶y‘üWìmJÙˆ;b †ÆÌ%Âr†ÕìÂþóx{«kWOÊë¿’©Â‘©¥™GæwÇåX{©"KM³ÅØÔ;fu¨Ø þ‰'錖«éër}¬õ$¬‚°Ø%¥,EÕÍèÚ}ÞÄ| Ô.È™fß"ÔÀl§«P2#ߣwiYΕËq’ìöu6oT½Ï`³cí¡ƒ«¾ö"Q$ï[V«y›§›X‰F¥š ]:wR%&ac6æªç<’` ö±)µÀ®ñž$Z§8Ù[^(Ï/ç'"¶æý±ôfK%îþréMÀºyÆ×],¦þؽ™z¿ˆ…©K ™Ú™ÃÐMš’•{‹%÷É ÷ÞŒ[CmΛ‚¬z— Õn—N²2Óü¾O¿ôgwèˆÊÜÏÏw¿Ä¤÷óéÄ BðÜÙä›ÛXí,¹²^ ú^ÈaÔ–âp|ô'ˆ²¢n›m;‚óòâ†`ùáoh<ùËûùj©:§â!ó[°ÜÙ3¿û³É7‡šç‹ªBöþX^’)Î4çéC]óÈ!ž æÞl<]MÈLÒ7´Q‚³¹jL}r+Û–Ù˹‡Ý§ûIÜÍa’Ýéûà‰!Æ÷Ädû¹7þÔ§ žaÈ ³TcýåŒv£:urÇŧñƼ1^M]aSéZ‹yèõ ßSQ¬úbà‡¿«¹ÔÝ,¥ÄÚÏ•+ BªVŠâüV\ŸùÁÙ0´=Ù¶£’Ewl‰§‰™É_v>Džç«h!…ÃtªšÁúI´évày M¼[o¼ô½«fJ vÃpõૌíˆçáÈÆª3ÅNA˜ycò ý¬NE’‹üÑÃÈx >¹~€¾¸‹ÆçAÀZÍg †îôlðh)xœÒm¶Rwü6ùbb"sf_Èb™äh Ö:Úð‚ Bp®T ×!0Cþa>ño%CY²Æ=æŒç³GïY1ôTm!›3f²¨äMm6n¬¤N1GÍïÏjÔƒàü›<¯9mà0‡Žörb«Ô6‡# 6SÔfªX™¾Ó98³YS¦ÀÂ"É ŠýÁu˜;<áÞxX—š7£X¬—¡Í À_ŸCúx`Ieoºô±FbSj‡+UÍýrÇAæKƒH2¶°L@:«È̯çwѽEEõ§+¸­'òÔ4m# g~¡†Rˆ7û0í‚n“*4ÂKµÊ@[ogMøÒ½Â†Hú· Wc5 rTqB{>ãd«Ïº—䣯GÓž§¦¸ðÑÅ¢¦Þ@»B}š“<à71ÙHJ+¦|KÃ?…p Ï v`+÷3Æh:+ï‹øˆäzƒäa¼nkL:ƒª^s ©Ùßø£×¯µü6y“j‹– ‹¨›úrê¥üf-œHÁ#P©+4¢‡ø‚ÊQYvûz¼`0ý‚bìÁÝ>Êä UÆÖŠîÕ-ø8ÁP”<¯ ̓%ª¼#Ë·:Y}y­oŪǧ ìtfÏ0-•ÀCsÔ3RžyÉæ 6_±‚‡ÖÇq˜T1'>Ÿì“YÍ,èú°çèkËTg;§_ËþüÛÿµ ¹ endstream endobj 926 0 obj <> stream xÚ­koÛ8òûþ £_*±bËrlo‹i‘¶9ä’\âàlXZ¦-¢²¨£äxýïo^”äGºXÜ!FHÎ ‡Ãá<ÕùOgÐéÃß 3Žà×ï$ëÎçYçüë¤3ˆÃa|Ñ™-ÝôÃ)Ì¿ßmw8¶ÝÞp•Åq\E¶ãé,Õ¥–iw: ´[—ûÄÏÝiØcè­Þ2øÞÙ•S@üûì Àà¢33I€Á(œÆ^‡“ˆ„¸^žÑ4Øu£ °ÂÅ$Xè×n4tf (&Êé˜|¬.†Ê5“qÍd‹UŽÿ+†˜ŠÉH|çÝ 5/, rѪT+§U¥KÙS­-K3Ï„`Sê¿öÖb3ÏL"ÒÕP9Ž85Ë×PlÏÖ5¥$M jeJòư5øñ0à1b1`½V?ºr/€Ò¥a\:­_Úe…,€#(ØAjT_Êäxðp;<ÒæÂ,}§¦¬œ™o*Añ#Š…UùJ›|¡—™- ¨*´¦.ìïKÞwÖŒ¸L4ƒ#ÕÙªªDL@êEŠ¥Í2K÷2ùŠA¹­L¢K^TÂ©Þ Fv{1Üÿºb¨òR-é©Ú[Oœ½~ƒyY)'»Ñ²pÔÊ+÷–à7‰¿ôq¦kN§­`mÉrЀ~¨“ʈ—ì GÒc ½%ÂDÿ™d›ÒØœ—däCo{Îy÷@#ü€(ïL¸µ™{S¦v“ UªÃ«78 T"e¦ Üçå%—®;gV)[½j“ M-€â=Lа¨`J¨ž½@Ɔ kçÍ+ë[n²ŒAl ââ:K ÖÉVx5ãp9ˆ[Ñ*žÔGlšÉFÑHÆãʼzH*1±÷%/sµ]’&<ÌÑKžš… È6ENÆ…Õeø©­‰‰÷ŤY!{ ¾¼tyúq§•ûÔÚQ?øØâÏP›*µ®f Â)èÅ™ÖeDrXÁ†•-„“_y¹Ã8ŒŠ8Ùíë€6έãùÚ.ÌrwüÈžVÂÉžš+NMíûÔ¸o·O2ѹv*ãÅ=Ehžß€Yä¥Y$(S-Ï4?!Q}Ä×Z¢£u© ¼ïŒÚÀþU;öK\ ß^D“íö„í¿Þ6v”ˆ‰®À3ýË«|'«ªƒÃÿýÜÍ ŠbL~ rj‹Ú Ívk2Ñÿ\h ‡‚‡žß Ž`Š_Ͼß=Íxqyû,Ðˇ‡ËÛÙóϬ×ïЯúP(³.2ãEÞRà«vµÎÜèŸW_¾ûËÏ×7׳çZûüª×³Û«ÇGYÜ=ˆdbW—³ë/O7—¾z¸¿{¼ Åñu+BÝùošê²qoq ])“•'ÞõÙ»£ÞôVÊG,§ ák?(A¬ÞýÏ^utK•YÌÏþÙ<ã³ó»–“!z‹”^‡Óª*~=?ßn·á*߄֭Î3>µ<ÿžª>±êl—Y)©C-¤z19¨uMNË+OʵÅ~©•XÎJ*‘*«)ca1ÇÅNê© ¶³9ªg¯\*—–\#aõf²úýQ¹N®«ÉaãžÃ‘TIX[òã¡ÉñU²Îœ %Ç¢áè¢]%ޤJ„àDŦâ}ŠA`0N u …yf~PõÁû¥rH¹œ+»¨¬Õ‘¼nd“òö­ò‡®¸€üòéz8ˆÂ±¤kÑ’O|ÿ·üØÈõFÀLìZ—‡V~ùùñîæivu#!åöîd4«[ÜY\dçëð$[áý>ü™Hog鳃:¤N×uöÚê /±_ãœÌáG´rt¢Ü!÷JÉm°üð“;%ïO«á”G÷|‰Ö4ä Q…+Ö™è\Ђۀé’GDè¶ë5ܼäí}ömßóÈZãÇŒx®«`ž·8°X`…3\—¦O•â‘whÀÕ‘¡>’â\"鉇¾[J[©Ÿª ‚¤åjU LYßc áÜS¼ê5ýåÂP—áÀ›áîÕîéMp«bªoO×>nŠ#/UÂ’Ã-/HcØúFPIœ}yQ|>åñFRìŸïÞhŸ©U„#"èïý‹DÐ]+ í8[iìÚ¯މ5”–´D_„¾fÉÛjáq+ ï~ð kD:ƒ—¢âµvLacJî ,Û ”90^Ô'póµÃFºHÜgVùÞ'ú&F€7&™2pö»£¸Éµ ½X<°¡á¤ùx2‚óQ„æP”¥r$dßi|íNâ€÷÷¥Ê@Ò½‰?b¶ä=«}yà¨ø+M=aÓ¿ÈKµîþvs†³ˆj ­ø¿ç?¯Nñ Œ"`‚»CÑf4 £ÉQx‰&,M¼ßâÂûm47Å"ø;eh\B&å w·˜¯`òÄ:éy蘾e¼qkÚæs o!ß³5 B„LxÊ6m‰:†ª$„!»Ãé|ÛÔéôËÒ’ƒ}næÜ”[vgfîÄrÎÒ¸>¯•/„`9 4üEWLÏÆ…3îËeV_Iˆ€æûi†°í #­ ‚=%&ጳ“…wK~ú4år‹¢³‘xÍc,Í8Bš;FÞÆäÑäš”,“-èË`9äEq“Ȇ(ăë‘Jøy@ÄÉËJ«E;—Ä-iëœÑ‹¡žù¼‘ñ+Ž+«ýVŸk$ô;d|ì^ñ8‹{œr®"5™-m‘îηé®ÞËVE¦Õ:;åoѰ^ŒöüÍuqëO‰ \«ö‹xB”ƒÉÀÓþë—ÿñÍ.ï endstream endobj 631 0 obj <> stream xÚå\M9’½ï¯È£êBñûc1h`¦^4vf1èî9}H©T¶1¶Ë¨*£w÷×ï{dHbÙÔÖWVÙƒ9ØŠT%ƒÁ÷‚ &•ÑéIOÑÙÉèŒO?Y“ð'o >ó,¾÷fŠÉáÓO)Aöi*&à³ Cƒ 'c|„`&c¨tÑCð“ñlÒdb€qsÊhÝdr¡'«£…P&k zLv².¡y “ °2¦<Ù˜¡9›Éf›3¬-ÔŒoް+çÉ™„›‹›œsÐ\ð'_ì”´ž\„©IÛ Š1&Wl€&¯¿É6ÿdôäÑ+7yõÉŸùM™| Bk'Ÿ,¾ Ÿô)_nvf ÿ%( H$t\¤P¦PõÒ 7…3“S(0*yŒ_€0£É„Ó°ö°7ÃHjR$ Í!8Bs`s¦J¤Àñç”h.ÀL@6QHìÍuܘРµ&àœ ;ΩМ¦¬i|.S&Îøû”m¦`¦ì4Ù³¯â§9´Ì4*4Ïì§ yÁÍYø@ÊÚMÅz(Cƒâx£ŽS ¸Êm‰à!ÔBÀ³A«ŒÞ3Ì-%S€i]­Š,0Ëð"ø&ͱðIà«Ùò>:G¶¼Ýf ·ÔÅð>´@cŒÄ¯Áÿ,BÀ<È0Ó"3þÁÙ=%Þ(yNºxöl‘",‡“yöl[h戱ô± –¥sä:g<|.Ãå0{0}èOÆr^dNËÞs@o¶°-|þEë#§æ$ôáfeŽháàÈA‚D’`¦#ñ„ƒB"_ Â8z@çìᯙ- ¹ýFÁ>0n¼êމnö0ŠúÚúÀ‘¶H´¥°E&iðƒIÍ ÕM @¿ –LcЮ €»ô8ð牜˜é$pYÈj ³²8êBVœCŒftbD‹ŒHÜ™h1m fš‰ŽÞøûeàŠœ…ˆ#X9z¤ˆù]ˆdL@’aÆÄê”J %j)yr˜ð‹B =§p¼†. Éq„šNŽj5lj8DäðR¨A˜£Jì"þî"›¥Ô|›ÁÓQ¤GbâQÝ/W횆¹REôƒy@‘áîÏŽ4d‡¨…©€¶pXÞ@WÉ¡j@Ü€X5°Ë\#7™£3³7’ŸÛd*ÔÐl ÕEkº:‚-ÄXç4S'‡RlG¤U8”jƒ±læÙ§¡y%ÔYÅ)N¨ŒÃ. Ó˜T–膼" ŠÔ[dZ"§hùŠ`i5C‘™Æ”*&ˆ–ÔfÀÉfL3ÚÓ‘ ó‹UC¡º"DC±T‘ÊŠa95dú> ò„‰Ž|Zm°àSHW1R$Êt‹ðÂÉŽ.-ÆÊàD¯y†}þáë_ÿçÓnýÇ/oÖ¿|ÞÜðê/ï>þcý§Ë«óÝÕkfrýÛúÇצ D“_ÖÿqùëåúÏ«bÎ~øaýón{óùUyz»ÎJæY­è`Æ)xÓo?üðo ö’rôƒ}_1ª¿ììÕåÇ~88‘ž~^¿™“P¾Mª2}G¾Õ\4p•ýÍÀS¯ÊX¾…@MF.÷{«-w®'ê÷Çß®.·¿ìn^¯ÿöçWë_wÿ}³þéÃüf÷cûøSûøiØàGÜœWfÀí‚ÿd½Uþ­SÞ~Ûƒ°ê@é±Zdô{ƒºî:#Ff>½‡nÀv§A¿{ôìw>qðƒÇÚs·cÞå/ëiùèiÙ©ðÉ(Ïõ±Š¡aX…´HgåÐ–äŠ L¬ð”á§÷ŠIÉk«°tY8öìãœ-ªè}œƒ ð3Ź}_û8w«³GMØ»½·›ÒÈ’.—ç˜ÓG;OÌîÞÎn|#›ˆ+}oÏcÈF'&}OØ“CÏÝ®r·õ'œé»°íDzÈ~ì$ìz®t²@€øîp{Ûœ² ¯}=¼lžŸ éVqÿ e…²Ü“CÞϨA¼ŽÊ•/9ž|³;î…ÈŽ–·F>ÌBýjíùV™ýw•;£-VÛE‹œ&î<Á¸®ë±ŸõÝ¿ý„9äõ—õŸÍÁrV0Ýy£ê>‡S¨’q±Žó_Œ;ƇAôC.øþ«hy„§Ã¬Gç&ýÊâ™j–Þkúî:'{ìÒâidl“ÙX±HwÖc‰[73TÑ×E…âéíü¸jÏ©öfð‰Î\1è¬î娤ã½fe_¶íºeM4/q»±?OVëŒé}·«ÒE¶Ã ^†aä_²ô9‘ZîZž )ßlÁó²>¹hñyb×o¸xÙ@½;î A: 3°Úb ¶A«àÀÒé1P?•;è?µ½yçúç{ؽ8æœ`”Ï|Bë‚J—Y%ç¸æî!<±AÜãÝáó\Û¢'¶/:¦Ÿ.ﻆÿÖIë¥óÁ“ ïthÏ–Û‡SãÉÝ>(Â=š³ûÆ#=™ÉìãÑßþ‰ÿVoon>ýûz}qóI½ùøY]^½Yãsýæý§¬‘ QÉǨ|ò“uVñ”÷Îý¡,z’ ÷°Ài«x”aoò®,i† ñûï¿ìøtµûT {{óáý1á­Š…-Á*®AÿÊ€fëõCbÔØ/íwKŒÿ͇Oïßmêð#öF+žB@WLÁ8Œ8ÓayýLè__^Üü>_íÖ°çæòòýúÃüñóü¾3ËUý£ZãCøàµÒšÏ®ëõ·2+ñPCQº>q/X¹VV5 ÖB#GX6Øå''ÛaØÊßdùiu·égዘ‘€§lš<œ"ž#?©·còEe,7}Ì*Óÿ£S<(æSÀÌÏËöU Óºâf6‹ve»ÎBTÅ#B¯œÅ*0rfT>ºG†´Û §ž¨}ûʵD‚ ÊÆ\Ÿr:7WTà>BŽ‹<3¶î¿‰*ðœŒÕ*Õ=.|†€ë ²Ë÷šßÂý"øÎêgý ©Œ§æ^l äãç1Ìzc÷<…š•qÿÏÖ[7²<ÞÂ슜Si¾¹ÏíŽÇBe=ó8•²Öò4-÷£­I*¦´l_HäõÜ@‰Š§žyV‰§I­F@Ó~zíÍÕêyD’©»«<;kÛ’N~ z‚îï¬Ò·±;‚bæÙo¬—€ËÊóèrWÐËD“ÔEî#”ÉaŒŒáLQ%:ÄtËØþðÇ×' Î÷ßM¸}p .jQhýÍ7ˆ=ùZ\Í»°^ˆ5ö>HZÅlŸ×—…äç;¡5Þ»Íãlj;—Ý :±5÷ìåï0"†.eå0v¯3¢/ª9ïU¬¿–‘eáΰHå=tVœâyfvfÇÄvÇ'iţŢÎñ·&XY:„_Ë¥¥[¶/gS=Ô¹ïËy>‚/µ/ÿÕƒ´>*<1tâ€KçK>¯?uœæ›ø¹±ÇŠVûzŽo_0Yø`ÄÒö9 & –4Ç‚ÉNb._0ÌZ!I_ÁrŽ-Ú—;K­”¼Ç¢-Õsí*ð’UÛÓ`ò>‡N^Ö©º£¥>>9Ôçæg|V Rä{9u¶¦›G}}¶C w?Á¸+]~ÇZl“¹-ÆŸ(|Æz¢‚?÷2+ïü éþ ‡ï­Ø2¶;ñ \ú†Å:㕎Ü?ò*E÷¯¸åœß-»‹~ÇÒ,ø+0W'2·›B,ËvƒšP%þ~Uú2Þb©mkgp·mc.ò”«[<ùyÖW1þ®‡NO¼4Tûä,ªõI®ã»æU-  gx«Cáì‘oP¤åE¶ãú¾"VþX :ËÌb¶væY ]|¹óÊß›c€!;ç@Šuî«ÜîËcÍâtà/Ú±h±÷¨&ŸcrŒ7.Iæ¹"ÞõÜgûîz§>_¼W»óÏë«Ýõn¾Ú¾]_š¯®wëùÃyE£KŠ?îtüM[{‹¯_Ò¢íåû/Œ2†Ão\Pž?’µõú>?7ÞÇž´[lü×jûv~ÿawu­0â¯1TáÕåÕ‡ùý_w7o/ϯ×}÷ñÝ/óÍ­<ÇÈ|„ƒôÏ_d»T¯ïódîk—|Jºÿ˧µw7·ž?FPÅŸ\£Æ 3ÜÔëQþع~˜âNO,¾~Þ@ûü×û‚Ðoºîòè Æ’ükjí\¦ÓÿÏdë‚þÖ¯JOìz?¶‹¿¼ûðîæúõJŸ­ŒÖg¿­ÿkþ°«×üý=® ¤Ò$|Yßvós½·¸Ú㊌6TŽªøMqNÚYÈ^d9ˆì!G‘ä4Ô©»ôºã_VÐÚ¥³â÷öå3®Eš\ Û¡¾™úv½¾ùŒïií6÷ömÏø»Éç“È;Èy [ï5ÿç»óë×|›î©ïÒ¨ŸÞÉgÚuÖÆôv]œ• ãœÁŠ‚@[¿÷#uÆR]ìÔá›d84Ž Ax7 !´h\¢êNgõW.nÐ÷ö†¸·4DÖæ(Тq‰q¨{ ݶW âÞ<°÷æ…$Ì •)Œ2Ù“Û;!46¢‘ÏÔ>“5¶äÖºÎ.|Ã7´´>ACh- hÑ ¤<ÔçÏê3£NhÈ2 ò~< ! ´0gùnƒ‘îrV÷%:Ý !ïí yohÈ‚­ÎY°EãR†Ô;¨Nf °ˆq°¿ˆm0¿ë°¾J0¾Ä“à¦3©4&²0T„¡2Œm{W,E†Qγҙ²@º¡<ô8_ï{[Þ(9§,#ÙQMdPÒ["ƒ’ÞhšÔi™ J– ’7'ଊ…N»ß™½°çuXÛeäãÜ­L $#fR •]&RÙe‚ìG¾•á\¹ T™Hvˤ@²[æ8¥Nˤ@ µLÃ(œdªÜªL $¿eR ù-“)Ó2A–2-ä0rH$§ÒåSZ#Ù­Én… H‰Vˆ‘”h…ÅpÙªX˜ñîL”dâ~ê ˺‚|\º UÈ€dÄB¤ª+ÄXªºBŒÓÈO UéU!’Ý Ç,é­©Ñ 1–­ã4â¼ PÍ] *d@Ò[!’Þ  H6ä<¢|†kÏkΤ@²ÛL $»Í¤@ʳ™ Iy6¤\N@[5 5iñÒž£¼çhXÒÍpó¹‹:3)Œ8“)êf‚,UÝLËÈQfDš¹Û\™‰Žä·™H~›IÔi3@¶R§¡-äé3Ê÷M—Dq;›mŠÍ´¦Ü€ÝÊ X4…<â|ƒ„ºé|׸³™¶VÒÛ&Pnœo"åÚBv' Ý¤#5E¢—Õv/GvXÜ1öíe©¾„S5ûö#26˜'›®ŠÀµ±Rn åFÆf¦,#&–Âpƒõi7épi¬ä· ”ü¶!ƒR«mÈ‘ÔjõöQlØ¢RÜvItK%½mÉ ¤·-”RmKޤVÛ’#7Ê[$ÔmçÚ[2(émK¥VÛ’A©Õ¶ÄH’Ù–¹ÃÂáÿøÚªÈ endstream endobj 1241 0 obj <> stream xÚXÁ’¹ ½ç+t´/m’H¢jk`S9ä”Äåƒ=#U¹j7—ÍþÞ#5j²Õûà1$ ð‚ŠIÃ%\bÒ|ÉŠÿ-]¢& õ’$BÀ×’š`J¸h1 ùb&j‚5Uµ^J³ª~©ÍÊõR+KωB¾ÄÀ}$âOÛM"½H“…gJ´Ê°B(QCàÄá!k‰Ý¡&ö–±áFsXê²p{¸ÍÖ¾‚2;ÀwI_AYV€u,¥RŸŠcÌÈ¥ #ϰ¯´È:Vg¼<1‡„%Þ¼0io^j¾¤@/¡Hô‚è!ÑKR)ÐKTH±Åâ>F$‰^¢ÅKJ-¸O©yø‰¼,j›3G/’6[D … ` %ž’JSR"bà5© • ßÐÆÉŒn, ™8˜O¹1±>+³†5þ%(±Q ‘JXiJ8+™J¬*Þ”ˆ»6¼P5*±ª¶DQÉ#‹““ïŠUˆö‚JjJ¸½FÖê¥JŒÌ—â+¬'ج@je \¤Qy: @ Ó L³ðd¦RX‡@J©,(¸‘Êà Lk;¹àLjá:À&ÞÀr¤ç¬Í@´h¹PYiŠ?À(ëVƒ6K…TXD8.¼Å mdQ¤ ¡EÌjcߥVX U“4ìašpûÊ–€¾€ÞÑNvD±ª´êAHÚ1E=jÇ”1i"G E{—AR2“¦ZëE@A­1ƒÜ=mžhÒˆ 3m¤V$(pÍp‚D!´À^KK\à¯0ñÀXJë¨@l˳Š%Z™yàn•è1iõæɨ·6ˆÃ¥Þ«¶Þ2BE[h!p -#˜$‹­ècÄÓb…Ô:MáwítSK<9”Zk×…„u½¿bK²‚ º¢Ó@úñF :–Ú:D€Rqz»¢ãWÂîNCƒ€&êÎ~>sdoCuYfY:e€_lŽ›À /ú€µwV°…#4«<½ÈÔ*:¼yø½û›3<oní’Åê :³VñU…¤pÄ3 ¾òKf×Ãï"6ƒ„«)òä“co?å’yö=Á ±Ït¼œZ·Fйa˜Bnð,í~¹˜P™ B‚mC1Ñʇ•Œ8­y¡?kL$~G/,ÜCd‘^2½°•åŒdùåÓß¿ÿñý~þð­~üðâ¿|úíû럟á>â®þ'÷)wÀÞ§ðå×_ÿ6Ø¿|…ý+ìÿñõkÿÜÎ V~xùFYºüBY»üJÙμ]?~xƒ·+W–nu£\›Üxd ]Ž”ã‰ã×ÇywŒÏXÙC{Ê=´W¥l]6ʹ˙r9ó\àùÛà¹på=¶ 9ßcsʱË)w^ R–´ÍóÍw",½ õ.d=‹ìö·!2RïùÁÜ}%Èù,AÎgDƒ™«ìÎhSz6W2Pz6W2P:®Wb\:®Wb\Î(¿*×Á1(=²+(=²+(×+1®×+1®gœ_ž‡Ò¼’z Ô{ld vίĨvŒ®Ä¨–²Íó™î<”7ŠêEµžE0oaˆŒhú=2àÙ&v`oÙÏÊäáÌvg7Rà=)ðžÎxöF½{#È~Fù-Ãó×Á3(`ÛkVåck|M®[ëk²SîÀÂòé·oð<”&>cå=¶Ê÷Ø^)wÒoIb ¶m]@{Û©qíDðmpîñiðlÏ~8ÚëµÙÞõ7û‘¾<¤{³äŒÝ—ÇÇv3ú9÷eŸþõïÿàå²ñ¹|C¨ÿýë÷ß¿œêcÝÀÑC_Ïôå¡{ò6\oz}²×°¡T×zÆ·Û×'ÿÑ·ø¦ßÕè ÙmC·³í%8íØmaŒsËÄK'o˜öê|3æ«ë\£6ðw®øŒ2$騴6¯»å¤Ì¥n1.,q§oÑJÌ › –e•G¿…ѸoÀä\©% ”¸V7{(-Ç™2 ¾[öûü$šƒ™Ö¼e]˜™Êƒ%Žç⮜±É¾‰ìÊ Œ6[Ò…ãæðxïgy”0‡Z·ÇaÒY7WóÁPªo–Þ©VÓ¼ðŒ§Àf{šEÁy>i+¾p‹^ºÙ£`Ë@ÊÝXdÐëzÛú´- _’í½¡•¾8`{·9q<ê:n–2Tu9&+›îíÂíÝ>wðŒ÷ÙVÊî9¯xv;ó:»ÅÜ8e{82œŠ:Tè©gOKvæž[âÐSëÐ¥Î>£ô¶GÖø’Å­êÂ×Ü~tòÁ¯L½<ê*—ä?Qú³æ¸ÕÔ¥óLˆhÞÒé…tïÒ{'*aªj¼²†kã „ç\‰‘vËéP'Bj´÷DYu²*g§thóõú¾åT{U߯újéútÃ8_A’·:\^ay!ÊÏi,Ût¡Äh½‰.®ßÊp˜TV}A$Íc._˜Y’ÍwÃùR7ßÊj? cû;XòVYÜøÓ}—×wšÇ·:\°÷ú,û¤?qs<µ å'Úlë,iÛïÝe5®rÝ­Mbm¥ÈÙ‡;Ó—fóø§:4–ƒ/¹›±4Ll˜ãÆãO·A‡hjô§‹véŒôÑ^uoãi.ÏÖ–’ãp’ø³åaÏGŸ’2_vvÃRq­ …=+¼îƒœ”áõ e¡T`>œùY‰×èêᮚ„”:¤q¿†ŠÙeOâ²ôg Ÿ›ìå˜ccÝ?èRÜ[PIËÙnÖhÆ4n ¥È˜|6›gŠ*Û¼öáKç®0¾ 5¯Ž÷Aƒ—Âfy¡dVY(“ŽO™ß*‡†˜W<Ì,"Á…ÕüR;ŠÙ–ã·²)]Öþ¬1ŒºEJA¤ƒËºt9s„RÓ¸P*´}¿ðþè-õùg€2Œ•ò£û|¤Ýõç?¡ì¯ºçiek«¼sgÏãÛ vÒ¸é>»YùÁœuhÓu«ûÎ5½ ë8„µI£œM`m^…ƒ]™ç -`¥ÓÃD™Öu~ø‹ÄÞÈ]'-t(§¡éói=(5?É”‚~öf-Ëו¤c¯J²PJ¯•ƒ’?ó W9œØiÍïÌh¥¡E¤¸P*æÐZÊ„Y³¾ÑõsÉ1 endstream endobj 1316 0 obj <> stream xÚ•Zi#·ýž_Áo±?¸—÷ øHŒN°p ‡ƒEÔši[# ZšÝÿú¼bëèj5¹“v¦Å"ëÕÅÇjj”ÔAH¡¤NB{ü6R8G¿µˆ–~¡ý÷5‰¢Èÿ•ǧ„9*H¡µ¤%´¥9ÁhN°ÂÈ<Ç 3êJÂxM#^˜¤„¢V%‘‚Öb‘ÄÜZá$Yç”pdž6qX-¡ÂEZmœð2`˽És¼ð„ ¡ÝgDP4Ç,¹ õ!ŸÉ‹(3–‘ ”0!æå°+F²ÇI‘h¹‚ ‰–+-Ñr¥I.=¥1zð0[LÓ ©‰8²ÿè‰Âb%=¥S¢e‰ôe—4Å)â‡&W)Ð$PÑŸ'Gè3ä­" Ç€j¸aè£"?l¶˜¬µ–ô9,¡iʯ%4MF:Z¦&;ø‰'Lqæy|ôd®ö÷"žä©´‡Ò1º¤>Pþ5ò…ŒÓZDSªm±,GXSnsˆ51&A²FŠUR” 騮ò<ü ²À,M)ϳBKç<щhiB¬sœ¥Òx¢8K”¯Îq–P¯sœ¥ò(Ù¬…ôe ‰¸hµ .Úd-ˆ j.'ÄxªÄE*|é©Þu¶ólÎ*>ç2ŽžRP£€Èy.gË”âGF"®”U }>"©}®0DR‡¼…< ¹Âm/—Ë'o´¼±"æœG苈_²XÉqa|B™&Ò›¨zIm‚ ªg‰¶ª¦eFBJP®˜Œð ˜Œ`…á„™±D£UD€m©"b󩯱@Ã\<d˜f¨>Œ¢§@Óà½1)?Ó½˜bœ£šFžPáy J2‹'§HÛ:ML´30ÅRUà ’  ^–x OJØ\Ýþ[˜@c”ãò<+ð@H–õÊûË•çšÂ¸ç€‘ƱrR´ tŠêÜX⩼K{8z2 ,Ú†è̇,u`/b6ø*%ODæòX^ó8-K!ðc\~ïs `8j„‚‹>æ0#`Af?Á F©!ˆA샕y,Šà²f"GoHŠÂÆž%›QØ!&52K”:?UÎJ-êçi&ò e]Ž ò=1Ÿ¹1ä¸x¢Ò\8+bÊ‘DR’¢½n°Ã“Î6ãÜHä ž, 1g@Éçl!$)Œ1@öå–O)ò7$ùHˉ%¿¥É4K¥&óÉb¨tq††|Ìù<ò]æMd(‰’¶ iSÑsb×\÷(¹Lúy®Î»˜”å íèœ4‰F}æ|RŽ3‘”å3µšLø)åG:·”Î2Ÿù´ùìÊÊ2qƒÉþC®HñÓ›þëßȪ âÝ=o·ÿýÃ\â’o€¶,D)5¨ƒe!*®ÁÈYˆ‘e@Ú“‰O±Ñ@ ˸ÄJ}•0;|ˆ â·,´24“•6–иÄH3Õé˜)ÞÅ=;g¦ñ4v•ÙJkb¯ “…ÐØ $1C)¾$A—$¡ f–×€uÎË’{Ý2ðU£/¶ƒSK˸W`ÿIr@±ÅeÌeðdc¯ñ—L§ªÁô³P±•֦Ɣ„8£k ÁD?ÕĉÐ#m+»‹ ùî¢`*L¡1—:rªT3‰UfªS¥â2¾M¢nÔ%¤Î”Ê%Î<@È‚½ Ù2ðf#¯ÂTò`&ÁÖ\ÀV.Oï™1øØ8†ŠçKp¶”$¥}7˜ө‰—]îl ÊùÒvuE¨à8MiÛ¨‹W¡¨p&q™Q¡?‡‰Nc”—±!š·Æ]eEÊátÆÑ×­ÎO')› BœÜM¸ºát1hz^´Þ„h¢c®Â%QûQBs¼tãTa:…FºBrš}]Aàìo\,,CGÚ8SâÝ®‰;ùîQq’£™o“š ö°tpI;93fB¼õNN†Ùñ5;¤¸ï ¡ã^÷‹)RÒLâÑ „‚ÌF7 *jP¼¶H¾Ä-3’˜9È—9Ÿ&'‘+VýLâlœèœ º$=5ŠU?“€øí Btî“ÚvÅÚö!U(ž ÑH7újgªu^ºXæÝI+‡IoV6:¬)$ð´©Oú*¿Ñ¬¦M¤›´Ÿù5¶)ÍåàðIÜÊaù井3ý^ƪý r¾^™ª<\º–(ô¦(ññuýÉ4ëªêÁ×_¿ù¾;tSËøí[û¹?n»/~|'ž†ýݶ{üòÍ7ýû›ö?ïß|ÿ…úòíÛ7ïÚ¡ÛÇ+Bø[÷é8^QÌÔüõ/%=zIÏ»¡û0^zLµê¹Öo‡¾ÛˆîSûø´ífz-Ó;®½h²sMßíŸúm¿»ŸiqKZÎÖ¦ó6týî·[¾¦ñÆ® A:ñÔ®~kïç^Òöç~8¯ýØ®½ùnÿ ¤¯L1Æ7¹úËî8ì×Ï«c¿ßÍà$ƒ“ N—à" “¿ ÓÝÐ/â¡k×Ý0L4n¡ž»¡ß_=í{,_P²†`‚_b·‚ZUSëJáÜßýÚ­æºÖÓü¶×G“Êù;—#Û?ã›îþ~ûô~…J?vÅ//±ãÀ™½—MS†»ÉqÒΡ;f÷»ö±‘Úá¿ß‰_¾Xa ßw¿|y¥9sH»yŽ,ÛÏV– €3UüÑÙþC'6Ï»Lˆ‹¦¸š)Œ¬ª™²î‡Ñ 03žŽýcÿ{› À¤n4e³m眡|ÅËŽS«—Li×ë÷Ãþãá‘õZìº"÷Ÿ)‚PÃV Û”°Wûí #Ï»WÀÇ<ãkKY€£Õ‚€|±R ›ñ“u%l8ZűßÖàyY_sýn·>,V ù}vYÏuWƒv :ÔOžÚáÐlQ5[ºEþ<ì‡# \á_™­kf0u‹<ºî¶“#Ÿ:!l†ýcĵ©3"u®~=CNàç#äøµ®Â1&u‹LºÚ?½L›'|œ!RŽ·¢®5Ž©[$Rtÿ‡iß–?¿»Ö58F£.¢Þ±¦ñøz¬ký­çÞ8÷£ôVŒ×<ñ¸_÷›ú4ìŸ1ÚÝœšuÍì­çt/wêšµ*µÍüÅÅ-2öým;;tØ]݇®ÖÅjÞ88F^•xßzz]»ªÛ%Ì“¯žqž×5 .íêÕ€W7ªú®f#;oJFìž'Ls±ÃwÝ@|GÂ9ðªÌ2ím øÊ2 À'Æ™c¯k،ݼ+aóõ‚]èLuWƒd„æ} ’w¦ÈrCª75TFf>Ô=¾<-9JÃó›0Yƒdæc r{·¸ÝDbs:ÇU5\ÖëùTÃ}^Â}~z*áê.k났%v!ħÄ.EÙÔP{UC½‰ò ³h[Œ¶‚®A? +±v5hFVÁÔóúš±ÀÙÿÇ †ñ5ƒ‰…*‰í~¯PØ¥OœX6§4j–0J EJc¯:¬þ_Ù³šX³‚±\ð5+.ï8óâx­!©fHñ¾ï„Véc4»½õìê=°Û?Š} c£P»þËWÒìþ¼Ïg@ÍÝæ§yà@‹´·žkÒéÓxÉð"z¼«,œ)fµ„q-#¼(‹ˆ—gÄóÝBt]e|U¥3žÄóÔ×ãÙU`o½û k¯îºvX=TŠÉ´Ób ¬)ŽêUWɼS·_͵«ßî‡.µüœŽŒ¬bùb®ï‹S‡U‹WýM»:îçßYµ„v$£§X¼˜;üúkífª¯kðŒ—b‘—.®3f¬¡š*ë¾b±ûº8=g°­³,._Ç‘îÉkäˆu~Z·ÇvŽèjˆŒ†â" =ïæ˜§‘*ª¯¡Æâ—dÐ[Û•›é®Œì žÑøó®,2<'Þ$_¿+ùšX;•tíÎMʱ¼5!|ž;jÓØÉ…ÄÚ©djwÆEès©.¢·5tFGi™ŽŽë÷wù»Êӵϫ#ÁíÖí°¥÷Ǿ݊߉J¬Uò¥}ÄO¥´üÅEOur¹iÝ‚!¯,#>öLJñï6†þqÈ7Âø}^õØö7»¿6'¾›ù«û".ØÐïÄ(nXÄ~5ÿó¹xNô§²òL&ÿ3iF endstream endobj 1402 0 obj <> stream xÚ¥\]Û8²}¿¿‚o;lÐ"%R° ›ù¸ƒM2A2Á½‹ì W–énݸ-C¶;Éüú[E–l•D²ìK"ë£N±ÈsªHQ-‹,™E&…Ìk<È…*K<(D! h¡uŽF˜²ÀƒR”µÄƒJÔÒG³\ÑkR»#¸CUx›TÞ €e# >fL…Gp¡¬ÝWx³,…Ê ‚ÊJ(Y!†¬…Ê3tMeB ŸUR(­ÝUðÛ|E&ŠZa4 )t¦Ý9%´,šZÕølQ]¸¨ØZ)àªq>ƒº4èsQ ]Õî¨&ÃÀ:FjŒ)˜7ªtVrarSpÍhg‚hŒF\èÚ‰xG³}•<åŠd®1WÖ§f›vïx‘"åHÎÑ1GúÕÿÝ>wÎÚöØÁ\;Ù9°N ØÄ€‡þS(pš‚05)PÍ@Ë(öq”º>ØÞ2mt•‚v}º„v§ƒÀU ¸dÀu ¸íƒ# NŸv‘X×)ÜjŠ+³n Ö„› w“Bgª#e =nBG|•À–Lg G°O»Õn};4_æ¢÷Ø ]³Ú‚ÍéÐíîÜÙŸvk»ÞÙâÚ”+‹†¿#m!¿ï×0®@2ÀêÌhaÑèÏÝpp6}W¾l—ݼŽâ™,.ØÊ0áçaÊm·ƒ6wýà#àòxùz½‡æ?ˆOÝñ^ï­ï{¶ïᜟÂNA€gx†‡Øí8C¼:nBNŒ½Á4O5¼‰¤ÂQÞÃ\4Y ˜éž,cÀߢòF¦€™êÉ*üm‚kT šéž¬SÐ_+¸&O3áSY ø›…Ï)t&|J¦Ð¿AøŒN`/Ûúkˆ·1ÑÑë‰èŒd!Ññ E§Šjët”ÞÉþÇn·&ݱõ¾kï›Ýý×÷c ðú¼õ,Óý3Z‘J2´y¬C8UgŒ26-Ùv§Ô×(œ]Aåˆ wç4 ÝXèIr ™2)VÝ.ê\k†/1š”LÑTI.ýþ8M-¯~ ä–ÕÐìÚûgÍný¬=Er‹Y¥|a"§ªx¦é#‰»\íàÄIÆ´)o8‚º÷ÐícIæ<±ÀXEffÂgò—g1üoÊ56Ì”/—1`üÇ Þ!7 Èœ•8¹ŠA¢<Æ´6„Zf)ÔEÓ^uŸíú<’`„ßÁÈyÀÊ1"µÆL¥–…¤6çõ]ÑÚY•ë»öÞ¶o?~$ºŸbcaººê¶ÝñËõ â°_w8ÚæÎ–<Í/‘ž¯ýƒáH{K9moÎR ýÛkî2™üÝͺŸ¿ùU¼ N‹hâåš3Ð *•”Ðx:σb?Øf}û°?ŒÃ«YŸEnÝâÕ›wbÓÍqî"Ïç9“²<(eŸ†îh/xîçWšà8²™våu´µÛ}¢±/Þ¼üéqv L9ÀÄ«Èâí=7ÿ ª” ¬Ç b&¢ðËË7ÿˆÀ× ø‚IZ¡â¸à‡cp I9°hñ›©al+Û b&®,á÷ &pfâ+*Šh4¹ß  “#&‡ms„éñ§~€{šv‘'Ö!Ø1’¬J+LÌ ¯ýÚn'à ʡ³Vø«lºMùÀCZ&}psÁ]Œx°IyÀ$­¨b¸•frœaG¸ÖÏ0«,…Ét¬¨c˜«S·Ùý>©ÛA5¶k­Ø ýCÜ™r„é™ÎbŽìûÃÑ—ÈÎËÏ(ªJ¡2 Ó2†º¬ ~üyíÀ¯òþ²c‚F=Âø¶öàÖ^5Ç{—;߯…ˆ¬¦"R°ªAG&¤£ˆŒjÎFŸÊ)LõwÇ[ˆ÷TMù’>ê©»Í- Eµâ™\³¹©.¢iäŒë87ƒõ#mlºí¢Lq즀ZÇóHºáÇ>Ž_¦ð™øi|7Î=þráïê¨Rþ0!Ôe´?Îî¸þˆy“î˜:呉ïÊÀ¤z¨I9ÂDR×ñ‚)ÔÔ‘éÌôšnY¥œ`i²x}ÝMKNæBº/Ú:J#åv"©X'З­+­³é+«­ŠU[šM' Ê:&”¼b2 ¡p™Ž&î T»ø÷ˆ³Èf_Ý\ß÷Ãb,ðJa ó2ß3š”NlEš=}K‚Û¤¦ÍÎóÊY³—áýÑ͌ݼ2VÜæ¬¸5 —·El^É׬L±œÛ¶ï|é4îy¹a˜Ìš Ì®6·ösÅt ÛøÅ·ã»iZHöÝŸtþæ9.Oø†ûT±Ñ*5mÿ°?QE€ã!¼‘9LºLiõiE«]_Ùìûæ VÖî=6wH§b2VF_¶®6í~¶ råÉÈÚ¤œaªVÊØ"üÅ¿ôþ®” WJ6›-£¯bW÷¨ê<0—~‹v€TãóK`°T)Ø^2O½ù_-ßàÂ$œµŸ1ÕÍ}šûQ§ü`a™|[±Š¾­¸Ú•&å û2Xnp@*oŒ<¦÷OÍ@“Âh_¬RÀL®Ê°\-W †W ·)dVÿ•Áú @4<ö¿ÿ?A þò\Hr¡ž®S€‹ÆVbi¥V,±5ïp`½rÌ#÷y3ƒºl›í-l8â¹4ã‰Þ+¤+èšÓÜEž¿K&{U–DkÇyƈF#: Ød!À1ÄL誠ÐGÌ¥µçSéöÛ®…{¿ˆÃ޶ݦ³øvôÓÜ ™p¢bW©´ç <á„ÍÜ•òƒÉ\•G 8ˆÃÑŽœ_ô²{@V ¼<ÎSÀLת ®¹}t`÷ž;[¤`óØÖIQš±ª‘ÆѬ*"K“3–±ê§ ê§+^ÿ´·nç­.úS¢ñoØüþ»~÷ÌO»ÇGó@ðt_1’We ¾í톣_^ñáµ =´ÚEÚ…2äÂØæ?ªã=푊ÕÓ>ë‘¥Ò=_?ââÝ:õ‚¨Î˜âj¬¯)ägkÖÕÂ÷n ®m¶[LdcæAà »bÚV/´íïü­y³½ƒšíxÿ0·º Y%ßù±z!]¿ƒ×Û í=È•]8ܦL35ª\}qÜs‡ÓŠ–[çÖ×)ëLrê"ä8Feß÷ó…ÓÆ¦ì²º¨^ðú­mýίbbw^Ûµ›fñ¯9šz:`©ÿhÀÖ:¢]ËÒuxÛ[ÀuhÝ|GýÊ&¯xʬ™`ÖUÌ¿ý{\ŽoZ\'vpãš¼¯9˜ ñesÅºŽ¶Êÿæxæío¦/·? ¼¥[Aù2×’UžrbÚ:ËbNàf…»f?«Êì¶qz«Npu\¤€k,cÀ»~m'ï(òÍKWk?£Ú¤u/‚æ.è¸ šmûÇ/¦".ìºÖy2n ÉÀ•6œv»“Ÿzqš;cRÎHæLsæÞž†ËÊ8à?vëÉÐKÝ«/ïëÇ®;Q¦œP̉"æDÛìnýî¨Ù\ mS0?Á©çº1’½WUÊœ¹£cîxÄ[‡Hþôýa²]ºgâÕÜ…:åBÁ\ˆJ”'åù-áå§ cïÐ ¦¹MÊÞ]©XV¬p¨§S5ò>°gâ±hâÔ,£mÆ·t‡ó2Úd¯ž£ÙSòŒ”IêÈ;s.L¬XÓ2*ÆX]…i”ˆ©@EÊñ–UZrèhEÙe=~`Yp8 ¾Â×q @ãÏÄQFÅqm·øÁ>ôn2}öà¼_$æC™òI£ŠJc»…aáú€¹eùÄ•ÃÓ¾T)_êÔÌ*6ÛéÛÈ1¦4}{–³j>Ùp2ß}ø‰I}S±Õ„š1À\5©goÕtä#ÜQnw‹ ånß\è†~÷ÖçÑa3r;aÐáoípè–3³mÕÖðEÐå9N¡ø²otø·;èÜ@·9試­S<¦ñ !›é‹v¿Ö/ñ ³a6ä_¶»ªo1’m ]3ô`±õøŸÁoRðLן( Ý[€ñøv‡%õͺ;øÒš@Éö:Ka3Q à°¡šÿ8Žf8ÑÚýñ)\™ÂeBþ¡ßÛ€¾c3A½ö_Ü*CZ¥ Ymþ¡ÝÂÜeŠÝ﯅ÎÐì“þ$ÁÃøÉ%ôï~Û|þÔÌZš;ëw^žç6ö³mCŸ¬‹”¬¶ Ðv`Ÿlû»+—ó·sH‚dR–Ѧ³‘)Ër]F^³Ú!ù¶ç@¼1)o˜Ä…wî?¸ý¾³­¿HAUWðóã°L2˃×~-`•dš–—1Ÿx ªNA1ý —¶oOnøÒÞãçÏÆ_߯›4“¯ð7 ½íºãå{Bí®ÍAW)ÐE ç©/Zü4Óâ‡}ÙCΟWÊ zà“¢Ck·ÛfgqŠ™(wÚš*Vm©È§5¼Üa ÄzùÕÅý§Ý¶w;Ñ\) ¢åAÝî·fXÁPžG——쫽üªáýnß´¿Æ¾ Ù§Þ+˜ö-¿#xÑï6ÝÝiñ†Éb“‚`ZWKˆ‡}·MØ,Àäkùà Ôë'ìË”}¦VË~õÂü‚J!0yZ~zð~×]…‘§0R~;ÊÂúgÄ ¿˜>ß&³n§ì¡Cì)Ø«Ç2Ââî¹ åøÙ}ˆdýÚkyJe_ èåNúŸQÆãÆLÈØ,V-? xýüÕO¸¿WüÝÛža¾xaË„yÍ8¾ÜXùö·ÿyù€ÄV)»,¾zÉæß^¾õ:jºN™f,^nÒûßQ³MÊ,ãîrïýÛç¯ù)jy•²ÌX»ÜUÿ÷ßÞ¿þ1j¹MYfl]îÿéõÏþÄðX§X ±Ü÷þνÃpå÷e‡Âæ´ ¶Ä¦€XÁ°Ü×þÓç÷‰¸o¬ñ+Éå®m»I™g]îáÆ—tÛOÃ"Uo²”Ý…£q–³–‚­p¶À"ULµxF6þìö´žGfÃß0jš5[t¤XÛ[+Yôé&™&o #ª ¤ÛËŠWxðoŠ”yFX³|„ ¹QË:e™v¹?û÷Ûö¯ãÇãus?ú» „·F&Èxl–<óí—Oý‚½›2e–±w¹ß{BªË··KfmªÆÂÙ³© 6ÓÊÇ!2Ò º*wól»ÜHþîˆ ŽÍ¶ßáßEºAn¿s‰hî ÿK\„³d¹9üù«çæx`»¨õr5d@°qó¦Ú)ò¬äžåËIÈ®{·Œû:e’1u¹ËùÏm·šÛ³){ùr¨A‡‹3ïúÍñ<%^õëÓÖÄûZ¿ú/ŸçlZV²:¯,®YÖl[½^nšþåõ{AtoN«m׊—]kw‡ 6‰Á2ãŸ.LáËé[©ü­oíªÜ‚à­ýþeoâÎNâ:Î>Ai@'?8¶ý1œþìÏÏûwgdà|ÿS“½KÿèÖ‡îá_zâ£üëრ|K…K |e-ü,Vø¹´ðëÈÂ/è ¿°*ü§ðKŽÂ/ÿ ¿'üJ˜ð«SÂ/ ¿X#üŠðËÂ/5?ù~¶.|¢~j ü¼OøÙ™ð“(ág:ÂOF„Ÿ6/-Âgç?x©¤ ¹Êx}QýÇÍóÝ®‡Üæþ ª|•)|I(|ý&|•%| $|­"|i!|i ¼ ¯—§>áó”ðÙCxµ^…×RáÇ¿ðTx OwáY*<“„¡Âï€~ëºð£@øQ$|;…oð[ˆ…ßÒ+ü&\á7` ¿Tø} Â/UÿVGø pÂo6~W ð›ø„ßW'ü®8áßi ¿ScÖ´GêŠÞðÛ¸¦½1jñéw៺¦ÿÇ¡^Ðÿšþ7ô? üŒF¾ß ¤çþ•kúŸìI²'Éž${’ìD™DT’Ä%Id’Ä&It’Ä'I„’Ä(I”’Ä)I¤’Ä*I´’Ä+IÄ’Ä,IÔ’Ä-Iä’Ä.Iô’Ä/I“Ä0I“žcÌUÊ\ÛgÒ³sÚiÓ”2×­<¬[m=vîDÀˆè² ij¦Ï_%Vc%QVg%‘Vk%ÑVo%Ws%QWw%‘W{%ÑW%Xƒ%QX‡%‘X‹%ÑX%Y“%QY—%‘Y›%ÑYŸ%ZV£ò“=â´$RKÏêyÇÓÝPdzŽ÷z0íx}f+É‚$]59SyhLD”‰ˆÝŠØ­ˆÝŠØ­ˆÝŠØ­ˆÝŠØ­ˆÝJŽ™ì»±[»7EìVÄnEìVc¢3å9U’½1YŽirÌ“c¢3%±Z«±ZåcÎ%;ÄjE¬VÄjE¬VžÕ³ÎR4ɼ¢³”—ƒigs¥Š$Ac@ÎPÞU”xe^EŒTÄHEŒTÄHEŒTÄH¥Ç’‚ì#1R#1R#1R#1R#•k²GŒTÄHEŒTÄHEŒTÄHEŒTÄHEŒTåXô=b¤"F*b¤"F*ÏÈyçTÅÕã©<íœò$´96vŸ<‹¨"QPÕXÈQ“H‰‚ Š‚JˆB5kÊR&“¾‹É<“ךÌ/É`f¢¸ÞD²–ŽT‘¢* hîÅ ­ü?±]Ôg endstream endobj 1590 0 obj <> stream xÚZË®·Ýû+úÄG=HÀ0x™!d'd$BøÊ‹ü½O‘왾l–BÍB^²û°êÔƒE²#k9¹æ£ä#>ÐÊ1QźӑÈ:¤¡ƒ¬ õÈ59ÑAšm€¦†¤‡DÁo*ÖQñÈ9Jx=×£ô9ŠáQ:ªØ/&x*FC­öþ‹Ò$‰GLb0mz&4 Æ$ ‹b²âÉ(1I  ² U{Èt2= N‹5Ð]ì5(k ö¯EÑÅG lr¤-s‰h˜èH‰‹µÂ‘2tÉ]Û ¢¥Öe‚†qÈÚÆäH’Û‹õHlóh‰Ð!•ù¼TŠu´€W<!ª*ºðJ 4ŒÐñþåX ݺ0#º 6ú‚J9¶±lô&tYC’u%£Ðƒͺ˜¬Ø›MóxP¦œ‰lÔUDá½ ÅÄØb¸¥hµð=R 5Û®,ÆbÞ ™ùÐ&âFѲ÷0V ÃÀZƒ5€Y<@¢È8Eò)^Ïx¥˜g1f* ^ö‘²,S´´q„;[ ³[Œþbþbé Hs@^O1ÌP —§¥:!gQmjhðð³Ì)‹56_Ik„ª– 9lB¨Z¼Â‚µæzÞ©¹!ÈUÞ|X Ö–0ŒTx—9–”U{É\¸J3 ÒSUn`,ÍÖ Ø .ÍRs¢Ëœ4˜´æh¥&·¥Ñˆè6C¢@#=†dÔ³­¥NÐóN Ž€8=¤%aBj4I‚ÿ;¢4pË!AŠ9 ½­l-8 ˆ‚N&{(MõÖY[Yz¶9ÍUÑŠ CŒ † Ñ"Bl퉴ŠY5füÝ,‰¤áp£Ør82= -Ïa™°V[4,–<£R{¢cãÔrq,p d´Š‰Q›_ÚjB k™úMà[îÆRS }UC .£ð6¬NæÛ–Â¥öŽuZ¢P3[B9~þùÃßþ÷ßÏ~ûÇ¿?¿}øõë_¾a^üùûgkYÇÇýÏ¿Þ>Es]üu4ýFƒÎ†-ÛÿþË/?}ÊÓÚ?üãç·¯üþÏÏo¶:4¨ÇtÏI ‘üúõË7t¼}2g5€ùòåë··^  à$ïCÒ)ßJåty3>5¶ÃÔ³¨~¾} ¸Ð,€> J¾œâЍ”·ASš‰â%QIö!ù{De‡¨(ƒ¨:4£‹¶eôÕ•¶Ùw ™DË7·Ð¡-ÆrŸ$Óø–ËK_ÌeR'-KŠi_ ¯Pœth”Æo]û$‘+HÉ„îCÈ‚Ã>D}…4Ð04•ï¡ø9­gŠG$<ìõt¡› Vø¿×ÄÁ²Á{™ËŠÿ'=;-LŽÕ`N\Ö’¶!$:¼A{^2Ñ0‚FFÆÇ㥸‚äY]Ch܆Ðà@Ð>D~…iZFšVÇ=U]AæõBPÂ>„g%oC”ô :r‡ŽªÄ—rȈه×>ìõt¡›Ÿæå¢ðs-eÖVã6XÖP;X-g•ö!·]‘/ÜÊÑŽ%ÚoMO-GÎõ[iMÁ÷°2‹Xg­ëJk y’ÂS^êŠÝäÓ}0™äëðRÚ‹¿vtÓ×¾GÑ%.ÆY°ê@äm§v¦(ûü‚‡Qg¹Mõ_w)Œid½RJÛ)>ýfTÉ3˜ìƒñì7ùÇý†úÖ¤ÏõßïtLn”3é•шgbŒßÍÏÄHy·ã,g-öH±ál°c ßœ2Óç˜3§mˆ7«³xe|Ôò”ƒ#€[u[]p¼ÚÝâ, Ö ¹[š;Äî–æ= cÓF}“ÖÎmׂ¸‹Qœ3©³¥!wK³€XW4Äq‚_¢clihliè¹¥ùD<¨âeÊð·±Î¢Í)#K Ɩ묄}ðyíÙîF¥ämHI¯PɃÊQÿ“ìVvÒW‰3¥Å3¥yÚú!éÝMĵEʳnN “ºQ6óÏX¢:=}3Õ.)–¨›ÓTy“F‚÷!œ¦eB7½ä :<Áåìe¨¸‘ßà‹ %qÓf€sr d‚ˆºQ^¡£Ç@»Šï¿úbNw„#özHÚ•–NJ>×S‰ÍtsÒúpRZ:©¿¸ƒÏNJá ¾L?þæàÎsú¡¸— òe·Í4¢†½Èq_v×SJ³`ÙÐ}ˆuaÀþâ±Íïè?óÈ×Î¥û;šÓŠ8Ñìøw'šýÿQ^¡CF4BŸBŸýBŸ¦›BŸýBÿADÙ‡ÐWè…>BŸU6O¸¦ä–ÏÍýt&7¢—N¸Æ¶õQa>ÒòC…;]þv„¦ú–Kp h"oÖ€$WÆÇêZœ *~N™ó¥³Ùàö!œR¸æmˆº{ñކ2ÒQµk}žþŽo5ŽqßG¦|ï^ï’Kù²z ‚8{ñÏéeºI íCdB÷!vO]ÞчéÇÚ;ü§»Åð•‘ùŽ‘”Ž‘7f ú5±LÕèé{ .?E¿F¾C®×3ñkä;D}…ÀY#™âÔÈâ×È2•câÔÈâ×ÈwÇ«ýùQ^¡cÔÈ®}#üRæâ3aÉyG)g)'ë‚Wü²[¦Ý¼8e·øe÷bóÛ×aŠAϨ™Ex÷‹vÑY€u!+~!{ƒp Yñ Ù;Äîw*ïiAÃÈ0Ï‚ˆËõÁ?—y}(·õaù]Šøuê ²:Ye‚_!j”º2Ç¥>?Ö°*5¸Q Ó驆¹ ÒåÅ¢Þ‡¼Ê׋ « Põ¿—¹ƒÎ ºY¸¾£²žâäñ+¯e&9o/å,®äÌUÎ'ˆêØ£SÖUçÃõ?ì¹C°Q÷!vsÏc¦è8æ×¸ÎPê×ì:ݬéóÞ?7>ó endstream endobj 1721 0 obj <> stream xÚX XS×¶>iðä8‡z4´šCÕVmqž[Çõ:OàŒÈ$3$  „’¬„@ƒÊ¤8T@QÁyª×Z¯-½¶Ú~VªÖjß­ÚÁu¸›ï~o‡ ·¼çýÞƒ/‡ä¬µþÿkíGÂxx0‰¤×"ÿy –¾?{áòå³üGûº^?‡Xþù}kYñ-F ¾&*¤b_ # éíºvéI¯Ì£^®ë{ôÂíÃxH$Ü6Õ×w¬¯ï˜Ù1±Éñá¡aJïaAýGOž³YÄ,f–0K™åÌ f%³ŠYÍø3ÌfôkŒ„ñ Á¶0 ’é’Û¯M­I:MZã!xX<îu™ß¥„}“ý˜=ÈÞ“)e7¸w8[׉] ݺu‹ëö¤ûšî×zLï±ÿõ¾¯?ðœãiñlêùqÏŠžz­íµ·÷ìÞu}º÷ ìóà7‰O\Ù,qâ ):p%ſtÚÚPHH› ¡¡µà<ÅFb)ûçòRÉñC©˜Ø:“Ï-3عòäÒE4dÄ´äÁ¿¼äYj0ŽSíLªTìÇnK>Go†f±ðòÉR Fã@)b«/¿ ömT$A¶1==y{pÈ0#—§‹­Ba?ÔØöåqm…Óeia´×kXÇ¢……€F˜Ëº">sŸHð9zK¯Ýå32À)\¦,´ ýfë…5‚S%°+1_g€$PA‚I™À¢{Ö(.ò:îüY¸Ï¡çXdÈPE,ӯݢխMö;µ@ž›iɶC>äØ-ÎÒÕG?îÖ's ° Øoñ0Õ#,ý #îKPġҟÅ3|^º rÀ9V›ýôW_B!pŸåo]#@*¬ Nˆ‰7F5¦m&ƒQg€,ØÎ%Ëâ̦=ŠcìË>ðÓÍó"`¦Ýïª6ßdÎ Lk2‚)ý/ çÒZ¦`œñ·‡è¥€k¯Œ®øîXÕ5¸Èá82¸p>è7mÓx‡ùl;83y̺ñÚŒƒŸHî`?|“R€áâ<ú³æŠª=P¹V ؈íYA¹,ÛPaªRì¡|UV®.= Ü5øpúðá !>κmÈ5äê Œú¬ÌT¥2Œ )óap0Ž¿÷N@ùŠ‘ŠxHÈNÐv°¯‡Ý—œÀA8›JAœC¥•`+ŒsÄRò8R¤~ì NL¾¦]õ'Î\ʽ·¸‹€‹ÈjÅ ŠŒ]j{`./>²ïëÏók`'ì1T¦Ùõ£ 8'8‹âÓvŸ¦yÐr§òë/¿…9ƃßÁ³5Ž2ܯEœW*£[^ÝMuÆe“ Ô›HhÛS¹>*SÏÅî†"E-»@Ñ‘Ã(•ã~¶ú}g˜=© ¼Î±E»¡J*}!ׯˆïòÅÇ ëòj93kKcžò1©–“(Ö•±3›1´Eò#¾gQ¢Ð:ŸMׄm;ä_ÅþÿRˆóÀ·‰P’û°ììŠýH8*ÈHrŠÇPì*;Œœa$aIˆG>ã1ûÈjPÂñÖ­¥—g<O%Wp˜´µ/æótÖlEDÏ'oSrç ƒïáðsôÏ$á>4†U©rõ®¦±‚Íf¶–R¤f«ÉšiYR¾¨h:½Ã@z“îDKŒøa1[¸ g_ϳíœgk ´ˆ»\à†à8äUàv°h¸‹ï¢¿·Óþkù—3~"=œóiäim¿óâ.ì+ÃÈ|âC’›Ô9\•;šXd–l8N¤•K#uò›*¡šþVÂÎì‹×åŽÊs8À¾‡3·¹§ê‹»«œÈÆC¼1es»Ê_$¡á…ÖA|â‘(×ððyuòr³ ÷¶í/ Ú¥àõSçȱlpFZ˜ÐVn’y¶.£*„ÛXäj¢¡¸Ã5!´XÆãG?úœöÕûïX^¹ØC¼ÈcÿÂÅsý4 È›ñÄ"Ö´¡UîÎ,¥AÅ$üŠ¿Zü¸°‡$ 6(ˆ®sÌ¦Ž˜%(•á$r¤(¡ÊÁë2[ºö mðUØO†\ÙúyKRW’žté+±âW:qzÓÂ{K±B\È«l +è6w÷nNµâœJ;¹¶Dm6Y©¼lKqñòœ<ºéZ ÏdŽ/œS³ÄæÜ2*‘,`Ρõ»’N¯n̸•|!­\_žäÈ(K„`näxÃVÅD˜Up<Ýi„lºë µzœÜHw ºO&þj3^O#À[[§€ `ßk¦CúÍ~¿©“ŸŒ€«^,]Hgùa©LÁ|øDÀiê#9 \qª pY"L†€õÚ ÎâÏ:÷Wœî)Œš1F!âwkŠh*µæÞ¹%9ä¹þÙ'Œ…œÅèÈPdSed¤¨×mž Ü`xúÙw¶ïŸ × j{m”S“CwOää›­9yŽ =u°)ykË£sé¸î3—Ì&SZfàûB|j¾^½·˜ÊÄÑ MŠ+ÑK*fÿ\».I’lCC€=’ÚdÅšõ@Vâá(48Np!EÕwßðTqÚè¤øíJc:pïÂÛ7ázû *£<‘&Ì£ GžÅÍt9yÜ‚R©8·ò»ÍÇ‘_ÜB†“qÓF“dÒã©8Z¨ƒ‹¶Ï–Ø-à»aŸ)/û€É¬šŒ%þ‹u@º@ú}Ãgœù,o¹RzóøŠ—Z¦Óíè>”‰’fœÝ,i¡À0FìÇ7±/O+þ(a÷À‘kŠO T[ºÍžÙîÞ ÁQ"œA¥ÉnÎM¤N–›Az¤÷„©²D×ᢚvùѽàÊqv67cW”œhÆÅÍ×x·<“⺇|(uñ©ÎlkJ1ì»9ÇœÛwÊ€;Šc' pIU£-Ø5P¯±íF py¶\»V}¥Ñ‘] 9É´‹Òƒ•묶n.ŒBï *¨Û[@Ûr·–Ū³V'È,^}5úbÜuS#p—q9PŸëKyKÈÆnü\CÝùó–Ã_|a ^±Â°e®pŽ$ñßM õ#,Dyà‚ºD¹ëÑ.ŒO©0¦¹iÀ[ü¯ëßQ …õ¥Æp&j_Ýî!'ûáRý™&‡Ò_Aöº;­ã-OÌ£áÇ—>Á´©¼¤ÏZðí–½,‘vHq†m‚²FúX+Ô“ºN­FþÕ™yW$× r…ù}ùâíÏ]¨®·Cšî~H[_Àš+¶†ÎÛþóK lƒ@ذ5R™¡Ss¦Sl'óáñ?q>¸Rw²© q• çÿó­ ¿‚ÞA°áôØÿ;ëdWl¤s侫Ã`„+t1ªxœ4µ…L$S?CÆ“‰-³p4Žþ¡')H6Ã|û ÜŽ Œ> |½]’Ue8¡Ù5’^޾€Ãüñ€óPD§[˜kº\Jæ K`UBh8w(Õþ’ü³ ÍŽƒ À=3“nƒ€ô%]%$ç¥ç'ì #k'u Ow,&¦ððøöá«Öæ€=\£¬ìÉŠ˜•±Ž0œéš›ŸˆÎü¼lÉÉ”„_Jý†¾¿HEo|›‡ Q5É%Aµa¹y+Ayp˜«?˜wXqjã÷¨ÿkŠ–¬*ÒXƒ "ÌqÀm o,Àšò¨ª„šˆÃº‹š}úÓZØÈ­Û¢Û¢ØË ×]ÐÛ –,÷ <˘š¾Œ>Mþ»Òl:ŸR;€;}¬8ŒÖ6ŒÖÖÜŒÒRÉ=j1šN¦ûÿžLcEº‘MRÊ4!_«”’\öÝÚM7ùp Δì°]ÚI7f‹ÑžU¦/5æjé00™²²4™±ª@àÔ;>w­£æŠ(ÿs#‹>œÉÍ [6gyVÑYžu¼ån·C2ïKQ¿)ªàKh¼ËÅuÚ0=EC{KöˆË¥b˜8Š·¹L·7ÔŠD64jmÌ0r^> ÏëÊtåkÁ+UÇCŒ@Í’Ñ–ŠÝۺȋÐ4÷•û¨{”Ú µ;jeëik8‹7ìuÍÀunH]­ú`#ñU/›€gåY床õt>+!U©Uo$3ÃHשX+ϨÖl.‰ÝFÝŽ!æ¶¾òÂõ{`7p{ÙFÈ+.8Rq§–®Ä³Yž»ìS¸® Ô¶ípcÀátTs/‘UŠ«¤x3x|?r8]‡T¯ò$Šn› éªÖëçKQŽGFžR¦1+ÛȦ©\îJGÏ´™ø>ñ““1du–.[™^*—»j î*ÇR~°ûÊŸ‘!EINºxc‹Ê\Þ*/Ûªs}f wÅó¥’Zq^·…”[W i »T VôSHœÞJô'7ÿ´é瘫ºâàâØÔxˆ Û¢ËÑãÒ¶qòÌDƒÆ‘¾5eÃJØ Ê"ëË ³8}¦!]€ÌÜ,ÙùéçŒ%ÔœÃIì–WÉyªÊÅ ;0¦œ%›2E7‰¥=ºÚ{t3÷èþ¨ènîበz¼.¾Ö÷¿GB endstream endobj 1723 0 obj <> stream xÚ=”{T÷dzÙ×E££ËI²»$\q•¤DD/K‘7‘OÄe Â",Râ•~€F¢¢”©ÜúªVŪ4 Ôåác‘…*§A9¢MRûº³ù-M@Oÿ¹sæ7÷~ïçÞïÌ0H"A Ã(â““6&&,‰ˆIL\8uò~<©ù1ÔY)ÞDÂ[Œð¶HP‰……’·bVÌŠRÑØœ©¸„ö?o Ãp;va.À_§[aÎ+Î7edZ4ZÃbÍò•+ý4+tº•š°c¾É–«‰I³dsÒ,ôf›&Ñl0-Åmp¦Å’´lYQQ‘ZN¿9?#d±Ÿ¦ÈdÉÔ$ Œù;Œéš5æ\‹fCZŽQ3í?s‰0çäZŒùšsº1?—rÎñG+Ð{ÌZ-ŠC (¥!22&´ å2ùL!Å÷@ó -òCK‘?ZŽP G‘h Z‹ô(Å¢8”ˆ’hõBb„¦ç¢äbR™Jæ·"…(VÔ ê‰ËÅÏ%^’pÉFIÄ!qIÓ¥'„ 8ŽG˜ç#báW­aB¾/\èeàÕ°ŽB&ßÒzù\ë¹–³®c;¢°ïÉ*-NˆÉ󽘬l·v=ÆÜ_®G…¨ñ²¨È””¸¸øØÄ.Z˜uŸ„ÈJpIe æUM 7¯MÐ62Ð:$†B(?nÓ Á,Ùï –nLB‡e¤vñ]¯A[i?—BF wvÃ=„ö24*ὤß%½Ç6\¾`½Ž¹¶›"#‘©£qÜÅíÙ‰Êk‘ƒæ;˜nü{ƒGÐK_u&6•äp §¬´"ºá¯½L÷(¼ 6øO6Å€ѱé{ ¥ÌÍà ï€×· …·Ôð•‚o u#Êõg·ÿ>N!n$’¬#‚;ÑC¬ÚŽûº­T\…›œ^Ìe}-òP -Ò%,yJ~’ÂO“úQ(”Álð„Bò£ôÝÍ!Ü'ük¦àxÿ¿­¥8Ýi®0·U8ïÌ(>,ì Ÿ nü&âUº=/¨,Û³’=ÐXÖ´³}ÿé}Ö}-D+| $n“úÇ‚³ŠÅ•_|b# tÍV:X˜cµ_8zÎóÈ铎Ï[¹*vê G^Qšºàê-æÙ¸IÝ—y÷D€–Nj²g ý2 óá5\{xøÚCˆ\MÀU*ðw*pÃuÓ·(¦ †ùê*ÐuTÂ_z¾\2N¼UÄ2©vXÄB±KGY—Ÿ à¡Ê`^[D|²!”(Õ §dfbœz~5KÂ\–òÝÛ–M[ú»ìgŸÞ Á›J“²?_¯<Ùp¥õ!æÚ­é1j£Œ¼W¾h3æ¶ž zª:ÿ\Ýu…û¥C J゜âíŸfUìÆ\ª©åœÛAwØZÅ)„÷K{àQs†và…wy|xscÉÁ¬cix/}-¬&RÂù·Þা‡¯7_üºì®rKVjq2æVo¼ÿâá™ñÔØº÷Ú¶i-uþÛÆœîË]±ð&˜y|¦¢7û›ÌÛ õ[0÷nÀb2Ì÷™º wÖÝ<V4WVáêV|pSzÒŽÆk:€„«íäë:¯þñ>í ïp ¸D]ùGdؘ ‡‚Žÿ[—7Ìgû;ŽYUGp >¿‡»+³2×bÎ_ªUû®‰àâ2äã&Á³¼G­]êôáGÙrâ͇¹Âìt”ISOµÔ§°I==ŠhKÁÆ8† š.h)´ñ=»ž©*§e™M\w¸+jÊe=¿yx¬&Τ"†¦>sºÓasjêiÕÈâa¾ßDBdþÞd.™÷ÊÄÀN|sTÄ@øÈ ]À×åNß½išTŸ¼^­€ʬnf)Òb0ñxâAÏX50º26;ã#n$Ò55š‹v¹ÃXí°Ê.†AAÇǵl®ÎÁ\äÏò}ÔØD…§Ë®ío߇S¹ŸGà=*N:šz¾dòvVç¾kô¯âa¼­Æ7Ìg~u"ëë’š•¿Þ]ý‹£¸»Ýƒ«úð¥¢S»¨»E¥]àjüÿ.„p>”´²aÉ9 ëËš¯{(”­>e| :‹ÕvÜäR)ÝÎz!üdÕ7׳dË™Ê]Rl–»–»WÉgÙ܇fÝ:$—ÕÊgÃÝùÿSnW endstream endobj 1725 0 obj <> stream xÚE“}LSWÆÏí¥·W,U7"Îöj4C P!Œ‰(²V…"BEt3…`_Ö cJêÇÆ´ÇLq8¢‰Ò:7¦N4¸ [œDPf‡¢†t0¿’eqSßSÝv™YöÏ{òžäyßß“óùù!†aToëò²St:cNΘɛ8#Ýÿrƒ×!'³y!³eDÍ’~³bÔRE¾i“ulúdŠ<.ù1 _¹kµ±QZmŒ®¼¢ÚZ¼±È&†..Z)Æhµ‹ÄäR‹µ¸° L4ØŠ,¥6©)sÊ ‹-¶j1,±Èf«HˆŽ®ªªŠ*(ÝUnݸtA¤XUl+³-[,ÖJËz1¥¼Ì&f”ZÄWÐQ¯]yiÅV›Å*Ë×[¬e­2Œ‰DZ6éQ 2 ldB%h+ª–°§ €Qz £¹h>zE X‡Œ(­E2Ä ?¤C»Ñ1&ˆIcŽÊä²%2»ì´ì>Ææ±el3û”ìQ‘ét¿ó¥©‘¹3ÌÂ1ï.†ÓP 5c©¾æÁ|*ð.nýÙÌ;E ¯ßù?ÀÐþ æ ôòÿË¡RÒst¿ázÌâ1èó!Î_ÁµnìYr†ÊOÆŠÂZLÛçÒy©F^M4Ðùç=æÉ=ôû„» Í + ”ŸçT¤¦ÒEÜ.æÂ0|6ÌŒx`ÏíÍCùà·äx.6àŒM7é?NÀq˜2õÆ–å_¦]+Ä×qßÙÓ7N¼…ã©™žh0†‚ÇÜ{Ž^mºØtóŒif´§ã´jcEDÎŽÍX²Sƒ»È®îo%?%wX¸ä}Kø€Û¶íÝ÷(ÚË×8ÕšBEþžŸ8BU+áç.ªRLÊI[/wÙŽ>!ƒÌ¤) ;¶;옹'=ìïr÷÷õâ‡<°KŸÒ5Eؤ¯ˆj)Ä{ëíÍ/¾épcÞÓ™§Á«+W¦¦ñÿÚ‡s.°_eà/;Nê…æk=m˜ÿ¡½Ì Á©ëL«ìµŽŒÚ~ÅâæXSÂÚL&'¶¬ûiGVHÌØ¶Éç”±'Ï5øvÞà›§nžkÀ×yOB¸z1Ö›-Òï,ìC'‰mdN’q–°^ƒËÑ>ƒÜÍݳÎpnj–sôªW&€’þ-§»9•ׄ;ÉH'ó`”„޲$•χ°B!²a5 14QC“}Ap„>§ šFÓ); ¹,mnwA]?ó«‡%¥pCpÑïá ŠÜàhØ“û&}©¸!ÅÁ\Ùë ¦}”%Ó¤uñ­ÜÊòÜXuÎ?a=U³,¤«´Ó~óÏ®÷¾Ð¨¼þÒôžD÷K"¤óU÷0vó¿‹¿Ð9jºÃg…› åÀHoÊ=ÜD à0ÌQ@@wzªqÕ;4Häé %̯BãþœÑ7ñ8B&û}R?æSx8|ˆÞ9Ò—r³)‘&û nÉ€cç2­‘¹= «¥<'’,!‰¶rI¹ Ë?:qQ ÷“¨G¡;¾ö¾ú åT—ÿðÔë”ÊáCÊ þ> r| endstream endobj 1726 0 obj <> stream xÚ]P»n„0ìý[^E<"¥BH9îP(.‰.©½KÁ¶Sð÷± º"…W»ë™ÑÌ&Usj´r|’-:”–„³YH ô8*Ͳ¤nŸb·,©.ܾó !9×_oßÝcu¹féÓ­«³8lˆnµù>7§vN H®^pv´ÂáUšÂîƒ$’Ò#nU7íbí/N¨¤¬,£\¶YFâl¹@âzDV¤i E]— µü÷—oŒ~?œ<òGOðýyëŸ#oG…õžT,DÞC¼GLŒ(÷“Yc+¾?Ào¦ endstream endobj 1728 0 obj <> stream xÚ­z tÕòwC¦[„Z'Š=‘]VQUvd ;!ûFömÈžL–É,53Ù÷e2d²MB²°DH@@DÙž"(Š·Ã¾ïvÀï{<¿wÞÿÏáô9éܾUõ«ª_UÝÕ¿?%‰½·xãÒMë',\µnêáÅ l|¤êJ¶á9Š—‹x‡~ü1ÿbÿW(Jt`¨ðì7˜<©»C„çkäñ:eGÑ"‘ØfÀЄ”¬Í;ÖìpÜáè6eÊôIS¦L[¶ÃÇ7Âa¬Ç8‡©³fÍœè0mÊ”Yó½Âvx¸9¬r‹ðõ t‹ ?88{ìðŠˆv;Û7""äíÉ“###'¹†O óywÜD‡È¾ë¼Â½Âvzy:,Špxß-ÐË¡GÿI=Ï…Á!Н0‡UÁž^aADãýû=/!%ÓoÂ9Ôüá®ÃÈkµH#ÒŠPTèyªIÙPŠ¡ž£P©A”-5˜B %æI©aK½@½HÉ({ê%êej8ÅQ#©W©QÔkÔhj 5–G§&P “¨ÉÔj*5šN½AÍ Þ¤fRoQ³¨·©w¨ÙÔê]j>µ€ZH-¢Þ£SK¨¥Ô2j9µ‚ZI­¢Þ§VSk¨µÔ:Ê‘ZOm 6R›¨ÍÔj+µ ¦´T"åÔQý) uO´¾ß ýˆW÷_Ôß`coó­Ä*áéõt™EÌ&FÁ4?7é9ÅswÜ|¾pà„ƒíô“íJ[ãàÁƒ3† 5ä§¡[‡>²K·»$%½:ìa'Øålé ’N¼˜$›+k´Í>÷¥%/Û¼¬}ùûá¢áÆáõýR̽Æä/ÉUò»WF8Ø3rØHëÈï_55JóÚ ¯åŽ>0úŸc\Æ|66aÜäq‡ÇÛŸ4~áxà5¶]“à Dþ‡|-j«ùÜ‚nY>¯ó¨kÛ}X’‚§ØX$†VceV^föÇ º'Ƀ 3%Ki 5¸3I÷éîR–?)ÉFïØ„I4Ûu¡)ñ*å&Pƒ–DÃzHÍM)ÐÖj÷1a>U°a›ñ­Ž0<ÏÒnm¶Hl»’ÁÊÿ¹[„†ß@7Ä|m4ä]à*¬Ì ¨\0(}äÝå´Vù. i0~{öœ‡†£¬áô»Ú¼F9ÿ9êìþüïVØvyCÿ»UÔ%­ó ºÄæäB: C¡IÇnè  ÅJÐ8äSާ»‚‘¦»S®…92à?q2®HR‚4öÊ\(âøNI5R“£ñ;KBðTbnÄ–ÿ†ØbcEfÑÃÓÈûôëb~=?ŠE´@ŒäÆíû9#AQj¢::˜ˆâȪš"SE£ïnGn ¸x¥©ƒš3B€™ˆ™M˜’cÉì€Køí¬„¥\]¯?l°Xj›ˆmôR%ì—£ Èûéï›õí†ê–vh!¿ßIÏlÇuè!‹lè»ß¶}Ê„ê(=0::F™Á Ò‡U%k LÓ¶|g{}£ÑlG¬Xy{ùié!t…˜q +Á]Žwý{]x1í’cuäØK¯huZˆ'È @6’{×Z>áj¡1Éá®UC,ãW™P¶kWqíGëÛæOÂÏoÆ"î?0ö‰ŠHmRö(èsZz——õþîCþOÚGe#½¬^mð/t%0#±ÈñÕÿaùXYìG̸óõ¯¸¨‚êädul„Btv\‰Š±íúê p·ëûôêÅ®CÉÿú‚ç©ÙªNmj{éUê?›ë<¢ã"ÜL[€y?G üâÆçÿcõ²>£ï_oþˆ«€†´ª`Omr8D‚"?¶4±Eµððr9g²»öpI­”G¯#/¶™w²©) ‰öãš»·éãô)ù`Ÿ Æ } ÓŒ§°5áAAááAAá555œ-¯áåå;Q爇võh Âü•ðþ‰^篱'Â÷»úF‡„†–„4r&(ÌÍÌÔôzňWËÁ?uáÊU‰‰Bn2©$Ÿó®|phã ÿ݇DÇr‹1·‘ñö/µU&»£µHjEÒŽÀZ韇Q):Å¢aYã!–n[:;‰ @,î §g8u$|’®ËÖ¥SUVVU½³4Lå¡Ý*‡i‡'£¡)Œ³õý[ι;ð®8w$çxìóÉÙ–ÏHÿ(G»èïÔ¸9ªõZ}0¡‘ÑÁ–¸rã^ýA9Ü]v÷Ïdöl§±8iéT˜‹›¶•ÆìñÜÒ‘ÀÜîWª¯ N´òM¶Žf„Í`FFóu³èè'h½-<Å]ó»œØÌƒ2™¼ä%—i©ªÔ-K–†,€÷`•e}gTÉÎ"`æ.š‰ŸÃƒ¾|ûü¹c7P9BûÎÎO½¥5Â×ÐaÍL×ëdÝþ˜šœi %ĘœËå‚!=;±ð“ØÈeèmôΧå‡;æÄÔ¦…›äüêî1ÏübÑ“k®/úÄr$Êžǵž¸à‘û¶¼ Ë9šD÷Ž‹ÑUœÊ‚ 1%x(²óGk½hÁ´ FC òI…02Yj£Š 4uÉ,ÝŒû%b1Ì„9yxÐ‡Øæ|my.0™éÆ,ùÓ½Q,Ù¼ Y¸¨DƒÖ#›ÕhðŒO‰[UjµJЖEÿ4öžØ ð\o¼Áv ½ÊªÒՙǛŸDBõËGb¸J\ZúV9Úß‚˜D¼M‹˜ۨNRX&SÄ 4_/)„²ÈHˆŠçp=®§ã£ 2² åˆü$‰‡(“ Ê @ñ†@Ë  Ïõê¢gO…·z<Á³ò3s³ ™^¯‹—Êà÷]œT*Bëê,ó/]B4ÙhõqQ*£´š=ŽK×Ò=” ºöPŒÖ~fž÷t”QÌ/'‘˜Q à߉ñ NÒ$áü¹@–– €Ä(s’ó¸BHÏ5æ2äc…¹Kf5_AÙWļ+:ÇÂ7ißø~µýÇYÅn°„ºOò_œ6ÞyéS[çî}û\äA8_—ïû¡îLÆE¸Ä`|Žõ„5–è•'à6ifNÁéì#eèùó9¨‡ÓÑecsa.¬„y°D¹"nâº@gdzo²î#® ùJŒÚ»†±`ˆàV­˜$UhÙª³’é.¢}4‰S9¡ ¹--×{Úzª&¯I.lsýöÛÏV»C¿!—[a½ôû𚂸Gà¾=’LýÛb›ù“§9cIC~ket¥/—"„†n×§GšŽskïÛ³äðΖÙëWáõØO¦:“pFúO“¶diKÒS]’âRS– ˜€\õYÄ Q»Ð€Ÿ?±Øµ¡þoþ‚Þ¹=÷Sh/úý¶êøžo§0zîê¹~樫É\sÈ â8ëÁÓÀ´~¨˜*‡DíÚP—Àm;4aº]¸6Rt©:Hb¤ÝJe”pû$ß6-‡‡/r‘»Â¼ßÒ¬fØÃ4†˜‚Âýã]¦ÜY†DÈöÖ­_8"¾]yñÕò^|ÑKVÞÜ~Œf±oÝ|ng€¤ÕØ mm‡¡õiWsý¾u ¿ÀžË%“XIIÄ'ºwÈhd!UK#Aþ9›ÃQ¿ŸÐJ3zñŠÝ¡{Û¬(ê†ôw~Ú΢çgÝÇ· \c}|´‰6©êSëH“;ø‹[™šŒT¹Ž š¦‰LÞ¹<`{–SyŠQKÞ1I+ÇéhH)ä²À`LÏÌ+n:r:Á²=;ºØÛà [é#ð…ÕánážÞ¡Ûa¬;ó‘QgÔåS_b©¨ˆ±øÅû¦nŸqf«·§Eô†O9ÿéÑQË·Å|ÿ͘±œÁj ¶mºŒt÷~ØÌ Æâœ“ùY™¡€@é!QÆÎÆ"…ßTü²–Ãk:ç`.×AÇÆ³¤ï*¼¶ï“ÞEŸC%ÄêCûP很CÒ»h&¿Ý^«Þ %ÌÇŸ¶=wjÓBÖyn[í˘ãØ/›vÂiæö´cSƼ=Ñç6§¼Ä¦0K #}°6h†#ŒeFü²ô7dóÕß9hTî÷j‹*Í]ÑÂŒqcÑà9ÕQíð¾ýüy›fÍXøÉŽ×ú®½WŸÆÛWwñ£7,¿Šåmÿ•cñÅþÿÊ»=Œæ _’V-Ê,ýùÙKïDu‹Y2ÌY1?5åiéüòÄÔh¿Úð¤>dÿëõYúKYÏ`3ŸKæ"|Ñ+Ⱥ™(pÚŒš­vH~¿»à>áæ0¾‹tt½!«CC$wÞܸbëL,–ßJfï–9_1×'‹_àºû=U+héo}£(?\‚ìoÞø‡®Ï:ÅùÌ*|‰ÅC%NÚ¬z9ªDkè{m“–.Ú4k”0¡*¬]¯[íŽ>àýHa¸sýÀbô&žŠÞG3BrÄäBV§Pé’R𫳰˜÷ñæÝ¨CN<Ú‰6íþ˜C"¸1Å„GâASL1Ëå(‰.,%§5!Ê-óeÞ›MFz¯Æ3ðtìJ䧃µKd!î/½/nèšËTÐMzlP? š84­AëðËh*ž+ÇÃþp`{,â÷ô"u_ò œQt,Ú»&gÌ,ŽZí³52dÝÚÑ„Lºf OXQ}ïȿՂ&XŒ1~‘},ä+IÊ#E, OŠX€ç‘!Ⱦ2ÓMúnžÿ›r * “ÌPŒç¦¢TI¯{X éݪÖcùãùýÄcŸØv9¡íVt Wèz zÕ"æ/uÍf»<óŒá"4·Þ‚F/~ôD(h#Ý5úÇÜÇ¢g&ùMàf Ì>Ñ%h~OÃnØ ½§£uriÜ9ø¦r÷GLo®}bE»­9tùåñ¡‹ÄW3¼¼æ/Q§/pîD ô߬x"Ï:~AE¨ýí ú£/ü†ß#… Ž1ïW)› ^ž³{„UÒ—Œ}Â4ÊÙ\¨°Õ%ØÓ|©g«Pz¶FØŠÏU˜£þüN«¨õG㮉чh,;y‹ãFNKÀç8Ó™_[Ùl Vìˆw™võ ù/póúlBk»~ ÝZ'‰k\´^:'·éàE„7Ò?A‚/‰¥Ò§šò£ø™,ZŠægg··Ò¡ñY;Èt‹.3’!6))%ŸÆ2töâBš´pýÐ2\ž™œ“‰öžIØ­A`·†==ìFo€éûˆ“mˆ“=L<×ëäï„pGyl˜DùZ<Š3«7§øZz7þÀÕ[%>š)àî9çÙ*ñ¥ÛGcûLw¨æ+.‹‘ªk›lÖiðœ'y¤¡CÀi” ˜þ ¡¾þ V0‚íUr¾QO#Õý22’sÁ>ŒÙéyH×5H¦ï>+yl|“ñshnþ šþrÄWñ88cAƒÍ|Åîè}4ьƴ>¸f•þ“Bç‹Ù &Üÿ  ‡Ë·ï¢á3p6sñˆsGý­fs€«»B ¢ôZMÎewDù«Éر9å@QMy}³ü˜ÝòÖ2­Q,pø;4 Ðæ_rFO-ç¬ÐY“ÃHÿTM,œ|˜_Ê}G.ä)åÉ@fŽ$Õ·@Wp‚°Ýá§HœG(Ì«ÃfÔI*7w éÍÜ?V’æ+B8÷̧a䛹†0sõWãׇ¿ÇÊï'°w+.~ ™±ä*ÃáÏžg£ñ, Ƴ=µàq&f"š–þQ mаcÀRX­^­>ªj¹Xòmu&ä%ÈI©NÖ¥ªùF‡‘ž:¥#þNÂ7²èS[ë×—‘³“ü)ÕvG+CO¡ÏOm¬”žC¿ð2³®*ò<Çí¿8òñE½füV¦³^*R; £L޶÷’~*èt©‰¾ëd5î­ÓHÄ‹gN!‡·/¸’§îHü‚4ÁwªRkS«½ËCsýÀY´eáL.æfl<¸öˆæ”®Q—›B¦'&R£å؉ŽÔ<2Ñè Yy 7ë[wœò¹A:ùç¾ù õ“KÏÁýeßÎ41º•ŸUŽæ7‰-(ûʶˆ»& 7H…d(D3ŠêÑ(…JÈÕ–«A  vÄä<„¡î8pàAÏPçA„ÂÝB–'–¦çª Œ„ ùâ=E5™ õb/™uY2‹eñÈñïLtÂ,hÇý[fDãˆÁäsÑpóN ’M- :G×Ã~!»}tÛ´;|·|žd· µ¼k„UTÖµMÜ%â¿e ›ªj>×3V:@ë¡ \kwêÊC ¦hTZ^ѽS†yƒªƒ}Í1°›kƒ×6×ÞÍ?%Æz¡¸îG²¬¨ M”€!#£±}”ß+¯ôQ¸øÑ"¯ôØÞÜf òµºÀ ½ò>Ó™ü Tš"o|·» ¿Á'èÒµ™a_{*{ä-! ¸Ü…õÇ ò}Ìïɰ¼{>žÁ+ÉšÆg®=éiùÞÈ©»KfL6&1#+½Íâ3dèíîÌÞ—ö½o™'ü[ѵNÌæ_`Ñ+h»¹nwÝ ¡zꜴaÛÀ£·š¥$­6U‰%xŽ ³hƒÖ˜– éö$EKö ¸új€WÀ*½7ù¢ŒþÊRË‚ÑJl•á·pZ|dàöÑ`Oz}›¡¾éÞ¤¤·ëcªH”åÓ³òÐHä-CÓpŠAmTƒÆ1®ÂÈÐ`<{ÚzG€(zìÌØi}ª=ºzMÌÿÎ_e›>þ(½úüÐçßÖâ¨H9(U jž…Ëexú 5W¸>²/·¤ïïpxºm×»‘å¥ôç­,EÞøÞôL&‰ ßÕä6ËÑÚ–G°›ÿÓ*:cáW‘*½¯k8+$d1Å*Rß»×K”=ù”…lj/£·H.N•tÛwãT%è Å>&Ê9ÞMR‚L¤eNÁò¨×ñ*BoI„©ÏØòhb‹ h£lld[Æ?šx·¿òg-œ¹sG ÎH“a}ø•ðþ‰,¼#[SåÃEB|’J¥Ó ×9Œ ÓåP—õåÉOòûÎEÓÒÓ”oÍÅVW8ïm(­ªÝÿ»ÿ¢êóDÕé]É,~ÅãîŸÇ{ WCž¨úe’<_ÿ[%‰áJsŒù›+oN½}Àl×vaÛm4óÌ9‹4ð0ºö5›îQåÖLùÇ…—åGÃéµa*¥Ÿz‡œhBùÍ>MžÍ[Š·‘j±Ó²@SLeu©‰L ùiõÛõU óHü<æ9MîMK÷Þ¬yO³2pÞŽ°Mà¼}7ì$G¤œ†-eíL*z‹CO\¸Ãy«{Ã!>l»‚fe •AiV–󯚑w›ÝÃ3¨øŠ4Íã±è RÚÐ_d§n•wß±Ðz}vaU;#=XѶå+Ïÿúb‘tÜ=,!-ÿpuŠfŒ¸˜Eî4a}^qóѳ+`?4†VxUº×;xkW9ï ðòÛÎàSÞ_F(%š¬QZPýí&‹Ýî+hÓíxá¼ò9Ä¢™ß¶ærमÁÇ]£ „&´4²ºÒTRûùÜæwñÐɤ½ÂIÃÃî%]ëKuh`nnh¸dЪµª I˽ÉüÉoœ¾Í÷X¬hãí{,&¢ŠÏiȇì2ɳ±Òï¥d”Kò¿þÕ~@5ºVn.ÉFŽÃ,–þ4 VŸ‚ý»-u *ïÝhˆ­2&p›³ÂU0®2|Oh«æ´B“áDÍþrëžú#ÐmqVç¼ÐBtŸÑåhÙ®ú J>ÝsJÛe°™hÜUËn`äâ—=å8y§po6Bù½ wIOÍL…‡Ê‰Í/ý6ÑÈv?—å¦Ò›UÚßQS! ¶€GmDSàp[t¼÷.ó«Ùfêúöu1ZÈ/dCÿÁûž}WÜä]¿ñ½77Žà0ýÝñ=ãîG«êØ}Zwüê.»ìª;#Ï£ç:]ŽKW¢04}îï’C•¾®È’¿«º˜ë0&‚ôt:ÿ¸°”Ĉ`2ãÉB:ì*15·jÊ€¹sæÌ94Å6…íjÜݘQ*ð!uJuš™˜‚Äâܲ¬]%‰už$I]TnînõnFÒNZ¼ø]9¸˜½,;â¢ýÀ—‘vQPàe\ãï ÌÂ{ë‘-ðkÇEâ;6Wo¬^ ïC¸BªÞ?}§ˆwGá3ìèŇåp`OÓ>#ó‘äê36,Ú2NÞ{IÜN"Ôï ò:#Fý¾fû€jÐwª*;µ»Ÿ^v®¤={ôÔɼ ë8O?kÝ&"^WË G®5 1¾ÄÏ´f‚Ëê/=øk` ‡tÄ­mhÐC»óß;-½ƒÞãßg±ƒ°âÓ ]ócuú#†Š††^ËÔÍréÏéü¶.¬<8@bµV[ÊëEÇnæâïùðž}=nwþ¶ü4ér½…' ;_ÈHÁvNž±‚K#•6´ (ÝTULe´)88:2tÓÑàcç?9u‹$fפgò½áÚ&zxZüð `õ$²jj[t-O{@Ÿúðˆ6Gˆ¶ŠQG‘5Õú å55ºa7(Àë0–¢%2!-“IúÙ¹Ù';Ú åB•Ò$@°Ï*C¼P]Ët¹JH€ÈøD2%À¶2>â_ÐìGŠO‹Ñ{]ËÙ¿r`É¿¿ÁoS˜ízc€ü—$ô]—Óÿ“Xøßˆ™øëóóœa8¹¯b¤—# ª`•ô`¯Ñ½åðTwéþÿ ÅŸ­Ðc%.mÆ[H³Ñ[‰.óC>fñ’/?¦ ½¦ØHï&T»Ÿ|G`Ê‘ãñ xèÝш!Š­{Í5Œ°x þÑÁŠð„xÿ'`¼ƒTŠç¿¸òÕ7mol$€¿üØëO?¼&½€ÞAß±¨åO"^ºÿi <‹ñ'Ñ÷Ún|-ÜJA§ÑE&B(\g.µä×ÕÔ¸rÒ Àgi¼+1–Sšù7Ëìê-a hKÄÒÈmdÍêoca!³Ù×c7|ŽE}§)Ð¥'=že½Sbèõee"¦´lŸÛ~]9ž>ðÙ—r8X›˜ïWç™í–M‚Ê1oig*[¯q¨dL5è“sˆz½³ìϽ£l©½ ‰uR²ZãUíqF[¯¥Žrð-®R0Òu¡Õª/ã‰Ö2RžÇ˜P°½eýz½d£ùÂ_Y½jů¢•aݬ@‡qjFñ®¡ñà;‰g«ÏžâŽ…­§çzy/…[%ÜãŽÃ¦íq~Eñ/_b§ÒhÔÓ~c?B4ó´ßXL¿±mÉ‚™êöN}×÷›‹ ™&Çãé90Mä¤QGa_upUA:¸—ÈäÈÇ‹ù7Ð56gWÉÞÓ÷EhƒtáÛ 1÷5éò"È$—¬U«•¯álîêT=ƒce3”’É"Pç¨ñÐ ËOBºª €”>$ËŒ7¤@¤ç¤ç ãx¯¸RáòäŸè[zÈZÐ ˆSqŠ gC”ð}£Î A mZœ#‹êÔù:aŽ©j‘¤Û¬  ê•ÖÅÚÜ„ U^`VÔ œ&›ˆLiBWþxunêúž¡öäkòý‘þ]–oLt3dfþŒe¿à¦t¥ðʾŒ=úöUQ>¯£”ÈÖîÙs°¢ÒÚØZÔ.hª $ãõFC‚°s¹6;b!6)!MµjŽlÎÏÉÂì•iEE9¦žÕºeÚØNúaõ ×µ¯¾‡YÙëøùmk×hw c¥Áª¯¬iÓVY«0¦ÎÊ\Sÿñ—_‘e+ b &ÉÉq!¨X«?j0W5ëj{ÏS£ 5=Äàf.½Ê+ˆK¯ŠùéâÊ“úbxìÑh'ƒBoÕÇ–MÒiÓGc ‹‘Y«M'¨U6A׫mÌc~ ø¢ñÝ"YZB¼Ÿ*A±>xñ ÊwT©5=Û ÅLeTqD¤"!йÍçwZUºT°ðÃÌ¢6 ú„Œ/ñ¯±9y‚s˜‚ˆæð926Î ccæ/eM$í$‘àºîAÉŸ ¤ÙÇgUÐ25®&Sc2°Ó3B#-!¤H3 ¼ZÌ«Q6kîV+hÛGq=/ÅŠÅ /ÿŒUôL_ÞqÞow]“~Ç¿Ñ5‚-²Ñy9¹pV“RCø>J±Ù±8N¦ßÓ¾Û–¸’¤ªØÒÔØe掣Œ­ÂÌ/,AAy™f vϧ­Î> stream xÚ]Qkƒ0Çßó)î±c cº¶ˆÐ*‚Œn£¶¬}Ôät™„¨~û™(}èCÂï.÷¿»üƒ$Os%{¾­æöPK%,vz°¡ÂF*2’÷KäoÞ–†ɱ4Ÿe‹Ü®?×Ósr,n!}¹œ³p ë¹ä<¶ÄyZŒ]m®j QD‚ÓÔ±ëí«½Ð>¹Ü—h¥j`uI Ÿ)cþ°EÕ%qìÛ…óN\ ìLÉÑ–ªAQC”e1A%Þv³¢ªùoi§Êtªd4Mcm™ã5Ý;^Ï|pü:ó›ãÍÌÛL¼óZFw~æÒÝMw>Ým⃵ÓþÞLïŒû„Tx÷ÛhãTþü–²{Í endstream endobj 1731 0 obj <> stream xÚuU P“çß’E\·FB»&q»ÕRŒ«¥s´ÚúÕ³`+‚°†!æ ’@ "‰ È ,A,E±zÝiE¶íõVuÝV×Þºvó¼ÚÞºÞõnçž7y‚Û“-½Ý.—ÿû¼ÏóÿøýÏÿÿi*'‡¢iº`OÕîmUOmÜQ¹g¥4½³N{Wò›ÄÑ\v9Å>E³Åöi.[˜#º½5ç?ùœ'(оýHZž_˜–ƒß#’z’ˆyÌ÷©p(šZ@-¢~DS¥Ô&jµ‹ÚCÕSjÊDÙ)å£úh.G åJ½\­ëšÌz£Za0(š[dê½BfTè3k™^¯3é• ÆÌj_½ú;/õ:c£R»_©UÍ µB£Ð[´Jv¿Z§Ó«û™EÆD®Pª•Ú†ôæì2³]/Ó?ZY½Z&•®.‘JWmL£II–Ê—IV––®-–¬’JK%å…^)—i%;dÆF…Ff$/jI¥N®TÍ’¥ëƦçV¬0™L%2¡D§ox~Y±Ä¤46J*…¾U±O²Y§5J^–i’,×%ÙÇF¦©…ä,Ù¡Û§Ðk £ùgõ(½˜ZF8\I×Põ¹h-¥'49N;h'í¢Ý4ÐÚKû躗öÓ:Hí¥ê¨Z:Dýœî£ ÓW‘Cœl¡nÒËéÃiâ$¹oçTç\É]˜[žkÈËý˜§åçð‹ùÍüÓü{¬³ 1ŒÚâôg,â&– 6ÁÐ0D£fh§ÎòÚÌ`2 ø@{îÑ·ïqÑ.äŒFµZƒA«5ŒŽŽ‹ˆ“PŒÝ¥ÑÖÄe‹ÐIÞ‹j,—×EGŽØ¬bèôºÂV´× 1V«ËEÖ>[Ÿ(^o$‚jPɱÜëtû¡( …Åà…g¯Û‹W£•{¦Ð6´MØëìïõ{¼==`ÂöEd‡Ãje ’íXO|§§ã‰Ëqnò à:$ÃÝØE¢Êq :,CÝÈ…ö"9ŠˆR;SÏ °oAÈŠl$ÄNÔŒŒh ®ÀVlÃÛðNÜ,& â'â¨$ÆžŽf¹ZËÞ„{ƒ½É‚è›ÃáJ]ÁÂ6»³ì`ówt±Wp¿°¿Ó >`¡tF!‡¿-˜Š"·õ§LY¾[¡]œ:Ãko}À÷ÿ„{},ðû‚>‡ÿP uõ àÆbOók v‡»Ù ÂTƒÉæ¶CW‘5d ‹|„ÅþÞƵÿ'\²=]ÓÉyÜÄŸI ì’5ÕÛ;ê6Û·ƒ›±D (Bøð±¯ßýʽéñy!.ŸËó‹!¼àŠ­sFܾ6`ì°ˆÁÚ~ᥨf¼ñW*fæÏœ-£áLœ"’VœN@Ÿ.4L5Ÿjo8TÝ\ßÈÌ,䵜ÅÃÞáÕÔî^ Œµü¤>ÐŒ}ó7ׯ}ðÞͱ_ù=¯×ëtjäçö:½B—Çí9èÇÇ—Ü­ü·5êö¦«5Sk&÷2©;Ù‚þålÆY$(ÀrW¯Ÿø‚LÄ 6Q;€Ûfª_Q¾Vîrº¡“ìò¸¼$@Ô†8µŸ>3…™[;L( 15V\gX ¯b«fØKB¢AO(zþ‹[_ Âé¿ÏCÒÈ`uyÝSs.•þ½ 1ŽÃcÆfM3g?±áêV&5†_hÆ•£õ£¿8q<eؼڷ ç »T½É”®uë[4AO°…°…#\¶ ^ý½eP}¼òbåp08o=æà<Ì¿…¹ˆ/F|øìîä'ï¼i?©Ÿ®›6Oƒò>B”‡øåˆ‹ùḃg¥Õ?cÞP ÎÿéÖ7(˜{ïüxå²—ž[-~ê.´ÆôcÆ“/ÿ…Ùüº ~cù“˜(,~õ_Ÿ}ó¯wÄ×à¢,Öz¼é˜ú½uLA¢D'5•-ç¹ìÅïL–u¼z ñ¿B‹ )ïá^ÅÃëññ"¼¯Aä‰Ö‹Ñª9çR^ ˜ÿ•=–Ñg¯FI·³Ú8—Eì»Rd&˜Í"|Ÿ—㵪2Ql½öÖó“ð>Œ1h†ÿP%ÅáãbôôôZ„–þ-°;±/ž,#clq¸ûƒ±ÙvÁeI)/kÛÚ.º¿†¯êqL̵0ǹh$Q'øVGŠËø™‹Á mâMø|§Ä‹Xr}|6F¢zNŒx*‡C%&ÞÛ¡5…áaQRÊŸcò È)§O%›xߺ/»/å=4*`Ä‚Ý?Ê* 2õM.:ÃÎ þÆûˆôzÈäô“¡VÑV¹Ë|û@%?ШU¸ZÜÝn‡ºàˆúÜ7—ÂÕ>+iWóAªËŠsšÖsd  ´>¢êÙÞS=Ñ1å ‘ ?àý|¸dRM´Æ´}ºà§ÇÎ\‚kÌ,ªÆ«ŒeQ©qžäÍÛ0Ý™ÉXÓóOørÒóƒªs0?uzü¬wēŶ¥§æŒuÒÎF#¨.ÀDÍYùÉÍ}ÊL'‘žÏ ÿcRÕ_å³eÑTµÁ¶ U¬uüÈ›öRcC-¼ÂO[šÝJBÔ|Âîê‡WHJ„\„Ìs9Íè ãhQ-K¼.8šQm!·½Š(KÿQÚü)9‰¥Ý–œ¤Œ Îq2ÍrÙŸàVAïáÞ#ý¾ d™ŠLÀí1Šf6óŒnw§¾N¯}>³Vèðu Áøü~Oä ØK<<–z;·À0šX?ÂÇù¢y9k£ùyüyžüùñyñùñ£ùùä¿Ý~ô¿ôxÓ endstream endobj 1732 0 obj <> stream xÚ]P»n„0ìý[Þ)ŠxDJ…‚ Åå’p'¥5öÂY ¶eLÁßÇ6èŠ^í®gF3›Ð¶n•t|ZÍ;t0H%,Îz±¡ÇQ*’å $wû+Ÿ˜! =1óÁ&„„žë÷·¯zª~²ôñzi²g8lËjò}nënN­4H¾½âìì ‡¡{<†ÝÙ ´Rp¸Ò.nºÅ˜_œP9HIYF¹lóĵÀÙ0Ž–©I‘¦%MSTâß_¾1úߘõÈ* +OðýëÖ?EÞŽ !ë=*_¬õâAbº`D*¼ßÌhXñýMRoÐ endstream endobj 1734 0 obj <> stream xÚ•Yy\W¶®¶¡ªÜPi+‚K7ÑWMÜÅ]dYeA »O7ûª"«Š ´¬B‰û5qâ£/NŒ‰&1ÑÑq¢§È%ï½[š1“÷Þ¼?ìþY}ëžïlßùîEÁXY1 …ÂfÖâÙÍ]:rÖB§Õãå'ï-#©}­Œ­ ÖRFê«úuÔJ©§U?†QlíA?©›üù »ü9‚~hÎØ2V  ŽŽïŽqt?+(8:t£¯_˜Ã0¯áã&Ož4Êa¼£ãd‡™>¡½<z„ùùx„ÑÿlvXäµÑ',ÚaØ¿°°àÆŽŒŒã°eLP¨ï´á£"7†ù9¸ølñ ðñv˜æ°È#ÀÇ¡õ˜ö¯YAÁáa>¡ ƒ¼}B)ÚŽ6ÌPft—™ü|k΃÷ïÆ(:1ŠÎ ÏØ0ݘîLÆ–Q1=y‡éÅØ1öLof3Ä f†Ðw‡1ÙÌ(f43†Ë82ã˜w™ ÌDæ=fó>3™ù€qbf1³gf3—ùˆù˜™Ç,`2‹˜ÅÌf)ãÂ,c–3+˜•Ì*f5³†Yˬcœ:0 ÆŠ©TLìЩÒ^;œRVnV~k¥·ºcÇÚ²[9ŽËâ­øøŽ:®íØÐ©[§æÎ#:{wníò~—Ë]]»^¶bóY·¤n_t_ÔÝÜcvǶëmŸ©üTWzÎëÙ Ø OÞqy§¤×ˆ^ëz½´ó´;n?Íþpo›Þ'û(ûx÷9×WÛ÷i¿ÍýNJ:›Öñ âsƒÍŠÈàd¾ÇnJ©Bê/`G‘t{Æ"w/­Pi† Cl|bDñîÕQûV×7n8:UíK“µÕË xbCúNš¡3´·Èó9Z®ÊxÌÔØØ¬?Üe8ŸãËÓjc“©¹æ ˜éÓ ¹M­=áî}Vó½ºJ’rStúàXØ1™…q|ΦÕÖ‚R{î ªöšme¤ó±×@dTÇ%5}¹,ü4ä/´'äÈì$ƒ  ·W}M†>aïý¥æu'—nI Ž/Þ»"Ä|¤¢¼þäú+¤éNy“Žêÿ ?gó«Ë(= Û¡øþçD|«ë¿‹çóoRN;–lt;ê4¼áGºþÏáõýSЄð„}x»ê+u1”éöÇnØž¸¢ >5ð` oƒ7ðqq>'Žèh{gøšUHç…$bå¼<<&E—¢ƒüŽÜY¨ø>ßpv©ëf?w¯ý>'Ô%P”µ{ÝÅé±"Ï+ñ:: ÉùÝÐQq•¸ãŽÐèWíîîççî^íרX]ݨ¶‘nÔâ_—)®H.JÉÔºDHσ 0òE[s·©# y[Ò¶¶nÿ9Æ.9’ÀÀGîŽ/ ¤çgP{Òx³ô½YÑ„=1 {*¥}xCxlÀD’D’ $aø0#ÙŠI¸Ó„1OÕ$™ˆ‚/,+Ù~3á$üÎÀ ø4ëdÞƒk9epê£ö®ß³úÃdXŽ;Wm³`[ÈF@”’Ä£E ŒÃÎJ|ÙªJ 'DzHØ9Íeœ˜Hm»Î/ìåÛ ˆFËM}--/à(Mqàäm°žÃþ5¢âÂ9H)µC-«‹L˜¿mg|Ò ØJ3<”kO66BöÞ~â‘øéOºŽ^8nɱزªº’ãj8é±;6­¢¬&× üýæ¹340Çg®ólâJ<ì¶ÇQ`‘|´4S¶ßX…£Ñºöö«©µ=†£IWÔ ûÑïÑ*Âà/ø‹ðyñÍspŸ¿=ýµÔyêüÝ+ƒkšÊ«Ž¨áüŠÜcõ£Y•À:“¶H¯Ižz½!ٰàßI¼ª->: ÕGYTÀðÕZ†Ý÷É™Qã"ìá€}Um¸ör€lqcæ®2ñ´ù(„úÒ0ßäè`à7–ÕÖ–í«¹äq¹?éK&O$éjÕ¯0%ûÃú9âô/·\£Îh~þ+öF‡!7)]¨ÚÂiQ{Lç!—…U\›¸{kÜ„B{œÏü3†™CävŒ/–2°‡âŠøW9MÒBN.˜ š'îl¡éÛÒ"Ò Ùú^Ëú‘Lk‘Íù2??Í”›qöP³SÙåóF«Y¤aöÎg!c·˜þ™º™ƒc©Ç2Åì«Åªë-­Û(Ý¥nß_q ÷ÜZq_u×I[„­ÙA{à0íafݽãžsÕ°6dãú@þh¨pÍ\yÎówl",Ñ8O©†õ… î¬çU&mXï3yZÑÌjZ^î~‡Ô€Ì$qížLŸ+TG‹Ág6 =ëøI£·º w9qG wN5Vµc)Æ-f|!硯mÔÅØVKo<'„sà”°$vcŒ·»Ûˆ_S@Q^ê‘hâ‡ðöÞâ3÷„ *ñw³i®æ‘dÀ°Ho¢þÛ ìF“^ bfÍ5ž(=…Qpëéøê¥æ”®LÛ‘· –ÂF~AÈàIj›ÖVÚ CDi^‘¢¾u¿R l Ä‚”ÄÑÄØö7»¤X]âtà#´l %úÊÚ³p„6§Ÿù0¦æDZ«³ÉëQtUêO´U¾{Ý*$YRiM¢X›Ö Ô`“÷ˆ¶8{ái@8Jé¿Rê,àœÇ=+œâ:mÝÂdcdö~znó?LøŠLT·ÍÑ"Óö€UýB­äÍâ÷¾{¢Ÿ'^%³ù‰äŠ@`®d‹@„Ãî‡Ãþœã>S#âa-;3Á}„z9æà('Â>§Ý¤+/²›1Éú7…ä¯)¦V[š0_ºu©ˆ%¯¶+b?º»]ë¡íï¯Ò”?ƒ£-”-ó§–ç~Î~c*‘šZƒ%è ›*¶‹t¤¦l~í/ú£·(um圌Àk[T±­ýO •ÁC2/€ü]týJäütÀ{éXÑe áT"UÞa!±þIþ0&V¬½ä~fûuøЪèü‘–ºã·ü /ÿ5 èϽt§ó³rVÑÈX2”x‘u8˜ŒÅ\*ö<7¿ÄÛüjGcP+bžØƒ/p€²u'Í2"ë£îîÃÁGFÆ<òæÑçÜÛÏ-9¦Cä 46>9J Öâ¤ö_ŸÓ9úÑ›: ÄÙ+²žtGW×áà)ïÈÒY-WOßln~õò›,•‹öÿô¦-Mp'jK à ØïY/ $ûÌ_º—EPž¼;%Θ­kcÉ%;: ÿ=丧_£')KO}j’}tb$ø/ÃyMuŸ["[ º´¸Ý´<çþ /Òêée©ÍÄ91d<¡ý6ˆÖw‘]¯# X»~È?–®QŸ¾|õú°SÒoò˜hD;ì”öÅ—ÇÓC€= •W_d!Ü`ÒmÑé)yñ¡rQžƒÚ†“–Ø„ÒcŒ6Ò¹ %¼$9,o{’™—œ öEµ+-«$bg´˜eÍ©?B}ý#ˉ0#’.â!>´½ Ú:%¥œRâéÖ‰B|žÁ(Kæèÿ?˜"NJnû:'ÎhØ öû!»T#Ýâ ÄhдM|IöENEt‹@zc öaqLŸ5¦‘‘›ÖçñæP+ÍXi™}1G8àèï«¶¢°;q8Ñ4uÑ2xŸLÖàÈùƒ'>…Ïøg¤Ã=²DÝÖýU3µÚÐðäU"±’SÇŽl…ÊU~”DœàcX{mãÑðK)TV½Ì¸»dìÐP ¸Ã°=Y‹!ázrƒ>7ñsCú¶kË+Ýåš¶¥Ãä?m¯4¹=ÆÏOkRÝ”†Hã*0½²—†Oì\zªþ žm,%}Ó¶€¾ø2H/ÕàüvJ¤*3~‡Ûz»¥Íó²×É =kä Ì;äZÞ²öðNTláU?~µGW±+¶<\ùu!sª§U”ˆÃ …NÀ[ )LCæqQP¨Î“)+³¹Ùî³µ?&Qwpò%´~¦QÝT~p×q/Å]OK÷ÎyEƒH‰a&Òn k$ü6‘ IT^e£uÎ]üí¶;d´–=ŠJ¸p~œ–#8Zºó%‡!çÃÂZXœ§qxÚ^’攲5\z)üj·+G+S±–ªìYzìuV-MøÅ{J® ôB—ohqu“¥Kbq++*öµžS¶FI¿ ùiÙ7ßKÍÖ都V·LrÙÿqHÑ%tÄ­mÙ(m±~$c îÞ“À.úÊßYÑi‰À~7äCnoÓת¼ÝBY_«0寧%"dì1š*S‹LŰx‘ 6øéÝ|¶“i9ƒŠx2£m™q–ܬ–MŒ¦&¦XLÜçêeíüËŸÿ†;SdlMÛQöå–“±¤•vèÔ¶ò­§¼E°ÉÌs¸µA)EÉ·&S0$·Àh¬Nµ/KÍã]!²ºµtóiíÀ ¡ªã úä$½ŽØ‘Yv”ÖX-Ï“Qàæ5Áá ‡¡ä"q#… qz½¿Î>Raˆ>PË6¤¶@címKQâò¿\£)=Ã”Š“1ˆb¤eó¾–­§¢¯éÕùH¦£W8¥ØW®‰ÿ² ² $u©ÐHu{1DW}÷2Ø c,…ý°o‡>(J²˜°#ëñ¸õ72Æã¸×Mm k)$K_7þÜÎ& Œ¤Cól’9@ÄÅq´Ù¶ ;N£ºz²ª©Óma3¸þC}Œ-ʃ²Òí°]³ÈH³\ÊS1ð`ö§d¸ ±Iyw}uÔþʪâ5¤Mg:QeÌþVµÇtÍF*8fëHfÁüHìý¹Zñˆõ% | ŽFq#Çn]íU}T>àø‚ã©2EP@ÅR?3.=cûYLÇžªXÜ$ °™#ΉÖZîR&xkÚ‹\ËYkUKVbËŠ´k‡?HiÔ~ô#2˜Ê'X¸%’Ï ”_Ó¸ýÕÇ*ÎÐ56@º:k@ ËC¼=]ãýÁ¼Oïï)²’ê¤nuŠJ±Nt^b›4RˆÞª€þµ÷ Ÿ±”ÌI8ÂûG£p ¾wùÌÊ}êh Õ²=dÁº¨Õ”–4€C›Ï=pšjØ£Ë×½rM””×d;é4бÒ{ÂZçgX‹ÜÂP«‘~ùg7É*NÕ²¦vUÆ&ºëïÒÿÝ£puñ8VVYÎãe+’Êmö\>]¾ÛìzMCÛêô¾ÚŠ1§ÎAI õ°,©ÂÌŠ*j<ñ'¥ä‰BIì×@eÒÍ5Ç7˜WΡ{L˜0ˆô ½ŸŽÀ‰8¾ñÅžÂ(HÖÄÈe¶5b‹ÿ<º¤¿íOhY™j ŇöÕÕåUvéeôãmðo.,)ï0°›;JK„W7bì[W‹ø9‘t}Æa‡/³ËÕé™ú?\b6ø6MNbm¹Žr5㨟¯›1¬Þ¶ê‘3=×ͦTûó}ÕËxÌBá]¸ÚÔW¿û>rsƒÞÕ›Bó–úrZƒÎÜ¡CÅî>¸»Ø”kÔ'ë ‰Ý½oßž½e¥1Õ®êXÐêÖûEçyϤÞZ>•Vg‘gU¯je‚ü’6AĦ­­óß®sŠ€üê33P‹Îw.\£xù£ÃË,†‘@ç$×gÆ×@!ä¤íÊÈâ/‘¦•h }½WwH—µÍÍ/CÆr…Ú^ Zù,º#«¤"V !;`¼hª©½ ?`¹.ôáPq¿åòáâˆéjR:G˽ýs÷ËŠÚ¡ê‘°zi˜?ýsAÉ×}">;ómï #鄌êG “V ÄI^tÁRu—èž•ÆSÃÁz9K 9Õ³éªpÔ÷°ÇëÛÁóá£4ÏÛs½êŒ|9­¤'±‚äúV§§›1Š&ó‘c–Íæ Š«(ÍÊ(*xFlí²ãvG‚ŽOˆ†íj-wÐô­1Ý|Ø _‹ÆpîT oßM¦¢¯¾ó¬ 7;ó*ØÓ¢ …ày¦°vLÕe%ò¿¤4r¼ #¬užðG o]¹¾º%~vÆ×lk ¶Gû?U ý–Kþ5èß¶\:\9íÏ‚þüœÇ=_]?Hí«Ö„¸Fþ86Õ&€‹›ÿ^uŽÌ±ªZÚsd¹Kÿ­UÓÿëß©…•.!«yÕíßm5µÛ’nPæSµ“B¦|C[KY{}F&‘÷{Òý»¡ø!Nùö•$‹,ˆŠö·h‚{ï=ÒPÜ аµÄ¯x#,‡uü QQ¹aKVŠØß,)ÎxÕ½aó»Œ`¯ÑXPPW2£ø«g[ÒßyÕ<Í6ÊÎn§ãóÁ{ù©V~GwÈšlÄß-ìîøˆ ÒÌ€•›Ã¢yÕã–ßËÌGÓfü£ït¼= {]dÑÎ},MÁDƒ.6ÂkÉêøà.>ö8à ñâ—Ǧ¬Ñ<üZ–\,sî ñôÐÿÙÔhZ © ¹Ž&Œ¬ú£-é‘'5@Ó–—Ë£‹y64këñ¡€ÖùàwJ¿ôÇ¿®à,NuûZ9ÚëÓ"»I?Ž[ÝL²P¿Âᬶ.y¡ùT)ÙïœÔœb:ø¯·ï_ÞZ,˺.Bz~ZÖyÿ0}€aK°ÖnÝ-†x ètIÝ’mGX> stream xÚ]PMkÃ0 ½ûWèØ1F>;…Àš.Ňî+)ôêØJjhl£8‡üûÅnèa ôôž¤§¤ân´‡ä›¬lÐC¯"œìL¡ÃA–å ´ô[³…cIuîSŒÉï±=þðçê´¿dù˹­³7PØß)íâò­æ‡f™<ŽÜôŠ‚Á*^'Nžؽ+ÛáSÀ¾H!i3Àî\5ifçn8¢ñ²²Œã²ûMÒ*œœH Ȋ4-¡¨ë’¡Qÿz›¢ëåUÐÊüÌ}ú¹TÁßÞœ‰Ö½ñ ÑQX® >þä¬ ªº´mq endstream endobj 1737 0 obj <> stream xÚ•YXçÖžuÙë(˜8 Vì½–clX1(Ë‚ ½#ˆ”¥ÃîaAzïH]ƒ¨,FMLÔÄÄï5jô¹ÑèFÏàGòÿß,¦ß’û€ËÃÌÇéç=ïù”1ffŒL&³\³dí’ÕË&,t\à2õéÉŒõ$ëe³°®D…ø#¾,‡÷¹8Øl8ÃÈ`ýd~ì'}Þé/}ާª«3™Œ‹ˆ{ûi“íí_Yêãånc·}œÍÔÙ³gN´yÅÞ~¶ÍüÏPŸín6ŽnáÞžnáôç í>žáQ6v¯y‡‡¿:eJddäd·€°ÉA¡^¯›héîm³Æ3Ì34ÂÓÃÆ!(0Üf•[€§MÕ“{~, ÞîjãäáH­µ°è5‚ÛkbßùÜ Åù†^›·~¡\ 5;€ ”õa"Žé͘3}K¦ÓŸÀ d1ƒž e¬kf3‚ÉŒbF3c˜±Œ3ŽÏLd&1“™)Œ=3•™ÆLgþÂÌ`f1³™Wf³YÄ,f˜%ÌRf³œYÁ¬d™UÌ›Œ³šqfÖ2ë˜õÌÆ…ÙÈlb\-³¤#cÌÌLvº×ô^¡½.ȧÊå òjùf‹ÍÒÌ~P*î(“X36œ}Æ…r_õvì}Þ|¤yŒù…>¾}.Yôµ(²¸ØWÝ÷±å6ËCýÖôgú/ë|Àª_ txlÐkƒ÷œ4ø[~éAC¢‡œj7ôèÐûV«;Öó¬ 3v`ØÓ—_jzyÑˇ;o~LL·ìR€ŸŸ¸ŒUÙ“'èñDŽÄµ|õˆEšç  š"ýâ „ÛQ¶ÏÐPÓvrëûcˆ’Lô!}…1óÕŸ‘çj¶Fêë/BÅ(£>ÇÅl]¶Î[E®üþ8™}¡Úˆa?)˺–ó‰º iiZHÈ Îõ…xàHbëIz«þ­?>eÉq4ÿˆ}øeíÅì·u©è@—žŸ 1á•1ÌZ>ŸKøáØeìWþ ɒ®±6ÂX·Îß­c5DQKd< Èÿdé Ó½©w®ì»&”A‹¶>* 1& "wWE<7…µ¯¢X…óq”¬ §_Åérœ-^àµs}·&&étÆ%&dw­?ö=é¼-Ø×ëÎëˆÐå%¹¹&ùó‡-ñ£Ÿ´Ý”TyýOª,Åe$«êùÚJ2÷ä¢9Iâ! ô»Ê‰š©qHßá 4CEaaFdq…Hi9„DQ„]BVY då§d Ž ÜÞzÈnO!ª~%>þž¯£ž\é€KÈäBªiE—ª Ò@[…fÄÌHô½q™ÄB£1y¡)„=BèaoŽBö\ ¸Trž¬ÿÉy{9n¯àuA©³f/NNÑj!Õä{ÑÛ8ì\À©µ¿ñ=+‹þñ¢{²Bì”Ó.âï‘Nš:üL²FÉq×%þo³‡‡¯¿»»ÁÿÀCó!ÁR4È:ÐcÑB.ã%þ>` ‰' @’ÇO¢ÁxŒÏÀ˜‡}xœ÷ƒ°¢ÈªÐºèR@ \€s¹'Š^Ê©†8S<3Ï^…U@âcb"#ƒÂ@RF1ÓØAƒ‹ 9>ìbùF-ø óW9ìn—ºBùtf,⺫‰JͶ뿇#GžB;­p2œ•$ 9žCëãFÙ)´F',õèÇ»)Ó#’b’’çÒžåÈe[ËW-)@ùŸ‡ûšÛ\$VD1~ÅÄõƘšæÖª·h÷¯òÏ:øvgVp÷:ÞX¨‚¹ëº«I‰´Jê(ŠÛ-Î’´j@¾u··Ê®b/tD[9ãMÍ`¤ëV°%Œ*–eºî3æ•4Cw(°ÑÝ-0ÐmÊ£uØgþÕ#Ž…~C¦ÔYÿáøœ»²ð,Q³ÙN¯n<½·ñ­ jQM¾Í9í‡>làî€C€ Ò¶ø¹‡ø„h=µ]¤.M›’É´ìvgC¥`Š(*ârÒ¿¡L..Æ©üãxq¾²N—*DQ'41äA÷›VjÜO1X¦fõ¡ußC¨§1ϙē‹zܼˆp’៴¥¤Æ{ƒÐJŽ“ÅR~_R=”@-¼ç5Wœ8 5Ü(Ô: }S·DoŠw†5àZ°¹,YŸ®ON »U¤ƒÝñ•B>è3ró ‹[;nÑPä×ÂHÒOµVû¼Çu¬n ©ßàµyúç3±N~pû£å¬Ûd¸j;¸&©ýLEz‰á]4oh•A½pà<|˜y¦áÝêöã>‚ hM¯ õL‹‚`Ϋ>¼e¯¡¬ãƒíŽ Èܹ¤˜âA & Õ·WÑmÆFú‘°¶ÏàPF>àW@è»i¹±¸yöë¯VeÙÕ©1â†J\^…îFÙ´3Úå] ]ÓùÈÜ)¼±ÐùèÒÚù`M’Èd2šì î8ŽŒC-: ‹–h^–’£J #JŸH&~ÃTXÓÊÏz·ùàÛ’ËGN»ò(ÿ(\ìëÖDéóhuq5 ¯¥<¦@ü€:9 ‰/S'Û~qr6‹kÑŽ:ï‹d"ö#N*âôÃP^|€ãÙÛpÁgÿ†F÷ŠM@x ½c6xoöÞ²Ôw*E÷®¼v#–•äZálêÓz¬¡ÐAÆí˜KPX¶ÇöÓÊûùîóTíØä¦|#Ám‚à„¥h¯ÄI`X^Bx®]ˆ Šîï©9÷lÕ] š• Tp#ý~!xlÞ5—ï¾ÓsFÙ¨G%ìï¼Ǥ1a'Ùû¹ÛôèX´m‚°q¤§AÝ‚bÒ—ê°|ÎѸÅ= x…â\Wîæ¯•aZð[µ VYŒR£íh" h{hdœ‚…8»bǡÃ>´€Çewþû8c ûŸª:Ÿ—êÜç÷^X&p…_ª²|.§Þ6b¹±ÇÛk’ea]Cù§Fe µÌËË©eOI9¹†åOìožJ9¤ÿ Z[ŸA#‡-ÆkäðïŸR¸Ÿñ¢FJß@5 ™Qé¥ nncÁKrÞ¬û1S³­úGÐÞþZ¥ðšQ"lösùXÉEñUqkQA^î°6²oR†³5`.„Rl5Ôêö&p:¶Ûœ\RàÍ?a¯/ûøKô$-úô¬TH³Žß;5Û¢ÿÚšþajï`v¤íI(¦E7óW¦tq¦rKvˆ&¯PâÇÙКµ6*7i_õ;ˆò…âûÔ‰/þrìñ‰„æM8ˆ'Éâ[‰U‰4ãÖćž=¯„:]HZ”6RG9{¸ZY£¿ Ÿ›Ìgƒéô Ë ÌÒe@5'žÌ`±®ûÙžøì„2°.ƒìü=ØÔÕË*CRª¬×?}ûž˜¯­øà©‘ø°‰œ)ë=~SŽÈÑØ5ƒO(ÐeDÒ¦ ùŸ 1°bR÷ך ]X×BvJ¼ÎBuFÆÞ¬r}eF9­O£2\;‚‚^ƒp•¶žŽ±ÚôÆ´ ìäºgЕ떦­««©;–S²ÓUƒ_óèMCBIÅó±Ä‹x¡ ±Å`úeƒ¶è%nrž_+›=ßs½œú¸LgóÍCŸt\¸Tw®ÃêÆ­ûW:ÂX°‹ŸµÑ!Ôg­z®„y´èKÚ°³“ðˆÄ®ñ}_W✯o=Ffâ-2[Õ=±'ÊßÖ2ð8f/Y3ÉQa'ÅkC„÷°Õ8Ð$¶ mň{%G^j5\‚w¹G#nG¡[ñ³Ø'Tì÷/ q?;èöQ„MuH“3Ké—ûqŸÞ7tÕÀ}Wx·¸,)3Nµ tɺ¸ÔþA”K$ŸOºÇ ŠIéLþŒ0”ØVò¤7¶RI83s¶ÓZÝt2‡b°BcìbÊÎÜÅËwå˜#®äíªÓ/A1wÜpúðno®"C3#@W\d֨Љ­€œ!Òu‰ êMV¡UŒ§2rÞT"SÁÒÖÍű'64¤< ´³P[Q×.œ:â5b&L¢jJÂ1ºrȤUéáØ)=K.r ##?¯  ¯¨®îý-7â> TÅþã§OUðÇ»DVGTCëóË2¼*õ™Ç?ŒUF’ÊpòP–{ Gw½ûK2A­¼¦ û>ü+\“Ðb‚øå5–¾Ì™GzI¸Ûõ½Æ(Š= +Žx›Ê»ø]šsÿei`ÉÈ1«‰9Y˜†ÃÞÄY@”©,±zJzát¼Iæ@Áòe3]bUW£ìy³ø|N¹>û&pFv#ª5 LªÂ/!VE7mZ"y­{Y"ú+¾1*ý´“ÁÓ¼éÐMöaÈðn†8ЗÿyxùM4AÝMà²wg&Wƒu5dæd—âÑÍ v»eG›žVÀž¬œ ÎÄm¤n}EçbD~Q–Þi½73 Û+E`ùOïÁÐB8M2†¸XÑ©á¡øB‚éIàîcÁôýCÉ9²…T%jÒÓ½Ó­Cµ©º à‚%¸ Í7‘6\ °’ˆD+\J2³$2ôˆ’¡Ç¦÷ØŸíÂ(µîòê’ñyEÙy®Â¨ Ò®…€ …¦œ°u°êâ“5Vd-i#ø¡â¦©Ñàé3ÆdÓ}õÝ ‰6¡û÷ÐÚöZ¨Œî¹† ù_P)UAÏ=Äb1„×_5œ9u8/×´ËçiòSbGÏ$ÖË kOuÔ´†¶n!*&)Iº‡øó‡-EcŠÝëqºA¶åè.íIj<Áß[p†Ø:óÔ™n-QõMUmT$—ï.0äÕÒ=‚ûäçlÕv–Î’iۈܹÈOUƒcí•ÜPÿS8®¬Ê…j:-bU+3(½¯áˆì?if”ß&w]æ¾B¦ùÛ=4ÛŠƒ8Ì€ëŽK·Ft¿F®å<™Ÿ¤P³grÀCÕýÏv¶¬¢¬¢´òøú“ñi÷ OoR:|Ò]º9Áæ]î~ÜWþ­£'ÊÛéÛþ@-SÁVX¶Ãßus‚,Gc«©¯é)­âÐVYÝä—HSÍ{ó…ñ DƒN—ªIÞ¼t … [À‰‡OgàPšsZ›J _§ÓêÒÓãb ”sÛ·»®ª­èÈ Âf¯#‹éÎÂ’—¿™‚cqj3r9¯]’4eÓâ#‰CöøC¶²;+¶5:PE#ÆL#6däÃh­: G*¸ ,:d+Œ¬c2P‰"]A»ïòn«\⼤û;ÀA«à¼SÝÖ|êtv ‚Ž(Ã6êZ~J+:7âëY3Õ™xO.º`_“ u*hJ¾²åˆ[»sÑj‰eÎM›Çö8'~ZV)*êzJ\Èòe®ôÈh¾tJÕh¦?”q ªµ¢å­j#<ƒù¸Ô €^—­IHÜ Üö–¨½Õ­%‡¼ÚÙ¹'á„Ñ¿Üê]†ÆëPK‹º´c“--øÊ½+-·OÖ|Þfßã\Î 9E7lšú“» ‚ã­šüÆÒÚ¬2}z*Ýq⸈â]{÷WTÕFµ¸ jpˆˆr¯õÈs¡Þk__¬ÿ|÷vŸÝ»¢¼Á Ô5;ª¢ÃRÃa çôÑR\‰¯Þ|÷Š_®n -t­]Óè*µ R3Ô9š6Zì¹%EöÉæ§Ã§o¿ ŸÞ¾ [¶€ÃtÕ)âÊ_¾·ÁÛ{5±"V^§ÚÎ…•éNV47Õí*n•úªOó߸#½„1°iQl§Ão•¿®ô÷M1¹D©Ëåwš>,2×:Ïí¯ ›'úß¿6Ý|Q<þO%eCŽa]rÓý—»¿§g³Ï!ÓýYD–Ñê;mª¾ &!ŸB}Ã9SÜEŠmxŸl6ˆgMrÖ£ù*©€J:èײ}»Ÿßöí-~¶´ÈR“¤2¨†m5 8Þ¼€ßÏû¸ 7]sÓ¼ö$u[Ï?y×-šØ{'(‘›—DûEßZR²&ÀÇWšä^J2÷g©/ð»$Ë®Ÿ8»¿zçÜ‘äÿòšý©Öþe¡-GoŸ7þœ ÿ±ÐÄÓ;‡õ K¡t ZA”(NyH¦’™ÓG’!dè½I8gÞ~HIÑ“Õ<Øû† ®*Z«.7Â{Ð\TéÀ•›;y /Éz#Ž6HÐü„º- ·ÈÞ×*ëvv„JŒkø³/p “ï—(æ»Dn÷ãNü¦"rk³ƒxˆß´³ôpv¢½9z¡Ë •ÔÕþG(\në Ù“'%óÀ¼!§ao!6>y7Dqî†Ýuu†²CÇ74¸ ¯C¬ ¢\Ifý>ˆ¿E°7)ôÛ4ÉÚ>ÁèO¤[©y¼‰•¦ÐrŒILKONM*Ý‘MÁ<€Œ2D#°ÿÎæÔúTCJL< nÜëö!¸ÀÊÒ )•ºŒÝ?Rö'Bª‡ÊÒ½V‡½ßÊ Oâ€B:@àhˆ!²Ü}ŸOöºüoÀQî£;P% ²ëC3âr¥ÝÛD–-Åe4›¬çUʾ£ïÛ.ýqJJG¡³›Rgçjg—Îù^'ͬíðKŸuœúLètÛÀ. ôÎ×¼˜rÜ¯à ŸŠ«~žq.ì¼­«æ¾‘VwRÀû,qø%j ìØóÏ„Zø Œ×¹ŒW•8ÿ—yg&Dj•ÈSú—$Zò9%Y¹g%6êEÙ¨{0e¤6ÔW§&KlT—š@z“|+Âã>ÅI‰.†àÀÕBeqQ÷À¼]úÔ°.…\}^%%=²)¯îËç”eæ¼/ÉÔÆ—{œi«góŽAœIvZÂRdEXlS¼']{8A°‹6Ò3§Ṳ̀=ë2Sòà ´éɺôydµa°B:®]Á~®`:‹“ºäDeI ·€& ·ò)–S^š·SúUâÂÙ9åÜOØ(û[ŸÑTmœ!¬*À?,Âgs‡Û x÷3J!)UƒV±…q¶\\)Žçó(©€l®"v äGe> stream xÚ]PMkÃ0 ½ûWèØ1†v -] í>’B¯Ž­d†Å6ŠsÈ¿_ì†v@OïIzâe}¨­ À?É©ôÆjÂÉͤ:ŒeÙ´Qa«RV£ôŒ—GéOrDàïo—¯Ëé¾<¶u&Îm•=ÆþJi°ßêúÐ,SÀ±¶½ƒ> stream xÚ­z tTU¶vÅEÒQ…±ï aF@AQ‘IH LaÈ<Ïs%©¤æyWUj®ÌIeNe ! ó`¨€ Ø€N­¶¯ûµ¨çÆ›ÿ½w*[}öÿëß½jåf%ëÖ={ïoïoûœËfËb³ÙÞ›7íÙ¶gë3k·ìظd±ç?/Ç1Æè!Ù8z‹~šMÿq Mrè'Ç’÷7ýo¯1d±Ø0És%ÇWÖWOx®Óñeþ±É¬±l6‘S‹/]´xñskSÓò2âcã²üæFÎó[²bÅò~Ï-^¼ÂourtF|dxŠß–ð¬¸èäð,üG’_Pjd|tVžßÜ—ã²²ÒV>û¬@ Xžœ¹(5#ö•y üñYq~Û£3£3r¢£üÞHMÉòÛží7jû¢Ñ_kS“Ó²³¢3ü¶¤FEg¤`;½½Æø³æŒYÈ^B¬æ¼ÁÞÈÚkk!këYÖbÖÖRÖó¬XËXËY+X+Yñ¬5¬µ¬×YëXo°Ö³6°6²6±6³Þdmame°YÛXA¬¬¬]¬Ý¬=¬`Ö^Ö>V*kÍ›5–õ û.g§—ÃŒ Û:öþ8ö¸|î+ÜÏÇ$"‰o'T>öìcÇ&L|à%ðúëŽ{˽<~ó‰ˆIÏOútòºÉïùtO1ò‚xßOÍ2›¿ŒÐ7Ø÷oOí˜Æ›&yÚ÷é““|²žRû™>vúIÿ'ý¯ÎØ>ベÛf%½eÎs.ÌUÌm¦5Þô }ÃEûºÑŒÛM.vÆ]ôŹSw9¨‰žÉCû¹k™.Z-„Bß]cŽ’P]Wê®èt€°ËAAŠA§Sfå¾D:4”P`2KãMô_o6˜ð}䓌œ[ñEÕ_Š/"oðm„#šºŒPDŽÙrë]ï3Aɰ:*™ž·¿‰›/\± ʨ Ü7˜!é^É^ñ^_EºhW,h!Dͦ’Z¨"\yvaF† nÿáÜvò38Œf7¢Y„7}÷'î-¼UåqsŽ3ä=´”g0ë‹ÀèqBHpsÎû‡qØ÷Š;¡ý¤zÚgî¢×é;€ãþqÛQ°í š%pêSÃeºGðVºËºßcþ)äfØ ß·59JÁL!5· ­ƒ­¦êرâ.ìTÏÏj¨qµœ]ãØG2Ó üÁ¬¼üÜ|)䉬PŽ‘x}˜% ‘…ˆC|eq¢½q l(üeVè$?ÁHø5¢9çÑ»|¤ændþ"Ðäåïð•g(²ÓÒ2A ¹a.pV¹* aäëiYÙ‰{…=ä8sÝ^Òy¾a§qf9hª:œþÝd”„ÆeÖ^ó\|þ Ðx’€è×7î‰u:P£ÂR‰ž@Ñ„jUOXdF\Jb´š,‡ ›ÝN ÍSÏíÞhð ¬I£¿ÿÎ5½éŒ±ú‡ *6Zpœƒj `PØw~(¿×==HG VR¢×㱨JRÌø•Ï3þÌfc³ü ÐöfEp݆Þm%@˜‹ŠÌÔOž{ï8‡žLó`Pv1ïxÆ;a…@(Õj%… Wk‘ž^a]ë€y:px<£` ±áBQ¤1“@ãï|ŒüÑ´ÑvÀ÷Øë€³ìûÈÌAo¡^%˜Àè4˜Í.("œ2\¾Ìn®?W-Ò*U¹ "prT8TðClʸÈs «S’Ò+òëÛܭͤ7m7êFì*62Äãé+Nf«²HI*qÒ‹ ^™¹N‘¢Qé$:È'ÄN("Ká˜ùH;óØp _ž(—®B>J (¢zûŒ½‡û{ù[Š¡Ò)!%çŠ _/Òg•z\fƒM_„Ão;fq!§ r±ÑŠfäåB3Þå ïñŽß¿Ñí®@‹>þü Ư:½Š™»‚ Ù$0‡õÝêA^²v‘R¥R’žHêµfq‘ÄDJÌô­b©©ñòû(ywI{‘fÖóË熤…g†ï^·\²£Ô&Ò ƒÑam¬8Ø -Ð(¨Ë¯Ïsgw^®­qxªžòT½ZXµa¤B”UXk²%dZ­nÄ׃Ûhšû‚ ŸØ_¹o4ìºvÝu΃Ñ7¼|äH=%ÚÈ­Ю¤ O6ww@jüŒ†àfí{½êâ(%Ê$eY{´yëÜC“Ñäo‘ •꯶?høn÷6[ÅLœí¿,®2¥££¿ýx¥Ä-õ_£×â¸ê,"( âSSÊÊŠ[ŸùuÇѼµB)Ȭð€ÌìªFK›«›é›UìÃô½íæ•âŒ7õ™z ™ Êtu¾FÍÌ×)×Ôw‹Rì1Ž|L$ba‘Õ ãº z¢:ß$%S@™¥HK`&…2^¯3ÄËÌ”çÖ©5 Mb> µEd%ÍPêtXmV›e*  Ú%ŪZ©KÃÌã« ù¨Ô¢4h( ¨u*mˆ D¡eO)SÕ5~ªV©‘¼Ê¼Å×itrÐR‹ÖLZÀ`´XNœ;ck¢»*n';Rüs"CWfÇ@,l­Ò}mÔpým•M5U¢’¬ÝÊÀÄ5½ï£)è)4 -¸zóyêDäǤŒÚLû»¾ºÝUÇF^—‘ñzc+Ù̼@ñ…¦[ý(ùR%à‚òL›Ø&€$8Ç<-ˆJßD&ºÏ«ù¬öíþA÷¡SGÏãûZÕöXbŸ*BQhÍ«o«hì<Ó@­€%Û×ÎZÆxe3Ka›öBlËdäƒ)dþñ´ï˜qäV K1¨š®s¹ÆF3élšOñ”˜qeXÁ‚©G¯/²¼fý¹ú `žQ”§–¥”©Ê¡ J‹J,³™•:mÂÆÅ̦\?Œbv…¤œ<¶k›yõ ŸôÄI4¶ÿjc¯­ØÃ¨žª$UAµ¦@ÀÙóJSªiSwª›# öÊ·í¨9ŽoÖv)¨0ÍêtŠÂÑÐ =^ÇþúøÅ3è•ÁÒ>= óþztàmx¸¹¹g3fÎÌ9$Ä–¤ÚEf¹^×ɼòrî<!–_Ûå©%\Îh< -²AƒÒÕ–UEÌø„—W*uA-ñöûopêPÂ6fÒz%©^a&*>¯.»&?㥥/=»9´÷ 7?ùë‘Qƒ:nÿÅEϬc?h¯¿ŽŠ.sè7Ñ /}zF@hPNú¾Ý[0SÄ[DMG‹Œ]`"Jäéñy)±»úÓ.»w޼ó74½­ƒÃD g˜©Ì“Œî(sC꘱ØÔsp¸Ë}„`ø›x¯Ã ¬3:›Ñ´ÆãNWï•w8Q¶/lm#eþHy Áöºé UìÁ¡?pÐ4Žöj˜:N+Ñéò1š½ÌAÖ5ëÝ-Í^þ&ÌÇ8ä ×+õ±pƒÍä´•_G“ù(—ë`VŽdŠÃ$bÌãN0’]ÆÎöƒm^þf'Tc}HíU[6Äåë\:£„ V(%DÃáÕ0·Ç1Ñ\ï¡ lÒÛ˜ÒÝ“é{Ÿ&}âóÍ£‡y¶ƒhÅù÷®}}Ò²Wf1\ŠásQ¢Œ‡¼Þ»×/1l’¹Äz‰*Ý Oa)£U2Ó†»ø>ÿ)WÊ×!|$AÑG\œÜÞ|´¡­`ü˜[<æ n-˜v½ùjã£×¸_˜_HŸÿÒ f [h¶{h¡›æÌ:1´Š§/Ò›q5è¬RR‹e¬Lòæj~ØÕmeÁ@0L"“͈™¿Ÿ‰H´±QÂQOŽRJLùf3ió‹@,_zùSp¡-¹Æ\ùóŸû?⻃ϢŸÔTd¸&"",ÂË_! \[ÓHhE: óôp7_ž “o"Gy‹Öâ \wwo×C &Á°8(ÜÍ#Q³®wa¨“CkèxèM´°¦òÊ[o›}­z»ʱÖ5)Èœ MV\t¼—¿R¹›ÎD•èœ*±¼ü¡ˆù–éçßB×­-VëEð­¶A…CaPPÑš¨Èˆ¨ÑoýZÿåÎnã¡®îCØXÏ(@° ¬6œ±ÖSE;šÉG.p¦ÅìÑ ßÄhÈŸäÁCÆŽæ–&œ Ö¢Rœ 2*V/¶ˆÝØÇñ}¤9ôT<ØÚÍö;@عå ŽjÈ~͈ðÈßf¨§&é׸.ÜÍå7Q"§5n“„ÓSX%j¹‰Ï…1³ˆ•?¯¹¦Œšòö/s~˜DӼшžˆaZͧ˜)\Ü A’Ç|1|Dh]ž±Þ—ñýU.œ2ìäE‹C´„\¢Ë“™5ª¹ÍèniwrµS¡SÛ Úz(#†¼ ùÒ|=÷üð7¬¤JÁ·L³ƒž0ÄÆÿf¦_uÕ÷GL:;;»;~‰‰,# $|”@nÎP}‡Wv鬱IOúòÑšKÐ$&Æ'yù«F3ÇFÔZ¸úeZ…VÎŒÞÌgère™NŸƒýœô£Ÿ–Ó ÷0‚V#eøÃ üÂ1¢¿ÝOíä£Äá/Mzm øbþÁ†íµd×-¯g£¹ŸÑÑ÷8CMt ½8ëkf2ÎDâ^ZÀ<ó¥zíG1˜o•äðœá7y‹ƒ>D)è/A~×÷©/?¿ñ1ºÀVÈ?Y`Õ”ç9 ÙK,^5ç¹×^;ø€„SƒÑ½Gº:dXºbi¬Uìf¢ù¸=j0ÿ+MjϘ 7Xíg}‹½¸c祂“XßLF覠IÑÞ’á4æš’l*C|i~ t~ðé½/ׯ&!]§Pgë ù?—¡xg:ØC’} ·`V½ÕÐå@<¨)ÜBáy,W¨•xæ^Bäù2ÙFcE3ZJî Û¹Œ•2/YÏÇuè¹]âÑuE£Ñ`ÐëíõGÐôÆjÄà ·‹9 Z™V‰›q_'“.ÅàŽöN0Q'NOœ<}b¤W9¤P@p…dÐ@ªQU„{ãH‚bzÀð<‰[rÈû¿NÉ š¤Ä„FÏ14?‘áM_¼ˆÝ;Ú>§Àej1¹þFÏæÿ„9ÿŸ½æ™á©|y"ž3¤ãuwý—$òŒÎÔ4fÄÄê¡éØÄè¡9œ¡lú ¯ëvG‡ÑªwT­MBf¦i2’RðÃqÄ)XÁª+ÓÕ*<;®ZÁô ø{èêqͧôö’Ñ®¢!c"5Ññq £¾‰íPBá±FfÈ87<Ì7äêUe€C©wTüƒEO •rh íÃCËQ€Ó^[ßÑ}ÓäëÐÛ*›Â¨$S“5)ñ1 £–àx)‹®I‹Ç&¹F’—ÃÌe^á¯Aû@¯¶ƒÞ,U•FÂäЗÆ(R5bò‘A§¡HjÍþ†iá3QŒ4p}&AëûpbPäv²Ñmlj;ØŠ'†¨²KôZ*Ùˆ§?;¦S»ÅŽ3gäÃÇóFê'Œ\¯6¨pciN^,®™ ˆ‘ÂC#ùq€Ø j‡¢ò®£¡ç9C1ô;¼#ouV-²yœ®$ô`„?)1ùG§ÍT¹®D‰gŽü¬4­†Ieªø Ð)ì2}kzõÅǨ\"G<Žù©ÇGÀ®°d}Ç|Ì7¨ JÏVB³T•+Ú¡Ó¬Ö…?㯞Nlð¨lÊMJƒr ¬Î£–&çQ[«½ÇT‹udã“ün::)¨šŒj3Ѹkž‹Ï¡t6Ïq®óÝ·O;õz\‹FE‘Ë<ÁLd&ä˜Â{»êÚ›Z²ì9d>äɤRÏÆçï¹ÏŸ=­J뚌XWЫç}>@ä9övä´Ãoß´¾‚êøE%8r¦ÑÝœDPÄëT„O_nobY"&Ló³€™½¬Ýû”Ïápu×1â4²ðö3Ûä‰[VîßýòÁf Ž»Ñ„ŠžºóýÇ»8\·;œ­N¥UbKð¥ ](¦‡Æ¿…ÒÞá ³CKm/Ú”F9©©N£›+ç‹={‹¹„cuÔ ’ ÑàN0w˜âë4Òˆ&–÷¬¿Æ¢ h>šó}À±2âsâ Ͱ7/#¡ú} ÛÚ›×R †Òª¦®Î¶N úìÛ)Oc&¦lg„­Û£V¡Î[}.6s …ßãÐëé?ð‚•éQèÖ4Ôº:…ulÆððP>{îàÆOДþVj’;ä¤T.]½ð9u>;3ú(8Õðmýу—·÷ú´¥AzèúJúôïs}#â¸ÓÂÅ(¿ îRs-XË“'m}iÿ5+Ôè*RíB{ ä‚F§~„Js¡—p˜¸W‘ª“ƒäHÈk†wŒG+oµÀe°ý1‡6û33f3ë–]öÕ? Ñ&É»‡(è´÷Y³‹×‹^üÆh¢«&-~:³(o4zöFçºÑÂ?Ï\¸ËAÍôLÞ‡ÜrûC‰¼Š[òž±¢ôšµÃqê 6¹Z[,LVf‚`ä|¤®®ª½7¢&‚œÌTE|3†¿Ñ#[8®¥Ôîšá â-Òeޝ<ÞsT%…\£¤ô$!½9äèF1–ƒž`Ü|颽]¸ÜNÝM»âó-úü/g¹8X™“ï¹? @I樲:«ñÜT,«LÏK*ŒŠìÈ»K~ 7ß®¼‰Øô&þÈFkÑh±‰!K®N!|¾*lJk ÃeÆcŸ¾ìÈz\lßž€Þn§“¸ŒJx!Ì&yâÖU¸Øvjoâùíh3šP}¤îôá¾C@œ³-—S?Kµ{g+Îÿî"cæÌ×iu2<°T’ÕP\nt•¶ ©–F“Ë\mrÙê -U-½¯á"7„äP°%”™X)Š×È ‡mŒ=úEšgÉBàö[ OK›· ¤ºRœ…uözkmÕ©n4ˆw¸ö’ ..)Ùs3j¿ïÉhÊÙ#gÂ?ô¡Ñ]4ƒ÷ÓG¥¤=ƒ%/Ô7`9XÜZÜq ½Ê·7a+‰3Ñu1 ã™y*é¨Òc bk­ÿb‡C•EA¦$E‘›ü"_” ÆŸÂh5Î "ª6âä—­h~éó©ŠÎâÕ ¬…9i‚ÔŒ*yIUce9š—¶Û´c͏»(îÜþ|†ÑUt‡·¨ Jˆ#ɽAsw1s—½¹¬îb×,ë Ùy5¹já‚áI|Ñ®¨U[  ­Z}»ÃØ‚y÷Q¦Ätä&oÂíËÕ÷ŸoÐSC+xÙfqFff¦È.¨­­sÕ‘£õ˜ÒpíNñ(ÒG. ÞûבnK£Áv…ò;T—r`›g“]S8²Ù.%ÖÉè ƒ«ÕQéê,9?zDüˆbD{rׇ‘¦­©¢ ÆÒ¨7™ªñpX WÖ5¼i«)©®npŸ<Ô‰^®PÅüÇ#îú¼¶r„…ÇGnß(Æåã<Ày<Äëayî÷û5iXÃשU¬;Fo;¡ª¡¸®¼½äÒ#«U J‘ÁÏ_—žúsnôIA6Š=¶žG»p 壵¼ÑÔ/>guÓñÞ«@ôÞ Ò)ZÙ&¦˜¯Uê°ð!$Ö‚*Ò åKezžÿO¿÷/”ÌÝmUûÉuš*¿º»2`oBüűøæ0ˆA–097Rè9ÀxXz“«âZå17õ"y˜Š¯1§~ÅhÏ<õlù¹û'@_ÞTRÛ÷þÍW寀}¢Ü›éÖ‡¦ãnî¼Æ¡ÍÈÍû*ðêóÚ÷Ì‹[>BO <Ó¢9$cfªxQ1îë¸Ö#NËéŽóG›1•k ¤ ,{fb@ÊŽ=!{=:ÁÊìr£#ϦÞá|ÆLÁ-T®‰Ò2¬G&•…jh26¶´¹ÊE)î³³¥¾¨ì šÍ·ä×Ex†B6šˆæ¢yÝBí…°Ø”xñ@ˆ3ã·y¯"•ÌâYÛ.Ü:ó«¢f›ôž•Â$.lø I5ºz«›=÷QêÆµÔ‡x÷ñdØU…qM¢çl—b…»äÐÉMŽò ˆ fKNEU&ü `:i±`ÄõÖm´èÊq×ä›÷gÑä·ößðù æ–öIa'‘˜öÒL2¶™„'N˜ z¥¨8'+5?dë@ì»h~'òî'áãU6Âç»Ts¬z‰Úê+·Éè:¢Õò4ÌQs~my½³·?âÐFfBÄ3»IŸà•Ë…X {’‘w>ÖVáðcR)Æ‚âÞèæŸg#ù%nš;*}Gºrž_ÔQÌRþ²¼ãrû'ï…·FžüÏR]  “çåí‹|m;æA¨+{ô†Š7Ýú0#Ÿ=–`åg§§y^²1a.rÈKd2`þ¯aúøª<ÐÊD¹©)ɘKCd‡[)8ßúYÝk5ž»*‰ã î°EqÌ\åO:›ÕÝðÕHgÓ¤ãÎ&M+ŒJ_—¾vϤœ&OA[smsÅÎ^eåï~”êl´ø|ÉY´ä‡–Ò^¼v±;%+#+‹‘EaVÔ¦qŧîgŠ˜ñ;%Ç[Ihù¸áº©Ì\ú›­MZ&€ýÄâK)ƒèå~ôêIï¡_r-:ñêO —yŠT]’¤w­ƒ÷ŠI8]ÿžûCK¥é·/Ì< éxJŽ·Æ×g¶¤öiʡڋ›O”Æt¥ Â9èén~·ùÊ!´N¿ê-D&úçGdïNŒ8D°°»‡›¾Öq¸½Ì7»ì]XÒ`šŠ4­2Râ*¹Òo—¸Ø§î¢ãw9t =Ÿ)…˜‡¯yjîÄ6g ¹öJs³Ïíµf1g'ód–ÇÊ£"Le ÷Oꢩ2+û"Þ+‹‘DèÔ’ÂM9/€2!¿¤Ùj«ƒR¢>Ç,ÊÈÈIˆêÉê'BkgysÕöc’z ¾9žªúñ-•0í…à(ß¡¡z^4³buh0û ;M&½Eï69 Œ¨:òÄQÊ ÝÝñg°‚þü›º¿þM޾õ‹´?Â÷ù‹"%2 ðß“ò>ßõƒ»¶¸x„v.9<¯“8.±/г9hõðŽÞÛèôHþ‹¶‹TB,ŤöÜzqY~ žvW‡-È,Z+åÄ šœVWS]TA…Ü%m-p@)äË$B!ó"³œ´cßjÌ> stream xÚ]PAjÄ0 ¼û:n)%vJ{2’êBÚ²Ù}€c+©¡±ãòûÆÞ°‡$ÐhFÒ¨¨E#¬‰P|§zŒ0«.n aÀÉXÂJÐFÅ£ÊYÍÒ“¢î¤ÿ”3BÑœ?D÷þXw`ôéziÙ+ho”ËæÊ£M¿-gaGœ€â¼O\bØàô¦Ý€ û ƒ±œ®uŸ‘~õþg´(©ª<ŽÝnRNãâ¥Â í„„SZoÛŠ Õÿz‡bÕ „—/;“>·,s4©’¿»=µ†°ïÍOÈŽÒrcñþ'ï|Råøšfm< endstream endobj 1743 0 obj <> stream xÚ¥yy|Seö~B \°\"©KnÑâ€ÎÀ€b•}GvJ)]èBÓ-m“nÙד}mÚ&mÒ=miK)”½BYÙFGq\FGgtœ÷Ö·óýþÞ´€3ÎÇù}ÿèí§¹¹ï=ç<ç9Ïs€Í>œÅf³#_]·léÊ%¿Š]¹réŒéáOæe`ó­ýŠ Íb¢ÙÌ„aÌD3~¸àÖ²áÿ1ìI‹-}0|}t,¹²Æ…¯ÏË„“±(6{䍯>ª2x÷$dîJJ§e§å¦f͘>ý…ç¦OŸ›•-ÉMÛ*ŠŽIœ=cΜÙS£gNŸ>'zafrnZb‚0ze‚(593ADþؽ>+1-Y$‰Ž™—*eÏ}þùÂÂÂç2óžËÊÝ=ÊÔèÂ4Qjôºä¼äÜ‚ä¤èEYBQôª„Ìäè¡lžú›•™/JÎ^™•”œ+$‘GðX|ödÖÜá G­¾Ž½µ••0&›+ÆbkÙ:¶žm`ea=ÉÇ¢YY“XO±&³žf=ÊaMa=Ëúkë9Öó¬é¬¬X¿fÍb½Èz…Ëz•õkk1k k)kk9kk%kk5k-kk=ëuÖÖFÖ&Öò¶m¬ßw±†³„löä°ýîpãdpš8ýÃ#¦8Â]4r5šúݨ÷F¯}öm3"þ0fþ˜"Ï5Ž{iܱ“üæ¡­S‹y䑃¼ÌGYêÆ§¿Â¿e{låcŸ>.zœybÏ“O=Y+ØF?N_gt‘Ìûe5ýÏU³{õ£Þþ‰Gð´JQe¾ € p]F£ Ì`Ö›t¹[]¡ªÆ;™‹ü‚ÓÊ·¥)™Ò¡7Ò­j»ºnñW¸Ž›pƒTªVCYT‘WZ)¨§Ûá¢"™¥8!Àì x(\NW³k7¾ÿqsíIzáavlþ4Ø Û²Lº–t§öÝ,4f;Ÿ¼PBJ$ÉÜ#ˆ‡ôZ™Cm1µ@)õ*­´w÷©7»O¥áHŠOf-µ¦•—Y …ŽûêZþ_ftÃþ}ØÝQÖ 5@5Ÿ‡PÝNS-!¤Hsêµ­à‡Sí7Þíðå!TÝÕÇ“è2ȃ ¥sêíP^k ˜ŽELrh¬* ÄéPh+1j£3¿ó!Å—p8›BSP¯’|Ñ m`1ø4J\b‚ÌI½„ëyA[<{É­ˆ§”Z¹6D ‰ƒçmY úßÓlôÉQò1£xh7Ç(vÂ(lGš+žÔ¨ê_5 60©½Â«ð4B¯ý ÷ q¹åíÐV[bßææC2ÄoOMʉ e…Gà“Åæ8zã4TÕÇÍÀc6à1 Ó•% %®T– šÁÑèéðSù1‘Çžþ>ÀL °¯7#[ýá«ô𗼪å‡w^ E ‡Ñ$ôÌ÷Kû^¡_„˜×âð#ZÙjœ3©Í¾í(RÐÕ–.ð l† LiTƒÚ ”Óf©=Ï̈ƒ·ip@gð =2‹—±+ø 盾©?´ÿò±ºV :Z„‹hx]ˆ‡goM_±-#¨HÔ ß³o}ÏA¯÷òšòj…¼<¡°6¯©©¶¶I@îâ 5èåïÙhi€ƒâ¼‹¹û’Ò s³²«sZ(·¸œf“ÑhÊh4”Ò°0uuzºLFŠ £TV­Õýþ 4JÙïKªaÚªÙ7ÄéŸÍhx›Ý nÊ­pÊ:òí2ÕÀqìåË4J AWêи5Løƒr•‰…r;nÜ*«Ô6@F~$£ÃæšÖW³O1ã9ÌòþíÎÁ%xÙhý1ü®«÷ÐçT} fÊ%½@ ½^©Š^]´vÑúE›€š1ášNC_ šõ uîÊÇ>ê¯gæcІDTYî i‰phÁKêg‡Øý;?æ ~¬• ÄÒpЇ\”DŠ»e¡ ³Ðpü,.ÐÐíjº|¡RoÓìN>0ð†ŠCýûç›1Ÿ†­…ø·³ð0aʼx,Il÷ß«DB) È ¡Ö6vÿfTÊ3YÍv0QFpI Ыõêe8&e ^@Nxú>'\Bõü¯¹AA. *ª2õƒŽÐQcQ;ÉØ2[-}¨Œo#ƒwð<´`DôsñÂðºßPüaÇPL?̼Ӏït bùÜ0€T<Àx›ÿs^Ô“\£ð“ÿiBã‡l|ybQÆ\2Ê …Mç [öš[ÛÚ Í‰÷§Š^g”Uk7ZÍnôÓÍ7roýƒe’ ”Qn°¹­v&¦ ùO¸<”uÔ½±ÑxÉܸÿÀþAÝÿ§¶²ÜaÖÁ;ª£cÞ幺|¡÷Í”Õcô“Y_F§§êÒÓR ¶êp¥]à û î2ntúƒXËÇ9Œ_é3E$×Ǹ…Š!D¬çAA‡1J.J-3ˆ‰ûIr.…QF¯5)ÄÀ%Çgêø5è­rd¸Å·™õNÒŽáéKB5ç×÷ÿ¶Ž}ìsÆò §_Ì,á¡ßL@,<ïÁÙ¸—â¹høÓè)”ŠòˆH* ^åżöD”ï =MŒà;ßýùaÎ\§Ð›§Çà±ÛVÍY3›8ÑþGɘé¬GçI=bˆc9…Þá¡ù\4Ñß¡á7–^Çãi|ã?"úÏ}w§¸½üß)Žczî ö—Ü›½ÙÄ)'þ&i÷–«•ñdPOàFöC~€ÄØ@';šÞoûœÃ<ÀüÀ³Õš]~³ÓØÞ® ÄÐV¼())'gcÆ òìp.J.ãý%€¸ ¡n͸€Ç pç=À~ñÄ»lnl¼Ò887~šÀEä㣸ŸúÖ§ÒP¢Ü£©²)PHaŠ€òöþÅKøk+¾J¯Ê]¸³HTº*°è€í¸¥Åä5ùÁ 7–„²Ã»e?qfÓ‰›½ŒJ.sú£î ˜†˜´tÛ:~ÎáMuËHjã<¡anoÜñ’¿gñ;'K`5cδ)Ë1'€Æ  ÖZk´-dK0Q.•QCNÑ“$µÚõXL´Ym%*o%¶Àã=ÚÇ?°öRéi²=AœiGÃ;im%^Q°Ä23˜oÛíR˜²iMÐKýáýþtóÜN<\Z ¨‡ö2Í–°ÇŸO2b_ºÁéf×~_óOØ•––òsìšûùiø1<ò×ϵxÃÁ[4™W-îƒ_1QüÿRþÔ²µ(ÿ¾"i^««²ÈþYBáÈO_û›=hÑŠøá€¡ùÒûIýÏðŒ“l”“¨‚``.7T]-~/ác¤"ƈh´Gà“ÝdîD£O\DÓIÅfsNýc´¥ ‹RØÁ'`‡g®Ñæ¿‚røF ñ‘Š{pæjUñø‰m±x>Aq7’©“ .§]W8Ì(&’'é6ì ·Fáqøüô´“KOWÃ1ËÙ+Ž„½éG`/ƒ•-Uíåç¨*@¶dZ]iÑ2Éš]@eëêÉb09ÜÝÝ&—³³Eóí¤ŒªJê*äAI¾.ŸZ†=<ô%Eñ¯ï*ÎjKéIÒ“ÇZˆ‰;:ÓÓÑÔ[Þ9jšˆ™Ú !­¹p0N”ÒÍ>|ÉÈ­ì_À c*Á+Ê½Ò 3€„"3¢âˆI%€J‘¦)˜ƒßãK·h‹!•šÚ»ò:i®±h zêÓï¼(ˆƒ]ÂÌ=Tá|ž-&§ûè[=õ@µ7d.§aM:)IN_·; ¨´ô†ë4A×_yžDòª,€ÚnwØû¯#!™ÑÌ8^1‘ÝÒÒâ}¨¨<ŸÌßÔPÛut{Ç«øq…'á 3NÏûMúð{MmW‡™ W+çÅ`6Y{©ÙGÏÒ°¿ú«¶7C}'œ„6è,óf“WUÝK:ŒOùÝŒK`ª¢ˆd¬Ö@Ùë Wcù~Qÿ7üjMvB¦åÞÿ¢dR˜ìz1À>tUµrÐjTÌk‚ë¦c5—›­gÀKLÞ¿sð¯žÅ±“ÏÌûóÏä%Ň-4xŒ¡Šs”-ÀÛ‡¦~Fæpƒ0mþ5ì¢#™Rœðßf²Chò'¾»÷3té3ÃažâÝâV»î8„ßrk×Rã½bóD9ýU5DëÁ/‰×ÊS E>©¿¾)Ðy(.¸K+$™1ê<?D-º+8~ú"÷åZòlÑôM¥%ëƒØwÈìl‡ *(ñˆs„ùÉ;æíœ„®3¾Î–óA4ÆvqÙ$>ÏG·ÌÄûÚU“ÁŒá‘5Ä ö!È![¥Ý-éH­O$lã´¢ñS1çÖ\¥ÏÀáÃ.·ÑÀ/˜)ÝE¶0EZÌCº1ËÙìt×CU)ógçgHwu~)@ÂÕßWœ¥ÄhO#ÊÍHöH„®’]4iB£Ž7=ÐÕ ÔEï\ q¨.- ñÚ½æB·ÎV\à ®ÿÌ(]!žýùÿ¤åPá´y¬Î´ÒVצû –’Ý\«“ë¥z)Ȩ5]‰'ÍÐPè¨;è>ù¯C¤ðÑfbšÄeîvª,AK¥¥ŠPÎo­hšåùZZ‚µGz8 6²˜ ½1¼RÀ`ÒSÛtŠ$RÅnq!å¾fQëAÄ)c_LKNJL.!Ø—úyÝìCç9È}ŸÄÄQôŠ#F…2œØC:L¯‚â¨uS Z¡®ºªÝ×é9ýÓÁ'^C(˜ -^2øŒV«Ÿ¬ÆD±l˜·Ïðt%jh(‰WQ!ð€Ïa¯6š<‡mu?ò‡ßRåh2Z*B½Ÿþ ¨gJ: ¹ª,ef¦ø… ´…Š4ÐD >[£Å{Š´¿sŸ¹¼E ö]’¬KÀÜŠ<­ì“Ä¢›8Ͼ!’¼ ›ãS6ÊumYµ¹5Ö\˜[—‰4} Í; ÄI ‰$µl q_wy`´ª®Ti'Ûe…2™ð@'+ÛDziˆflôÃÿ¡+·âGŠw*D†pãÜ/ÂÅéë·þk:½ÝhIçí]±‚;ÁŸÚŠ ^.)N+]Úû_í.Kÿ1xÀChê`̬«œÉS¦éU¤5¥dª+ÃKQC“¹±µ­åÎÆ'‡Ò-`wÍéF³íuåÂÆÔãÄZQèAô4zæ‹uÐ[`Ûîô$ù;kRîV2­lõ}+Yå Wrˆ•d<{CC£¯bo¨É^TWmêš»î"íµmé)@--»i M“ÙCb_÷cìaÍßÌÄò,:›J ƒÄÄ"aþI•D0Fã±8Ožrfå5úì«moW¤¦ãÇu e–R»Þ@•‘ý›¸ÅòŸl¶r(Þ6˜§Ýd39)L£'x«µ7ªu‚]Õº~¢{XÖ窈¬¿Ž³tÚ’¬õËד=Ù$«Aç>)'=ñåç÷ï“¥ =añ9Z}—m –òÆÃµ‡½©þÑÜ ©25ùy3Hð†Æ`ûÞŒæÍ‚e¿Uœ¥ìÙݲý—Uõ.Ä©²@ïmsí0‰'ªMéã03£yY†Â|ȧJ%@mÕ¾žû`~Êäx¼t½¤I}B~B¯S9¢Ù8BP óAÔÛ©©k†F*Xì)ÈÉ,ر®/ñšµé@»¸NêÉnZ㻉v衚jÏÝÔÁ1UEGÿ ‰ ¡Øjö2‘vïñÅ]ï!¡_à¶£‰d‚Û†ô^YEj~?-üb)Ù#èÛÜXÜ¡-"yCgòí ³C Ú°O×id;'mÌKª@^Þz×’E2ïÜá%ë‚›ˆß·§xî]{sü¬­+]/^œp÷Œ€ç°co#bñÍ®NK…5èê$áùH±ˆÿÊ1(ÓįÄãXéFƒ6ñÅW€Ú$ïé áTã{õïxšï©èÔ”UѺ;;:rVˆŠæÉ„ê’”˜‚•°•šúNî‚‹ÐÞS q‹ïÄ;à:‹ÆÁaRŠ÷FN¥$7/'_eVµ[VSXž»©„UX‚Gmí=!€S ×B7íU?«áM9lº«á¹òl•$Seq°“,À·‹¡y}èÂHæ’,Pþ J·oÓgèíÏ8èct’g«~v¬P 5eYšÂ\ÈìÎ@‹¯ëÄoš`-¤n”Šr/np?5iæå†_M;Àl29Û¾¿XG샯b- {Š–¤àèâ•© ñDÚEPP^g Ô¾jÈw”dæædÄ+<®Æe³Í“Òžt¨oû¯. M–s­^•½8P;©¸¥@e ¸’²•kÑ}»ûŸ0gŠ˜y/™ö!è§ÕнF¹G+Q娲ÕÙ;ÈÆ¨-ÙùÚR 6Ë U½Ùv»r¿ÅM¼Æý0ü'”+ÏQ‰'HÖÁvjæùÌ3‚}ÐVÕØX¶Iº5qcNZ²0Žì:;ÌEû*¡¼—ÓUNÀ e[ä¢ôâ­[¦¼)ø¾ý´\ Þv'àx›Ðô&ïÓMuí!0¾ÙÛÞþ§ÏGÈVH* ¨Èþ­Qdn+(΃> stream xÚE”iP熻˜i  ­¢Ø3*‰²Ý²\®W QLŒ; Š8l3Í&aG˜™3 #û¦,‚8* Dq—Ä傉 j¢ ‰ÑSzÕÓäóVÝÆüHuÕ[uþœ>çùÞ÷Дµ5EÓ´ß:ÿõŸož³ÌÿË#õ¼0büóÂp¦0™\haŠ•ÀI„ ÖS(жw•úíƒ}à0¢ŠÂÜt¢¬išás==ÿáîéé½LÎ+f†ÌRx-\8ßMáíé¹PñI”2&"$X­ðæÃ•QÁ¼X¨ë4!J>I1sq8ÏG/òðHHHpŽŠu×Ä„-™å¦HˆàÃ_*c•1ñÊ] _šW¬ ŽR*FFv‘eš¨è8^£ð×ìRƨÅI¥3é9”稔’Š¥)jeKÙQŽ”5–G±Ôxj5‘r¦&QË(_j=µr²¢hÊš  NÑVt*}Ùj¡Õ +é±^oÝaãkÓ'õ“6˶ÈZ{Á‹kþ\WM¿º.ÁGÄÈ–B©òõ†Ô22Ù\è؆£qò™Îò2ƒLŒ)· ƒK†-›³2É$¢Ð@ì€ðOÉ t™ÃüݵbÛ+hdáY2JýÑ6à‰çIÀdh³sä ºÒ4Tç#dw ­d4qÙ˜šª×C“cÌ.æ*¡çLaNB…WÚ1öÃ}Ókðj'^«¦…Ia&°Ø%-¯…ºº8H‘“.ì––C-ÏC\ GºI·,%x¾Êå(VÒˆ««ƒÚrÎ^0Ç›‡mÍtÛÖ I„¼ÉÂÛôë‘×¶ÿ´¨v='œ›¢ [ª› ›`¥ñ£îv~r;ñtÃ£Šž-7Cp!<¹ÎF€oeüëôKðΠø®äBÍË{Åõpnì­ö,]ƒ|^iëâ§ù¦D‚ÈÈ áˆå”)í¾û†ÙÃ:C4·3dc¬0‘²Ãp.fÞËBµin\x¤´Íø::C›«%\æ¦-m‘´y€¼þÝBŸ{ü3 ÃleE»¥²üÊ¥Þ ð ƒ£gÜ%ŽÄn±§wÀÉìòšæŠg·@×x«¯þ40¿v/ž/‡éK}ˆ-CœÈø‰ié ƒFKÑÏF%Õ&dmIKÜ—åÉÀ_鶦[(Á¯.7з_âÎÿJp?>fï÷¬F? Ý(÷­?ǯ¯³áëvGkö†¸½ôG):ÿúä9<\9ðaí}so?üÀüàuiºbÑZŸÐú䆿êÚFZv—ÇÚ/Ü5¦a ËUËÕÁ)ÉQ*^·&7QŸ¥‡T&¥ª¸÷ q‚E!Þ¼#¸áÉl5Æs© ×g¤›ïB&Fâ±"Áô%)4æÁ¥Ky0(äeK´%-ò‡o,Se 6ì;R {¿ÛëèkFv°´š~kAÝ *„^¶,·5£tø©¢$Û˜#׉˜2sv}˜¶A|Ú€ Ui†Iz`R!=IN:eIVÉ‚1ßTXZqâÌ \„ÃE‰Uay° Bõ4Û£BTá3XÕÆ_7ê÷ƒsíæuYBÒîŒ^÷Ÿ‹6Ü÷ðuÇ¡3 ™äÇ‚º&®…o/Îè…öÃmõÇTwA4®4æÔþ ÌânÞbg˜¹•§h”Ü£C\=üKf¥ÛDÊú ³äï~i–¿r(¢KÙÎ8­~Çqèäú‚ØËCÀ޽IŒq !¯â@cKWM‡xÉNªª£ª¢ËÃa)ððiض° m©‘°Bê÷œL;(ºõ @•ÑŒ! ¸ÀL7 aA¿DðÂD¶v?Ô ¼æ0Û•8©è„c{ÞÖåk‹SåâÉÖí ›=O›$º(°&ª3ª®Ach`‹P1x¨pä“©^üÅ|q·õô±ó˜}^‚‚°€­„âT.´œ¬ÓgfjÅÜé`_~r‰º$H¼R •ÏV9liQµ­Qu¹}i]™wSÀÙµ'ЃûÔ÷RÏå–éMiÀ$CV¢œ8È’!£Œh8pÐd*)3™:vvéDKŽ=uëßrèVGF×få­+ÎUÁ¶hešjÛŸqh ¦…yCV¶˜J(8(Þd¯ŒfaŒˆ)°@—f ®¦±8ËBfáj•Tï¹ÓÍ]Ëh~& 22êç¤Î¾ÖoîpUd¾ªPå xTÉÙ‹1ZVšâÂ) .‘YlF›Mvv•vc8[ëùÕv£ðí¸ÿ?ÈU' endstream endobj 1747 0 obj <> stream xÚ­W{pTuš½M‡æB"(ÚÚ™uƒQQA™…Ì2 @‚H!¦I óèW:¯~?n÷×ïGºÓI:éΣ“Ð! IPIfeQ§TÊ)ÔuÜÙ™_Çwö—d¨ejkÿØêª_UߺuïùÎw¾s¾Ë!’’‡s߯œ×·fìX‘‘™ùëÕÓ^•²ŽïoMêæ&þ‰H<ÊIüxN‚â&I¢nlLú[Êœç©ðIümÑôùåýÓçOð±hb1‘Äáò:Kzúó+Óӟ˨¬ª•”‰öÉÒ–•,O{vÍš—žN{.=}MÚZ±PRVRT‘–Y$Û'ÉðŸiÛ*KÊ„²Ú´e¯î“ɪ^~晚šš•EbéÊJ‰èçËŸN«)“íKËJ……°4m}e…,-«H,L›¾ræÌ¨WÉeBIZfe©PR±&¯#~Il$²ˆnGD”Í­âÈ %†ü8ñ±‚x†xžXE¼@¼H¬#2ˆ øÎMÄf"ß¿…È&rˆ×‰ÄÃs‘D´pR9Msþ™ûÓ$NÒÐÜRÞ^ç¼u󮻿ÿbþЂ ɾ”-)ßß×·°"Á,œ†8šˆ¡8g2õk.úÙÇ|Т_ ¤R ÊÆ ´Ò‰y<´-Bó¿¦áƒÍç~Ò„ÈÈ·WásòÃuçÙÅû¯V…o @k¼êi0[­ŒŠŒ°ÀŸ@ŒoÀæ‚T´”÷MdSñ‹ééìC4«`¿àëì €¼v¯Ý}õ P!ïý›·-_‘ΦР'Yˆ'~À˜˜›\ôÊ?bB_óíE»‘ýô‰ÿ`—Óì¿ßÆg ‰îã¡ùo`ÒPÞȾ´ŠM*ÜöÂ&vìrÞhÈ…‰±wþ’¨‰s>E\nb"ñg¾ïÝûÍAÛ¬ÁFÚ*fÈ Œ6µ-ߦÒØ€_ß´ º¡ËÒcq›A= ƒ%§„‚š5¿ÎÞ ØæVŒ‘ïºbòLZ¤Üšy:ÿ:} ñ^×·äÂÉë/=ž¸Äœˆt^v~¯;è6yµ´Aɬ}E¥KYRÏhôª ÕGOX  Á&s=;gj£€5&Âú6 H!•}ø6'´ú jd45 Pﬖo°FµµÖèÒûigÔqùã/e‰3á€Æn E6±ËÑ 6ôH",°ñPÿÔWžz›¥ RñE§³#RÄ q4CÇã‹7z¿y°!!HLÞfüSÞï?R¼LC¡ì_v•ç—åh²1׋xHUÏG‹ú¿úþ@~¶üpƒÆK½Þ‹ý‘">ùTm¼„š.q'ŸŸ\÷9ínp‘£Ë@ÀbѨ5ªêýuéÙÍÍ;p­4›ÌÎgy4d÷—¹ ñ}½úËu‡tvè5ôÞ«‡ÕäªV.ÙÈ&·£û)p@‡»Óæ463¥«Ù$+f_˜ UÀz·ÉCyÀfk ŽDÅgKþ„%ýJF Ž5 VÅÄñroA ÂSꓹŞmíp‘¼výúw7SÀHÍ 0“jŸÅC¦Ø‚uþŸXj}““Ø‘øŽï´ÙqÓ®òþ(ßIƒÄ¸Çj²h¬:°*㦚Àév„{ÐVA³j©©< XÀ Èb× ,&FFRï1zñ}v—»õ,ZÕ@Où¯ÏfÕÓÀ˜k¬fV0Á-e4¹_ J+¨ZéxßÑäx1¸ÈÄ€ôb6k Š–‚ªíûf'Áis:ü¸ Ÿ ‹ãœË×¹“ÏÌ H´óÒb’3÷£Õd5Z «ÙÏÍ*»”]üê2 ×g}IC«£ÇÙòmb©À7h÷}d{`fÈëi%H-J+¹™·ª ÍõwŠÔ¨käÏ rÙ}¯™ *•ÿå«(™BzÍ;ˆø˜â m,AÇ8#׸‰Gðu­#YXÉì#XË¿°å#ú=8}ª­½mýï,8Ñ#ÞÖöÁæwÁIºÍ5¥‹Ñ(i|M™[ ¤LŽaÀ¾w—»+4îlk¿*pu6 cF•^Õ­éù+¶›¿s}®b?»dÃoÑp¼ç¯‘£½'†y>¼NGL²ÜX­*‹vF™7ƒ G9'~‡,׸ˆ™|šo³;‚`#]fŸš2ÃFfÙfÈ-Z+ž ÆfŒa (0jKŒ²UìŸú2h€:ré¿ný§ÅCh zâß6…Ú{Dr%Ù<•ĉbÐÐãì Œyz=1o¯« ìÐÀðhÿ0'Ãy»iØ+Oo­Þž_X˜ÝC¿Œ%ø1ÎUL¡!1—]ÊaÍÔ+ƒÚZ³Bl™!õa6•}’%.m¿Bƒ¡®x¯üY¦ÈPQZ^$‚ÿ¤6©+ðw@+ÙYTHÔ”ä\3Sh \ºš «Q>ßP)¯Q(u¡¸È’Šø8 Ã]ˆÓsêàÙãñ7¼Ð¶VG3s¢fyãÉùüýøE.:5™ÄԷȪ+¤byK}´»·³bŸœâò·³”©Á¤†ºÔ¼#¢·¿BiA¿Þa˜n¯ÑÊ^)..R­võÐÐéi öû{ü=M=ýŸ |Ñ@?{²äÐŽ§ŠØ4•ÎcöR¸/n‡?vëXO%¿©’­µQ+ÆŒ­ÅŒ%nÌ`j¸…d—¹‰g1¨pCX*®®¬V†”}ݱnŠþð"¿!+ocÔCƒÓbë9{À7CJE•¤\xXr–š4çHJ¹‰¾8v/„ÈÓ…od?–yGØžPßû§N²#ÐXŽ}–Á?Œã¤6†Fn†fD…Î^=óþŸEÅ€ÅTË.™ú-ö?0‚•¬kn Sà=èlöwÿ¥iø´ñ‚r¦sÏ¢eTœ€äÖ£{Þ¥†¡»?î<Ü2nò6ÃFs­ª zVTµ1‚Ú®è´Bü~iÛÏáÈÀ@ xúÑÃcØkŒW»Ýø½òÖ†HO_dh@:¸“ʆÜœœì‰¦Þ@.Dµ±É”QÎèe. ÝUÙ“ú½Œ—”zwI÷OØFð£3Oí?I@t )ÒÃ#ìf<*c²RÆTËh²•E" ¥†h' aG“#H.üþ³~2ùòû.üÞ´šïù8B¿»Óî·»âçÆºã^l¤‡Ûå»hešÝ†êº ƪ†-SAŒ©’…õAª BOÀáö¸:¢_fŸÓüØ¢ñø‰ãG/9Ø¡( áµ"vž2_[Í@Iæ¯ùæ.õJW …@ÖëýQ¢Þˆ¿+tä(šgÈs3¨õ#Ú©ÿdS[.사ú×2 ãù±ØE]™´@›‡3涬žîÀ‰¶sغÝ9 µ&¥¾Ü¢oØjnÜË>…å`”àûü8³Ì$¼‹™{WÄSæ©Ê±´T÷®hMQéÿRÑË›W!4œ.<¸D ‘ÕÀUìüÿ¨"ÑϾG+f+ɺÆ}‹½¯ßoÑcshÄ;ÎgrÑ~§ãÊåÏì¾ÖÜê|pûhð´]êCóƒ²~Ñ;x5¸Ãé-_\!V\ÚڿÕíÖìÀ[Åpƒ§ÚÎâøïòȤØKÌR‹ž¼\Ïwµ‚=Ôvdt$:x/þUý5 v{“Í¡Wü7ô鸫J¤ã É6½!¹Í^f¶¸´¾RfÞ€'a¨·¯ÛÊ`›ë²ÁºÙJªñB8³ñÆ´‘oó>6Æ äÿ,Ú.gˆT!;S§ÌÍ*Ô+î•zZfÀ©g1XM*;«´Ûc2âðMÊ‚Œ @æÕ ŽÒpîÐÍÈ—ÃmØîúv-+fSßa»Ý_2äÓÊhédª}Eéö€ˆ\~¥úõ!wºZ Fká8Dßô„îJsÎݵ9Å÷NswOà8v®®·šj¹Î Åpoic¡›(»)çàWè“[Ü„%ñ8¿Pc)Å*š¶¨È@ëÈÙÍ-{©–ËJåoç†ñóYNû@å4r:€·2G úÁøþŠy#\)¢¡F½K¿ßP!ΤlÜ.*Ú f¨Eó±&žŽ×ÚfyU…L¸ëDõ)êm8üfÛÁHÞ1Ù–g=›zvXj6älÇ«}¹42LC»;Ú|ÆÓùÜn~ëÐÈ(¸ð×PEG"ÃßÔ„ª:xìÿ> stream xÚ¥y TWÛÿÄɨHÝFAÛ´ÚW­Z—ZëR­ûRµâ¾³ƒ@€„°o$yö}K ì à†¸—ZÅÖ¸µ‹]¬¶ÕúöU{Ú;žKÏ÷Ý0´µïùþçoâœ3Ìg»¿ç÷<ψ²³£D"рŮ+\6lzsѪõëgYþ0#ÇŸ¯–#)áU‘ðZ Ãí^£(Qñ r¥~yÅrýv å:Š\ÆnLÙ‰DŒ"R=eÊôÉS¦L[$‹ñõö‘;sïž»åäf¯ó‡Aòçqs}ärÙì·ÞR*•“w„N ñž7~¢³ÒWîã¼Î3Ô3$ÌÓÃyiP ÜyõîOç.›'w]ÈrÏçUAž!ÄVz´h¬Óæɺþ;9ŠSvMI)†êKõ£úSöÔÊz…H ¢SC¨¡K £†SŽ”5‚I½J½FqO¦^§ÆPc©7¨Qã¨ñÔj"5‰šL½EM¡¦RÓ©·©Ô;ÔLê]j5›šCÍ¥Þ£æQïS ¨…Ô"j1µ„ZJ-£–S+¨•Ô” µŠZM¹Rk¨µÔ:êCj=åFm 6R›¨ÍÔj+µÚNí 6ö¡DTÊMd/ªìЧE,o v ìbì vgìžKKré>tý\&}Ä,dZúÎí+ï{¾Ûo}?cÿýSú?±_`ß6àõ“¿¾²à•ïîØ>èÕAç¾8düõбC«X– fØøaó‡% Ã÷ ?ê8Ú1Òñk§òÃGŒøj䮑†Wç¾Úøê¿_ÛùÚ§ÜÜi~$ÏéìçüxTƨǣýF§¿>À}e@™zÑÿPÑ×~þù«ŸÅH&\g› "¹ðNLÛZ€·9êBrâ*@ùùZ#ƒÖ!¯ÿºÀ ˆ¿…FÝBÎz‘À öl]ÐZPä ŒgüÇ<Ê.o;Ê8  hÍSª3‰Ñ#!‰5ûÞé¨à Y·ûdªò´ZNÉä#S­\¼;!%!"˜ˆ’èbãïWÐPÎá]Ãs¹^„æ›ÅŠ ,'d&faÇ{{¿Âmƒ©¼íÐ퓇×gedæ@“›¬—qr˜¹ö÷7¼9 Ãò‰—&ž\ô…k%0Õ™ú\Þ"rõ9j0‹Ñoè —c­x´åÆ{ÁÀ¥(TC&S]¬ä!%5%•qøÒ€æÜBs‰‰Š[bô2°ˆëÉŒ8sˆ§óà€I¿8ó˜—vgb>Èž-dq>ç€yꇆˆÐV4NŒtlŠ"ÂsSdbjD2(˜è¢ˆ²†g!»s^­Ûæ§ûœ²[ % ¥Óåjµ ƒt¦Ri•GûN¸ BÃîýðˆƒ»«În3Ü<“u‰ ýÎüKX‚_Y±eY@yDe¥A_ÅANj^JVcµ 2¹Ö浇‡ Ø=!Á‘šm©j¥%DÄÉ"Žà™I`HDotˆ `c ›‡1é18¤ãJÇ¿_Wä–ÛhÐõ™Ùv³=¥÷«r|¸@:’5±a žÞI³È=”à‡R‹Û&4Õ$úÖŒT¼ÐʾxëißD•' ¤JnâJ!##;·®¹­ð$0_]òÁ¼¥kfñî°±XѪÕ:fåjuºüîÈT)õÁáAqž³ï.F4è?øéÜǸ/ç{Rv)äÒ¥¼öšaú•‘˜FÙ"ätÿë$‡+¡8*9)5ž‹¼D^[­/«;æ~,I>¯à­8‰ßÿ‰þó5€$Ó`;n=l ßãÍäãñ,äìKƒRæ“ONßùòÌÊE³>X·h´ Õrñ¡Ñ$:j>Iœ•g׬Øú¾ÏìØAEjåv&¼[šµû‹¹t¤@"´ô×'e¥i:(b,áð:©8Sy<œß! yK ª9~ΙQñå!úš=Wr¹ ®2wg~í±ý̹³8Xzyû¹¨•á ÖÃlfüӉ˃¼ÿ˜ƒ¯ç·»”2sØ%®­Ÿj?~ûvû¶Íë]w-áñ»Ù.g/]ø¤ãÞ÷g]W¯pùpvW-œq Õ’È™QÙ7ba4ª`cñ¹Ó¦A,j•EééPÂTDVÊ”áÛÖ D¯ !h#ŠÇÔ­7°dìLb–äþTdǵÁG'0ñh«MÒE–X»nÓ¼9M7¾¹úñ î2ì__²A—¬MÖ¦0Ú ÿ4I§ì_·pZbã'Aüw‚ŸØý´º)³ç]Çx×¥SÌ&ú†D'¥F'Ax™–?nG’ ²»½eA>©øž§ÔŒÃƒà¥·Ré!‚ÍÍ*ÌS©(ˆæÔQñø6öpŒSÅ'”…‰Ù)è>öwÌJÍÖh)ÕU𛓅›Ð2G´þÖ[¢aƒXpAÙ¼fÂÌÃãÇtŒ鿚Iÿ…žá‰láAÒÕy“® t¼7áìƒPÈ÷¶f-2²ùÙyY¤5ÔÇä¨2ð}ä¦Òj€‰PFËyP$æ&¡&¼ÌÃkö¥ª’!Ü)¤<¶ˆË€ ]¦Žt“¦‡&a^T#øˆÑuák6©.!ǘÚTI{q¿ÎRLj®ȯ Šy$²’©|xÃC šL&I|=T+²QmíÐt¢«´MN?ÈhiûŽ/‡oËðÀôJȦ*ʺj•Â$úÒŒrÍâó½]2t*Âz¹äN£áߣQèmôö 4;ñØ®³•?H}†H1fÖb{g‹@dB›M¢‡f4ØÜA`.jaÑ`ÚÂ[,:¹GÝ¥*Ü“DmF‰n´•=ȳ;ÒFUŽ/×Ùצº¶Sh»xk½û©[ˆ<œ[BXÙ¢ÖÃòýÇŒ†™µ Q‹†½\í0äR^¢v %#¸¨!¸hèTøÛîÐTº°– $ˆƒM´…u&šÐA“¨ÅŒJº¡=¬¡ ,ϱ½ {‡hÕ\Ÿ…Ë™?ÿWô/4þγÛ|;Ûš7O­‹hìÞÄK»6XÉѱAò2/ãz²ÁöcÁ¯À«~ÅŽ¨?Õ—”0Á¹ñÕ]&Ûðøy\‡mXÆô‹vˆ7a´éÏO_ØhìT„öÊÛªPK, µIúÓSº=HAÂ}†¨G”-J¸•Ž $2»¢Gu*0Õë¾µ×:ªG̽1ªCÏY4­•´H4-¥wªeïýüë —Ç;qŽå¤Eֺťÿ¯OékÂÐPú©¼¯âdI|`÷ó;V7äГ¿™Q,qc9qãcÛËx–-2Í oÛ`oâVF«Ðpn)Ž•vK»Ò ÄÂkl¬{ìžä½Œ†N®M¨o\‰¶:&Ô&æYh­Õ^#Ôñ i@h7ÖîZÕ‡Ûo­4#4'0'ð áëô¸ìà:¨ƒìªôüÏ›#h+ndm§7ýÒ—Ò:c7&×Ò>„˜nû~è@!ľÂ56æ@(€Yü€ zm¹à«¥ w”l-Ù†X,8zÀHæ¦Ría^Ð¥6|Q½Åùj蘶È‘Ç{Úì³Ö´ñ±´ÙGÂjð*¼*L†[ñƒ ­B.åÕè‡÷{ÈËãÅ/¡>ƒùm§kó?‡;PWà–· p®° –ÆmHت˜]4½Ø„’ºø'±‹}’Y‚ZÔÿúO?þ¸ø'ÜŸ'ýñ? r´í| -(ìžÒ/Û¸qϲ‰jÄv·n–Lrn¡ùˆyH,úeÏ4’±úcæ»y_“¶/û¿¥–=äô-ÚFMmp9a"Ø«Á¯Ô¿Ì¿6ª ˜O«?k%Sw"ŸÁ ñc’ÕÞÑ!pü$!3ÑÈ ‰m ¬Ø—ÆàMìRäq•þñК;=\'÷”3×Pã5Rrmå#16)ÀíК´Â.¢ùsIÏïVë•wxg]Ò­ÈÜÔ«QipQY¶ |™»>\Àí÷Yñöš}‡5ešbÞ§«ÛSò˜•Fƒ¬+‡œ‚,Ò‹šâÉ ˜ß?à¡!ñÐރǷåyg‡e,,‰Mß‘çÝ G™“Ç_áŠ&§‡¤”hŠÿ\€ªÌhåÛÍ#ƒ^ÂÍÃ--¸?_úâI;Ô©Ø$µÑÊâ¿´ejºaFÑj›ˆØÚ^yíhãöZü€ã²q×3Ï8ô Vú«ÒxÐý)OžÜÿ â B½IT*D‹…õDö~K¦’žh´N°Ÿ_‚[b7*¦¤ìqÒÐêò¤ÆäªIÂpÇýÝ99ÚJˆF² í,ÈõÐC 8U k3Ó-?_H D~nM7pæØàj¤wãëIë“w¥n±høt'Ú”ŸPª„ò!׈äøØMýAêÁä¶äc»Ð÷޶̱’z äðZúZg^š2-¬œrˆú\cZÖi$O;Ìèè´=§°<]•+¯ =ÃH+וöp:޾ ”d’rÛ˜ål…{%øðˆ%h„¤¤ºÛßQ6ËËiÄ`Š % [~ün þ[äòv‘DX¢_KzÈßl†+z—a5‰Þ¶íÝ:ªˆúÀU®x ÊQÓªC®hPàæE…e+Ez½Ž?–àe¡Ò—9´¬G_‡U^Â!6·ˆÌ¬¹L‹”þú%À)¾Ý’ ÉàäUz=±Ö‹ŸmËB\"ux×ô|$ñ%ÐâËó¾l‘5Z¤·^Iû%ª|ù?VHý²÷sh%m{6áùHº×Yrz>‰MÉK, %]t¸¥‹V¥«´©èË?–:æ†å'–ž¾ÌÒÓgïËÖ¤1=:I^ óÏÙ®ü"úlCô„?Fâ ½îWZmw˜Ðs>3áŽgú)ZKæô•&1º$Ìb!S}dKšâ5­ZK‚– ÕÙ¦ëGr3r3ÉXZYê¼ ]дçhsqm9çbÂ4‰>2wíï<ÔÌ~îú9vÞþ¼Xa,®Ï<ÁÕ¤•Z·¾8æ·šÇsÔØqŒgæ_]õ˜Ë‡ÛÐ~ÐèÛ¤¹ª1v5Q|4„Ax³à*Kx6Ì]é¹ö³fOã!N>Ùj‹æ‹&Ô§«rh-•C¸d Í|[$Žv­´n³ž«8q”0Ÿøñ#2¾öŸñÛñÛ`w¤O ƒ‡Ø?òÂÕóËÞž¶rùÂÅ_érí²ItÝŒöþD`„D¬!:GÁÅB $*’¢#w/æ¥Wï®ÿ åK P“zµV£MLó­N „Y­×Wß Ûð‚ÕxätìðïqdŒ}½þ—"Þfûþ.Û……/³O¤eîû‹ß|¯<˜€(¾ ZKš›™½y„»mËäô4ŒuÛ1ûý¥k®Ü»oº|³ãÔF·./Ø‹hÙ¡ÏQ.Of£µ¬¾ fåϘÅÇâþxà¯ãÐP4¢íÑâ#C†ñDEèºÈð¹fîW>b´Ù²»Ÿü®ÁáíYïwîv²'¸\I‚Ÿ#ôaQ_›5¸ï1úæm—&3D€)«*løtDÏ›½ë-~ó›Ò.ž¶xù·¿Ñ«Ó¬µqô¿ˆf_8}m¸(2™Ñsçbäý«"ö©Ò¢&âósR  Ò!?#§:º>±˜‡æ›ß[J[MdUy~‘®P›lPSQVj¬VÔoàå°3Ù+0¨Ô7ÔÈI NçÁ«À¿441*!˜”ï݆ zÙîÔ•ÍLÿÍ•Œúƒïøž r[”Ý´«µ½½µõôéÖ]nn»vmâµx1û‰à]÷%»Þ¿ðp+- ‡O§w…é|J×Xvµ±¿li›Åmƒí‘ž~ ú@úwÐ*vöJæwzí1Z@ÿûvÓÉ“…¡k8êß«–Nèëæ|ñTÔÕR™„sl¼"(H. ª×ÔTTÔpسMH‚ÛÉŒaSÚnÛ‡ÑèÝe¢Vš„J‹Ø?¡)ÄéKï²~ÑC ëGCx{û’lŽ!­Òi´­9è—Œ"$ÊÞà{õ»Â ­éF˜” Œ"½ï”Å¢þÈNÒÔk,šb«Q4žˆ_— _¬o¯°êD§bk/ˆM±¹¶õ}ç&ñ}œÄ?´»r!{›ø½™˜ºs¿C÷öO‡õº¿×˺aÝ!:ÝhËW,ìD³å€ì¦q °ölV§‡s#añSï«UB0~ViåÐÄãv鋃¶S´XúÍác‡ô1«8)M ìÞµëÿOK¬Ðü'\ÖhJöü™ÚÿAiåÓÍ–#SÁíeÑÀI¿` –L‡â& ;d÷è1Èaw<…]èzóÁý‹Ÿ^½öÙªiS].äpH×þåûà¶—ÛèÿBñͱÎ2}o‡ú ìßK@·Æ‹&Ñ3*%fo8ÖÚ(÷rþu†„é±ñ`<àÇqˆæoÀñ#…… öØÚ+ózAŽÐô3vý–÷æ,úàʽ®›nÝnçÚ vš@¼’#öÉåïÅ¥yÕ$Þ2”Ԕŵ½Ë¯—ЭnL½âØÎ†þ/q{¯N•öØÅ=‘¿aB¹&±°@Åv_¤Ä¥&y–mHâÄ¢è)A7:Pá¢Î*sT7…䮊—¹×ï:Ã_ƒöOk¿ë‰ÒI3ª'VnG°…`ù!Û:zÜ·Ž[m£GŠ—b>C.ˆï=ž[Û÷ ¶ÑÃçXFtÔòí.GÈ…28ùaÝÙ8e z[Jœ:€†ë˜|kÔ"øX®Þ¼6¶@8ƒÉ‚P؉ÔL‚L³×¿Z“ã©°Bºžë¶Ц¸¤6’ùƒÌ^õAZGè ª™ž_î»~n~îľøuù9RÛ¯É5q' F8ŠœtLnµ¶¾A¦M$ÓàTv™[¥>æR·£|…Î2Dì­Ñd“Ôò.“ÂaËÙ€ýI©´šžx¸š‰³bª”¯„˺SUçêà$ €C|ž°(½ŸGãðL©©Ÿ¹¿ÉÞÞl?€ëgdßW(ú¿ÐËC' endstream endobj 1751 0 obj <> stream xÚ-’iPSW†ï%!9(•¢ÜŠÛMªh]pw)T\@”ªDBHLˆÈ:b˨€–Š bHcB¬‘ʸ¢‚‚¢Õ©ZEFŠTìȸڞë6Ñþyf¾óãœ÷}¾CS|>EÓ´çšÕ"VÇL Ž vÍÁY¤b,ßò¾ÈCqcinœÇò¸‘üqEaoû½\ìýÒʼnN¸?Nñiiwè‚‚fÍ Wª²Õ)òd­xrÒñŒyóBüÅ3ƒ‚承UÈÔ)I’tq´D›,SH´Î!M«LJ‘i³Å“&kµªùYYY…&@©–/žâ/ÎJÑ&‹cd™:S&G(ӵ╅LìÊàB¸R¡ÊÐÊÔâh¥T¦N§œE‚<(Ê›N |(†úŠIùR£¨ÑÔP7Цø”œ²ÓèSnžn'yËyvþ"þ ®d‡3­ïݬtÇ ¾8ÈãÎà;Ì]À&¢'z ¦°p F¬ÇzÀÆ;¬ó°“‘À2ƒ¦7ç ¼€kð+<øáÒÑûípnfÔ/©]W‹! &íŒUÎÏÛÈù88ƒ£Å@cÓc&kldÔD’ Mp:ÌèC¹päù±‰RÁåÊnhkë†Ëž~ŽD¡´‰\× à¿0õÄAßÁ®~Íãìx³U Ï-ŒÜU°»x>ä"«ØçmSã“®c–QKóø aoâ~—Œ&ÌŒàéñ§ŠkŽþTw¼>Ϻ™=r¡óÄm@ïÚÍÁw߇-"…Dá[XXZ iˆ[&pé9~ ±È†éwmôàß8óxø îcúÚc&·È„0‘ üönºâ¨üѨIsd›J±S2»ÅâxòËÁ—,Ü}@†Zšººàê™ÞA<‰Ç̸y‰¶|ƒ©±ÎαŒ:Uå™Ö§PèB—f®Ö¦Mû¦8»T¥/‚ÂÒ‚RØ…rjàûI'övpñš£zy\'žË8ˆ·Rxö©ÙlЗå“W6úJq×§Òü6]*0”=«hiyVbp*M†À›¨G8—›Ä‰Yø©(‡¬ØëéçžF:°ñ/æZ[‘]×õÐ×퇪¯5ƒ,¬Ð±%P :yn|î ØqU›VêÊu€r¡ GD. wB~[•ûöµ¶4uÂ^@¦¦Š@Z»mKšlcN"D@Ä Í•se{p5f6¤Iö¬쟅‡ãq=ÇÞXø–0ì XŸ™ªBŸczY»m6úúÜä ‚ÿ`ÊΗ÷Ú¯µÜ¿ié€#pZ× ÜZ\¼rÐöº ‹åðácÏO$ÄŸŒ!)D‡Ýý±/ë€[{;¯Z­Ž“ð'4éºV¶'[7Ûƒa)ÄËSV#ìGn3äkÀ¡ŽÇíD­`ÉlH5Ka¬ƒ}JJ’F‘š“ðéƒg¹ .qÏyÜ-î5SU å`F¤F°4eÒŠ ùe{ÐVœ(ÝT«¯ÖÖìßûjZ2¹qQšô©ÄcÄAÂÙspú k^Ûüâ|ÇÿÕ?:kwá¾6ÇàÌ=[Û9¸ƒ^Œo@ܧ,›ÄBtsÂ/êê↼êâHu@,LBÄ{¯ÁÂn=˜ÇÂmIó®ÚuëÍr"‘/}Y¼N£­÷º$†²°xîe.š³œ©)þgUc®1ï²bÐÂÀ-Ás.õ±Ð×ÓvÙð9ŽùùC+çíŒô 7½áq±øKv‡ÊW©¥ ëâ*”&뾪z8ŒLÙõ ÅŽióWôã,Âb,Ã:Â{F|CP ñe!Ô,9.oI<»ý.ôÙv£‘©QL4¨Žå•'JOA;\‡­ÙÜd«kuŠdIÒŒÕ f‰†97^‹•Õû"©:†ôµîóôì=äù;„bðôàfûüWëÞÈ endstream endobj 1752 0 obj <> stream xÚ]PÁj„0½ç+渥”¨…BA„]·²l‹®“Ñjb<ø÷M¢ì¡‡ 3“÷ï -ëk­¤úm5ïÐÁ(•°¸èÕr„'©HšÜS¬|f†Ð²aæ“Í´jný­}.›öý¥¿WéwÀ}3Ù1××n[ε5ä9 ­×[œÝàtzÀ§°û²­Tœú²‹›n5ægTRQ.Ýq-p1Œ£ejB’'IyU•ø÷—íŒaä?Ìzä% /žàû½¼BÒGP¾Zë=ÄsÄtÁˆTø¸˜Ñ&°âû¶èot endstream endobj 1754 0 obj <> stream xÚ¥y|U×þ,KvFˆAXF6ˆ3¡w MŠ`”P¥·„BHôFz²é»{vÓ{Hß´ )@RèiŠ¢´ECÕˆr'ÜèﻳAô{_ô{ÿþY2¿”¹÷žóœsŸçœ{%TïÞ”D"1]´bñúÅkÆ[­X3[üyúœø¼¨+ÚDx‹†H„·{ œTÔûmŠ’$÷'Oê‡~âó_oˆÏ‘ä1zûª·DÂø%XZN›di9ÕÊË;Øw§‹«¿ÅDZSfÏž9Ábª¥ål‹…N¾;<-V8ø»:y8ø“Ü-Öz9îtò¶3×ÕßßûÝÉ“'9xøMòòu™?v‚EàNW‹5N~N¾»vX,òòô·øÈÁÃÉB4y’ø°òòððwòµXáµÃÉדXÊô•£F÷šÐoµP±…Ú6„’ô¡<(OI_*b¨×¨>Ôë”ÕzƒêO  äÔ@Š¥Þ¤Q ÊœL½E ¡8j5œA¤FQ£©1ÔXj5žš@M¤&Q“)Kj 5•šF½CM§fP3©YÔlê]j'µzŸ²¢> >¤QÖÔbj µ”ZF-§VPQ+©UÔjj µ–ZG­§6P©MÔfʆ²¥¼(5µº%¡zS'$¶’G½¾’ÚI+z÷êmß;»wuïó&ŒIœÉ9Ù\Ùuz}‘qaN½¶îµû}†õ îÓÖw^ß#¦ÓLó^ïûz€Ùkf…fú-ë×ù†Õ×ú¯ì_2 ï€ãråÀéõì¬ò͹o>¡è­X¡øÞÜɼ}ðÒÁÕo½ñÖ!Û‡´¼=ämÃÛßpù<ÏG[˜X[Üš4ôò°ÃʆێxkDÕÈ^#œ ¨Ì„‡`L H§—<»„v]ºÿ­T¸*Œ` Ø™Ð÷ÚZš¹DȂܸ¨„ÐHðe| ‚õåùeõ.5«9°‹stÙ­wܳ˜á˜^;ŒÇ&sݯã¯h;%,áÜéV]¶¥uæé½D -<ú íúãïÇtÙÚ#J5çÈßé÷U™õ<ºBã4”ýñξO¸,¨ÑT…F«ü¢À¢K¢T‘ ‘ ¦±m&\è±¾ÿýªöKÑaª!ÿ@­QC80Ø õ’=½_ÛΕÀ¾8½ßŽ„8w2ƒGiHIyQAEûºæ9£±éz }:Ýš±ÇÅý–ÐëÃ~‡U*Ìïú€UF“èžå¤ %fÉ0µrÔÿ+`¯XîW‚žÈ>¾Õp‘+‚"uq\xlt(„Bxjh^4ƒgŠHu=zÔƒÊ&­úí€Å­„U!6ÎUŽ¥«€…_[7ôÿß‹ÿÚî‹Ù_îï=AR£Qcð´'H€Ðô ‚³Æ¤ÈÞ.B %AƒôÈJ/E–Â×ìyŸF× ooïïZ.²“2Óu:­V Œâ¢yXâñ‘­½Z­RA<Ÿ›šñõ—È”C[ÞügÍо—V¬ &8ÿcÌ„áXWô|M¡äÇsRtG³¬JŒKÅ,ê³-dhrZ…†¢ÁIIºDHfRã“b¹H˜bµKlÇûܬұìîó1î×ñ~0©ÉI©üS£H2÷”Ä¿"Q¯Hº õ›ôE$0Qêñ:Uj쩨xàá>ØÄo©U ÄX•.&ƒÄãÞåãHÒö°ô'@¦ ¯ÀRÀÒ<vÁì÷¬âI¼4F3o^E}>÷©ßñ;*úÜ\-nÅYI&*—¢}h{—¯ Éd@&úQR´é8[é§÷ððóõô(õ«ª*-­"eàÄ¢çk %íÂp©°±Ë–ML×%A“™Í…B‚2!wþ6_¡ŠV'@–›ÎåARfRCè»è%î œ;RÁ}ÁÂÕ×/·Þ¯t5¬„÷ü¶Žw[ÿ.¼Kuãšæ¶Î¸ÚŸÀ•ŠÆï«.¤| 7ìŽ/²`•„L¢>†;ПÁõ¬…ߞϯ}p.°`Ræ:˜ËaÌŒZµËFù‚¸8Ù˜õ ¼*Eí]rV¯Ñùr+–M&„ǸÓpŽ—1Ý9´³*rçæ.«KüîAÙnô$UV=/Nru>í4HŽ’þÐH>ù!6áäÝ+a›«×J½¯±k`WkdeP³æä1 ˆzH6Ó!¨^Qà6`K>6AÎîk¶Æz3< H8{CÒn¸ß!"„glz&è ˆÁ:ªlUã%Û…L*dI%i'³³RS®CñÛY6ÂobëH<Ö˜+Á¾¥fs‡h@£‹sì²qöŠ®~Äßã>m¨¢Íç¸ü*Z ذþåPÏ|rqÿ§WÏ®ÿƒWÚ9ú3úPöpé‡á&sâ‰)Ãf/˜ÌSŽK©çž ”„SÎŒüÛi«>‚ÙÌП“ôfÿ Q|úb]9õßßÖ CÅ,í@ßÉŸ ýÐglUXºm ©š6%ùìe’diêýip€) .ôò öXrlÛ=Ä’yqò稛~:Ó#' äßG$Ͼ€Çò›ˆÐ}À†¤ÝÎí#¸·‘Ïá¢}UGög×Ú)_”•ãœôlcÞß5|"×ÞÈí%ƒ ¯³U~¥„Bý<)JKd×Üc-øÊ£9ñ(´4'Â-2 „^Êô¨ RH¡õ,VÊPtÃĬËXð‰Õ á·Ñ¥‡>‘ (P@l.µ•CoÊ7Ì[9ñ¢‰<ž"Cj%û¤ðâ9¸Â|3þ&VpÝŒ{‰ìªNéÌwÓÎjå|Îß]&ÿY!CoÝÿ¶ƒ‡{ï|¥Y Þ„¯³[Ô©5<*E«iÄìûÑü•ï „º&$íB|¹Tè~cÝ kNŽ"L¿ÏÂÓ±=ÞŽÞÅSÑ:ôîOèmôZ¤‡ó±šè<›.Ì ¼äÚ‹ªÑÒc·ø'ðó‚RVø=â¿…¬±‚úq–ût¾å{ɦGºå&¡YO|Ë%T¬ÏÃL…̬k*Y¯Õ€ZzÖ³!ë=×;õŸëÉšÏBËï Ö(À– D€‘úý(ÓmFÏJ3”nã¸)(ùÅJdh"è׿aθRk€E„ÆÈYß“v-èšÃþ äM ÿÇmh&~mâïÃ床C{¼ë\3€É„ô<- $%_à ôR•6옮¦#Ü«éŽÄHg~9Íðˆ˜WBõ=Aæ^äžÝtÖ€j FïÏÝ“ õÍâs(\V¯Ë¼Ê•döªµ`g·ìÉü%ô¿gnsâIhi9 Íz¾ZìãrÐ9œówoÅôßÌn&È^äšÅ=) ~dëtY78½A¶]e Û¶YÃvò²ž¾¡‹tMqQGÎá|Ýe ‰ŸASÓgÐ@ò¥ç¨³êÈTú};¢„ ƒ¤*“ïJ…ád§6äÂÝÒS®wœf„®†~ B×mKOÞ¸a#ç¶¾ûö'””ƒ© (us÷Ûíúþž羆oæ<Ô¦ÁA(í[…‡Â7ì¹Ïj÷hí©Ú QÎZÑ3ºB“A£Š‰Åwðúœþç¿G#3d‚Vâ‚4ez(Í=w@0a¯ƒ‰‡¡¹ìén9„§»µàôµÂ¬ëÍ—V¢{©ðe’*Q9*ÀÖÀ¼Ó³m„ º>)ë;®Ú sUY‚£ÝŠWÛ$TÊÌž/|1ãHƒPwSÚeßűZI÷…—†ŸN¼¹)WŒ¥ÖÄÏ•í†Xˆ ÆþÝçØ_8S¨Ñyƒ9žûrãÅÓÞ`;’¸uB—£=Ô–«9.º5ÚÊy¡šÖj‘æW*9"): Ì3!9=)1æsŸaAŠ”]ÓØ˜,Až!WÈÚ@Kº®îº¿™:›æu?K‹L†d0σ´^h¥Ë¡­“$Ìzu˜ÆÖ&B»VŒi'ØzóÝï‘û@@e×”Jq[ûwJ»‚Ñ÷,Ú†'£x%ùL&}øV¼YFþˆ|,ÑT´•Ãðmvæ¿A™H…†_ô ŸKê„LÌOÅ÷Ð`]:'2î=tº“ä-ºÀ"‹Î»ŸŒ¸‹yãWèÈ«’%’V¡Ã=ÚôP†fîeoOø] ¬toè¼Xúè}…¤ý š¦G'žH…ÊTöÙÁNÔÐl毜ája_jijþ˜Üw:€yZ„I‡¬>â4ñ1ïXÇ…ÂzØÝä’ÁÙì¸ú…¤A´fñ÷ž>EüT¬ã+‡N_xØýäR`l\vØñà—¤Õ0hz*ë¶3·ü:ª1¯ª¸j? вב8«ô*:¢GGˆ »‹2XÑùØ AÁè‹2h(Ó¥$¥ëª¡˜;Hxìô­ËñIÂØå×>†kÌüúM<šÃ—_d+ÙImmäëO@&Òòd*» ÕNI UÎÀbØÚæÔê|2¹{·4²ŒRK:™øåî~îàʘ=ÑÅÑŸÅ5Çœ¾€¥µ¤V¼@Ü’À}ÝgTb6ž4ì9Jäx=iPÒD¥Ðhb##‚3²wm )Üxx"Iì×fZŽäa^«mr|óÖüxÔ×ëfPºzïN­¦ÆV1Ö6 ,¹ù€ùê4[“ )À„CL ×Ó“Å¥‚V›š•±÷èÙ•×£H‹†ÌnþðŒ‡öÝýª¶°Ï\šK0!ý*®—ÔPæ=”aõk6û+- Ĥ€ÏA³ +Ñ8R`UB†:?A¾ At'„ ãvˆÝ+êEè™<Äþu= rkDB€2mzaR†®ò /ôÌÁ³r™I0d¤,ÁÄУǘ}h< ½>qhômôöꦫ õÕ›ÿ@ã!cgŒ^MjÑbN\«¨k¨ARØå)EnÂ,Á=´LÕ¨$Ø«6C˜öq‚/ 3!ÇÅww)RÂcó S’sP˜p[Qt¬!§÷»ª&Rì…!¤±ZX(ASzŽ)«…5lyP¹+ ÊhµZ<—eÔ’ÎçUgÚšuºDñx/9.56jÆlº¬Ì¡±¶ ¼\<¦ügÅcÊV\Ñ‹ÍÝ?µ€¸£ÔÖ"}åýZÒú^³í@s®\®Û*уËl²C¥K0ús¹7ø“^ëh%lvq¶<YÑÐ5ö Î{ms73óC‡eîE!eå…eM[“5|yY[z%0GÚ¦ñ»hyµ^½ ~±›•kÀFpdf?ò¾À‘5nÁ¾9Lôçì¸[·l­9ÌÁ§íÑÄ‘f•úð"ÁBœ<»„ôwä{Ñt™%$¥ÍÌ«i9”·šà€_™CÙ6Ý*ÂÕ[â6ø8¸mwßöàTêW^Z(`¢×±†­‡½Žfì‹z=DƒPÿ1?bSÞ¶¸úy3ò-èÇ(MÜéÏÒcmøîŽ ÚLØ¢¬@ußUVHjî ­RÞfw'†ƒ'ãSXVV´ÇpöÃ}ÓðÀñ¸?fŸŽ%ý%_^OÏR‚ŠSégCü­õÙ̲ÙGI_ey£õ4Ÿ ÇÕõ¾/œ3o#+è/É÷ æÈ”…`P…ív·· r„màXêÓèÓ¤þª¡5åXÙâêÃ1h„»Ë²B 1‰gØøûcóˆ”ô³‹YÜÿ‡Q¨/ÿ47åß–Ñh|¦‰¶ŽN=Ä Oÿ쨙`Gœt-Eóõ’Ê;Hõ™T‚Ùâd(úií<›NŽßÀƒ~M V³CÏJRãS¢ù(PÅjvŽœª[Ø^î_³ëæ442ÚR6Mº—W'à´ƒdÌÐ÷)ÈäRÇ·RtÌxIÕ™Ðßjnâ2ˆÚd$üÛ%Õ>§½ëæÍ^EÄþ_ׯ¾u‘·—£åçn”£ØrIåIvµæ¤õGÖ¬>ÔÖ̃˟]çáWMDκVÈ‚xRÉC0£L *ÉÉË(*78rž`¯tuñ.Þ‘ãÌ+ë¹[úiÞ]3ß~âØ…­'ò2>½Ã÷ÜBSC‚z_AÎW¤hY×RöÏ)š÷çË–¶¶lͱ?®d–Ò¿|yôÜÇÙ6+9úÊ÷6/h ZGÃ-¨ôªõ¯pÊÞLª!W÷µŒF&<‘°5"SD ¸Ž¨…—äh¹ð‹GˆœO³áqÑï37늴óÁxݳ4!y?/ÿ1QØg»ôìÙED-2Ñh$ã4´ZCHÜñ. ))*É­ªö¨²çV‚ƒƒÿ c‰ò {E_ÁéfÂX¥^°,–ÔAG¤è‘ðnÏA[<©#"Õêèè¸x÷b÷”ÄQÅ®÷7ñà–ãSPã¾/öHô‘¨=ªâŒ}81ÓFA87|¾Ž<®ÊФD{§`¤C :‹#]‚6¿ )%3;9¹q{‹J/^Ú4]¾ÀCs`y@Éν.© s|’ßφv¦º¤ñ;Q:Kç«„¸lcoW ^Æ’|“ЬBÉ/WÐà )ºfÔ¸‘h¹­™é:bœŠñ½‹+iÜû¦ÿ± µç/qí^ëé…î..‹á›|UÑ¿—&/w`æ°S7/³šßtœC·i<^Dï*¨¦òx KÁ¡Åµ2°!ö…C%•§yv– y©õ½óBë÷+‹„Á¤KÔR´!V•¢NT¦¬ HݼMí¯Ùêê ."‹µ’+×ÂH‘š¦J‡tÒ{¤îACÐMEёڬZ±ü÷PÙƒÚË]ë%ލTï #|Mz›åpœLJõËu­–võGwÙâ3 IEâ8G—»œÂÁQפÉñ&º¥ŽSÅNƉŠQ¨œôD‰¤'*3èʈ]vªíêî nâÛÕP¨É OWf;‚ ÔñJÐÌÆŠ (;.—l¯$óòýF_ìˆ/Ž»H/ŽiƒluÖNÄâ_É‘‰Q¹¤ýHÊLÊèD{?á½IQIÊ\0Ï…ÄŒ¤ ¦G>L ’!SŠN¡66TZÐ]{–f¨©)=Ós6è žNÁ=䪳cˆ¡ÑÊø¸esóžÄ¦«ujY™Y%âÛNj½z ìßþtê–U?aVà³aI€ïæ•kԻŠãÊÄr¨¬®ÖT‹[Ò7Qµ2 9¹ù¥†²*}ÕõQŠ‚’þq ŒŠð»¤F¢KMºvØ/p¨í' ›w[ð'À-EKÑ/l\$ƒŽ)«":Pã zaL3iL³¼ÑÔnZá»*`ƒ§õR0÷…l•.M[‘5Duóü}ƒC½írŸ@Ó©Òh‰0G‘Y–ßp^G|sS¹CÄï9ТH%)çbFáh©¡¡B0ÓKš èŒA*Œ†÷\!&1¹QÂáÉ”x–I…,¥3¿™½×[†k»™hñº:Þ<4ÈæèíAkL¼dQX± ÷LÄ[l”ª—€!¿cõݾ´Ùó,ã/ŸgIÅïXýoYä—Å‚Õä™™R,ÃÛ³hCŸ+}õ)¦¦WòL_çúôžYhúz0ð;CVÖ endstream endobj 1756 0 obj <> stream xÚZ\SWÛ¿¸¹.TâU¨ö^Ü­ZgmÕZ·¶ XnE‘½B Œ„½’'Œ°G a†¡ˆu+NAmgk«µU¬¶µU[ûžØCßï;aúÖoð —ß]Ïyæÿyþ‡(kkJ Ø:¹®þxéò ‹\\]§N1_™‘Šå¦=/—Û˜†Q¦áÓ›½Lœ•i¨õ›%¨DŽÔÌÇÍÇäðvŽe-0á2˜2eú¤)S¦- ŽûxyKßÚñ¶ãÔY³ÞŸè8mÊ”YŽ <Å>;¶:ºl—x{l—Ç5A;|<%‘ŽoÍñ–H‚gOž,•J'm$öšûöDG©ÄÛqµg¨§8Üs§ãÒ @‰ãŠížŽJOêü³(( 8Lâ)vt Úé)$Úö1ǧ¨^”eMÙP4%¤ª7Õ‡êKõ£úS¶Ôj 5ˆ²£DÔ`Š¥†PC){ÊzƒF §Þ¤8Ч©ÔHj5šC¥ÆQoQoSã© ÔDêj5™šBM¥¦QÓ©w©Ô{ÔûÔLj5›ú€šC}HÍ¥æS ¨…Ô"j1µ„ZJ}D}L9QÎÔ2j9åB­ >¡VR«¨ÕÔÊ•ZK­£ÖS¨Ô&j3µ…ÚJ¹Qî”[/J@Ô_OÕ ¶õâ{¶J±úÌÚÁz—M?›µ6ù6Gm¾¢íè­t£ð a#3„Éï=¾wLï?úÄõ9Ò·_ßÍ}‹ûþØo{¿¶þúmçÚf è; r 50iàåAÃé=µË´û·È]tlðVÖšÝ?¤ÿ¿!—‡ }n¿Éþý3‡ñ;’.¿±å ðáÃ2‡=îüæÛojß|Éùp¿ðïð7W8fް8âúÈ‘WFÍU0zÂè}cæŒ);rìGc[ÇM¶…§÷t¦Zò~j…®˜ZÙÓ™ ©ë8ðÉ“ÓÝT°3ÝCR …°2rÒ÷§ŸQ]QQÊ< §™ök}XyPPXXPPy˜^_^®çlÑtLð_TÌÅÆŸîþd…M—ÙŒc>91qî…ØÝ^%Ë×Cd•ª4 Z¶ýïOØ‚¼ŠÆ^E#µ‚FÓ&+S/ô>û%]ÐÞË;Ñ¥h¬ÍqËOº ³šBódàà©ÊXîo?úµWçÒ±ÞàíÝüçt$k³ÉráS:€TP2‘EQ:®2jÓ J­ýo¯»Áà!èö·!£iÛ™º †›÷ë½VíÝùËËÚ¾3üzsÙeÑ_:tÕ²ŸÅrƒ °Ám˲8fŠf±Lè¦ö(—Tgæå@£ÕH¼R·r0óü\ÄÄ1»„Ñ ®¯ƒªnŸÙ–ü®BsЯxL #ú÷i´S¸;õ„¼dC|bJ,Ä0Mx®² ‰ƒ¯\¯ã>yL“°ªüAÍy q¯˜eó`„ª1…æø3W­Wç­Û 'áøñý­yŒíÌV4²¥µ¢Q­‚Æ–Ö–?ȯ•iÑËAlf^zd3¥2” …¤ˆ”X\ý×ûÔxE $1%Ñe\%d—fæ3è»ßÙ›».lܸkå‚M+Oœhºp“{w1QsøpYMAAY°»{Dp,ךn³·w¶lÞä¹jþ‡Ÿ®9Þ¼ïü­Î'õ‡”Ö–x¸GÅò¶qtÀ†z£ºå^ ²'Z½o¢Ùzº¸ êêC!šŸLËÄà_ >x±ïŒàu1:KÒ3Ï^ÀâVCø—‹7®uÇÁ¶ì5ºå‰‰«–)”¡ÑÞ°•™wlÑ—Ü)8ÐP¿¯$âІóÀ|VûÅñÝ! Q„¤ð©î1Ѱ <&èµGóª¼ge§”§!‡9_]]¾'ýã#½6®a¤ØšÍŽ.ó-’”ïÌJЄîZç•"Æ-þR Çó ŽblÑY]8j÷Ôy#v…AdB?š’Ù¯v5yøF†„k%u\6d©ÒÉ„„d"ÒÍÙš˜ŸÑL¤F^Tù‡Ùq¶³t/CI!/0Z™œÖ²Pœ”Y€ÞÛŠYÃÓ}ˆGoüP’Ÿ ÅLNŠ6$oÃö8—Ü÷èÔÆ§ÞZS Lu–6‡ï–µ×h…^  , ¾[zŸXwc~K(0âdi"²ü¤¬44 Šñ p†q»0‡M‘‘Ä“¨–VÕ¢mÈår¶uá¦Eøñ%4àÒ5­Ý&{,ýLôot©YƒÏ.íÕí5Ñ錶°´˜Ml®B%Ö|´;¤Qì ² ³¡ŒX^»ƒÃ¥W«>ƒZ‡\Øíë ¾f7«œÒC0uÉ^ž«€$`¤1‘2â¢üäÂ$$Xi©•±I1É uH…Àýx]¢t‚@‡ðݽvók•Ÿ)ªÛ;:ôáU4—X-½j…N J´À ‰FÑÐèMp!–ãðHá+ˆ@#ñ(:¼ÉÜ-æI85xÎmAcI±›Pc+sÙ›Ÿ™RFV¥ix~õ2ìüÔ}‡$ÀϳV¼›SC¶*;äCåUA‹iŠ•iQ¢Á5 (Ù$ ÒY¡Û­lS@µŸ§ØßW]HþªúzŽàÎK‰VpÞ4ÑÊäör›]¢’›ÕI²äüí_Kí“¢•‰Ldq”–+‡ìbu!CJË”cœ0¢OI¢ó,Z1 ްõ8üvÆ+žã¡¨²~ŠÞ@ÎöÆ9ì‡Î¨z 5þzóÆÕ·ñ8ü–3îó!ÑÑ`²5<'þL!Yt™·y¸HŽM‰õ|o}\„"Z®€ F\šRÌ•Áõá}Lûì)ÂèPð¨‚beZ z m˜fœº…jVŸŸg“S@ÎøWA ‡Ñ»³søja”ûxCD‡è '¾uhÿ¥–£—áõ{ Ûâ>sf½·K§ÑUhô¤&d=V˜»_mÎÃ’M«œ\Í~@é‘›ÁîpÛ'm(ظÃ(zb²B÷Ù–½úsp†¹¹ðs,Äý–l^ê[%×v +JÎK˨¯¿¹À|q¡™wp˜_ˆXá¥X*dD¿L*áŽÒ¿žüxÕŠ5˧ð;`n~ȱ¬¬l5h™Ê­X&ó›öd€†~÷è1'z×¶\pª#=Ѐ(ƒ©·VP{‰[¬ö¡46!$Ÿ|s“ê9”…)Úâ¼-ÎsAÔmËÙ‡è½;)LJ ¢C!E#eðí ‹Äè¹ ~.$¶·ÜCœÍ0Øj[gDJ£è_¨ÎäÀzƒ{’G˜¹]' _IÃå´oR‚Ë„‘ iàJ!3+'¯¦á@)NÑŸw,tþ`ñ'ïóA°,'èlVVN6±³VR. HØ9óÞdýúYq¢=›û îÙ}ßÔŠfìNäm뤀’®Z„Füx÷ì’¸¬ò“ ‘Lh©´ºJ«©kö:3žäç¸?vãD/p<²^ø+ürõCôô6Ü‹™ÖÃú(79â¬3ìl–j¥Z¡f”™@~T¹'úRf+4¤·µ^<ñåÓ/˜á´zÑIgj2Ï‘²èo:Æâx¹Ü‹‘ƒo£F“_Ëe¡&ôZHZ}iz:1f÷pø[:¹$ñ°~»0Âö4B™¾ÃÎtÚJrÌèjDä z‚ŠQ;»ÐåHË©–ã_ß>·yýj÷…ü×þì75Gšás÷½Û¸/î÷þœÙ¬>ºñë’Qó×­„ùÌøÇÓÑ d÷èÁn9_X cæàv¦S‹ÑpþÒÎ-_±ÔiÍÌŽî9«5÷×·¡˜Û$±G£j6üð­ ^ªð’̬,5h˜ÊHmˆXàWº &`>€,°‰ø%c+ãDl5v&q8ý`"þ}r NiŽ`ðèLvöºÏoÞ¿Ör?zI‰´Ú·`$ƒB©€HÉŒ†ÆuíꙜÆ“ÊLÖÿÄ2|ÁúŸøF –`NÇ»f´ò‚èÙë_=^ÙnÍÆ¬õŒ%&§É“HË4ƒoùÏgõg ž^!A>AïfζEgr×vâîJS4›Ÿ]˜CúNEDA4—iJy¾‹wØ'$Ç$’!5&'./ }=í‹2”¤ÞKÊ *x(#׳ñ~ädo‹Ö_½{U°ÏäjerAOÙ‚ÝÆwœÇ¿Òò]Æw›Ç <‘-j"w|Íÿ'ëKî4AßS›Õ$8¹j³6P˜˜Ÿ¿Gž¤Û¥©€‰Žˆ•nG®'¡ýØÉ“C\’YEIYl — ª¢\¦cÌG¿ìZÛŽ>úÍæ‚Þ’Y8VrîñÉÚ’¦Z8Å4‰ïc\Ê-ÅZ¡¨…¡¡BˆnÜåeÜã®ÛÑ™WÜ‘b݉»:-wCXŸœçõ÷¦efo›¥Öu„Ì×ü<7¢ádi+4éY4œ~­ÌáÈe¼Fæ ‹¦»Ûå¾=œ0ÉÒ×Óf žn@‡ ‚}FTMZÊZäÉVV@}]ÈxÜ·›¼”ðéXl½iË:`fÏ# ?½óÍo·ùF¸$Ñ`*=J[Ý Äw0;.Râd>Þu;Š·“0÷‡a'¼üwRI}ùsp°N[Á„´Ó¢Wy*¸oDÞfÞ@’´Ê¢hOEª°öFn¿ûjبj—‹{Œ}-O‰IŠzãp±EÒßîÒ]Y„"ˆÇO˜k„¢‹IyÕw8bŸ%Dˆj—cªÇù¾ÏQfš‡Ãkmh)±cTG—Tu;ÔÉòÞÝöIô{³R"¸DØ Õ™Y™YPòjîZþÙ–§mwÎüÀu©ÕÖb…jÑŸ,šˆ\möꈼ`‚áÓÍâüjHYb/\fƒÊÊ…ʈ‰Iã:×2qG¼:{J¿z& 9ÐQo2Šdؼ*ù[÷%È+2SÕÊt¦Û7#J&îYJ¬j¡‹jº­~Ïâñ¦vù.Ë™©_w‘hAG2VNŠ$Yh÷(#cÁÕTE,;d²ac½“%l:*P¨ã+Å@êšÎxé o— ý»$ßí ]8øñ¦•0ëeìš“#)ôÌJR'$@!åäe¨¿Cê‚ÓŒª=„~íËraƒÙ›bbÇRb©ò„ns· p¢ÜjÓu6v·,#˜z¤¡9Ñ^ýÑ#“LA*-oO+ô.QVƒC]AÆ>Þ¤®² ª#z¦k’îBË#ª!)ãmæ:Ãõ¤º„ãCø .¹ åå5è ‡=Ï™b]ì‰Ø“pÎB+|‘´ðB}Á]¸ Å®[`>¬X·6nMHø4èØ—IKg ÀÙHañðñã±Ç’ Ô.ïtˆµäwm’[ÿAÿ|héºuÛ–N –˜' õTÿ̳Å(ãA-ÝWžX¹'©ðpiicîõøŽ2ÿ4Ž+„ÈW©cNKO͉͇‚ƒÑ*Öž R}ü™„“ðœø*ïxáÙrí#h}T¾sîøÖö”ÊÃd›ïÛ'+UR`âhy$Dð¢JËH1S¨]˜jGàÅɸݨ5Š¢Ñ’Å×éG‡WnÞä¶j ¿ˆF®~ìgMe8À|?ï.!xÉÿX|iщÛtÔACPy8„Ávp†€2?M€>z0—*?Û×`niñ¤¥)˜DÅ®¨ 8zšƒK“P[+ÑÉó»¯Ý©+¨äŠçÑcÔŒjX}ò·Rx—Y¿må.6eî¨Ù^“zPYªÔ(Ký€1·Û›·âêsVå6ì0D_1×´ñpÙë`l¡ÇþàìKÑ³Ù¥Û <á˜ÃÉæã×8ÔŠßQûg„å'k»±Û¾» ‹J ðh\[àF"a5Î{<||ÔéÛPFô8SùDR”Ö]#ÕFä`DöݘiÿšV4ŒöMLôå _Ý9Úåë… ^ð=ÉŒ ·Œ(ÎÜþAÙyФ֝_ç|ê_ú±Î }¯{êW¸?ùéÓûÐÎ6QgÚc”šd²;°ÔüΘÎWtÐÈÏÅbÖEÌKÚæ ¤SS5 MãMöÿxr/qX»&ϳjÁ¡†ŒÅ¹M ‘H/]fä›”V¦ ²D~7PÎé‘N´;þ>qEÒzeY$ùò´I©N¨ÚRˆKKÚ‚·¤¸<„,eYÒ™õ&Gû=oN'òë!—WÑ×ÛµYÞ•P¹ …+>'ªm±¦”‡œÔ¼45Ó½¦œTÜÙ—#ØŽ3¯0ñ¯Qxbs§NÝm'vïåMü¶òLÌÓq¨Uªµ#É»±„*\1Ífk¤\¤Ê̤B®špËŒë_ÍÉÊ3+¥QEòÐK±Ýܦ]v—VWš™–«M5<5Ø5nkC.FQ¸©W[î\¹}w·C|Vbƒü…×ÖÞã·…ºèJ®ô¹ª&ÈQ©´éEªBóÖ—§üó¢cxI°&0K/9?çDáMК}¬ž‰C+Ø÷…YÃwFzE¹™78\<ö|ÊCó÷MhL&cVH‡ÙtLój£H†f›ìYä܉O -ÔæH»š–B8™IµUœ¨ùÀöC JO~B"4`Ú/#x‘l3¸Eúø3x£õ á…ó§/Ý<¿ðÝ Kœ—|èýà¸Ùxô•ApÈBÛH¶!«„d.âIÒ䘈- €yoÑÕŽë‘ Ó} ¼Ê»L^ L¥NS{c¸áùŸàáÓq¿Ç ;ÄïùEÃw:ô‹ý÷véÿç Ö äû¹ÝÀ(çÝLjúöài´¨Ù·Ö£dqÁ„‰X„>ÿ1£Öèkäg½X¸ÆmæÜÅŸ\kûùê•«—›×¸v˜1ü"lœ5¢J’ÝsÐVWMˆ^ö ‚ûNGh’í³±ˆ þ±‡Uf#ùHHLKŠÛ°6!ˆ óODϨ.²E7.œ½ „ZŠsGwÌ!­4ˆäïrã“ûVHm¢YdÛ£8lÑ·?‡:.5wg£¶¢Dñˆþ`îÖw¹uã„f™‘änÛcþ®´ËX2D^D νˆ¶^´«=aD®ÆOϯº.úW’£ÅìÚíÇNŸ;|øÔ™ƒ[Ö­vw_ÏOõf3û$ÍÀ<ºqt̺„Ú(½® 2³P¥®HÊFSQP[Q¿–ƒMÊ­>ÑùÞe[ygñ|Ò·i|‹#¦â¢ ¼‹Ä¹± ÜÈTÇÌx± Fƒ_´~ÇASä‰ 51ÙÛ˧³„N„HL7LlQ\‘R é™^”™Ç ¾ø;nþ¡Ã<”æ64h«Jrá0mÈf¸Ïß6®ƒ˜v¤‚y’s%‘™‡Ž²Ï6šÃ} n> Zñ𬖻÷ ïÓé¢îéß-¡ŸÞÜwòtQÐ'–îìt±™M wzèT!¼xô‘PÔÜvàØŠ¢(gË…Ýa¿õ·‡þÏGR­Cô4.gDU¤B¼?á:“~ÅÖØzÒ[xý4õB½~úÙqx;žÁ.p¹õø‡+W®]¿ìkýš.ÑÕ#DOjEž/Eýÿd-ݽèÍŽ}³ ¢¹«É‘í8¢<¹àZêÕÅ­Çt øãQ/þ 8Ú¤«`°ß¦Ð=R‘^Š»zÓ¬Y œ¯>|tÕøÍ­#s¸WAïÑÒû¢#HLzè~Fý9U¨FZL¹¶¤F{p&¿–Eº.gD_íé,ÜË’õwpëì5PÔ£†¬èÎ Ø]7 Xƒ¿Aô $µ&É”fˆ³3?*€O™ê†úŸ¸o¡( #D•UßÅAŒÝ$U®Hr×¹C±úÉ,/&¿ˆz$'¤9ñ›XÇìÚå;…ÛkòÅ·SJSóCºøÐøN:” %ª‚¦f¯Ó =‰Î´†oó¢gð;fu~Y)ò…á7­Àì‚i¤ÅæN4³GͼK¿öf½ki>p=á ¯7ïj+·¯2<ŠSº¬Ž—3NUuõëÖî´@6°*?”Ó³]“¢þg»ö!?uv¬ßØÝÀ¡ŠB9Î¥'Cop¢ˆp ¯IÏØ¦žB· ‚JS°•i!±¡®‡ ½-ÁÑÓX€oaºe£ÿÛ¯ ®ŽFBü¸ÀG :p(ƒ ÈßM„ëÐ#²2JLqV¦­fùf ‘<Ò‘¡4¡Œo¦7â“6J:µ:æhìÈKiùÞ„ÅD@a1;0—*%,f=:iÓܹ›-!ܼûuÔñq[¦$C¶öCFn©¡êª(£œ°—¬õM¸wfbAT)á.MQ’YÞ…*‚“¾Å,"$ÀfͨÞÝü¡†_0vÞ3›êî‰÷¶ì–í§QüˆgØì°\E½»7†üùïÑ€6<À&¨›¾{¯ÖØAwõ-Á¡ûÿ‡ÛaŸ˜]É‘Iþf*Y– K*›„’z¹ž1¨§ÑHü23 t…xVŒ8ÐÕK!S‚*+ ™ªÈRqpTdÈö=;š¹§pÙgæw;¤Ùˆtìß¾duZÒ5] çq'ÃÙja8Õ(]ˆ¯àæp©2 ¢:Ži]®&ܱ˜9oá8ž¸ÜÌqÐ ó§»_iX¨‚ý9¥û¤7£Öª+ëÍù°° &jº26B3U^ óŠö’mT’ÂH–&‡T*óøj%¤¥¯eðl!™–ÜN”œM: É‹úZ±*ÇÃ3`/Ô3h†ªÒ¸Ö¬*Þ­ªbºSçW"^c_}â¯yBË7þSÙ ,èáÈúÚÍÕË3½‰"uR–JÍ)ˆ~¾ &«ì(ö;$Yã§Ø© ^*$ƒ…£èPÙ¿ 4ü}øI[|G¥† g ‰vÅ{KöWUvZ_ªŠçCU¸Wº¢…±5Å¢~ÎWìî£ßDß™œL_²%²’h.’S’’‚B¢å¤0sc b ¥:† hI”T‘Ltqt —ê¬lu¾º¤ò '¡0¶0F¾j@_R¡Ñ×–C)c—oZ”‹æåÓ82[hècìkè×ÏØ¯?×Ç:2¨_oSùàÿäÜ„ endstream endobj 1757 0 obj <> stream xÚ]Moƒ0 †ïù>vš&H¦u„Z(šº/Úi×i$Q€ÿ~$ vˆõر_[o”•y©ÕÑ»3¢Â¥¥ÃÞŒN ÔØ*M(©Ä°f!ŠŽ[e'n_y‡}¼³ç¯Ûìtü¦ñÝå\Ð-Hl––ódØš—y5õv¥n $ ˆ>gÅ~plöÒÔxãkoN¢Sº…Í%«B¥­ýÅõ1IÓ G—›„‘Ø[.ÐqÝ"Iâ8…¤(R‚ZþûÛ.u#~¸# esg³]:óýÂOž÷ž ç3?xeÆ(õ¼»ò¼gUô½7WkÄèÜ|s00¸áW¯[cýTxç{xô endstream endobj 1759 0 obj <> stream xÚmUkt×ÞµìÕBÁåaÃYK !Ÿlh vC|Ê#˜74P$K6.²-Ëk É$?¥•…lccW2Å„º !˜-!†¼ÊIÛC Ð“@)$¥Mi¤î•ïB{e?HìÝ;sw¾ùfæÛ]–‰eX–Ï^öbfÖúd®xqãì´¨g^‰pÏ*ÄŽìÃÏ0x‹Scpš OŠMb˜˜¤ñteñ÷£ëÍqte´teÀ<ðL<#0)Ì<&ƒYÉlbÌŒ•)g¼L3ÓÁ¼Êô2g˜óÌeæ¯ìJv-›c5ØÌ…s®hÌÏË0lùyÛ,£ÍcþöhÀ<Œ­C1¢u0â›íãn£8 Ft䛆üßæCÔÄaÄÄ’Ò‚ƒ˜_T(šw¦ü«Åàó-&³#ßdNKû᬴´9™EVç@œ~FNŠ~vzú¼™ú9iiéú%4]Ž¡P¿Â n7G1r ýš¢œ|³èÔÏXå½ 5ÕápÌ2”Ì*²å-N™©wä‹Ûõ«Í%f›ÝlÒ/¥ô+ fý£¹ÍztË,*°–Šf›~E‘Él+¤#â'°SØ4v>÷»ŠÙH°õ¬—õ± ¬ÌúÙ6ÀîfÙ&vd›Ù¶•ÝËLŒÎ2–q1wÙΘ̘pŒ¢Z¢’TccëcïÇM‹«Œ»Á-çþ¬NÁÞøˆ(Üÿ ,Œz.Ä"Ó5Ud•pÿ¢>¿¯!÷HÖ¹,Ũ%]¬Ôõ:ºÒQß4õêÕ'À |s Th+ÀååäsòþTe+(é $ýMÑ£&r:$¾a<–׺ËmÀ·5A³nxV¼êš ÿR ;5€“fc=iB§ûÍÇŒ¯ïjõAð»ªÀ£ƒú@½ßw8ï\Ö9 ¹¤å¹ ŠHW¹MÒIß"2uþ|ƒÁçõyÁË{‚Ъm£äÚÛÑçèý{x+àt>>R5TìušöY¡?U'á/Ë?5½µúwK{І/ƒ¦Á{<¾¤†% õ·ö¢8|äÒ"‹wÍØœ²ÈN⽨‚,^1ªÁ$wÕÔ•i„[^V%IP.Yj«>—{+3DÆDçæ•›j Oßž‰Æ­êrSLàÃ2té`Ÿ$Wï6†ˆæOv4Í×-pöÿrýÀè³wÑ”‹MY†}Ð!ÉîF’u˃’á)q|_ðxáÈd”ÛG¶!‘ÄN’6#Ñ<õ?64r&ŒZ“¹4ÃQÈ/F>Õà“ÃŽ.¾¥±C-Hn*TPbIÏô‰ ©H%ZHŒíÎ@ý|J²´ø}ѯ]TüµAr“ñ)RÇ·ÕB©v8ò7ê>ª‘ZjÁüZ®´*t0M"UÅÄ¿Ni#“I?)"gkª¢Âæ={ ]»/ ì4 ‰hú´%¢ŽkèÝ#˜iè # mmïÃòwú“zYœ®ôhR–U{$ÔOv¡S¹À]Gþ8g{!kås…euKKH2ðÊóº—4ý ˜ I¦ì/ãÕ‰XÏ!«æy™?ÀÍE•q.DÛfÑÅ q„~ï !öû5ÝkÐXt‰‚›žzò%¢.°×¥“µý6‡ñ—M{(úîÉÑÿGM³’ŸˆË¡)p³"è{»ú†ëʦen}mÍCÆ¢×âbäD$o­ä…àÆÝ¶'*íÊ<» ¤GÅãÓøÞñW³€O«ð‘\Ífãú‚…ÛC…–ްAqu©Çáq¸]ë~–Øæ:uì̯ú`r/rvrõ¸zátïéj5‡Z:ÚÞ>‘ïqq†Ô'GŸü^oÓ˜1ô«ë,3 ]Oø-Jz‡ endstream endobj 1760 0 obj <> stream xÚ]PMkÃ0 ½ûWèØ1F> c)atuÃØnŽ­d†Å6ŠsÈ¿_í†v@OïIzÊêöÐZ û §ŒÕ„³[H!ô8ËŠ´Qa«RV“ô,«Ò¿É !û|éN߯÷õQ|==tç¦xÕq^=B¹ÕíA¬sÀ©µƒÎ@vº œ­°{֮ǻˆ½“F2v„]W‹„ˆÅû_œÐÈYU¥qÅõ$å4Î^*$iGd<Ï+àMS1´ú_oSôƒú‘Äø>2Ë|_&î†FU´ws§¢ËÞôƒä(.7ooòÎGUŠ?’\m> endstream endobj 1762 0 obj <> stream xÚUQ_HSQ¾ÇÍyÕiÿ´fÖîM´‰N#jaF L ”þùÔЋínº]›K:]»zrº¹?׿œS)Ð4_>ôÒ«ÑSD"=ô,çŽ3²;)8çƒßïÇù~ß÷@Èå àQÓƒ¶ŽæËú–ö'×3›ìïÖsòD*ž-R„HñB–X&ÏÈÕ»ÍòeÖy‚å'2Xr,ƒÇ%$.I £N¤Äxº´LŽ®ìc3ÙŸ±Îhfìv¦·Ï`î±™X†13,cá´Ú+ÕZmÞÚã´™º]Ù©¡kuºkUtV«£o³ÒûNƒ…n‘‰F*Ìt»µÓÄpNº²ÞÈq=7jjGµµW[mÝ š*ÚaâŒtcglÏ™.ºÑjáèû–¡ V¢ÞÊöôIâèkc³H&²%õD¡%ê$/o€ð`LŠ,rBC|Rë—Ȧ¶‘# öR¥²T+rGpi©P鯊>Èq ¥ Å·ë‹âÙ8@#Ÿeb-R=>8É蜣àÂèô` iÕÜOªYßBpÖòûB0HF< ¬—kæPåÔüÄŠ–8áРoˆΙÃ\òÓíçáKX20ärR°?ä}=¾m^Ùrà܇ª1¾ß=ÆzøQè&s®¨zNÁ•Êù¡ÄW³ónA˜ÆÕ0ä]›Œx×ùü)Y I¤[wâ=Mâˆ?è‡ »Ô“ÒÆaOz¿W {Üè‚® 'âwð†JŸ‚>H ¡@ÁÈXÀåOo¡•¸–Nü ‡Ë„óEñâ(´¹¹(öÆÁ*òÊPL´ÏÓ"ß± «ºŽ½CøTZ¯òCNB·"ÄÇÆ¦`fæ%Áï%ÑD怽2ñûÿЦ…È}TI¤S p½7á Lã;X.b Ý¥Pý?sWALî»EÚ—S·XÉQçÉÂÊÜ€2ï•2?™—ÌOÆ”Jé Ý¢?ëkb€ endstream endobj 1764 0 obj <> stream xÚ]“klSeÇÏY»úÂjACµF=§Î%³â§Ä@&š!S§ˆlLGÝV]Û­;]·¹µ§÷ËÓ;¥[;zÝalUS'0`ƒ‚x†‰1!¨ñõÃ{ê!Ñ3âãû៼×ç÷üŸç% ©” Iòú–¶–-Û_¼§±¹¹©aya£Qˆüu®â¬æo#øÛIžªâi ³”º¼Uú·¼êv‚ •7,+±JTâ·ÕËz—(²§o$ªIò:Åkl´WkسW«ÑÜ_¯Ñ¬o4õ ›õÝ=Œº®s­ú¾†† ëÔë5šõfƒÎ¬ïÔÕÍZ¦GgÐ2â¤Wý¼©S¯c†Õu{¦ï‘{ïµZ­õZÃ@½ÉÜýØÚuj«žéQ?§Йu{ÕO˜ŒŒúi­A§¾–Aý5m4ú,ŒÎ¬n6íÕ™",R›É&bÑKXˆ!qÉG¬"®'j‰;‰»‰F¢™ØA´5Ub^RÂ@„‰ ¤¹êæªC’‡%‡¥Õ4ïWð¿Ø •ú<ÉWáåûÂÚyAš´åû÷Á, ’,ŠE ±@صOx'<=ÿ¹Š9ß”èä´Ǿ`*8ë7eºþfUœÀ9.7ŒÞ2˜u¤©0ž‰F‘Ï&È+˜àg”3 ×Û˘ƒ¹\.q3”¸/¼PÀ›Ä3x+'Á['•ð 4l~Üã ø;á§¾ù¯øÐrl·ÞÚo2åûSÈÄö§¢’‚2~©ÌoÉ‹·ñ eÛ£þN¿;èuy¢îýTn1’+ž)Êkã·‡ü´3¤ ‹Y¦S¹HìVªpZa"úˆ9º7Þ~4:6Òâ°Á0»/ r0ÎC¦B“ð„a*8,'-?7Á‚~‚ ÿÌ–J•*P ÆF` 9Çý¡Rð—X.s·^ÉpäìøâOžåë”]nöUECéîÐôÔ܉ÖR;õ ôì°êàvR·kú— é$Dbáxù·OÊó€f‰UéÞ-<`Ûåê54o+ &ñéX¾7”2ö›õmg¬ ÔûpødfškúÀ9 gñMS˸4 AŸwÔÒØÒú" c_ö$ Åô{ÉùhváÄø‘Ùw—ÄO•ógHa)ò©T ›Š2A›ºŽZ)Ý—¯HÈW†ä5å•k¸¸\Ž/¯ù6Šö endstream endobj 1765 0 obj <> stream xÚ]P±jÄ0 Ýý¯”â$C¡=» ×+õ´£c+©¡±ã ùûƾpC ôôž¤'Ê:ÞY~§FŒÕg·…Ðãh,)+ÐFŽÊYMÒÊNÒ¿Ë ¾ìëüÈNâûåéziËgÐ8Ü—Õ#T{Ýq±Î§ÎêšÐÏmàà ‡Wíz|HØ9h ÆŽp¸2‘±xÿ‹Úiš<®¼¤œÆÙK…AÚI] ÔmÛ´ú_oWôƒú‘acòYœgîŽ&U²ww§–¶½ùÙQZn,ÞßäOªj>m< endstream endobj 1767 0 obj <> stream xÚ%ËOQ‡ïm‡òj«ª]”é]ˆ¤T4Á*j¤Ñ“ZMÄØ 7´¦œÎtœ"ôZj Т}ãÎ…1™•KcŒÿü4¹3Üœââ|çœßâä;p€:nNLï…ÏC3÷íàjòpÚÃej‡>tê^‹Ž¬úŽß¿ÃÙ-À¾SmvŸ0 ŽN¶yÖ„e¼ØÌ‹§^jBLâXH-¨¢Çé4~"Gâ~ÿŸß?l§±ù¨„…!t>F£~ÝH`1&D’(‘¢8‘Ì%ŽfRB K*JÒÂå‘EQ|‘DÚ—ç¯ #%&EÑ4Nc1ƒçЭTRBw# ŒŽ_ò3˜J,ÈQ(5‡Å¤)Ïàýà±éþ®Áu0 :, ø =úºÓøBU î6«1FUWµFš …d½­¯¶¬B2rT½Îƒ‹kÆo ~ÓŒ_šõà!ÝpѨÀò¬È1̶Ù65;-Ò<5sZâ[ZW\Le!:E—è2¤a*S•†Ø[bËl’…™ì5˜O£ú÷úÛú×Va§HÊ]å•­eþyIžçZ?Ù÷³Õœ9“¥ÜÖšþƒí¹wW $OºÞw7½¤ü¢°ò¶õ‰–Üú»VÞU©“FS&‹íWe"gê¤âuÒÏl£q0S‡Ô¡Yé%cÖU!õŒLžªüáhg–(&©Uygzϸ޴1ÏN'ßÃÕíÝ›öž7ö^­GëÕ*v»YºßÿÙ‡þW endstream endobj 1769 0 obj <> stream xÚÅTkP[e>á¤égEÔݦ¦ZÏIµ¬Õv)[:v[/;–¶Øj[ EíÒ‚‘’BMBBB€$Bò6„I¹@(k@ ih«µÔÕÞÖRgëuÆz«Ž[ë^tf×ùN÷sÆ=À^ü±Žã/ÿ<3ß9g¾ó<Ïû>€ )@pSÁÓî|rEþ¶][ÖÍ ¨mërøØñ#©ôxæ]Þô¬Ð°¼~<àö„¦q@‚E¢BEU,4¹Zfs‘µjѲ¿;"W’_û{› ig{{sýöju %x”…~Ϥ;Ôï<Q8£ßG9!±T4C݇}„Å@ªmØ4¡ý`‚gëSVQ"/²•Êâb–wOB€3.Ñ\ ·@ì ‚<(ÜäoàV×bW[£ïD„ä&’MVdŸÝu‘=ÇNDbþ²1M^€Ø_¸“* É"rÉÎ{ù¡/™«ðéɉ?üW>®8:çÀ…ë÷‰;ÝЛÛä¼Û&1»¬.0¡¦¿-6ì3ã-$ÉOgLU¯åAo`WšÆfl¿§|‡ƒ—†»_…:.Od“û~I¶ák[>þ·Úÿã^õÝ1|0Òwyâðš¿u‹©TËHle³ðësÝ~Y€KŸ§ñ×iq_sX¯Õê5ê»?dz¿Ñ‰g6ò,ízk¥z=¯¥¥éà!ÂÞ28îðäó×$Ýþç ‚^RŽ–®¬ Ù¶æ^èd‚p°ÓÓÛ5tè¯gõøXжL{9»±AÖnkÑÛ´`@Åêôãøž.&‹{{nq¹%ç‚Ó4–Lˆà„6d ZCÌtF¯tF‚/w}£ý—¼‡<áSƒƒ¡ÐèèïMtïçC¶ó²ÀTÚ¼ßiýÿ®þ>ƒ½#¾xÿ‰4¦á4z½<µ‰É‡’²U¶“C2>XƒQÞ h,â׎¯/ðtF£—#ãÀúzlÕ,èí\ŽïdŽßìð[4ׇÅ_ìxsù9¹,%¿È9³á^„âl¼”!~+Êßg!ýGjzôôÔÈ$?¢±ÊõDTº¹ê·{ªd3YÞh‰q+xKÖ|Hã>|Dìî:†oþ¼0 1³ÊÚ¦…fd5G†âÉÉ=ÅÌ(¯Ô*-ljg„‚|’–|×ì D¼¾$ÊÂ×x]‹’8?*À™hÜÏ-_…ýsUÇ> âí«—Å³õR –:‡iÉ•Ü?× =ÐǾ'ÚHRàj3‚yqirïÙ¯^ÁÙ=þ¹êãgÒ¨Þ$+.d1¹Sÿ Ïl&f ]=í;×LÑp7ˆ_­ 4èkõ¬î6ŸÍß©ƒ=HUB\dþö¶ÓC œˆ]ûswÜã‡è/¤Æ¢j­ßE–ƒªÁ {ŸW%Õ“Ž ¼~ _;ÊfÕŹ|?Öì‹‹ˆÌ??¹àÒ of&³@¸6šyG/ü>À‡‡ endstream endobj 1771 0 obj <> stream xÚ-‘Il†gâ! ©1‹bÕRÛɉ’Š(5e©R•" )¡¡ ©Ô´ˆÅM‡ØŠíqœ±ÇŽ=ÛóxÇ»Ý:Ág¤ ”ÒCX.pàÂr@j/l*(\˜±¦ìˆÃû¤ÿ=ýÒ'=Á0EÑG‡F_{vpddè¥öâ圞:ˆýØŒ=¤@´ƒ¨v¨C# Ú~Œ¸7Œýkì8„ ˆúD›»µùëãm>Ó‚á䓆¢¸oV°ZŸï·Z Òž ×1igÈÞ‰#äsÇûÈcVëùª‹ò:&lnrÄÆØ)—i'9FO8(&Höž´3ŒçÄÑ£@ ßæšé§½“§Žô‘c'ߤf(¯ŸºL¾F»ò ›‹"÷Üû÷8H»<>†ò’#ôeÊëFÔpq S-Å‘aä4‚u (‚!ß —:4ÞÔ¤áí÷[¨VÑþ4/)’ô)à¿tþ]rŽöÀ¼àáœ"/,G—9¢ RV*ÕÕs–ʈˆÎi îÖ‡-\xq>©EH¦2«Ÿ©¦õ-Õ øÏ×@‚<¯xpÓ§ÙÍÑì(ˆÐns<ËqóÀ⢮uh¤ê€o®&ëFÃøÔ(ü,Aä´”’ó óÅ88Áþ¤/ÉH‘$”p“6U´ýŠÚ½üUU-wê?ÔÝ&f®ËŒÇ=íö^ ­(×׉3ú_f9›©É™TFÎBß¹°~á鋺ÅÇʱbË;µ˜ÊܸÿåG7¯¦ÃL!!~^ï¶DÜ „a†Y|üÖäíÝmÕ²"‰ù 1"›ø`nüÒ™qÀƒ±|­ª‹¥Â:njöFUù­¨¨ï~ŽªúOßþaPï6ûÌIYZ„+PˆQÇb–Y1, *@™Xƒ4_à 7§“v,ܰ àÞj¬Ddáª\¸–.lª'ÒÊwì÷sp¶udù> øÚ¡¾¾¿¡^ú_LH°³ÑIú•–[¹(CòJuoòpç…Ú©t­´\ÞÜØ¾ùÅÖm(´ž”‰Úã!üøÔj¼¸òqy{kJ¹Hœ†³o½=qþçôûó¸É¿¬ fs9ճܩ¿—}˜èÂŽW¤]Iã¾®»û6d£Q½×ýרzð endstream endobj 1773 0 obj <> stream xÚcd`aa`ddäõttñ õÒvö Ž4 ضÿóa5ü¹Œõ‡4ÃÆ²L?䘈³È=ôbùÏÃ$ËÀÀð^D¾á‘/@¤:`”b`adä(­ê400Ö300rÎ/¨,ÊLÏ(QÐHÖT0´´4×Q020°TpÌM-ÊLNÌSðM,ÉHÍM,rr‚ó“3SK*4l2JJ ¬ôõËËËõs‹õò‹Òí4uÊ3K2‚R‹S‹ÊRSÜòóJüsSÀnדÎù¹¥%©E ¾ù)©Ey@G1]ǰŒ‰‘‘EëG߯°ï%û¿ þŒaþ¹á{‰èì%ÝK—uWËÿåb«.ê.,\Ò=[ž¯xñOû%l¿§³Ëq1OSýÏÃ9‰‡«‡‡{?×~îý xx€˜÷ûCÛˆdä endstream endobj 1775 0 obj <> stream xÚm“{LSWÇï¥årT†ØX|Ü{E2°<\Â\Ôlc``>˜‚q‡¥^h…R,•ò†^(þú¢Ï¹ÔØíÿg˜SºûÀvÔgqðt=ØÚ›+u©§DJL”Hñ`Þaï§³Å,”@á‚ä¾ïeø üP÷R˜Áô ùUúcq#>¢jÿƒÑÎÛ¬bìâ¸Ò¢i±fªk€ªæNk7ã†)G—ݧ¾†@»P§.ø¡¦´Bb;tºúŽ&Ý× xÍ‚‰ý"!&î3’fvý…·>ýÙ×ÕÐ×ÂXÁÖÁ[ò²öseÖ>10â¹íC]E¯ú68èZ°J/ª ˆ‰BážI5ó2a_Rü‘ñ0ETˆÅ âv1b>玕·Òâ€èQpù—¿d 4ôÓøÝÛOfG®š¾QœÁ@IÝË…ûKróŠN,Á‡ÄcAœ~[ÐÎÉ~W*šÏX[9@MRnm‹—év;Ÿ|âs/Ö†Jð1àöŒºÎ_ÇÛ”ÃÜxõ @8¯Æ,N{Éä ÍYCãtá`1蠢ʬ­ÖÕ†VÔÐôy°;;/öÏÌHXÐò Ôu´ØZÑý÷.¿Ýá ÍNþÏïlËsN‡Ûî–ð³-;Oq“IÉšÔxÓ™°MˆRhyÐCªö5ú]·àîlÎèqC‰Hr4œí5 Õ WõvÌ6 ·}ØÇ‘þìëb] 9ÎÊ÷C]pœèB½¯²ÜhV½[ø§LâåÓ4|·kàŒ§ [çI¸tïsz®6yKQ ¤lVñ›ƒ$^óH†/ qŠ(¿7ü»k™4ê:Þêê¸cGÌnž.f}ZLR¦PÕK³ÓýÌ3*C ¶š¥)¶ÄæLùàÏ{˜õyë¡®“†´µ¡`[¾¹±mx˜ô8½(¦rHHïÁ&»ˆOõD—Ï­¸££éåò´ÁèeÂÚµÿĺl> endstream endobj 1776 0 obj <> stream xÚ]PÁjÃ0 ½û+tìÃNÆv2-%#…¬cn?À±•Ì°ØÆqùûÅnèa ôôž¤'Z·ÇÖšô+8%0Â`¬8»%(„GcIQ‚6*îUÎj’žÐº“þSNô|ú8 ñ؉÷®`O×KS¼‚ÆáF¹¬¡Üëö(Ö9âÔÚÁç€~oçV8¼i×ãCÂÎAc0v„õ‹÷¿8¡ÀHUåqÅí&å4Î^* ÒŽH8cð¦©Zý¯·+úAýÈ@øs³1Ë’½dîŽ&Uòw·§–¶½ù ÙQZn,ÞÿäOª¶ÈmX endstream endobj 1778 0 obj <> stream xÚcd`aa`ddäó÷r÷ Öö vò54‰˜…ü±áTÿ¥ÃúC†á‡,ã9¦òÌ?ÄYd^ ‚Èçü ò±ˆTŒ‹„X9êZ:Ss J*‹SK Œõ Œœó *‹2Ó3J4’5 --ÍuŒ ,sS‹2“ó|K2RsK€œ…àüäÌÔ’J ›Œ’’+}ýòòr½ÄÜb½ü¢t;M…òÌ’ … ÔâÔ¢²Ô·ü¼¿ÄÜTˆóõ ”kiNjÐUŒö@¢‰‘‘eó¾Ÿs;7ÿèßÌø D2ÿ ÿ±Ytæôî‰Ýýó*{:åZº;:+«í<$Ê:žúÍÒÍñÛä·ÔoáßVòݺ›BæçU×tuD”Wvvv7qÔOnž.7©»·{ç%¦4^uø.ÐÍñÝî»Àw¹ïúòÝ/’V,ëé™8¡¿ŸãOØïç¢Qºw/äø®òý;Ów9¹oÝÇý¦6p,Ë]?'²;ˆã·ÊoößL¿åäºýO4Nãà+ŸÿÓqÛï¤é웹6s¯›ÀÃļr\,æóy8¿;ž¥ endstream endobj 1780 0 obj <> stream xÚ]‘ÑoÛTÆ}“ ¬Ñ­ÃC“Jl¡ÒNê5ëâ&£Ô!D*ÙÓ¸ ¢Œ¥UgˆÚ®¢*qÂŵ³,8}%Büáe{ÛÛ4}oÿ€MBj©zœÝeâÜÄ-²teùžïøû~‘B!‰¢|ôî•O¯¾7öÙçÓ~2=~5=7ÿí-qÏýóÍüthàÞ+Þ˜ä]$ÞxÀzo†Þ’$2xOéïAq>9-NЯ¯Kg ½zâäé³çΩo¿sa,ß^¦1Ʀh,Nc ªOP=JõKTŸ¤úeªÇ¨®S}Šêqª'èÔŠNLD#“ñÉ÷2†F2ߥ—Œôœf,h³Ë‹i-ª}±¬ÝúòÒ¢½¨e—æ #Ÿ’tÁ0´oÜœÏDz‰Ð*‰JÄ$%R&ßF~ Ù$6qH…Ü%UrÔÈÒ™€D¤€4)-J i›Ée’Æ«?…ÀÃ@'.‚\¶„õç»ÊVÅ­ª¬RvÌM>£ H1 rm£–Ëç7r|Vx¾>åýÞyÔ"Þnç7EÜ…9eüú*FL»h™¼‘+¬© _m"<s1È0¹V«ºê±øùce+WÙX±\2ù(á©n’ůòÕ¼ {‡•¦Šþàk4x÷\µà®‰Û0ã4ÁS¨5Kå"+Èb¾«°ažy»ŠVY}”‡wx •Ýa‘öø äo‹<íŸ[„µ)GÿV2H%]mšN¹Âäª[ÙjðuXåª/Èz•5·P ;̱l0?\ßAe7© Ãø:_5Ôâ,SÄnqF®;BÁ¨½i9¬"‹l_Åy‘àhäÎ5…9X†Íg`f,õã2Aó»0Ë“6:tŽð¶S/œiß|qÇï¦Î¸µ/øÝô˜ôºIòY¨kÐøŸøZgZ)b-¦Égð±†q‰üš&÷’0kÛhÝéZžá4}ÿ'Ÿ:¯sKèM+*v©‘Jâ#Ë ù’8ÛÆÀ=g¨Ûç.‘û59Š8Šû£ ég_aÏît醡ÎÀ ú¹øÑ4wyóe-kO+¾3äÖ>î8îPå ´¡qdÕŸ¤×Ë*½õPßK¨û™ø ±"»Ø—¯lhmÿµ½=0Ðz­÷rÒ+½ñ/Vc?@ endstream endobj 1782 0 obj <> stream xÚ]AkA†çKQ“F+³Pe©éÁ¸-ÙÖÕÚƒEÔƒBK#( …m»B(Mb\]{Êe·»®ënv/¹Ø!ù…zoÞÿÂ|0{p¶=膙y™™÷}˜o> Ù,€Ò£Æ“ÆÊÊíç/Ü_<÷TÛi½ÙK ň?!9¼I°8›ÁÙ ¼–½Nù3•èÏK‰~»œè$—Œ…ä&rçóÅ©’ n¨ª¢ÞU>ï©uY­+ª\ãKVj5y~±¾ø°ÓÖÅíNû­ÖÓµQïˆý®&ÊâÖ¾¸÷r¡«Ë’hôZº®µ“«õ펮‹«ên«=V.!p.uX#ÏH‹¼æGx.|>‚O.d ¹C¶È€|!ªÐ„¨ˆ=A©d¹ÎÍNâ²c¹–×Ì¡+„^è÷Ë>ߺC3ê{B§éw\à„åØ6;Š+ãù#¬¤Ò¿â%7tBvŒ3–Ïîiº}Áã{zÏpÇzQä …¤šßqù,ý§ÇÓ¼¼=ø?ï².5{¬™@Ü´üx“6SX`‡n²f [¦k€»uú–pÌ ÕqÈ`ÕÈ;º øŠ.óŸÇ“l;Õ)4¨©>qâ+àý|Ú«x‰Ž1¡ÏÝÃ45º8*FùQa«*? endstream endobj 1784 0 obj <> stream xÚ]T{PTç¿—}ÜK\#WÑš»K(j|D)H„bå!¨<•]y³XX–°Þ¯"á‘€ò•D³4*©ISgê£MuÔØ–fÆÄ¦Ñžk?Óöb'“Nþ93ß÷ù}¿ÇœCSR)EÓ´Ãö_Å„Çm[¶-ÖwîbÓ.R³L:ø¼D&ü‚–ÑÂkv/œ¥¯Q½tX)2®>tš««Ä¼JIišÍ;löòZ¿ÖËk]N_“–’jP­LöPyûúú¬Q­óòòUfisÒ’ÕÙª0µ!U›¥6ˆ‡LU´.9Mk(P­Ü’j0è7{zƵê¬Üµºœ5*cš!U¥ÍÕæäk5ª`]¶A®ÎÒª^’^û²é²ôymŽ*L§Ñæd‹\k(/jíCùR;¨½”–J£²é:O$í@- RΔ µ”ZMùPÁbGIES»ÅN';Ц¤T ÕOóôY;¥Ý€Ý’=’¥2iºtT6_6 ·*ñ.ÙÛ…èM?D fœàÊý4Ñû´åï–W@){ÜRÔÜþì!*o¤^‰ŠÓi4É}š)¾ :[šXGáQ‘Ux`¥/ +æá‰0†¿ç¾«À"RI*LÄHìÜjˆ+±¢õ(áI59Ïé!Ørl¶tþ —á:Üo¼Øþ§/Zza®¶nmÜ! ¶™W¨É‹O,H‡¹ñ¾1h£¯¡†¢›D8…y\¬Ü|´äí#eÇÊá0°ÄM>=>sñãáû×þp ¾aÑ^u›¸§U‘ž1ÖÜáÁ±ž)ºKÎî· Ÿœ¨íöÞTø[JJ Ý»‡ä½Kq1T‚‘=$„3sâ&N£ç³ñÏÑí¬•¾‡Ëq=zK°ïr(¸DpW)‹ ¸:aèBkóô°Ó’R²cß|Kñ×wžÌòðeÄ "ûàïÃ#7àSövÀgăÌ÷ Ýœ8¨³ŽŸåaèÐ©ä¦Æ†ÑþÏ€ý vd(!:ÃFÑýtsqe¡Š¡Œ5¶@?ǨK¨Egãq‘Dø0Ë5µTÕC {Šbò¨ê‹kŒu• æ6VžJše“ò–íõUÐ^D¹¸YîNìÁœŸéKœ ˆBØí—ÍÍ|t¼WW×Þup³ Ãç7_¦;Ñ‰Üø(þÃJ‰‹p7ºJw<ÃAhÙÎCêcï$ïÝ ¥™]§[Z{¡—ËèI×kÇ…LF"‹Jôþ3Öñ0Uñ}ìÓl»Î¯#ZîæG–‘¼ÑCyÆ».±„IåVÃÍoÃ]¤•ס'º¦Ä’»!M( ö«Eåÿ,²¶ã*!ÒF÷à:T¡R"$=_ÀݵÉTl…ý‰¢­by<ª^aÞJÖ†ñFH¯Õµ hs±¥ô'ÐêbïÄ¢º}=óïø/§’®ç2ý¼F \}kmÓ-`;lò=HŽÎ­Šј^†Þb’ú"Å…d 9²Y›<µbPûF|Ÿeðô‹ÿXômð>,yÚÀÒ'º6bÇà3¸ÉJá4#ô˜ÁuYऺÍv\J<Ñ/:ñKBYüí ôGß±gïuÁ¤,³ÉtÔ®ß)ö¼nFΦ<#­¾P'ÊÚC-q¬NfÅÁ>¾òHœ\T D‚e nJÝ—’®Ñ¨Oœ8gíÿˆ'adÏ\m’\ ‰g¾¨n­³µV~¢Xn ÜÇçî"ÎV_A{<ˆöá^åp^PïžÌ‡xï²#låS9 ,•Å33?âܪ±€u´îˆ8!¨fP:{~æ\g~O:~þ<7K¦qAñ?G,s‹â2fs¸Øó{âOÞÞ@hò*qúË ÀûOqOÚI(GÁÓ¯îÃäp¬ðÙ®„S: G^ʦ‘F R¸P".–lnö!û¸¦¸¸ü0²û‡'»Ç&c†"ùí›·‹­DZNü~®¡>úð*L‹$7‰$š¬ÂÂ3ôÈ-,»%\…-\´ùãPXZp<£MS+î¢L²ˆ‹^ÇÅyæ{G[ QlЛÇÇÂŽÖìÙò•5ùÀ¾¦\¥+SÅ|TCw[ß —‹™ÓsSØßPÂdö`A{⹌º-­ûw6Ã;ó7èæÅÝRY­¯:ÚÍÀ~XU÷R ÉdEråÿBr¹µD1~1qþþïvOóø5CÂ~RYÈú¡ñ1?¿ƒÉÛlƒ!õ2Q #Jü7ãXd"›pg³EN›?ÏÚ¤P ýI…ÿŠÔ§Sa_¥pxçÿ+°oá endstream endobj 1676 0 obj <> stream xÚå\[S9’~Ÿ_QoÓÝ•š˜˜ƒ/`_Û¸=~`mÆM¬€ggÿýä—RÕ©ÒQá‚6»±q‚*•.©Ì//J©Î!Û©.šÐ…Øé}§­ãçÔÅwk:5ß}g-¡Cìœò(¤ÎqïȵŽPAªóºèLç#îL2hôä#cm ÎwDLÕ¥.žÅ›N+‹¾d¹Ä}¢g’:0gž»Z&9tâ‹åÇÈcµ³(0ïNHSè´ÌWT\HBSØ•Ü#:ž0r/ôˆÄ3“g¾Ð)…NL+á¸Ñ(Ó1Ú¡?qAh%n4Ü“çp ÉvÆ2¿¤ØI\r\ ›7šœP Vu¤¹WpÒ?2Þ,iî äþdW±NˆŸÈðÔI M©³Š±%ÃúQÁ Š:«0«Î·•f-2èÄJcuZT©Îº -ÓòÀ0‡ /wc26¸-j!a¹ÄºçRè,1‡ÄÚ³£ŠMl>ä¹-1Ð\Åæ¡X}ĺtŠ r•ïœÓ…„w2üDljÎZ™‡Í˲xÄ`;0¡æF0H°AÏÚ#6<Ä`]„ú¢2\J(in%¶9be:‚)D†Ã%¦H¬=¶0¨CçÛ%˜4WÙÎÃöƒãEÁqu“XBfAÆq ¶—xjï < @2Xˆª‰}9JŒ¦‘ ¬;O–íž5æ“ÜhKQ¤0]PÎBº ÚÀ–ÙTƒa4¸É0\ï4Daaƒ‰™$»@c+a€&†-ƒKV 'Š–¡ÐlD(˜K̉JÁ¸I)H_”0aÊ»¢çgE»À^‘H!káçâ²bEZœV'±ªÀ} â&³‡°à±lRä&ˆ¹èP4€Ê1O‹‚EÊqÃ`Ñ–§ë œLðk ¿ÃÊU<»%wXW!~(6 @ëŒð€`Á&¦¸àÅÌØG´ƒ§°Š5‡=ŒE—!ØÅ5¦…µ±Å•KN€}ØüaJ¬Y–8NÁ¥”8ª„9-Ã1—Ô@>8Á*DíDÀÖ*‰FXŠâ©ILEXÊ6Àž©!Š„Ëò¬$¸²ÀʱZ#|Aöö{~„mhᙃÂ#‡T"|:F*@ÛìЕh‡°U[*¹=RÐia¯„öd}‚…sÉÎÝyU`õÙ$# §dPÉ@+…&b‰2Xº€['¦ƒ«(ÏWG¶7€,VAؤ0üíoªHÐrqDbpÉ=¾ñ;ieäÓÓO¥ðÐEY¼÷eùn2ÂñiŽ‘X1bÕ ·œ„!—“·‚#exåÈwßSy‡rÅ’›†*–\fóþÙÙùÕeÎ|¸Bˆ;Û$î—wqR…xE’–“¼•EYÊй¡»VÚ¬Èi…ŒäYß[ú ãÓ9’Î$±æHfV˜€ï)…öŒÅùYõ’­àò3vïÝrö:ÁFP‘!îŠÑz3ÃÀ¬×«˜qÿ –“H3$ìbÁ,4¼ ÞŠ=ÃH˜e¤Ž©ÁÏHËIÐ*‚D9‹Å5bÓé£_L<®9}X9ýbà‚+€Å–±Ü×Pc3Ò¼—Ôq™ê HÔŒSä–“œñ]ŠËI„ÛX\Ž.²÷Ëwm¨Ó#2z—²ƒ' š8ͺ â穬٩˜S2-¤Yóø‘ôÉV:É”eÒTdL±9IZ> Õ“˜~¤„ëÄ‘þ-$Žô±"n:B铊‘§Œ>Ò×|d˜¹.”{l²<‡«Y^ÃÃxè¬YÒ-Í’v‹'Ñkš «IB“8-'kâñæ #+ϲªroÇ\2³1&U‰ 5CÂ-'aWª7Eå9Ãæ;•{+’]Χ­caJ·P§ÂŽ)÷góï¨jwšÉ¿i6ÿn+máлbÞ®iÞn9Ÿ®2ï¨ô-,É>Ùââ––f¬Ó0^ârï)ƒÆÎ3®éw³yyT¶–:ÖR»ÖJ³¹ë:ÉIîzMâÕhý#Wsi%oå4äý,+¾fÅÕÒ­B–o]Ÿ–§šxˆ‡b•¡i•Á-ž$¬Y%-²Ê)¸¾X¥/Ñ'̵0ï“©f¬ÝSTËI¤v1‰¸0»ŸÂQvjJðz†‘¹ì>ê:zÄÕæžbO¶„**¡Šš™ ÙÅ“P•™D­›ÎJËù¾>Íœ°ì§©dôDîVÉj‰ƒÝ8Í€–\Ѝ¹H¦ÙФëДT  \65ƒMòˉ×ÁF¯’°fÆK³oƒxlô²ÝYÔc½QÑW*ñ µ8©y›¬v;I™a9 ?C"-'A Íx GÊ+©¼HÉ÷Øf¤ j1R¥aIë~9 7C‚–“ˆ·£dÍ)Ÿ¼1j2b殊Ïi&{N³Ùsƒ„!—“·‚#‡¢Trádü­R¹â˃Õú8=| s‡å Ï=‡ð<ˆ0Ë%éBÃ' ºÏ0ÝpPxsïäÓéñÖù¿ÞC‹)Çd åí‹“ã«ó‹Ÿžžuÿuzõ[÷OvqqòîëñÇÿä9Þ|yqþéÛÇ“‹Ÿ>ýóôë§üþ¯îï?¥•²†þþóÏ™Èéùك㫓Ÿü…›¬ŠxUã“I¿(ûg¥þüsžïÅד³ûÑù}ŽMN¯>ˆh{çŸN6__ž¼øvõåôŒ%}~ü;Û‡¶%Hôõ¨É~"€¬0¶¯Ž¿œF°¶!l`¨—D×Ö_ë­Ý°ýU™ ÂÉɆÃËQ¦´ÞÐ¥UuÖª ̃ÝH'<¥‡1ªPèïytß¿žmʇÇkÜ€þŽԥ셂µeH!µÆ{áC•‰ôeÄЋùfÃtÎ@§—K¢Ñc”øïßÞn1…•”ó½úÞ'˜P¤Ä e`ã1 ¼ALx¦”„ï ‚ •G¹ ߤç˜è9GwC±`gŒéQ(%GÀyů5ŠûÚ dieI-ëº|•Ñq›Àßúõ™e/};áÊû ÈgþÓšdÁfÞBˆeöåcÕšÕ@{f¨u.Š„Aì/$¢1#Ýy‚Ýy±™|¥†%ÎÌ.vîUžS #s½›ÍWžUêJ‹ô[^úgF4zŠÅc![–-Òeï âÁ‹“+òÛâEè‘iö3^%{|rŒÍåX| èú>Ï©•‘å1;÷J03°8Vȸìj£²U¢‚¡G*ך•à䢰¡wîaÜÚJàÉÀ[3빜¯npxæE‹ä„˜nŒòôS†ŒÂæw4†Œª&mòJÿ±Ÿuª…õkovµ©¯j‹Éý"BG°ÙØ“§….4þXŠnü,®™k=oL—þM©òö|ßï"¶L’ÅŠ7°0ýbÎ –,È£ÍÁ*)OìI+¹¡™Ä¯"åN G³,4ÆI|,O¨µØ_™=L%Ë r*Có‚VÊl—¼¸y]dε=2X$ú§Œq5ôÌ=\„TÎË• ™´fr9_…h‘g õ'=Ò q2Ú 4r­esɇ?z­4차ĔdaE;ƒ”‚6ä;[,?Tcq”D$]%YìBô,¿V°çfbãg’‰È&(‡A‰dD•NV?­ƒ)3çk…w‚/Rø2îZìÙYxR6ÓcRj®¹&ë@Æ }ûÔIo·ê!ã²ì¹\®â§ZÏÊ|?N‚(éÅ¡Åk72^«‚dN0§|-õ>‡ë>¸d£¾éµ ¨.g âsZÜUMËŠ&FŽ0áK*&nDÝIV³<^^ˆ9$E#áD°(4s/—×îéS-}æÒáë–aüTPêòóª¶ä¤:Õ›Jê>g·Ònû±!HH–ÈãDÖܯwÚœÁH ƒðq^“Ë—³¶J†<,nyɇD-QÏ …Ëq°aô´DIƒw?̳Iò«œ×†²KPð9Ö.Ó²7—‘Mßd³9+$3ZNñª=Ö*gåÖÈÒŽÜÖ¿ÊXyÈ»$îa8pŒ\îðÅ@xuÄ·ìrê¸wù¸óظ€œ½äMQBœDzî5ž²Pž‘µá„oW¸'ÆÖ#XÜîú£ÓŸúÌÙEsí^†Ã%ð€Dä½´HDqA°ósC@^eÐ$¨ôƒ†®xg<› ùlë~¼ÿñ*û7ð¢iÖ¦¾¼5fÎ’Mb;E#Ö!4Æ•×örSd¦ì1™NûÒ]ÿ©…s©[´ü¸?ðÉDNkns…ŽR’X¦åx¹8!ÑvX•8ŽqÄäå5%Ù¤b³¥Ö!šärõG®™N¾*IGܰ1PXr„t’šÇWh‘bJâL òå~øò/¢šðŒH yž<ç Stµ^Z>¦ªÅ!?'qä˜q¸÷Oë-ß=MÔjÖÊ)™Q"ÖäËõ˜ŒyÃ6·â¯°Ñ2—´~Þ >:?»Ú<øöWx@Þ|{úéê·Ëü;¾ü’íâòjû·ã üâÙq)k£7·Ž/O„Àó£Ý½w¯~ÙÞ;8Ø:ÒJ¨>8¹üxqúõêü"ÿÖmúE…iÍíã¯;'§Ÿ»âÔÌmÞ¿üˆž(¢Ê÷4?ì^9ýxÿìó—“Nm\üþ?Û|ôåøóeg‚Ñ>Ͻ…÷•÷8Wºgäœ=áØQ}¶G§_Nð+³òUxYXËPñ:‹‘©1 #Œt\aôêõáÑÁ¾Ðçêu„ÂGÈ7Š=@a„§Œ ïÿpQAc§ÐLX_ Œ«Q3Ƴµ}´ÿh;S7 `â]™N˜` oŒñÛð5`ü˜ ë×sxþúìôãù§ÉïœWXÅ«1TaÕÃGovÞò|ûM'£ÅH‘½R!5rªw/ªÝ‹¦PY¿RiŠ”­CÒØ¨´[!õîèíÓ#1ÙwM¨Ò- RPj‚Ò=N5”+P±™g¨â8±÷~*«5Þ ú)V¶ Eæ—ƒ•¿v<ËV`i=¶+³BkûŃLj}íèÔr´ÂÍ¢7ël&zûPÌKËÿa¨Ì«|÷|€l"Á ód¡†ÌŒ!ØþãÃǯv󄨕ôA¦Ò,d6Ç.­mÃ#ËwíÈ&Ü2ª K×BfW=}rôêè9Ox¸Û´2ó£Ã×Ä1µ“  X™iX™SSÈ&,‡¬ü¤w€ÌÕIƒ™sÌûOv÷vx½6döN!‹¦ ™éã¾£dUî0‘`aîà®ÍôhA||°wøâ« 5Ðqwµ63Û,U—*uq¾•:6…qªiÔ •'ûo^n æ-XüÝMÓÏØ»ŠŸé8Uh °ªÐ±“$Ê|êÅî³7 ~x˜è,ÏÃy9íÑá‎ank¥›ÜßÊ9.þUD…Jª\iÄøBTüÚŽV¨øñîäå¯^"åØ Lâ]9w_ÇÄô‰%þ_Êš­ø*Yq¾<"û*Uò×§J£uÿÑÞÎë™®e1ÙÚÚ>z!ÊháeïÌìì1€ü2'_® ª² 1ïK ©C4ÞŒqLZeÎG;û¯ÞÈV¦ÌíRg¿ÔÔõ{±ÖÆ"Ti,ÀBtb Ñ8GT£th÷ÕÓƒ£±ÒÐ@Çß):äèèþ0Ûðnr œX%Ecþ—‚cæ]j€vï?xþ:G·2á®Ê7÷¢¼ˆ%üÿ?kä‹Å(ÕVtÌúRPêh 3;ÑgÏw<|'æØZ±âÝú“½ÞŸRcÏ« éX€å9VGÙ±>Ê£”1Œƒ^;ÜÚâ9Ü?Ø™EH«ÿ9„ðNË_O•¶X_ O:7ó’ñáÎÛçï¶äL·±ªë»;”ÖqöPš†(ÔH©JÇ0£ÿ¢â’• endstream endobj 1812 0 obj <<6c29951886913b2f2ef8e8a926bc40d4>]/Size 1813/W[1 3 2]/Filter/FlateDecode/Length 4040>> stream xÚ5ÚwPUišÇñóœ{îÅ€ŠbEALÀ„Š9ƒ1‚bÀfŒ愊æŒ 末'ôNÍvMOÏÖNõÖn×ìÌîö†®žížÝÞË÷yî?Ÿzê÷¾ÜpÎ{Þsxßë8ŽóÓO®(qæá\×ñ¯sîQoÁm¸C§Žã¸ŽSÝqÄé_U{Þ§µw‹#]¬Ðú¼„ÄEzèdža5¬Ž5°&†c-¬u0ëb=ŒÄúØb#lŒM0 £±)6ÃlŽ-0ãÄñ¾³o×’o÷˜:[aklƒm±&`{쀱&bvÆ.Ø»awLÆØ{a öÆ>Øûa€qÆ!8‡ápLÅ4#qŽÆ18ljþ;>韧Ôã1'àDœ„“q NÅLÌÂi8³qÎÄY8spÎÅy8`.æáB\„‹q .Åe¸óq®ÄU¸×àZ,ÀuXˆE¸^œ&Ivd6pd^PoÄM¸·àV܆ÛqîÄbÜ…»qêU¶÷á~<€ñÆR<‚GñÇX†'ñžÆ3xÏáy¼€ñ^Æ+xËñ^§ÕZ;2782¯¨oâ-¬ÀÛxïâ=¼•øâ#Ô+ô êh|†ÏQÏÂKÔ÷}oð-¾Ã÷ø?â§ _gB÷ïòøü_WÍxA]ô¡‡~ `VÃêXkb8ÖÂÚâôýÞ^¹Gæ uÖÅz‰õ±6ÄFØ›`FcSl†1Ø[`,ÆaKŒÇVØÛ`[l‡ Ø;`G섉˜„± vÅnØ“±ögDM;½8ï©S°7öÁ¾Øû‹“þGû«üÕîDûðÂR<*NÆë?þÅÉÚcIp¶ $Û™LÿãX†§ÄÉg=‡ÐÓG~Fœ¼e–%÷‹“ÿsK†‘èxŽ©â¦Xk­ÕÄY_nÉ'#q”8[ýÖ:šV9cp,ŽÃtqvŸ³žãé]‡¿°$ƒ$Bœ²2K&Ôçlš%Iê‰s9Ù’I$ ĹnÉd’†âTfZ2…¤±8Ï*-™JÒDœ÷',É$‰ç¡÷Ê"i*Îß„¾û4’fâ|QlÉt’q¾:hI6I q~:ï3HbÅùæ¢%3I‚÷ñ?Õ°dI+q¾«mÉlÛ9œÇsâ|g­shm+ÎOW-™K¢c~ÎÇ"þ'Ö'—>Djϳ$D¯‹…"õZ¾ˆ`­hM£Þ(²ãºå›ÈGˆ”„Fòf’Ñ"ÿÉ’-$cDŽÅZ²•dœHÙLK¶‘¤‹œÍ±d;Éx‘òŸY²ƒd‚Heè»ì$™D],òd¼å»È'‹¼ü%»I¦Š|œ`É’L‘_„¾c I–Èç-ÙK’-òe¢%ûHfˆüCèŠÛO2Kä_#-9@’C}‰üw7k=Lë\êR<‚Gñ˜È¡#yœž ¨O`™¸n´µž¤5ú”¸Õ~²ü4ùBq#WXr†d±¸ÑÿeÉY’%âÆý%çH–ŠÛ64'Ÿ'YA}AÜ×,¿H¾Šú’¸É,¿L¾†úЏ)¡Ùï*y¸ýþdI9É:q‡ö³äI¡¸#¿µä:ÉzqÇø,¹A²AÜŒKn’lwjh\Ý"Ù,nvhn© Ù"nNhÄÞ&Ù*–Ü!Ù)n~è:ºKR,îš9–Ü#Ù-ná}Kî“ìwÛDK*IJÄ=eÉ’ýÔñ‘¸§—ZëcZu„<Á§øŒkó^Árq/æÚ_=ç¯S¿À—âVü£µ¾¢UÇÒkþöº¸O÷ZëZS¿¥õ¦¸Ÿ…ŽÞ;Z˨õŽÿAÜ¿íd­i=C|sןÄü¹¿®j Ö"îgµKÏsÔ>q¿Ë±Ü#Ž¥+,ñ“\Ÿ/Í’É%ñ…÷³$Œä*u5¬Ž5°¦ø;Ö3œžåâ‹ÛnI-’kâKØkIm’âK\hI’›âK¹`IÉ-ñ ýÂ’º$wÄ7ö7–Ô#¹+¾©+-‰$¹/¾œê–Ô'©ßâзk@ò@|+ÿbIC’ÇÔÄWÔÓòÆäO8G|÷-G­µ ­OÅ·«À’(’ôÔ•„Jòhñ•†>sSú¼ßÙ–4#yMƒÍÅWþgkmAë;ñÝûÉ’X’÷â{:ƒq$Ä÷&ô[’|ß§Ð_Åóyñýj´%­HD|¿Ý`IkŸø~ß’6$žø¾É´¤-‰_|ÿò%íHtT$ˆï?wXÞž\GHñýð–w$¯)ž·Ä’N$uÄ«¶Ù’D’ñ¿µ$‰¤žx‘ÿlIg’Hñ¢¦ZÒ…¤¾x1Ï,éJÒP¼Ö,éFÒH¼ŽÇ,éNÒ„:{`Oñº<¶>½èÓ”:{cñz†FK_ú4oP¢%ýHbÄÙÆ’þ$qÔp ÂÁ⥷³žúlO=‡‰—z¯á´¶¦Nov-ËÓÈÛQÀ‘8J¼¼¥Ög4}ÚSÁ±âåc­ãhíH.^Ñ)ËÇ“'Š·ý…%$Iâ•\±dIê‰8 'ãñFYÏ©ôì&މЫe’tïÌK²Hô\LÃé˜3Ä;ßÝzΤ§ž‘Yâ•fùlòà9º[b‰>Ùö§ž#ÞÓ\Ëç’빘'Þ›ŸY>Ÿ|0õÌï³Ð‘Ì£u¨xŸÿhÉB’à™úU–%‹H†‹÷Å—–,&Iï«8K–è™ZŠËp9æ‹÷÷•Ös=ƒgóëк’dõ*\-ÞŠ­u ­ã©×Š÷ï¡Y¨€|õ:ñþòWË É'áCñ~øƒåE$“ÅèjÉz’)âL¶dI¦ø›gX²‘$KüNZ²‰dšøû ³d3I¶øSÿÃ]}!þI¡;ÈV’™âŸÕÅ’à“ª÷UÕQ úó°œÖíÔ×ð:ÞÀ›x‹>;¨oã] >Køã«Îx°u'u.æáB\„‹éSŒ»H–ð Úºõ î¦^ŽkèS#±>}öP7À†Øc}J¨›b7ì½xåúìÅ}ä½±Ä!´î§Ž#pNÁ©ô9@…Ó1gàLú¤>…gð^À‹ô9„‡I.áe¼‚ú,QÊç‚Ã0õ³=¥Ï’‘8 GãKŸ£Ôãp fb]^ç=}Žáq'ÉuêxÓµulèñÙ…»±„W¨‡z¯?gHšc ŒÅHZÏRGc:ŽÇ Ô«øõDœ„“QÇ•ÞÝÎSGc3ŒÁæKŸ x‘¿Õq8‹ZÇÞlZõlæàœ‹ó1—>z®âbl…­± }t$´Ãö¼Kêc¨gJÇI9­ú™õÜ•áIZõJ?gQ¿i&êýHçîØS°êAg‰A8Sq9êóáMÔ9¤‚|.Å|N}ÇÛÔqØã±ê½ûuìŠS1‹Ö»ÔÓp:ÖÂlœAŸ{¨s×LÔó¥³D[Z+©°vÄN˜HŸÔ±+&ó:zÄ–Ðç!u \E뜋~ú<ÂÇ$ Ãj¨ÿ5<¡®51kóÊGèó”Z¯ëy¨Ÿ\§>ŸèUÙ 1 ;£Þ¯Ÿã ’Ù¨ãVgc}þyI=3pND}†yE=[âXÔÙ[çÞ×Ô:ëL«s©Î–:¾Á·øŽ\gÈRÜŒz7Oý_ ~Ný$úd¨3˜¾ï|‹úÊéôùÈ·® ±1Fѧ€>Ÿ¨ƒÿK®gõ&Xo¤O?ìÈuVˆƒ°F½j\êᘆ:–z ^}:—êý+{cìKý$ùÔšë'Œœ‡Ã0 GâhÔ¸‚Z_g%®ÆµX ×a!ázÜ€Õ±nÂ-¸·¢Žg}}îà=Ô+1õŠÓkê¥×”~*½ÒÛb;LÀö´&¡^/u0ëŠ'OžÁžkYÏ×9DÏf®Ã XˆE¸žþ:SmÃM¸·àVÔgží¸õy©õn¥O>{Pïz{qîÇxáaÔ§½ïë p ã Ô{ôI<…§Qï¤ú­õžx/ Þ×.áe¼‚WQï2×ð:ÞÀ›x +Pçv½â=Ôy¸àKÔó«³¢Î~OQg°ç¨sÔ|…¯ñ ¾Åwøž3¥s¦^ÝŸHô— "þ#éV»èCýÀ0¬†Õ±ÖÄX k£îÇE`]¬‡‘X[`Cl„± Fa46ÅfƒÍ1cQ÷°0[aklƒm±vÅöØ;b'LÄ$ìŒ]°/vÃ=°'ê\ öÆ>ØûáÔ}´Ñ8ãŠÃp8¦bŽÀ‘8 'à‹ãPi03p2NÄIX€3p*fbNÃé˜y8gálÌÁ9¨¿“™‡óqæâ \ˆ‹p1.Á¥¸ —c>êLµWáj\ƒ%¸×a!¡ÎZú낸 7ãÜŠÛp;îÀXŒ»p7–â^܇ûñÄCxÏã<ŠÇð8žÀ2<‰§ð4žÁ³x¯á¼ˆ—ð2^Á«XŽ×ñ6êo nâ-¬À;ü­»x)¨óC%>ÃøŸà[|Ž/ñ5êlóNüì _MWYumY°:êJ²®îÖ@]ÖuÚxl„ÑØuõ²¶ÃÖ˜ˆ Ø»bOLFÝŸ…}q êNôHÔ=èTÔÕ±¨;º{«;¿º«{ˆº‹:u·T§î]ÎGÝñÔ]HÝ;ÓÝÀ|ÔFÝC,BݹÓ_šéªø)Ô½3Ýù*EÝóÒ]­C¨{OGðž@Ý[Ñ#݇Ò&ÝÒ=+¨û2oQ÷Vâ3|„º[¡û¯øœºžÿ‘Ú•°ÖüŽ%X0ð:êš[ ¬‹ 0 csŒF]kÕ•çXl‰º^­kź €PWzuM¸'&ãÔµÙÔ•U]›€ƒ0uutêúáD‹é¨+Ÿº†9gá|ñ? âÿy˜Õ¹âÿµWõtýe®%yâÿ홪äǾ–,ÿ_KƒIÀŸnÉ" Š«’ ,Y,Ø!UIÊ6K–H ÷ƒª$+ß’¥˜vÁêeX}ÔêåØ8Áê| ”ì³z…ÊûT½BÅpKVJàv¡Õ«$ðË»U­ÿ–`Éj |[P•ü9Û’5ø~¿Õk%Pµf(a’dI„¹3­^'aÞÿZ](a5 ¬.’°:1V¯—°ˆªw kXÏ’ ÖhÕ%¬I†Õ›$¬Y#«7KXó)Vëjáv܉»pîÅýxã<†'ð$žÆ³x/âe¼Š×ðÞÂÛxõ—¢ð‘„¥|ã8ÿí*L endstream endobj startxref 473829 %%EOF glpk-4.52.1/doc/glpk.tex0000644000062000006210000000760112175147600014151 0ustar maomkpasswd%* glpk.tex *% %*********************************************************************** % This code is part of GLPK (GNU Linear Programming Kit). % % Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, % 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied % Informatics, Moscow Aviation Institute, Moscow, Russia. All rights % reserved. E-mail: . % % GLPK is free software: you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % GLPK 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 General Public % License for more details. % % You should have received a copy of the GNU General Public License % along with GLPK. If not, see . %*********************************************************************** \documentclass[11pt]{report} \usepackage{amssymb} \usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, urlcolor=blue]{hyperref} \usepackage{indentfirst} \usepackage{lscape} \usepackage[all]{xy} \setlength{\textwidth}{6.5in} \setlength{\textheight}{8.5in} \setlength{\oddsidemargin}{0in} \setlength{\topmargin}{0in} \setlength{\headheight}{0in} \setlength{\headsep}{0in} \setlength{\footskip}{0.5in} \setlength{\parindent}{16pt} \setlength{\parskip}{5pt} \setlength{\topsep}{0pt} \setlength{\partopsep}{0pt} \setlength{\itemsep}{\parskip} \setlength{\parsep}{0pt} \setlength{\leftmargini}{\parindent} \renewcommand{\labelitemi}{---} \def\para#1{\noindent{\bf#1}} \def\synopsis{\para{Synopsis}} \def\description{\para{Description}} \def\returns{\para{Returns}} \renewcommand\contentsname{\sf\bfseries Contents} \renewcommand\chaptername{\sf\bfseries Chapter} \renewcommand\appendixname{\sf\bfseries Appendix} \newenvironment{retlist} { \def\arraystretch{1.5} \noindent \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} } {\end{tabular}} \begin{document} \thispagestyle{empty} \begin{center} \vspace*{1.5in} \begin{huge} \sf\bfseries GNU Linear Programming Kit \end{huge} \vspace{0.5in} \begin{LARGE} \sf Reference Manual \end{LARGE} \vspace{0.5in} \begin{LARGE} \sf for GLPK Version 4.52 \end{LARGE} \vspace{0.5in} \begin{Large} \sf (DRAFT, July 2013) \end{Large} \end{center} \newpage \vspace*{1in} \vfill \noindent The GLPK package is part of the GNU Project released under the aegis of GNU. \noindent Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All rights reserved. \noindent Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. \noindent Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. \noindent Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. \noindent Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage {\setlength{\parskip}{0pt} \tableofcontents } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \include{glpk01} \include{glpk02} \include{glpk03} \include{glpk04} \include{glpk05} \include{glpk06} \appendix \include{glpk07} \include{glpk08} \include{glpk09} \include{glpk10} \include{glpk11} \include{glpk12} \end{document} glpk-4.52.1/doc/glpk01.tex0000644000062000006210000002772012175147600014316 0ustar maomkpasswd%* glpk01.tex *% \chapter{Introduction} GLPK (\underline{G}NU \underline{L}inear \underline{P}rogramming \underline{K}it) is a set of routines written in the ANSI C programming language and organized in the form of a callable library. It is intended for solving linear programming (LP), mixed integer programming (MIP), and other related problems. \section{LP problem} \label{seclp} GLPK assumes the following formulation of {\it linear programming (LP)} problem: \medskip\noindent \hspace{.5in} minimize (or maximize) $$z = c_1x_{m+1} + c_2x_{m+2} + \dots + c_nx_{m+n} + c_0 \eqno (1.1)$$ \hspace{.5in} subject to linear constraints $$ \begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} x_1&=&a_{11}x_{m+1}&+&a_{12}x_{m+2}&+ \dots +&a_{1n}x_{m+n} \\ x_2&=&a_{21}x_{m+1}&+&a_{22}x_{m+2}&+ \dots +&a_{2n}x_{m+n} \\ \multicolumn{7}{c} {.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ x_m&=&a_{m1}x_{m+1}&+&a_{m2}x_{m+2}&+ \dots +&a_{mn}x_{m+n} \\ \end{array} \eqno (1.2) $$ \hspace{.5in} and bounds of variables $$ \begin{array}{r@{\:}c@{\:}c@{\:}c@{\:}l} l_1&\leq&x_1&\leq&u_1 \\ l_2&\leq&x_2&\leq&u_2 \\ \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ l_{m+n}&\leq&x_{m+n}&\leq&u_{m+n} \\ \end{array} \eqno (1.3) $$ \medskip\noindent where: $x_1, x_2, \dots, x_m$ are auxiliary variables; $x_{m+1}, x_{m+2}, \dots, x_{m+n}$ are structural variables; $z$ is the objective function; $c_1, c_2, \dots, c_n$ are objective coefficients; $c_0$ is the constant term (``shift'') of the objective function; $a_{11}, a_{12}, \dots, a_{mn}$ are constraint coefficients; $l_1, l_2, \dots, l_{m+n}$ are lower bounds of variables; $u_1, u_2, \dots, u_{m+n}$ are upper bounds of variables. Auxiliary variables are also called {\it rows}, because they correspond to rows of the constraint matrix (i.e. a matrix built of the constraint coefficients). Similarly, structural variables are also called {\it columns}, because they correspond to columns of the constraint matrix. Bounds of variables can be finite as well as infinite. Besides, lower and upper bounds can be equal to each other. Thus, the following types of variables are possible: \begin{center} \begin{tabular}{r@{}c@{}ll} \multicolumn{3}{c}{Bounds of variable} & Type of variable \\ \hline $-\infty <$ &$\ x_k\ $& $< +\infty$ & Free (unbounded) variable \\ $l_k \leq$ &$\ x_k\ $& $< +\infty$ & Variable with lower bound \\ $-\infty <$ &$\ x_k\ $& $\leq u_k$ & Variable with upper bound \\ $l_k \leq$ &$\ x_k\ $& $\leq u_k$ & Double-bounded variable \\ $l_k =$ &$\ x_k\ $& $= u_k$ & Fixed variable \\ \end{tabular} \end{center} \noindent Note that the types of variables shown above are applicable to structural as well as to auxiliary variables. To solve the LP problem (1.1)---(1.3) is to find such values of all structural and auxiliary variables, which: \vspace*{-10pt} \begin{itemize}\setlength{\itemsep}{0pt} \item satisfy to all the linear constraints (1.2), and \item are within their bounds (1.3), and \item provide smallest (in case of minimization) or largest (in case of maximization) value of the objective function (1.1). \end{itemize} \section{MIP problem} {\it Mixed integer linear programming (MIP)} problem is an LP problem in which some variables are additionally required to be integer. GLPK assumes that MIP problem has the same formulation as ordinary (pure) LP problem (1.1)---(1.3), i.e. includes auxiliary and structural variables, which may have lower and/or upper bounds. However, in case of MIP problem some variables may be required to be integer. This additional constraint means that a value of each {\it integer variable} must be only integer number. (Should note that GLPK allows only structural variables to be of integer kind.) \section{Using the package} \subsection{Brief example} In order to understand what GLPK is from the user's standpoint, consider the following simple LP problem: \medskip \noindent \hspace{.5in} maximize $$z = 10 x_1 + 6 x_2 + 4 x_3$$ \hspace{.5in} subject to $$ \begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} x_1 &+&x_2 &+&x_3 &\leq 100 \\ 10 x_1 &+& 4 x_2 & +&5 x_3 & \leq 600 \\ 2 x_1 &+& 2 x_2 & +& 6 x_3 & \leq 300 \\ \end{array} $$ \hspace{.5in} where all variables are non-negative $$x_1 \geq 0, \ x_2 \geq 0, \ x_3 \geq 0$$ At first, this LP problem should be transformed to the standard form (1.1)---(1.3). This can be easily done by introducing auxiliary variables, by one for each original inequality constraint. Thus, the problem can be reformulated as follows: \medskip \noindent \hspace{.5in} maximize $$z = 10 x_1 + 6 x_2 + 4 x_3$$ \hspace{.5in} subject to $$ \begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} p& = &x_1 &+&x_2 &+&x_3 \\ q& = &10 x_1 &+& 4 x_2 &+& 5 x_3 \\ r& = &2 x_1 &+& 2 x_2 &+& 6 x_3 \\ \end{array} $$ \hspace{.5in} and bounds of variables $$ \begin{array}{ccc} \nonumber -\infty < p \leq 100 && 0 \leq x_1 < +\infty \\ \nonumber -\infty < q \leq 600 && 0 \leq x_2 < +\infty \\ \nonumber -\infty < r \leq 300 && 0 \leq x_3 < +\infty \\ \end{array} $$ \medskip where $p, q, r$ are auxiliary variables (rows), and $x_1, x_2, x_3$ are structural variables (columns). The example C program shown below uses GLPK API routines in order to solve this LP problem.\footnote{If you just need to solve LP or MIP instance, you may write it in MPS or CPLEX LP format and then use the GLPK stand-alone solver to obtain a solution. This is much less time-consuming than programming in C with GLPK API routines.} \begin{footnotesize} \begin{verbatim} /* sample.c */ #include #include #include int main(void) { glp_prob *lp; int ia[1+1000], ja[1+1000]; double ar[1+1000], z, x1, x2, x3; s1: lp = glp_create_prob(); s2: glp_set_prob_name(lp, "sample"); s3: glp_set_obj_dir(lp, GLP_MAX); s4: glp_add_rows(lp, 3); s5: glp_set_row_name(lp, 1, "p"); s6: glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); s7: glp_set_row_name(lp, 2, "q"); s8: glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0); s9: glp_set_row_name(lp, 3, "r"); s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0); s11: glp_add_cols(lp, 3); s12: glp_set_col_name(lp, 1, "x1"); s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0); s14: glp_set_obj_coef(lp, 1, 10.0); s15: glp_set_col_name(lp, 2, "x2"); s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0); s17: glp_set_obj_coef(lp, 2, 6.0); s18: glp_set_col_name(lp, 3, "x3"); s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); s20: glp_set_obj_coef(lp, 3, 4.0); s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ s30: glp_load_matrix(lp, 9, ia, ja, ar); s31: glp_simplex(lp, NULL); s32: z = glp_get_obj_val(lp); s33: x1 = glp_get_col_prim(lp, 1); s34: x2 = glp_get_col_prim(lp, 2); s35: x3 = glp_get_col_prim(lp, 3); s36: printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", z, x1, x2, x3); s37: glp_delete_prob(lp); return 0; } /* eof */ \end{verbatim} \end{footnotesize} The statement \verb|s1| creates a problem object. Being created the object is initially empty. The statement \verb|s2| assigns a symbolic name to the problem object. The statement \verb|s3| calls the routine \verb|glp_set_obj_dir| in order to set the optimization direction flag, where \verb|GLP_MAX| means maximization. The statement \verb|s4| adds three rows to the problem object. The statement \verb|s5| assigns the symbolic name `\verb|p|' to the first row, and the statement \verb|s6| sets the type and bounds of the first row, where \verb|GLP_UP| means that the row has an upper bound. The statements \verb|s7|, \verb|s8|, \verb|s9|, \verb|s10| are used in the same way in order to assign the symbolic names `\verb|q|' and `\verb|r|' to the second and third rows and set their types and bounds. The statement \verb|s11| adds three columns to the problem object. The statement \verb|s12| assigns the symbolic name `\verb|x1|' to the first column, the statement \verb|s13| sets the type and bounds of the first column, where \verb|GLP_LO| means that the column has an lower bound, and the statement \verb|s14| sets the objective coefficient for the first column. The statements \verb|s15|---\verb|s20| are used in the same way in order to assign the symbolic names `\verb|x2|' and `\verb|x3|' to the second and third columns and set their types, bounds, and objective coefficients. The statements \verb|s21|---\verb|s29| prepare non-zero elements of the constraint matrix (i.e. constraint coefficients). Row indices of each element are stored in the array \verb|ia|, column indices are stored in the array \verb|ja|, and numerical values of corresponding elements are stored in the array \verb|ar|. Then the statement \verb|s30| calls the routine \verb|glp_load_matrix|, which loads information from these three arrays into the problem object. Now all data have been entered into the problem object, and therefore the statement \verb|s31| calls the routine \verb|glp_simplex|, which is a driver to the simplex method, in order to solve the LP problem. This routine finds an optimal solution and stores all relevant information back into the problem object. The statement \verb|s32| obtains a computed value of the objective function, and the statements \verb|s33|---\verb|s35| obtain computed values of structural variables (columns), which correspond to the optimal basic solution found by the solver. The statement \verb|s36| writes the optimal solution to the standard output. The printout may look like follows: \begin{footnotesize} \begin{verbatim} * 0: objval = 0.000000000e+00 infeas = 0.000000000e+00 (0) * 2: objval = 7.333333333e+02 infeas = 0.000000000e+00 (0) OPTIMAL SOLUTION FOUND z = 733.333; x1 = 33.3333; x2 = 66.6667; x3 = 0 \end{verbatim} \end{footnotesize} Finally, the statement \verb|s37| calls the routine \verb|glp_delete_prob|, which frees all the memory allocated to the problem object. \subsection{Compiling} The GLPK package has the only header file \verb|glpk.h|, which should be available on compiling a C (or C++) program using GLPK API routines. If the header file is installed in the default location \verb|/usr/local/include|, the following typical command may be used to compile, say, the example C program described above with the GNU C compiler: \begin{verbatim} $ gcc -c sample.c \end{verbatim} If \verb|glpk.h| is not in the default location, the corresponding directory containing it should be made known to the C compiler through \verb|-I| option, for example: \begin{verbatim} $ gcc -I/foo/bar/glpk-4.15/include -c sample.c \end{verbatim} In any case the compilation results in an object file \verb|sample.o|. \subsection{Linking} The GLPK library is a single file \verb|libglpk.a|. (On systems which support shared libraries there may be also a shared version of the library \verb|libglpk.so|.) If the library is installed in the default location \verb|/usr/local/lib|, the following typical command may be used to link, say, the example C program described above against with the library: \begin{verbatim} $ gcc sample.o -lglpk -lm \end{verbatim} If the GLPK library is not in the default location, the corresponding directory containing it should be made known to the linker through \verb|-L| option, for example: \begin{verbatim} $ gcc -L/foo/bar/glpk-4.15 sample.o -lglpk -lm \end{verbatim} Depending on configuration of the package linking against with the GLPK library may require optional libraries, in which case these libraries should be also made known to the linker, for example: \begin{verbatim} $ gcc sample.o -lglpk -lgmp -lm \end{verbatim} For more details about configuration options of the GLPK package see Appendix \ref{install}, page \pageref{install}. %* eof *% glpk-4.52.1/doc/glpk02.tex0000644000062000006210000032131312175147600014312 0ustar maomkpasswd%* glpk02.tex *% \chapter{Basic API Routines} \section{General conventions} \subsection{Library header} All GLPK API data types and routines are defined in the header file \verb|glpk.h|. It should be included in all source files which use GLPK API, either directly or indirectly through some other header file as follows: \begin{verbatim} #include \end{verbatim} \subsection{Error handling} If some GLPK API routine detects erroneous or incorrect data passed by the application program, it writes appropriate diagnostic messages to the terminal and then abnormally terminates the application program. In most practical cases this allows to simplify programming by avoiding numerous checks of return codes. Thus, in order to prevent crashing the application program should check all data, which are suspected to be incorrect, before calling GLPK API routines. Should note that this kind of error handling is used only in cases of incorrect data passed by the application program. If, for example, the application program calls some GLPK API routine to read data from an input file and these data are incorrect, the GLPK API routine reports about error in the usual way by means of the return code. \subsection{Thread safety} The standard version of GLPK API is {\it not} thread safe and therefore should not be used in multi-threaded programs. \subsection{Array indexing} Normally all GLPK API routines start array indexing from 1, not from 0 (except the specially stipulated cases). This means, for example, that if some vector $x$ of the length $n$ is passed as an array to some GLPK API routine, the latter expects vector components to be placed in locations \verb|x[1]|, \verb|x[2]|, \dots, \verb|x[n]|, and the location \verb|x[0]| normally is not used. To avoid indexing errors it is most convenient and most reliable to declare the array \verb|x| as follows: \begin{verbatim} double x[1+n]; \end{verbatim} \noindent or to allocate it as follows: \begin{verbatim} double *x; . . . x = calloc(1+n, sizeof(double)); . . . \end{verbatim} \noindent In both cases one extra location \verb|x[0]| is reserved that allows passing the array to GLPK routines in a usual way. \section{Problem object} All GLPK API routines deal with so called {\it problem object}, which is a program object of type \verb|glp_prob| and intended to represent a particular LP or MIP instance. The type \verb|glp_prob| is a data structure declared in the header file \verb|glpk.h| as follows: \begin{verbatim} typedef struct glp_prob glp_prob; \end{verbatim} Problem objects (i.e. program objects of the \verb|glp_prob| type) are allocated and managed internally by the GLPK API routines. The application program should never use any members of the \verb|glp_prob| structure directly and should deal only with pointers to these objects (that is, \verb|glp_prob *| values). The problem object consists of the following segments: \vspace*{-8pt} \begin{itemize}\setlength{\itemsep}{0pt} \item problem segment, \item basis segment, \item interior-point segment, and \item MIP segment. \end{itemize} \subsection{Problem segment} The {\it problem segment} contains original LP/MIP data, which corresponds to the problem formulation (1.1)---(1.3) (see Section \ref{seclp}, page \pageref{seclp}). This segment includes the following components: \vspace*{-8pt} \begin{itemize}\setlength{\itemsep}{0pt} \item rows (auxiliary variables), \item columns (structural variables), \item objective function, and \item constraint matrix. \end{itemize} \vspace*{-7pt} Rows and columns have the same set of the following attributes: \vspace*{-7pt} \begin{itemize}\setlength{\itemsep}{0pt} \item ordinal number, \item symbolic name (1 up to 255 arbitrary graphic characters), \item type (free, lower bound, upper bound, double bound, fixed), \item numerical values of lower and upper bounds, \item scale factor. \end{itemize} \vspace*{-7pt} {\it Ordinal numbers} are intended for referencing rows and columns. Row ordinal numbers are integers $1, 2, \dots, m$, and column ordinal numbers are integers $1, 2, \dots, n$, where $m$ and $n$ are, respectively, the current number of rows and columns in the problem object. {\it Symbolic names} are intended for informational purposes. They also can be used for referencing rows and columns. {\it Types and bounds} of rows (auxiliary variables) and columns (structural variables) are explained above (see Section \ref{seclp}, page \pageref{seclp}). {\it Scale factors} are used internally for scaling rows and columns of the constraint matrix. Information about the {\it objective function} includes numerical values of objective coefficients and a flag, which defines the optimization direction (i.e. minimization or maximization). The {\it constraint matrix} is a $m \times n$ rectangular matrix built of constraint coefficients $a_{ij}$, which defines the system of linear constraints (1.2) (see Section \ref{seclp}, page \pageref{seclp}). This matrix is stored in the problem object in both row-wise and column-wise sparse formats. Once the problem object has been created, the application program can access and modify any components of the problem segment in arbitrary order. \subsection{Basis segment} The {\it basis segment} of the problem object keeps information related to the current basic solution. It includes: \vspace*{-8pt} \begin{itemize}\setlength{\itemsep}{0pt} \item row and column statuses, \item basic solution statuses, \item factorization of the current basis matrix, and \item basic solution components. \end{itemize} \vspace*{-8pt} The {\it row and column statuses} define which rows and columns are basic and which are non-basic. These statuses may be assigned either by the application program of by some API routines. Note that these statuses are always defined independently on whether the corresponding basis is valid or not. The {\it basic solution statuses} include the {\it primal status} and the {\it dual status}, which are set by the simplex-based solver once the problem has been solved. The primal status shows whether a primal basic solution is feasible, infeasible, or undefined. The dual status shows the same for a dual basic solution. The {\it factorization of the basis matrix} is some factorized form (like {\it LU}-factorization) of the current basis matrix (defined by the current row and column statuses). The factorization is used by simplex-based solvers and kept when the solver terminates the search. This feature allows efficiently reoptimizing the problem after some modifications (for example, after changing some bounds or objective coefficients). It also allows performing the post-optimal analysis (for example, computing components of the simplex table, etc.). The {\it basic solution components} include primal and dual values of all auxiliary and structural variables for the most recently obtained basic solution. \subsection{Interior-point segment} The {\it interior-point segment} contains interior-point solution components, which include the solution status, and primal and dual values of all auxiliary and structural variables. \subsection{MIP segment} The {\it MIP segment} is used only for MIP problems. This segment includes: \vspace*{-8pt} \begin{itemize}\setlength{\itemsep}{0pt} \item column kinds, \item MIP solution status, and \item MIP solution components. \end{itemize} \vspace*{-8pt} The {\it column kinds} define which columns (i.e. structural variables) are integer and which are continuous. The {\it MIP solution status} is set by the MIP solver and shows whether a MIP solution is integer optimal, integer feasible (non-optimal), or undefined. The {\it MIP solution components} are computed by the MIP solver and include primal values of all auxiliary and structural variables for the most recently obtained MIP solution. Note that in case of MIP problem the basis segment corresponds to the optimal solution of LP relaxation, which is also available to the application program. Currently the search tree is not kept in the MIP segment, so if the search has been terminated, it cannot be continued. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Problem creating and modifying routines} \subsection{glp\_create\_prob --- create problem object} \synopsis \begin{verbatim} glp_prob *glp_create_prob(void); \end{verbatim} \description The routine \verb|glp_create_prob| creates a new problem object, which initially is ``empty'', i.e. has no rows and columns. \returns The routine returns a pointer to the created object, which should be used in any subsequent operations on this object. \subsection{glp\_set\_prob\_name --- assign (change) problem name} \synopsis \begin{verbatim} void glp_set_prob_name(glp_prob *P, const char *name); \end{verbatim} \description The routine \verb|glp_set_prob_name| assigns a given symbolic \verb|name| (1 up to 255 characters) to the specified problem object. If the parameter \verb|name| is \verb|NULL| or empty string, the routine erases an existing symbolic name of the problem object. \subsection{glp\_set\_obj\_name --- assign (change) objective function name} \synopsis \begin{verbatim} void glp_set_obj_name(glp_prob *P, const char *name); \end{verbatim} \description The routine \verb|glp_set_obj_name| assigns a given symbolic \verb|name| (1 up to 255 characters) to the objective function of the specified problem object. If the parameter \verb|name| is \verb|NULL| or empty string, the routine erases an existing symbolic name of the objective function. \newpage \subsection{glp\_set\_obj\_dir --- set (change) optimization direction flag} \synopsis \begin{verbatim} void glp_set_obj_dir(glp_prob *P, int dir); \end{verbatim} \description The routine \verb|glp_set_obj_dir| sets (changes) the optimization direction flag (i.e. ``sense'' of the objective function) as specified by the parameter \verb|dir|: \verb|GLP_MIN| means minimization; \verb|GLP_MAX| means maximization. \noindent (Note that by default the problem is minimization.) \subsection{glp\_add\_rows --- add new rows to problem object} \synopsis \begin{verbatim} int glp_add_rows(glp_prob *P, int nrs); \end{verbatim} \description The routine \verb|glp_add_rows| adds \verb|nrs| rows (constraints) to the specified problem object. New rows are always added to the end of the row list, so the ordinal numbers of existing rows are not changed. Being added each new row is initially free (unbounded) and has empty list of the constraint coefficients. \returns The routine \verb|glp_add_rows| returns the ordinal number of the first new row added to the problem object. \subsection{glp\_add\_cols --- add new columns to problem object} \synopsis \begin{verbatim} int glp_add_cols(glp_prob *P, int ncs); \end{verbatim} \description The routine \verb|glp_add_cols| adds \verb|ncs| columns (structural variables) to the specified problem object. New columns are always added to the end of the column list, so the ordinal numbers of existing columns are not changed. Being added each new column is initially fixed at zero and has empty list of the constraint coefficients. \returns The routine \verb|glp_add_cols| returns the ordinal number of the first new column added to the problem object. \subsection{glp\_set\_row\_name --- assign (change) row name} \synopsis \begin{verbatim} void glp_set_row_name(glp_prob *P, int i, const char *name); \end{verbatim} \description The routine \verb|glp_set_row_name| assigns a given symbolic \verb|name| (1 up to 255 characters) to \verb|i|-th row (auxiliary variable) of the specified problem object. If the parameter \verb|name| is \verb|NULL| or empty string, the routine erases an existing name of $i$-th row. \subsection{glp\_set\_col\_name --- assign (change) column name} \synopsis \begin{verbatim} void glp_set_col_name(glp_prob *P, int j, const char *name); \end{verbatim} \description The routine \verb|glp_set_col_name| assigns a given symbolic \verb|name| (1 up to 255 characters) to \verb|j|-th column (structural variable) of the specified problem object. If the parameter \verb|name| is \verb|NULL| or empty string, the routine erases an existing name of $j$-th column. \subsection{glp\_set\_row\_bnds --- set (change) row bounds} \synopsis {\tt void glp\_set\_row\_bnds(glp\_prob *P, int i, int type, double lb, double ub);} \description The routine \verb|glp_set_row_bnds| sets (changes) the type and bounds of \verb|i|-th row (auxiliary variable) of the specified problem object. The parameters \verb|type|, \verb|lb|, and \verb|ub| specify the type, lower bound, and upper bound, respectively, as follows: \begin{center} \begin{tabular}{cr@{}c@{}ll} Type & \multicolumn{3}{c}{Bounds} & Comment \\ \hline \verb|GLP_FR| & $-\infty <$ &$\ x\ $& $< +\infty$ & Free (unbounded) variable \\ \verb|GLP_LO| & $lb \leq$ &$\ x\ $& $< +\infty$ & Variable with lower bound \\ \verb|GLP_UP| & $-\infty <$ &$\ x\ $& $\leq ub$ & Variable with upper bound \\ \verb|GLP_DB| & $lb \leq$ &$\ x\ $& $\leq ub$ & Double-bounded variable \\ \verb|GLP_FX| & $lb =$ &$\ x\ $& $= ub$ & Fixed variable \\ \end{tabular} \end{center} \noindent where $x$ is the auxiliary variable associated with $i$-th row. If the row has no lower bound, the parameter \verb|lb| is ignored. If the row has no upper bound, the parameter \verb|ub| is ignored. If the row is an equality constraint (i.e. the corresponding auxiliary variable is of fixed type), only the parameter \verb|lb| is used while the parameter \verb|ub| is ignored. Being added to the problem object each row is initially free, i.e. its type is \verb|GLP_FR|. \subsection{glp\_set\_col\_bnds --- set (change) column bounds} \synopsis {\tt void glp\_set\_col\_bnds(glp\_prob *P, int j, int type, double lb, double ub);} \description The routine \verb|glp_set_col_bnds| sets (changes) the type and bounds of \verb|j|-th column (structural variable) of the specified problem object. The parameters \verb|type|, \verb|lb|, and \verb|ub| specify the type, lower bound, and upper bound, respectively, as follows: \begin{center} \begin{tabular}{cr@{}c@{}ll} Type & \multicolumn{3}{c}{Bounds} & Comment \\ \hline \verb|GLP_FR| & $-\infty <$ &$\ x\ $& $< +\infty$ & Free (unbounded) variable \\ \verb|GLP_LO| & $lb \leq$ &$\ x\ $& $< +\infty$ & Variable with lower bound \\ \verb|GLP_UP| & $-\infty <$ &$\ x\ $& $\leq ub$ & Variable with upper bound \\ \verb|GLP_DB| & $lb \leq$ &$\ x\ $& $\leq ub$ & Double-bounded variable \\ \verb|GLP_FX| & $lb =$ &$\ x\ $& $= ub$ & Fixed variable \\ \end{tabular} \end{center} \noindent where $x$ is the structural variable associated with $j$-th column. If the column has no lower bound, the parameter \verb|lb| is ignored. If the column has no upper bound, the parameter \verb|ub| is ignored. If the column is of fixed type, only the parameter \verb|lb| is used while the parameter \verb|ub| is ignored. Being added to the problem object each column is initially fixed at zero, i.e. its type is \verb|GLP_FX| and both bounds are 0. \subsection{glp\_set\_obj\_coef --- set (change) objective coefficient or constant term} \synopsis \begin{verbatim} void glp_set_obj_coef(glp_prob *P, int j, double coef); \end{verbatim} \description The routine \verb|glp_set_obj_coef| sets (changes) the objective coefficient at \verb|j|-th column (structural variable). A new value of the objective coefficient is specified by the parameter \verb|coef|. If the parameter \verb|j| is 0, the routine sets (changes) the constant term (``shift'') of the objective function. \newpage \subsection{glp\_set\_mat\_row --- set (replace) row of the constraint matrix} \synopsis \begin{verbatim} void glp_set_mat_row(glp_prob *P, int i, int len, const int ind[], const double val[]); \end{verbatim} \description The routine \verb|glp_set_mat_row| stores (replaces) the contents of \verb|i|-th row of the constraint matrix of the specified problem object. Column indices and numerical values of new row elements should be placed in locations\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, respectively, where $0 \leq$ \verb|len| $\leq n$ is the new length of $i$-th row, $n$ is the current number of columns in the problem object. Elements with identical column indices are not allowed. Zero elements are allowed, but they are not stored in the constraint matrix. If the parameter \verb|len| is 0, the parameters \verb|ind| and/or \verb|val| can be specified as \verb|NULL|. \subsection{glp\_set\_mat\_col --- set (replace) column of the constr\-aint matrix} \synopsis \begin{verbatim} void glp_set_mat_col(glp_prob *P, int j, int len, const int ind[], const double val[]); \end{verbatim} \description The routine \verb|glp_set_mat_col| stores (replaces) the contents of \verb|j|-th column of the constraint matrix of the specified problem object. Row indices and numerical values of new column elements should be placed in locations\linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, respectively, where $0 \leq$ \verb|len| $\leq m$ is the new length of $j$-th column, $m$ is the current number of rows in the problem object. Elements with identical row indices are not allowed. Zero elements are allowed, but they are not stored in the constraint matrix. If the parameter \verb|len| is 0, the parameters \verb|ind| and/or \verb|val| can be specified as \verb|NULL|. \subsection{glp\_load\_matrix --- load (replace) the whole constraint matrix} \synopsis \begin{verbatim} void glp_load_matrix(glp_prob *P, int ne, const int ia[], const int ja[], const double ar[]); \end{verbatim} \description The routine \verb|glp_load_matrix| loads the constraint matrix passed in the arrays \verb|ia|, \verb|ja|, and \verb|ar| into the specified problem object. Before loading the current contents of the constraint matrix is destroyed. Constraint coefficients (elements of the constraint matrix) should be specified as triplets (\verb|ia[k]|, \verb|ja[k]|, \verb|ar[k]|) for $k=1,\dots,ne$, where \verb|ia[k]| is the row index, \verb|ja[k]| is the column index, and \verb|ar[k]| is a numeric value of corresponding constraint coefficient. The parameter \verb|ne| specifies the total number of (non-zero) elements in the matrix to be loaded. Coefficients with identical indices are not allowed. Zero coefficients are allowed, however, they are not stored in the constraint matrix. If the parameter \verb|ne| is 0, the parameters \verb|ia|, \verb|ja|, and/or \verb|ar| can be specified as \verb|NULL|. \subsection{glp\_check\_dup --- check for duplicate elements in sparse matrix} \synopsis {\tt int glp\_check\_dup(int m, int n, int ne, const int ia[], const int ja[]);} \description The routine \verb|glp_check_dup checks| for duplicate elements (that is, elements with identical indices) in a sparse matrix specified in the coordinate format. The parameters $m$ and $n$ specifies, respectively, the number of rows and columns in the matrix, $m\geq 0$, $n\geq 0$. The parameter {\it ne} specifies the number of (structurally) non-zero elements in the matrix,\linebreak {\it ne} $\geq 0$. Elements of the matrix are specified as doublets $(ia[k],ja[k])$ for $k=1,\dots,ne$, where $ia[k]$ is a row index, $ja[k]$ is a column index. The routine \verb|glp_check_dup| can be used prior to a call to the routine \verb|glp_load_matrix| to check that the constraint matrix to be loaded has no duplicate elements. \returns \begin{retlist} 0& the matrix representation is correct;\\ $-k$& indices $ia[k]$ or/and $ja[k]$ are out of range;\\ $+k$& element $(ia[k],ja[k])$ is duplicate.\\ \end{retlist} \subsection{glp\_sort\_matrix --- sort elements of the constraint matrix} \synopsis \begin{verbatim} void glp_sort_matrix(glp_prob *P); \end{verbatim} \description The routine \verb|glp_sort_matrix| sorts elements of the constraint matrix by rebuilding its row and column linked lists. On exit from the routine the constraint matrix is not changed, however, elements in the row linked lists become ordered by ascending column indices, and the elements in the column linked lists become ordered by ascending row indices. \subsection{glp\_del\_rows --- delete rows from problem object} \synopsis \begin{verbatim} void glp_del_rows(glp_prob *P, int nrs, const int num[]); \end{verbatim} \description The routine \verb|glp_del_rows| deletes rows from the specified problem object. Ordinal numbers of rows to be deleted should be placed in locations \verb|num[1]|, \dots, \verb|num[nrs]|, where ${\tt nrs}>0$. Note that deleting rows involves changing ordinal numbers of other rows remaining in the problem object. New ordinal numbers of the remaining rows are assigned under the assumption that the original order of rows is not changed. Let, for example, before deletion there be five rows $a$, $b$, $c$, $d$, $e$ with ordinal numbers 1, 2, 3, 4, 5, and let rows $b$ and $d$ have been deleted. Then after deletion the remaining rows $a$, $c$, $e$ are assigned new oridinal numbers 1, 2, 3. \subsection{glp\_del\_cols --- delete columns from problem object} \synopsis \begin{verbatim} void glp_del_cols(glp_prob *P, int ncs, const int num[]); \end{verbatim} \description The routine \verb|glp_del_cols| deletes columns from the specified problem object. Ordinal numbers of columns to be deleted should be placed in locations \verb|num[1]|, \dots, \verb|num[ncs]|, where ${\tt ncs}>0$. Note that deleting columns involves changing ordinal numbers of other columns remaining in\linebreak the problem object. New ordinal numbers of the remaining columns are assigned under the assumption that the original order of columns is not changed. Let, for example, before deletion there be six columns $p$, $q$, $r$, $s$, $t$, $u$ with ordinal numbers 1, 2, 3, 4, 5, 6, and let columns $p$, $q$, $s$ have been deleted. Then after deletion the remaining columns $r$, $t$, $u$ are assigned new ordinal numbers 1, 2, 3. \subsection{glp\_copy\_prob --- copy problem object content} \synopsis \begin{verbatim} void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); \end{verbatim} \description The routine \verb|glp_copy_prob| copies the content of the problem object \verb|prob| to the problem object \verb|dest|. The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the routine also copies all symbolic names; otherwise, if it is \verb|GLP_OFF|, no symbolic names are copied. \newpage \subsection{glp\_erase\_prob --- erase problem object content} \synopsis \begin{verbatim} void glp_erase_prob(glp_prob *P); \end{verbatim} \description The routine \verb|glp_erase_prob| erases the content of the specified problem object. The effect of this operation is the same as if the problem object would be deleted with the routine \verb|glp_delete_prob| and then created anew with the routine \verb|glp_create_prob|, with the only exception that the pointer to the problem object remains valid. \subsection{glp\_delete\_prob --- delete problem object} \synopsis \begin{verbatim} void glp_delete_prob(glp_prob *P); \end{verbatim} \description The routine \verb|glp_delete_prob| deletes a problem object, which the parameter \verb|lp| points to, freeing all the memory allocated to this object. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Problem retrieving routines} \subsection{glp\_get\_prob\_name --- retrieve problem name} \synopsis \begin{verbatim} const char *glp_get_prob_name(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_prob_name| returns a pointer to an internal buffer, which contains symbolic name of the problem. However, if the problem has no assigned name, the routine returns \verb|NULL|. \subsection{glp\_get\_obj\_name --- retrieve objective function name} \synopsis \begin{verbatim} const char *glp_get_obj_name(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_obj_name| returns a pointer to an internal buffer, which contains symbolic name assigned to the objective function. However, if the objective function has no assigned name, the routine returns \verb|NULL|. \subsection{glp\_get\_obj\_dir --- retrieve optimization direction flag} \synopsis \begin{verbatim} int glp_get_obj_dir(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_obj_dir| returns the optimization direction flag (i.e. ``sense'' of the objective function): \verb|GLP_MIN| means minimization; \verb|GLP_MAX| means maximization. \subsection{glp\_get\_num\_rows --- retrieve number of rows} \synopsis \begin{verbatim} int glp_get_num_rows(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_num_rows| returns the current number of rows in the specified problem object. \subsection{glp\_get\_num\_cols --- retrieve number of columns} \synopsis \begin{verbatim} int glp_get_num_cols(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_num_cols| returns the current number of columns in the specified problem object. \subsection{glp\_get\_row\_name --- retrieve row name} \synopsis \begin{verbatim} const char *glp_get_row_name(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_name| returns a pointer to an internal buffer, which contains a symbolic name assigned to \verb|i|-th row. However, if the row has no assigned name, the routine returns \verb|NULL|. \subsection{glp\_get\_col\_name --- retrieve column name} \synopsis \begin{verbatim} const char *glp_get_col_name(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_name| returns a pointer to an internal buffer, which contains a symbolic name assigned to \verb|j|-th column. However, if the column has no assigned name, the routine returns \verb|NULL|. \subsection{glp\_get\_row\_type --- retrieve row type} \synopsis \begin{verbatim} int glp_get_row_type(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_type| returns the type of \verb|i|-th row, i.e. the type of corresponding auxiliary variable, as follows: \verb|GLP_FR| --- free (unbounded) variable; \verb|GLP_LO| --- variable with lower bound; \verb|GLP_UP| --- variable with upper bound; \verb|GLP_DB| --- double-bounded variable; \verb|GLP_FX| --- fixed variable. \subsection{glp\_get\_row\_lb --- retrieve row lower bound} \synopsis \begin{verbatim} double glp_get_row_lb(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_lb| returns the lower bound of \verb|i|-th row, i.e. the lower bound of corresponding auxiliary variable. However, if the row has no lower bound, the routine returns \verb|-DBL_MAX|. \vspace*{-4pt} \subsection{glp\_get\_row\_ub --- retrieve row upper bound} \synopsis \begin{verbatim} double glp_get_row_ub(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_ub| returns the upper bound of \verb|i|-th row, i.e. the upper bound of corresponding auxiliary variable. However, if the row has no upper bound, the routine returns \verb|+DBL_MAX|. \vspace*{-4pt} \subsection{glp\_get\_col\_type --- retrieve column type} \synopsis \begin{verbatim} int glp_get_col_type(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_type| returns the type of \verb|j|-th column, i.e. the type of corresponding structural variable, as follows: \verb|GLP_FR| --- free (unbounded) variable; \verb|GLP_LO| --- variable with lower bound; \verb|GLP_UP| --- variable with upper bound; \verb|GLP_DB| --- double-bounded variable; \verb|GLP_FX| --- fixed variable. \vspace*{-4pt} \subsection{glp\_get\_col\_lb --- retrieve column lower bound} \synopsis \begin{verbatim} double glp_get_col_lb(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_lb| returns the lower bound of \verb|j|-th column, i.e. the lower bound of corresponding structural variable. However, if the column has no lower bound, the routine returns \verb|-DBL_MAX|. \subsection{glp\_get\_col\_ub --- retrieve column upper bound} \synopsis \begin{verbatim} double glp_get_col_ub(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_ub| returns the upper bound of \verb|j|-th column, i.e. the upper bound of corresponding structural variable. However, if the column has no upper bound, the routine returns \verb|+DBL_MAX|. \subsection{glp\_get\_obj\_coef --- retrieve objective coefficient or constant term} \synopsis \begin{verbatim} double glp_get_obj_coef(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_obj_coef| returns the objective coefficient at \verb|j|-th structural variable (column). If the parameter \verb|j| is 0, the routine returns the constant term (``shift'') of the objective function. \subsection{glp\_get\_num\_nz --- retrieve number of constraint coefficients} \synopsis \begin{verbatim} int glp_get_num_nz(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_num_nz| returns the number of non-zero elements in the constraint matrix of the specified problem object. \subsection{glp\_get\_mat\_row --- retrieve row of the constraint matrix} \synopsis \begin{verbatim} int glp_get_mat_row(glp_prob *P, int i, int ind[], double val[]); \end{verbatim} \description The routine \verb|glp_get_mat_row| scans (non-zero) elements of \verb|i|-th row of the constraint matrix of the specified problem object and stores their column indices and numeric values to locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq n$ is the number of elements in $i$-th row, $n$ is the number of columns. The parameter \verb|ind| and/or \verb|val| can be specified as \verb|NULL|, in which case corresponding information is not stored. \newpage \returns The routine \verb|glp_get_mat_row| returns the length \verb|len|, i.e. the number of (non-zero) elements in \verb|i|-th row. \subsection{glp\_get\_mat\_col --- retrieve column of the constraint matrix} \synopsis \begin{verbatim} int glp_get_mat_col(glp_prob *P, int j, int ind[], double val[]); \end{verbatim} \description The routine \verb|glp_get_mat_col| scans (non-zero) elements of \verb|j|-th column of the constraint matrix of the specified problem object and stores their row indices and numeric values to locations \linebreak \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq m$ is the number of elements in $j$-th column, $m$ is the number of rows. The parameter \verb|ind| and/or \verb|val| can be specified as \verb|NULL|, in which case corresponding information is not stored. \returns The routine \verb|glp_get_mat_col| returns the length \verb|len|, i.e. the number of (non-zero) elements in \verb|j|-th column. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Row and column searching routines} Sometimes it may be necessary to find rows and/or columns by their names (assigned with the routines \verb|glp_set_row_name| and \verb|glp_set_col_name|). Though a particular row/column can be found by its name using simple enumeration of all rows/columns, in case of large instances such a {\it linear} search may take too long time. To significantly reduce the search time the application program may create the row/column name index, which is an auxiliary data structure implementing a {\it binary} search. Even in worst cases the search takes logarithmic time, i.e. the time needed to find a particular row (or column) by its name is $O(\log_2m)$ (or $O(\log_2n)$), where $m$ and $n$ are, resp., the number of rows and columns in the problem object. It is important to note that: 1. On creating the problem object with the routine \verb|glp_create_prob| the name index is {\it not} created. 2. The name index can be created (destroyed) at any time with the routine \verb|glp_create_index| (\verb|glp_delete_index|). Having been created the name index becomes part of the corresponding problem object. 3. The time taken to create the name index is $O[(m+n)\log_2(m+n)]$, so it is recommended to create the index only once, for example, just after the problem object was created. 4. If the name index exists, it is automatically updated every time the name of a row/column is assigned/changed. The update operation takes logarithmic time. 5. If the name index does not exist, the application should not call the routines \verb|glp_find_row| and \verb|glp_find_col|. Otherwise, an error message will be issued and abnormal program termination will occur. 6. On destroying the problem object with the routine \verb|glp_delete_prob|, the name index, if exists, is automatically destroyed. \subsection{glp\_create\_index --- create the name index} \synopsis \begin{verbatim} void glp_create_index(glp_prob *P); \end{verbatim} \description The routine \verb|glp_create_index| creates the name index for the specified problem object. The name index is an auxiliary data structure, which is intended to quickly (i.e. for logarithmic time) find rows and columns by their names. This routine can be called at any time. If the name index already exists, the routine does nothing. \newpage \subsection{glp\_find\_row --- find row by its name} \synopsis \begin{verbatim} int glp_find_row(glp_prob *P, const char *name); \end{verbatim} \returns The routine \verb|glp_find_row| returns the ordinal number of a row, which is assigned the specified symbolic \verb|name|. If no such row exists, the routine returns 0. \subsection{glp\_find\_col --- find column by its name} \synopsis \begin{verbatim} int glp_find_col(glp_prob *P, const char *name); \end{verbatim} \returns The routine \verb|glp_find_col| returns the ordinal number of a column, which is assigned the specified symbolic \verb|name|. If no such column exists, the routine returns 0. \subsection{glp\_delete\_index --- delete the name index} \synopsis \begin{verbatim} void glp_delete_index(glp_prob *P); \end{verbatim} \description The routine \verb|glp_delete_index| deletes the name index previously created by the routine\linebreak \verb|glp_create_index| and frees the memory allocated to this auxiliary data structure. This routine can be called at any time. If the name index does not exist, the routine does nothing. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Problem scaling routines} \subsection{Background} In GLPK the {\it scaling} means a linear transformation applied to the constraint matrix to improve its numerical properties.\footnote{In many cases a proper scaling allows making the constraint matrix to be better conditioned, i.e. decreasing its condition number, that makes computations numerically more stable.} The main equality is the following: $$\widetilde{A}=RAS,\eqno(2.1)$$ where $A=(a_{ij})$ is the original constraint matrix, $R=(r_{ii})>0$ is a diagonal matrix used to scale rows (constraints), $S=(s_{jj})>0$ is a diagonal matrix used to scale columns (variables), $\widetilde{A}$ is the scaled constraint matrix. From (2.1) it follows that in the {\it scaled} problem instance each original constraint coefficient $a_{ij}$ is replaced by corresponding scaled constraint coefficient: $$\widetilde{a}_{ij}=r_{ii}a_{ij}s_{jj}.\eqno(2.2)$$ Note that the scaling is performed internally and therefore transparently to the user. This means that on API level the user always deal with unscaled data. Scale factors $r_{ii}$ and $s_{jj}$ can be set or changed at any time either directly by the application program in a problem specific way (with the routines \verb|glp_set_rii| and \verb|glp_set_sjj|), or by some API routines intended for automatic scaling. \subsection{glp\_set\_rii --- set (change) row scale factor} \synopsis \begin{verbatim} void glp_set_rii(glp_prob *P, int i, double rii); \end{verbatim} \description The routine \verb|glp_set_rii| sets (changes) the scale factor $r_{ii}$ for $i$-th row of the specified problem object. \subsection{glp\_set\_sjj --- set (change) column scale factor} \synopsis \begin{verbatim} void glp_set_sjj(glp_prob *P, int j, double sjj); \end{verbatim} \description The routine \verb|glp_set_sjj| sets (changes) the scale factor $s_{jj}$ for $j$-th column of the specified problem object. \subsection{glp\_get\_rii --- retrieve row scale factor} \synopsis \begin{verbatim} double glp_get_rii(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_rii| returns current scale factor $r_{ii}$ for $i$-th row of the specified problem object. \vspace*{-6pt} \subsection{glp\_get\_sjj --- retrieve column scale factor} \vspace*{-4pt} \synopsis \begin{verbatim} double glp_get_sjj(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_sjj| returns current scale factor $s_{jj}$ for $j$-th column of the specified problem object. \vspace*{-6pt} \subsection{glp\_scale\_prob --- scale problem data} \vspace*{-4pt} \synopsis \begin{verbatim} void glp_scale_prob(glp_prob *P, int flags); \end{verbatim} \description The routine \verb|glp_scale_prob| performs automatic scaling of problem data for the specified problem object. The parameter \verb|flags| specifies scaling options used by the routine. The options can be combined with the bitwise OR operator and may be the following: \verb|GLP_SF_GM | --- perform geometric mean scaling; \verb|GLP_SF_EQ | --- perform equilibration scaling; \verb|GLP_SF_2N | --- round scale factors to nearest power of two; \verb|GLP_SF_SKIP| --- skip scaling, if the problem is well scaled. The parameter \verb|flags| may be also specified as \verb|GLP_SF_AUTO|, in which case the routine chooses the scaling options automatically. \vspace*{-6pt} \subsection{glp\_unscale\_prob --- unscale problem data} \vspace*{-4pt} \synopsis \begin{verbatim} void glp_unscale_prob(glp_prob *P); \end{verbatim} The routine \verb|glp_unscale_prob| performs unscaling of problem data for the specified problem object. ``Unscaling'' means replacing the current scaling matrices $R$ and $S$ by unity matrices that cancels the scaling effect. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{LP basis constructing routines} \subsection{Background} To start the search the simplex method needs a valid initial basis. In GLPK the basis is completely defined by a set of {\it statuses} assigned to {\it all} (auxiliary and structural) variables, where the status may be one of the following: \verb|GLP_BS| --- basic variable; \verb|GLP_NL| --- non-basic variable having active lower bound; \verb|GLP_NU| --- non-basic variable having active upper bound; \verb|GLP_NF| --- non-basic free variable; \verb|GLP_NS| --- non-basic fixed variable. The basis is {\it valid}, if the basis matrix, which is a matrix built of columns of the augmented constraint matrix $(I\:|-A)$ corresponding to basic variables, is non-singular. This, in particular, means that the number of basic variables must be the same as the number of rows in the problem object. (For more details see Section \ref{lpbasis}, page \pageref{lpbasis}.) Any initial basis may be constructed (or restored) with the API routines \verb|glp_set_row_stat| and \verb|glp_set_col_stat| by assigning appropriate statuses to auxiliary and structural variables. Another way to construct an initial basis is to use API routines like \verb|glp_adv_basis|, which implement so called {\it crashing}.\footnote{This term is from early linear programming systems and means a heuristic to construct a valid initial basis.} Note that on normal exit the simplex solver remains the basis valid, so in case of reoptimization there is no need to construct an initial basis from scratch. \subsection{glp\_set\_row\_stat --- set (change) row status} \synopsis \begin{verbatim} void glp_set_row_stat(glp_prob *P, int i, int stat); \end{verbatim} \description The routine \verb|glp_set_row_stat| sets (changes) the current status of \verb|i|-th row (auxiliary variable) as specified by the parameter \verb|stat|: \verb|GLP_BS| --- make the row basic (make the constraint inactive); \verb|GLP_NL| --- make the row non-basic (make the constraint active); \verb|GLP_NU| --- make the row non-basic and set it to the upper bound; if the row is not double-bounded, this status is equivalent to \verb|GLP_NL| (only in case of this routine); \verb|GLP_NF| --- the same as \verb|GLP_NL| (only in case of this routine); \verb|GLP_NS| --- the same as \verb|GLP_NL| (only in case of this routine). \newpage \subsection{glp\_set\_col\_stat --- set (change) column status} \synopsis \begin{verbatim} void glp_set_col_stat(glp_prob *P, int j, int stat); \end{verbatim} \description The routine \verb|glp_set_col_stat sets| (changes) the current status of \verb|j|-th column (structural variable) as specified by the parameter \verb|stat|: \verb|GLP_BS| --- make the column basic; \verb|GLP_NL| --- make the column non-basic; \verb|GLP_NU| --- make the column non-basic and set it to the upper bound; if the column is not double-bounded, this status is equivalent to \verb|GLP_NL| (only in case of this routine); \verb|GLP_NF| --- the same as \verb|GLP_NL| (only in case of this routine); \verb|GLP_NS| --- the same as \verb|GLP_NL| (only in case of this routine). \subsection{glp\_std\_basis --- construct standard initial LP basis} \synopsis \begin{verbatim} void glp_std_basis(glp_prob *P); \end{verbatim} \description The routine \verb|glp_std_basis| constructs the ``standard'' (trivial) initial LP basis for the specified problem object. In the ``standard'' LP basis all auxiliary variables (rows) are basic, and all structural variables (columns) are non-basic (so the corresponding basis matrix is unity). \subsection{glp\_adv\_basis --- construct advanced initial LP basis} \synopsis \begin{verbatim} void glp_adv_basis(glp_prob *P, int flags); \end{verbatim} \description The routine \verb|glp_adv_basis| constructs an advanced initial LP basis for the specified problem object. The parameter \verb|flags| is reserved for use in the future and must be specified as zero. In order to construct the advanced initial LP basis the routine does the following: 1) includes in the basis all non-fixed auxiliary variables; 2) includes in the basis as many non-fixed structural variables as possible keeping the triangular form of the basis matrix; 3) includes in the basis appropriate (fixed) auxiliary variables to complete the basis. As a result the initial LP basis has as few fixed variables as possible and the corresponding basis matrix is triangular. \subsection{glp\_cpx\_basis --- construct Bixby's initial LP basis} \synopsis \begin{verbatim} void glp_cpx_basis(glp_prob *P); \end{verbatim} \description The routine \verb|glp_cpx_basis| constructs an initial basis for the specified problem object with the algorithm proposed by R.~Bixby.\footnote{Robert E. Bixby, ``Implementing the Simplex Method: The Initial Basis.'' ORSA Journal on Computing, Vol. 4, No. 3, 1992, pp. 267-84.} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Simplex method routines} The {\it simplex method} is a well known efficient numerical procedure to solve LP problems. On each iteration the simplex method transforms the original system of equaility constraints (1.2) resolving them through different sets of variables to an equivalent system called {\it the simplex table} (or sometimes {\it the simplex tableau}), which has the following form: $$ \begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}r} z&=&d_1(x_N)_1&+&d_2(x_N)_2&+ \dots +&d_n(x_N)_n \\ (x_B)_1&=&\xi_{11}(x_N)_1& +& \xi_{12}(x_N)_2& + \dots +& \xi_{1n}(x_N)_n \\ (x_B)_2&=& \xi_{21}(x_N)_1& +& \xi_{22}(x_N)_2& + \dots +& \xi_{2n}(x_N)_n \\ \multicolumn{7}{c} {.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ (x_B)_m&=&\xi_{m1}(x_N)_1& +& \xi_{m2}(x_N)_2& + \dots +& \xi_{mn}(x_N)_n \\ \end{array} \eqno (2.3) $$ where: $(x_B)_1, (x_B)_2, \dots, (x_B)_m$ are basic variables; $(x_N)_1, (x_N)_2, \dots, (x_N)_n$ are non-basic variables; $d_1, d_2, \dots, d_n$ are reduced costs; $\xi_{11}, \xi_{12}, \dots, \xi_{mn}$ are coefficients of the simplex table. (May note that the original LP problem (1.1)---(1.3) also has the form of a simplex table, where all equalities are resolved through auxiliary variables.) From the linear programming theory it is known that if an optimal solution of the LP problem (1.1)---(1.3) exists, it can always be written in the form (2.3), where non-basic variables are set on their bounds while values of the objective function and basic variables are determined by the corresponding equalities of the simplex table. A set of values of all basic and non-basic variables determined by the simplex table is called {\it basic solution}. If all basic variables are within their bounds, the basic solution is called {\it (primal) feasible}, otherwise it is called {\it (primal) infeasible}. A feasible basic solution, which provides a smallest (in case of minimization) or a largest (in case of maximization) value of the objective function is called {\it optimal}. Therefore, for solving LP problem the simplex method tries to find its optimal basic solution. Primal feasibility of some basic solution may be stated by simple checking if all basic variables are within their bounds. Basic solution is optimal if additionally the following optimality conditions are satisfied for all non-basic variables: \begin{center} \begin{tabular}{lcc} Status of $(x_N)_j$ & Minimization & Maximization \\ \hline $(x_N)_j$ is free & $d_j = 0$ & $d_j = 0$ \\ $(x_N)_j$ is on its lower bound & $d_j \geq 0$ & $d_j \leq 0$ \\ $(x_N)_j$ is on its upper bound & $d_j \leq 0$ & $d_j \geq 0$ \\ \end{tabular} \end{center} In other words, basic solution is optimal if there is no non-basic variable, which changing in the feasible direction (i.e. increasing if it is free or on its lower bound, or decreasing if it is free or on its upper bound) can improve (i.e. decrease in case of minimization or increase in case of maximization) the objective function. If all non-basic variables satisfy to the optimality conditions shown above (independently on whether basic variables are within their bounds or not), the basic solution is called {\it dual feasible}, otherwise it is called {\it dual infeasible}. It may happen that some LP problem has no primal feasible solution due to incorrect\linebreak formulation --- this means that its constraints conflict with each other. It also may happen that some LP problem has unbounded solution again due to incorrect formulation --- this means that some non-basic variable can improve the objective function, i.e. the optimality conditions are violated, and at the same time this variable can infinitely change in the feasible direction meeting no resistance from basic variables. (May note that in the latter case the LP problem has no dual feasible solution.) \subsection{glp\_simplex --- solve LP problem with the primal or dual simplex method} \synopsis \begin{verbatim} int glp_simplex(glp_prob *P, const glp_smcp *parm); \end{verbatim} \description The routine \verb|glp_simplex| is a driver to the LP solver based on the simplex method. This routine retrieves problem data from the specified problem object, calls the solver to solve the problem instance, and stores results of computations back into the problem object. The simplex solver has a set of control parameters. Values of the control parameters can be passed in the structure \verb|glp_smcp|, which the parameter \verb|parm| points to. For detailed description of this structure see paragraph ``Control parameters'' below. Before specifying some control parameters the application program should initialize the structure \verb|glp_smcp| by default values of all control parameters using the routine \verb|glp_init_smcp| (see the next subsection). This is needed for backward compatibility, because in the future there may appear new members in the structure \verb|glp_smcp|. The parameter \verb|parm| can be specified as \verb|NULL|, in which case the solver uses default settings. \returns \begin{retlist} 0 & The LP problem instance has been successfully solved. (This code does {\it not} necessarily mean that the solver has found optimal solution. It only means that the solution process was successful.) \\ \verb|GLP_EBADB| & Unable to start the search, because the initial basis specified in the problem object is invalid---the number of basic (auxiliary and structural) variables is not the same as the number of rows in the problem object.\\ \verb|GLP_ESING| & Unable to start the search, because the basis matrix corresponding to the initial basis is singular within the working precision.\\ \verb|GLP_ECOND| & Unable to start the search, because the basis matrix corresponding to the initial basis is ill-conditioned, i.e. its condition number is too large.\\ \verb|GLP_EBOUND| & Unable to start the search, because some double-bounded (auxiliary or structural) variables have incorrect bounds.\\ \verb|GLP_EFAIL| & The search was prematurely terminated due to the solver failure.\\ \verb|GLP_EOBJLL| & The search was prematurely terminated, because the objective function being maximized has reached its lower limit and continues decreasing (the dual simplex only).\\ \end{retlist} \begin{retlist} \verb|GLP_EOBJUL| & The search was prematurely terminated, because the objective function being minimized has reached its upper limit and continues increasing (the dual simplex only).\\ \verb|GLP_EITLIM| & The search was prematurely terminated, because the simplex iteration limit has been exceeded.\\ \verb|GLP_ETMLIM| & The search was prematurely terminated, because the time limit has been exceeded.\\ \verb|GLP_ENOPFS| & The LP problem instance has no primal feasible solution (only if the LP presolver is used).\\ \verb|GLP_ENODFS| & The LP problem instance has no dual feasible solution (only if the LP presolver is used).\\ \end{retlist} \para{Built-in LP presolver} The simplex solver has {\it built-in LP presolver}. It is a subprogram that transforms the original LP problem specified in the problem object to an equivalent LP problem, which may be easier for solving with the simplex method than the original one. This is attained mainly due to reducing the problem size and improving its numeric properties (for example, by removing some inactive constraints or by fixing some non-basic variables). Once the transformed LP problem has been solved, the presolver transforms its basic solution back to the corresponding basic solution of the original problem. Presolving is an optional feature of the routine \verb|glp_simplex|, and by default it is disabled. In order to enable the LP presolver the control parameter \verb|presolve| should be set to \verb|GLP_ON| (see paragraph ``Control parameters'' below). Presolving may be used when the problem instance is solved for the first time. However, on performing re-optimization the presolver should be disabled. The presolving procedure is transparent to the API user in the sense that all necessary processing is performed internally, and a basic solution of the original problem recovered by the presolver is the same as if it were computed directly, i.e. without presolving. Note that the presolver is able to recover only optimal solutions. If a computed solution is infeasible or non-optimal, the corresponding solution of the original problem cannot be recovered and therefore remains undefined. If you need to know a basic solution even if it is infeasible or non-optimal, the presolver should be disabled. \para{Terminal output} Solving large problem instances may take a long time, so the solver reports some information about the current basic solution, which is sent to the terminal. This information has the following format: \begin{verbatim} nnn: obj = xxx infeas = yyy (ddd) \end{verbatim} \noindent where: `\verb|nnn|' is the iteration number, `\verb|xxx|' is the current value of the objective function (it is is unscaled and has correct sign); `\verb|yyy|' is the current sum of primal or dual infeasibilities (it is scaled and therefore may be used only for visual estimating), `\verb|ddd|' is the current number of fixed basic variables. The symbol preceding the iteration number indicates which phase of the simplex method is in effect: {\it Blank} means that the solver is searching for primal feasible solution using the primal simplex or for dual feasible solution using the dual simplex; {\it Asterisk} (\verb|*|) means that the solver is searching for optimal solution using the primal simplex; {\it Vertical dash} (\verb/|/) means that the solver is searching for optimal solution using the dual simplex. \para{Control parameters} This paragraph describes all control parameters currently used in the simplex solver. Symbolic names of control parameters are names of corresponding members in the structure \verb|glp_smcp|. \bigskip {\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) Message level for terminal output: \verb|GLP_MSG_OFF| --- no output; \verb|GLP_MSG_ERR| --- error and warning messages only; \verb|GLP_MSG_ON | --- normal output; \verb|GLP_MSG_ALL| --- full output (including informational messages). \bigskip {\tt int meth} (default: {\tt GLP\_PRIMAL}) Simplex method option: \verb|GLP_PRIMAL| --- use two-phase primal simplex; \verb|GLP_DUAL | --- use two-phase dual simplex; \verb|GLP_DUALP | --- use two-phase dual simplex, and if it fails, switch to the primal simplex. \bigskip {\tt int pricing} (default: {\tt GLP\_PT\_PSE}) Pricing technique: \verb|GLP_PT_STD| --- standard (``textbook''); \verb|GLP_PT_PSE| --- projected steepest edge. \bigskip {\tt int r\_test} (default: {\tt GLP\_RT\_HAR}) Ratio test technique: \verb|GLP_RT_STD| --- standard (``textbook''); \verb|GLP_RT_HAR| --- Harris' two-pass ratio test. \bigskip {\tt double tol\_bnd} (default: {\tt 1e-7}) Tolerance used to check if the basic solution is primal feasible. (Do not change this parameter without detailed understanding its purpose.) \newpage {\tt double tol\_dj} (default: {\tt 1e-7}) Tolerance used to check if the basic solution is dual feasible. (Do not change this parameter without detailed understanding its purpose.) \bigskip {\tt double tol\_piv} (default: {\tt 1e-10}) Tolerance used to choose eligble pivotal elements of the simplex table. (Do not change this parameter without detailed understanding its purpose.) \bigskip {\tt double obj\_ll} (default: {\tt -DBL\_MAX}) Lower limit of the objective function. If the objective function reaches this limit and continues decreasing, the solver terminates the search. (Used in the dual simplex only.) \bigskip {\tt double obj\_ul} (default: {\tt +DBL\_MAX}) Upper limit of the objective function. If the objective function reaches this limit and continues increasing, the solver terminates the search. (Used in the dual simplex only.) \bigskip {\tt int it\_lim} (default: {\tt INT\_MAX}) Simplex iteration limit. \bigskip {\tt int tm\_lim} (default: {\tt INT\_MAX}) Searching time limit, in milliseconds. \bigskip {\tt int out\_frq} (default: {\tt 500}) Output frequency, in iterations. This parameter specifies how frequently the solver sends information about the solution process to the terminal. \bigskip {\tt int out\_dly} (default: {\tt 0}) Output delay, in milliseconds. This parameter specifies how long the solver should delay sending information about the solution process to the terminal. \bigskip {\tt int presolve} (default: {\tt GLP\_OFF}) LP presolver option: \verb|GLP_ON | --- enable using the LP presolver; \verb|GLP_OFF| --- disable using the LP presolver. \newpage \para{Example 1} The following example main program reads LP problem instance in fixed MPS format from file \verb|25fv47.mps|,\footnote{This instance in fixed MPS format can be found in the Netlib LP collection; see {\tt ftp://ftp.netlib.org/lp/data/}.} constructs an advanced initial basis, solves the instance with the primal simplex method (by default), and writes the solution to file \verb|25fv47.txt|. \begin{footnotesize} \begin{verbatim} /* spxsamp1.c */ #include #include #include int main(void) { glp_prob *P; P = glp_create_prob(); glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); glp_adv_basis(P, 0); glp_simplex(P, NULL); glp_print_sol(P, "25fv47.txt"); glp_delete_prob(P); return 0; } /* eof */ \end{verbatim} \end{footnotesize} Below here is shown the terminal output from this example program. \begin{footnotesize} \begin{verbatim} Reading problem data from `25fv47.mps'... Problem: 25FV47 Objective: R0000 822 rows, 1571 columns, 11127 non-zeros 6919 records were read Crashing... Size of triangular part = 799 0: obj = 1.627307307e+04 infeas = 5.194e+04 (23) 200: obj = 1.474901610e+04 infeas = 1.233e+04 (19) 400: obj = 1.343909995e+04 infeas = 3.648e+03 (13) 600: obj = 1.756052217e+04 infeas = 4.179e+02 (7) * 775: obj = 1.789251591e+04 infeas = 4.982e-14 (1) * 800: obj = 1.663354510e+04 infeas = 2.857e-14 (1) * 1000: obj = 1.024935068e+04 infeas = 1.958e-12 (1) * 1200: obj = 7.860174791e+03 infeas = 2.810e-29 (1) * 1400: obj = 6.642378184e+03 infeas = 2.036e-16 (1) * 1600: obj = 6.037014568e+03 infeas = 0.000e+00 (1) * 1800: obj = 5.662171307e+03 infeas = 6.447e-15 (1) * 2000: obj = 5.528146165e+03 infeas = 9.764e-13 (1) * 2125: obj = 5.501845888e+03 infeas = 0.000e+00 (1) OPTIMAL SOLUTION FOUND Writing basic solution to `25fv47.txt'... \end{verbatim} \end{footnotesize} \newpage \para{Example 2} The following example main program solves the same LP problem instance as in Example 1 above, however, it uses the dual simplex method, which starts from the standard initial basis. \begin{footnotesize} \begin{verbatim} /* spxsamp2.c */ #include #include #include int main(void) { glp_prob *P; glp_smcp parm; P = glp_create_prob(); glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); glp_init_smcp(&parm); parm.meth = GLP_DUAL; glp_simplex(P, &parm); glp_print_sol(P, "25fv47.txt"); glp_delete_prob(P); return 0; } /* eof */ \end{verbatim} \end{footnotesize} Below here is shown the terminal output from this example program. \begin{footnotesize} \begin{verbatim} Reading problem data from `25fv47.mps'... Problem: 25FV47 Objective: R0000 822 rows, 1571 columns, 11127 non-zeros 6919 records were read 0: infeas = 1.223e+03 (516) 200: infeas = 7.000e+00 (471) 240: infeas = 1.106e-14 (461) | 400: obj = -5.394267152e+03 infeas = 5.571e-16 (391) | 600: obj = -4.586395752e+03 infeas = 1.389e-15 (340) | 800: obj = -4.158268146e+03 infeas = 1.640e-15 (264) | 1000: obj = -3.725320045e+03 infeas = 5.181e-15 (245) | 1200: obj = -3.104802163e+03 infeas = 1.019e-14 (210) | 1400: obj = -2.584190499e+03 infeas = 8.865e-15 (178) | 1600: obj = -2.073852927e+03 infeas = 7.867e-15 (142) | 1800: obj = -1.164037407e+03 infeas = 8.792e-15 (109) | 2000: obj = -4.370590250e+02 infeas = 2.591e-14 (85) | 2200: obj = 1.068240144e+03 infeas = 1.025e-13 (70) | 2400: obj = 1.607481126e+03 infeas = 3.272e-14 (67) | 2600: obj = 3.038230551e+03 infeas = 4.850e-14 (52) | 2800: obj = 4.316238187e+03 infeas = 2.622e-14 (36) | 3000: obj = 5.443842629e+03 infeas = 3.976e-15 (11) | 3060: obj = 5.501845888e+03 infeas = 8.806e-15 (2) OPTIMAL SOLUTION FOUND Writing basic solution to `25fv47.txt'... \end{verbatim} \end{footnotesize} \newpage \subsection{glp\_exact --- solve LP problem in exact arithmetic} \synopsis \begin{verbatim} int glp_exact(glp_prob *P, const glp_smcp *parm); \end{verbatim} \description The routine \verb|glp_exact| is a tentative implementation of the primal two-phase simplex method based on exact (rational) arithmetic. It is similar to the routine \verb|glp_simplex|, however, for all internal computations it uses arithmetic of rational numbers, which is exact in mathematical sense, i.e. free of round-off errors unlike floating-point arithmetic. Note that the routine \verb|glp_exact| uses only two control parameters passed in the structure \verb|glp_smcp|, namely, \verb|it_lim| and \verb|tm_lim|. \returns \begin{retlist} 0 & The LP problem instance has been successfully solved. (This code does {\it not} necessarily mean that the solver has found optimal solution. It only means that the solution process was successful.) \\ \verb|GLP_EBADB| & Unable to start the search, because the initial basis specified in the problem object is invalid---the number of basic (auxiliary and structural) variables is not the same as the number of rows in the problem object.\\ \verb|GLP_ESING| & Unable to start the search, because the basis matrix corresponding to the initial basis is exactly singular.\\ \verb|GLP_EBOUND| & Unable to start the search, because some double-bounded (auxiliary or structural) variables have incorrect bounds.\\ \verb|GLP_EFAIL| & The problem instance has no rows/columns.\\ \verb|GLP_EITLIM| & The search was prematurely terminated, because the simplex iteration limit has been exceeded.\\ \verb|GLP_ETMLIM| & The search was prematurely terminated, because the time limit has been exceeded.\\ \end{retlist} \para{Note} Computations in exact arithmetic are very time-consuming, so solving LP problem with the routine \verb|glp_exact| from the very beginning is not a good idea. It is much better at first to find an optimal basis with the routine \verb|glp_simplex| and only then to call \verb|glp_exact|, in which case only a few simplex iterations need to be performed in exact arithmetic. \newpage \subsection{glp\_init\_smcp --- initialize simplex solver control parameters} \synopsis \begin{verbatim} int glp_init_smcp(glp_smcp *parm); \end{verbatim} \description The routine \verb|glp_init_smcp| initializes control parameters, which are used by the simplex solver, with default values. Default values of the control parameters are stored in a \verb|glp_smcp| structure, which the parameter \verb|parm| points to. \subsection{glp\_get\_status --- determine generic status of basic solution} \synopsis \begin{verbatim} int glp_get_status(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_status| reports the generic status of the current basic solution for the specified problem object as follows: \verb|GLP_OPT | --- solution is optimal; \verb|GLP_FEAS | --- solution is feasible; \verb|GLP_INFEAS| --- solution is infeasible; \verb|GLP_NOFEAS| --- problem has no feasible solution; \verb|GLP_UNBND | --- problem has unbounded solution; \verb|GLP_UNDEF | --- solution is undefined. More detailed information about the status of basic solution can be retrieved with the routines \verb|glp_get_prim_stat| and \verb|glp_get_dual_stat|. \subsection{glp\_get\_prim\_stat --- retrieve status of primal basic solution} \synopsis \begin{verbatim} int glp_get_prim_stat(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_prim_stat| reports the status of the primal basic solution for the specified problem object as follows: \verb|GLP_UNDEF | --- primal solution is undefined; \verb|GLP_FEAS | --- primal solution is feasible; \verb|GLP_INFEAS| --- primal solution is infeasible; \verb|GLP_NOFEAS| --- no primal feasible solution exists. \subsection{glp\_get\_dual\_stat --- retrieve status of dual basic solution} \synopsis \begin{verbatim} int glp_get_dual_stat(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_dual_stat| reports the status of the dual basic solution for the specified problem object as follows: \verb|GLP_UNDEF | --- dual solution is undefined; \verb|GLP_FEAS | --- dual solution is feasible; \verb|GLP_INFEAS| --- dual solution is infeasible; \verb|GLP_NOFEAS| --- no dual feasible solution exists. \subsection{glp\_get\_obj\_val --- retrieve objective value} \synopsis \begin{verbatim} double glp_get_obj_val(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_obj_val| returns current value of the objective function. \subsection{glp\_get\_row\_stat --- retrieve row status} \synopsis \begin{verbatim} int glp_get_row_stat(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_stat| returns current status assigned to the auxiliary variable associated with \verb|i|-th row as follows: \verb|GLP_BS| --- basic variable; \verb|GLP_NL| --- non-basic variable on its lower bound; \verb|GLP_NU| --- non-basic variable on its upper bound; \verb|GLP_NF| --- non-basic free (unbounded) variable; \verb|GLP_NS| --- non-basic fixed variable. \newpage \subsection{glp\_get\_row\_prim --- retrieve row primal value} \synopsis \begin{verbatim} double glp_get_row_prim(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_prim| returns primal value of the auxiliary variable associated with \verb|i|-th row. \subsection{glp\_get\_row\_dual --- retrieve row dual value} \synopsis \begin{verbatim} double glp_get_row_dual(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_dual| returns dual value (i.e. reduced cost) of the auxiliary variable associated with \verb|i|-th row. \subsection{glp\_get\_col\_stat --- retrieve column status} \synopsis \begin{verbatim} int glp_get_col_stat(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_stat| returns current status assigned to the structural variable associated with \verb|j|-th column as follows: \verb|GLP_BS| --- basic variable; \verb|GLP_NL| --- non-basic variable on its lower bound; \verb|GLP_NU| --- non-basic variable on its upper bound; \verb|GLP_NF| --- non-basic free (unbounded) variable; \verb|GLP_NS| --- non-basic fixed variable. \subsection{glp\_get\_col\_prim --- retrieve column primal value} \synopsis \begin{verbatim} double glp_get_col_prim(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_prim| returns primal value of the structural variable associated with \verb|j|-th column. \newpage \subsection{glp\_get\_col\_dual --- retrieve column dual value} \synopsis \begin{verbatim} double glp_get_col_dual(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_dual| returns dual value (i.e. reduced cost) of the structural variable associated with \verb|j|-th column. \subsection{glp\_get\_unbnd\_ray --- determine variable causing unboundedness} \synopsis \begin{verbatim} int glp_get_unbnd_ray(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_unbnd_ray| returns the number $k$ of a variable, which causes primal or dual unboundedness. If $1\leq k\leq m$, it is $k$-th auxiliary variable, and if $m+1\leq k\leq m+n$, it is $(k-m)$-th structural variable, where $m$ is the number of rows, $n$ is the number of columns in the problem object. If such variable is not defined, the routine returns 0. \para{Note} If it is not exactly known which version of the simplex solver detected unboundedness, i.e. whether the unboundedness is primal or dual, it is sufficient to check the status of the variable with the routine \verb|glp_get_row_stat| or \verb|glp_get_col_stat|. If the variable is non-basic, the unboundedness is primal, otherwise, if the variable is basic, the unboundedness is dual (the latter case means that the problem has no primal feasible dolution). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Interior-point method routines} {\it Interior-point methods} (also known as {\it barrier methods}) are more modern and powerful numerical methods for large-scale linear programming. Such methods are especially efficient for very sparse LP problems and allow solving such problems much faster than the simplex method. In brief, the GLPK interior-point solver works as follows. At first, the solver transforms the original LP to a {\it working} LP in the standard format: \medskip \noindent \hspace{.5in} minimize $$z = c_1x_{m+1} + c_2x_{m+2} + \dots + c_nx_{m+n} + c_0 \eqno (2.4)$$ \hspace{.5in} subject to linear constraints $$ \begin{array}{r@{\:}c@{\:}r@{\:}c@{\:}r@{\:}c@{\:}l} a_{11}x_{m+1}&+&a_{12}x_{m+2}&+ \dots +&a_{1n}x_{m+n}&=&b_1 \\ a_{21}x_{m+1}&+&a_{22}x_{m+2}&+ \dots +&a_{2n}x_{m+n}&=&b_2 \\ \multicolumn{7}{c} {.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .} \\ a_{m1}x_{m+1}&+&a_{m2}x_{m+2}&+ \dots +&a_{mn}x_{m+n}&=&b_m \\ \end{array} \eqno (2.5) $$ \hspace{.5in} and non-negative variables $$x_1\geq 0,\ \ x_2\geq 0,\ \ \dots,\ \ x_n\geq 0 \eqno(2.6)$$ where: $z$ is the objective function; $x_1$, \dots, $x_n$ are variables; $c_1$, \dots, $c_n$ are objective coefficients; $c_0$ is a constant term of the objective function; $a_{11}$, \dots, $a_{mn}$ are constraint coefficients; $b_1$, \dots, $b_m$ are right-hand sides. Using vector and matrix notations the working LP (2.4)---(2.6) can be written as follows: $$z=c^Tx+c_0\ \rightarrow\ \min,\eqno(2.7)$$ $$Ax=b,\eqno(2.8)$$ $$x\geq 0,\eqno(2.9)$$ where: $x=(x_j)$ is $n$-vector of variables, $c=(c_j)$ is $n$-vector of objective coefficients, $A=(a_{ij})$ is $m\times n$-matrix of constraint coefficients, and $b=(b_i)$ is $m$-vector of right-hand sides. Karush--Kuhn--Tucker optimality conditions for LP (2.7)---(2.9) are the following: $$Ax=b,\eqno(2.10)$$ $$A^T\pi+\lambda=c,\eqno(2.11)$$ $$\lambda^Tx=0,\eqno(2.12)$$ $$x\geq 0,\ \ \lambda\geq 0,\eqno(2.13)$$ where: $\pi$ is $m$-vector of Lagrange multipliers (dual variables) for equality constraints (2.8),\linebreak $\lambda$ is $n$-vector of Lagrange multipliers (dual variables) for non-negativity constraints (2.9),\linebreak (2.10) is the primal feasibility condition, (2.11) is the dual feasibility condition, (2.12) is the primal-dual complementarity condition, and (2.13) is the non-negativity conditions. The main idea of the primal-dual interior-point method is based on finding a point in the primal-dual space (i.e. in the space of all primal and dual variables $x$, $\pi$, and $\lambda$), which satisfies to all optimality conditions (2.10)---(2.13). Obviously, $x$-component of such point then provides an optimal solution to the working LP (2.7)---(2.9). To find the optimal point $(x^*,\pi^*,\lambda^*)$ the interior-point method attempts to solve the system of equations (2.10)---(2.12), which is closed in the sense that the number of variables $x_j$, $\pi_i$, and $\lambda_j$ and the number equations are the same and equal to $m+2n$. Due to condition (2.12) this system of equations is non-linear, so it can be solved with a version of {\it Newton's method} provided with additional rules to keep the current point within the positive orthant as required by the non-negativity conditions (2.13). Finally, once the optimal point $(x^*,\pi^*,\lambda^*)$ has been found, the solver performs inverse transformations to recover corresponding solution to the original LP passed to the solver from the application program. \subsection{glp\_interior --- solve LP problem with the interior-point method} \synopsis \begin{verbatim} int glp_interior(glp_prob *P, const glp_iptcp *parm); \end{verbatim} \description The routine \verb|glp_interior| is a driver to the LP solver based on the primal-dual interior-point method. This routine retrieves problem data from the specified problem object, calls the solver to solve the problem instance, and stores results of computations back into the problem object. The interior-point solver has a set of control parameters. Values of the control parameters can be passed in the structure \verb|glp_iptcp|, which the parameter \verb|parm| points to. For detailed description of this structure see paragraph ``Control parameters'' below. Before specifying some control parameters the application program should initialize the structure \verb|glp_iptcp| by default values of all control parameters using the routine \verb|glp_init_iptcp| (see the next subsection). This is needed for backward compatibility, because in the future there may appear new members in the structure \verb|glp_iptcp|. The parameter \verb|parm| can be specified as \verb|NULL|, in which case the solver uses default settings. \returns \begin{retlist} 0 & The LP problem instance has been successfully solved. (This code does {\it not} necessarily mean that the solver has found optimal solution. It only means that the solution process was successful.) \\ \verb|GLP_EFAIL| & The problem has no rows/columns.\\ \verb|GLP_ENOCVG| & Very slow convergence or divergence.\\ \verb|GLP_EITLIM| & Iteration limit exceeded.\\ \verb|GLP_EINSTAB| & Numerical instability on solving Newtonian system.\\ \end{retlist} \newpage \para{Comments} The routine \verb|glp_interior| implements an easy version of the primal-dual interior-point method based on Mehrotra's technique.\footnote{S. Mehrotra. On the implementation of a primal-dual interior point method. SIAM J. on Optim., 2(4), pp. 575-601, 1992.} Note that currently the GLPK interior-point solver does not include many important features, in particular: \vspace*{-8pt} \begin{itemize} \item it is not able to process dense columns. Thus, if the constraint matrix of the LP problem has dense columns, the solving process may be inefficient; \item it has no features against numerical instability. For some LP problems premature termination may happen if the matrix $ADA^T$ becomes singular or ill-conditioned; \item it is not able to identify the optimal basis, which corresponds to the interior-point solution found. \end{itemize} \vspace*{-8pt} \para{Terminal output} Solving large LP problems may take a long time, so the solver reports some information about every interior-point iteration,\footnote{Unlike the simplex method the interior point method usually needs 30---50 iterations (independently on the problem size) in order to find an optimal solution.} which is sent to the terminal. This information has the following format: \begin{verbatim} nnn: obj = fff; rpi = ppp; rdi = ddd; gap = ggg \end{verbatim} \noindent where: \verb|nnn| is iteration number, \verb|fff| is the current value of the objective function (in the case of maximization it has wrong sign), \verb|ppp| is the current relative primal infeasibility (cf. (2.10)): $$\frac{\|Ax^{(k)}-b\|}{1+\|b\|},\eqno(2.14)$$ \verb|ddd| is the current relative dual infeasibility (cf. (2.11)): $$\frac{\|A^T\pi^{(k)}+\lambda^{(k)}-c\|}{1+\|c\|},\eqno(2.15)$$ \verb|ggg| is the current primal-dual gap (cf. (2.12)): $$\frac{|c^Tx^{(k)}-b^T\pi^{(k)}|}{1+|c^Tx^{(k)}|},\eqno(2.16)$$ and $[x^{(k)},\pi^{(k)},\lambda^{(k)}]$ is the current point on $k$-th iteration, $k=0,1,2,\dots$\ . Note that all solution components are internally scaled, so information sent to the terminal is suitable only for visual inspection. \newpage \para{Control parameters} This paragraph describes all control parameters currently used in the interior-point solver. Symbolic names of control parameters are names of corresponding members in the structure \verb|glp_iptcp|. \bigskip {\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) Message level for terminal output: \verb|GLP_MSG_OFF|---no output; \verb|GLP_MSG_ERR|---error and warning messages only; \verb|GLP_MSG_ON |---normal output; \verb|GLP_MSG_ALL|---full output (including informational messages). \bigskip {\tt int ord\_alg} (default: {\tt GLP\_ORD\_AMD}) Ordering algorithm used prior to Cholesky factorization: \verb|GLP_ORD_NONE |---use natural (original) ordering; \verb|GLP_ORD_QMD |---quotient minimum degree (QMD); \verb|GLP_ORD_AMD |---approximate minimum degree (AMD); \verb|GLP_ORD_SYMAMD|---approximate minimum degree (SYMAMD). \bigskip \para{Example} The following main program reads LP problem instance in fixed MPS format from file\linebreak \verb|25fv47.mps|,\footnote{This instance in fixed MPS format can be found in the Netlib LP collection; see {\tt ftp://ftp.netlib.org/lp/data/}.} solves it with the interior-point solver, and writes the solution to file \verb|25fv47.txt|. \begin{footnotesize} \begin{verbatim} /* iptsamp.c */ #include #include #include int main(void) { glp_prob *P; P = glp_create_prob(); glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); glp_interior(P, NULL); glp_print_ipt(P, "25fv47.txt"); glp_delete_prob(P); return 0; } /* eof */ \end{verbatim} \end{footnotesize} \newpage Below here is shown the terminal output from this example program. \begin{footnotesize} \begin{verbatim} Reading problem data from `25fv47.mps'... Problem: 25FV47 Objective: R0000 822 rows, 1571 columns, 11127 non-zeros 6919 records were read Original LP has 822 row(s), 1571 column(s), and 11127 non-zero(s) Working LP has 821 row(s), 1876 column(s), and 10705 non-zero(s) Matrix A has 10705 non-zeros Matrix S = A*A' has 11895 non-zeros (upper triangle) Minimal degree ordering... Computing Cholesky factorization S = L'*L... Matrix L has 35411 non-zeros Guessing initial point... Optimization begins... 0: obj = 1.823377629e+05; rpi = 1.3e+01; rdi = 1.4e+01; gap = 9.3e-01 1: obj = 9.260045192e+04; rpi = 5.3e+00; rdi = 5.6e+00; gap = 6.8e+00 2: obj = 3.596999742e+04; rpi = 1.5e+00; rdi = 1.2e+00; gap = 1.8e+01 3: obj = 1.989627568e+04; rpi = 4.7e-01; rdi = 3.0e-01; gap = 1.9e+01 4: obj = 1.430215557e+04; rpi = 1.1e-01; rdi = 8.6e-02; gap = 1.4e+01 5: obj = 1.155716505e+04; rpi = 2.3e-02; rdi = 2.4e-02; gap = 6.8e+00 6: obj = 9.660273208e+03; rpi = 6.7e-03; rdi = 4.6e-03; gap = 3.9e+00 7: obj = 8.694348283e+03; rpi = 3.7e-03; rdi = 1.7e-03; gap = 2.0e+00 8: obj = 8.019543639e+03; rpi = 2.4e-03; rdi = 3.9e-04; gap = 1.0e+00 9: obj = 7.122676293e+03; rpi = 1.2e-03; rdi = 1.5e-04; gap = 6.6e-01 10: obj = 6.514534518e+03; rpi = 6.1e-04; rdi = 4.3e-05; gap = 4.1e-01 11: obj = 6.361572203e+03; rpi = 4.8e-04; rdi = 2.2e-05; gap = 3.0e-01 12: obj = 6.203355508e+03; rpi = 3.2e-04; rdi = 1.7e-05; gap = 2.6e-01 13: obj = 6.032943411e+03; rpi = 2.0e-04; rdi = 9.3e-06; gap = 2.1e-01 14: obj = 5.796553021e+03; rpi = 9.8e-05; rdi = 3.2e-06; gap = 1.0e-01 15: obj = 5.667032431e+03; rpi = 4.4e-05; rdi = 1.1e-06; gap = 5.6e-02 16: obj = 5.613911867e+03; rpi = 2.5e-05; rdi = 4.1e-07; gap = 3.5e-02 17: obj = 5.560572626e+03; rpi = 9.9e-06; rdi = 2.3e-07; gap = 2.1e-02 18: obj = 5.537276001e+03; rpi = 5.5e-06; rdi = 8.4e-08; gap = 1.1e-02 19: obj = 5.522746942e+03; rpi = 2.2e-06; rdi = 4.0e-08; gap = 6.7e-03 20: obj = 5.509956679e+03; rpi = 7.5e-07; rdi = 1.8e-08; gap = 2.9e-03 21: obj = 5.504571733e+03; rpi = 1.6e-07; rdi = 5.8e-09; gap = 1.1e-03 22: obj = 5.502576367e+03; rpi = 3.4e-08; rdi = 1.0e-09; gap = 2.5e-04 23: obj = 5.502057119e+03; rpi = 8.1e-09; rdi = 3.0e-10; gap = 7.7e-05 24: obj = 5.501885996e+03; rpi = 9.4e-10; rdi = 1.2e-10; gap = 2.4e-05 25: obj = 5.501852464e+03; rpi = 1.4e-10; rdi = 1.2e-11; gap = 3.0e-06 26: obj = 5.501846549e+03; rpi = 1.4e-11; rdi = 1.2e-12; gap = 3.0e-07 27: obj = 5.501845954e+03; rpi = 1.4e-12; rdi = 1.2e-13; gap = 3.0e-08 28: obj = 5.501845895e+03; rpi = 1.5e-13; rdi = 1.2e-14; gap = 3.0e-09 OPTIMAL SOLUTION FOUND Writing interior-point solution to `25fv47.txt'... \end{verbatim} \end{footnotesize} \newpage \subsection{glp\_init\_iptcp --- initialize interior-point solver control parameters} \synopsis \begin{verbatim} int glp_init_iptcp(glp_iptcp *parm); \end{verbatim} \description The routine \verb|glp_init_iptcp| initializes control parameters, which are used by the interior-point solver, with default values. Default values of the control parameters are stored in the structure \verb|glp_iptcp|, which the parameter \verb|parm| points to. \subsection{glp\_ipt\_status --- determine solution status} \synopsis \begin{verbatim} int glp_ipt_status(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_ipt_status| reports the status of a solution found by the interior-point solver as follows: \verb|GLP_UNDEF | --- interior-point solution is undefined; \verb|GLP_OPT | --- interior-point solution is optimal; \verb|GLP_INFEAS| --- interior-point solution is infeasible; \verb|GLP_NOFEAS| --- no feasible primal-dual solution exists. \subsection{glp\_ipt\_obj\_val --- retrieve objective value} \synopsis \begin{verbatim} double glp_ipt_obj_val(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_ipt_obj_val| returns value of the objective function for interior-point solution. \subsection{glp\_ipt\_row\_prim --- retrieve row primal value} \synopsis \begin{verbatim} double glp_ipt_row_prim(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_ipt_row_prim| returns primal value of the auxiliary variable associated with \verb|i|-th row. \newpage \subsection{glp\_ipt\_row\_dual --- retrieve row dual value} \synopsis \begin{verbatim} double glp_ipt_row_dual(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_ipt_row_dual| returns dual value (i.e. reduced cost) of the auxiliary variable associated with \verb|i|-th row. \subsection{glp\_ipt\_col\_prim --- retrieve column primal value} \synopsis \begin{verbatim} double glp_ipt_col_prim(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_ipt_col_prim| returns primal value of the structural variable associated with \verb|j|-th column. \subsection{glp\_ipt\_col\_dual --- retrieve column dual value} \synopsis \begin{verbatim} double glp_ipt_col_dual(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_ipt_col_dual| returns dual value (i.e. reduced cost) of the structural variable associated with \verb|j|-th column. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Mixed integer programming routines} \subsection{glp\_set\_col\_kind --- set (change) column kind} \synopsis \begin{verbatim} void glp_set_col_kind(glp_prob *P, int j, int kind); \end{verbatim} \description The routine \verb|glp_set_col_kind| sets (changes) the kind of \verb|j|-th column (structural variable) as specified by the parameter \verb|kind|: \verb|GLP_CV| --- continuous variable; \verb|GLP_IV| --- integer variable; \verb|GLP_BV| --- binary variable. Setting a column to \verb|GLP_BV| has the same effect as if it were set to \verb|GLP_IV|, its lower bound were set 0, and its upper bound were set to 1. \subsection{glp\_get\_col\_kind --- retrieve column kind} \synopsis \begin{verbatim} int glp_get_col_kind(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_kind| returns the kind of \verb|j|-th column (structural variable) as follows: \verb|GLP_CV| --- continuous variable; \verb|GLP_IV| --- integer variable; \verb|GLP_BV| --- binary variable. \subsection{glp\_get\_num\_int --- retrieve number of integer columns} \synopsis \begin{verbatim} int glp_get_num_int(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_num_int| returns the number of columns (structural variables), which are marked as integer. Note that this number {\it does} include binary columns. \newpage \subsection{glp\_get\_num\_bin --- retrieve number of binary columns} \synopsis \begin{verbatim} int glp_get_num_bin(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_get_num_bin| returns the number of columns (structural variables), which are marked as integer and whose lower bound is zero and upper bound is one. \subsection{glp\_intopt --- solve MIP problem with the branch-and-cut method} \synopsis \begin{verbatim} int glp_intopt(glp_prob *P, const glp_iocp *parm); \end{verbatim} \description The routine \verb|glp_intopt| is a driver to the MIP solver based on the branch-and-cut method, which is a hybrid of branch-and-bound and cutting plane methods. If the presolver is disabled (see paragraph ``Control parameters'' below), on entry to the routine \verb|glp_intopt| the problem object, which the parameter \verb|mip| points to, should contain optimal solution to LP relaxation (it can be obtained, for example, with the routine \verb|glp_simplex|). Otherwise, if the presolver is enabled, it is not necessary. The MIP solver has a set of control parameters. Values of the control parameters can be passed in the structure \verb|glp_iocp|, which the parameter \verb|parm| points to. For detailed description of this structure see paragraph ``Control parameters'' below. Before specifying some control parameters the application program should initialize the structure \verb|glp_iocp| by default values of all control parameters using the routine \verb|glp_init_iocp| (see the next subsection). This is needed for backward compatibility, because in the future there may appear new members in the structure \verb|glp_iocp|. The parameter \verb|parm| can be specified as \verb|NULL|, in which case the solver uses default settings. Note that the GLPK branch-and-cut solver is not perfect, so it is unable to solve hard or very large scale MIP instances for a reasonable time. \returns \begin{retlist} 0 & The MIP problem instance has been successfully solved. (This code does {\it not} necessarily mean that the solver has found optimal solution. It only means that the solution process was successful.) \\ \verb|GLP_EBOUND| & Unable to start the search, because some double-bounded variables have incorrect bounds or some integer variables have non-integer (fractional) bounds.\\ \verb|GLP_EROOT| & Unable to start the search, because optimal basis for initial LP relaxation is not provided. (This code may appear only if the presolver is disabled.)\\ \verb|GLP_ENOPFS| & Unable to start the search, because LP relaxation of the MIP problem instance has no primal feasible solution. (This code may appear only if the presolver is enabled.)\\ \end{retlist} \newpage \begin{retlist} \verb|GLP_ENODFS| & Unable to start the search, because LP relaxation of the MIP problem instance has no dual feasible solution. In other word, this code means that if the LP relaxation has at least one primal feasible solution, its optimal solution is unbounded, so if the MIP problem has at least one integer feasible solution, its (integer) optimal solution is also unbounded. (This code may appear only if the presolver is enabled.)\\ \verb|GLP_EFAIL| & The search was prematurely terminated due to the solver failure.\\ \verb|GLP_EMIPGAP| & The search was prematurely terminated, because the relative mip gap tolerance has been reached.\\ \verb|GLP_ETMLIM| & The search was prematurely terminated, because the time limit has been exceeded.\\ \verb|GLP_ESTOP| & The search was prematurely terminated by application. (This code may appear only if the advanced solver interface is used.)\\ \end{retlist} \para{Built-in MIP presolver} The branch-and-cut solver has {\it built-in MIP presolver}. It is a subprogram that transforms the original MIP problem specified in the problem object to an equivalent MIP problem, which may be easier for solving with the branch-and-cut method than the original one. For example, the presolver can remove redundant constraints and variables, whose optimal values are known, perform bound and coefficient reduction, etc. Once the transformed MIP problem has been solved, the presolver transforms its solution back to corresponding solution of the original problem. Presolving is an optional feature of the routine \verb|glp_intopt|, and by default it is disabled. In order to enable the MIP presolver, the control parameter \verb|presolve| should be set to \verb|GLP_ON| (see paragraph ``Control parameters'' below). \para{Advanced solver interface} The routine \verb|glp_intopt| allows the user to control the branch-and-cut search by passing to the solver a user-defined callback routine. For more details see Chapter ``Branch-and-Cut API Routines''. \para{Terminal output} Solving a MIP problem may take a long time, so the solver reports some information about best known solutions, which is sent to the terminal. This information has the following format: \begin{verbatim} +nnn: mip = xxx yyy gap (ppp; qqq) \end{verbatim} \noindent where: `\verb|nnn|' is the simplex iteration number; `\verb|xxx|' is a value of the objective function for the best known integer feasible solution (if no integer feasible solution has been found yet, `\verb|xxx|' is the text `\verb|not found yet|'); `\verb|rho|' is the string `\verb|>=|' (in case of minimization) or `\verb|<=|' (in case of maximization); `\verb|yyy|' is a global bound for exact integer optimum (i.e. the exact integer optimum is always in the range from `\verb|xxx|' to `\verb|yyy|'); `\verb|gap|' is the relative mip gap, in percents, computed as $gap=|xxx-yyy|/(|xxx|+{\tt DBL\_EPSILON})\cdot 100\%$ (if $gap$ is greater than $999.9\%$, it is not printed); `\verb|ppp|' is the number of subproblems in the active list, `\verb|qqq|' is the number of subproblems which have been already fathomed and therefore removed from the branch-and-bound search tree. \newpage \subsubsection{Control parameters} This paragraph describes all control parameters currently used in the MIP solver. Symbolic names of control parameters are names of corresponding members in the structure \verb|glp_iocp|. \bigskip\vspace*{-2pt} {\tt int msg\_lev} (default: {\tt GLP\_MSG\_ALL}) Message level for terminal output: \verb|GLP_MSG_OFF| --- no output; \verb|GLP_MSG_ERR| --- error and warning messages only; \verb|GLP_MSG_ON | --- normal output; \verb|GLP_MSG_ALL| --- full output (including informational messages). \bigskip\vspace*{-2pt} {\tt int br\_tech} (default: {\tt GLP\_BR\_DTH}) Branching technique option: \verb|GLP_BR_FFV| --- first fractional variable; \verb|GLP_BR_LFV| --- last fractional variable; \verb|GLP_BR_MFV| --- most fractional variable; \verb|GLP_BR_DTH| --- heuristic by Driebeck and Tomlin; \verb|GLP_BR_PCH| --- hybrid pseudo-cost heuristic. \bigskip\vspace*{-2pt} {\tt int bt\_tech} (default: {\tt GLP\_BT\_BLB}) Backtracking technique option: \verb|GLP_BT_DFS| --- depth first search; \verb|GLP_BT_BFS| --- breadth first search; \verb|GLP_BT_BLB| --- best local bound; \verb|GLP_BT_BPH| --- best projection heuristic. \bigskip\vspace*{-2pt} {\tt int pp\_tech} (default: {\tt GLP\_PP\_ALL}) Preprocessing technique option: \verb|GLP_PP_NONE| --- disable preprocessing; \verb|GLP_PP_ROOT| --- perform preprocessing only on the root level; \verb|GLP_PP_ALL | --- perform preprocessing on all levels. \bigskip\vspace*{-2pt} {\tt int fp\_heur} (default: {\tt GLP\_OFF}) Feasibility pump heuristic option: \verb|GLP_ON | --- enable applying the feasibility pump heuristic; \verb|GLP_OFF| --- disable applying the feasibility pump heuristic. \newpage {\tt int ps\_heur} (default: {\tt GLP\_OFF}) Proximity search heuristic\footnote{The Fischetti--Monaci Proximity Search (a.k.a. Proxy) heuristic. This algorithm is often capable of rapidly improving a feasible solution of a MIP problem with binary variables. It allows to quickly obtain suboptimal solutions in some problems which take too long time to be solved to optimality.} option: \verb|GLP_ON | --- enable applying the proximity search heuristic; \verb|GLP_OFF| --- disable applying the proximity search pump heuristic. \bigskip {\tt int ps\_tm\_lim} (default: {\tt 60000}) Time limit, in milliseconds, for the proximity search heuristic (see above). \bigskip {\tt int gmi\_cuts} (default: {\tt GLP\_OFF}) Gomory's mixed integer cut option: \verb|GLP_ON | --- enable generating Gomory's cuts; \verb|GLP_OFF| --- disable generating Gomory's cuts. \bigskip {\tt int mir\_cuts} (default: {\tt GLP\_OFF}) Mixed integer rounding (MIR) cut option: \verb|GLP_ON | --- enable generating MIR cuts; \verb|GLP_OFF| --- disable generating MIR cuts. \bigskip {\tt int cov\_cuts} (default: {\tt GLP\_OFF}) Mixed cover cut option: \verb|GLP_ON | --- enable generating mixed cover cuts; \verb|GLP_OFF| --- disable generating mixed cover cuts. \bigskip {\tt int clq\_cuts} (default: {\tt GLP\_OFF}) Clique cut option: \verb|GLP_ON | --- enable generating clique cuts; \verb|GLP_OFF| --- disable generating clique cuts. \bigskip {\tt double tol\_int} (default: {\tt 1e-5}) Absolute tolerance used to check if optimal solution to the current LP relaxation is integer feasible. (Do not change this parameter without detailed understanding its purpose.) \newpage {\tt double tol\_obj} (default: {\tt 1e-7}) Relative tolerance used to check if the objective value in optimal solution to the current LP relaxation is not better than in the best known integer feasible solution. (Do not change this parameter without detailed understanding its purpose.) \bigskip {\tt double mip\_gap} (default: {\tt 0.0}) The relative mip gap tolerance. If the relative mip gap for currently known best integer feasible solution falls below this tolerance, the solver terminates the search. This allows obtainig suboptimal integer feasible solutions if solving the problem to optimality takes too long time. \bigskip {\tt int tm\_lim} (default: {\tt INT\_MAX}) Searching time limit, in milliseconds. \bigskip {\tt int out\_frq} (default: {\tt 5000}) Output frequency, in milliseconds. This parameter specifies how frequently the solver sends information about the solution process to the terminal. \bigskip {\tt int out\_dly} (default: {\tt 10000}) Output delay, in milliseconds. This parameter specifies how long the solver should delay sending information about solution of the current LP relaxation with the simplex method to the terminal. \bigskip {\tt void (*cb\_func)(glp\_tree *tree, void *info)} (default: {\tt NULL}) Entry point to the user-defined callback routine. \verb|NULL| means the advanced solver interface is not used. For more details see Chapter ``Branch-and-Cut API Routines''. \bigskip {\tt void *cb\_info} (default: {\tt NULL}) Transit pointer passed to the routine \verb|cb_func| (see above). \bigskip {\tt int cb\_size} (default: {\tt 0}) The number of extra (up to 256) bytes allocated for each node of the branch-and-bound tree to store application-specific data. On creating a node these bytes are initialized by binary zeros. \bigskip {\tt int presolve} (default: {\tt GLP\_OFF}) MIP presolver option: \verb|GLP_ON | --- enable using the MIP presolver; \verb|GLP_OFF| --- disable using the MIP presolver. \newpage {\tt int binarize} (default: {\tt GLP\_OFF}) Binarization option (used only if the presolver is enabled): \verb|GLP_ON | --- replace general integer variables by binary ones; \verb|GLP_OFF| --- do not use binarization. \subsection{glp\_init\_iocp --- initialize integer optimizer control parameters} \synopsis \begin{verbatim} void glp_init_iocp(glp_iocp *parm); \end{verbatim} \description The routine \verb|glp_init_iocp| initializes control parameters, which are used by the branch-and-cut solver, with default values. Default values of the control parameters are stored in a \verb|glp_iocp| structure, which the parameter \verb|parm| points to. \subsection{glp\_mip\_status --- determine status of MIP solution} \synopsis \begin{verbatim} int glp_mip_status(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_mip_status| reports the status of a MIP solution found by the MIP solver as follows: \verb|GLP_UNDEF | --- MIP solution is undefined; \verb|GLP_OPT | --- MIP solution is integer optimal; \verb|GLP_FEAS | --- MIP solution is integer feasible, however, its optimality (or non-optimality) has not been proven, perhaps due to premature termination of the search; \verb|GLP_NOFEAS| --- problem has no integer feasible solution (proven by the solver). \subsection{glp\_mip\_obj\_val --- retrieve objective value} \synopsis \begin{verbatim} double glp_mip_obj_val(glp_prob *P); \end{verbatim} \returns The routine \verb|glp_mip_obj_val| returns value of the objective function for MIP solution. \subsection{glp\_mip\_row\_val --- retrieve row value} \synopsis \begin{verbatim} double glp_mip_row_val(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_mip_row_val| returns value of the auxiliary variable associated with \verb|i|-th row for MIP solution. \subsection{glp\_mip\_col\_val --- retrieve column value} \synopsis \begin{verbatim} double glp_mip_col_val(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_mip_col_val| returns value of the structural variable associated with \verb|j|-th column for MIP solution. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Additional routines} \subsection{glp\_check\_kkt --- check feasibility/optimality conditions} \synopsis {\parskip=0pt \tt void glp\_check\_kkt(glp\_prob *P, int sol, int cond, double *ae\_max, int *ae\_ind, \hspace{105pt}double *re\_max, int *re\_ind);} \description The routine \verb|glp_check_kkt| allows to check feasibility/optimality conditions for the current solution stored in the specified problem object. (For basic and interior-point solutions these conditions are known as {\it Karush--Kuhn--Tucker optimality conditions}.) The parameter \verb|sol| specifies which solution should be checked: \verb|GLP_SOL| --- basic solution; \verb|GLP_IPT| --- interior-point solution; \verb|GLP_MIP| --- mixed integer solution. The parameter \verb|cond| specifies which condition should be checked: \verb|GLP_KKT_PE| --- check primal equality constraints (KKT.PE); \verb|GLP_KKT_PB| --- check primal bound constraints (KKT.PB); \verb|GLP_KKT_DE| --- check dual equality constraints (KKT.DE). This conditions can be checked only for basic or interior-point solution; \verb|GLP_KKT_DB| --- check dual bound constraints (KKT.DB). This conditions can be checked only for basic or interior-point solution. Detailed explanations of these conditions are given below in paragraph ``Background''. On exit the routine stores the following information to locations specified by parameters \verb|ae_max|, \verb|ae_ind|, \verb|re_max|, and \verb|re_ind| (if some parameter is a null pointer, corresponding information is not stored): \verb|ae_max| --- largest absolute error; \verb|ae_ind| --- number of row (KKT.PE), column (KKT.DE), or variable (KKT.PB, KKT.DB) with the largest absolute error; \verb|re_max| --- largest relative error; \verb|re_ind| --- number of row (KKT.PE), column (KKT.DE), or variable (KKT.PB, KKT.DB) with the largest relative error. Row (auxiliary variable) numbers are in the range 1 to $m$, where $m$ is the number of rows in the problem object. Column (structural variable) numbers are in the range 1 to $n$, where $n$ is the number of columns in the problem object. Variable numbers are in the range 1 to $m+n$, where variables with numbers 1 to $m$ correspond to rows, and variables with numbers $m+1$ to $m+n$ correspond to columns. If the error reported is exact zero, corresponding row, column or variable number is set to zero. \para{Background} \def\arraystretch{1.5} The first condition checked by the routine is the following: $$x_R - A x_S = 0, \eqno{\rm (KKT.PE)}$$ where $x_R$ is the subvector of auxiliary variables (rows), $x_S$ is the subvector of structural variables (columns), $A$ is the constraint matrix. This condition expresses the requirement that all primal variables should satisfy to the system of equality constraints of the original LP problem. In case of exact arithmetic this condition would be satisfied for any basic solution; however, in case of inexact (floating-point) arithmetic, this condition shows how accurate the primal solution is, that depends on accuracy of a representation of the basis matrix used by the simplex method, or on accuracy provided by the interior-point method. To check the condition (KKT.PE) the routine computes the vector of residuals: $$g = x_R - A x_S,$$ and determines component of this vector that correspond to largest absolute and relative errors: $${\tt ae\_max}=\max_{1\leq i\leq m}|g_i|,$$ $${\tt re\_max}=\max_{1\leq i\leq m}\frac{|g_i|}{1+|(x_R)_i|}.$$ The second condition checked by the routine is the following: $$l_k \leq x_k \leq u_k {\rm \ \ \ for\ all}\ k=1,\dots,m+n, \eqno{\rm (KKT.PB)}$$ where $x_k$ is auxiliary ($1\leq k\leq m$) or structural ($m+1\leq k\leq m+n$) variable, $l_k$ and $u_k$ are, respectively, lower and upper bounds of the variable $x_k$ (including cases of infinite bounds). This condition expresses the requirement that all primal variables shoudl satisfy to bound constraints of the original LP problem. In case of basic solution all non-basic variables are placed on their active bounds, so actually the condition (KKT.PB) needs to be checked for basic variables only. If the primal solution has sufficient accuracy, this condition shows its primal feasibility. To check the condition (KKT.PB) the routine computes a vector of residuals: $$ h_k = \left\{ \begin{array}{ll} 0, & {\rm if}\ l_k \leq x_k \leq u_k \\ x_k - l_k, & {\rm if}\ x_k < l_k \\ x_k - u_k, & {\rm if}\ x_k > u_k \\ \end{array} \right. $$ for all $k=1,\dots,m+n$, and determines components of this vector that correspond to largest absolute and relative errors: $${\tt ae\_max}=\max_{1\leq k \leq m+n}|h_k|,$$ $${\tt re\_max}=\max_{1\leq k \leq m+n}\frac{|h_k|}{1+|x_k|}.$$ The third condition checked by the routine is: $${\rm grad}\;Z = c = (\tilde{A})^T \pi + d,$$ where $Z$ is the objective function, $c$ is the vector of objective coefficients, $(\tilde{A})^T$ is a matrix transposed to the expanded constraint matrix $\tilde{A} = (I|-A)$, $\pi$ is a vector of Lagrange multipliers that correspond to equality constraints of the original LP problem, $d$ is a vector of Lagrange multipliers that correspond to bound constraints for all (auxiliary and structural) variables of the original LP problem. Geometrically the third condition expresses the requirement that the gradient of the objective function should belong to the orthogonal complement of a linear subspace defined by the equality and active bound constraints, i.e. that the gradient is a linear combination of normals to the constraint hyperplanes, where Lagrange multipliers $\pi$ and $d$ are coefficients of that linear combination. To eliminate the vector $\pi$ rewrite the third condition as: $$ \left(\begin{array}{@{}c@{}}I \\ -A^T\end{array}\right) \pi = \left(\begin{array}{@{}c@{}}d_R \\ d_S\end{array}\right) + \left(\begin{array}{@{}c@{}}c_R \\ c_S\end{array}\right), $$ or, equivalently, $$ \left\{ \begin{array}{r@{}c@{}c} \pi + d_R&\ =\ &c_R, \\ -A^T\pi + d_S&\ =\ &c_S. \\ \end{array} \right. $$ Then substituting the vector $\pi$ from the first equation into the second we finally have: $$A^T (d_R - c_R) + (d_S - c_S) = 0, \eqno{\rm(KKT.DE)}$$ where $d_R$ is the subvector of reduced costs of auxiliary variables (rows), $d_S$ is the subvector of reduced costs of structural variables (columns), $c_R$ and $c_S$ are subvectors of objective coefficients at, respectively, auxiliary and structural variables, $A^T$ is a matrix transposed to the constraint matrix of the original LP problem. In case of exact arithmetic this condition would be satisfied for any basic solution; however, in case of inexact (floating-point) arithmetic, this condition shows how accurate the dual solution is, that depends on accuracy of a representation of the basis matrix used by the simplex method, or on accuracy provided by the interior-point method. To check the condition (KKT.DE) the routine computes a vector of residuals: $$u = A^T (d_R - c_R) + (d_S - c_S),$$ and determines components of this vector that correspond to largest absolute and relative errors: $${\tt ae\_max}=\max_{1\leq j\leq n}|u_j|,$$ $${\tt re\_max}=\max_{1\leq j\leq n}\frac{|u_j|}{1+|(d_S)_j-(c_S)_j|}.$$ \newpage The fourth condition checked by the routine is the following: $$ \left\{ \begin{array}{l@{\ }r@{\ }c@{\ }c@{\ }c@{\ }l@{\ }c@{\ }c@{\ }c@{\ }l} {\rm if} & -\infty & < & x_k & < & +\infty, & {\rm then} & d_k & = & 0 \\ {\rm if} & l_k & \leq & x_k & < & +\infty, & {\rm then} & d_k & \geq & 0\ {\rm(minimization)} \\ &&&&&& & d_k & \leq & 0\ {\rm(maximization)} \\ {\rm if} & -\infty & < & x_k & \leq & u_k, & {\rm then} & d_k & \leq & 0\ {\rm(minimization)} \\ &&&&&& & d_k & \geq & 0\ {\rm(maximization)} \\ {\rm if} & l_k & \leq & x_k & \leq & u_k, & {\rm then} & d_k & {\rm is} & {\rm of\ any\ sign} \\ \end{array}\right.\eqno{\rm(KKT.DB)} $$ for all $k=1,\dots,m+n$, where $d_k$ is a reduced cost (Lagrange multiplier) of auxiliary ($1\leq k\leq m$) or structural ($m+1\leq k\leq m+n$) variable $x_k$. Geometrically this condition expresses the requirement that constraints of the original problem must ``hold'' the point preventing its movement along the anti-gradient (in case of minimization) or the gradient (in case of maximization) of the objective function. In case of basic solution reduced costs of all basic variables are placed on their active (zero) bounds, so actually the condition (KKT.DB) needs to be checked for non-basic variables only. If the dual solution has sufficient accuracy, this condition shows the dual feasibility of the solution. To check the condition (KKT.DB) the routine computes a vector of residuals: $$ v_k = \left\{ \begin{array}{ll} 0, & {\rm if}\ d_k\ {\rm has\ correct\ sign} \\ |d_k|, & {\rm if}\ d_k\ {\rm has\ wrong\ sign} \\ \end{array} \right. $$ for all $k=1,\dots,m+n$, and determines components of this vector that correspond to largest absolute and relative errors: $${\tt ae\_max}=\max_{1\leq k\leq m+n}|v_k|,$$ $${\tt re\_max}=\max_{1\leq k\leq m+n}\frac{|v_k|}{1+|d_k - c_k|}.$$ Note that the complete set of Karush-Kuhn-Tucker optimality conditions also includes the fifth, so called {\it complementary slackness condition}, which expresses the requirement that at least either a primal variable $x_k$ or its dual counterpart $d_k$ should be on its bound for all $k=1,\dots,m+n$. Currently checking this condition is not implemented yet. \def\arraystretch{1} %* eof *% glpk-4.52.1/doc/glpk03.tex0000644000062000006210000014661312175147600014323 0ustar maomkpasswd%* glpk03.tex *% \chapter{Utility API routines} \section{Problem data reading/writing routines} \subsection{glp\_read\_mps --- read problem data in MPS format} \synopsis \begin{verbatim} int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, const char *fname); \end{verbatim} \description The routine \verb|glp_read_mps| reads problem data in MPS format from a text file. (The MPS format is described in Appendix \ref{champs}, page \pageref{champs}.) The parameter \verb|fmt| specifies the MPS format version as follows: \verb|GLP_MPS_DECK| --- fixed (ancient) MPS format; \verb|GLP_MPS_FILE| --- free (modern) MPS format. The parameter \verb|parm| is reserved for use in the future and should be specified as \verb|NULL|. The character string \verb|fname| specifies a name of the text file to be read in. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine \verb|glp_read_mps| decompresses it ``on the fly''.) Note that before reading data the current content of the problem object is completely erased with the routine \verb|glp_erase_prob|. \returns If the operation was successful, the routine \verb|glp_read_mps| returns zero. Otherwise, it prints an error message and returns non-zero. \newpage \subsection{glp\_write\_mps --- write problem data in MPS format} \synopsis \begin{verbatim} int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, const char *fname); \end{verbatim} \description The routine \verb|glp_write_mps| writes problem data in MPS format to a text file. (The MPS format is described in Appendix \ref{champs}, page \pageref{champs}.) The parameter \verb|fmt| specifies the MPS format version as follows: \verb|GLP_MPS_DECK| --- fixed (ancient) MPS format; \verb|GLP_MPS_FILE| --- free (modern) MPS format. The parameter \verb|parm| is reserved for use in the future and should be specified as \verb|NULL|. The character string \verb|fname| specifies a name of the text file to be written out. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine \verb|glp_write_mps| performs automatic compression on writing it.) \returns If the operation was successful, the routine \verb|glp_write_mps| returns zero. Otherwise, it prints an error message and returns non-zero. \subsection{glp\_read\_lp --- read problem data in CPLEX LP format} \synopsis {\tt int glp\_read\_lp(glp\_prob *P, const glp\_cpxcp *parm, const char *fname);} \description The routine \verb|glp_read_lp| reads problem data in CPLEX LP format from a text file. (The CPLEX LP format is described in Appendix \ref{chacplex}, page \pageref{chacplex}.) The parameter \verb|parm| is reserved for use in the future and should be specified as \verb|NULL|. The character string \verb|fname| specifies a name of the text file to be read in. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine \verb|glp_read_lp| decompresses it ``on the fly''.) Note that before reading data the current content of the problem object is completely erased with the routine \verb|glp_erase_prob|. \returns If the operation was successful, the routine \verb|glp_read_lp| returns zero. Otherwise, it prints an error message and returns non-zero. \newpage \subsection{glp\_write\_lp --- write problem data in CPLEX LP format} \synopsis {\tt int glp\_write\_lp(glp\_prob *P, const glp\_cpxcp *parm, const char *fname);} \description The routine \verb|glp_write_lp| writes problem data in CPLEX LP format to a text file. (The CPLEX LP format is described in Appendix \ref{chacplex}, page \pageref{chacplex}.) The parameter \verb|parm| is reserved for use in the future and should be specified as \verb|NULL|. The character string \verb|fname| specifies a name of the text file to be written out. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine \verb|glp_write_lp| performs automatic compression on writing it.) \returns If the operation was successful, the routine \verb|glp_write_lp| returns zero. Otherwise, it prints an error message and returns non-zero. \subsection{glp\_read\_prob --- read problem data in GLPK format} \synopsis \begin{verbatim} int glp_read_prob(glp_prob *P, int flags, const char *fname); \end{verbatim} \description The routine \verb|glp_read_prob| reads problem data in the GLPK LP/MIP format from a text file. (For description of the GLPK LP/MIP format see below.) The parameter \verb|flags| is reserved for use in the future and should be specified as zero. The character string \verb|fname| specifies a name of the text file to be read in. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine \verb|glp_read_prob| decompresses it ``on the fly''.) Note that before reading data the current content of the problem object is completely erased with the routine \verb|glp_erase_prob|. \returns If the operation was successful, the routine \verb|glp_read_prob| returns zero. Otherwise, it prints an error message and returns non-zero. \newpage \para{GLPK LP/MIP format} The GLPK LP/MIP format is a DIMACS-like format.\footnote{The DIMACS formats were developed by the Center for Discrete Mathematics and Theoretical Computer Science (DIMACS) to facilitate exchange of problem data. For details see: {\tt }. } The file in this format is a plain ASCII text file containing lines of several types described below. A line is terminated with the end-of-line character. Fields in each line are separated by at least one blank space. Each line begins with a one-character designator to identify the line type. The first line of the data file must be the problem line (except optional comment lines, which may precede the problem line). The last line of the data file must be the end line. Other lines may follow in arbitrary order, however, duplicate lines are not allowed. \para{Comment lines.} Comment lines give human-readable information about the data file and are ignored by GLPK routines. Comment lines can appear anywhere in the data file. Each comment line begins with the lower-case character \verb|c|. \begin{verbatim} c This is an example of comment line \end{verbatim} \para{Problem line.} There must be exactly one problem line in the data file. This line must appear before any other lines except comment lines and has the following format: \begin{verbatim} p CLASS DIR ROWS COLS NONZ \end{verbatim} The lower-case letter \verb|p| specifies that this is the problem line. The \verb|CLASS| field defines the problem class and can contain either the keyword \verb|lp| (that means linear programming problem) or \verb|mip| (that means mixed integer programming problem). The \verb|DIR| field defines the optimization direction (that is, the objective function sense) and can contain either the keyword \verb|min| (that means minimization) or \verb|max| (that means maximization). The \verb|ROWS|, \verb|COLS|, and \verb|NONZ| fields contain non-negative integer values specifying, respectively, the number of rows (constraints), columns (variables), and non-zero constraint coefficients in the problem instance. Note that \verb|NONZ| value does not account objective coefficients. \para{Row descriptors.} There must be at most one row descriptor line in the data file for each row (constraint). This line has one of the following formats: \begin{verbatim} i ROW f i ROW l RHS i ROW u RHS i ROW d RHS1 RHS2 i ROW s RHS \end{verbatim} The lower-case letter \verb|i| specifies that this is the row descriptor line. The \verb|ROW| field specifies the row ordinal number, an integer between 1 and $m$, where $m$ is the number of rows in the problem instance. The next lower-case letter specifies the row type as follows: \verb|f| --- free (unbounded) row: $-\infty<\sum a_jx_j<+\infty$; \verb|l| --- inequality constraint of `$\geq$' type: $\sum a_jx_j\geq b$; \verb|u| --- inequality constraint of `$\leq$' type: $\sum a_jx_j\leq b$; \verb|d| --- double-sided inequality constraint: $b_1\leq\sum a_jx_j\leq b_2$; \verb|s| --- equality constraint: $\sum a_jx_j=b$. The \verb|RHS| field contains a floaing-point value specifying the row right-hand side. The \verb|RHS1| and \verb|RHS2| fields contain floating-point values specifying, respectively, the lower and upper right-hand sides for the double-sided row. If for some row its descriptor line does not appear in the data file, by default that row is assumed to be an equality constraint with zero right-hand side. \para{Column descriptors.} There must be at most one column descriptor line in the data file for each column (variable). This line has one of the following formats depending on the problem class specified in the problem line: \begin{tabular}{@{}l@{\hspace*{40pt}}l} LP class & MIP class \\ \hline \verb|j COL f| & \verb|j COL KIND f| \\ \verb|j COL l BND| & \verb|j COL KIND l BND| \\ \verb|j COL u BND| & \verb|j COL KIND u BND| \\ \verb|j COL d BND1 BND2| & \verb|j COL KIND d BND1 BND2| \\ \verb|j COL s BND| & \verb|j COL KIND s BND| \\ \end{tabular} The lower-case letter \verb|j| specifies that this is the column descriptor line. The \verb|COL| field specifies the column ordinal number, an integer between 1 and $n$, where $n$ is the number of columns in the problem instance. The \verb|KIND| field is used only for MIP problems and specifies the column kind as follows: \verb|c| --- continuous column; \verb|i| --- integer column; \verb|b| --- binary column (in this case all remaining fields must be omitted). The next lower-case letter specifies the column type as follows: \verb|f| --- free (unbounded) column: $-\infty #include #include int main(void) { glp_prob *lp; glp_tran *tran; int ret; lp = glp_create_prob(); tran = glp_mpl_alloc_wksp(); ret = glp_mpl_read_model(tran, "egypt.mod", 0); if (ret != 0) { fprintf(stderr, "Error on translating model\n"); goto skip; } ret = glp_mpl_generate(tran, NULL); if (ret != 0) { fprintf(stderr, "Error on generating model\n"); goto skip; } glp_mpl_build_prob(tran, lp); ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, "egypt.mps"); if (ret != 0) fprintf(stderr, "Error on writing MPS file\n"); skip: glp_mpl_free_wksp(tran); glp_delete_prob(lp); return 0; } /* eof */ \end{verbatim} \end{small} \newpage \subsubsection*{Example 2} In this example the program reads model section from file \verb|sudoku.mod|\footnote{This is an example model which is included in the GLPK distribution along with alternative data file {\tt sudoku.dat}.} ignoring data section in this file, reads alternative data section from file \verb|sudoku.dat|, solves the problem instance and passes the solution found back to the model. \bigskip \begin{small} \begin{verbatim} /* mplsamp2.c */ #include #include #include int main(void) { glp_prob *mip; glp_tran *tran; int ret; mip = glp_create_prob(); tran = glp_mpl_alloc_wksp(); ret = glp_mpl_read_model(tran, "sudoku.mod", 1); if (ret != 0) { fprintf(stderr, "Error on translating model\n"); goto skip; } ret = glp_mpl_read_data(tran, "sudoku.dat"); if (ret != 0) { fprintf(stderr, "Error on translating data\n"); goto skip; } ret = glp_mpl_generate(tran, NULL); if (ret != 0) { fprintf(stderr, "Error on generating model\n"); goto skip; } glp_mpl_build_prob(tran, mip); glp_simplex(mip, NULL); glp_intopt(mip, NULL); ret = glp_mpl_postsolve(tran, mip, GLP_MIP); if (ret != 0) fprintf(stderr, "Error on postsolving model\n"); skip: glp_mpl_free_wksp(tran); glp_delete_prob(mip); return 0; } /* eof */ \end{verbatim} \end{small} \newpage \subsection{glp\_mpl\_alloc\_wksp --- allocate the translator workspace} \synopsis \begin{verbatim} glp_tran *glp_mpl_alloc_wksp(void); \end{verbatim} \description The routine \verb|glp_mpl_alloc_wksp| allocates the MathProg translator work\-space. (Note that multiple instances of the workspace may be allocated, if necessary.) \returns The routine returns a pointer to the workspace, which should be used in all subsequent operations. \subsection{glp\_mpl\_read\_model --- read and translate model section} \synopsis \begin{verbatim} int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip); \end{verbatim} \description The routine \verb|glp_mpl_read_model| reads model section and, optionally, data section, which may follow the model section, from a text file, whose name is the character string \verb|fname|, performs translation of model statements and data blocks, and stores all the information in the workspace. The parameter \verb|skip| is a flag. If the input file contains the data section and this flag is non-zero, the data section is not read as if there were no data section and a warning message is printed. This allows reading data section(s) from other file(s). \returns If the operation is successful, the routine returns zero. Otherwise the routine prints an error message and returns non-zero. \subsection{glp\_mpl\_read\_data --- read and translate data section} \synopsis \begin{verbatim} int glp_mpl_read_data(glp_tran *tran, const char *fname); \end{verbatim} \description The routine \verb|glp_mpl_read_data| reads data section from a text file, whose name is the character string \verb|fname|, performs translation of data blocks, and stores the data read in the translator workspace. If necessary, this routine may be called more than once. \returns If the operation is successful, the routine returns zero. Otherwise the routine prints an error message and returns non-zero. \newpage \subsection{glp\_mpl\_generate --- generate the model} \synopsis \begin{verbatim} int glp_mpl_generate(glp_tran *tran, const char *fname); \end{verbatim} \description The routine \verb|glp_mpl_generate| generates the model using its description stored in the translator workspace. This operation means generating all variables, constraints, and objectives, executing check and display statements, which precede the solve statement (if it is presented). The character string \verb|fname| specifies the name of an output text file, to which output produced by display statements should be written. If \verb|fname| is \verb|NULL|, the output is sent to the terminal. \returns If the operation is successful, the routine returns zero. Otherwise the routine prints an error message and returns non-zero. \vspace*{-6pt} \subsection{glp\_mpl\_build\_prob --- build problem instance from the model} \synopsis \begin{verbatim} void glp_mpl_build_prob(glp_tran *tran, glp_prob *P); \end{verbatim} \description The routine \verb|glp_mpl_build_prob| obtains all necessary information from the translator work\-space and stores it in the specified problem object \verb|P|. Note that before building the current content of the problem object is erased with the routine \verb|glp_erase_prob|. \vspace*{-6pt} \subsection{glp\_mpl\_postsolve --- postsolve the model} \synopsis \begin{verbatim} int glp_mpl_postsolve(glp_tran *tran, glp_prob *P, int sol); \end{verbatim} \description The routine \verb|glp_mpl_postsolve| copies the solution from the specified problem object \verb|prob| to the translator workspace and then executes all the remaining model statements, which follow the solve statement. The parameter \verb|sol| specifies which solution should be copied from the problem object to the workspace as follows: \verb|GLP_SOL| --- basic solution; \verb|GLP_IPT| --- interior-point solution; \verb|GLP_MIP| --- mixed integer solution. \returns If the operation is successful, the routine returns zero. Otherwise the routine prints an error message and returns non-zero. \subsection{glp\_mpl\_free\_wksp --- free the translator workspace} \synopsis \begin{verbatim} void glp_mpl_free_wksp(glp_tran *tran); \end{verbatim} \description The routine \verb|glp_mpl_free_wksp| frees all the memory allocated to the translator workspace. It also frees all other resources, which are still used by the translator. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Problem solution reading/writing routines} \subsection{glp\_print\_sol --- write basic solution in printable format} \synopsis \begin{verbatim} int glp_print_sol(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_print_sol writes| the current basic solution of an LP problem, which is specified by the pointer \verb|P|, to a text file, whose name is the character string \verb|fname|, in printable format. Information reported by the routine \verb|glp_print_sol| is intended mainly for visual analysis. \returns If no errors occurred, the routine returns zero. Otherwise the routine prints an error message and returns non-zero. \subsection{glp\_read\_sol --- read basic solution from text file} \synopsis \begin{verbatim} int glp_read_sol(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_read_sol| reads basic solution from a text file whose name is specified by the parameter \verb|fname| into the problem object. For the file format see description of the routine \verb|glp_write_sol|. \returns On success the routine returns zero, otherwise non-zero. \subsection{glp\_write\_sol --- write basic solution to text file} \synopsis \begin{verbatim} int glp_write_sol(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_write_sol| writes the current basic solution to a text file whose name is specified by the parameter \verb|fname|. This file can be read back with the routine \verb|glp_read_sol|. \returns On success the routine returns zero, otherwise non-zero. \newpage \para{File format} The file created by the routine \verb|glp_write_sol| is a plain text file, which contains the following information: \begin{verbatim} m n p_stat d_stat obj_val r_stat[1] r_prim[1] r_dual[1] . . . r_stat[m] r_prim[m] r_dual[m] c_stat[1] c_prim[1] c_dual[1] . . . c_stat[n] c_prim[n] c_dual[n] \end{verbatim} \noindent where: \noindent $m$ is the number of rows (auxiliary variables); \noindent $n$ is the number of columns (structural variables); \noindent \verb|p_stat| is the primal status of the basic solution\\ (\verb|GLP_UNDEF| = 1, \verb|GLP_FEAS| = 2, \verb|GLP_INFEAS| = 3, or \verb|GLP_NOFEAS| = 4); \noindent \verb|d_stat| is the dual status of the basic solution\\ (\verb|GLP_UNDEF| = 1, \verb|GLP_FEAS| = 2, \verb|GLP_INFEAS| = 3, or \verb|GLP_NOFEAS| = 4); \noindent \verb|obj_val| is the objective value; \noindent \verb|r_stat[i]|, $i=1,\dots,m$, is the status of $i$-th row\\ (\verb|GLP_BS| = 1, \verb|GLP_NL| = 2, \verb|GLP_NU| = 3, \verb|GLP_NF| = 4, or \verb|GLP_NS| = 5); \noindent \verb|r_prim[i]|, $i=1,\dots,m$, is the primal value of $i$-th row; \noindent \verb|r_dual[i]|, $i=1,\dots,m$, is the dual value of $i$-th row; \noindent \verb|c_stat[j]|, $j=1,\dots,n$, is the status of $j$-th column\\ (\verb|GLP_BS| = 1, \verb|GLP_NL| = 2, \verb|GLP_NU| = 3, \verb|GLP_NF| = 4, or \verb|GLP_NS| = 5); \noindent \verb|c_prim[j]|, $j=1,\dots,n$, is the primal value of $j$-th column; \noindent \verb|c_dual[j]|, $j=1,\dots,n$, is the dual value of $j$-th column. \subsection{glp\_print\_ipt --- write interior-point solution in printable format} \synopsis \begin{verbatim} int glp_print_ipt(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_print_ipt| writes the current interior point solution of an LP problem, which the parameter \verb|P| points to, to a text file, whose name is the character string \verb|fname|, in printable format. Information reported by the routine \verb|glp_print_ipt| is intended mainly for visual analysis. \newpage \returns If no errors occurred, the routine returns zero. Otherwise the routine prints an error message and returns non-zero. \subsection{glp\_read\_ipt --- read interior-point solution from text file} \synopsis \begin{verbatim} int glp_read_ipt(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_read_ipt| reads interior-point solution from a text file whose name is specified by the parameter \verb|fname| into the problem object. For the file format see description of the routine \verb|glp_write_ipt|. \returns On success the routine returns zero, otherwise non-zero. \subsection{glp\_write\_ipt --- write interior-point solution to text file} \synopsis \begin{verbatim} int glp_write_ipt(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_write_ipt| writes the current interior-point solution to a text file whose name is specified by the parameter \verb|fname|. This file can be read back with the routine \verb|glp_read_ipt|. \returns On success the routine returns zero, otherwise non-zero. \para{File format} The file created by the routine \verb|glp_write_ipt| is a plain text file, which contains the following information: \begin{verbatim} m n stat obj_val r_prim[1] r_dual[1] . . . r_prim[m] r_dual[m] c_prim[1] c_dual[1] . . . c_prim[n] c_dual[n] \end{verbatim} \noindent where: \noindent $m$ is the number of rows (auxiliary variables); \noindent $n$ is the number of columns (structural variables); \noindent \verb|stat| is the solution status (\verb|GLP_UNDEF| = 1 or \verb|GLP_OPT| = 5); \noindent \verb|obj_val| is the objective value; \noindent \verb|r_prim[i]|, $i=1,\dots,m$, is the primal value of $i$-th row; \noindent \verb|r_dual[i]|, $i=1,\dots,m$, is the dual value of $i$-th row; \noindent \verb|c_prim[j]|, $j=1,\dots,n$, is the primal value of $j$-th column; \noindent \verb|c_dual[j]|, $j=1,\dots,n$, is the dual value of $j$-th column. \subsection{glp\_print\_mip --- write MIP solution in printable format} \synopsis \begin{verbatim} int glp_print_mip(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_print_mip| writes a best known integer solution of a MIP problem, which is specified by the pointer \verb|P|, to a text file, whose name is the character string \verb|fname|, in printable format. Information reported by the routine \verb|glp_print_mip| is intended mainly for visual analysis. \returns If no errors occurred, the routine returns zero. Otherwise the routine prints an error message and returns non-zero. \subsection{glp\_read\_mip --- read MIP solution from text file} \synopsis \begin{verbatim} int glp_read_mip(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_read_mip| reads MIP solution from a text file whose name is specified by the parameter \verb|fname| into the problem object. For the file format see description of the routine \verb|glp_write_mip|. \returns On success the routine returns zero, otherwise non-zero. \newpage \subsection{glp\_write\_mip --- write MIP solution to text file} \synopsis \begin{verbatim} int glp_write_mip(glp_prob *P, const char *fname); \end{verbatim} \description The routine \verb|glp_write_mip| writes the current MIP solution to a text file whose name is specified by the parameter \verb|fname|. This file can be read back with the routine \verb|glp_read_mip|. \returns On success the routine returns zero, otherwise non-zero. \para{File format} The file created by the routine \verb|glp_write_sol| is a plain text file, which contains the following information: \begin{verbatim} m n stat obj_val r_val[1] . . . r_val[m] c_val[1] . . . c_val[n] \end{verbatim} \noindent where: \noindent $m$ is the number of rows (auxiliary variables); \noindent $n$ is the number of columns (structural variables); \noindent \verb|stat| is the solution status\\(\verb|GLP_UNDEF| = 1, \verb|GLP_FEAS| = 2, \verb|GLP_NOFEAS| = 4, or \verb|GLP_OPT| = 5); \noindent \verb|obj_val| is the objective value; \noindent \verb|r_val[i]|, $i=1,\dots,m$, is the value of $i$-th row; \noindent \verb|c_val[j]|, $j=1,\dots,n$, is the value of $j$-th column. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Post-optimal analysis routines} \subsection{glp\_print\_ranges --- print sensitivity analysis report} \synopsis {\tt int glp\_print\_ranges(glp\_prob *P, int len, const int list[], int flags,\\ \hspace*{134pt}const char *fname);} \description The routine \verb|glp_print_ranges| performs sensitivity analysis of current optimal basic solution and writes the analysis report in human-readable format to a text file, whose name is the character string {\it fname}. (Detailed description of the report structure is given below.) The parameter {\it len} specifies the length of the row/column list. The array {\it list} specifies ordinal number of rows and columns to be analyzed. The ordinal numbers should be passed in locations {\it list}[1], {\it list}[2], \dots, {\it list}[{\it len}]. Ordinal numbers from 1 to $m$ refer to rows, and ordinal numbers from $m+1$ to $m+n$ refer to columns, where $m$ and $n$ are, resp., the total number of rows and columns in the problem object. Rows and columns appear in the analysis report in the same order as they follow in the array list. It is allowed to specify $len=0$, in which case the array {\it list} is not used (so it can be specified as \verb|NULL|), and the routine performs analysis for all rows and columns of the problem object. The parameter {\it flags} is reserved for use in the future and must be specified as zero. On entry to the routine \verb|glp_print_ranges| the current basic solution must be optimal and the basis factorization must exist. The application program can check that with the routine \verb|glp_bf_exists|, and if the factorization does not exist, compute it with the routine \verb|glp_factorize|. Note that if the LP preprocessor is not used, on normal exit from the simplex solver routine \verb|glp_simplex| the basis factorization always exists. \returns If the operation was successful, the routine \verb|glp_print_ranges| returns zero. Otherwise, it prints an error message and returns non-zero. \para{Analysis report example} An example of the sensitivity analysis report is shown on the next two pages. This example corresponds to the example of LP problem described in Subsection ``Example of MPS file''. \para{Structure of the analysis report} For each row and column specified in the array {\it list} the routine prints two lines containing generic information and analysis information, which depends on the status of corresponding row or column. Note that analysis of a row is analysis of its auxiliary variable, which is equal to the row linear form $\sum a_jx_j$, and analysis of a column is analysis of corresponding structural variable. Therefore, formally, on performing the sensitivity analysis there is no difference between rows and columns. \newpage \begin{landscape} \begin{footnotesize} \begin{verbatim} GLPK 4.42 - SENSITIVITY ANALYSIS REPORT Page 1 Problem: PLAN Objective: VALUE = 296.2166065 (MINimum) No. Row name St Activity Slack Lower bound Activity Obj coef Obj value at Limiting Marginal Upper bound range range break point variable ------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------ 1 VALUE BS 296.21661 -296.21661 -Inf 299.25255 -1.00000 . MN . +Inf 296.21661 +Inf +Inf 2 YIELD NS 2000.00000 . 2000.00000 1995.06864 -Inf 296.28365 BIN3 -.01360 2000.00000 2014.03479 +Inf 296.02579 CU 3 FE NU 60.00000 . -Inf 55.89016 -Inf 306.77162 BIN4 -2.56823 60.00000 62.69978 2.56823 289.28294 BIN3 4 CU BS 83.96751 16.03249 -Inf 93.88467 -.30613 270.51157 MN . 100.00000 79.98213 .21474 314.24798 BIN5 5 MN NU 40.00000 . -Inf 34.42336 -Inf 299.25255 BIN4 -.54440 40.00000 41.68691 .54440 295.29825 BIN3 6 MG BS 19.96029 10.03971 -Inf 24.74427 -1.79618 260.36433 BIN1 . 30.00000 9.40292 .28757 301.95652 MN 7 AL NL 1500.00000 . 1500.00000 1485.78425 -.25199 292.63444 CU .25199 +Inf 1504.92126 +Inf 297.45669 BIN3 8 SI NL 250.00000 50.00000 250.00000 235.32871 -.48520 289.09812 CU .48520 300.00000 255.06073 +Inf 298.67206 BIN3 \end{verbatim} \end{footnotesize} \end{landscape} \newpage \begin{landscape} \begin{footnotesize} \begin{verbatim} GLPK 4.42 - SENSITIVITY ANALYSIS REPORT Page 2 Problem: PLAN Objective: VALUE = 296.2166065 (MINimum) No. Column name St Activity Obj coef Lower bound Activity Obj coef Obj value at Limiting Marginal Upper bound range range break point variable ------ ------------ -- ------------- ------------- ------------- ------------- ------------- ------------- ------------ 1 BIN1 NL . .03000 . -28.82475 -.22362 288.90594 BIN4 .25362 200.00000 33.88040 +Inf 304.80951 BIN4 2 BIN2 BS 665.34296 .08000 . 802.22222 .01722 254.44822 BIN1 . 2500.00000 313.43066 .08863 301.95652 MN 3 BIN3 BS 490.25271 .17000 400.00000 788.61314 .15982 291.22807 MN . 800.00000 -347.42857 .17948 300.86548 BIN5 4 BIN4 BS 424.18773 .12000 100.00000 710.52632 .10899 291.54745 MN . 700.00000 -256.15524 .14651 307.46010 BIN1 5 BIN5 NL . .15000 . -201.78739 .13544 293.27940 BIN3 .01456 1500.00000 58.79586 +Inf 297.07244 BIN3 6 ALUM BS 299.63899 .21000 . 358.26772 .18885 289.87879 AL . +Inf 112.40876 .22622 301.07527 MN 7 SILICON BS 120.57762 .38000 . 124.27093 .14828 268.27586 BIN5 . +Inf 85.54745 .46667 306.66667 MN End of report \end{verbatim} \end{footnotesize} \end{landscape} \newpage \noindent {\it Generic information} {\tt No.} is the row or column ordinal number in the problem object. Rows are numbered from 1 to $m$, and columns are numbered from 1 to $n$, where $m$ and $n$ are, resp., the total number of rows and columns in the problem object. {\tt Row name} is the symbolic name assigned to the row. If the row has no name assigned, this field contains blanks. {\tt Column name} is the symbolic name assigned to the column. If the column has no name assigned, this field contains blanks. {\tt St} is the status of the row or column in the optimal solution: {\tt BS} --- non-active constraint (row), basic column; {\tt NL} --- inequality constraint having its lower right-hand side active (row), non-basic column having its lower bound active; {\tt NU} --- inequality constraint having its upper right-hand side active (row), non-basic column having its upper bound active; {\tt NS} --- active equality constraint (row), non-basic fixed column. {\tt NF} --- active free row, non-basic free (unbounded) column. (This case means that the optimal solution is dual degenerate.) {\tt Activity} is the (primal) value of the auxiliary variable (row) or structural variable (column) in the optimal solution. {\tt Slack} is the (primal) value of the row slack variable. {\tt Obj coef} is the objective coefficient of the column (structural variable). {\tt Marginal} is the reduced cost (dual activity) of the auxiliary variable (row) or structural variable (column). {\tt Lower bound} is the lower right-hand side (row) or lower bound (column). If the row or column has no lower bound, this field contains {\tt -Inf}. {\tt Upper bound} is the upper right-hand side (row) or upper bound (column). If the row or column has no upper bound, this field contains {\tt +Inf}. \noindent {\it Sensitivity analysis of active bounds} The sensitivity analysis of active bounds is performed only for rows, which are active constraints, and only for non-basic columns, because inactive constraints and basic columns have no active bounds. For every auxiliary (row) or structural (column) non-basic variable the routine starts changing its active bound in both direction. The first of the two lines in the report corresponds to decreasing, and the second line corresponds to increasing of the active bound. Since the variable being analyzed is non-basic, its activity, which is equal to its active bound, also starts changing. This changing leads to changing of basic (auxiliary and structural) variables, which depend on the non-basic variable. The current basis remains primal feasible and therefore optimal while values of all basic variables are primal feasible, i.e. are within their bounds. Therefore, if some basic variable called the {\it limiting variable} reaches its (lower or upper) bound first, before any other basic variables, it thereby limits further changing of the non-basic variable, because otherwise the current basis would become primal infeasible. The point, at which this happens, is called the {\it break point}. Note that there are two break points: the lower break point, which corresponds to decreasing of the non-basic variable, and the upper break point, which corresponds to increasing of the non-basic variable. In the analysis report values of the non-basic variable (i.e. of its active bound) being analyzed at both lower and upper break points are printed in the field `{\tt Activity range}'. Corresponding values of the objective function are printed in the field `{\tt Obj value at break point}', and symbolic names of corresponding limiting basic variables are printed in the field `{\tt Limiting variable}'. If the active bound can decrease or/and increase unlimitedly, the field `{\tt Activity range}' contains {\tt -Inf} or/and {\tt +Inf}, resp. For example (see the example report above), row SI is a double-sided constraint, which is active on its lower bound (right-hand side), and its activity in the optimal solution being equal to the lower bound is 250. The activity range for this row is $[235.32871,255.06073]$. This means that the basis remains optimal while the lower bound is increasing up to 255.06073, and further increasing is limited by (structural) variable BIN3. If the lower bound reaches this upper break point, the objective value becomes equal to 298.67206. Note that if the basis does not change, the objective function depends on the non-basic variable linearly, and the per-unit change of the objective function is the reduced cost (marginal value) of the non-basic variable. \noindent {\it Sensitivity analysis of objective coefficients at non-basic variables} The sensitivity analysis of the objective coefficient at a non-basic variable is quite simple, because in this case change in the objective coefficient leads to equivalent change in the reduced cost (marginal value). For every auxiliary (row) or structural (column) non-basic variable the routine starts changing its objective coefficient in both direction. (Note that auxiliary variables are not included in the objective function and therefore always have zero objective coefficients.) The first of the two lines in the report corresponds to decreasing, and the second line corresponds to increasing of the objective coefficient. This changing leads to changing of the reduced cost of the non-basic variable to be analyzed and does affect reduced costs of all other non-basic variables. The current basis remains dual feasible and therefore optimal while the reduced cost keeps its sign. Therefore, if the reduced cost reaches zero, it limits further changing of the objective coefficient (if only the non-basic variable is non-fixed). In the analysis report minimal and maximal values of the objective coefficient, on which the basis remains optimal, are printed in the field `\verb|Obj coef range|'. If the objective coefficient can decrease or/and increase unlimitedly, this field contains {\tt -Inf} or/and {\tt +Inf}, resp. For example (see the example report above), column BIN5 is non-basic having its lower bound active. Its objective coefficient is 0.15, and reduced cost in the optimal solution 0.01456. The column lower bound remains active while the column reduced cost remains non-negative, thus, minimal value of the objective coefficient, on which the current basis still remains optimal, is $0.15-0.01456=0.13644$, that is indicated in the field `\verb|Obj coef range|'. \newpage {\parskip=0pt \noindent {\it Sensitivity analysis of objective coefficients at basic variables} \medskip To perform sensitivity analysis for every auxiliary (row) or structural (column) variable the routine starts changing its objective coefficient in both direction. (Note that auxiliary variables are not included in the objective function and therefore always have zero objective coefficients.) The first of the two lines in the report corresponds to decreasing, and the second line corresponds to increasing of the objective coefficient. This changing leads to changing of reduced costs of non-basic variables. The current basis remains dual feasible and therefore optimal while reduced costs of all non-basic variables (except fixed variables) keep their signs. Therefore, if the reduced cost of some non-basic non-fixed variable called the {\it limiting variable} reaches zero first, before reduced cost of any other non-basic non-fixed variable, it thereby limits further changing of the objective coefficient, because otherwise the current basis would become dual infeasible (non-optimal). The point, at which this happens, is called the {\it break point}. Note that there are two break points: the lower break point, which corresponds to decreasing of the objective coefficient, and the upper break point, which corresponds to increasing of the objective coefficient. Let the objective coefficient reach its limit value and continue changing a bit further in the same direction that makes the current basis dual infeasible (non-optimal). Then the reduced cost of the non-basic limiting variable becomes ``a bit'' dual infeasible that forces the limiting variable to enter the basis replacing there some basic variable, which leaves the basis to keep its primal feasibility. It should be understood that if we change the current basis in this way exactly at the break point, both the current and adjacent bases will be optimal with the same objective value, because at the break point the limiting variable has zero reduced cost. On the other hand, in the adjacent basis the value of the limiting variable changes, because there it becomes basic, that leads to changing of the value of the basic variable being analyzed. Note that on determining the adjacent basis the bounds of the analyzed basic variable are ignored as if it were a free (unbounded) variable, so it cannot leave the current basis. In the analysis report lower and upper limits of the objective coefficient at the basic variable being analyzed, when the basis remains optimal, are printed in the field `{\tt Obj coef range}'. Corresponding values of the objective function at both lower and upper break points are printed in the field `{\tt Obj value at break point}', symbolic names of corresponding non-basic limiting variables are printed in the field `{\tt Limiting variable}', and values of the basic variable, which it would take on in the adjacent bases (as was explained above) are printed in the field `{\tt Activity range}'. If the objective coefficient can increase or/and decrease unlimitedly, the field `{\tt Obj coef range}' contains {\tt -Inf} and/or {\tt +Inf}, resp. It also may happen that no dual feasible adjacent basis exists (i.e. on entering the basis the limiting variable can increase or decrease unlimitedly), in which case the field `{\tt Activity range}' contains {\tt -Inf} and/or {\tt +Inf}. For example (see the example report above), structural variable (column) BIN3 is basic, its optimal value is 490.25271, and its objective coefficient is 0.17. The objective coefficient range for this column is $[0.15982,0.17948]$. This means that the basis remains optimal while the objective coefficient is decreasing down to 0.15982, and further decreasing is limited by (auxiliary) variable MN. If we make the objective coefficient a bit less than 0.15982, the limiting variable MN will enter the basis, and in that adjacent basis the structural variable BIN3 will take on new optimal value 788.61314. At the lower break point, where the objective coefficient is exactly 0.15982, the objective function takes on the value 291.22807 in both the current and adjacent bases. Note that if the basis does not change, the objective function depends on the objective coefficient at the basic variable linearly, and the per-unit change of the objective function is the value of the basic variable. } %* eof *% glpk-4.52.1/doc/glpk04.tex0000644000062000006210000014715012175147600014321 0ustar maomkpasswd%* glpk04.tex *% \chapter{Advanced API Routines} \section{Background} \label{basbgd} Using vector and matrix notations the LP problem (1.1)---(1.3) (see Section \ref{seclp}, page \pageref{seclp}) can be stated as follows: \noindent \hspace{.5in} minimize (or maximize) $$z=c^Tx_S+c_0\eqno(3.1)$$ \hspace{.5in} subject to linear constraints $$x_R=Ax_S\eqno(3.2)$$ \hspace{.5in} and bounds of variables $$ \begin{array}{l@{\ }c@{\ }l@{\ }c@{\ }l} l_R&\leq&x_R&\leq&u_R\\ l_S&\leq&x_S&\leq&u_S\\ \end{array}\eqno(3.3) $$ where: $x_R=(x_1,\dots,x_m)$ is the vector of auxiliary variables; $x_S=(x_{m+1},\dots,x_{m+n})$ is the vector of structural variables; $z$ is the objective function; $c=(c_1,\dots,c_n)$ is the vector of objective coefficients; $c_0$ is the constant term (``shift'') of the objective function; $A=(a_{11},\dots,a_{mn})$ is the constraint matrix; $l_R=(l_1,\dots,l_m)$ is the vector of lower bounds of auxiliary variables; $u_R=(u_1,\dots,u_m)$ is the vector of upper bounds of auxiliary variables; $l_S=(l_{m+1},\dots,l_{m+n})$ is the vector of lower bounds of structural variables; $u_S=(u_{m+1},\dots,u_{m+n})$ is the vector of upper bounds of structural variables. From the simplex method's standpoint there is no difference between auxiliary and structural variables. This allows combining all these variables into one vector that leads to the following problem statement: \noindent \hspace{.5in} minimize (or maximize) $$z=(0\ |\ c)^Tx+c_0\eqno(3.4)$$ \hspace{.5in} subject to linear constraints $$(I\ |-\!A)x=0\eqno(3.5)$$ \hspace{.5in} and bounds of variables $$l\leq x\leq u\eqno(3.6)$$ where: $x=(x_R\ |\ x_S)$ is the $(m+n)$-vector of (all) variables; $(0\ |\ c)$ is the $(m+n)$-vector of objective coefficients;\footnote{Subvector 0 corresponds to objective coefficients at auxiliary variables.} $(I\ |-\!A)$ is the {\it augmented} constraint $m\times(m+n)$-matrix;\footnote{Note that due to auxiliary variables matrix $(I\ |-\!A)$ contains the unity submatrix and therefore has full rank. This means, in particular, that the system (3.5) has no linearly dependent constraints.} $l=(l_R\ |\ l_S)$ is the $(m+n)$-vector of lower bounds of (all) variables; $u=(u_R\ |\ u_S)$ is the $(m+n)$-vector of upper bounds of (all) variables. By definition an {\it LP basic solution} geometrically is a point in the space of all variables, which is the intersection of hyperplanes corresponding to active constraints\footnote{A constraint is called {\it active} if at a given point it is satisfied as equality, otherwise it is called {\it inactive}.}. The space of all variables has the dimension $m+n$, therefore, to define some basic solution we have to define $m+n$ active constraints. Note that $m$ constraints (3.5) being linearly independent equalities are always active, so remaining $n$ active constraints can be chosen only from bound constraints (3.6). A variable is called {\it non-basic}, if its (lower or upper) bound is active, otherwise it is called {\it basic}. Since, as was said above, exactly $n$ bound constraints must be active, in any basic solution there are always $n$ non-basic variables and $m$ basic variables. (Note that a free variable also can be non-basic. Although such variable has no bounds, we can think it as the difference between two non-negative variables, which both are non-basic in this case.) Now consider how to determine numeric values of all variables for a given basic solution. Let $\Pi$ be an appropriate permutation matrix of the order $(m+n)$. Then we can write: $$\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)= \Pi\left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right)=\Pi x, \eqno(3.7)$$ where $x_B$ is the vector of basic variables, $x_N$ is the vector of non-basic variables, $x=(x_R\ |\ x_S)$ is the vector of all variables in the original order. In this case the system of linear constraints (3.5) can be rewritten as follows: $$(I\ |-\!A)\Pi^T\Pi x=0\ \ \ \Rightarrow\ \ \ (B\ |\ N) \left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)=0,\eqno(3.8)$$ where $$(B\ |\ N)=(I\ |-\!A)\Pi^T.\eqno(3.9)$$ \newpage Matrix $B$ is a square non-singular $m\times m$-matrix, which is composed from columns of the augmented constraint matrix corresponding to basic variables. It is called the {\it basis matrix} or simply the {\it basis}. Matrix $N$ is a rectangular $m\times n$-matrix, which is composed from columns of the augmented constraint matrix corresponding to non-basic variables. From (3.8) it follows that: $$Bx_B+Nx_N=0,\eqno(3.10)$$ therefore, $$x_B=-B^{-1}Nx_N.\eqno(3.11)$$ Thus, the formula (3.11) shows how to determine numeric values of basic variables $x_B$ assuming that non-basic variables $x_N$ are fixed on their active bounds. The $m\times n$-matrix $$\Xi=-B^{-1}N,\eqno(3.12)$$ which appears in (3.11), is called the {\it simplex tableau}.\footnote{This definition corresponds to the GLPK implementation.} It shows how basic variables depend on non-basic variables: $$x_B=\Xi x_N.\eqno(3.13)$$ The system (3.13) is equivalent to the system (3.5) in the sense that they both define the same set of points in the space of (primal) variables, which satisfy to these systems. If, moreover, values of all basic variables satisfy to their bound constraints (3.3), the corresponding basic solution is called {\it (primal) feasible}, otherwise {\it (primal) infeasible}. It is understood that any (primal) feasible basic solution satisfy to all constraints (3.2) and (3.3). The LP theory says that if LP has optimal solution, it has (at least one) basic feasible solution, which corresponds to the optimum. And the most natural way to determine whether a given basic solution is optimal or not is to use the Karush---Kuhn---Tucker optimality conditions. \def\arraystretch{1.5} For the problem statement (3.4)---(3.6) the optimality conditions are the following:\footnote{These conditions can be appiled to any solution, not only to a basic solution.} $$(I\ |-\!A)x=0\eqno(3.14)$$ $$(I\ |-\!A)^T\pi+\lambda_l+\lambda_u=\nabla z=(0\ |\ c)^T\eqno(3.15)$$ $$l\leq x\leq u\eqno(3.16)$$ $$\lambda_l\geq 0,\ \ \lambda_u\leq 0\ \ \mbox{(minimization)} \eqno(3.17)$$ $$\lambda_l\leq 0,\ \ \lambda_u\geq 0\ \ \mbox{(maximization)} \eqno(3.18)$$ $$(\lambda_l)_k(x_k-l_k)=0,\ \ (\lambda_u)_k(x_k-u_k)=0,\ \ k=1,2,\dots, m+n\eqno(3.19)$$ where: $\pi=(\pi_1,\pi_2,\dots,\pi_m)$ is a $m$-vector of Lagrange multipliers for equality constraints (3.5); $\lambda_l=[(\lambda_l)_1,(\lambda_l)_2,\dots,(\lambda_l)_n]$ is a $n$-vector of Lagrange multipliers for lower bound constraints (3.6); $\lambda_u=[(\lambda_u)_1,(\lambda_u)_2,\dots,(\lambda_u)_n]$ is a $n$-vector of Lagrange multipliers for upper bound constraints (3.6). \newpage Condition (3.14) is the {\it primal} (original) system of equality constraints (3.5). Condition (3.15) is the {\it dual} system of equality constraints. It requires the gradient of the objective function to be a linear combination of normals to the planes defined by constraints of the original problem. Condition (3.16) is the primal (original) system of bound constraints (3.6). Condition (3.17) (or (3.18) in case of maximization) is the dual system of bound constraints. Condition (3.19) is the {\it complementary slackness condition}. It requires, for each original (auxiliary or structural) variable $x_k$, that either its (lower or upper) bound must be active, or zero bound of the corresponding Lagrange multiplier ($(\lambda_l)_k$ or $(\lambda_u)_k$) must be active. In GLPK two multipliers $(\lambda_l)_k$ and $(\lambda_u)_k$ for each primal (original) variable $x_k$, $k=1,2,\dots,\linebreak m+n$, are combined into one multiplier: $$\lambda_k=(\lambda_l)_k+(\lambda_u)_k,\eqno(3.20)$$ which is called a {\it dual variable} for $x_k$. This {\it cannot} lead to the ambiguity, because both lower and upper bounds of $x_k$ cannot be active at the same time,\footnote{If $x_k$ is a fixed variable, we can think it as double-bounded variable $l_k\leq x_k\leq u_k$, where $l_k=u_k.$} so at least one of $(\lambda_l)_k$ and $(\lambda_u)_k$ must be equal to zero, and because these multipliers have different signs, the combined multiplier, which is their sum, uniquely defines each of them. \def\arraystretch{1} Using dual variables $\lambda_k$ the dual system of bound constraints (3.17) and (3.18) can be written in the form of so called {\it ``rule of signs''} as follows: \medskip \begin{center} \begin{tabular}{|@{\,}c@{$\,$}|@{$\,$}c@{$\,$}|@{$\,$}c@{$\,$}| @{$\,$}c|c@{$\,$}|@{$\,$}c@{$\,$}|@{$\,$}c@{$\,$}|} \hline Original bound&\multicolumn{3}{c|}{Minimization}&\multicolumn{3}{c|} {Maximization}\\ \cline{2-7} constraint&$(\lambda_l)_k$&$(\lambda_u)_k$&$(\lambda_l)_k+ (\lambda_u)_k$&$(\lambda_l)_k$&$(\lambda_u)_k$&$(\lambda_l)_k+ (\lambda_u)_k$\\ \hline $-\infty= {\tt piv\_tol}\cdot\max|u_{i*}|$, i.e. if it is not very small in the magnitude among other elements in the same row. Decreasing this parameter may lead to better sparsity at the expense of numerical accuracy, and vice versa. \medskip {\tt int piv\_lim} (default: {\tt 4}) This parameter is used on computing $LU$-factorization of the basis matrix and specifies how many pivot candidates needs to be considered on choosing a pivot element, \verb|piv_lim| $\geq$ 1. If \verb|piv_lim| candidates have been considered, the pivoting routine prematurely terminates the search with the best candidate found. \newpage {\tt int suhl} (default: {\tt GLP\_ON}) This parameter is used on computing $LU$-factorization of the basis matrix. Being set to {\tt GLP\_ON} it enables applying the following heuristic proposed by Uwe Suhl: if a column of the active submatrix has no eligible pivot candidates, it is no more considered until it becomes a column singleton. In many cases this allows reducing the time needed for pivot searching. To disable this heuristic the parameter \verb|suhl| should be set to {\tt GLP\_OFF}. \medskip {\tt double eps\_tol} (default: {\tt 1e-15}) Epsilon tolerance, \verb|eps_tol| $\geq$ 0, used on computing $LU$-factorization of the basis matrix. If an element of the active submatrix of factor $U$ is less than \verb|eps_tol| in the magnitude, it is replaced by exact zero. \medskip {\tt double max\_gro} (default: {\tt 1e+10}) Maximal growth of elements of factor $U$, \verb|max_gro| $\geq$ 1, allowable on computing $LU$-factorization of the basis matrix. If on some elimination step the ratio $u_{big}/b_{max}$ (where $u_{big}$ is the largest magnitude of elements of factor $U$ appeared in its active submatrix during all the factorization process, $b_{max}$ is the largest magnitude of elements of the basis matrix to be factorized), the basis matrix is considered as ill-conditioned. \medskip {\tt int nfs\_max} (default: {\tt 100}) Maximal number of additional row-like factors (entries of the eta file), \verb|nfs_max| $\geq$ 1, which can be added to $LU$-factorization of the basis matrix on updating it with the Forrest--Tomlin technique. This parameter is used only once, before $LU$-factorization is computed for the first time, to allocate working arrays. As a rule, each update adds one new factor (however, some updates may need no addition), so this parameter limits the number of updates between refactorizations. \medskip {\tt double upd\_tol} (default: {\tt 1e-6}) Update tolerance, 0 $<$ \verb|upd_tol| $<$ 1, used on updating $LU$-factorization of the basis matrix with the Forrest--Tomlin technique. If after updating the magnitude of some diagonal element $u_{kk}$ of factor $U$ becomes less than ${\tt upd\_tol}\cdot\max(|u_{k*}|, |u_{*k}|)$, the factorization is considered as inaccurate. \medskip {\tt int nrs\_max} (default: {\tt 100}) Maximal number of additional rows and columns, \verb|nrs_max| $\geq$ 1, which can be added to $LU$-factorization of the basis matrix on updating it with the Schur complement technique. This parameter is used only once, before $LU$-factorization is computed for the first time, to allocate working arrays. As a rule, each update adds one new row and column (however, some updates may need no addition), so this parameter limits the number of updates between refactorizations. \medskip {\tt int rs\_size} (default: {\tt 0}) The initial size of the Sparse Vector Area, in non-zeros, used to store non-zero elements of additional rows and columns introduced on updating $LU$-factorization of the basis matrix with the Schur complement technique. If this parameter is set to 0, the initial SVA size is determined automatically. \newpage \subsection{glp\_get\_bhead --- retrieve the basis header information} \synopsis \begin{verbatim} int glp_get_bhead(glp_prob *P, int k); \end{verbatim} \description The routine \verb|glp_get_bhead| returns the basis header information for the current basis associated with the specified problem object. \returns If basic variable $(x_B)_k$, $1\leq k\leq m$, is $i$-th auxiliary variable ($1\leq i\leq m$), the routine returns $i$. Otherwise, if $(x_B)_k$ is $j$-th structural variable ($1\leq j\leq n$), the routine returns $m+j$. Here $m$ is the number of rows and $n$ is the number of columns in the problem object. \para{Comments} Sometimes the application program may need to know which original (auxiliary and structural) variable correspond to a given basic variable, or, that is the same, which column of the augmented constraint matrix $(I\ |-\!A)$ correspond to a given column of the basis matrix $B$. \def\arraystretch{1} The correspondence is defined as follows:\footnote{For more details see Subsection \ref{basbgd}, page \pageref{basbgd}.} $$\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right)= \Pi\left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right) \ \ \Leftrightarrow \ \ \left(\begin{array}{@{}c@{}}x_R\\x_S\\\end{array}\right)= \Pi^T\left(\begin{array}{@{}c@{}}x_B\\x_N\\\end{array}\right),$$ where $x_B$ is the vector of basic variables, $x_N$ is the vector of non-basic variables, $x_R$ is the vector of auxiliary variables following in their original order,\footnote{The original order of auxiliary and structural variables is defined by the ordinal numbers of corresponding rows and columns in the problem object.} $x_S$ is the vector of structural variables following in their original order, $\Pi$ is a permutation matrix (which is a component of the basis factorization). Thus, if $(x_B)_k=(x_R)_i$ is $i$-th auxiliary variable, the routine returns $i$, and if $(x_B)_k=(x_S)_j$ is $j$-th structural variable, the routine returns $m+j$, where $m$ is the number of rows in the problem object. \subsection{glp\_get\_row\_bind --- retrieve row index in the basis header} \synopsis \begin{verbatim} int glp_get_row_bind(glp_prob *P, int i); \end{verbatim} \returns The routine \verb|glp_get_row_bind| returns the index $k$ of basic variable $(x_B)_k$, $1\leq k\leq m$, which is $i$-th auxiliary variable (that is, the auxiliary variable corresponding to $i$-th row), $1\leq i\leq m$, in the current basis associated with the specified problem object, where $m$ is the number of rows. However, if $i$-th auxiliary variable is non-basic, the routine returns zero. \newpage \para{Comments} The routine \verb|glp_get_row_bind| is an inversion of the routine \verb|glp_get_bhead|; that is, if \linebreak \verb|glp_get_bhead|$(P,k)$ returns $i$, \verb|glp_get_row_bind|$(P,i)$ returns $k$, and vice versa. \subsection{glp\_get\_col\_bind --- retrieve column index in the basis header} \synopsis \begin{verbatim} int glp_get_col_bind(glp_prob *P, int j); \end{verbatim} \returns The routine \verb|glp_get_col_bind| returns the index $k$ of basic variable $(x_B)_k$, $1\leq k\leq m$, which is $j$-th structural variable (that is, the structural variable corresponding to $j$-th column), $1\leq j\leq n$, in the current basis associated with the specified problem object, where $m$ is the number of rows, $n$ is the number of columns. However, if $j$-th structural variable is non-basic, the routine returns zero. \para{Comments} The routine \verb|glp_get_col_bind| is an inversion of the routine \verb|glp_get_bhead|; that is, if \linebreak \verb|glp_get_bhead|$(P,k)$ returns $m+j$, \verb|glp_get_col_bind|$(P,j)$ returns $k$, and vice versa. \subsection{glp\_ftran --- perform forward transformation} \synopsis \begin{verbatim} void glp_ftran(glp_prob *P, double x[]); \end{verbatim} \description The routine \verb|glp_ftran| performs forward transformation (FTRAN), i.e. it solves the system $Bx=b$, where $B$ is the basis matrix associated with the specified problem object, $x$ is the vector of unknowns to be computed, $b$ is the vector of right-hand sides. On entry to the routine elements of the vector $b$ should be stored in locations \verb|x[1]|, \dots, \verb|x[m]|, where $m$ is the number of rows. On exit the routine stores elements of the vector $x$ in the same locations. \subsection{glp\_btran --- perform backward transformation} \synopsis \begin{verbatim} void glp_btran(glp_prob *P, double x[]); \end{verbatim} \description The routine \verb|glp_btran| performs backward transformation (BTRAN), i.e. it solves the system $B^Tx=b$, where $B^T$ is a matrix transposed to the basis matrix $B$ associated with the specified problem object, $x$ is the vector of unknowns to be computed, $b$ is the vector of right-hand sides. \newpage On entry to the routine elements of the vector $b$ should be stored in locations \verb|x[1]|, \dots, \verb|x[m]|, where $m$ is the number of rows. On exit the routine stores elements of the vector $x$ in the same locations. \subsection{glp\_warm\_up --- ``warm up'' LP basis} \synopsis \begin{verbatim} int glp_warm_up(glp_prob *P); \end{verbatim} \description The routine \verb|glp_warm_up| ``warms up'' the LP basis for the specified problem object using current statuses assigned to rows and columns (that is, to auxiliary and structural variables). This operation includes computing factorization of the basis matrix (if it does not exist), computing primal and dual components of basic solution, and determining the solution status. \returns \begin{retlist} 0 & The operation has been successfully performed.\\ \verb|GLP_EBADB| & The basis matrix is invalid, because the number of basic (auxiliary and structural) variables is not the same as the number of rows in the problem object.\\ \verb|GLP_ESING| & The basis matrix is singular within the working precision.\\ \verb|GLP_ECOND| & The basis matrix is ill-conditioned, i.e. its condition number is too large.\\ \end{retlist} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Simplex tableau routines} \subsection{glp\_eval\_tab\_row --- compute row of the tableau} \synopsis \begin{verbatim} int glp_eval_tab_row(glp_prob *P, int k, int ind[], double val[]); \end{verbatim} \description The routine \verb|glp_eval_tab_row| computes a row of the current simplex tableau (see Subsection 3.1.1, formula (3.12)), which (row) corresponds to some basic variable specified by the parameter $k$ as follows: if $1\leq k\leq m$, the basic variable is $k$-th auxiliary variable, and if $m+1\leq k\leq m+n$, the basic variable is $(k-m)$-th structural variable, where $m$ is the number of rows and $n$ is the number of columns in the specified problem object. The basis factorization must exist. The computed row shows how the specified basic variable depends on non-basic variables: $$x_k=(x_B)_i=\xi_{i1}(x_N)_1+\xi_{i2}(x_N)_2+\dots+\xi_{in}(x_N)_n,$$ where $\xi_{i1}$, $\xi_{i2}$, \dots, $\xi_{in}$ are elements of the simplex table row, $(x_N)_1$, $(x_N)_2$, \dots, $(x_N)_n$ are non-basic (auxiliary and structural) variables. The routine stores column indices and corresponding numeric values of non-zero elements of the computed row in unordered sparse format in locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq n$ is the number of non-zero elements in the row returned on exit. Element indices stored in the array \verb|ind| have the same sense as index $k$, i.e. indices 1 to $m$ denote auxiliary variables while indices $m+1$ to $m+n$ denote structural variables (all these variables are obviously non-basic by definition). \returns The routine \verb|glp_eval_tab_row| returns \verb|len|, which is the number of non-zero elements in the simplex table row stored in the arrays \verb|ind| and \verb|val|. \para{Comments} A row of the simplex table is computed as follows. At first, the routine checks that the specified variable $x_k$ is basic and uses the permutation matrix $\Pi$ (3.7) to determine index $i$ of basic variable $(x_B)_i$, which corresponds to $x_k$. The row to be computed is $i$-th row of the matrix $\Xi$ (3.12), therefore: $$\xi_i=e_i^T\Xi=-e_i^TB^{-1}N=-(B^{-T}e_i)^TN,$$ where $e_i$ is $i$-th unity vector. So the routine performs BTRAN to obtain $i$-th row of the inverse $B^{-1}$: $$\varrho_i=B^{-T}e_i,$$ and then computes elements of the simplex table row as inner products: $$\xi_{ij}=-\varrho_i^TN_j,\ \ j=1,2,\dots,n,$$ where $N_j$ is $j$-th column of matrix $N$ (3.9), which (column) corresponds to non-basic variable $(x_N)_j$. The permutation matrix $\Pi$ is used again to convert indices $j$ of non-basic columns to original ordinal numbers of auxiliary and structural variables. \subsection{glp\_eval\_tab\_col --- compute column of the tableau} \synopsis \begin{verbatim} int glp_eval_tab_col(glp_prob *P, int k, int ind[], double val[]); \end{verbatim} \description The routine \verb|glp_eval_tab_col| computes a column of the current simplex tableau (see Subsection 3.1.1, formula (3.12)), which (column) corresponds to some non-basic variable specified by the parameter $k$: if $1\leq k\leq m$, the non-basic variable is $k$-th auxiliary variable, and if $m+1\leq k\leq m+n$, the non-basic variable is $(k-m)$-th structural variable, where $m$ is the number of rows and $n$ is the number of columns in the specified problem object. The basis factorization must exist. The computed column shows how basic variables depends on the specified non-basic variable $x_k=(x_N)_j$: $$ \begin{array}{r@{\ }c@{\ }l@{\ }l} (x_B)_1&=&\dots+\xi_{1j}(x_N)_j&+\dots\\ (x_B)_2&=&\dots+\xi_{2j}(x_N)_j&+\dots\\ .\ \ .&.&.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\\ (x_B)_m&=&\dots+\xi_{mj}(x_N)_j&+\dots\\ \end{array} $$ where $\xi_{1j}$, $\xi_{2j}$, \dots, $\xi_{mj}$ are elements of the simplex table column, $(x_B)_1$, $(x_B)_2$, \dots, $(x_B)_m$ are basic (auxiliary and structural) variables. The routine stores row indices and corresponding numeric values of non-zero elements of the computed column in unordered sparse format in locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, respectively, where $0\leq{\tt len}\leq m$ is the number of non-zero elements in the column returned on exit. Element indices stored in the array \verb|ind| have the same sense as index $k$, i.e. indices 1 to $m$ denote auxiliary variables while indices $m+1$ to $m+n$ denote structural variables (all these variables are obviously basic by definition). \returns The routine \verb|glp_eval_tab_col| returns \verb|len|, which is the number of non-zero elements in the simplex table column stored in the arrays \verb|ind| and \verb|val|. \para{Comments} A column of the simplex table is computed as follows. At first, the routine checks that the specified variable $x_k$ is non-basic and uses the permutation matrix $\Pi$ (3.7) to determine index $j$ of non-basic variable $(x_N)_j$, which corresponds to $x_k$. The column to be computed is $j$-th column of the matrix $\Xi$ (3.12), therefore: $$\Xi_j=\Xi e_j=-B^{-1}Ne_j=-B^{-1}N_j,$$ where $e_j$ is $j$-th unity vector, $N_j$ is $j$-th column of matrix $N$ (3.9). So the routine performs FTRAN to transform $N_j$ to the simplex table column $\Xi_j=(\xi_{ij})$ and uses the permutation matrix $\Pi$ to convert row indices $i$ to original ordinal numbers of auxiliary and structural variables. \subsection{glp\_transform\_row --- transform explicitly specified row} \synopsis \begin{verbatim} int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); \end{verbatim} \description The routine \verb|glp_transform_row| performs the same operation as the routine \verb|glp_eval_tab_row| with exception that the row to be transformed is specified explicitly as a sparse vector. The explicitly specified row may be thought as a linear form: $$x=a_1x_{m+1}+a_2x_{m+2}+\dots+a_nx_{m+n},$$ where $x$ is an auxiliary variable for this row, $a_j$ are coefficients of the linear form, $x_{m+j}$ are structural variables. On entry column indices and numerical values of non-zero coefficients $a_j$ of the specified row should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, where \verb|len| is number of non-zero coefficients. This routine uses the system of equality constraints and the current basis in order to express the auxiliary variable $x$ through the current non-basic variables (as if the transformed row were added to the problem object and the auxiliary variable $x$ were basic), i.e. the resultant row has the form: $$x=\xi_1(x_N)_1+\xi_2(x_N)_2+\dots+\xi_n(x_N)_n,$$ where $\xi_j$ are influence coefficients, $(x_N)_j$ are non-basic (auxiliary and structural) variables, $n$ is the number of columns in the problem object. On exit the routine stores indices and numerical values of non-zero coefficients $\xi_j$ of the resultant row in locations \verb|ind[1]|, \dots, \verb|ind[len']| and \verb|val[1]|, \dots, \verb|val[len']|, where $0\leq{\tt len'}\leq n$ is the number of non-zero coefficients in the resultant row returned by the routine. Note that indices of non-basic variables stored in the array \verb|ind| correspond to original ordinal numbers of variables: indices 1 to $m$ mean auxiliary variables and indices $m+1$ to $m+n$ mean structural ones. \returns The routine \verb|glp_transform_row| returns \verb|len'|, the number of non-zero coefficients in the resultant row stored in the arrays \verb|ind| and \verb|val|. \newpage \subsection{glp\_transform\_col --- transform explicitly specified column} \synopsis \begin{verbatim} int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); \end{verbatim} \description The routine \verb|glp_transform_col| performs the same operation as the routine \verb|glp_eval_tab_col| with exception that the column to be transformed is specified explicitly as a sparse vector. The explicitly specified column may be thought as it were added to the original system of equality constraints: $$ \begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} x_1&=&a_{11}x_{m+1}&+\dots+&a_{1n}x_{m+n}&+&a_1x \\ x_2&=&a_{21}x_{m+1}&+\dots+&a_{2n}x_{m+n}&+&a_2x \\ \multicolumn{7}{c} {.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ x_m&=&a_{m1}x_{m+1}&+\dots+&a_{mn}x_{m+n}&+&a_mx \\ \end{array} $$ where $x_i$ are auxiliary variables, $x_{m+j}$ are structural variables (presented in the problem object), $x$ is a structural variable for the explicitly specified column, $a_i$ are constraint coefficients at $x$. On entry row indices and numerical values of non-zero coefficients $a_i$ of the specified column should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, where \verb|len| is number of non-zero coefficients. This routine uses the system of equality constraints and the current basis in order to express the current basic variables through the structural variable $x$ (as if the transformed column were added to the problem object and the variable $x$ were non-basic): $$ \begin{array}{l@{\ }c@{\ }r} (x_B)_1&=\dots+&\xi_{1}x\\ (x_B)_2&=\dots+&\xi_{2}x\\ \multicolumn{3}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .}\\ (x_B)_m&=\dots+&\xi_{m}x\\ \end{array} $$ where $\xi_i$ are influence coefficients, $x_B$ are basic (auxiliary and structural) variables, $m$ is the number of rows in the problem object. On exit the routine stores indices and numerical values of non-zero coefficients $\xi_i$ of the resultant column in locations \verb|ind[1]|, \dots, \verb|ind[len']| and \verb|val[1]|, \dots, \verb|val[len']|, where $0\leq{\tt len'}\leq m$ is the number of non-zero coefficients in the resultant column returned by the routine. Note that indices of basic variables stored in the array \verb|ind| correspond to original ordinal numbers of variables, i.e. indices 1 to $m$ mean auxiliary variables, indices $m+1$ to $m+n$ mean structural ones. \returns The routine \verb|glp_transform_col| returns \verb|len'|, the number of non-zero coefficients in the resultant column stored in the arrays \verb|ind| and \verb|val|. \newpage \subsection{glp\_prim\_rtest --- perform primal ratio test} \synopsis \begin{verbatim} int glp_prim_rtest(glp_prob *P, int len, const int ind[], const double val[], int dir, double eps); \end{verbatim} \description The routine \verb|glp_prim_rtest| performs the primal ratio test using an explicitly specified column of the simplex table. The current basic solution associated with the LP problem object must be primal feasible. The explicitly specified column of the simplex table shows how the basic variables $x_B$ depend on some non-basic variable $x$ (which is not necessarily presented in the problem object): $$ \begin{array}{l@{\ }c@{\ }r} (x_B)_1&=\dots+&\xi_{1}x\\ (x_B)_2&=\dots+&\xi_{2}x\\ \multicolumn{3}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .}\\ (x_B)_m&=\dots+&\xi_{m}x\\ \end{array} $$ The column is specifed on entry to the routine in sparse format. Ordinal numbers of basic variables $(x_B)_i$ should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]|, where ordinal number 1 to $m$ denote auxiliary variables, and ordinal numbers $m+1$ to $m+n$ denote structural variables. The corresponding non-zero coefficients $\xi_i$ should be placed in locations \verb|val[1]|, \dots, \verb|val[len]|. The arrays \verb|ind| and \verb|val| are not changed by the routine. The parameter \verb|dir| specifies direction in which the variable $x$ changes on entering the basis: $+1$ means increasing, $-1$ means decreasing. The parameter \verb|eps| is an absolute tolerance (small positive number, say, $10^{-9}$) used by the routine to skip $\xi_i$'s whose magnitude is less than \verb|eps|. The routine determines which basic variable (among those specified in \verb|ind[1]|, \dots, \verb|ind[len]|) reaches its (lower or upper) bound first before any other basic variables do, and which, therefore, should leave the basis in order to keep primal feasibility. \returns The routine \verb|glp_prim_rtest| returns the index, \verb|piv|, in the arrays \verb|ind| and \verb|val| corresponding to the pivot element chosen, $1\leq$ \verb|piv| $\leq$ \verb|len|. If the adjacent basic solution is primal unbounded, and therefore the choice cannot be made, the routine returns zero. \para{Comments} If the non-basic variable $x$ is presented in the LP problem object, the input column can be computed with the routine \verb|glp_eval_tab_col|; otherwise, it can be computed with the routine \verb|glp_transform_col|. \newpage \subsection{glp\_dual\_rtest --- perform dual ratio test} \synopsis \begin{verbatim} int glp_dual_rtest(glp_prob *P, int len, const int ind[], const double val[], int dir, double eps); \end{verbatim} \description The routine \verb|glp_dual_rtest| performs the dual ratio test using an explicitly specified row of the simplex table. The current basic solution associated with the LP problem object must be dual feasible. The explicitly specified row of the simplex table is a linear form that shows how some basic variable $x$ (which is not necessarily presented in the problem object) depends on non-basic variables $x_N$: $$x=\xi_1(x_N)_1+\xi_2(x_N)_2+\dots+\xi_n(x_N)_n.$$ The row is specified on entry to the routine in sparse format. Ordinal numbers of non-basic variables $(x_N)_j$ should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]|, where ordinal numbers 1 to $m$ denote auxiliary variables, and ordinal numbers $m+1$ to $m+n$ denote structural variables. The corresponding non-zero coefficients $\xi_j$ should be placed in locations \verb|val[1]|, \dots, \verb|val[len]|. The arrays \verb|ind| and \verb|val| are not changed by the routine. The parameter \verb|dir| specifies direction in which the variable $x$ changes on leaving the basis: $+1$ means that $x$ goes on its lower bound, so its reduced cost (dual variable) is increasing (minimization) or decreasing (maximization); $-1$ means that $x$ goes on its upper bound, so its reduced cost is decreasing (minimization) or increasing (maximization). The parameter \verb|eps| is an absolute tolerance (small positive number, say, $10^{-9}$) used by the routine to skip $\xi_j$'s whose magnitude is less than \verb|eps|. The routine determines which non-basic variable (among those specified in \verb|ind[1]|, \dots,\linebreak \verb|ind[len]|) should enter the basis in order to keep dual feasibility, because its reduced cost reaches the (zero) bound first before this occurs for any other non-basic variables. \returns The routine \verb|glp_dual_rtest| returns the index, \verb|piv|, in the arrays \verb|ind| and \verb|val| corresponding to the pivot element chosen, $1\leq$ \verb|piv| $\leq$ \verb|len|. If the adjacent basic solution is dual unbounded, and therefore the choice cannot be made, the routine returns zero. \para{Comments} If the basic variable $x$ is presented in the LP problem object, the input row can be computed\linebreak with the routine \verb|glp_eval_tab_row|; otherwise, it can be computed with the routine \linebreak \verb|glp_transform_row|. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Post-optimal analysis routines} \subsection{glp\_analyze\_bound --- analyze active bound of non-basic variable} \synopsis \begin{verbatim} void glp_analyze_bound(glp_prob *P, int k, double *limit1, int *var1, double *limit2, int *var2); \end{verbatim} \description The routine \verb|glp_analyze_bound| analyzes the effect of varying the active bound of specified non-basic variable. The non-basic variable is specified by the parameter $k$, where $1\leq k\leq m$ means auxiliary variable of corresponding row, and $m+1\leq k\leq m+n$ means structural variable (column). Note that the current basic solution must be optimal, and the basis factorization must exist. Results of the analysis have the following meaning. \verb|value1| is the minimal value of the active bound, at which the basis still remains primal feasible and thus optimal. \verb|-DBL_MAX| means that the active bound has no lower limit. \verb|var1| is the ordinal number of an auxiliary (1 to $m$) or structural ($m+1$ to $m+n$) basic variable, which reaches its bound first and thereby limits further decreasing the active bound being analyzed. if \verb|value1| = \verb|-DBL_MAX|, \verb|var1| is set to 0. \verb|value2| is the maximal value of the active bound, at which the basis still remains primal feasible and thus optimal. \verb|+DBL_MAX| means that the active bound has no upper limit. \verb|var2| is the ordinal number of an auxiliary (1 to $m$) or structural ($m+1$ to $m+n$) basic variable, which reaches its bound first and thereby limits further increasing the active bound being analyzed. if \verb|value2| = \verb|+DBL_MAX|, \verb|var2| is set to 0. The parameters \verb|value1|, \verb|var1|, \verb|value2|, \verb|var2| can be specified as \verb|NULL|, in which case corresponding information is not stored. \subsection{glp\_analyze\_coef --- analyze objective coefficient at basic variable} \synopsis \begin{verbatim} void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, double *value1, double *coef2, int *var2, double *value2); \end{verbatim} \description The routine \verb|glp_analyze_coef| analyzes the effect of varying the objective coefficient at specified basic variable. The basic variable is specified by the parameter $k$, where $1\leq k\leq m$ means auxiliary variable of corresponding row, and $m+1\leq k\leq m+n$ means structural variable (column). Note that the current basic solution must be optimal, and the basis factorization must exist. Results of the analysis have the following meaning. \verb|coef1| is the minimal value of the objective coefficient, at which the basis still remains dual feasible and thus optimal. \verb|-DBL_MAX| means that the objective coefficient has no lower limit. \verb|var1| is the ordinal number of an auxiliary (1 to $m$) or structural ($m+1$ to $m+n$) non-basic variable, whose reduced cost reaches its zero bound first and thereby limits further decreasing the objective coefficient being analyzed. If \verb|coef1| = \verb|-DBL_MAX|, \verb|var1| is set to 0. \verb|value1| is value of the basic variable being analyzed in an adjacent basis, which is defined as follows. Let the objective coefficient reach its minimal value (\verb|coef1|) and continue decreasing. Then the reduced cost of the limiting non-basic variable (\verb|var1|) becomes dual infeasible and the current basis becomes non-optimal that forces the limiting non-basic variable to enter the basis replacing there some basic variable that leaves the basis to keep primal feasibility. Should note that on determining the adjacent basis current bounds of the basic variable being analyzed are ignored as if it were free (unbounded) variable, so it cannot leave the basis. It may happen that no dual feasible adjacent basis exists, in which case \verb|value1| is set to \verb|-DBL_MAX| or \verb|+DBL_MAX|. \verb|coef2| is the maximal value of the objective coefficient, at which the basis still remains dual feasible and thus optimal. \verb|+DBL_MAX| means that the objective coefficient has no upper limit. \verb|var2| is the ordinal number of an auxiliary (1 to $m$) or structural ($m+1$ to $m+n$) non-basic variable, whose reduced cost reaches its zero bound first and thereby limits further increasing the objective coefficient being analyzed. If \verb|coef2| = \verb|+DBL_MAX|, \verb|var2| is set to 0. \verb|value2| is value of the basic variable being analyzed in an adjacent basis, which is defined exactly in the same way as \verb|value1| above with exception that now the objective coefficient is increasing. The parameters \verb|coef1|, \verb|var1|, \verb|value1|, \verb|coef2|, \verb|var2|, \verb|value2| can be specified as \verb|NULL|, in which case corresponding information is not stored. %* eof *% glpk-4.52.1/doc/glpk05.tex0000644000062000006210000011240012175147600014310 0ustar maomkpasswd%* glpk05.tex *% \chapter{Branch-and-Cut API Routines} \section{Introduction} \subsection{Using the callback routine} The GLPK MIP solver based on the branch-and-cut method allows the application program to control the solution process. This is attained by means of the user-defined callback routine, which is called by the solver at various points of the branch-and-cut algorithm. The callback routine passed to the MIP solver should be written by the user and has the following specification:\footnote{The name {\tt foo\_bar} used here is a placeholder for the callback routine name.} \begin{verbatim} void foo_bar(glp_tree *T, void *info); \end{verbatim} \noindent where \verb|tree| is a pointer to the data structure \verb|glp_tree|, which should be used on subsequent calls to branch-and-cut interface routines, and \verb|info| is a transit pointer passed to the routine \verb|glp_intopt|, which may be used by the application program to pass some external data to the callback routine. The callback routine is passed to the MIP solver through the control parameter structure \verb|glp_iocp| (see Chapter ``Basic API Routines'', Section ``Mixed integer programming routines'', Subsection ``Solve MIP problem with the branch-and-cut method'') as follows: \begin{verbatim} glp_prob *mip; glp_iocp parm; . . . glp_init_iocp(&parm); . . . parm.cb_func = foo_bar; parm.cb_info = ... ; ret = glp_intopt(mip, &parm); . . . \end{verbatim} To determine why it is being called by the MIP solver the callback routine should use the routine \verb|glp_ios_reason| (described in this section below), which returns a code indicating the reason for calling. Depending on the reason the callback routine may perform necessary actions to control the solution process. The reason codes, which correspond to various point of the branch-and-cut algorithm implemented in the MIP solver, are described in Subsection ``Reasons for calling the callback routine'' below. To ignore calls for reasons, which are not processed by the callback routine, it should simply return to the MIP solver doing nothing. For example: \begin{verbatim} void foo_bar(glp_tree *T, void *info) { . . . switch (glp_ios_reason(T)) { case GLP_IBRANCH: . . . break; case GLP_ISELECT: . . . break; default: /* ignore call for other reasons */ break; } return; } \end{verbatim} To control the solution process as well as to obtain necessary information the callback routine may use the branch-and-cut API routines described in this chapter. Names of all these routines begin with `\verb|glp_ios_|'. \subsection{Branch-and-cut algorithm} This section gives a schematic description of the branch-and-cut algorithm as it is implemented in the GLPK MIP solver. {\it 1. Initialization} Set $L:=\{P_0\}$, where $L$ is the {\it active list} (i.e. the list of active subproblems), $P_0$ is the original MIP problem to be solved. Set $z^{\it best}:=+\infty$ (in case of minimization) or $z^{\it best}:=-\infty$ (in case of maximization), where $z^{\it best}$ is {\it incumbent value}, i.e. an upper (minimization) or lower (maximization) global bound for $z^{\it opt}$, the optimal objective value for $P^0$. {\it 2. Subproblem selection} If $L=\varnothing$ then GO TO 9. Select $P\in L$, i.e. make active subproblem $P$ current. \newpage {\it 3. Solving LP relaxation} Solve $P^{\it LP}$, which is LP relaxation of $P$. If $P^{\it LP}$ has no primal feasible solution then GO TO 8. Let $z^{\it LP}$ be the optimal objective value for $P^{\it LP}$. If $z^{\it LP}\geq z^{\it best}$ (minimization) or $z^{\it LP}\leq z^{\rm best}$ (), GO TO 8. {\it 4. Adding ``lazy'' constraints} Let $x^{\it LP}$ be the optimal solution to $P^{\it LP}$. If there are ``lazy'' constraints (i.e. essential constraints not included in the original MIP problem $P_0$), which are violated at the optimal point $x^{\it LP}$, add them to $P$, and GO TO 3. {\it 5. Check for integrality} Let $x_j$ be a variable, which is required to be integer, and let $x^{\it LP}_j\in x^{\it LP}$ be its value in the optimal solution to $P^{\it LP}$. If $x^{\it LP}_j$ are integral for all integer variables, then a better integer feasible solution is found. Store its components, set $z^{\it best}:=z^{\it LP}$, and GO TO 8. {\it 6. Adding cutting planes} If there are cutting planes (i.e. valid constraints for $P$), which are violated at the optimal point $x^{\it LP}$, add them to $P$, and GO TO 3. {\it 7. Branching} Select {\it branching variable} $x_j$, i.e. a variable, which is required to be integer, and whose value $x^{\it LP}_j\in x^{\it LP}$ is fractional in the optimal solution to $P^{\it LP}$. Create new subproblem $P^D$ (so called {\it down branch}), which is identical to the current subproblem $P$ with exception that the upper bound of $x_j$ is replaced by $\lfloor x^{\it LP}_j\rfloor$. (For example, if $x^{\it LP}_j=3.14$, the new upper bound of $x_j$ in the down branch will be $\lfloor 3.14\rfloor=3$.) Create new subproblem $P^U$ (so called {\it up branch}), which is identical to the current subproblem $P$ with exception that the lower bound of $x_j$ is replaced by $\lceil x^{\it LP}_j\rceil$. (For example, if $x^{\it LP}_j=3.14$, the new lower bound of $x_j$ in the up branch will be $\lceil 3.14\rceil=4$.) Set $L:=(L\backslash\{P\})\cup\{P^D,P^U\}$, i.e. remove the current subproblem $P$ from the active list $L$ and add two new subproblems $P^D$ and $P^U$ to it. Then GO TO 2. {\it 8. Pruning} Remove from the active list $L$ all subproblems (including the current one), whose local bound $\widetilde{z}$ is not better than the global bound $z^{\it best}$, i.e. set $L:=L\backslash\{P\}$ for all $P$, where $\widetilde{z}\geq z^{\it best}$ (in case of minimization) or $\widetilde{z}\leq z^{\it best}$ (in case of maximization), and then GO TO 2. The local bound $\widetilde{z}$ for subproblem $P$ is an lower (minimization) or upper (maximization) bound for integer optimal solution to {\it this} subproblem (not to the original problem). This bound is local in the sense that only subproblems in the subtree rooted at node $P$ cannot have better integer feasible solutions. Note that the local bound is not necessarily the optimal objective value to LP relaxation $P^{\it LP}$. {\it 9. Termination} If $z^{\it best}=+\infty$ (in case of minimization) or $z^{\it best}=-\infty$ (in case of maximization), the original problem $P_0$ has no integer feasible solution. Otherwise, the last integer feasible solution stored on step 5 is the integer optimal solution to the original problem $P_0$ with $z^{\it opt}=z^{\it best}$. STOP. \subsection{The search tree} On the branching step of the branch-and-cut algorithm the current subproblem is divided into two\footnote{In more general cases the current subproblem may be divided into more than two subproblems. However, currently such feature is not used in GLPK.} new subproblems, so the set of all subproblems can be represented in the form of a rooted tree, which is called the {\it search} or {\it branch-and-bound} tree. An example of the search tree is shown on Fig.~1. Each node of the search tree corresponds to a subproblem, so the terms `node' and `subproblem' may be used synonymously. \begin{figure}[t] \noindent\hfil \xymatrix @R=20pt @C=10pt {&&&&&&*+<14pt>[o][F=]{A}\ar@{-}[dllll]\ar@{-}[dr]\ar@{-}[drrrr]&&&&\\ &&*+<14pt>[o][F=]{B}\ar@{-}[dl]\ar@{-}[dr]&&&&&*+<14pt>[o][F=]{C} \ar@{-}[dll]\ar@{-}[dr]\ar@{-}[drrr]&&&*+<14pt>[o][F-]{\times}\\ &*+<14pt>[o][F-]{\times}\ar@{-}[dl]\ar@{-}[d]\ar@{-}[dr]&& *+<14pt>[o][F-]{D}&&*+<14pt>[o][F=]{E}\ar@{-}[dl]\ar@{-}[dr]&&& *+<14pt>[o][F=]{F}\ar@{-}[dl]\ar@{-}[dr]&&*+<14pt>[o][F-]{G}\\ *+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times}&*+<14pt>[o][F-]{\times} &&*+<14pt>[][F-]{H}&&*+<14pt>[o][F-]{I}&*+<14pt>[o][F-]{\times}&& *+<14pt>[o][F-]{J}&\\} \bigskip \noindent\hspace{.8in} \xymatrix @R=11pt {*+<20pt>[][F-]{}&*\txt{\makebox[1in][l]{Current}}&& *+<20pt>[o][F-]{}&*\txt{\makebox[1in][l]{Active}}\\ *+<20pt>[o][F=]{}&*\txt{\makebox[1in][l]{Non-active}}&& *+<14pt>[o][F-]{\times}&*\txt{\makebox[1in][l]{Fathomed}}\\ } \bigskip \begin{center} Fig. 1. An example of the search tree. \end{center} \end{figure} In GLPK each node may have one of the following four statuses: \vspace*{-8pt} \begin{itemize} \item {\it current node} is the active node currently being processed; \item {\it active node} is a leaf node, which still has to be processed; \item {\it non-active node} is a node, which has been processed, but not fathomed; \item {\it fathomed node} is a node, which has been processed and fathomed. \end{itemize} \vspace*{-8pt} In the data structure representing the search tree GLPK keeps only current, active, and non-active nodes. Once a node has been fathomed, it is removed from the tree data structure. Being created each node of the search tree is assigned a distinct positive integer called the {\it subproblem reference number}, which may be used by the application program to specify a particular node of the tree. The root node corresponding to the original problem to be solved is always assigned the reference number 1. \subsection{Current subproblem} The current subproblem is a MIP problem corresponding to the current node of the search tree. It is represented as the GLPK problem object (\verb|glp_prob|) that allows the application program using API routines to access its content in the standard way. If the MIP presolver is not used, it is the original problem object passed to the routine \verb|glp_intopt|; otherwise, it is an internal problem object built by the MIP presolver. Note that the problem object is used by the MIP solver itself during the solution process for various purposes (to solve LP relaxations, to perfom branching, etc.), and even if the MIP presolver is not used, the current content of the problem object may differ from its original content. For example, it may have additional rows, bounds of some rows and columns may be changed, etc. In particular, LP segment of the problem object corresponds to LP relaxation of the current subproblem. However, on exit from the MIP solver the content of the problem object is restored to its original state. To obtain information from the problem object the application program may use any API routines, which do not change the object. Using API routines, which change the problem object, is restricted to stipulated cases. \subsection{The cut pool} The {\it cut pool} is a set of cutting plane constraints maintained by the MIP solver. It is used by the GLPK cut generation routines and may be used by the application program in the same way, i.e. rather than to add cutting plane constraints directly to the problem object the application program may store them to the cut pool. In the latter case the solver looks through the cut pool, selects efficient constraints, and adds them to the problem object. \subsection{Reasons for calling the callback routine} The callback routine may be called by the MIP solver for the following reasons. \para{Request for subproblem selection} The callback routine is called with the reason code \verb|GLP_ISELECT| if the current subproblem has been fathomed and therefore there is no current subproblem. In response the callback routine may select some subproblem from the active list and pass its reference number to the solver using the routine \verb|glp_ios_select_node|, in which case the solver continues the search from the specified active subproblem. If no selection is made by the callback routine, the solver uses a backtracking technique specified by the control parameter \verb|bt_tech|. To explore the active list (i.e. active nodes of the branch-and-bound tree) the callback routine may use the routines \verb|glp_ios_next_node| and \verb|glp_ios_prev_node|. \para{Request for preprocessing} The callback routine is called with the reason code \verb|GLP_IPREPRO| if the current subproblem has just been selected from the active list and its LP relaxation is not solved yet. In response the callback routine may perform some preprocessing of the current subproblem like tightening bounds of some variables or removing bounds of some redundant constraints. \para{Request for row generation} The callback routine is called with the reason code \verb|GLP_IROWGEN| if LP relaxation of the current subproblem has just been solved to optimality and its objective value is better than the best known integer feasible solution. In response the callback routine may add one or more ``lazy'' constraints (rows), which are violated by the current optimal solution of LP relaxation, using API routines \verb|glp_add_rows|, \verb|glp_set_row_name|, \verb|glp_set_row_bnds|, and \verb|glp_set_mat_row|, in which case the solver will perform re-optimization of LP relaxation. If there are no violated constraints, the callback routine should just return. Note that components of optimal solution to LP relaxation can be obtained with API\linebreak routines \verb|glp_get_obj_val|, \verb|glp_get_row_prim|, \verb|glp_get_row_dual|, \verb|glp_get_col_prim|, and\linebreak \verb|glp_get_col_dual|. \para{Request for heuristic solution} The callback routine is called with the reason code \verb|GLP_IHEUR| if LP relaxation of the current subproblem being solved to optimality is integer infeasible (i.e. values of some structural variables of integer kind are fractional), though its objective value is better than the best known integer feasible solution. In response the callback routine may try applying a primal heuristic to find an integer feasible solution,\footnote{Integer feasible to the original MIP problem, not to the current subproblem.} which is better than the best known one. In case of success the callback routine may store such better solution in the problem object using the routine \verb|glp_ios_heur_sol|. \para{Request for cut generation} The callback routine is called with the reason code \verb|GLP_ICUTGEN| if LP relaxation of the current subproblem being solved to optimality is integer infeasible (i.e. values of some structural variables of integer kind are fractional), though its objective value is better than the best known integer feasible solution. In response the callback routine may reformulate the {\it current} subproblem (before it will be splitted up due to branching) by adding to the problem object one or more {\it cutting plane constraints}, which cut off the fractional optimal point from the MIP polytope.\footnote{Since these constraints are added to the current subproblem, they may be globally as well as locally valid.} Adding cutting plane constraints may be performed in two ways. One way is the same as for the reason code \verb|GLP_IROWGEN| (see above), in which case the callback routine adds new rows corresponding to cutting plane constraints directly to the current subproblem. The other way is to add cutting plane constraints to the {\it cut pool}, a set of cutting plane constraints maintained by the solver, rather than directly to the current subproblem. In this case after return from the callback routine the solver looks through the cut pool, selects efficient cutting plane constraints, adds them to the current subproblem, drops other constraints, and then performs re-optimization. \para{Request for branching} The callback routine is called with the reason code \verb|GLP_IBRANCH| if LP relaxation of the current subproblem being solved to optimality is integer infeasible (i.e. values of some structural variables of integer kind are fractional), though its objective value is better than the best known integer feasible solution. In response the callback routine may choose some variable suitable for branching (i.e. integer variable, whose value in optimal solution to LP relaxation of the current subproblem is fractional) and pass its ordinal number to the solver using the routine \verb|glp_ios_branch_upon|, in which case the solver splits the current subproblem in two new subproblems and continues the search. If no choice is made by the callback routine, the solver uses a branching technique specified by the control parameter \verb|br_tech|. \para{Better integer solution found} The callback routine is called with the reason code \verb|GLP_IBINGO| if LP relaxation of the current subproblem being solved to optimality is integer feasible (i.e. values of all structural variables of integer kind are integral within the working precision) and its objective value is better than the best known integer feasible solution. Optimal solution components for LP relaxation can be obtained in the same way as for the reason code \verb|GLP_IROWGEN| (see above). Components of the new MIP solution can be obtained with API routines \verb|glp_mip_obj_val|, \verb|glp_mip_row_val|, and \verb|glp_mip_col_val|. Note, however, that due to row/cut generation there may be additional rows in the problem object. The difference between optimal solution to LP relaxation and corresponding MIP solution is that in the former case some structural variables of integer kind (namely, basic variables) may have values, which are close to nearest integers within the working precision, while in the latter case all such variables have exact integral values. The reason \verb|GLP_IBINGO| is intended only for informational purposes, so the callback routine should not modify the problem object in this case. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Basic routines} \subsection{glp\_ios\_reason --- determine reason for calling the callback routine} \synopsis \begin{verbatim} int glp_ios_reason(glp_tree *T); \end{verbatim} \returns The routine \verb|glp_ios_reason| returns a code, which indicates why the user-defined callback routine is being called: \verb|GLP_ISELECT| --- request for subproblem selection; \verb|GLP_IPREPRO| --- request for preprocessing; \verb|GLP_IROWGEN| --- request for row generation; \verb|GLP_IHEUR | --- request for heuristic solution; \verb|GLP_ICUTGEN| --- request for cut generation; \verb|GLP_IBRANCH| --- request for branching; \verb|GLP_IBINGO | --- better integer solution found. \subsection{glp\_ios\_get\_prob --- access the problem object} \synopsis \begin{verbatim} glp_prob *glp_ios_get_prob(glp_tree *T); \end{verbatim} \description The routine \verb|glp_ios_get_prob| can be called from the user-defined callback routine to access the problem object, which is used by the MIP solver. It is the original problem object passed to the routine \verb|glp_intopt| if the MIP presolver is not used; otherwise it is an internal problem object built by the presolver. \returns The routine \verb|glp_ios_get_prob| returns a pointer to the problem object used by the MIP solver. \para{Comments} To obtain various information about the problem instance the callback routine can access the problem object (i.e. the object of type \verb|glp_prob|) using the routine \verb|glp_ios_get_prob|. It is the original problem object passed to the routine \verb|glp_intopt| if the MIP presolver is not used; otherwise it is an internal problem object built by the presolver. \newpage \subsection{glp\_ios\_row\_attr --- determine additional row attributes} \synopsis \begin{verbatim} void glp_ios_row_attr(glp_tree *T, int i, glp_attr *attr); \end{verbatim} \description The routine \verb|glp_ios_row_attr| retrieves additional attributes of $i$-th row of the current subproblem and stores them in the structure \verb|glp_attr|, which the parameter \verb|attr| points to. The structure \verb|glp_attr| has the following fields: \medskip {\tt int level} Subproblem level at which the row was created. (If \verb|level| = 0, the row was added either to the original problem object passed to the routine \verb|glp_intopt| or to the root subproblem on generating ``lazy'' or/and cutting plane constraints.) \medskip {\tt int origin} The row origin flag: \verb|GLP_RF_REG | --- regular constraint; \verb|GLP_RF_LAZY| --- ``lazy'' constraint; \verb|GLP_RF_CUT | --- cutting plane constraint. \medskip {\tt int klass} The row class descriptor, which is a number passed to the routine \verb|glp_ios_add_row| as its third parameter. If the row is a cutting plane constraint generated by the solver, its class may be the following: \verb|GLP_RF_GMI | --- Gomory's mixed integer cut; \verb|GLP_RF_MIR | --- mixed integer rounding cut; \verb|GLP_RF_COV | --- mixed cover cut; \verb|GLP_RF_CLQ | --- clique cut. \subsection{glp\_ios\_mip\_gap --- compute relative MIP gap} \synopsis \begin{verbatim} double glp_ios_mip_gap(glp_tree *T); \end{verbatim} \description The routine \verb|glp_ios_mip_gap| computes the relative MIP gap (also called {\it duality gap}) with the following formula: $${\tt gap} = \frac{|{\tt best\_mip} - {\tt best\_bnd}|} {|{\tt best\_mip}| + {\tt DBL\_EPSILON}}$$ where \verb|best_mip| is the best integer feasible solution found so far, \verb|best_bnd| is the best (global) bound. If no integer feasible solution has been found yet, \verb|gap| is set to \verb|DBL_MAX|. \returns The routine \verb|glp_ios_mip_gap| returns the relative MIP gap. \para{Comments} The relative MIP gap is used to measure the quality of the best integer feasible solution found so far, because the optimal solution value $z^*$ for the original MIP problem always lies in the range $${\tt best\_bnd}\leq z^*\leq{\tt best\_mip}$$ in case of minimization, or in the range $${\tt best\_mip}\leq z^*\leq{\tt best\_bnd}$$ in case of maximization. To express the relative MIP gap in percents the value returned by the routine \verb|glp_ios_mip_gap| should be multiplied by 100\%. \subsection{glp\_ios\_node\_data --- access application-specific data} \synopsis \begin{verbatim} void *glp_ios_node_data(glp_tree *T, int p); \end{verbatim} \description The routine \verb|glp_ios_node_data| allows the application accessing a memory block allocated for the subproblem (which may be active or inactive), whose reference number is $p$. The size of the block is defined by the control parameter \verb|cb_size| passed to the routine \verb|glp_intopt|. The block is initialized by binary zeros on creating corresponding subproblem, and its contents is kept until the subproblem will be removed from the tree. The application may use these memory blocks to store specific data for each subproblem. \returns The routine \verb|glp_ios_node_data| returns a pointer to the memory block for the specified subproblem. Note that if \verb|cb_size| = 0, the routine returns a null pointer. \subsection{glp\_ios\_select\_node --- select subproblem to continue the search} \synopsis \begin{verbatim} void glp_ios_select_node(glp_tree *T, int p); \end{verbatim} \description The routine \verb|glp_ios_select_node| can be called from the user-defined callback routine in response to the reason \verb|GLP_ISELECT| to select an active subproblem, whose reference number\linebreak is $p$. The search will be continued from the subproblem selected. \newpage \subsection{glp\_ios\_heur\_sol --- provide solution found by heuristic} \synopsis \begin{verbatim} int glp_ios_heur_sol(glp_tree *T, const double x[]); \end{verbatim} \description The routine \verb|glp_ios_heur_sol| can be called from the user-defined callback routine in response to the reason \verb|GLP_IHEUR| to provide an integer feasible solution found by a primal heuristic. Primal values of {\it all} variables (columns) found by the heuristic should be placed in locations $x[1]$, \dots, $x[n]$, where $n$ is the number of columns in the original problem object. Note that the routine \verb|glp_ios_heur_sol| does {\it not} check primal feasibility of the solution provided. Using the solution passed in the array $x$ the routine computes value of the objective function. If the objective value is better than the best known integer feasible solution, the routine computes values of auxiliary variables (rows) and stores all solution components in the problem object. \returns If the provided solution is accepted, the routine \verb|glp_ios_heur_sol| returns zero. Otherwise, if the provided solution is rejected, the routine returns non-zero. \vspace*{-5pt} \subsection{glp\_ios\_can\_branch --- check if can branch upon specified variable} \synopsis \begin{verbatim} int glp_ios_can_branch(glp_tree *T, int j); \end{verbatim} \returns If $j$-th variable (column) can be used to branch upon, the routine returns non-zero, otherwise zero. \vspace*{-5pt} \subsection{glp\_ios\_branch\_upon --- choose variable to branch upon} \synopsis \begin{verbatim} void glp_ios_branch_upon(glp_tree *T, int j, int sel); \end{verbatim} \description The routine \verb|glp_ios_branch_upon| can be called from the user-defined callback routine in response to the reason \verb|GLP_IBRANCH| to choose a branching variable, whose ordinal number \linebreak is $j$. Should note that only variables, for which the routine \verb|glp_ios_can_branch| returns non-zero, can be used to branch upon. The parameter \verb|sel| is a flag that indicates which branch (subproblem) should be selected next to continue the search: \verb|GLP_DN_BRNCH| --- select down-branch; \verb|GLP_UP_BRNCH| --- select up-branch; \verb|GLP_NO_BRNCH| --- use general selection technique. \para{Comments} On branching the solver removes the current active subproblem from the active list and creates two new subproblems ({\it down-} and {\it up-branches}), which are added to the end of the active list. Note that the down-branch is created before the up-branch, so the last active subproblem will be the up-branch. The down- and up-branches are identical to the current subproblem with exception that in the down-branch the upper bound of $x_j$, the variable chosen to branch upon, is replaced by $\lfloor x_j^*\rfloor$, while in the up-branch the lower bound of $x_j$ is replaced by $\lceil x_j^*\rceil$, where $x_j^*$ is the value of $x_j$ in optimal solution to LP relaxation of the current subproblem. For example, if $x_j^*=3.14$, the new upper bound of $x_j$ in the down-branch is $\lfloor 3.14\rfloor=3$, and the new lower bound in the up-branch is $\lceil 3.14\rceil=4$.) Additionally the callback routine may select either down- or up-branch, from which the solver will continue the search. If none of the branches is selected, a general selection technique will be used. \subsection{glp\_ios\_terminate --- terminate the solution process} \synopsis \begin{verbatim} void glp_ios_terminate(glp_tree *T); \end{verbatim} \description The routine \verb|glp_ios_terminate| sets a flag indicating that the MIP solver should prematurely terminate the search. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{The search tree exploring routines} \subsection{glp\_ios\_tree\_size --- determine size of the search tree} \synopsis \begin{verbatim} void glp_ios_tree_size(glp_tree *T, int *a_cnt, int *n_cnt, int *t_cnt); \end{verbatim} \description The routine \verb|glp_ios_tree_size| stores the following three counts which characterize the current size of the search tree: \verb|a_cnt| is the current number of active nodes, i.e. the current size of the active list; \verb|n_cnt| is the current number of all (active and inactive) nodes; \verb|t_cnt| is the total number of nodes including those which have been already removed from the tree. This count is increased whenever a new node appears in the tree and never decreased. If some of the parameters \verb|a_cnt|, \verb|n_cnt|, \verb|t_cnt| is a null pointer, the corresponding count is not stored. \subsection{glp\_ios\_curr\_node --- determine current active subproblem} \synopsis \begin{verbatim} int glp_ios_curr_node(glp_tree *T); \end{verbatim} \returns The routine \verb|glp_ios_curr_node| returns the reference number of the current active subproblem. However, if the current subproblem does not exist, the routine returns zero. \subsection{glp\_ios\_next\_node --- determine next active subproblem} \synopsis \begin{verbatim} int glp_ios_next_node(glp_tree *T, int p); \end{verbatim} \returns If the parameter $p$ is zero, the routine \verb|glp_ios_next_node| returns the reference number of the first active subproblem. However, if the tree is empty, zero is returned. If the parameter $p$ is not zero, it must specify the reference number of some active subproblem, in which case the routine returns the reference number of the next active subproblem. However, if there is no next active subproblem in the list, zero is returned. All subproblems in the active list are ordered chronologically, i.e. subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. \newpage \subsection{glp\_ios\_prev\_node --- determine previous active subproblem} \synopsis \begin{verbatim} int glp_ios_prev_node(glp_tree *T, int p); \end{verbatim} \returns If the parameter $p$ is zero, the routine \verb|glp_ios_prev_node| returns the reference number of the last active subproblem. However, if the tree is empty, zero is returned. If the parameter $p$ is not zero, it must specify the reference number of some active subproblem, in which case the routine returns the reference number of the previous active subproblem. However, if there is no previous active subproblem in the list, zero is returned. All subproblems in the active list are ordered chronologically, i.e. subproblem $A$ precedes subproblem $B$ if $A$ was created before $B$. \subsection{glp\_ios\_up\_node --- determine parent subproblem} \synopsis \begin{verbatim} int glp_ios_up_node(glp_tree *T, int p); \end{verbatim} \returns The parameter $p$ must specify the reference number of some (active or inactive) subproblem, in which case the routine \verb|iet_get_up_node| returns the reference number of its parent subproblem. However, if the specified subproblem is the root of the tree and, therefore, has no parent, the routine returns zero. \subsection{glp\_ios\_node\_level --- determine subproblem level} \synopsis \begin{verbatim} int glp_ios_node_level(glp_tree *T, int p); \end{verbatim} \returns The routine \verb|glp_ios_node_level| returns the level of the subproblem, whose reference number is $p$, in the branch-and-bound tree. (The root subproblem has level 0, and the level of any other subproblem is the level of its parent plus one.) \subsection{glp\_ios\_node\_bound --- determine subproblem local bound} \synopsis \begin{verbatim} double glp_ios_node_bound(glp_tree *T, int p); \end{verbatim} \returns The routine \verb|glp_ios_node_bound| returns the local bound for (active or inactive) subproblem, whose reference number is $p$. \para{Comments} The local bound for subproblem $p$ is an lower (minimization) or upper (maximization) bound for integer optimal solution to {\it this} subproblem (not to the original problem). This bound is local in the sense that only subproblems in the subtree rooted at node $p$ cannot have better integer feasible solutions. On creating a subproblem (due to the branching step) its local bound is inherited from its parent and then may get only stronger (never weaker). For the root subproblem its local bound is initially set to \verb|-DBL_MAX| (minimization) or \verb|+DBL_MAX| (maximization) and then improved as the root LP relaxation has been solved. Note that the local bound is not necessarily the optimal objective value to corresponding LP relaxation. \subsection{glp\_ios\_best\_node --- find active subproblem with best local bound} \synopsis \begin{verbatim} int glp_ios_best_node(glp_tree *T); \end{verbatim} \returns The routine \verb|glp_ios_best_node| returns the reference number of the active subproblem, whose local bound is best (i.e. smallest in case of minimization or largest in case of maximization). However, if the tree is empty, the routine returns zero. \para{Comments} The best local bound is an lower (minimization) or upper (maximization) bound for integer optimal solution to the original MIP problem. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{The cut pool routines} \subsection{glp\_ios\_pool\_size --- determine current size of the cut pool} \synopsis \begin{verbatim} int glp_ios_pool_size(glp_tree *T); \end{verbatim} \returns The routine \verb|glp_ios_pool_size| returns the current size of the cut pool, that is, the number of cutting plane constraints currently added to it. \subsection{glp\_ios\_add\_row --- add constraint to the cut pool} \synopsis \begin{verbatim} int glp_ios_add_row(glp_tree *T, const char *name, int klass, int flags, int len, const int ind[], const double val[], int type, double rhs); \end{verbatim} \description The routine \verb|glp_ios_add_row| adds specified row (cutting plane constraint) to the cut pool. The cutting plane constraint should have the following format: $$\sum_{j\in J}a_jx_j\left\{\begin{array}{@{}c@{}}\geq\\\leq\\ \end{array}\right\}b,$$ where $J$ is a set of indices (ordinal numbers) of structural variables, $a_j$ are constraint coefficients, $x_j$ are structural variables, $b$ is the right-hand side. The parameter \verb|name| specifies a symbolic name assigned to the constraint (1 up to 255 characters). If it is \verb|NULL| or an empty string, no name is assigned. The parameter \verb|klass| specifies the constraint class, which must be either zero or a number in the range from 101 to 200. The application may use this attribute to distinguish between cutting plane constraints of different classes.\footnote{Constraint classes numbered from 1 to 100 are reserved for GLPK cutting plane generators.} The parameter \verb|flags| currently is not used and must be zero. Ordinal numbers of structural variables (i.e. column indices) $j\in J$ and numerical values of corresponding constraint coefficients $a_j$ should be placed in locations \verb|ind[1]|, \dots, \verb|ind[len]| and \verb|val[1]|, \dots, \verb|val[len]|, respectively, where ${\tt len}=|J|$ is the number of constraint coefficients, $0\leq{\tt len}\leq n$, and $n$ is the number of columns in the problem object. Coefficients with identical column indices are not allowed. Zero coefficients are allowed, however, they are ignored. The parameter \verb|type| specifies the constraint type as follows: \verb|GLP_LO| means inequality constraint $\Sigma a_jx_j\geq b$; \verb|GLP_UP| means inequality constraint $\Sigma a_jx_j\leq b$; The parameter \verb|rhs| specifies the right-hand side $b$. All cutting plane constraints in the cut pool are identified by their ordinal numbers 1, 2, \dots, $size$, where $size$ is the current size of the cut pool. New constraints are always added to the end of the cut pool, thus, ordinal numbers of previously added constraints are not changed. \returns The routine \verb|glp_ios_add_row| returns the ordinal number of the cutting plane constraint added, which is the new size of the cut pool. \para{Example} \begin{verbatim} /* generate triangle cutting plane: x[i] + x[j] + x[k] <= 1 */ . . . /* add the constraint to the cut pool */ ind[1] = i, val[1] = 1.0; ind[2] = j, val[2] = 1.0; ind[3] = k, val[3] = 1.0; glp_ios_add_row(tree, NULL, TRIANGLE_CUT, 0, 3, ind, val, GLP_UP, 1.0); \end{verbatim} \para{Comments} Cutting plane constraints added to the cut pool are intended to be then added only to the {\it current} subproblem, so these constraints can be globally as well as locally valid. However, adding a constraint to the cut pool does not mean that it will be added to the current subproblem---it depends on the solver's decision: if the constraint seems to be efficient, it is moved from the pool to the current subproblem, otherwise it is simply dropped.\footnote{Globally valid constraints could be saved and then re-used for other subproblems, but currently such feature is not implemented.} Normally, every time the callback routine is called for cut generation, the cut pool is empty. On the other hand, the solver itself can generate cutting plane constraints (like Gomory's or mixed integer rounding cuts), in which case the cut pool may be non-empty. \subsection{glp\_ios\_del\_row --- remove constraint from the cut pool} \synopsis \begin{verbatim} void glp_ios_del_row(glp_tree *T, int i); \end{verbatim} \description The routine \verb|glp_ios_del_row| deletes $i$-th row (cutting plane constraint) from the cut pool, where $1\leq i\leq size$ is the ordinal number of the constraint in the pool, $size$ is the current size of the cut pool. Note that deleting a constraint from the cut pool leads to changing ordinal numbers of other constraints remaining in the pool. New ordinal numbers of the remaining constraints are assigned under assumption that the original order of constraints is not changed. Let, for example, there be four constraints $a$, $b$, $c$ and $d$ in the cut pool, which have ordinal numbers 1, 2, 3 and 4, respectively, and let constraint $b$ have been deleted. Then after deletion the remaining constraint $a$, $c$ and $d$ are assigned new ordinal numbers 1, 2 and 3, respectively. To find the constraint to be deleted the routine \verb|glp_ios_del_row| uses ``smart'' linear search, so it is recommended to remove constraints in a natural or reverse order and avoid removing them in a random order. \para{Example} \begin{verbatim} /* keep first 10 constraints in the cut pool and remove other constraints */ while (glp_ios_pool_size(tree) > 10) glp_ios_del_row(tree, glp_ios_pool_size(tree)); \end{verbatim} \subsection{glp\_ios\_clear\_pool --- remove all constraints from the cut pool} \synopsis \begin{verbatim} void glp_ios_clear_pool(glp_tree *T); \end{verbatim} \description The routine \verb|glp_ios_clear_pool| makes the cut pool empty deleting all existing rows (cutting plane constraints) from it. %* eof *% glpk-4.52.1/doc/glpk06.tex0000644000062000006210000003034512175147600014320 0ustar maomkpasswd%* glpk06.tex *% \chapter{Miscellaneous API Routines} \section{GLPK environment routines} \subsection{glp\_init\_env --- initialize GLPK environment} \synopsis \begin{verbatim} int glp_init_env(void); \end{verbatim} \description The routine \verb|glp_init_env| initializes the GLPK environment. Normally the application program does not need to call this routine, because it is called automatically on the first call to any API routine. \returns \begin{retlist} 0 & initialization successful;\\ 1 & environment is already initialized;\\ 2 & initialization failed (insufficient memory);\\ 3 & initialization failed (unsupported programming model).\\ \end{retlist} \subsection{glp\_version --- determine library version} \synopsis \begin{verbatim} const char *glp_version(void); \end{verbatim} \returns The routine \verb|glp_version| returns a pointer to a null-terminated character string, which specifies the version of the GLPK library in the form \verb|"X.Y"|, where `\verb|X|' is the major version number, and `\verb|Y|' is the minor version number, for example, \verb|"4.16"|. \newpage \subsection{glp\_free\_env --- free GLPK environment} \synopsis \begin{verbatim} int glp_free_env(void); \end{verbatim} \description The routine \verb|glp_free_env| frees all resources used by GLPK routines (memory blocks, etc.) which are currently still in use. Normally the application program does not need to call this routine, because GLPK routines always free all unused resources. However, if the application program even has deleted all problem objects, there will be several memory blocks still allocated for the internal library needs. For some reasons the application program may want GLPK to free this memory, in which case it should call \verb|glp_free_env|. Note that a call to \verb|glp_free_env| invalidates all problem objects which still exist. \returns \begin{retlist} 0 & termination successful;\\ 1 & environment is inactive (was not initialized).\\ \end{retlist} \subsection{glp\_printf --- write formatted output to terminal} \synopsis \begin{verbatim} void glp_printf(const char *fmt, ...); \end{verbatim} \description The routine \verb|glp_printf| uses the format control string \verb|fmt| to format its parameters and writes the formatted output to the terminal. This routine is a replacement of the standard C function \verb|printf| and used by all GLPK routines to perform terminal output. The application program may use \verb|glp_printf| for the same purpose that allows controlling its terminal output with the routines \verb|glp_term_out| and \verb|glp_term_hook|. \subsection{glp\_vprintf --- write formatted output to terminal} \synopsis \begin{verbatim} void glp_vprintf(const char *fmt, va_list arg); \end{verbatim} \description The routine \verb|glp_vprintf| uses the format control string \verb|fmt| to format its parameters specified by the list \verb|arg| and writes the formatted output to the terminal. This routine is a replacement of the standard C function \verb|vprintf| and used by all GLPK routines to perform terminal output. The application program may use \verb|glp_vprintf| for the same purpose that allows controlling its terminal output with the routines \verb|glp_term_out| and \verb|glp_term_hook|. \newpage \subsection{glp\_term\_out --- enable/disable terminal output} \synopsis \begin{verbatim} int glp_term_out(int flag); \end{verbatim} \description Depending on the parameter flag the routine \verb|glp_term_out| enables or disables terminal output performed by glpk routines: \verb|GLP_ON | --- enable terminal output; \verb|GLP_OFF| --- disable terminal output. \returns The routine \verb|glp_term_out| returns the previous value of the terminal output flag. \subsection{glp\_term\_hook --- intercept terminal output} \synopsis \begin{verbatim} void glp_term_hook(int (*func)(void *info, const char *s), void *info); \end{verbatim} \description The routine \verb|glp_term_hook| installs the user-defined hook routine to intercept all terminal output performed by GLPK routines. %This feature can be used to redirect the terminal output to other %destination, for example, to a file or a text window. The parameter {\it func} specifies the user-defined hook routine. It is called from an internal printing routine, which passes to it two parameters: {\it info} and {\it s}. The parameter {\it info} is a transit pointer specified in corresponding call to the routine \verb|glp_term_hook|; it may be used to pass some additional information to the hook routine. The parameter {\it s} is a pointer to the null terminated character string, which is intended to be written to the terminal. If the hook routine returns zero, the printing routine writes the string {\it s} to the terminal in a usual way; otherwise, if the hook routine returns non-zero, no terminal output is performed. To uninstall the hook routine both parameters {\it func} and {\it info} should be specified as \verb|NULL|. \para{Example} \begin{footnotesize} \begin{verbatim} static int hook(void *info, const char *s) { FILE *foo = info; fputs(s, foo); return 1; } int main(void) { FILE *foo; . . . glp_term_hook(hook, foo); /* redirect terminal output */ . . . glp_term_hook(NULL, NULL); /* resume terminal output */ . . . } \end{verbatim} \end{footnotesize} \newpage \subsection{glp\_open\_tee --- start copying terminal output} \synopsis \begin{verbatim} int glp_open_tee(const char *fname); \end{verbatim} \description The routine \verb|glp_open_tee| starts copying all the terminal output to an output text file, whose name is specified by the character string \verb|fname|. \returns \begin{retlist} 0 & operation successful;\\ 1 & copying terminal output is already active;\\ 2 & unable to create output file.\\ \end{retlist} \subsection{glp\_close\_tee --- stop copying terminal output} \synopsis \begin{verbatim} int glp_close_tee(void); \end{verbatim} \description The routine \verb|glp_close_tee| stops copying the terminal output to the output text file previously open by the routine \verb|glp_open_tee| closing that file. \returns \begin{retlist} 0 & operation successful;\\ 1 & copying terminal output was not started.\\ \end{retlist} \subsection{glp\_error --- display error message and terminate execution} \synopsis \begin{verbatim} void glp_error(const char *fmt, ...); \end{verbatim} \description The routine \verb|glp_error| (implemented as a macro) formats its parameters using the format control string \verb|fmt|, writes the formatted message to the terminal, and then abnormally terminates the program. \newpage \subsection{glp\_assert --- check logical condition} \synopsis \begin{verbatim} void glp_assert(int expr); \end{verbatim} \description The routine \verb|glp_assert| (implemented as a macro) checks a logical condition specified by the expression \verb|expr|. If the condition is true (non-zero), the routine does nothing; otherwise, if the condition is false (zero), the routine prints an error message and abnormally terminates the program. This routine is a replacement of the standard C function \verb|assert| and used by all GLPK routines to check program logic. The application program may use \verb|glp_assert| for the same purpose. \subsection{glp\_error\_hook --- install hook to intercept abnormal termination} \synopsis \begin{verbatim} void glp_error_hook(void (*func)(void *info), void *info); \end{verbatim} \description The routine \verb|glp_error_hook| installs a user-defined hook routine to intercept abnormal termination. The parameter \verb|func| specifies the user-defined hook routine. It is called from the routine \verb|glp_error| before the latter calls the abort function to abnormally terminate the application program because of fatal error. The parameter \verb|info| is a transit pointer, specified in the corresponding call to the routine \verb|glp_error_hook|; it may be used to pass some information to the hook routine. To uninstall the hook routine the parameters \verb|func| and \verb|info| should be specified as \verb|NULL|. If the hook routine returns, the application program is abnormally terminated. To prevent abnormal termnation the hook routine may perform a global jump using the standard function \verb|longjmp|, in which case the application program {\it must} call the routine \verb|glp_free_env|. \subsection{glp\_malloc --- allocate memory block} \synopsis \begin{verbatim} void *glp_malloc(int size); \end{verbatim} \description The routine \verb|glp_malloc| dynamically allocates a memory block of \verb|size| bytes long. Note that: 1) the parameter \verb|size| must be positive; 2) being allocated the memory block contains arbitrary data, that is, it is {\it not} initialized by binary zeros; 3) if the block cannot be allocated due to insufficient memory, the routine prints an error message and abnormally terminates the program. This routine is a replacement of the standard C function \verb|malloc| and used by all GLPK routines for dynamic memory allocation. The application program may use \verb|glp_malloc| for the same purpose. \returns The routine \verb|glp_malloc| returns a pointer to the memory block allocated. To free this block the routine \verb|glp_free| (not the standard C function \verb|free|!) must be used. \subsection{glp\_calloc --- allocate memory block} \synopsis \begin{verbatim} void *glp_calloc(int n, int size); \end{verbatim} \description The routine \verb|glp_calloc| dynamically allocates a memory block of \verb|n|$\times$\verb|size| bytes long. Note that: 1) both parameters \verb|n| and \verb|size| must be positive; 2) being allocated the memory block contains arbitrary data, that is, it is {\it not} initialized by binary zeros; 3) if the block cannot be allocated due to insufficient memory, the routine prints an error message and abnormally terminates the program. This routine is a replacement of the standard C function \verb|calloc| (with exception that the block is not cleaned) and used by all GLPK routines for dynamic memory allocation. The application program may use \verb|glp_calloc| for the same purpose. \returns The routine \verb|glp_calloc| returns a pointer to the memory block allocated. To free this block the routine \verb|glp_free| (not the standard C function \verb|free|!) must be used. \subsection{glp\_free --- free memory block} \synopsis \begin{verbatim} void glp_free(void *ptr); \end{verbatim} \description The routine \verb|glp_free| deallocates a memory block pointed to by \verb|ptr|, which was previously allocated by the routine \verb|glp_malloc| or \verb|glp_calloc|. Note that the pointer \verb|ptr| must be valid and must not be \verb|NULL|. This routine is a replacement of the standard C function \verb|free| and used by all GLPK routines for dynamic memory allocation. The application program may use \verb|glp_free| for the same purpose. \newpage \subsection{glp\_mem\_usage --- get memory usage information} \synopsis \begin{verbatim} void glp_mem_usage(int *count, int *cpeak, size_t *total, size_t *tpeak); \end{verbatim} \description The routine \verb|glp_mem_usage| reports some information about utilization of the memory by the routines \verb|glp_malloc|, \verb|glp_calloc|, and \verb|glp_free|. Information is stored to locations specified by corresponding parameters (see below). Any parameter can be specified as \verb|NULL|, in which case corresponding information is not stored. \verb|*count| is the number of currently allocated memory blocks. \verb|*cpeak| is the peak value of \verb|*count| reached since the initialization of the GLPK library environment. \verb|*total| is the total amount, in bytes, of currently allocated memory blocks. \verb|*tpeak| is the peak value of \verb|*total| reached since the initialization of the GLPK library envirionment. \para{Example} \begin{footnotesize} \begin{verbatim} glp_mem_usage(&count, NULL, NULL, NULL); printf("%d memory block(s) are still allocated\n", count); \end{verbatim} \end{footnotesize} \subsection{glp\_mem\_limit --- set memory usage limit} \synopsis \begin{verbatim} void glp_mem_limit(int limit); \end{verbatim} \description The routine \verb|glp_mem_limit| limits the amount of memory available for dynamic allocation (with the routines \verb|glp_malloc| and \verb|glp_calloc|) to \verb|limit| megabytes. %* eof *% glpk-4.52.1/doc/glpk07.tex0000644000062000006210000002126412175147600014321 0ustar maomkpasswd%* glpk07.tex *% \chapter{Installing GLPK on Your Computer} \label{install} \section{Downloading the distribution tarball} The distribution tarball of the most recent version of the GLPK package can be found on \url{http://ftp.gnu.org/gnu/glpk/} [via http] and \url{ftp://ftp.gnu.org/gnu/glpk/} [via FTP]. It can also be found on one of the FTP mirrors; see \url{http://www.gnu.org/prep/ftp.html}. Please use a mirror if possible. To make sure that the GLPK distribution tarball you have downloaded is intact you need to download the corresponding `\verb|.sig|' file and run a command like this: \begin{verbatim} gpg --verify glpk-4.38.tar.gz.sig \end{verbatim} \noindent If that command fails because you do not have the required public key, run the following command to import it: \begin{verbatim} gpg --keyserver keys.gnupg.net --recv-keys 5981E818 \end{verbatim} \noindent and then re-run the previous command. \section{Unpacking the distribution tarball} The GLPK package (like all other GNU software) is distributed in the form of packed archive. This is one file named \verb|glpk-X.Y.tar.gz|, where {\it X} is the major version number and {\it Y} is the minor version number. In order to prepare the distribution for installation you need to copy the GLPK distribution file to a working subdirectory and then unpack and unarchive the distribution file with the following command: \begin{verbatim} tar zx < glpk-X.Y.tar \end{verbatim} \newpage \section{Configuring the package} After unpacking and unarchiving the GLPK distribution you should configure the package,\linebreak i.e. automatically tune it for your platform. Normally, you should just \verb|cd| to the subdirectory \verb|glpk-X.Y| and run the configure script, e.g. \begin{verbatim} ./configure \end{verbatim} The `\verb|configure|' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `\verb|Makefile|' in each directory of the package. It also creates file `\verb|config.h|' containing platform-dependent definitions. Finally, it creates a shell script `\verb|config.status|' that you can run in the future to recreate the current configuration, a file `\verb|config.cache|' that saves the results of its tests to speed up reconfiguring, and a file `\verb|config.log|' containing compiler output (useful mainly for debugging `\verb|configure|'). Running `\verb|configure|' takes about a minute. While it is running, it displays some informational messages that tell you what it is doing. If you don't want to see these messages, run `\verb|configure|' with its standard output redirected to `\verb|dev/null|'; for example, `\verb|./configure > /dev/null|'. By default both static and shared versions of the GLPK library will be compiled. Compilation of the shared librariy can be turned off by specifying the `\verb|--disable-shared|' option to `\verb|configure|': \begin{verbatim} ./configure --disable-shared \end{verbatim} \noindent If you encounter problems building the library try using the above option, because some platforms do not support shared libraries. The GLPK package has some optional features listed below. By default all these features are disabled. To enable a feature the corresponding option should be passed to the configure script. \verb|--with-gmp | Enable using the GNU MP bignum library This feature allows the exact simplex solver to use the GNU MP bignum library. If it is disabled, the exact simplex solver uses the GLPK bignum module, which provides the same functionality as GNU MP, however, it is much less efficient. For details about the GNU MP bignum library see its web page at \url{http://gmplib.org/}. \verb|--enable-dl | The same as `\verb|--enable-dl=ltdl|' \verb|--enable-dl=ltdl | Enable shared library support (GNU) \verb|--enable-dl=dlfcn | Enable shared library support (POSIX) Currently this feature is only needed to provide dynamic linking to ODBC and MySQL shared libraries (see below). For details about the GNU shared library support see the manual at \url{http://www.gnu.org/software/libtool/manual/}. \verb|--enable-odbc | Enable using ODBC table driver (\verb|libiodbc|) \verb|--enable-odbc=unix | Enable using ODBC table driver (\verb|libodbc|) This feature allows transmitting data between MathProg model objects and relational databases accessed through ODBC. For more details about this feature see the supplement ``Using Data Tables in the GNU MathProg Modeling Language'' (\verb|doc/tables.pdf|). \verb|--enable-mysql | Enable using MySQL table driver (\verb|libmysql|) This feature allows transmitting data between MathProg model objects and MySQL relational databases. For more details about this feature see the supplement ``Using Data Tables in the GNU MathProg Modeling Language'' (\verb|doc/tables.pdf|). \section{Compiling the package} Normally, you can compile (build) the package by typing the command: \begin{verbatim} make \end{verbatim} \noindent It reads `\verb|Makefile|' generated by `\verb|configure|' and performs all necessary jobs. If you want, you can override the `\verb|make|' variables \verb|CFLAGS| and \verb|LDFLAGS| like this: \begin{verbatim} make CFLAGS=-O2 LDFLAGS=-s \end{verbatim} To compile the package in a different directory from the one containing the source code, you must use a version of `\verb|make|' that supports `\verb|VPATH|' variable, such as GNU `\verb|make|'. `\verb|cd|' to the directory where you want the object files and executables to go and run the `\verb|configure|' script. `\verb|configure|' automatically checks for the source code in the directory that `\verb|configure|' is in and in `\verb|..|'. If for some reason `\verb|configure|' is not in the source code directory that you are configuring, then it will report that it can't find the source code. In that case, run `\verb|configure|' with the option `\verb|--srcdir=DIR|', where \verb|DIR| is the directory that contains the source code. Some systems require unusual options for compilation or linking that the `\verb|configure|' script does not know about. You can give `\verb|configure|' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: \begin{verbatim} CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure \end{verbatim} \noindent Or on systems that have the `\verb|env|' program, you can do it like this: \begin{verbatim} env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure \end{verbatim} Here are the `\verb|make|' variables that you might want to override with environment variables when running `\verb|configure|'. For these variables, any value given in the environment overrides the value that `\verb|configure|' would choose: \verb|CC | C compiler program. The default is `\verb|cc|'. \verb|INSTALL | Program used to install files. The default value is `\verb|install|' if you have it,\\ \verb| | otherwise `\verb|cp|'. For these variables, any value given in the environment is added to the value that `\verb|configure|' chooses: \verb|DEFS | Configuration options, in the form `\verb|-Dfoo -Dbar| \dots'. \verb|LIBS | Libraries to link with, in the form `\verb|-lfoo -lbar| \dots'. \section{Checking the package} To check the package, i.e. to run some tests included in the package, you can use the following command: \begin{verbatim} make check \end{verbatim} \section{Installing the package} Normally, to install the GLPK package you should type the following command: \begin{verbatim} make install \end{verbatim} \noindent By default, `\verb|make install|' will install the package's files in `\verb|usr/local/bin|', `\verb|usr/local/lib|', etc. You can specify an installation prefix other than `\verb|/usr/local|' by giving `\verb|configure|' the option `\verb|--prefix=PATH|'. Alternately, you can do so by consistently giving a value for the `\verb|prefix|' variable when you run `\verb|make|', e.g. \begin{verbatim} make prefix=/usr/gnu make prefix=/usr/gnu install \end{verbatim} After installing you can remove the program binaries and object files from the source directory by typing `\verb|make clean|'. To remove all files that `\verb|configure|' created (`\verb|Makefile|', `\verb|config.status|', etc.), just type `\verb|make distclean|'. The file `\verb|configure.ac|' is used to create `\verb|configure|' by a program called `\verb|autoconf|'. You only need it if you want to remake `\verb|configure|' using a newer version of `\verb|autoconf|'. \section{Uninstalling the package} To uninstall the GLPK package, i.e. to remove all the package's files from the system places, you can use the following command: \begin{verbatim} make uninstall \end{verbatim} %* eof *% glpk-4.52.1/doc/glpk08.tex0000644000062000006210000006403312175147600014323 0ustar maomkpasswd%* glpk08.tex *% \chapter{MPS Format} \label{champs} \section{Fixed MPS Format} \label{secmps} The MPS format\footnote{The MPS format was developed in 1960's by IBM as input format for their mathematical programming system MPS/360. Today the MPS format is a most widely used format understood by most mathematical programming packages. This appendix describes only the features of the MPS format, which are implemented in the GLPK package.} is intended for coding LP/MIP problem data. This format assumes the formulation of LP/MIP problem (1.1)---(1.3) (see Section \ref{seclp}, page \pageref{seclp}). {\it MPS file} is a text file, which contains two types of cards\footnote{In 1960's MPS file was a deck of 80-column punched cards, so the author decided to keep the word ``card'', which may be understood as ``line of text file''.}: indicator cards and data cards. Indicator cards determine a kind of succeeding data. Each indicator card has one word in uppercase letters beginning in column 1. Data cards contain problem data. Each data card is divided into six fixed fields: \begin{center} \begin{tabular}{lcccccc} & Field 1 & Field 2 & Field 3 & Field 4 & Field 5 & Feld 6 \\ \hline Columns & 2---3 & 5---12 & 15---22 & 25---36 & 40---47 & 50---61 \\ Contents & Code & Name & Name & Number & Name & Number \\ \end{tabular} \end{center} On a particular data card some fields may be optional. Names are used to identify rows, columns, and some vectors (see below). Aligning the indicator code in the field 1 to the left margin is optional. All names specified in the fields 2, 3, and 5 should contain from 1 up to 8 arbitrary characters (except control characters). If a name is placed in the field 3 or 5, its first character should not be the dollar sign `\verb|$|'. If a name contains spaces, the spaces are ignored. All numerical values in the fields 4 and 6 should be coded in the form $sxx$\verb|E|$syy$, where $s$ is the plus `\verb|+|' or the minus `\verb|-|' sign, $xx$ is a real number with optional decimal point, $yy$ is an integer decimal exponent. Any number should contain up to 12 characters. If the sign $s$ is omitted, the plus sign is assumed. The exponent part is optional. If a number contains spaces, the spaces are ignored. \newpage If a card has the asterisk `\verb|*|' in the column 1, this card is considered as a comment and ignored. Besides, if the first character in the field 3 or 5 is the dollar sign `\verb|$|', all characters from the dollar sign to the end of card are considered as a comment and ignored. MPS file should contain cards in the following order: \vspace*{-8pt} \begin{itemize} \item NAME indicator card; \item ROWS indicator card; \item data cards specifying rows (constraints); \item COLUMNS indicator card; \item data cards specifying columns (structural variables) and constraint coefficients; \item RHS indicator card; \item data cards specifying right-hand sides of constraints; \item RANGES indicator card; \item data cards specifying ranges for double-bounded constraints; \item BOUNDS indicator card; \item data cards specifying types and bounds of structural variables; \item ENDATA indicator card. \end{itemize} \vspace*{-8pt} {\it Section} is a group of cards consisting of an indicator card and data cards succeeding this indicator card. For example, the ROWS section consists of the ROWS indicator card and data cards specifying rows. The sections RHS, RANGES, and BOUNDS are optional and may be omitted. \section{Free MPS Format} {\it Free MPS format} is an improved version of the standard (fixed) MPS format described above.\footnote{This format was developed in the beginning of 1990's by IBM as an alternative to the standard fixed MPS format for Optimization Subroutine Library (OSL).} Note that all changes in free MPS format concern only the coding of data while the structure of data is the same for both fixed and free versions of the MPS format. In free MPS format indicator and data records\footnote{{\it Record} in free MPS format has the same meaning as {\it card} in fixed MPS format.} may have arbitrary length not limited to 80 characters. Fields of data records have no predefined positions, i.e. the fields may begin in any position, except position 1, which must be blank, and must be separated from each other by one or more blanks. However, the fields must appear in the same order as in fixed MPS format. \newpage Symbolic names in fields 2, 3, and 5 may be longer than 8 characters\footnote{GLPK allows symbolic names having up to 255 characters.} and must not contain embedded blanks. Numeric values in fields 4 and 6 are limited to 12 characters and must not contain embedded blanks. Only six fields on each data record are used. Any other fields are ignored. If the first character of any field (not necessarily fields 3 and 5) is the dollar sign (\$), all characters from the dollar sign to the end of record are considered as a comment and ignored. \section{NAME indicator card} The NAME indicator card should be the first card in the MPS file (except optional comment cards, which may precede the NAME card). This card should contain the word \verb|NAME| in the columns 1---4 and the problem name in the field 3. The problem name is optional and may be omitted. \section{ROWS section} \label{secrows} The ROWS section should start with the indicator card, which contains the word \verb|ROWS| in the columns 1---4. Each data card in the ROWS section specifies one row (constraint) of the problem. All these data cards have the following format. `\verb|N|' in the field 1 means that the row is free (unbounded): $$-\infty < x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} < +\infty;$$ `\verb|L|' in the field 1 means that the row is of ``less than or equal to'' type: $$-\infty < x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} \leq b_i;$$ `\verb|G|' in the field 1 means that the row is of ``greater than or equal to'' type: $$b_i \leq x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} < +\infty;$$ `\verb|E|' in the field 1 means that the row is of ``equal to'' type: $$x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} \leq b_i,$$ where $b_i$ is a right-hand side. Note that each constraint has a corresponding implictly defined auxiliary variable ($x_i$ above), whose value is a value of the corresponding linear form, therefore row bounds can be considered as bounds of such auxiliary variable. The filed 2 specifies a row name (which is considered as the name of the corresponding auxiliary variable). \newpage The fields 3, 4, 5, and 6 are not used and should be empty. Numerical values of all non-zero right-hand sides $b_i$ should be specified in the RHS section (see below). All double-bounded (ranged) constraints should be specified in the RANGES section (see below). \section{COLUMNS section} The COLUMNS section should start with the indicator card, which contains the word \verb|COLUMNS| in the columns 1---7. Each data card in the COLUMNS section specifies one or two constraint coefficients $a_{ij}$ and also introduces names of columns, i.e. names of structural variables. All these data cards have the following format. The field 1 is not used and should be empty. The field 2 specifies a column name. If this field is empty, the column name from the immediately preceeding data card is assumed. The field 3 specifies a row name defined in the ROWS section. The field 4 specifies a numerical value of the constraint coefficient $a_{ij}$, which is placed in the corresponding row and column. The fields 5 and 6 are optional. If they are used, they should contain a second pair ``row name---constraint coefficient'' for the same column. Elements of the constraint matrix (i.e. constraint coefficients) should be enumerated in the column wise manner: all elements for the current column should be specified before elements for the next column. However, the order of rows in the COLUMNS section may differ from the order of rows in the ROWS section. Constraint coefficients not specified in the COLUMNS section are considered as zeros. Therefore zero coefficients may be omitted, although it is allowed to explicitly specify them. \section{RHS section} The RHS section should start with the indicator card, which contains the word \verb|RHS| in the columns 1---3. Each data card in the RHS section specifies one or two right-hand sides $b_i$ (see Section \ref{secrows}, page \pageref{secrows}). All these data cards have the following format. The field 1 is not used and should be empty. The field 2 specifies a name of the right-hand side (RHS) vector\footnote{This feature allows the user to specify several RHS vectors in the same MPS file. However, before solving the problem a particular RHS vector should be chosen.}. If this field is empty, the RHS vector name from the immediately preceeding data card is assumed. \newpage The field 3 specifies a row name defined in the ROWS section. The field 4 specifies a right-hand side $b_i$ for the row, whose name is specified in the field 3. Depending on the row type $b_i$ is a lower bound (for the row of \verb|G| type), an upper bound (for the row of \verb|L| type), or a fixed value (for the row of \verb|E| type).\footnote{If the row is of {\tt N} type, $b_i$ is considered as a constant term of the corresponding linear form. Should note, however, this convention is non-standard.} The fields 5 and 6 are optional. If they are used, they should contain a second pair ``row name---right-hand side'' for the same RHS vector. All right-hand sides for the current RHS vector should be specified before right-hand sides for the next RHS vector. However, the order of rows in the RHS section may differ from the order of rows in the ROWS section. Right-hand sides not specified in the RHS section are considered as zeros. Therefore zero right-hand sides may be omitted, although it is allowed to explicitly specify them. \section{RANGES section} The RANGES section should start with the indicator card, which contains the word \verb|RANGES| in the columns 1---6. Each data card in the RANGES section specifies one or two ranges for double-side constraints, i.e. for constraints that are of the types \verb|L| and \verb|G| at the same time: $$l_i \leq x_i = a_{i1}x_{m+1} + a_{i2}x_{m+2} + \dots + a_{in}x_{m+n} \leq u_i,$$ where $l_i$ is a lower bound, $u_i$ is an upper bound. All these data cards have the following format. The field 1 is not used and should be empty. The field 2 specifies a name of the range vector\footnote{This feature allows the user to specify several range vectors in the same MPS file. However, before solving the problem a particular range vector should be chosen.}. If this field is empty, the range vector name from the immediately preceeding data card is assumed. The field 3 specifies a row name defined in the ROWS section. The field 4 specifies a range value $r_i$ (see the table below) for the row, whose name is specified in the field 3. The fields 5 and 6 are optional. If they are used, they should contain a second pair ``row name---range value'' for the same range vector. All range values for the current range vector should be specified before range values for the next range vector. However, the order of rows in the RANGES section may differ from the order of rows in the ROWS section. For each double-side constraint specified in the RANGES section its lower and upper bounds are determined as follows: \newpage \begin{center} \begin{tabular}{cccc} Row type & Sign of $r_i$ & Lower bound & Upper bound \\ \hline {\tt G} & $+$ or $-$ & $b_i$ & $b_i + |r_i|$ \\ {\tt L} & $+$ or $-$ & $b_i - |r_i|$ & $b_i$ \\ {\tt E} & $+$ & $b_i$ & $b_i + |r_i|$ \\ {\tt E} & $-$ & $b_i - |r_i|$ & $b_i$ \\ \end{tabular} \end{center} \noindent where $b_i$ is a right-hand side specified in the RHS section (if $b_i$ is not specified, it is considered as zero), $r_i$ is a range value specified in the RANGES section. \section{BOUNDS section} \label{secbounds} The BOUNDS section should start with the indicator card, which contains the word \verb|BOUNDS| in the columns 1---6. Each data card in the BOUNDS section specifies one (lower or upper) bound for one structural variable (column). All these data cards have the following format. The indicator in the field 1 specifies the bound type: \verb|LO| --- lower bound; \verb|UP| --- upper bound; \verb|FX| --- fixed variable (lower and upper bounds are equal); \verb|FR| --- free variable (no bounds); \verb|MI| --- no lower bound (lower bound is ``minus infinity''); \verb|PL| --- no upper bound (upper bound is ``plus infinity''). The field 2 specifies a name of the bound vector\footnote{This feature allows the user to specify several bound vectors in the same MPS file. However, before solving the problem a particular bound vector should be chosen.}. If this field is empty, the bound vector name from the immediately preceeding data card is assumed. The field 3 specifies a column name defined in the COLUMNS section. The field 4 specifies a bound value. If the bound type in the field 1 differs from \verb|LO|, \verb|UP|, and \verb|FX|, the value in the field 4 is ignored and may be omitted. The fields 5 and 6 are not used and should be empty. All bound values for the current bound vector should be specified before bound values for the next bound vector. However, the order of columns in the BOUNDS section may differ from the order of columns in the COLUMNS section. Specification of a lower bound should precede specification of an upper bound for the same column (if both the lower and upper bounds are explicitly specified). By default, all columns (structural variables) are non-negative, i.e. have zero lower bound and no upper bound. Lower ($l_j$) and upper ($u_j$) bounds of some column (structural variable $x_j$) are set in the following way, where $s_j$ is a corresponding bound value explicitly specified in the BOUNDS section: \newpage \verb|LO| sets $l_j$ to $s_j$; \verb|UP| sets $u_j$ to $s_j$; \verb|FX| sets both $l_j$ and $u_j$ to $s_j$; \verb|FR| sets $l_j$ to $-\infty$ and $u_j$ to $+\infty$; \verb|MI| sets $l_j$ to $-\infty$; \verb|PL| sets $u_j$ to $+\infty$. \section{ENDATA indicator card} The ENDATA indicator card should be the last card of MPS file (except optional comment cards, which may follow the ENDATA card). This card should contain the word \verb|ENDATA| in the columns 1---6. \section{Specifying objective function} It is impossible to explicitly specify the objective function and optimization direction in the MPS file. However, the following implicit rule is used by default: the first row of \verb|N| type is considered as a row of the objective function (i.e. the objective function is the corresponding auxiliary variable), which should be {\it minimized}. GLPK also allows specifying a constant term of the objective function as a right-hand side of the corresponding row in the RHS section. \section{Example of MPS file} \label{secmpsex} To illustrate what the MPS format is, consider the following example of LP problem: \def\arraystretch{1.2} \noindent\hspace{.5in}minimize $$ value = .03\ bin_1 + .08\ bin_2 + .17\ bin_3 + .12\ bin_4 + .15\ bin_5 + .21\ al + .38\ si $$ \noindent\hspace{.5in}subject to linear constraints $$ \begin{array}{@{}l@{\:}l@{}} yield &= \ \ \ \ \;bin_1 + \ \ \ \ \;bin_2 + \ \ \ \ \;bin_3 + \ \ \ \ \;bin_4 + \ \ \ \ \;bin_5 + \ \ \ \ \;al + \ \ \ \ \;si \\ FE &= .15\ bin_1 + .04\ bin_2 + .02\ bin_3 + .04\ bin_4 + .02\ bin_5 + .01\ al + .03\ si \\ CU &= .03\ bin_1 + .05\ bin_2 + .08\ bin_3 + .02\ bin_4 + .06\ bin_5 + .01\ al \\ MN &= .02\ bin_1 + .04\ bin_2 + .01\ bin_3 + .02\ bin_4 + .02\ bin_5 \\ MG &= .02\ bin_1 + .03\ bin_2 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ + .01\ bin_5 \\ AL &= .70\ bin_1 + .75\ bin_2 + .80\ bin_3 + .75\ bin_4 + .80\ bin_5 + .97\ al \\ SI &= .02\ bin_1 + .06\ bin_2 + .08\ bin_3 + .12\ bin_4 + .02\ bin_5 + .01\ al + .97\ si \\ \end{array} $$ \newpage \noindent\hspace{.5in}and bounds of (auxiliary and structural) variables $$ \begin{array}{r@{\ }l@{\ }l@{\ }l@{\ }rcr@{\ }l@{\ }l@{\ }l@{\ }r} &&yield&=&2000&&0&\leq&bin_1&\leq&200\\ -\infty&<&FE&\leq&60&&0&\leq&bin_2&\leq&2500\\ -\infty&<&CU&\leq&100&&400&\leq&bin_3&\leq&800\\ -\infty&<&MN&\leq&40&&100&\leq&bin_4&\leq&700\\ -\infty&<&MG&\leq&30&&0&\leq&bin_5&\leq&1500\\ 1500&\leq&AL&<&+\infty&&0&\leq&al&<&+\infty\\ 250&\leq&SI&\leq&300&&0&\leq&si&<&+\infty\\ \end{array} $$ \def\arraystretch{1} A complete MPS file which specifies data for this example is shown below (the first two comment lines show card positions). \bigskip \begin{footnotesize} \begin{verbatim} *000000001111111111222222222233333333334444444444555555555566 *234567890123456789012345678901234567890123456789012345678901 NAME PLAN ROWS N VALUE E YIELD L FE L CU L MN L MG G AL L SI COLUMNS BIN1 VALUE .03000 YIELD 1.00000 FE .15000 CU .03000 MN .02000 MG .02000 AL .70000 SI .02000 BIN2 VALUE .08000 YIELD 1.00000 FE .04000 CU .05000 MN .04000 MG .03000 AL .75000 SI .06000 BIN3 VALUE .17000 YIELD 1.00000 FE .02000 CU .08000 MN .01000 AL .80000 SI .08000 BIN4 VALUE .12000 YIELD 1.00000 FE .04000 CU .02000 MN .02000 AL .75000 SI .12000 BIN5 VALUE .15000 YIELD 1.00000 FE .02000 CU .06000 MN .02000 MG .01000 AL .80000 SI .02000 ALUM VALUE .21000 YIELD 1.00000 FE .01000 CU .01000 AL .97000 SI .01000 SILICON VALUE .38000 YIELD 1.00000 FE .03000 SI .97000 RHS RHS1 YIELD 2000.00000 FE 60.00000 CU 100.00000 MN 40.00000 SI 300.00000 MG 30.00000 AL 1500.00000 RANGES RNG1 SI 50.00000 BOUNDS UP BND1 BIN1 200.00000 UP BIN2 2500.00000 LO BIN3 400.00000 UP BIN3 800.00000 LO BIN4 100.00000 UP BIN4 700.00000 UP BIN5 1500.00000 ENDATA \end{verbatim} \end{footnotesize} \vspace*{-6pt} \section{MIP features} \vspace*{-4pt} The MPS format provides two ways for introducing integer variables into the problem. The first way is most general and based on using special marker cards INTORG and INTEND. These marker cards are placed in the COLUMNS section. The INTORG card indicates the start of a group of integer variables (columns), and the card INTEND indicates the end of the group. The MPS file may contain arbitrary number of the marker cards. The marker cards have the same format as the data cards (see Section \ref{secmps}, page \pageref{secmps}). The fields 1, 2, and 6 are not used and should be empty. The field 2 should contain a marker name. This name may be arbitrary. The field 3 should contain the word \verb|'MARKER'| (including apostrophes). The field 5 should contain either the word \verb|'INTORG'| (including apostrophes) for the marker card, which begins a group of integer columns, or the word \verb|'INTEND'| (including apostrophes) for the marker card, which ends the group. The second way is less general but more convenient in some cases. It allows the user declaring integer columns using three additional types of bounds, which are specified in the field 1 of data cards in the BOUNDS section (see Section \ref{secbounds}, page \pageref{secbounds}): \verb|LI| --- lower integer. This bound type specifies that the corresponding column (structural variable), whose name is specified in field 3, is of integer kind. In this case an lower bound of the column should be specified in field 4 (like in the case of \verb|LO| bound type). \verb|UI| --- upper integer. This bound type specifies that the corresponding column (structural variable), whose name is specified in field 3, is of integer kind. In this case an upper bound of the column should be specified in field 4 (like in the case of \verb|UP| bound type). \verb|BV| --- binary variable. This bound type specifies that the corresponding column (structural variable), whose name is specified in the field 3, is of integer kind, its lower bound is zero, and its upper bound is one (thus, such variable being of integer kind can have only two values zero and one). In this case a numeric value specified in the field 4 is ignored and may be omitted. Consider the following example of MIP problem: \noindent \hspace{1in} minimize $$Z = 3 x_1 + 7 x_2 - x_3 + x4$$ \hspace{1in} subject to linear constraints $$ \begin{array}{c} \nonumber r_1 = 2 x_1 - \ \ x_2 + \ \ x_3 - \ \;x_4 \\ \nonumber r_2 = \ \;x_1 - \ \;x_2 - 6 x_3 + 4 x_4 \\ \nonumber r_3 = 5 x_1 + 3 x_2 \ \ \ \ \ \ \ \ \ + \ \ x_4 \\ \end{array} $$ \hspace{1in} and bound of variables $$ \begin{array}{cccl} \nonumber 1 \leq r_1 < +\infty && 0 \leq x_1 \leq 4 &{\rm(continuous)}\\ \nonumber 8 \leq r_2 < +\infty && 2 \leq x_2 \leq 5 &{\rm(integer)} \\ \nonumber 5 \leq r_3 < +\infty && 0 \leq x_3 \leq 1 &{\rm(integer)} \\ \nonumber && 3 \leq x_4 \leq 8 &{\rm(continuous)}\\ \end{array} $$ The corresponding MPS file may look like the following: \medskip \begin{footnotesize} \begin{verbatim} NAME SAMP1 ROWS N Z G R1 G R2 G R3 COLUMNS X1 R1 2.0 R2 1.0 X1 R3 5.0 Z 3.0 MARK0001 'MARKER' 'INTORG' X2 R1 -1.0 R2 -1.0 X2 R3 3.0 Z 7.0 X3 R1 1.0 R2 -6.0 X3 Z -1.0 MARK0002 'MARKER' 'INTEND' X4 R1 -1.0 R2 4.0 X4 R3 1.0 Z 1.0 RHS RHS1 R1 1.0 RHS1 R2 8.0 RHS1 R3 5.0 BOUNDS UP BND1 X1 4.0 LO BND1 X2 2.0 UP BND1 X2 5.0 UP BND1 X3 1.0 LO BND1 X4 3.0 UP BND1 X4 8.0 ENDATA \end{verbatim} \end{footnotesize} \newpage The same example may be coded without INTORG/INTEND markers using the bound type UI for the variable $x_2$ and the bound type BV for the variable $x_3$: \medskip \begin{footnotesize} \begin{verbatim} NAME SAMP2 ROWS N Z G R1 G R2 G R3 COLUMNS X1 R1 2.0 R2 1.0 X1 R3 5.0 Z 3.0 X2 R1 -1.0 R2 -1.0 X2 R3 3.0 Z 7.0 X3 R1 1.0 R2 -6.0 X3 Z -1.0 X4 R1 -1.0 R2 4.0 X4 R3 1.0 Z 1.0 RHS RHS1 R1 1.0 RHS1 R2 8.0 RHS1 R3 5.0 BOUNDS UP BND1 X1 4.0 LO BND1 X2 2.0 UI BND1 X2 5.0 BV BND1 X3 LO BND1 X4 3.0 UP BND1 X4 8.0 ENDATA \end{verbatim} \end{footnotesize} %\section{Specifying predefined basis} %\label{secbas} % %The MPS format can also be used to specify some predefined basis for an %LP problem, i.e. to specify which rows and columns are basic and which %are non-basic. % %The order of a basis file in the MPS format is: % %$\bullet$ NAME indicator card; % %$\bullet$ data cards (can appear in arbitrary order); % %$\bullet$ ENDATA indicator card. % %Each data card specifies either a pair "basic column---non-basic row" %or a non-basic column. All the data cards have the following format. % %`\verb|XL|' in the field 1 means that a column, whose name is given in %the field 2, is basic, and a row, whose name is given in the field 3, %is non-basic and placed on its lower bound. % %`\verb|XU|' in the field 1 means that a column, whose name is given in %the field 2, is basic, and a row, whose name is given in the field 3, %is non-basic and placed on its upper bound. % %`\verb|LL|' in the field 1 means that a column, whose name is given in %the field 3, is non-basic and placed on its lower bound. % %`\verb|UL|' in the field 1 means that a column, whose name is given in %the field 3, is non-basic and placed on its upper bound. % %The field 2 contains a column name. % %If the indicator given in the field 1 is `\verb|XL|' or `\verb|XU|', %the field 3 contains a row name. Otherwise, if the indicator is %`\verb|LL|' or `\verb|UL|', the field 3 is not used and should be %empty. % %The field 4, 5, and 6 are not used and should be empty. % %A basis file in the MPS format acts like a patch: it doesn't specify %a basis completely, instead that it is just shows in what a given basis %differs from the "standard" basis, where all rows (auxiliary variables) %are assumed to be basic and all columns (structural variables) are %assumed to be non-basic. % %As an example here is a basis file that specifies an optimal basis %for the example LP problem given in Section \ref{secmpsex}, %Page \pageref{secmpsex}: % %\pagebreak % %\begin{verbatim} %*000000001111111111222222222233333333334444444444555555555566 %*234567890123456789012345678901234567890123456789012345678901 %NAME PLAN % XL BIN2 YIELD % XL BIN3 FE % XL BIN4 MN % XL ALUM AL % XL SILICON SI % LL BIN1 % LL BIN5 %ENDATA %\end{verbatim} %* eof *% glpk-4.52.1/doc/glpk09.tex0000644000062000006210000003226012175147600014321 0ustar maomkpasswd%* glpk09.tex *% \chapter{CPLEX LP Format} \label{chacplex} \section{Prelude} The CPLEX LP format\footnote{The CPLEX LP format was developed in the end of 1980's by CPLEX Optimization, Inc. as an input format for the CPLEX linear programming system. Although the CPLEX LP format is not as widely used as the MPS format, being row-oriented it is more convenient for coding mathematical programming models by human. This appendix describes only the features of the CPLEX LP format which are implemented in the GLPK package.} is intended for coding LP/MIP problem data. It is a row-oriented format that assumes the formulation of LP/MIP problem (1.1)---(1.3) (see Section \ref{seclp}, page \pageref{seclp}). CPLEX LP file is a plain text file written in CPLEX LP format. Each text line of this file may contain up to 255 characters\footnote{GLPK allows text lines of arbitrary length.}. Blank lines are ignored. If a line contains the backslash character ($\backslash$), this character and everything that follows it until the end of line are considered as a comment and also ignored. An LP file is coded by the user using the following elements: keywords, symbolic names, numeric constants, delimiters, and blanks. {\it Keywords} which may be used in the LP file are the following: \begin{verbatim} minimize minimum min maximize maximum max subject to such that s.t. st. st bounds bound general generals gen integer integers int binary binaries bin infinity inf free end \end{verbatim} \noindent All the keywords are case insensitive. Keywords given above on the same line are equivalent. Any keyword (except \verb|infinity|, \verb|inf|, and \verb|free|) being used in the LP file must start at the beginning of a text line. \newpage {\it Symbolic names} are used to identify the objective function, constraints (rows), and variables (columns). All symbolic names are case sensitive and may contain up to 16 alphanumeric characters\footnote{GLPK allows symbolic names having up to 255 characters.} (\verb|a|, \dots, \verb|z|, \verb|A|, \dots, \verb|Z|, \verb|0|, \dots, \verb|9|) as well as the following characters: \begin{verbatim} ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~ \end{verbatim} \noindent with exception that no symbolic name can begin with a digit or a period. {\it Numeric constants} are used to denote constraint and objective coefficients, right-hand sides of constraints, and bounds of variables. They are coded in the standard form $xx$\verb|E|$syy$, where $xx$ is a real number with optional decimal point, $s$ is a sign (\verb|+| or \verb|-|), $yy$ is an integer decimal exponent. Numeric constants may contain arbitrary number of characters. The exponent part is optional. The letter `\verb|E|' can be coded as `\verb|e|'. If the sign $s$ is omitted, plus is assumed. {\it Delimiters} that may be used in the LP file are the following: \begin{verbatim} : + - < <= =< > >= => = \end{verbatim} \noindent Delimiters given above on the same line are equivalent. The meaning of the delimiters will be explained below. {\it Blanks} are non-significant characters. They may be used freely to improve readability of the LP file. Besides, blanks should be used to separate elements from each other if there is no other way to do that (for example, to separate a keyword from a following symbolic name). The order of an LP file is: \vspace*{-8pt} \begin{itemize} \item objective function definition; \item constraints section; \item bounds section; \item general, integer, and binary sections (can appear in arbitrary order); \item end keyword. \end{itemize} \vspace*{-8pt} These components are discussed in following sections. \section{Objective function definition} The objective function definition must appear first in the LP file. It defines the objective function and specifies the optimization direction. The objective function definition has the following form: $$ \left\{ \begin{array}{@{}c@{}} {\tt minimize} \\ {\tt maximize} \end{array} \right\}\ f\ {\tt :}\ s\ c\ x\ s\ c\ x\ \dots\ s\ c\ x $$ where $f$ is a symbolic name of the objective function, $s$ is a sign \verb|+| or \verb|-|, $c$ is a numeric constant that denotes an objective coefficient, $x$ is a symbolic name of a variable. If necessary, the objective function definition can be continued on as many text lines as desired. The name of the objective function is optional and may be omitted (together with the semicolon that follows it). In this case the default name `\verb|obj|' is assigned to the objective function. If the very first sign $s$ is omitted, the sign plus is assumed. Other signs cannot be omitted. If some objective coefficient $c$ is omitted, 1 is assumed. Symbolic names $x$ used to denote variables are recognized by context and therefore needn't to be declared somewhere else. Here is an example of the objective function definition: \begin{verbatim} Minimize Z : - x1 + 2 x2 - 3.5 x3 + 4.997e3x(4) + x5 + x6 + x7 - .01x8 \end{verbatim} \section{Constraints section} The constraints section must follow the objective function definition. It defines a system of equality and/or inequality constraints. The constraint section has the following form: \begin{center} \begin{tabular}{l} \verb|subject to| \\ {\it constraint}$_1$ \\ {\it constraint}$_2$ \\ \hspace{20pt}\dots \\ {\it constraint}$_m$ \\ \end{tabular} \end{center} \noindent where {\it constraint}$_i, i=1,\dots,m,$ is a particular constraint definition. Each constraint definition can be continued on as many text lines as desired. However, each constraint definition must begin on a new line except the very first constraint definition which can begin on the same line as the keyword `\verb|subject to|'. Constraint definitions have the following form: $$ r\ {\tt:}\ s\ c\ x\ s\ c\ x\ \dots\ s\ c\ x \ \left\{ \begin{array}{@{}c@{}} \mbox{\tt<=} \\ \mbox{\tt>=} \\ \mbox{\tt=} \end{array} \right\}\ b $$ where $r$ is a symbolic name of a constraint, $s$ is a sign \verb|+| or \verb|-|, $c$ is a numeric constant that denotes a constraint coefficient, $x$ is a symbolic name of a variable, $b$ is a right-hand side. The name $r$ of a constraint (which is the name of the corresponding auxiliary variable) is optional and may be omitted (together with the semicolon that follows it). In this case the default names like `\verb|r.nnn|' are assigned to unnamed constraints. The linear form $s\ c\ x\ s\ c\ x\ \dots\ s\ c\ x$ in the left-hand side of a constraint definition has exactly the same meaning as in the case of the objective function definition (see above). After the linear form one of the following delimiters that indicates the constraint sense must be specified: \verb|<=| \ means `less than or equal to' \verb|>=| \ means `greater than or equal to' \verb|= | \ means `equal to' The right hand side $b$ is a numeric constant with an optional sign. Here is an example of the constraints section: \begin{verbatim} Subject To one: y1 + 3 a1 - a2 - b >= 1.5 y2 + 2 a3 + 2 a4 - b >= -1.5 two : y4 + 3 a1 + 4 a5 - b <= +1 .20y5 + 5 a2 - b = 0 1.7 y6 - a6 + 5 a777 - b >= 1 \end{verbatim} Should note that it is impossible to express ranged constraints in the CPLEX LP format. Each a ranged constraint can be coded as two constraints with identical linear forms in the left-hand side, one of which specifies a lower bound and other does an upper one of the original ranged constraint. Another way is to introduce a slack double-bounded variable; for example, the constraint $$10\leq x+2y+3z\leq 50$$ can be written as follows: $$x+2y+3z+t=50,$$ where $0\leq t\leq 40$ is a slack variable. \section{Bounds section} The bounds section is intended to define bounds of variables. This section is optional; if it is specified, it must follow the constraints section. If the bound section is omitted, all variables are assumed to be non-negative (i.e. that they have zero lower bound and no upper bound). The bounds section has the following form: \begin{center} \begin{tabular}{l} \verb|bounds| \\ {\it definition}$_1$ \\ {\it definition}$_2$ \\ \hspace{20pt}\dots \\ {\it definition}$_p$ \\ \end{tabular} \end{center} \noindent where {\it definition}$_k, k=1,\dots,p,$ is a particular bound definition. Each bound definition must begin on a new line\footnote{The GLPK implementation allows several bound definitions to be placed on the same line.} except the very first bound definition which can begin on the same line as the keyword `\verb|bounds|'. \newpage Syntactically constraint definitions can have one of the following six forms: \begin{center} \begin{tabular}{ll} $x$ \verb|>=| $l$ & specifies a lower bound \\ $l$ \verb|<=| $x$ & specifies a lower bound \\ $x$ \verb|<=| $u$ & specifies an upper bound \\ $l$ \verb|<=| $x$ \verb|<=| $u$ &specifies both lower and upper bounds\\ $x$ \verb|=| $t$ &specifies a fixed value \\ $x$ \verb|free| &specifies free variable \end{tabular} \end{center} \noindent where $x$ is a symbolic name of a variable, $l$ is a numeric constant with an optional sign that defines a lower bound of the variable or \verb|-inf| that means that the variable has no lower bound, $u$ is a numeric constant with an optional sign that defines an upper bound of the variable or \verb|+inf| that means that the variable has no upper bound, $t$ is a numeric constant with an optional sign that defines a fixed value of the variable. By default all variables are non-negative, i.e. have zero lower bound and no upper bound. Therefore definitions of these default bounds can be omitted in the bounds section. Here is an example of the bounds section: \begin{verbatim} Bounds -inf <= a1 <= 100 -100 <= a2 b <= 100 x2 = +123.456 x3 free \end{verbatim} \section{General, integer, and binary sections} The general, integer, and binary sections are intended to define some variables as integer or binary. All these sections are optional and needed only in case of MIP problems. If they are specified, they must follow the bounds section or, if the latter is omitted, the constraints section. All the general, integer, and binary sections have the same form as follows: \begin{center} \begin{tabular}{l} $ \left\{ \begin{array}{@{}l@{}} \verb|general| \\ \verb|integer| \\ \verb|binary | \\ \end{array} \right\} $ \\ \hspace{10pt}$x_1$ \\ \hspace{10pt}$x_2$ \\ \hspace{10pt}\dots \\ \hspace{10pt}$x_q$ \\ \end{tabular} \end{center} \noindent where $x_k$ is a symbolic name of variable, $k=1,\dots,q$. Each symbolic name must begin on a new line\footnote{The GLPK implementation allows several symbolic names to be placed on the same line.} except the very first symbolic name which can begin on the same line as the keyword `\verb|general|', `\verb|integer|', or `\verb|binary|'. \newpage If a variable appears in the general or the integer section, it is assumed to be general integer variable. If a variable appears in the binary section, it is assumed to be binary variable, i.e. an integer variable whose lower bound is zero and upper bound is one. (Note that if bounds of a variable are specified in the bounds section and then the variable appears in the binary section, its previously specified bounds are ignored.) Here is an example of the integer section: \begin{verbatim} Integer z12 z22 z35 \end{verbatim} \section{End keyword} The keyword `\verb|end|' is intended to end the LP file. It must begin on a separate line and no other elements (except comments and blank lines) must follow it. Although this keyword is optional, it is strongly recommended to include it in the LP file. \section{Example of CPLEX LP file} Here is a complete example of CPLEX LP file that corresponds to the example given in Section \ref{secmpsex}, page \pageref{secmpsex}. \medskip \begin{footnotesize} \begin{verbatim} \* plan.lp *\ Minimize value: .03 bin1 + .08 bin2 + .17 bin3 + .12 bin4 + .15 bin5 + .21 alum + .38 silicon Subject To yield: bin1 + bin2 + bin3 + bin4 + bin5 + alum + silicon = 2000 fe: .15 bin1 + .04 bin2 + .02 bin3 + .04 bin4 + .02 bin5 + .01 alum + .03 silicon <= 60 cu: .03 bin1 + .05 bin2 + .08 bin3 + .02 bin4 + .06 bin5 + .01 alum <= 100 mn: .02 bin1 + .04 bin2 + .01 bin3 + .02 bin4 + .02 bin5 <= 40 mg: .02 bin1 + .03 bin2 + .01 bin5 <= 30 al: .70 bin1 + .75 bin2 + .80 bin3 + .75 bin4 + .80 bin5 + .97 alum >= 1500 si1: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + .01 alum + .97 silicon >= 250 si2: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + .01 alum + .97 silicon <= 300 Bounds bin1 <= 200 bin2 <= 2500 400 <= bin3 <= 800 100 <= bin4 <= 700 bin5 <= 1500 End \* eof *\ \end{verbatim} \end{footnotesize} %* eof *% glpk-4.52.1/doc/glpk10.tex0000644000062000006210000001617712175147600014322 0ustar maomkpasswd%* glpk10.tex *% \chapter{Stand-alone LP/MIP Solver} \label{chaglpsol} The GLPK package includes the program \verb|glpsol|, which is a stand-alone LP/MIP solver. This program can be invoked from the command line to read LP/MIP problem data in any format supported by GLPK, solve the problem, and write its solution to an output text file. \para{Usage} \verb|glpsol| [{\it options\dots}] [{\it filename}] \para{General options} \begin{verbatim} --mps read LP/MIP problem in fixed MPS format --freemps read LP/MIP problem in free MPS format (default) --lp read LP/MIP problem in CPLEX LP format --glp read LP/MIP problem in GLPK format --math read LP/MIP model written in GNU MathProg modeling language -m filename, --model filename read model section and optional data section from filename (same as --math) -d filename, --data filename read data section from filename (for --math only); if model file also has data section, it is ignored -y filename, --display filename send display output to filename (for --math only); by default the output is sent to terminal --seed value initialize pseudo-random number generator used in MathProg model with specified seed (any integer); if seed value is ?, some random seed will be used --mincost read min-cost flow problem in DIMACS format --maxflow read maximum flow problem in DIMACS format --cnf read CNF-SAT problem in DIMACS format --simplex use simplex method (default) --interior use interior point method (LP only) -r filename, --read filename read solution from filename rather to find it with the solver --min minimization --max maximization --scale scale problem (default) --noscale do not scale problem -o filename, --output filename write solution to filename in printable format -w filename, --write filename write solution to filename in plain text format --ranges filename write sensitivity analysis report to filename in printable format (simplex only) --tmlim nnn limit solution time to nnn seconds --memlim nnn limit available memory to nnn megabytes --check do not solve problem, check input data only --name probname change problem name to probname --wmps filename write problem to filename in fixed MPS format --wfreemps filename write problem to filename in free MPS format --wlp filename write problem to filename in CPLEX LP format --wglp filename write problem to filename in GLPK format --wcnf filename write problem to filename in DIMACS CNF-SAT format --log filename write copy of terminal output to filename -h, --help display this help information and exit -v, --version display program version and exit \end{verbatim} \para{LP basis factorization options} \begin{verbatim} --luf LU + Forrest-Tomlin update (faster, less stable; default) --cbg LU + Schur complement + Bartels-Golub update (slower, more stable) --cgr LU + Schur complement + Givens rotation update (slower, more stable) \end{verbatim} \para{Options specific to the simplex solver} \begin{verbatim} --primal use primal simplex (default) --dual use dual simplex --std use standard initial basis of all slacks --adv use advanced initial basis (default) --bib use Bixby's initial basis --ini filename use as initial basis previously saved with -w (disables LP presolver) --steep use steepest edge technique (default) --nosteep use standard "textbook" pricing --relax use Harris' two-pass ratio test (default) --norelax use standard "textbook" ratio test --presol use presolver (default; assumes --scale and --adv) --nopresol do not use presolver --exact use simplex method based on exact arithmetic --xcheck check final basis using exact arithmetic \end{verbatim} \para{Options specific to the interior-point solver} \begin{verbatim} --nord use natural (original) ordering --qmd use quotient minimum degree ordering --amd use approximate minimum degree ordering (default) --symamd use approximate minimum degree ordering \end{verbatim} \para{Options specific to the MIP solver} \begin{verbatim} --nomip consider all integer variables as continuous (allows solving MIP as pure LP) --first branch on first integer variable --last branch on last integer variable --mostf branch on most fractional variable --drtom branch using heuristic by Driebeck and Tomlin (default) --pcost branch using hybrid pseudocost heuristic (may be useful for hard instances) --dfs backtrack using depth first search --bfs backtrack using breadth first search --bestp backtrack using the best projection heuristic --bestb backtrack using node with best local bound (default) --intopt use MIP presolver (default) --nointopt do not use MIP presolver --binarize replace general integer variables by binary ones (assumes --intopt) --fpump apply feasibility pump heuristic --proxy [nnn] apply proximity search heuristic (nnn is time limit in seconds; default is 60) --gomory generate Gomory's mixed integer cuts --mir generate MIR (mixed integer rounding) cuts --cover generate mixed cover cuts --clique generate clique cuts --cuts generate all cuts above --mipgap tol set relative mip gap tolerance to tol --minisat translate integer feasibility problem to CNF-SAT and solve it with MiniSat solver \end{verbatim} \newpage \begin{verbatim} --objbnd bound add inequality obj <= bound (minimization) or obj >= bound (maximization) to integer feasibility problem (assumes --minisat) \end{verbatim} For description of the MPS format see Appendix \ref{champs}, page \pageref{champs}. For description of the CPLEX LP format see Appendix \ref{chacplex}, page \pageref{chacplex}. For description of the modeling language see the document ``Modeling Language GNU MathProg: Language Reference'' included in the GLPK distribution. For description of the DIMACS min-cost flow problem format and DIMACS maximum flow problem format see the document ``GLPK: Graph and Network Routines'' included in the GLPK distribution. %* eof *% glpk-4.52.1/doc/glpk11.tex0000644000062000006210000001635212175147600014316 0ustar maomkpasswd%* glpk11.tex *% \chapter{External Software Modules Used In GLPK} In the GLPK package there are used some external software modules listed in this Appendix. Note that these modules are {\it not} part of GLPK, but are used with GLPK and included in the distribution. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{AMD} \noindent AMD Version 2.2, Copyright {\copyright} 2007 by Timothy A. Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. \para{Description} AMD is a set of routines for pre-ordering sparse matrices prior to Cholesky or LU factorization, using the approximate minimum degree ordering algorithm. \para{License} This library is 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. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 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. AMD is available under alternate licences; contact T. Davis for details. \para{Availability} \noindent \url{http://www.cise.ufl.edu/research/sparse/amd} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{COLAMD/SYMAMD} \noindent COLAMD/SYMAMD Version 2.7, Copyright {\copyright} 1998-2007, Timothy A. Davis, All Rights Reserved. \para{Description} colamd: an approximate minimum degree column ordering algorithm, for LU factorization of symmetric or unsymmetric matrices, QR factorization, least squares, interior point methods for linear programming problems, and other related problems. symamd: an approximate minimum degree ordering algorithm for Cholesky factorization of symmetric matrices. \para{Authors} The authors of the code itself are Stefan I. Larimore and Timothy A. Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. \para{License} This library is 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. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 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. COLAMD is also available under alternate licenses, contact T. Davis for details. \para{Availability} \noindent \url{http://www.cise.ufl.edu/research/sparse/colamd} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{MiniSat} \noindent MiniSat-C v1.14.1, Copyright {\copyright} 2005, Niklas Sorensson. \para{Description} MiniSat is a minimalistic implementation of a Chaff-like SAT solver based on the two-literal watch scheme for fast BCP and clause learning by conflict analysis. \para{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. \para{Availability} \noindent \url{http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{zlib} \noindent zlib version 1.2.5, Copyright {\copyright} 1995--2010 Jean-loup Gailly and Mark Adler. \para{Description} zlib is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files \verb|rfc1950.txt| (zlib format), \verb|rfc1951.txt| (deflate format) and \verb|rfc1952.txt| (gzip format). \para{License} This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. \hfill Jean-loup Gailly \hfill Mark Adler \para{Availability} \noindent \url{http://www.zlib.net/} %* eof *% glpk-4.52.1/doc/glpk12.tex0000644000062000006210000010571412175147600014320 0ustar maomkpasswd%* glpk12.tex *% \begin{footnotesize} \chapter*{\sf\bfseries GNU General Public License} \addcontentsline{toc}{chapter}{GNU General Public License} \begin{center} {\bf Version 3, 29 June 2007} \end{center} \begin{quotation} \noindent Copyright {\copyright} 2007 Free Software Foundation, Inc. \verb|| \end{quotation} \begin{quotation} \noindent Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. \end{quotation} \section*{Preamble} The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. \section*{TERMS AND CONDITIONS} \subsubsection*{0. Definitions.} ``This License'' refers to version 3 of the GNU General Public License. ``Copyright'' also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. ``The Program'' refers to any copyrightable work licensed under this License. Each licensee is addressed as ``you''. ``Licensees'' and ``recipients'' may be individuals or organizations. To ``modify'' a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a ``modified version'' of the earlier work or a work ``based on'' the earlier work. A ``covered work'' means either the unmodified Program or a work based on the Program. To ``propagate'' a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To ``convey'' a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays ``Appropriate Legal Notices'' to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. \subsubsection*{1. Source Code.} The ``source code'' for a work means the preferred form of the work for making modifications to it. ``Object code'' means any non-source form of a work. A ``Standard Interface'' means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The ``System Libraries'' of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A ``Major Component'', in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The ``Corresponding Source'' for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. \subsubsection*{2. Basic Permissions.} All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. \subsubsection*{3. Protecting Users' Legal Rights From Anti-Circumvention Law.} No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. \subsubsection*{4. Conveying Verbatim Copies.} You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. \subsubsection*{5. Conveying Modified Source Versions.} You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to ``keep intact all notices''. c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. \subsubsection*{6. Conveying Non-Source Forms.} You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A ``User Product'' is either (1) a ``consumer product'', which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, ``normally used'' refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. ``Installation Information'' for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. \subsubsection*{7. Additional Terms.} ``Additional permissions'' are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered ``further restrictions'' within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. \subsubsection*{8. Termination.} You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. \subsubsection*{9. Acceptance Not Required for Having Copies.} You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. \subsubsection*{10. Automatic Licensing of Downstream Recipients.} Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An ``entity transaction'' is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. \subsubsection*{11. Patents.} A ``contributor'' is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's ``contributor version''. A contributor's ``essential patent claims'' are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, ``control'' includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a ``patent license'' is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To ``grant'' such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. ``Knowingly relying'' means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is ``discriminatory'' if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. \subsubsection*{12. No Surrender of Others' Freedom.} If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. \subsubsection*{13. Use with the GNU Affero General Public License.} Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. \subsubsection*{14. Revised Versions of this License.} The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. \subsubsection*{15. Disclaimer of Warranty.} THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. \subsubsection*{16. Limitation of Liability.} IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \subsubsection*{17. Interpretation of Sections 15 and 16.} If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. \section*{END OF TERMS AND CONDITIONS} \newpage \section*{How to Apply These Terms to Your New Programs} If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. \begin{verbatim} Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . \end{verbatim} Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: \begin{verbatim} Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. \end{verbatim} \noindent The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an ``about box''. You should also get your employer (if you work as a programmer) or school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see \verb||. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read \verb||. \end{footnotesize} %* eof *% glpk-4.52.1/doc/glpk_faq.txt0000644000062000006210000005151712175147600015024 0ustar maomkpasswd GNU Linear Programming Kit FAQ Summary: Frequently Asked Questions about the GNU Linear Programming Kit Author: Dr. Harley Mackenzie Posting-Frequency: Monthly Language: English $Date: 2004/01/09 05:57:57 $ $Revision: 1.6 $ Introduction Q. What is GPLK? A. GLPK stands for the GNU Linear Programming Kit. The GLPK package is a set of routines written in ANSI C and organized in the form of a callable library. This package is intended for solving large-scale linear programming (LP), mixed integer linear programming (MIP), and other related problems. The GLPK package includes the following main components: * implementation of the simplex method, * implementation of the primal-dual interior point method, * implementation of the branch-and-bound method, * application program interface (API), * GNU MathProg modeling language (a subset of AMPL), * GLPSOL, a stand-alone LP/MIP solver. Q. Who develops and maintains GLPK? A. GLPK is currently developed and maintained by Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. Andrew's email address is and his postal address is 125871, Russia, Moscow, Volokolamskoye sh., 4, Moscow Aviation Institute, Andrew O. Makhorin Q. How is GLPK licensed? A. GLPK is currently licensed under the GNU General Public License (GPL). GLPK is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GLPK is not licensed under the Lesser General Public License (LGPL) as distinct from other free LP codes such as lp_solve. The most significant implication is that code that is linked to the GLPK library must be released under the GPL, whereas with the LGPL, code linked to the library does not have to be released under the same license. Q. Where is the GLPK home page? The GLPK home page is part of the GNU web site and can found at . Q. How do I download and install GLPK? A. The GLPK source distribution can be found in the subdirectory /gnu/glpk/ on your favorite GNU mirror and can be compiled directly from the source. The GLPK package (like all other GNU software) is distributed in the form of packed archive. This is one file named 'glpk-x.y.tar.gz', where x is the major version number and y is the minor version number. In order to prepare the distribution for installation you should: 1. Copy the GLPK distribution file to some subdirectory. 2. Enter the command 'gzip -d glpk-x.y.tar.gz' in order to unpack the distribution file. After unpacking the name of the distribution file will be automatically changed to 'glpk-x.y.tar'. 3. Enter the command 'tar -x < glpk-x.y.tar' in order to unarchive the distribution. After this operation the subdirectory 'glpk-x.y' which is the GLPK distribution will have been automatically created. After you have unpacked and unarchived GLPK distribution you should configure the package, and compiled the application. The result of compilation is: * the file 'libglpk.a', which is a library archive containing object code for all GLPK routines; and * the program 'glpsol', which is a stand-alone LP/MIP solver. Complete compilation and installation instructions are included in the INSTALL file included with the distribution. The distribution includes make files for the Microsoft Visual C/C++ version 6 and Borland C/C++ version 5 and by default compiles and links a glpk*.lib library file, a glpk*.dll DLL file and an glpsol.exe application file. A GNU Windows 4.1 binary, source and documentation compiled using the mingw32 C/C++ compiler is also available from . Q. Is there a GLPK mailing list or newsgroup? A. GLPK has two mailing lists: and . The main discussion list is , and is used to discuss all aspects of GLPK, including its development and porting. There is also a special list used for reporting bugs at . To subscribe to any GLPK mailing list, send an empty mail with a Subject: header line of just "subscribe" to the relevant -request list. For example, to subscribe yourself to the main list, you would send mail to with no body and a Subject: header line of just "subscribe". Another way to subscribe to the GLP mailing lists is to visit the web pages and . Currently there are no newsgroups dedicated to GLPK. Q. Who maintains this FAQ and how do I contribute to this FAQ? A. The present maintainer of this FAQ is Dr. Harley Mackenzie, HARD software, although the content of the FAQ is derived from many sources such as GLPK documentation, GLPK email archives and original content. Harley's email address is and his postal address is c/o HARD software, PO Box 8004, Newtown, Victoria 3220, Australia. All contributions to this FAQ, such as questions and (preferably) answers should be sent to the email address. This FAQ is copyright Harley Mackenzie 2003 and is released under the same license, terms and conditions as GLPK, that is, GPL version 2 or later. Contributions are not directly referenced in the body of the FAQ as this would become unmanageable and messy, but rather as a list of contributors to this FAQ. If you are the author of any information included in this FAQ and you do not want your content to be included, please contact the FAQ maintainer and your material will be removed. Also if you have not been correctly included as a contributor to this FAQ, your details have changed, or you do not want your name listed in the list of contributors, please contact the FAQ maintainer for correction. Q. Where can I download this FAQ? The latest version of the GLPK FAQ is available to download from in the following formats: * DocBook * Formatted text * Adobe PDF Q. Who are the FAQ contributors? A. The FAQ contents were created from the following sources: * Michael Hennebry * http://www-unix.mcs.anl.gov/otc/Guide/faq/linear-programming-faq.html * Harley Mackenzie, HARD software Pty. Ltd. * Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute GLPK functions & features Q. What is the current state of GLPK development? A. GLPK is a work in progress and is presently under continual development. As of the current version 4.3, GLPK is a simplex-based solver is able to handle problems with up to 100,000 constraints. In particular, it successfully solves all instances from netlib (see the file bench.txt included in the GLPK distribution). The interior-point solver is not very robust as it is unable to handle dense columns, sometimes terminates due to numeric instability or slow convergence. The Mixed Integer Programming (MIP) solver currently is based on branch-and-bound, so it is unable to solve hard or very large problems with a probable practical limit of 100-200 integer variables. However, sometimes it is able to solve larger problems of up to 1000 integer variables, although the size that depends on properties of particular problem. Q. How does GLPK compare with other LP codes? A. I think that on very large-scale instances CPLEX 8.0 dual simplex is 10-100 times faster than the GLPK simplex solver and, of course, much more robust. In many cases GLPK is faster and more robust than lp_solve 4.0 for pure LPs as well as MIP's. See the bench.txt file in the GLPK distribution doc directory for GLPK netlib benchmark results. You can find benchmarks for some LP and MIP solvers such as CPLEX, GLPK, lp_solve, and OSL on Hans Mittelmann's webpage at . Q. What are the differences between AMPL and GNU MathProg? A. The subset of AMPL implemented in MathProg approximately corresponds to AMPL status in 1990, because it is mainly based on the paper Robert Fourer, David M Gay and Brian W Kernighan (1990), "A Modeling Language for Mathematical Programming", Management Science, Vol 36, pp. 519-554 and is available at . The GNU MathProg translator was developed as part of GLPK. However, GNU MathProg can be easily used in other applications as there is a set of MathProg interface routines designed for use in other applications. Q. What input file formats does GLPK support? A. GLPK presently can read input and output LP model files in three supported formats: * MPS format - which is a column oriented and widely supported file format but has poor human readability. * CPLEX format - which is an easily readable row oriented format. * GNU MathProg - which is an AMPL like mathematical modeling language. Q. What interfaces are available for GLPK? A. The GLPK package is in fact a C API that can be either by statically or dynamically linked directly with many programming systems. Presently there are three contributed external interfaces included with the GLPK package: * GLPK Java Native Interface (JNI) * GLPK Delphi Interface (DELI) * GLPKMEX Matlab MEX interface There is an unofficial Microsoft Visual Basic, Tcl/Tk and Java GLPK interface available at . There are other language interfaces under development, including a Perl interface currently being developed by the FAQ maintainer, Dr. Harley Mackenzie . Q. Where can I find some examples? A. The GLPK package distribution contains many examples written in GNU MathProg (*.mod), C API calls (*.c), CPLEX input file format (*.lpt), MPS format (*.mps) as well as some specific Traveling Salesman examples (*.tsp). All of the examples can be found in the GLPK distribution examples sub-directory. Q. What are the future plans for GLPK? A. Developments planned for GLPK include improving the existing key GLPK components, such as developing a more robust and more efficient implementation of the simplex-based and interior-point solvers. Future GLPK enhancements planned are implementing a branch-and-cut solver, a MIP pre-processor, post-optimal and sensitivity analysis and possibly network simplex and quadratic programming solvers. Q. How do I report a GLPK bug? A. If you think you have found a bug in GLPK, then you should send as complete a report as possible to . Q. How do I contribute to the GLPK development? A. At present new GLPK development patches should be emailed to Andrew Makhorin , with sufficient documentation and test code to explain the nature of the patch, how to install it and the implications of its use. Before commencing any major GLPK development for inclusion in the GLPK distribution, it would be a good idea to discuss the idea on the GLPK mailing list. Q. How do I compile and link a GLPK application on a UNIX platform? A. To compile a GLPK application on a UNIX platform, then compiler must be able to include the GLPK include files and link to the GLPK library. For example, on a system where the GLPK system is installed: gcc mylp.c -o mylp -lglpk or specify the include files and libglpk.a explicitly, if GLPK is not installed. Q. How do I compile and link a GLPK application on a Win32 platform? A. On a Win32 platform, GLPK is implemented either as a Win32 Dynamic Link Library (DLL) or can be statically linked to the glpk*.lib file. As with the UNIX instructions, a GLPK application must set a path to the GLPK include files and also reference the GLPK library if statically linked. Q. How do I limit the GLPK execution time? A. You can limit the computing time by setting the control parameter LPX_K_TMLIM via the API routine lpx_set_real_parm . At present there is no way of limiting the execution time of glpsol without changing the source and recompiling a specific version. GLPK Linear Programming Q. What is Linear Programming and how does it work? A. Linear Programming is a mathematical technique that is a generic method for solving certain systems of equations with linear terms. The real power of LP's are that they have many practical applications and have proven to be a powerful and robust tool. The best single source of information on LP's is the Linear Programming FAQ that has information on LP's and MIP's, includes a comprehensive list of available LP software and has many LP references for further study. Q. How do I determine the stability of an LP solution? A. You can perform sensitivity analysis by specifying the --bounds option for glpsol as: glpsol ... --bounds filename in which case the solver writes results of the analysis to the specified filename in plain text format. The corresponding API routine is lpx_print_sens_bnds() . Q. How do I determine which constraints are causing infeasibility? A straightforward way to find such a set of constraints is to drop constraints one at a time. If dropping a constraint results in a solvable problem, pick it up and go on to the next constraint. After applying phase 1 to an infeasible problem, all basic satisfied constraints may be dropped. If the problem has a feasible dual, then running the dual simplex method is a more direct approach. After the last pivot, the nonbasic constraints and one of the violated constraints will constitute a minimal set. The GLPK simplex table routines will allow you to pick a correct constraint from the violated ones. Note that the GLPK pre-solver needs to be turned off for the preceding technique to work, otherwise GLPK does not keep the basis of an infeasible solution. Also a more detailed methodology has been posted on the mail list archive at . Q. What is the difference between checks and constraints? A. Check statements are intended to check that all data specified by the user of the model are correct, mainly in the data section of a MathProg model. For example, if some parameter means the number of nodes in a network, it must be positive integer, that is just the condition to be checked in the check statement (although in this case such condition may be also checked directly in the parameter statement). Note that check statements are performed when the translator is generating the model, so they cannot include variables. Constraints are conditions that are expressed in terms of variables and resolved by the solver after the model has been completely generated. If all data specified in the model are correct a priori, check statements are not needed and can be omitted, while constraints are essential components of the model and therefore cannot be omitted. GLPK Integer Programming Q. What is Integer Programming and how does it work? A. Integer LP models are ones whose variables are constrained to take integer or whole number (as opposed to fractional) values. It may not be obvious that integer programming is a very much harder problem than ordinary linear programming, but that is nonetheless the case, in both theory and practice. Q. What is the Integer Optimization Suite (IOS)? A. IOS is a framework to implement implicit enumeration methods based on LP relaxation (like branch-and-bound and branch-and-cut). Currently IOS includes only basic features (the enumeration tree, API routines, and the driver) and is not completely documented. Q. I have just changed an LP to a MIP and now it doesn't work? A. If you have an existing LP that is working and you change to an MIP and receive a "lpx_integer: optimal solution of LP relaxation required" 204 (==LPX_E_FAULT) error, you probably have not called the LP solution method lpx_simplex() before lpx_integer() . The MIP routines use the LP solution as part of the MIP solution methodology. glpk-4.52.1/doc/gmpl.pdf0000666000062000006210000064573212175147600014145 0ustar maomkpasswd%PDF-1.5 %äðíø 7 0 obj <> stream xÚMOOÃ0 Åï| ‰†8®Óö‚M‚)paª--“ |{’”²þóÞïÁ˜X•màðW.VÖhç|Rkª¡ n´mÀŸ±TÁáí4qtnºqøî†6‡ëûÇåÜv_¯ÛyÔ‹¿X TiK’°d$&@!•n$cÿ1ˆqú0‡ñ²·h4KÛ:‹ûIY‡ó¢]o¶wËô¤¬`˜?OÓ¸J-æ/JÍ¥Ëé¢%…Ç7gÞ¯w—+]‘Ûv‰þ“Akˆ÷*Cn<<œýL!K endstream endobj 13 0 obj <> stream xÚVM“â6½çWø(ªÀ+YþâÈ&™Ô$™Ô$Ëž’4¶cYÌÖþûíVËØ,s˜‚*äׯ¥þx-“üŸˆ„ÃG$U_ž4§äã6ùð'‚§k¾N¶;0¯rY§¼H¶íßl{Ћ•”’ýòûóo´:«f‘Uì¸( ¦öÁœ13ŒFçq•3»#Ä_wøã3Yž]¬Àù?ÝD®ÓVƒn‰xé[ínœs¦ô~<³´W2åy²)ÿpQDÖ¼8"Oe "%ãœ/!±Æ¥ÀeÆq™M¨œÐ|Z¡œÐjBë ]_QÁ¯¨˜Ní%Ûô­Ó_BÈ«²HsE‘iA]|Rǃu¦G¯ª`?ilÓI÷X)lAY²Å’—ÛœÏ ­(köØ~RÞ4Cô}²CcÑï ùm^ ˜mOÎýà¿xØåŒÝÿº ƒQ)ô?/Ø¦ë® ¼ÆJƒ¸R–Óƒv¯ˆèö~?,j œ(ÃOvçY ÁAë•‹(p2fAV!Ò%}“.I\… EžSý±3}ÜÏ/£ÉìüØÈ±.º´ƒÛJö´¡_ž Á!-°>Ú¼þsHÌ ”‹˜U"ÌRVel¡„J`7Ðà-NêÜU}KpkïÌ TŸž_±Ú½@Ö'¢6öltÜÇýa<ïDÇ]TGì³ ­{5í5€Cܺ¹™²*NÙM{ ª‰£B¤y¦)ÎÙ9Ôp–9‚7>..Σ ™–ÚB|à€€‚#%öŽúJ^Ò]Å«Ûú¢닆]ɾJÁ<¯/>Ÿ°5ÀpYä:’H©OÈ?ÜW¼sGÇY¡‘1^x`¢ /ÄзƇ]îJK³*ùxXì0"ccL¿ºû¾‹ÈQÝ`iåÊ+^´‚ÅKÁPõ9Žß¥ó°=B fjE¶ÆIÃQ8’™º+f¥j ¸Þé<u—’‡}w¿«w ‹17¡  ÐH rƒM{ýuäÐNôÈ!Ìu 7Íg%FtMêÀÅ\Hóà?tŠZ˜X°„¨™ Ÿ hé@Y°jèÔ©~×íò¾v÷ïK(ÞKÐ&µ/ÈÏdž£”äb0Þ AÌT¾Ÿ·÷ÿ2)Ò¬‚×N^Ó‹qdþùÃ7)n:Ó endstream endobj 50 0 obj <> stream xÚíš[sã4€ßùžœ‡Ý/Ð݅ O,i¢¶fb»8ɰå×#Y’ewÒ"§³e6ñ´ÓtÒ(q¿ïéèÈÙ_Ê ùB™Àæf«2ûf‘}õŽg˜!E¶¸1ž+8Ïëßó‹ºÚéj·ý±øÞ¼Nd•§€ öuh6W˜å—ÕŒ |×Ô³¹y\ïW»¢®Ú±oþ“ýÖÿÒܺÏî¿'å’Í£@‰öynGúA´7q@¸Ã%`Ø] 0׃ Æùû¢ÒËÆ\ !ù}Sß6˲,ª[ûµO\ot9› ˆs0›3OëáyðtÆÓÁK  ðà±ÿ£ ,óµÞ8øõµ¹(žÿ©W&˜æñ“þú¾"{‘ìK1ÀC¢ïëjטlÝ7Úëºq)R>Ò¸ÖÛUSÜ·i=W =ÿÈRäÿhÆÄ_ØM™~®t³’tÈ öÈåùø™´÷*5@0!áŸÂÝLzõPΰÈM›Ÿõ¦X¹€¨–¥6 Mà©%4Uêu"‰ `~ëCG0Ùùpê¦ÞŸö¥n‚ŸM±ÓÍrc±IÑ EÚ#qDH¦Þl뫾!OtU|uQ‘ùQ‚r‰zQ?臿í´W7k#H õ¿Ó8¥E4èŠäJÖ%!¯˜×õFoŠÒæ“‘ÅšªÊO +rO—E ©4Cnq/ë¢.K]Ùì²[Â'%Ÿ@WüºU¨3 I;€¸ õíÇûFo·¦þÜŽ)@” Þáäx! é.¢«@uî]Ô\p4EDrDD¶ B(rŠ!­Di_ í2˜óIÄ‹ˆLIÁ9 ]f´5¿ñf_šíϬ œÕºXÙ}•SJ$˜ˆPG˜fgS‚x¿UÛýµÛ±ëµï3.³KvU ô|1Gb#0+˜è0Sùê9È’¢³éˆ-5…fƒ‹;Ö̳~7“8ßW®™ßÎ/¾Ñ®Ú)†p:M* ô`"šlCÀc´soàÒ®¬]¨j©èÄ}À="D,™;1[ÐùÂs¿¨ÍBjÃ~¹9„‘³‡¹€M1È¥‡ý³-`–ÝÊ|w§·Å?.âñ;—gÌ;¢C<™77åI nåyÝ»;³d†ú½¾o{ûv¦©ÛR’ifÀGÀÈìš6ð¿+ çfeCþÎÆ»/Üݹq.dë½:ƒÆçø#I”|8M¥4Ä>~þ,k0ËPɧžB²šH‰ÔÌ`…›<Œš®§0U›ÇèÁa±p·‡5š mzð6=x—‡Ö‡ÓÎ7]¡"RE2YVáœÞªÝ„i™?’LÀï— Fq8}'Ý)íeµÖ»sÚÁê`óaY­ýM1móM89$6߈ŸÑ±ß¤#´¤ˆ{Òá˜õJïµõÉt—Ø EØ8¹×ϸCݺüÞµ÷]ìoµ=³“„œ­’£W‡Hw„i….iº…ú@¯Ù‰a/+^?“;Ž€9âä®(SȘä©´C¯žf¤g D˜é¸y†Äðg>ÄÆ—}©ÉÁÓz8`‚ìÝ9sŽÈ_¾øòZÁí endstream endobj 96 0 obj <> stream xÚí›IsÛ6€ïý„Âë@P×:¾+´€jnBàÆŒÿíÀ/¯Ì•´’äNR ’~t,xŽè„'S…f–½Éf Æéåu1ogwr/™yÉ‘pîÓMP0æ± ÒYÈNP?mWyUÌ{V].ð‰ð}´$Ó)@|,l©¿Ë—Y7ÝÙ[”SÍ;ìÇð ʳ'c†?»'ˆE4uÊÍÕa§cÞ; À›CÛÕ:«íþäB;Ÿœó –'–Ñ„fF¼+%ŒÉæpöd~›n")€Ûçr—në<«z²M)ÏpßõЈð€ãcC¸‹ îÓÍßÖõö²žWÅÆ¯Àï'Œé…¡È.—¹$°8÷D³Ã«hàˆìy»Dóâ#´ ⟮çfï1@a¬‰æØÂÜõ•xìt¬%Ç–í¶¨’zÖlLêãqwÐÁhÞ\¢å~ž'ÔÕ!½OÝ•#\H!Ôêší6D‡vCXˆqMz˜©t[ý£\å ™úiÝsUmçͶÒ2ÊN9@ËEkôw4¨Ä€…¨1¾kŸËþ›1‹¬ÉÚéª*Wí«b½ÙÚÆë¦u&?A7ã'wuå°xÊŠ››=eÒRþÃŒøªh,iìIk¨¥­yo šxÐLžÓ ÓAGb Ü C×áÂÚ ÷[Ã¥‹ÜWJ;ž‡×¹;L£ë@ŒPÛÙÁ|ûu¹;ÇpF:ÚkS‚(×ú¹W¡èo“xÈ4ºĨp- Ì×µý D0r¹lm¹­-fã>öq¤4º“qd›G´4ßóôª®‹ëõýŪÊçeµ0ß夣€>ž%n:c‚º.#À7A-‹y~ˆ?—ê%œ½>›†€t€)VÞƒkˆº(V›åAfC4B“F÷ëpˆ\Ó‰1àz£ÞfMUÜ2@9=åÁ´Ì˜è‰K軨´ öŽ_¿ø©êU endstream endobj 123 0 obj <> stream xÚí™Ksê6Ç÷ý^Ê T½--IïLçf’[h7m(ÄsMm“¤ß¾G–Á&Á0}Üf,Ë>óû‡þh@àCƒˆÁ—ÓE0œßÿ J°!&˜<‚b!ƒ» ‚ÉìW$1Ã2P*š„š¡"ÎÊe8`ÊK; œs´ˆ«"yõãY\Ån$Pa§ywD„ „1î ýÙ·~ø}òcp3i€ýô©óÈd„aÔeFÚénæŽITa®‚XÒ†3Ê„1tÛ¸ˆ¶²Å6SŽÒØk4u7} FËÿÔÿJšæÃÒ4K€kLÖK€cÚ,«²Læ™÷ïV•µ§K#.üwðï°d}ùKŠÕfi`Öð§ÉÔîïô·aþØw¼ ¢½UPÓvðF…û4Nö.n¢K,Ú¯B‡ho"£¢›ã‡U×Y‚íȼš‰ ü.ü$ïËÞ0ÌäþÁR¨jÙU ù!j¡´Þ )‘Xo@«m/H²ù[/Ì (<¦2/ß®D7$ÅNúQgû9ÁÌǤ+È¢œ ŸKÏ[sT®~#T½Úò€!Ñ–!ÒKÚ>XÊ^–H¡;q†.ŸStW.ßkâlæ-ª’…õ£ÇU6­’<;ɶöURõ­×©Ò˜ù2t5¡¦Ý=T ÿähº* ›¹ò¼j.Ä©Ífëà7gã²'xgËððšbÝ8†+øQ^c~¡²EÕ*à®>A5m(†JèO×?W¹»taJœYÑ×wm!xíæüí·0ïWã i·à¤îð5Xóz„…Ih$$¼´qîŠä9„ˆl‹S‚\çñŠöÞ”àPéûü1ªƒÀÙÔ7éºs¦¸NVeø‡Û‡ø»6'ZÜGh$6¬Ñˆy^‡Wã›wUb‘ºÈsôÞц´â½åQ‹¨‘‡{y£wÕ‘ì¢ÎÑê´ P'˜¬ðêÜþ9þòù]yt$þ•¬sº´ˆU¯ÊŸ…‚×N¨Fã<}Þt! WM@6´ié/¼$Õ“ÍÓe™§§$Çö•ªW²æŒa#ê g#èNo^ãÅ2µomô ËÌ–Ó"Yºåë:/‹zÿŸÀ¹ÂÂx ëÔ-ºÍë- oß6«ö÷—"©*Ûœ¬÷õnãêé¾È¿ç½WÑavhI0i\¡Î¿ú“Ílíj³ôùÞ—Eñdá±&YYřۄø¿ZˆëM^q,×.Î=ù;ðæEœns‡ °òN®¸¹dÔÞ¢´|÷ˆò6*j‰ß컚†œ¢¯YB|IílnXà¤:¥{é<9ýƒqêöª‰é›´ó廿ϴiº endstream endobj 135 0 obj <> stream xÚÕYKsÛ6¾÷Wpz¢¦J3i쎛¸ÓCÝ,Ñ2[‰TI*©ó뻋ER‚#Çñ¤íÄàbßß\FEó?š R–;‡‰Ž™ `¨¤cȇ½¸ÍïPÇ>Fáöœ£èEƒ*Úx ·“–VÞ4eΠIéG0•~¸ H­}Pê-< ³0+ÛŽ&õ –†¶èˆA¿Þv¶+6¡¥g¶Z’½ƒ—¶³äÄë5yqÿÄR8É]9æB‰T3aâ;zHFÀâ®u™+U|ÓÔZÛ?™Åz¢pñ9ád÷Rœ›€º»uÉ+K¯Ü®ßMîíÉz{žÃN¡z‡mCñYmK+]ëbÀK–1.|Êw ÃVíÚŽÐ5ΰ¬ÈçÀÙd#‘˜µiî7z$ÓD±Ü3Ú8<º\›Îa”´Qʵßk+»¾{[´ƒ,÷c€Í}~zLI™±<çƒ3Š匫F]C* o|Pv´îq^ûUú¦rð5ªO-ƒ)‰)´kŠ\%S¿¹-]šÝåÆöYŸ ^ömáÕóú%¬6´J•WEU4¬ŠªYB6irë´²(ÝÇÈWepá2“&%ä¼­Íœ—eS,ºõÍ®Qý;âf÷<(ð8é¿Ã—¹@ßSôÚzýº…Xr&TŸ•5É«¯;[RRΜBŽ­uq˜4àb0à½óa ¹2á åñéMßN:§ f*Êû£GªÑáª$ã³9çBÅg}õN=J ΣÇ&õE4þ{Ì¢&£85¤ìH ,\ÅgW3"‚ˆ%ÄW—D`ýÚM½†bnzÓ~éÔ†%TÌèþl)7åÛ¢R{ùû·[‘dçã"ð8Çj”›·ó¡Tõ…ã«ΙîëР§\ðdFެ@#£=ÉßG< ¦Ô1IeÁ²§ø,¨'üâÕS<ž"¬§y=¿„Ì…b±‚ɹ/©6qÝUˆ…f&`÷ˆÉáU0‹ó”JB¾‰÷4WátË™É÷þ T0–Hÿ˜{ØÀíÎ09J»ƒ²•? Äzø×Çè§Ûˆ-ûûCÈ·™gœpÇøìÈ𔩂ô‚ã]%B¬™Lûã÷HŽfi:–ô]6qpòT3TâD&€¢Ù»5c⑊žÂ*(ú€”•!¬¦a¬*¼µ$`w*¥c0‹>uï²:d²ž G¤H5Áx¯Ê/¡”V§…9Ïs¦8ŒË lÈIƒØO /çØ§°!ObC~06¼¢â‘Šª€WCØÿ5lLU~6äIlÈ“ØO yÿEnÏ‘ñþ½\kÈÃÆyxN-ºÎ$(~t+?;vÀØ661¼ºÚcAI¼ ù¨?Áï»Pª€Ä“V¤µâ×ÍÿLßÏ)A(Brùïaqšò*ÉG 0ei$8¾$>É­SÜ:ëRûžÉ¾«…=‡zW-Ûñ[²Œ_Ï4¼66¥…Ë6lpŽ%kY昮K2aðx”wu¨žÌߘŒeâýÊÉî¡b¦®áZŒëéI¯ˆãñq¼>fxÅœ8eOH/3>HÖǨ:ð䇡Wxò½«Dö8W†^彯¿<ƒ÷tõ”UBú*ñýeôWÄdžEoÜ7—XˆhS&öóuô*úÙ·Ê$Tá<ͼaÊ}s1èïÉ7¢UxY4®«Æ Ó9Ðæ K¨r\bÇK%yÿ¥&uÄp6tÒO\ƒ W-Má Ú} À%¬^8º>üúüâlʃA’é4~Ž]x¤xvvñ‚(ÊÍÖ÷賸£ö7­{yxÿÆ.(mÑY sзôEËí‰W~lí–Z»M ®wà©Ï‰—3-âúz¦%£M2‹˜¥X¡|´ï”Žý©Áçù¾#Àú¾Îwöu¹$®ç G𸽠±Ì°¸oò#aÿ%eÊ[è!¡¿Ó¢"î¿2_MU®nm‘)ìLd\]}Ms—òý§6\:rf®ýí(Ç-n‘ ü®5 ÈÅÐ;eŸ†ìo.ç¶!®×ŸÆ¯eQ-ðëD²!î<Ò`“Z ó<¹š}NÓí–ákžã‡Ì ,ÆØñ†;Q ÓSþüÉ?H endstream endobj 139 0 obj <> stream xÚíZYÛÈ~ϯPö‰BVöIÒÇCœØ€6à ³û²ÊGâŒèHÔ˜Çx&¿>U]ÍS­cìÙ60ìf«ëøªª«ª9û2ã³þñY$à8[ífo®f~§f=.¤Áý\+åéõ6«^ú›ˆIGøßÞmµp¯óŠö¬7vsì¯ç ­ƒÏÙªÎïçÂŽèMSÀ̾ðÒãB2©Ý–«Mƒų‚y–Ä…`†´çÀ\‚9¡)˜rªï(pó«ý|!â [†Ü,ìnÀ¯b:*’iMŒäY¿©ýf %‹åy•I» ô°3ey–½­(îlE ౨ê”8p¯²rGï–ÁrYmò›ú‡åœÞíoèM÷s¯è°ð¤© ³°5µô@(Í"3Šs¯T°¶[âÛ°(>E#Ò~fHSO‹œOXÛ„ƒÏܸa±îY ƒíZÐÊ4w°YËR¡`¡Yš_DæwÆÊt‚:'^?(+bJ•uÂ1å)ßOä¥$Ä$J%§?‡ ™ú8"|;€Ã‡†@Ï£¡ ºn÷¨Ù¯stõ§ô ƒ~…s×6ì›bíÇ€+@®ágŸ†ô³€ .%ñÀ'ôÇ èo¡¹»£`[ÒØç"âN¬‡.rm=ä8&*DΈßí¾$@¢ÎÆ)cN‘0O…DJùHDÄâxBÉDFÿ¡(âi&n!¥ºN(:O`-¤Cút:Ä•f²ÕSãKŸÁ;Šè õûAÑx“Í  ˆ

-eÎkB)Ä‚ÇLÓ¾oÜ/…í/ñïAšJ‹5=L|q! fŒX°‹ ±ô&£œ]ªÈk7JíZŽFçÚvK[¥n‡¼hWƒ’‚7Y•¯³ p ò‰=N™°²rñqx†Z®¢dÀ ²/Mº¥ÇÚæx(cYf©y_¬óâ–ÞUßïcI2ŠTW<$ËfœPj…+oö[Çr·YÃÇ;:Ö+š³Ä‡À+ƬáPÌÎRÒíPMëÎÆô0W ³Zh¬½ðÇË0 ¹×ž%f$dϯhÿòûWÛ•Šñö€þ“‡.$²­søÜ[‡hûôþÝ<–A™eu–Acïƒ}¶¶ íÄà}",’½p#õèTmµe(”¿ºb\vu¤e˧ÁY’<~A´’Y‚_ózÓ‡fs,4{È.8:ÆP OÃüpG!.P˜˜Ä‘¨PÊé D=úÎÁmž îÃ’¾oò øÛ¾ÑCÿ^óV^y__*¬ò ûú{%}—?lÂ'ÛÄf 64 гD?ÅhÝs "t±]óÉ+†dâb·èTÍG „ÏÞ”“ɸï1ø{NòÜ&P_‹~“Wþ<ú\´MND!Xl<ÑVžŒ¶Û¼ÈRçˆ7ûrç5I‚ FÁ惇?ÎYh<.ôÔ.Dí}a³˜œr r©i¢fñ\Þ–YZ·ñ³Þ`FdsÆ’Îr— Ù—ûŽz¢ù†ããwÀTžÇTžÅt¼‰ö@*/Žõ?ûR#Þ·f/Ç òÀêI ýæ~˜\‚Yò¿‡Ù‘óYAÉrLã:—C£Ž@óú¿u—×ß ÊÛsnä*B(wlµ çXNB¾¹^çØáÆ‘¢2þÞ5XIáÓ‡On¦Üö»ŠFÓzó©ÜßÒ(ÝVûöÉÕ]í¾£<_9v²[[Bšþu»ß–énG%¢Áã÷ãûOpÞúËÙ–ך ‹=ûXíwÙ8D¤Û­§)@šêêE¨yë2_Õ­A£ú4Û-IГ€Uy‘–óXÔkx{E7‘<œq°eÜU¤ŒÀLèTcbç‰M"%¬3ä2Òö&Â{QùœT!4çGÅÅÙêvtwc·Ç1^œ(.a¢Z•¹oíÞ¹­ð椢G¬Êqy•Õ¨lœÞ¥TkÚ‰QÅnç¦ýveꪕC@ï_zlóNl&ˆ­×¬-~â‘§«þìñ5wÊÕ³®?gslÒxukö½è‡®iÄãfÐ4º¢¾TdõB:Ë.éžbݬ¨q¡PUu¾j¶©[¸s+²-­ÔÆaí6uMÕ6PT°M‹Û&½u£ª†$f×Þ‚ØÞ‹ Þ¦­Žp“dލ­B(놭ïsÙ…’® ¦?Õãno;]¤èwø4 ·lŠüK“miÓycËêII'ªÒ#N‰¨mýà+šh}°p*LÀéU™Ý@(V¨ÁƒÎ4ê7í«¶#Øj¡ƒöãPoztÿLÍ·ȯ¶ëŠÁ çøÆõýä°ïP؞ضÎ×9`VAœµ 7†\¦6fW4¾nòmíèâü}×àÓè™ëìaDÕ¶cªY gxÄÇýçìo_ÏÕàK2þň[ÛOk¹õíŸl)ÓOÿâ?ÀãÑ%¿tãÃ.½»É^x7ž¢!ßGvm]ÿŒ1-ç¾Ïžþ´ò¾d«[(ÿÅS×™zéÛ"ŽXÔÒXÞÚ a&éøõœí}ôRí¨t̰WbêÐʲP‘8&¬ŠØ 5#üw,låý‡çžÀ$ž/%Æ&úBñ“á,„·/èöÀ×–…‹÷‰øñÅ„ñQ6âÜ{#"LÝ{*Fcª´j®ÁÇð™®pŽNTxø+õ¬ÊÑÝqxWº¶YÕ4Óþ¢wZ»'… Fd[´¤¢¿i·¦Û‚5žeѸÃÝ:¢ýf— ¢1É48&øåFŸàÈ}X#‰>XÛ±ßÚÐÇ7ݱڭ?<_d’¦íÞ¢¦ ¸Ãýb¬÷;<ó=9/Ç˵öh%kGÒÊ`¬ e ÙÔÿ©V2ÙÓ¹(V7w˜é‘IMy§ÉeàOð»P–{n1Ýc—˜l0ü´çåÄÞû?†ÞE™ƒªN›¯v—ÇÎñæ£<ØÇ”Àé'Š5nGO÷;eØ}èuq09ýMÔ7_:æ¾ûß‘Œ…7šsŒü»ƺ¯[Ñf™&Áwм¿9Rv_Ëþ¶šè+å…21æ@¢@á+æ£ðÃIø‚™Ô]-ôI·Áï'qAö®jLèp°/ܾ“HD“K›¶© 0!¹¥µYd +G\š;òyë°!}6ø ¨èY*ìw@15‰„+×0g΋¹B"YÛ£çÙ6Ÿq÷á‰TÇ-ÝØÑ½ äHËJl3—qÜ—~£v%”ë5,Œ¢>^Ô®üûþNÚG endstream endobj 142 0 obj <> stream xÚWKoÛ8¾ï¯ÐQj–)JÞ=í£Z »-ì¥í‘èZ…d¥’œlÿ}çAÙT¬,‚ák4~óqf˜|OT"áO%E?™T]òÇMòòµI”;¹Knö‰ÊÅÎ$[œ°ÉMý)½9øÍVË,6Y‘þ¸Ûl¡ Sýž[7 ŽVyØùG·,:Œ<Û„¶ö“ºæèkßF_NÏØ¬ê‡Á¸T¦ý±nŽ_î=MÕ¾ ò°nÓo¾š‚•Á€}ß¶ý&³éÃøëæËÍÛDi%²d›i‘ó™ßŪ´fUyP¥äΦ¿Ó‰-Ù­¯NLZ_Ý$ß¡weò(S°êReÒ%:“¢´ó¸M>&V\>2¥0ÙõÑO¤º0ÂîÀ“8÷ªõ?nÀÜÉsïZ×¹;†/¶üÉVÁsúî=ìס;ÀîlW¦Ÿ–ÇàÇvüÑá‰qѦ}Kje¬ñßM©Acãn[ÿ3ï7€i,iè«?ûã8 x0°ÏX9«*fUȉ…Ü•iÿ\ØÜã)<ž"—׺ÎFYäwa “ä Bœ#>5AÝ©çvð{žÊÎSŽ›;7LMuj]øbIR˜xÌ$ÖK×bM|<ô§¶æþíù¶àFQü¾©éž%Ít “¼|]F,32V/§Û±š»i ’1& ‚‚11Öˆ]#ýI€”1Z¥þ?×ݵþŒÑf”*i-JQÎÛ»•]¡ìçu !¨×q“më¼76ýg€wF£Dí?Ke(Ôà°Gh٧Ú-™„û˜‡ÍÞ‰<€å™ÐŸ¥ÌÖt(%ìŒÒÛ•óÀ«Ç–gü±òl*òÛfÏ'›™CÐë,Ç[AQÇ2uT™Viªxº$vÀàah¦É‡7®ž#+.î^sL.ŠÙ/ŸÖh!õì·ß lZàíšµ(æm¾$Ó‡@±¦Ó@ï¬tÅ?öâŸuçH¡¹7¶e'Ô™ŠÇz•!JHD¾­DåÏ4àÿÉ!Ðëeúfb7Rò_ŽlƉóSO¾f‰éà&–+ÇñúQÀ<À´I<Ê,4óH.¯ÆÄ£§(‚=ŒgÚD‘BÌÙŽ˜‚úÂm,bp&­È8`*¡*3éÇi8UÓi@69gvh1ƒë,¤]מ·CֈÕJ¶Z³GñüfÇXA;ö à$8„PÚšr ­r`–t”ã™.àJf Ä¡©ðb^„Pöüe0õ'Ú°LCM²Ðø‚ãnw.@dðßO -j :i¼õ!½¡Dí&N(ÅÎŽÙS*Î!z¹ upd1Ôé:Q :Š"8âC–Ñå‡ÁØ·kÖv¹†ÊÏ$‚Þ`bü‚Àž¥³Ó@Îñ@nìóÞܾsÓáýÐe}¤’«ª«»šx†½‰´˜“÷ÜNT¶m˜û:DE¨â¶Æä´Ñu~S¥Ò†[&äjö,Ü¿7TOÌB,£pÀ¬nbd#ï=CwnEY,s©Î¨ÎÛªRä:*½M¾,ma<ú* ¦»%ö¢,×~ÐClx‰à ÑÄ‚â0^ÂO’Ìò O –62 \A|q(<² ë·=|Íਸ਼ ž À>9¾ëf0áaѵsiË\²·nôáóù>"éYy&ÀüÅFÆ}¶ñêVϾ´&ÂÛC-ZÎãž`£H £º œ…¶: /¢þè$I C@/ΠGÆ@ÉÇgòFSñŒtžŠ‹Âó$æ ñ"ùð›aT’ñV9íÈ¢0|R|ƒ^8Å=ÞWlBù°]@EÉ%*0fB@'œzþ Ÿ+PU4ß<•_z¨t¹þ‘“È^ÿ2ˆ"&£ ®*§¯°¥gèþÃrLá{ +ÌÉó2 pk˧[7q ý½wœèpàèá GÞî@¯æ{Çn¸mà3ü`qBŸdeôÀ¤¶W •œÈ"ÀFêðPÑ:‚§óe¢§Âò:PVóâ"vèóåX–q¬ËðáÍB4ESÊYòÃ/?‰nJñ endstream endobj 146 0 obj <> stream xÚ–osÜ4Æßó)L™`×ÿíK™6mhZ(”-ÐF±uw¦¶u±|¹>;Z=:Çiš9—If~·Òjµ»Z­l[¾å©?ßJõïYym=˜Yw|+ðÜ$ ­Ù\M;S¬YñÊ>\²UÇÛ‰&‰L^Ïž(íÄ "7ÍR£+a m¡=»(›­HíÚ ð rÁeÞ–«®±Y¾çN½)Ùòcw){™ÂÞlÉÕº,Òv‚ÔØQòÐŽ(%˜“b¦æ 3næ°ªØn¤ã—~ÍE[3ó{-á»úyÿäðX;6¦'ʃ%kYŽ„d¡-yçNœxšRž0!u\Ž ÅÝ8Ò¡\LâØfUI~…ü •:Â0D„™‰PÉ×#T¬åï,™‹ªäÔFù| ÷}4Ãy³ê¸Q`9Aä©#Ó®¼½UÕx=ÐeÕjÉÎtòyWæðàZ&ä9I?Xò{¬ÜW9 bûp<"ûÒ·Àcàx<¾¾ž??ÏŸ€`ü ¼^¿¿¿é€®EÀ0sä@pD0‡´–@ ü ¼* @+àh tÀ¸6À%°þþØWYæ¦ñÈš¸Òmèø×5oQÁ׃÷| B B6cH 0ÝV„®?²Ôºr…2ÏKVý¿:ÿþÝ>>>C\§6ÄÓ ø9ðð%à.p8î__߯€×ÀïÀßÀ[ààß})ŒS7™Á^u³,;îÈËMƒúÐü˜ûûØÜÕCsƒŸ™;ÿbfšÅÑ{eI%ší˲[R‡ TÛ–]«[z©›§lY%!±¦€J.êš«ªNìNO©f«¥-„áC@뮇§6¿ÌùªÛ„µVT0‘“Ø/¡Ã×»PK'‹ýãàö­'sã± ³ùþíiL[¢hY.šòÔó£œé«JoT’fôšnIK]X5¡ÕÏt\£kI¯& Ï[Î+£»kþÁfBÚ\/öìŠ_–9ݽ¸);ãL'n¼8ß²^µúÁº˜`× ì–³‚•êhhf‹A1'Æxëh`ø<ÒÄàyTÑEÔßut4‡´ªE꤆š¶hF$_©vRŠVF(daÞŠƒœ!ï7ß¡œlQðå¤sô‡‰ê%€<ÐÞPJ¥b‹>Ú èbg†u¨ˆ]*ûª8ÙâhU㕱°ç+Â|'Ñ× ùùš7¹ù²Æý>$˜lèÅMÞ{¾@ÌW9]ˆ¶ärßI”®ïk2]¹­iG”¥¨ð…vÃj.ïíÙ2öw:òeèÞxðv}dï~ª#e#ûè@wײôYŒÝ*R_ááÈ­®tßPh|«/¶h‹ýÛ$±›Œ<´®*Ȳ¦Höo%n4öˆ®tw-\] Ù7Ñþ=˜í ö¶Êów*»bÍbÍæb°Ým.J™¯¥n&$šöiî€{«¿Aè»Aj9‰ñ¶ÿ‚yþÑØÄ^& endstream endobj 149 0 obj <> stream xÚ¥WKoã6¾÷W¾DÆÆ¬øÐë˜R´=-6·¦™‰YÈ’#É›øßw†3´-[Iw±ˆ’Ãáp^üf4{™ÉY r–)øÅ³j3û|7ûù 4#´IgwO°¿”±(`¾ú;RB.–R*}Ùo:ŽKøßÖ®‚I–DM¹±ý⟻ßAŒ™áÁ¸@)2…™-U!´ö’n˜)?eR"3p!î÷ûÍã"‘,Úh=!93"W|¨j›ÞõCdµO4–õv]‚¢*‹ìà¥!±YѤY}·±ídQ…„uÙ•Õ`»þ/Ï£am‰ý>–¦ë‡ñ ¯kG§HB¿nw5‹Ç{óˆGj‘Àÿ¯ð™jΘ$º©kð¦ÖèK ìd ““aj¢²³D[Ý®©ZÝGUÙ[bé-8ep_Q’½_öavâCŒq.ŠÌí[¹ÙÖÅÛ;N‰3öG ¤Òž;>µíníúø•‡Èöþ„cåcõ •|?eŽŠ}¹ôz‹½aLJÞ@Ú®·+" -ne}¤÷´GЉ6­ÍÊÖÄÑ‚à$‰þµÕÀâîÁwƒÏ€ÌD[Ȉ )‘éèë"Aÿ»òœÅ4LÀ¡+]T ;[r0ýä*ŽK¿ Èù¼ôÝm¼¹{\ªÈ5+WÙž¢wáÊ)'3È!c`zÙ·Ên‡‹ LfO/†%_ìõà 8·qrÛ/v{ÙÙk\$‘sYgôppÿÔÝþÛWÛ.ßqÑàÚ$Äùñ5Á|]¢fä2¤dQÓÒŽwizˆP^ݰ¦ÅrÁUeÍÇÐnP1M Ê«Ô[“†¼Š‹C^ÅüÎa$פè®9W³`÷Oä<9‰ŒúA¢ø9y _|ÕnÉ«×ôz_×6‚n™0 7Á9 ^$1h9 Þ* þºÄDLƒ3`òÔv›‰»R0Fò¡·7f̤fŽÛ ‰ÈÔ¡Îì§m"‹9—²t.Šä\›‘,#✛Xâ`BíY¨<¤LGû”»ÈÒnñ%`Ú"}e+·¡ ’O”–ÁæzB7ûÊÍ–Nè– £ªù—hÒX¤Ùè)’Ó=7Sî6R¨ŒÅ|š¸2'l·Ýd¼´ÐAÍ儈—>Dc"!DNOG²LŸF@Sà 4ûÆ.m¸Vøz¬¡’ñs«í€Ù ÔI‰vͨHÓ6W|ŒG¼ÕXjO¹^”ý¤^y&’p±ýصSÁÒ$©ò»û-ý#EþÉæ@ idR\nÀu·Ÿ’S:ŽÈòKf-@A»Ì¾¥8¸ëxc@¥ÆÁ£mKcg·í9!¸ÿ:m1T/»’ Ìà|Yá¬a¸Æª•bÕÊCl¡ZasíŽÀ¶ò-\½±eãšç1ݨLÄcº]ùÐÁÁïôºq)t°#ÈU* ºœFôT¢VÇDW…kªH ™‚Ú×TWÆ×TËîÑAËÔí‰iÜ}Óy8T·>0xÀ6"N"7ÖO¤õ ]Í‚_ví`{Úo;¢¾U»ƒn€.ðS§ÙDu‡Ÿ[ÀTvÃ;Å‚4ÎPîe稬1IrDÉí·'ªˆ% Aeœû›iêÁ!O±ÝˆÒž ¡&1m½äå4çפl Ö³š"hè`~XŒÖFæñNËveª}†”®÷‹\G×ÔºðFßF?g³q×õD"³q֎ϳq~0G³½œækèC®ðf¿Ñ²Ñ7Ú_¼ ²€±æÜ?ú•$ +ò_á×t°ð†iôñÆ ¿ºTn>q¤iémÎ/Â]åpuÅg˺ž>Ÿÿjëº%j¯çs\ºÍ|g€“ªÜðÕ#æßô2øaø¯cãìÆ§8ÕK©­]¦&§bÖ¿~úfÒl¥ endstream endobj 152 0 obj <> stream xÚ½XYÛ6~ï¯p ·+®(‘:r,Ð#Ú ì[’Z™^ ‘%W’÷(‚þöÎp†²d)ÇS± ðÎh>¿zõ÷J®ø“«$„ÿ`UìW?ݬ®ÞJ˜S"Rñêf ë¾ DýÍ;/jíK*ïwóô°Ž¯i7ÝúÃÍo°M­P0Èp—Ô"S+?ÌDÙ?²P:’" Á®}M»ÖÒÛ,¨SR(É’e·ö£(òrj:ó÷ÑÔ…Á‘òš-/V‡]~»öÃÔ3}YÐd±o—·yÑ›Öi©7Ô9Xá¦ëÊÛê‰U7{Ã=Z5E™Wƒ®ø¤KØoöu$ÂðJ…f¯+WàÔG4¡ „ÌÎnsZ½²F¾ÁQàõ¨œdi¢È{s×´¥é^,á˜B: -†¦3í½!4}Ǽ·x\©Ú)¸„ià=ìJòÑ}A]7=},â ÞÐàØ™ y“w4Ó=íÑ’j*PcÁ 3)t èDBkk©Î÷¦sQœØs˜{¦S¹s¯›Ú·Lœ‹ÒðkÎÉ Q|òͼ‹âÀË[<èXz­)š»ºü}Â…[z¢~ÑÐ!™ÇžwÙØ]ýδfÛ8%€u p@@a/§¯ôe¬DœŒAt6ª-Pc|±N!v³ãm-.6ÎlH‡tñ4èp–|­½Û¹mªªÁe}çL&#3{}™Y«î¸âPDš¡5Ug†I‡÷¾™ ë $ÒD1A ìâíÓL¾ÜÎÔb,ž‹=”ý®\ÐKÐ-Üí¹êz¦"‰T„J$r¬bSn· €fJà éEM÷3E•}ŸÓgT/„´‚Ê@Ù‰C+ù^¥`ÞIæ!yÓmÉ<ÉDXÖ“¨ })z8:Å`ÆtQ–pTAgNy8»Ëqú'­\콤z´Æ³ÔÛ›¼sÈA2â[šØ[ ’%I=þbRiU^Ö¤ܬ©Ý”]q:§qJ©拦œ˜îë :G§Ä7kté¾ÅÓE ‘º¾= —„×^þ³µà;æ;Raøæf9冱aÊ9WsÎýÅTå¾´¹ë‹W})ãF‡ÖÆi[Ê·Z(5Ê·ay¦DšÃ¾ÂÜ‹MàU†–§)W'é–„š³ýCî¶‹[šímÐوʼnðkªùûòŽÖNqÛ-r™ŒE(‰Ëà`Ÿ†äqq(óÕkî\Ûé=Î/xâ·ï¸½¾nÄ>>«ý‹e^sûêš•}úÄ—¼ò/·œ¤?×zÁZŸ;­î[¿wÁ+/ÜÄ{aÐ#ÂH‰Ô…Âv 'ŸEFÆ¯Øø+çö`œ'.¹ÂÙ^ÍöݽEA"²hLo¿ra7\±SøÚ«‡7³ìz¾i® œ„’½À“À¹tº›ÙíšcÅDx"Ô Ùéyaº‰€3]SŸ}åÔÞçxS%!mQÉÈ±ŽÆSÆDÑ1qùĘ:HÇŒ©ÉŒ‰bƒ381&‘!Qï˜1qþÿ`ʱ·#ŽTßÀ‘ ^SdÌùs³ßÃ!Àäÿ¦gÉÛuJ¬%ÚÛ4ÖÕâˆ*ÐJ|°r8¶î}`?‰Ùèìi8BcÊ©‡žLP9S@ÁàÐZ’º/76q¬_8+Î ,{­‹þ©DH9ªtÓd’CÁÈÞFÕX¾ 2L гô©ó+¤ J þ"8IÂÈ íÂÛ>¸"Õ6NÛ®§JPp1$¹³!œ°Š(›^ü "vè ½Øûç35yÄ ©q™_ÉpWÖ¯#ä¶×»žf­%^Œ‚TÄ“‡Ì³¥¯ÁH †bÎjñÇÞÔ¶€Á‘c Ã&ÕžqB–»ààÐm@4BFæ kœ ½’5.ª5æ¹!züàð5èÛ„í³qéi˜LQÍÒ ª©™·ÍèANÞØP‹àmLH#¯)x™¨”TMçÊÒQužÐUvrñêbùÚÙè0”„«¹¸ZÒ!…r¥ºàõIXÈ,¡GÒÀíoóýÊú)‹7‹i•b¤ üü‡#ÕÀc56Úæpleð’:Ϩ¹Ù!èØsmNM1º“ºp±ŠvÂ[Êvãýv°ŒÃù”)cN:—`⮆G1 ÄËÇÇ-ýCgBž°£oóº«òÞR2¬ÓÕ"Qœ9p5˜"V±K.0SÖ+úÌŠrí&!uŸ§,ûéoóÿÒO@g/«Ü¡ü+Îy&ã†)ÚõcEÕ¨”NôÏïþZ"p endstream endobj 155 0 obj <> stream xÚ­VÛnã6}ïWèm)4âŠÝÚ§m›¶@(à·$´L' tq)©M€~|IÎÈ–6ÎÆ °(ž™3Ρ£¿"¥îâ‚»oÕmôË&úø™E<¥y.¢ÍÞm'•_D›Ý ùõAFmãDä9ñÝæw‡Î#.iQˆÎÜ¢ èë§C,Rbõ0˜¾.#–Ò*­<œe´’Τ¤L>uˆ*—¨’–¹öýt°qÆø<ã2”6CœHž?vj´bdß[xU÷íaMw¿2òwœeD5“¦qR¤’|éà}ÛÇ /ÈN7°Þé¡¶æ0úH‚½nÎZdœ½ÃWPˆ¤,iêrg‚f2D[;«ÑŒ“îbG2:BpÒïý¯ µ¶£2_H2ŒjÔí ¤Á!ÖÒ ý}éÀò^wÚªݨAƒU¬aË=™a„ÐJÒBÊÎA·à•{BŒß+ýÞØ[Œ"…Dˆà7ÖÝ.”88ĨÆ1ÏɳæC›s>b\ S3ªÎCG¨Ë±G€P &ø"­=nIb ^=8@çÒ†¦éýÎ?$wUõ}o~ Y]o`0–-¡’G.;A«"dûï«PlÍ"™ZmM Œ‹°~‹²Ê©¬.¤ÎfbÕ‡°îê¦7¹_Í·±KÕƒ;`8”?‹Ã¾º¯ŸT{hôêr5öþ6>G õâÇãÛp€J€ sw€.ðÝM«ß¦øæ zšãyº˜JÝ|øC¹ 3'u> stream xÚ¥XÛŽÛ6}ïWøQnVŒxÑ­@ ´h $E qŸÖyÐÚrÌ%9ºtw[äß;ádÒ‘7nŠ]€¤4—ÙÃáÈ‹ ¾ˆà/RÿÑbS-~Z-^þÂÓXå‹ÕÞ‡9SÙbµ½ º¡úG/ÃX¨@×8ÆÁ[¶z·£ÙêÅá¸/nõ;Z}KÃÝ­¾¹·|·zn”ãEðŒq ÎÐÍ:Ð}Ù}¹]†RÊ |<¶e×é¦^/­®1´Ú!—,Ž ½³0Éïˆö5 ý¾´„ïHCyèJš}¼Õ/øx7M½Õ=,_ y=FÇAXìÜLÖžs,ZØžHq›þ›¢(>‡ŠH0ž†”%Â(ÿÖ´°s)dð¾¬!ZkCU¶zƒ\[I@–" úB׺~OB=j=,E4ô iI¸²^TpluU´O×z© ±âwË%m…Ç,Wn4P×·Ãf"Ñݨ ¡:)U°)[M2E«û}Uö¬ ÀG.6mÇlèÏN?–Æç«Ç¢:ÊÎȽZÍ&)–q#ÿ‚ÑÈ.(ÿ6áp‚B~s$4ëð³sä)ã½÷è›O“%K®‰M·ãË6TÿàŸ˜_?<~8Wÿ0aý…³WÔ[ï°ýð=ü«Ž&PÙ¬^Ò°ö¶iwÅYl?å$[pÎrDL9Is–|É8(œƒâïÓ88˜štèfΟ%ŸˆYLuòõŽø›¡É‰ç@9ŸçÞÉ$iÝ‘`AË3y9B¹9s6†C_ÐA$Ë-c¬ÄCé^›Ãð—nKêKj¿˜#l`~ªj)¹9N)Rm«7åÕ‘Jh¡œÈàÂÛ©PÜ‹ àp,ÈÊqÀnŸHp”‘ð“ƒSTRŒ ª9QÁ%ÁfhMáLHŽ£œrä ò¾†z2_qúfÌGÑÓŒàÙª# Þóñ–\°TMñ–6ÞÖÝp×mZ}¤rt„"_@¥*۫î„å N¦°+qFH%|B¢FµŠšÆÁǃ"’X{°v÷ô Û7ÃaKó;ªª´ˆÂ­®Ê:¼ÕÎ\ªëåe²§ ·Gv1¢IÅI'¾ov~¾œ=|!IY¢dJ’²IzûÿR´2©‘©“Xø©‘‰“ˆˆJ¤gxß–;tóÌ04ø9CO#@kj_tô¢±ìšÃ¡1×8^˜2ôDI(6ýXÐvM[}g7¹›Î¢3åÌõG(ÈÔÑ܎܈Y:v<Ú¾Ï)ËS|)Yš€–нÌç<(40‰ÜÌùÈ™L®õ!®÷¡|©uÁ€GIBC°9{\±XYñKˆÓ3Ä\¸cr=çâ®NçZ_8»P™$¶,¢»áa_¶åL¾%Ç/9g/16ƒ™%§]ʼn³+X%Q‚Ø 3,¯Î+üj†›Ïö}ðÜÀsUK—ðubg§¢vN¾\˜ Áü¬Cô3A¼Ñø­MYw>åôÇM?àw H;¦”®P|î¸Å¥÷݆ ‡p2tx÷à ï&õÖ~«êÝ-èìî“áP´´®J§”ö်=Ò²»Ð¤š3”ªt]vÿ¹nžmï]^ºm„WõD†ˆÂÄþ°Âå(úÇ7ÿ’´‰O endstream endobj 165 0 obj <> stream xÚíkã¶ñ{…ÑO2pfEŠ)A>4E$@ƒ¦Ùâ~ÐÚ\¯YÚ“äÜÝ¿ï z™²½w¾ ·€$šç=ùÕÛ]Å𮃿xµ;®¾}Xýå;š®(%™«‡'ø}Cc’ÉÕÃþ·(!”ˆõ†R&¢ïÖYª]WÔÕz“(5úI7ºÚévýŸ‡_áÒ8C8TŒ¯6L¡ ¬pË¢äÝó?›ú_IuÏÂþ ßm×Ú±§º,ë5“Ñ»¢Â,OEÙmŠÊÎ|rµvþ»çb·f*z¶ŸÇ?>ØÇõ–;À§Vï-„ÂáUáÔÓQ7ÁáóÒèvcζqÇ¡ A2ÁqZÜô+wpªÎOnOž?¶ÛÈϤ£™Œ‘ y‚“Þ‡@IÂ÷ûví&ˆÑï'Üýþ{hƒ„ÄÉ ¾ƒÿ=ÀÂÑê7H«OR—§NÛ¯?Ö‚Gyy2Ÿ,ªŸB(d1IÔ¥3n<Ƥͻ¼Z XJ$-ÁÆGJ€Ç&ov°QlŒP1Û†‡wq„yiŠjW¼äåeàÉX#›}ÚH^gÂD¤)%iz£Œ¤þX[+Ñ«É÷E^µ=!¦dOD‚´0t篠û‡4Aï)’’ÈOá›JÐŒ¼†o¨ô"ú&D,ªŸðOMù§¦üŽÊóOyþ©žÒòO,òˆˆÉ0bŒJgl”ÉzÃ…@CjLŒ¤ÙXqºçí gÑ.oµ}³8ó ÖÁXIžØóÀoÖ"ÖݳΛØ?+í’fb&S1ä^Jój”$JzQ³ÏîÎV†]mGöºÓͱ¨´£RE§”pšöö”ï›|Ð0¯Œ‰Ÿ‚n¬=•ÝdÎÀÿæPfTf´Ý.oö×5ç×´ yxÁħ‚ÄôFÿkÈE ðo³ñx–¢ÊË¢ó¾·EŸ\£+ùQ‘nzÓeè©KÝKib[Ý…¥‚•\"(3'lâ&vº(ïè&Ä‚›Š1'©¸Í±êÑG«ÑÛc^–ºuN °ÔÓOÚªv¿ÀœÖ‹oØRž ¸_uÛ-RÑÆV‹ÞGHËÛÜៗœ½Ÿ0¯¾gLÄÃ1l$‘$œ]>³‡! 46F„hD S÷uÐ,V$™˜ˆHïH´©ƒ¨Ö=ÈÐ÷§`*\V:Ÿ L›ý'Öà†6A£v>¤!)QžCphcfêÊ•ÂGYaN¨ø -6ŒsôS#Â>•uÝ„I›ðë¡ ¿hK¦vÂã§Ù’ÝM¶¤?~ƒ)94:ïüè¢5Ù+ÏívSQ[v5—Ô…ƒhߦË|¾3ñp슣ކ­‚óÙñ@Ð0ø2e|™4¾Œ1ëËðÙê]]í[û¡ËüÅ„"æµ}ã¯ÌŸýú(i^(ðƒqÑLÅîõoµ¸Œ‡í´u-ñøÿ®Š?еê¦õbþ§ò^ø©v ƒ(/ÊÖ{U7ámÓsû÷—íÿë{÷Òl¾?ñÿL ":`‘ ¾%tXKC«xBR:Yæ¡ü _³½‚d9™òúö©$)Ÿ¬Z’´cú–º:tÏaUç1‰}¬Ô†³œ!<©ºJÑ`ß«µõ#ø·Åjö4ÓðËÖ?ò&ß9ífQÛ5èâCúÐÁ··ak)!¹SÖ‡Ïï»a“°A:ßârjŠvj¼.Ô¼)ºçã%ãDÁñžÕMfDCÆÁ=¾4¾£ á .d KÖ»gP˜¸aD23‡Æác•®úI·D> ÔÇc]yó³×»"UÕßJM؇©™WÅDMùûÛEl „áþ†bôoèÚc©¢Ÿrkµbqvû<¼¤õTJûPð•9æ•õ¶„r¶mr„rP '4»Ð³hÃçÖ}þŒ¿³ô\ ®òpó@²x™…ò< šlÁ,¼´…9ÖœSæÜ¼êYØôJ†@  Þ¬ÍS«Eõ­øŸÐŠi>›ZÐvKnÚϤÉGë…š<äÇê¿®µuÏ^/šúTí¿€ï5û,DR\Áã•DÉT112ÑyLÔ‚EG•1v‘w:ô5Å©Âë{Å Mލû-¿’$™aʧ1O¯œOCväcA̸âPt p 7›ÞýUŸ?†M`öºøZéŠj1 LHg¥+v¥tE3AÒI½¯}ÛtŸµX †Å–ž^|úøvE8ˆñ;ð)Þáí1ábur’ößåê—ÕÏî&|ZIuË÷ä5G]m*}È;LåUä]ÂÛ“½ÑÀŸ«\¾ôãôj¢²Ù¤zÌ–Aª”½â^Ëp¯†§ÃÀ.É· }i¶Â2‡%PÓÙ tÌβ×8¹˜½ÆC° –ûB¯1º1¤Ç9$ÍûÜÁîlmÆ}m%×Vb_[‰?¦¶Bs¶Id‚ŽÝWØÕêd“eW\¡©2Uš Š+43Å×ñª%-ߨ&uÔ®9U»/àˆÍ>y· "9ßêµ®X^rÅ©œUDîtîÏî‹ïI·o̯xãôS½1¼³‰Éû¡É«=cü–ÊïAWºÉ»þÂë¥Õ§}½Aõ1X1gÑ©*À4ËÖ‰î 4H§Î6%ýmÎoÁª Ëj³ÝþëË|v‘ ÂåpñÂxÐÆeã›—]å‰ðá#÷…f>}j0¶_hžïövi­“¦}‘jãÓ•ªƒ‰WD ó}W1°S,QáeDTø2'Á'™Ú#G ½ŒC3blOk°> stream xÚíY_oã¸ï§ð£ ĬøG$•}º-°ж@®hú µ•Ä8[r%û’ôÓw†CJ¤Ì$»-phÑÅk‘Î3?g†«¬øª„|eü•«íqõ›»Õ¯ÏíŠsVWÕêîÆ7¼dµ^ÝíþVHÆ™^o8UñùÜ͹ݭ7ÒTEûrÚqÜ÷ݸþûÝ€‹Zá¼²F&¼bµZmDÅ*ãýÐy*SY&D‚=p_WeÖ/PJ­Šîrl‡ý$IHlNªy:0q¡ªhèç4ìÍðJn-L1±62ÚÍ tتx~‚! z¢ñ§Æs;?µôñÐýZèâyß=ÑøÚmܪ6\×Ì ø• • «97Û³&%LŽ·9uÁjÏ"¥ðI)›þ„¿¡³€aeŠ}·k_`›…†ü M~¤IÝ.£¸M-JVJ'úù©ÚÌ"¥`ö “E«´ºkIH)K*UªýQå_Öø¿? ºp¼kŽž  _?ú$Ýð fÚ»P3޲'Â/4B í@smq_Œ­ö´Á”åØ&huS<߯o2Ú†©:ìï «\+¥ÖLض ?4ŸáêqJí¦HŒóÐ;î.ÛÖsÛ]ŽN·ÿ%2ÝOc ÷±íÃôÃè7/$3f‰Èæ ëÉí^&§Í#(ÊwQäÀ5Ú6œ†~Ò*eºqhŸŸš3}šNÖþ8p<jÁÓ´ô0Ú›±¬æ°5Ë*Büg?íÍùéÏCÿ81Zâ vÏá_úš!ˆ$N’ño¨36’ű –€é0±q‰ô[X:*` .„›Ø‡€©ÜA6¬$>^ŽÝKŬñºŠ£ÓL`¨#Bž¬Æ¶$v?z¢zeXmÈyTŒW R1N4÷Eà$&*ÉÄt0¨\ÁÙ2Ö”²áŒsG¯(2|º½½ý41ªgF\1 7QuW‹…¥®hì~íá"Ì,Rd¦ê€Öû²œVÈcï†J XGõÑ»fU¸ñf-Å,j¡§:ZŸÑ¨%Øa¢¥”‘«‰ä\ÞZ·øc’Mcf6ǬkðF³”œÇªpp¢˜T™@.@ p‚[Ù’÷8 ýî0žfçõ$mÉl„È¿f©ýÿ]ˆduý&ÃèwTþò¨<î»@ {¸?má})ÜÚÎcJÿ¯óÿ~¡ï|æ;öì‰zÂ^óòöš— {à­ˆæÌzаI8S¿‚W“þß1bÉcê:‘KV ”¶þÖ}ª7·yƒ‘lU0ÚQü£‹›œ|¡™]ê9Ak²€œ À ‹y Æéòð(ÙÁæ”ìPc™!íð‹’$pIu„ÄK, Âj±i‚Ÿ òûc³t õ홨ú‡œ.0ÑqžÕåп9_N·'­ŠÑ§7Ûý}ɕۮ ³ð*ÐaSÐmJWIR…í(QA¾»ùuA %Z—C3õÏëª*šÃ%Œ7Àé± â1óv¿$Zy«hX’ªÛLœXN)iÍ —åÕ"ÉÔ)†NJëà#J½ •&yyÄ qaùžkๆê½#S}…kPy×°ô~ìßt 2q ¤®q©?: íãù9ÀU••Ë¿a¨CK͵7CÅ™ ì"œÙ€ÏOýèóX ¼Î ±§¼À¢X¨¹k½µºOü{ŸñNI{\²"àƒ’w_^œs÷;7ËòH´v¢m™ˆ ,"Ië ,ÐŽPdÅ"á¶<-ýã~ëÎLƒ–ܦa×Ú¼³äÈs7Ý4g‚/ rÁÑ4C›­í&5M_›å¶deuí๺º[¸œj:wË}äS¶‰_á*õé\-o#è #¬Œh|Ö;¯®.Ë+ï«×ZFg%ëpIÀÈOØÛ¾ÒQvÙÓ ñÌôÜ•‹gÀëª$Å+Ðþçb¿÷ 87?áMÒzñnã!bÄyãù«©r&šd 5+ƒ¾¡×‡˜÷t3k{ƲSÃi™‰BªÅ;=Ÿã›*14Œx<}Q©‚iàk~áKßþª¯1Ðf2Mä1TâÄl]Â׆çýغWHFMW;ÃÌèkmÔ%Ưɫ#-Õ9‰šŒ«‚ c6Àµq™ Øyhf¬ÒãÏcã*îy«2Q¼¤·»Y6|¤Æ…Žô‰§&SÆ3’rÉ1¹bØÒ?âGMN`zîD8wBEÆ5‘q͘Y3m^1ÜÌe †ÏŠ%<¡fAc‹*@µƆÖç¢RÐýL4}:iy$Ä—AÛi ~ý[’þ}Ï3ñêðšèQ3ï¾ ­ÁðÔM¾O¿ï"à„*ù0âõÌüÊß§Gšû#¯gáï¯7ät¿ÿl‡>TÓói]Žª…—¼ ¤ùÕ¿G’Vÿ endstream endobj 173 0 obj <> stream xÚ­XÝœ6ï_Á#›cc êKZ¥j*EMÔ«úÐk%n—Í¢òq6w׿¾3þÚ½Köt«ìñx~ãù´÷Ù£^ÔK"ø…Þ¶ö~¼ò^ÿLSR’űwµ‡ù€†$ÞÕî/ŸJÒM@iû6ŒúyW4øE_þWì6K¸_ÜßvEß—mÓoþ¾úXr™„r¤1ɸD1‰ÉõM³‰ÿ֊ЗïǺèÊ­˜˜á7õëÜ¢¾ÙQêš²ÙVm/…ºRÓßJa ÊXôŠt8䃚îÔd¾Êm^Ušqÿ»‰„/éãÌ/5u®yvew\ ñPFPc€gE"—˜)‰™\ñW(9ÓQNÎ-°ø1‚å<ò(çLőٶHoÃ+™Ÿ÷ŠT-a~^}*nº\Ï­šíoÕFÛrÿ F@$õ²ƒcîÔÆ‘ßv»¢[ÑÔ~’úwä:¨ÏY'~Ñ僴̸šEp`:UÔÂtû¶«‹Ùqú ³èô|apd‰jx, ›YlwW#/!¢Ðsºj)ŸÌ/¾lbš<æƒ4=˜ÒòƒÄ…¢Q[3îþÇjÈ3El–s¶(øŠµ\Inp`Kn0Übà >Û=Â2Øa@C¶ÇŠ¥JB%š„ÒYè÷y­ßòåÔc[Z¼Ý¶bù-OÞŠWúx{µ¦%"ãT¦ãÔ›ÖÅ 1‰¥ BÄBl»GâS*¹½Co¯Ÿ‡]ûI} ʹ@ÿ.ûaUcû¶ªZý®lä М% ’XÎ’ fÜvnG;nG;œÑ@ho†;¬hzŠßkä49…Ný¥¡¢UF˜…ãü½C‚#5l0Lª³¬Ž½kÏ á„ÙBÏ·g]*ô.–'ß»ÄËHšhÆkÊ0óÁ☄Fð|·+ã— \(L¼:LzÏ$Ovåb ä°.KHšêyåmZú‚禣箼)ok¶zäÚ/÷®ÍhÈF;n©ÿ>÷Þ!¡Fà¸:è„:®W}áÚ#æDÐ…)ÆÖ|J„Á{†¡[L’ÑsçDcÌ×çéDiB’ìkÎçÅ…öRKGª†ò¶‚:éÙÌæõ…bíÊ/eÿ\Â3§ ‡$ÎÈÃÙdŸíPv~—ùíé¼MUÏ*tÝî.º+ê¼l°˜“’žHÌžWâN[„Ü/OrŠW®õ“ø$þy$ø¶‡œh–CUªÑ]*С©ËAU˜óeå×êì'S·*dhë´gYH"•sá<ý,,2:…RW´æÛ((‰ÎЉŪ‚f²­+ÝŒ.È‚X0±+ÔwhAª•Á—l^_Âw %ßq'KiøªU¡,äš”«^ìªINØU–ö *«ª²&Ó±¸“<˜œwjlßµõJ±T{´~®ûxv姃ñl Ûv -:j‹J†—C rtºšÓ=+,“îÅS[VÝ Áàµßz¹®öt æ"Wcy¼Ø§md×ʱŒß·Ú%E>L´'mÍÜŽÚ±6ãèT‘`ùigN cR‘ªÇ±´œ”p©Îs O鲡á鬻ÀOTRfÉdY` 15§4,ضº¿/QÅ82+ÃêæRö‹}”hzÅ~ÅdòÛÛêaòýƒÖ—K™F-@TvK²f÷H¯íºQö:4ÔÍÎ/Úä Á9à¿u!£z²YïóøåLj5›xÀ󆶒m¢èjJ÷Æc¿;wTÊ3æDîp¦î3ð¹¸Fa§ÝK‘0¶Û•ßf× ’&(&­íÀ–Ú!µŽ?{„e©wçe É ¬Š©À+¯ªÓ„t¨¼ß½êDfaS¯‚ZWp¹Ó[c¶cf˜@ïÍÖ‚{í;;1ðŽ1˜ßôî„DÓeBLÜ q[”•ƒEMuè+­ãaK0ÔDYÊ} Ç« ]Ä„ ÛÒߞƎ ©RJ§²m,fˆ(nr‘X¤ðE…Àæe3…*(3§éœ(“°Àü±èRU´kv꼦&ò 8 Ü’lÑ(®÷¶àIØ26AcÝ´÷ó’ÝFfUuç 0hÐB¶h"¾زØ_,ž¸|*ϿզZyÚ>M"æsH³J¥aDÒØÖ黌I|ÎæÖe–NþÖë ÁÜvN4s§~DeóBŒma~¿Â!³4ÅYäÇF£L—%¶Fߘ›‘¹}ÚwçL4J§;„——™hp™‰Z· kg¢Ý—C­m¸ŠÑÖ–îûSÛ(ÍäÕtÛ> stream xÚÕËnã6ðÞ¯0r¨å®ÍŠz«·.°[¤Àm7@IŒL[JõÈRR6é×w†CÊ’£8^ @Q8ˆ¨á¼9/jñeÁ.üø"öàÏ]dÕâýÕâÇÁ‚»,uÓÅÕnÁC–‹ ¢ÅÕöڹʋvµñãÀÉ ©„ÊV^ìä+/qž l·ûVnq:]C­ì¤ªŠZøk^bxõfg°ö²¬©[™õ]ñˆ;’€ÍÃjƒoJtì©{ ìíUY%n\¨¶c«MÅÎånu{õ+ØeÌóYjóº¤>½4–£è… ˆdÁV^ìsi`].jC` òK/Ji/h$#Œjêízµ 8Ÿ•å‚•„@‚#Ç:€Œ»"Ÿ£]¤]7 £îØÄºé@¨ïY¡<5ªÐúØVi‘ðÌšêA(iµAø´\º¼P[ÍÚsd—JAà:æ²>B”ƒ¬ÝñÎÓƒ’mKÆŽ$+)(V$xa‘(ÑǾ‰!x?X(Y‰¢.ê=¾Gþl ,¢Å‹°XQåˆ#…¡j  Q[©˜VêÃ%‡¤ ˜D˜A i:dϼՆs/p>?W+ßuë4%¤‚Óƒèäf³ÑK™ïk~?¤dŒÄYàƒXÜoŸ«»U8¹(!ÆË/e¤!ó#CŽî÷ÒÄôP})iµÃÐÀ†¤&:x„ØÀ¢‚ +/BCá?éᥩó¸ C8¸^cÅàV´"|Û¡ó(ZÂ5\)„Ô“¿žÇb m§@8‡Íî„…¾)^xh.$**¡°b¹1ik cë)Obh*vhšP#'º¦0|´hB. ÐQ”˜ Üw¶}¥Eâ¢ÞÊ'³Õ×m×fªxÐfkåÀÄJn^«PRiR( BîB‹>Ûè†Ý]_g¦Œ@ÁQr'•¬3i˜a(p[×+@˜ó €^1„T$\G@]É͹L²sÄÈfÔĽG KÙ´Çy‡õ†‚"‡ðh_9×ËÎ8¶%вmìªl††B6¥6{Ãô®õ•Tá‹­a0GÑ|EÇãdlŒ 0ͨsª+éêÓöe'È#ò0‘“HøzTƒ#£cêxÓ°±ö]SAaÌÀgÏ‚ À˜ÔÎSgÀAûo,cÎrÜ×1o3µ&Õw|ˆžDõPJ[÷ø1bÌÂD#.? Ð/„bæ¹®¿œ©a^±86Eìæ˜ “I̛՜˜!¹þþmöãìïèì>›ÿÃÛüK¶*›égËi¯—â.[®ïßñÛ3<ö/ºqj ».n×½ãk >!{T§tÄ›:u¶àbGÁQà#ÔÙ†ÏKztzÁU{]¬ïoiý==.c´”%Mq]œå³iÅŠ6$ÚÙºßÀ»¤ÿ$þN« ÆŠ.Ù]Ñ.Ïñ椀Û~¡ÛÆó]–ø:Ï"Ojôd”Î^Ö˜4øÎ&{2\4@; `Àh:Ü@w@®Œ¬pTRÏ– ½y¾|¹©UxèTŸ ¡}7ÊݾfÅ¡æA&:Y‹CPNfäo+lÃŒx„î§1ã)Õ7HÔë%9ïbzúëåäý~º{»|Ù„/vª©ˆåÅ;+ºgHOÿ&â›Éëóþöõ±ôÅœãaÖY¡‡÷„º<¥íZÖ©€K{ñÜÀ¨I&gšÛ]šAK¨Mºkád`³ozƒGÝ>±M”¨­:{s§¬_ =æâŸh¢-… ÔLiFÐp¨çj7«£ B‚SzŠRôáqÌ\noŒë;Bè|\¥8 Új7Û¡žº„¶Q^Ö4Y|]þ›jÌhŠSš´óM¡¯š®½–lר‘É ³áxŽL[ŸÍ,t4Å`&Æã)™¦-3àF¯“Ókó¯öùOsõÔ¢†,ˆ&-È"órà2X˜[Ò·qnö×s àf«ìÓ}Ä<{ ›­ÓÜ\«€Vt˜QšÝœÀ0eIx¤ñ˜aÂâa»ª3ì<‡R_OÓ˜­nSs2¸›07:eœË¼¹Fÿ_{ù-úçyùÃ!ÌžRÝÐÿ_œÒäÏkµ¨M›Ëub>òJYï»|Ž}’²(=å4hV)‹£É ¥¨¤÷j„ñˆc7ÇÑgé¹Ç¸›ƒŸ:ÆŠjbô\’8æ3Ž9€Úˆ—l…HRm~Cs©dúùAƒ†p€õé°ÜJzÊ–È©-ô³Ì†…F@Ÿ^ÿøÅ,Ô~æã«Ÿ² YlÂØcùù=ó vŽ, ñÇdk;Åïå·ÈOb–ð £0y[| 1îM¨ìŒÉ(z ͘ü0)<:|÷Ä¡öÐlí-7À¯ ³ÇÎ]ˆÃt’ž3‡ï'lÀÉ›¾Ü’᎖H™Ž„àñ•ߡ畆°èZCj¾¡jnvÑ<˜ ™XM&ûBmígȃÍ-¥¨Õ‹Âd†=5ŽL'ÉÍÀKPî& h<à±Eýý» ÆCà endstream endobj 183 0 obj <> stream xÚÍXKoÛF¾÷WðTP€µår_dnm¶)P´©}«{`$J"@‘IÅñ¿ïÌÎ.ÒÚŽÝ-˜Ô>ffg¾ùf–ѧˆG üã‘IámŽÑ7Ñw?ʈ',OòèfqÅr­q@G7Û?ã›C¹Z§:o.»~ E·?Ëf•𨴻Õ_7¿€4næâÁ’ ”¢¨¡:–i?tná\­Ì˜öËúC{ª·$õ#<²ØYPÐÃjí]µ¡òË]Wö}Õ6W0`t\4n{5ôø"â¾Ü´~ðÜvî5¢Yk® 3ðL)kš`Ð!$š ˆ{8âvšjk4‡'C˜æ™1%&gÊDİìT…7B&iüy¥T\Ô§’~‚?íÊÁo±:µÕ©N^^¦<¾?Àˆ=œª§u=v§f3ÀboÆ®ìÊfSº½~ñ°´“Þ]„×þT£‡Š»»ú¡jöä»_&Uv¸%ÚàÀ< =ùëÝ ’gç,Gñ;Å:OQ°”¥«5穊¯Á‚£?Dâc±oïàÉã²+†¶ëPsæ§Š)c…¾=u³£~@ÛÀiÎè_‹áð{×îÉt8YWúHW½?ˆ;°ŒÛ†ö?Š´ álm{Ê—òÅ u‚ ‚ (QpÚoé1´NyŽÙ3Ûto-uòùl­Hq‰Ë³€¬‘JÓ˜D iê³9°=cBûí… ù‡'ÜBð×Z'?Š!æœõ Ë¢éi'dò¦ʦð8V.Y —¨ò~Înq@²ÇbÙžÒ9–'ÕͶ¿¢¸Î2 ÁQxlPâ¡èŠÍPv4ì‰ð œSp˜ÈG@ èŸ+ÐÚmÔüƒX2ÒžM56:íidgÝØTl뺵.qišÆu…\ŽÇö³S=MŒp>8{ìÉÁ“.7¬=ˆö ÌÖ«È'N0ä<èÿ,e‰ÿoòoSè1º¸&…åUÞG ø€ ¼£?EàÒ,ºrÃò`XÆ£c$LÂ>ÔÑuôá²ìù]@þ„ƒwžŽ OaÓÉÈNœ¹âÜjÞk3r41ƒÜÛ%žÑ}·qˆŒf¹q"¿ Ä_1ã“÷vEHÀÜPö”Û •µc·‹Ã?fçš%>å«]”‰÷$:”Wzè˜J´Ê1Ì¡lSÍ”|IJîËÄ”å|òt?¹ŠóÑ_9gFÙ2\Aye™*?ÏÄ# ;¯\!…—¾8–´™Ìf!ûu÷¸™~Ø’^USnÝj‚l’~^Q;„‚v–aÁN€O3Zq PùHõ¾>}„îhÌ6È%jÿøÉ½tûË|Q’iH*±Æ1g<™DàîÀFHx™/6^QÝûòp~a×ÏjçÈéb×íꌬDŒÚ‘µÐ áFG$ª–ñûf €¥R£–îÆÛâËöt„&%ñT^Ažmʧ¨;÷ü{ül¾*c‰Oçj2AçÖ„•Jb2#TØ5ããV4Sb›ìž§/U]Ýý„ú eìd!Á‘ù¢J³ã»M…—‚Ò‹£‡Å.½öå@/Óå`ÑJ dŸÉ!£õ”¹ëátW“&5¶&k ¡’‹n½¢F®km¡ßž6v¶ e(ux6@¾ˆälÞÚžK»ïla ÁPë}7ùwì}§(Ë‘OÀÆ©ªíÁÌ'^,›¡{pKòÈ Ë£{áx6¦ <ÄnÛÅqÉUPÏØ“}žô=âRϲufÎÊz"çGXÙ‡þ«MÀjÀðcfC‘€Ùt2{ï(Pj– Kèî’ûã#Ÿü7â#ŸüÆG.âsÖ?¸Ñš7!ÒK°7$UHrÐãH_|@㈻TLx¶Û‡®LÒ¨s F&êâÊ4W/à-{UžÊ¥©f)Uš>¥{—‹Éþ ™ÎúË&ݲ4cK8.±×¥4㳊•fiìnÜ]UöA|eþ\i F}qz‰}ÚTãPMAºëv_m°½µªÇzM“áh械Y¾ÉâŠX4þ6?ï™A$‡†¹vyT‰Õgã[lßn\|zW¸ ˆ‹™Õî©ì+³ˆÒ܆O…Õ_ÉÆï23‹+ÙY lÿYcwþa‡n“zv›]YÊâ¢ÞÃåJk*‹Ô{UÁ[›Y2¿P\‡ÀÇö˜Hï®Ç‹C‚f×¥ê"Û3ú+¸=À¹ 3rVÇÆëÏye–ÿg&7! gÇ%xŸrŸÔB- ôojÌuý¶žGï:Dà.¸ I=óÍ‹¿"ÐòeqÖã]ÿ«Ãü”HnuÍo/½˜1¡^´%ˆ¤ž  /\À¹®K5;Ëó2ÀåüÆò zн+ùœ|`â¾ßœúᄌ rÄ=0Д_/dC„êWNh˜Ä9Üã²9tö±è}K†-oƒË¯î]kIM=ÏüÒßü ½RF¹ endstream endobj 186 0 obj <> stream xÚ½]oܸñ½¿bµ€—'‘”(åÐIpAïÐ>gô¥îƒ,ɶ}ø$mýñá¹æz}È¡°a‘œ!9ß3$½ûm—ìbøIvŠÃo¼«ú݇ëÝŸä.‰Y»ë»]’²Bî8í®ëE×Íþ Ò$ö<‹ŽýžçÑíþÀUÔLàÑxGßv¨Ûª™m‡¾‹Ðæ[;ÜÓp£W[¦gÎ㱫 d÷¦óh.{Ó*çPÝöÍ0·ãà“³Âo˹­öÿ¾þØ2Ü –¦š»¹Y4ä‡OIâJA±‚ƒ¨åWƒàJI1aÁWûƒ2jYÃö‡,/¢ö.´¢ŒY’¼²b’°<5ðjvæø”‰ÔüÈ$’Ãr|ìšYo˜{¿‰9Í !ÝSO-+Rl¯"ÅÎqnj³F9„0Í<ç,爖çˆ,˜J&rƒ?ÖËP-^™Õz“‚3U¸Š{zh¦&´‡H¶Eä[E lÅ BK@Bc1Иদ6IT€ŠW#…Q”ht”(#BEÆ™³Tè¥FåÙ¥±±ik]Íg<ÅÛÜÁè.ŠÜDµ3 [U¦ùÉÄsÚL¬6Û€Hr&­Dªr V>q»’v¨}äXbô†ÄÅÐ=6A†I¬ÕêèΘc7b xºÙƒãÈ,Õ²21j€Æª[5À(2_ü|›aCPˆ}.Yšœ°_€'J› SÐÈ2Ò[dJìVŒ«Ð& }õÖ-ø¶ÐÜx’LyŸ,¼=ÏYœŸì*?C@È &²m(ýÍܡӴ ï‰îØ‚¶°q¢Áyì)ð¼`2sMAÛõ±o&ˆÐ¡8MRà‚Ïz]2•±#°ˆšoS3c°Ç8(ra– }»¦œMs4LZ+ÕK[?V®ã|ú¸<)cß õ4“&*ôÓvªI±ËÏÔÔǪÑA"]CGJ9Éml8ÙzŽ{c÷A§8Ýd?D…"šj¡žElõúN˜ âÓ^§èpŒ” 㯅Ťu•›3É!‘Œ«×rCŒVg¶0d&‡5W—ÝÍÞÈf -Rf¹"ÙÊK%/:­|Íi³78­¼è´ruZ€ÆM}ß ;­bù[œV¾â´ ‰ã5…É K7……VpTz)}¿P4¸W×™ôúH^Wµ˜ É[¤±eßýÄZUšüZ$LJ°Äí{CGîÒÉ·Z WÜ$¥—=² Ç0³m:ÿá÷ø­íÚR'^èö£¦¼n:ê?Ò4ú ©ó0‡p¡ ¨@•ÕbVìÚ/{S„á¸Y¹ûÚÖÇÒ,øuŸ‚$¦¶¼í°žT€úÏ}Eow4iíP@O\¿(!Þ(F)‹héëfi™o‘a% lTcOº€8I1h&ôpýÆ¡¸ââwp´ÜÝ4ö´#㺠µ·.fUnªgUpJì¥\«UJ#B1•{e| [€)ýv,‰«vi­ Ù#ÀZ¢}ÚCÁ´ÃUñûbæPéÐÌó$z¾vLÉ~bV™gV Ÿt³"à´§ÀFó(¬•fEÏÈ<çH­º³Í9Ì>us8cÇzš¡ž0†“Û 8DëXÓ|[®¬ â+ÞŒsB¤ Úy»öx§‰úéúåEâIU|½4½ ×xŸG`¼ñgÒ ^¬uõ}Ó‹ñq÷oZýæúÞ<~}8óè‘ý1"»Y¯¬<º@qÅJ—¾Fúe(ô¥Aà!C2¾®·>=1þF!¾™žOðà.·!‚Käw´Î_/ÜNR>=‡OŒ÷!zË’ÿ3=ï§°d”üÃT%Þ¦*+šçA9Ɔ Éï$H½4å ÓLД_Ê' SsΡ3ß¡y!èá0×שøvéÕDι4?qés‘¤4|ÞþHw¾U`=`4W¿+2T7‰”øXw€…² Ï¡b3©`˜ƒ éC~9ÛÃ?†—Xáæ¯r(Ë"^_®©wÍ—á(;ßì¯ÂÕj iÁ,Y¢^>;;;ò“ëñxK;Â!½Hdô§ÕxhD[´ƒ> stream xÚí]oã¸ñ½¿Â2sù)Jô!4@í¡òPàrЬØÚÈ’WÍî¿¿’ú4íõöwE»ØE$‘3Ãá|r†^}Z±…l¥9ü§«ô°úð¸z÷ WŒ’˜Æ«Ç—S$–« „«ÇíOÁ]Ñî«n·_o$ƒ¿'íþuµÃ/ä}–Uk_ u¬«õ†GAšm»:)ì\‘”».Ùe7ð©hðRÕ§\Ãß/3/·Ùç¼ÜÙ¯ìó±Îš&¯ÊÔ<³O]þïµRARd»]ÿüøpí˜D)Ã|Rìª:o÷‡<L¡ƒmÖ¤u~l-IH MφãÌŽî€<®S’õF«0ø«ƒ>&u›§]‘Ô¸‹PíÞa,VŠNWª^ìÓ¡Dã^‘w:e{ºo!DXæ*ä 3l Áƒ´êŠ-¾Ê @‰Ã"¯î35°p/Uó зæ½Yí݃žê\‡DÁúš¨È¬ot#"X¸(~‰¸›ßVVµ2&LLeäáQžañ)ð1! —àãzÂ[øêàÕC ìJD=±µgÚðèÊ ðm˜.6Æ$о²á³J)¼JQW²xïg‘/tòî!š †øÜùRcü§âä©­[»[®-66r3ñ¶Ïê mÚ9¾l»ÃÁ ®:Pžfw7œc››èÌ>ˆîÅqã#ÂTƒuœ¢+Âø•è>ƒ ½½ð¢æ’X! ˆe“¥]‹‘ "gád”@Ù•ÙÖ 0­j,G*@zhíøáhCLéjcÑ!hyØã!s”^UÏÿ¦íŽ…S„=…®=µêº:@8¤±‹‹ðòœ4&ˆÂk“µ^õư@¸ˆ Óõ#¢KòÕD/Üqމë°ï½Øj\Û¥­­ÇaÀ t€ÎºŠ#ɶ(”êà$åМøLÂŒBæ± ÎÊmcGF‡Æ‚VÒfŸ[Ç£s·Ê:%e„º +- cz–lžž%· Âx×d[Lœa<¬#˜L/)À'°“:㠱Ж)@vïo&{ŽñXç–_·4 Ò Ù¥~CźÌñP9ê6d„2N²¬ 76Ç6ðÅ.„«®µ#†™>Õr›j#—j…Mµá"ÕêIª&£ë˜dŸN“úgÔ¥¤×#ó Q*È#þFÆ­bBÃŒoOlŒ?¬7qhjŒž¼©9"B]K/q';)g3í}ÛzÏßÅöŸˆ-=›üÛÈKÄAeãm¿{é$·g¨½a³“4$Ó0 g={L=+B‚'T»ZâßF-â÷‰F /tðü[ê3f€¢ia÷·¬]œ¸Ü¹Ðv.Æ#¦šwB†. ~à9³GZ;ŽœNÛ¬NZ‹…­wpˆGµiÉG(Ì —¸Eä¼éžºv6/>:j¬ÖòõFqË®â*¸»±Ï§àãÍëÓÚ~ô“Üd1¾÷± Á,z5ì|<€ž&?å7°ÞMñ³WaP[i1ݶ- .6®Fý:”]bRŒÎuI‰ZB¦'ª\O4Ÿ3uŸé¥6٬ǩǚû Üè`¼ÎqÔT‹ÆèBYR„eôRm¬†jšÍb5”q‡¤þb½ÝL‚Á<®€GŽÕZ8 ·Øƒ 1 ÕõP|¥I¬­ÇHB¥y°pfœ@œD'Ñ‘„"a_äßݺéx˜†vÃØÈq!GŃý°àöõ÷/»—Þ&ü¼©¡W²‘Qp[œ’€ð¢ÕU4î½)d.0^Õ­=úØ<$Z[|„X‰­Ü ÷ç5f‚Û?Håܒq2äDƒÍ‰Xδ…?X”„°mÒœtf/cš“Ó‹;51G˜ÓLº4ÃIcGûMæš~½‘A}I㨖…Ö:jÏÜ™«繂R½á¹K¾¶\Ã'6¢áùkò™á§àS—lkiÌj8ˆ‹O+ Ày©êCï=éhIz³Ì]o~ާ߈áÃ{váD°ÑìíF܆ª2³/ 5ìÿPm¢òå¤Ë(Ä㣜¤ @[Í.!Þ4]Šh{læg>à8ÈlâËìô"ƒû¤n³&Oʾ#e;NÛ.uG§~ÃõL Eº¿õ:ÆÖÓ˜Ùï|g :¤³'JÏ] §>Œpõ 4|1h,²‹%_ºæéJª¯Ýþ¨™u…h]9 lÑþWÞsm]JpJ‹SÂô7ÞH)Ÿ}çCŸ˜€7| ãÁ|â?VmÖûUâ<-wþê‚'Œ¸à9õ¾&9d=øùêE‡|·ïO `^³bæ­ÎÛ6+ÏÔ3uÎßW;:ß{%á=såH/—¾þèK Ÿ˜%¨i!æyTpü™­úlÍiÒ™ã íoÉéìOR~ñOèñ@zæ/¼|Iò_qèâÚ ¼älz®fó[žð±Z%Rbï_„û5E¥¿@åU½£ôp‰^ž0Wõð™×v¦ùbäkUPöM%hÓ_ê(SÖŽ…N™õE±Yù¤Ìn\úJó'Ê$^í ¡¿<žþx„ó3á&”öwœö ÿüÓ/.ÂM| endstream endobj 192 0 obj <> stream xÚÝZYÜ6~ß_ÑoQÓ²D‘”z²YÀ6ÖÀÈÃbç-`énδ<:z%uìù÷©ƒÔÑÍ×F6À«X*Öñ±X=«ÿ­ÒUÿÒU.à²ÚÕ«77«Wïä*Mâm²]ÝÜ­Roåjƒzu³ÿ9zW6¦ª×E]­7YZD•°£¢á`±##ûÉÔÇÊòlÙìí§²¹ç‘ýtìlß—mÃã÷ë("·ïÔÛ=O›~ÁREýé}¿ëÊ£ûÔ¾­MÙð®²9£ÝÛ]e:3àG~¹ù¤w‡Èb¥èíPfYd¸‘›}YÛ¥2OÕ- ¶·4–Q ‚*}°»áŠ)z³:EÈèjÁ­Y‹<:Õ¶+wîó™iõ`†7 •ÇÂûkp7bòòf8ÁUÑ3ë»®­=kËSoM7ؾýÐü±k)&÷'g:Ñ{ÓƒÁØsuKËÚ¡g0&™€e÷è§-¡~Ò‚w“1ÞÂR¹·ƒ}pUî¸kïŠÙðuDëUEAñ‘oAˆÄ٘ə!¯CX ±)Åü~ø¿A¿Ü¤_û:‰3ý îã}LP= Ë8KcUŒ‡ /÷vÚ¯cH[xý!¼]¼p{¼Áü•d:²cî"œb*Ë´ð+^4\¡»-ÍãbDæMø’Hâb´\ϼ 3=Ë$ôÌSbF½›ƒÎT÷mW‡šIsL‚zÌ—8ÓÊG98¸oõ<8•ÐUç~™-s5\íŸólï»Ë«=sŒ2Ê'D¼BBHt~&€[8õoÈM\2™—$-^xà7¡‹ f>º@ë,Öù(Eœz°þ!(rú¬ÉRo²Û$IBJ€žç±^o´4Ã}ÞhO:V”R½PÍoÃjg~õê]1GFIˆH30ºô4@™/òá€Ë§È(Ž´ …›aÁ€ÐÄ>”ÅâŠÑ"”aL)å²™Hý» æÛm¸9vemºGôôÎ[0£¯{@€•³\y»è“í©Úó¼OÑ.2—çÑea2'î®Q‹‹ñ,sVc°Êi·ñ¤mÊ–‚&ÙFÏ­ý¤ !Aèv¼O!Aèiö7î}H8ðõ9áÔW §·Ÿ•.vaéòßYs?®7.ž'UР€Æê+hJ9!Â$Ö.,Öøh Þ]3©îCÅæu(›”IÂOÐ1›üÏÁ!ˆøC¤PcN¯2®Ñ á ôø¡Ås–7N(¥ ¥”Ç6èì0·ï·™êDÐfî•‚x§ ~þÍ×å|=÷ض3'ÿíI®âÍ ZË%TkWÂièÒ™ mZnç©vÙ›ßDÑøšé€Ý‘ŸæÍÞqÚ‘9wn“Tv=íÁW`}¤WVÛØQKÚˆ…´]…pîAåžY6øFÔi¬Ó³Äe™uŒ‰š«G(‰EÙ;Œ“ß4wUŠÝ©rÓeÏõÜWÇ„‹¾´Ã t2hÝÉ wrØÚÁÔ Rñ…]d··¨ð†Ëè0Ί)\4 —UçuÓü¬nJ-÷Ô¥ìëâþ„íMM½‚ouhÝRñ„`-\,=kV·Á5òe>Vœ%yîëd³oæçŽh›£pÑ2ÐUOu#Û\zÖâõ•Ì$ÊRJlé]6‰Ö2©ËSô¥/4|T­sòô"ñÉ|âƒÄn““¬§Ú‚©®\) ¶ø–“rb6Å" ¦ºç½yÁIÏ=€C0Ö¥‹uéc]BxüyϹʰÆå+0H>–å–ˆ#'Ä‘„/ú¶cvaÞKÈqú±Ãî‰2 ղ뱇Xßs·\Kcˆ|k÷m µh£+jaß0þÌ`ݔòĩ;³bR/‹Q8Cñ³ +Oh`H‡nøR‚I_¬ —!]HòcÛ ƒ)(LG Íœú±‚dÜ ½=ãorªìÑ…ˆ1ƒuU«‡Ò§·= õÑÝ]%z‰ÿlÙ,@]>Y(øSTÌrÕÇÌÔ¼`¦¾îW’k7ææï?p«¸!€Â΃[þ·ßýdºï'Ekùl¡-‡äKÌ?s'Eª¹œýôã -Ï6îÚÊ“±g(®I©Éµ¶¾¥Î+Pø3ÿb7~usUðÈó,èÕž’ø[—ž>[‰Iÿjµ§ü¥'~ªø¤ÎN¬·q‘ÿ¹ 7é¥QÄÂ(åÝœ·êe¥ÊÛDÈ ý𡞯{½ v÷8xu@€d¬ëÁSDÿ SNI=ï!Ÿì¡HÀG¶9I"â\¯2ÿgIà8:– Ö‘B¹ UʶÅè!_\)ûçÍåŸ0Qà 6Zì&©'ý÷ß~öPB| endstream endobj 195 0 obj <> stream xÚ½ÛrÛ¶ò½_¡é‹©©‰ @i_Ò™zÆ™ž‡3ñ[œŠ‚,º”è’Tד?»Xð&S·ô¤cÏ€‹½aošý9ã³þøL øfÙföëÝìÍœñ€%A2»[Á¶“hv·üèÝ­çB{»úzî‡"ôòŽÂkÖyM_ùvi¾äÛš™/O•©ë¼ÜÒü3ž6•Á4fIë©;ÒðTå›´z¦Imš}döv ·Úå]Ѥ[ÄÞî²ÜKZ_Ì}{fþéî½å,dJYÎYz«²(J<ôØxkßܨ@’‰pxt倆RSL*¸·ï=é8¢aÚüWÏ[Òpˆ& ƒ³ÿT“á%ö¹kí3›¶ÏﳬÆ·XNÜúv¿*Åâ™/B’?»&yämK5x³Ì³´14E¯†cýDn#Ëï.ÑkÙÝ-Öu –ÞùáòÈ_É0öÊ­q_Ÿ×y†ê_Ó¹&ýÃ:Æš¦å¯öþš+å¥ÅÎ8žâ¡H¸f±pL7U3ä›'¬«%À2†`¾T‚ÅÑЙ¥u½Û˜%³û¿ÝQ<à#@7`Ä. |LÊgôÉÁ°W«ßõ-Š%T:‹áÝS\0Ù:*ëÉ%—ï\ž (¯Që€E­$l™ ]Na‹ ûB»ŽÃç›Q>Ó‘6œÛIJEÞ˜ uçÐ\#Lž§Þ-ê¬ÊŸ|ÀÃMéímƒ­ûû´Ê›õÆ4yö#±àl¸×„ƒ–C „»!áÝ!it l¯áÀ;–ÛeŽfeù8 ʯh#Ý–à0ªƒà¯S³ÍŠ’r0Ð!z3Ÿ@ߤµµ©[­½¹Ñ{)a§¾ß¾¤k,Îäö5Sä*^î=.Âë«4M¯îç@½¯qïå?ñë«ÅbÑ®)X{ôa-Ë2Xû:½BÅBÑ…¯NáÖMÓGË!-¾;5ÀíiÜ{Vsé >æÀÊãOüÓé«þÑEœ±Æç$ÓÅ3ÉQœ¾slÜßúÒÐh;x#Pq×)±Å>*;m!>¼í¶_oÞœ¡ìAÄöæ}6ÍÀ_¹zÉÇ„ß:ªÇ½ÿJö öØá?F[÷º ¿™H,¬,}DÇ/#êàa¶Òü˜_?~¢oSÔÆ‰‘†e¾ZÀNÒ?ò:ß΂tèÀx@|ì¶Ö[«„å08GœÎÅÖ埖«/ Ó cët @,ÿ)1z %½³ua&äÕ8Y±;  þù–ܸ ¡¦ÄrÐ’´`}.œÞtØûØu;¯È/ÀÒ/º·†ô-Có™2 ÷0òîêî d¦Bb)âv²)]Æ öXV:ñ.ëÛ—gÊéæÝ+½þÚ¿æÃ½ò[úȪ²®Ý›rÊ öÜWk*Ð{÷Ô©wðr•^¹|µè¾²«¯ûOãåjÙm›îkuõÕÕ±Ù(g RG¬Ë˜é°Íx·9¯ò~ï"¶1÷X«Ú88™ðò>A´ál®¸g+m•:Q òþ¼MÕ\ïú'C“÷O`ª«´©uê°¸Vˆ·Bhôp¡~¦d!…,Ø¥…boê©Î –*ÁBñD£ÎÉ¡"®-f’™f‰¦Íß7‹ä¸‹ GU"¨ª¹ž.nC}îâü;äøŠ¶ægTò2*„Ù>(¯ºàÅÑÅ\"y3!|MzŠ©|öã€éØ:Ä3Ôˆ>ÔÌšVHã\•Mê,Æã)yêËä)OÈS_le½À%öǵԞÈàl‡À¦¶ø´¦Å'|çšã!ùéËìQ÷bü?Ùãé4’Ÿá-ª4ÃN‹AUp‹íÎ ¤Þ3Œi›ƒÙ1¶žî5%möéÕ³ßÒh6O+ð ê¢â~=ñrEÊnmÑ¥ÜÓêŽä “,‚Q+;pI$Þ³u¶l¹[Ñ2õ¶-aXuºò-æLZœ¤VìþR+^µj•¡jûãj_­’‡m×X ÔŠ³ýÙ b"¹¨?ëZÒ{ÚǵVûx£Pvʆ5R¶c ]OÛV°xd(PCj½+Òj2õâ,—tu©§=°v˜Yk·«È’l {ÔtšñÚüa­3ÿ¤-%’‰®¢‰Ð{WS<ùJ35úUâ\¥ØþÀÚýÜ ßkÛ,þkNuö ¸°t3îk#ù%S¹"zåJlb?vìõø÷‘QCÄH˜I*÷„hAÿûÃÿ„áÁ’ endstream endobj 200 0 obj <> stream xÚíKoÛ6ø¾_aì$c1Ç7¥lÐÝÐ]†­ÙeuŠMÇZm+•ì¦Ù¯ß÷‘”D9tâvÐÃÐæã{¿©LÞMØ„Â?61þÓÉb;ùñjòíO,Ÿ0F ¥&W+¸Ÿ1J =¹Z¾Î‘„OgŒq•ý±k×í¢©n÷v9 £²ÖîÛ雫_€†œ -S¤“WDGæåj:“¹Èökë·Mµ-›{ÜH¤âOí‡ÛƶmUïüEÕúó2ìc ðªÇgwëj1å:[ãÏÚu}بëéŒç™õTèlYmíÙ”›ùôb:Sœ9ÑP“Yž ‚öáA¤Ãf2p“3!¸ç*„p !„¸· ¤d¹ñG=lÙ¶µ“cQ•Þ‚pxWí×~ålƒ´u,oÔdõnYínüyO¨u”Îþ²‹=q2¿¸Jû1çå½Eðã«Oõâ•“(ôÞ`n/,ï]à 1èÄjìÊ6­‡Ý×þ·ôWãÀòD‘uÙ¡xî:[Õ›Mtï¼iÿ>Ø|±–îhU7ÛË Uk¥è$‰bN§]¹µŠ™ ´@ê`^w,PĈp_…ûbbHaðR£!„ˆ–€¥8H$Ѓ\¤xDèsyðóyÈ1 Xˆ­ýÉHŠ»É~Jbs$1ã±È*y—b¡ð¶y“Rˆ!b/Þ­mcÎ “˜{:¦Æ Ì‘ r;JEÈÝû-ÆÕµÏÅ‹-ÈDGʧâê(yÇIª\’&-Åòü#¼Ë’Ÿ@šhó±ô §Y q¸$ÙsCòüÑpЉp‡'7ƒeÓù¥«­Ó/€b9QÂÁ¾(ûÚƒ-¦CÀ­ê{®ûÞ€¬G¹Î\59lmã<øu1 ´ÃÑ]@äqéshJC©„@i ,|Ù@ÉE ªøójçO÷£Xšg›ª «^+šGZÑ"D'BøÀ…•«ªñUßýÖ‰7BµKÔ}üAha¸:° &Â%."‰+ßwh¬^h“&´Iïàν{Ÿ/öì°¼ Ùû)$Z¹9Ø•.œìx±Åíà¤Ö¸pšžƒ+ìKø[-C¯V÷žhé/nËZÌaS6~¿µQ…°á°ÀÀIbƒ ±ñÒÞݯËPA–vo›mµ³íQI$ÜPbL? È0 ÌçÏpßÖ‚R_Ÿ; äÃ4À 6L¼à¦üh€”ˆ¦ĪZ‡“þÎçe,I pÝ€GÁ¢üx@Š{·ÅL«ýÁÑT€G8´—éz¬ˆÄÑÀ<‘¨˜ÎW]9¢©þ•cìAIòÒD°PŸäÂNpÑ—ëû$E`á¹Ì)ÓXW;ˆAB}¹,Ì—¨ì¸ß €òS+ôû3høRËŒ~rSý7ê<ì©8ï–'¨aie'ÇÑŠF]’Ë£.£ ˆCò¼›ªÕPD=(”°”/MAàí8Èœ¨›û¾„2Õ{ÏohP°ùÛ6õ| ½SJÞ=3p–ZÀûgçC«ÇÁ‰Å%³Ûì»CÔÀêg¡ºÇF<Öä²q=ª)R“ÍɰbQœ©7ïÞϰ)˜Œ……Ih7±—i#Ê=ä´òì‡Ô+ßÓ ßžèþ®³[ßh–ÝCµ³LWcû’©âÙŒ^ÄSø*ýN’Çé"GÉTtjŠ”©»Hçbÿ6%"¡e¸wÆŸ)Ÿè—`ð,ÅÞÑò<%ž%=ÊÐDOÖ q²*Â\¹÷ß<5oÁ,*ßÁÐ]ô!k¨/Z%x«oñžS.ÏUQ¥Mô ~®•«¬AÒiBŒÈ‘7ODëeª H6Ìá!è…TkîªÖ†R%³@K,øéœþþDNËQNGåkÈi}òƒT:§E—ÓúDN+z9õþOéÏÒòÉ”–ÿYJGTJË/$¥ÏÇ>OJŸz") ƒEÿBRá…ôr·´ü‡FxÅԙ߽EÎBêæÑ[ 7>ia÷ƽKbø-»ý à C!êÇÍ>§Žæ¨0 þ|vê{¼¡Ãûv¾v‡bXGÞOÃU¨ _Á_Áó• Öösøýç°hn¼ýG–ƒ„Ì”4Dòà1@ܼ ¡…by[ÞØá¯†QLˆåO³7š05¿ÂG%çhÑ™–þýÌ{õ~ûê­@ endstream endobj 203 0 obj <> stream xÚÍYK㸾çWø(cF|H”vO› v/» 4™Ô6ÝV–:–{{z}ªX¤HÉT{zNA7 ©*V±êûŠåÍ7|“ÃßhÿùfÞüåaóç¿ójÃ9«‹bóp„ñÏY]nÿÎ$S¬Üî8EöãÕ\š«9lwR™ùò|1ãØý¸ýÏÃO Emð»¼F!¼`µÚìDÁ mýлYUg)1p'}~»ñz£Y­-fPä°’‡§(¦åfšò=°IY¢J^êÙ¥¤1=©ábÒÀ´¤`¨ÀÁiÆçmÂm:,’Â$wãŸóœ'$Ô,÷P÷tÇãß§°XÀÆQì²¼Áâ™()VÖwøZªvUYa6àå÷m™Ñ½|$XÀ×6®ñf–OŸ’[®r¦ªnºZÝsȬ"ç£í/e–\PQQ,ôGѰX@º`: @2ž¸Ä¢:gâ’È1¦Ø…:›Mt!k¤Ž(ç ¢k (¸Ë)÷áJ07‡áÜ´~^CïgàfHf6¯8@¾j}Üç!‰ä>ƒiPLíÛÏ9WTÊåÎË:,+ânxº1(ænøì`P`?A_U±ôôCôÒ5B¸)F}¥²ŸzÏ/×aQyE»F…¯`UC*s¦]°þrõÙ$A:ê÷@;<Û-¶ÕÀпCDªr„ *±$"³©C ]ˆŒñΗ#°µ>N›È=œœS!¬X%§MŽX »ˆ­áëˆÂ1ûxÌXðJÃx£PÆs@ï\Ätèì4ÓVòw,©ñ° ÇP/¨B”ŽÕ=B¬­§¢÷˜dˆ œÓD§˜P Ä ˜Wâ B޼Otòk‰îKÚ,òE)wÂÜ:讳ìmI¼Z#q¶à@ÿ˜q“9sáë,.ﲸüfq8ƒØÁpÓwX\0)îÇÔxT á™sN§I5«–ú£ý€ÈhIì†F¡üV¿U.©ÈðE;N˜!ð…åÐxFkBMA ÂgÚõuñû-Žüª‚$vä7$yy’lV®2À»Sƒù}‹,Fþ@_YX–5gJư<6gÇlgÓôßyÀl‰Dr{Hw|$ОSËG»–Ï_`Z¤È¦û`ׇpø‡TÓ‡Wîñp=Óñ±žh’únÓGú¦š¦©>h\;èä]7• kíž2j÷ˆõvÔ°ˆä%Út-W8zLÉ©„ÀÒúdt–xr§9ÿLÉÀ¸ñ¥„éF³&ÄãÞ¿’§­0zW:IËú] £ÔÌ&.ãmãõŒx™uÃS»·¡Àç‡ó”ï DªåÂp5·{:%…ÎÜlÎrñŽÙ€~Ø¢.‹Â ;¯²$Ÿ×Å8ó4¼tšìkäIÆHïm÷€û†¼°¹MåXž#ÂDyhϦ׋Ö¢nº\ÆC|\èUXêE™ÈÙÏãŠìþ0Ò?2ÉHêˆÆW¶w¥cBé©dW€ô‚xn~ÃŒ4o¯ˆrÃå D¤éþÕ(ìÆê/Gæ¨U¡´]©¨BÊOýõOÿZçY endstream endobj 208 0 obj <> stream xÚ¥XY¯ÓF~ﯰúäHdêÙ¼TêK-TªZÊ­DEú`’ ±äØÁvzáß÷œYì±3I. ®ˆ=ËÙ—ï8úÑ(4Êü%Ñöýüýð Í#JI!eô°‡ý5MH‘F»w1'‚«5¥LÆoÔ°ZóLÆí ~i¬ºrh»~õïÃo@CDx+)•¤ÑšI"3MæU78/‡ÃŸ]ûÁ¼ Õ)|±úTõøjöm]·+–ÅUcoôÊBXîDxfÕÏÌë±Ä—ÏøÂâ÷æ¼Ù9÷jgøVÍ‚°útêTßWmÓÿh5£ÔS ­“YhµÞº™¯<'’Ã9ÍîIˆcä$‘¾ Œpf÷ß…îd.šEVà/ÁXxІ»j¿Ñf)’¸¡`Fòb¤±I(‡Xh¶*DKä$g7-&RA;I"Ò…¢ì+¾HÑþóñ𮂓ŒßЕ%$£™£:Tn÷T§ ÅTzš“T&B zC>Èý,·û?Aždy¼‰ƒ„$ÉÒ›Ž¸ç‡[!‘OÄ7«õ”¤Ù"œÅŒy긇¥„‰{f/ŠÞÙA8J?»¿fEAäÅ\Õ ªûÖò%Ê êÕv¸RIdNd~'Ê\m6O«%H35ꊧ©»íÚ¾ÿVu \›øyÙ ª¯Ê\¢—N]«Á=K°'ç[¾&ßÖ Ê¶MN×Çu+ «.oDD8Ç• 45Áà©Jl®‚QÓÜpÅknÐ2…`¶e¦Ø2-âþО빵SPOD£ÌU Ñ›õvoVª2‘UmËÚ,íª£j¼yÝí: æöu"%EîçÁè¥KmVD_²ˆ &Á^\-Àä¼K¯ÙÖçêÍî±í”»PÚmc—L󇇪@P!E\Öu`Ó’-U··o»£Æ°¶ïÚ£áT«½å0´.;Œ>£ ºêÃA[ÓÀ•r»m»Ýˆ{àš†+#6:T GgÑ΄rÐ7 x„ÎvéÐ+ · e±Bx•ÆWü€ìX‘Æ`Ùs=”•—þ[I Æ9ÛÈ™™‘& !á£3Üß¶†ZY¡|¸¢Ý i]€;¸^õ F&³è¸—§SýY[ OŒwamÍ!ó|‰¶mGüYuK36»þ–8ðö‚Ÿ¹qü—ÁÆx4Æ<¤<®ˆ"«uʽó—ôB0+§Senƒaëá|ªUo9:ù|ÐìÌ‹“¸©×8HÛ“'œÌ2œÙ€GKê >c\ûŒÛÔ×}y´OårËW×VÎØ´?¹ |¡é‹±¼ÌùÕ^ýjbÅz´s‡W”__ÎǤ²É'.< ‰7ÎU¿ÈÔþ|ôÉx;#›~~ ú«á÷â!<±±\$G6Àff{iëŒküëD& «ù$§å¸9Êå^¼‡Æ3×vˆØHôVo6FÓÍëV>¯["\·3š¸œÑR„„ÌŒLùíK‹©s¿¼Ã÷cD )¢Ç(K ƒçœQDLj’Ù¸PGo¢×ƾµÜ-A 5’¼puÒH2ÓVÐù¨ì4À.Ô¿›öÃ:& 편·˜ÁàìLåok7€Üe™‡uñu,«ÉšQ8Ù¢ºÙ”]5` ª¶ß[Ù\öLÀ=›ÍO)á{ÃÙ±Ά¬œ¤Þ? QñÆBÂSÐ8ž \¤I!cšŒªKN(óñì ØrK›BLÊøˆ÷š2v𠛦8 ×=òj‰÷µO²¤ÞäêKYøBˆóÂé@ÙuYþnÆ*ªÑéÅȫݖ‚×CŸ@®ÉvÏéÞô>#Á&°~Äü€OE$$YŒ2#©‹'ʯÛèyÛì*t¢hý ê"¥®…¥)Iœª}¸|rÀ ij~²˜ Š .@Íš<Åøÿ*ŠªîÕ8ÛÁ0?ƺp¶ã –gcÓÃû­(D‹pr©÷¥é@ø` ^9ª²Ñ­ —ݹG¼l^ôÇÀð)V0}Æ|DÔí¿•ùœˆ„öXÚðÀ¬ [®S™ƒ‡Aé›ó{D‡nd>Öþõ«}è>\v)HJa¦‚_&mÿ§Ä~Ò$ðvàbΰùŸ™Jq*?¨/€Ò hz—;ÎÙ’Ín¹)ÄAœyˆäh¥u*LWeÒ}ýÝÿßμ© endstream endobj 211 0 obj <> stream xÚíY[oÛ6~߯p_y³8ñ&J] 6 Áº[3 EÒÕ‘¶”Iö’tØß9¤®6%Çn’í¡HRyøÛÇCzô爎<ø£#ÅàßM£W'£ï~¤ðN.üÑÉ ¾»Ô#!ôÏON䨥” ç§ì"™Fó±Ë•tâÛë<.Š$K‹ñ‡“c!F8É Q•$#—…„s-åe9(hb„#ü>ÏÆ’: ½Fè5ÆÒsÌ:–eŸP¿”,p"Óä«ylz³,7i¶¸^-“ôÃj`/ª¡óFÃÀùk,@YÅxçæÐ1å\–Ò¢Ôt>Ž]XÍCœ,/ãÜ¢,gñE‰u™¯b‹:ŒÆÊ!™Mˆ+d@˜÷€W¤7‹æ…U%4,eýÝ•„I˜i|rr  A¢s'‹(¿3µ „ [^6јùŽ©ÅñKd&¤h¡Õ"ÎÁVzP#Ì(BÏÉãy´„G³D°9 YÆy´ŒÏ è2’…qÞŒ/´¯9ø-Í´#ôËž)fdœNçYËé¯IjÚë(µ. ¥ˆ RZXµ,ìµmùÃm´¸žÇU.ÐõŠÈЄé·Ôæ-á¥Jwu­È9k>Û–pKÚNBK‰N“ÉÕ‡±+!s_`# ©¼uí¶ºöºÇÒÆEÅ)h9¹riµü‘YÿàM”˜îצ¹‹£üI ¡á'ÇQzs4*ˆ}ŽíkÓLó¬(L÷øI°½5xV©ŽI\÷Ä47@&¸—§É‡ NÁÃO84šÏÿN ÒÚ`Ó^uíxüi›”Uâ^‚í7¦ùˆJmÅ_ÂP2ï =™¡;YÞB¦{G‡mmêeðv¸#ùd€³-À]Æ=pM>Ó’Þd9’+‹8ÌÍCCÐÂëlÃúë43KGIªw:Ág‰¤}3²ÎÌ Ôg/êš-`ë ¸(§Š{|W˜öºií¼åT´Çª0[1pð4ΰÅÁÙµÙd ²|Gþ᤬mÖ†3î6ÅMÉ¢rŸ¨0Oé¹é@ÐN®ª·U^¼Õ¨¼5ZªÆ‰Ö¸Î¢Y¤URÅy2›™Þ]Ý¡| $Äå´î,QÚ @ªK;éü\o6÷.í$‘A«ŒððL±š/#æÔPR×Pæ1›a`b˜MØyíÊÃ[/ 0~›ò gb¹‡md†wëOmÎO KA% B ùpUFCRU©çÂ$ìJ23åŸVL—Ÿµ-|´W[àˆ¬;e­t JTnš¥î§8Ï8<ðœ_°Ð¹IŠxMÞš;J¢† J¡ž²šE·3TDT%çPYtÊÒÞH â7‘ÊÊHý½½™A°"ApZÄ}âõuŠ”â;o¢åå¯yvOš«‘ ±ß&Ų~k:³lG°ä&-œßÞVqˆ¦*U!¨caµ>F- dS?£€Š;õì•.A±—¤¦­`0¡ÜžÕ¹ú¼Úé¦öÐÃx·¶m2$Aµ}½°Ic\õýÎæTQyu£ñ4w§6YÜ'¢Ê¸[´€Bºe¹wåF(¡²­ÞV̇=ª{ájJ¢ü½P›²ƒ†U¢Î<&¬x`;a<¨<ÒϪîáP“wlmºO|µ¦ZïòûYø’²Ï°´°[úðÑÌ|ô‹(ùxªþ ô¹ ´{À9âòàÙ~ñ!ÂÇß²–÷9"îeƒ$Ýfƒ÷O˜#Ì Æ#| ËÚñPÁÉv+r› …V8‘Â"PÇ CÃáõ ¶• ¨‡L†Y ;êû¦Q±É£3ˆcëÁÌÚE rj[Bâ×z@ðÔf÷:DÈ!¯ J”Í麵Û\x›ù¸Ýè´kô–ß«>o5ªjÊoKÁ©\(‹©Ä¥6#Uáµí–H¥ºœùÄÛ‰õ᰼ŴeÔ‚tÀIA“˜}üèoáÇjOxÖ& †PàÈÃävxv(#PôD MÜ7•=Ïb«'XÛªqÈžžàƒžàûx‚÷e ÐY}þ~o­ì0â¿õ0kleêwÖXàxõff–Wû6 ¹‡úaó³Þ.ù΢*e$d̓m«KmY@ñǬ]´­7¦~µ¡4ØÃlN[á<ë‡!x“6 Bè1ìïßß]@. jÖúÝàF_eÙцŒlGkª»¶æ¹Øæ´íÚ$Zs©uy¦šãþ»ÖZþ[öÙ>﬷u~Fx_ˆlüZ›•¿;w ¼îÃ{>ßÉææ³h߯[!P *ÝÀ=±Œ?9ØlE ®´ˆX×£ˆ—ë·½Ý+ÚÎF¥“ë s«Êüjèo_ý ™Wä endstream endobj 214 0 obj <> stream xÚÝY_ã¶ï§pßd`ÍŠ)Q—§H€ â ,Їlt¶Ö*KIÎfûé;ÃJ”,gæÁV9œ¿?‡£Í¹‰áŸÜd þÇ›ýyóÇÍ߾ы<Î7ÏiD®7;H7‡ï#)¶;­’èc³Ý©4†SI?Úxڨ슡j›~ûÃã·ÀKf³<Æ€DäS5L1“&…ökR!%Ï7í°Ý¥×9%Z$éÈ “QÑÖXªT¤Š)ÿºÊKÅBz 6×FÍV¥Ñ弓?ÃH†³žé¹oÏä‘¶)8‹†žVVKÏ=ÅRwý°tcsèi¨?µ—štß)p‘4]‰±ôí.I4ñL’$ê‹3ÿ*úÅÔ¡:—M1¢WÔw¾´Ü·à*š ´N+Lâä+Dj:VÄGÇÉ=€q"t®}­†Ó±\a“MQq“›É„Ê&dhßDF.Lî‘q“ŸÖB[¦úLNäŠE,Ñ)K÷ûT ,~B•´ :”WCµ/jx®Dš‡ãw# ¯k^žqDáGWÖ.…›°adÚ®'šºê‡ò@¿ ¶ƒÕ#tåé¤ð8"ªŽhPu2§Á¿“È4:@ œaN‰sY4UsDô$Yôº:{½9£¹]Ù_ê¡ -Ke2ŒŽŠúRÒkå±eƒ°X-ŒËÐ]ʵl“‹8Ÿ@V«p3"ömrýþ=€ž4î=‰o»ÑÆzÜÅÎ0ðÜvL10É , pRv¯U_®¨ŸÄV$š•{.ê~͹À€iYÇÑSôÏv`Wê$*tåp*Ѓ4~;c°0ÎiÔÖÕ‡åäØžÈŠ®¤‰¶;”³^êòçjß»âå„á¬ß¶6qÌ•ÛJŽˆöF|8Y–”Í#ó/]¹/$u±Ôišq–sš¢mqh03Ž™xÚºÙ¯é “O”ÉžÝûc ‹d»“R™èã€;ÁY—™¨ü´éû e­œ‡Ê ºÜnkV¢'3‘û´V÷­« ,ð@))ø°Å—#˜ƒS5 ¢è­‰#¿&]ª}ªs胭Sà«sѽÑXÝy§ÁÌdÑ ¼BÜ0"'|ÅmÝÓ8à·â•DýíÀb?p `«Fg© pþ°æ5"Q¯:eûž~ÐmŸòas¬5ÇÝÂ3<‰‹ãèH‹Æ:lÇ’á);¾Âž[ÝpJØYÄâ5å)w-È&BqÑš½©u¾a7߸# ðÆ'¯°NB¤›Ó5S¶DH‰šÙx2Œ­µú’§™vÇÁC$‡±«]º}Ú>¬xGeBçcå¶”k§@½§lˆÖ >åÈ…F'ˆÒ;!4suÄ{]ë\x¸ìKæv¸œÏ>Yd12­Æ9JEðÃLnyݳñ€Š, ­'ƒ>kÖëLŒ»ùÐùTæö\…ÑÃ)2&B˜á×KÑÁN«^\ÁU#M¹¬Î†±ØeVä2¬>ò²ïàþԵǑIÇE#Ä¡g¡ƒÃÀÖþn`BâB 4Æ ^Ï…ìÑŸ8sé‰ÏdI¦BWôV«¼TØ +`‘XŸmàôaR ‰Ï’v%@©ˆ}=¹ûñÂ¥E…øžN÷k–VŠØÜÇò)òÚËP'¡üq^ñ|…kž¹ä#²B&RŠ˜\g%›‘ä+8»Ò4ú€löHi.ÅÀÝÅËÝ8IY-ŽEª'!|œÎ=”Ïj툊ǽòÇòû5S¤š.Tϫι?“3XÓ$pçWk¨‡„gDFšk·_ûwpŸyÜç¿îõû¡Ò¿=TúÝPé?îÿhμ÷³Â-I-zc—4e®*·+(ÝÆûÿÝé@ßÌØ0)^¨Ð‚üÀ‡Uù±0éB~௅Í ð©Â]»t"¹¼Iñ4ÕIPÞhWþ.k¢Ã8áS5TÑô6»  ¡W&ì+í¹¨<]Aõ…5‹Ò©/¡xÐàœöùFt_6ë ÷ f7\^jg8žoßå¾ò7k”ñÙ»#MYMéd ¼…%•NmXŸàªC‰üc¹ÌºÔEG«ÇËdOïp:6^<ÔÝÎ ‰Å ÞìjíZ82¬Hu† æœFð uR;öNÇ&ÐTüãšY·Š?eÁÅæ}žŽo_²8!÷KÿÑÆ(ØkAìJwGF_oR ƒfA\㯧¶çÚuÙ…‚¡)ÜV-_¨ëz}Xå¶Ëz=ØÎ|»ElÜhã}ƒ]•ñ®iæ}«±µõ•·N:k¥¯MS³ö ¼^µˆÃ[¾UÅ3éZsV ›¿Û“As.áæÜäO½ŒçŸ]’a²«ÝéX„Øà(¬)—¨÷º‡J!æcákÞx™ç@)¬ù•9uãžêI¸ôê6 'Œ9Ú¹àZŠ*΂òã®–"¹Ó(Û»¡©õ¯ª@íš*fÛ\»ÕC3½ÑûuÐTrZ@SÉš05ƒ&µo× ™Lýü{¼äš¹Š;Ç"׊28Ý7¬ ö›ÀySCØ`êwEg2öU¾<:ßO â½pÎ kÇF¯æFï§-7P\5[*rúê¿ÔõÕ÷w}3ßõå3^] -ͼúÚµCRO9µë`¦löuëZ"¸®bú§ŸrÕMï é»BH6kú޻#8ÿÁ5ž¾bê‚yrkxýËô}ãXú„âIG;éë©ïƒ/“¡ðB}³‘ðœ<Ïîôm¹`–ž¼¨åç®àY×û„Ñ©@|f©\8‹ûªóBÝ·‹QþºÂÑdTteÓ§K´\•ç€ ›¯ð2o¾ÂuÁJý›šlnž|–M>3ÙÄ]„æYß6vŽ$xç/¤.›}¹Á„ëó‘?·Çæh\.víû%g‹Šß@棋оWÜÒ|vró7sìß~Élð.Mí¢MLµ_â?¥ãö†_Årê=‘ïuŒLûÕÕ† nÕ†ŽŸç¦yÍ`‘Û.Õ”œTæIÿõ—ÿëZ÷ endstream endobj 219 0 obj <> stream xÚ­Yݓ۶ï_Áæ!C5G„~dÒ‡¦ug’´IîÍçÉÐu¢‡2IåîÜäÏ. ‰’ÎNÆSûÝßÒÞ;{!üá^"àoè­kï«[ïóóÔãœeJy·[ØxȲػݼò#¦˜Zœ åÛÞ—ë¼ZQ¢üvOî]>´]¿z}û 𑞠3dÃˤ8ŸhV/›U ¢Èÿ.vÿëÚ{|“þ°+º‚~e?Œ«ôcÛVU»‰ÿP6÷t¾²jà>ª!R«Æ ¼(é?ìÊ5žÙÑ:Ç—'zyCôôrè‹ ñ)z:Ì‹Ç}Wô}Ù6ýÆBžÌLDO%LeÚ¼¦, ŸÑˆ¥(‘äqÁM1‘Ù¾Y’³81û]â¯X]`/cf·›â>ÀC¥æT’ eȾX’‚¿)—¸pHåHw´ÏXjµÏ›Í5ÿ<-öÉcÿðeÿ\ÓàÓOMS,Ì.(ŽíþºmÞšµöbAÝM £_ïÀÊOîV‹r¢ˆÅòB¨2&b«é"Δë©@@ÀÚˆBÛ}ŒþÄ üúëÇ( "&­í›²¿„¶;!Noãü"¤,¶1øy‰AÆ’ ZB<ZŠU!æšìA—·NÇ]ʆ«7‡3Á/h“±(µ°ÄF‘˜;Ê)oŒòIÅ,DõS¦$Õì-TB©L=†Óz/›uuØ=½ÕmWع¡h³4•V©Üºe;Žü¼ZÚ4¬sËÙîmÛ®ÖÕÖ¶][!Åv0´¦PQÂ+B6uåýÒ)áçëuÛm¨»¨éBî=:ÓO@ò-·[CoéfJ£GiñÎï‹‚bãIü»Yì?Ü­Ø*<öowfÜz¨ðÚ¤Ú/+XÏ«CA¯'"§`Э ç•`Ö1òPº4ç¼DÝ¢yÅ—“>Š‹¥¡Ô1cHGsbKÏ|¿¯ž´û"Û¸O>íȯìˆ~"k6& _Üž%‰¾•Ä•|mâ`d‡ÿ‘¤ž‹StXžTn­ GàC_ QPó~G[=mŒ>ZÈÜ'wÉÓ4ÑŽnNB²€>²‹à rüwO9ÕM}]„ã¶„}}¢Šñï;EYê=€Ä`¼€›ŸzµÅ»”]¨¼Ÿ¼(ŽËì±:…ä$«ÂdÍmacŠèÌ;ÔEyœcPÍy?ɰ3]Žvf¹}IXÿT£8ºnmE"ß“ "Óad)²ž)„‡ …Ëób~,*}–’@,¥‹„ª²Ôd90‹-Øûr¹‹?j~ù÷¥‹Â™T#my1¬™iµ \IÛo¸:oá÷†jû–MQ!³›`õ(ãéÂæ3®0ês‘²lÔ?>¯ÿ?] x΄Xßãþ±6ŒÐõ\<¬!k„½@.ÄY0)]œKB«~` ýhÅœ¸MZ+²+|ÞL{+ïB.×WÓ ‰Yf=íñÁ©€H²(¹âF«ž0û+LÀ•0gÊç©Íž Ôdæ²¹ ôlˆéJŽÐû8†ñ3µ¡ó96 8ømÌ‚©¦eS©FwB˜F‡^fÇMKË2ì“ë}ƒÿðGŸ×©‹¼Ñm—-ݦ O*€Ò4 Þºkþ²¢!Ad‰Ài†í€DApêÖQD~:¼é‹õØ¡ËѧŽÿc~t÷§LIêAq°LЂ3N,ðôÂÁT0™9o(öù}ñ p~¢¯JçV„s ¥ƒž@"$5ä¡'râÈDÂNÒÿ¢“w”æÎ>’`¨ˆ4“Øï©[ÒR[ *à½RÜ×üU¢ù¯Tè›éáTD ®·³™Ež9=ºC5B²Ž~¬Ûz .ƒÜRkôTaÂÑá c0D8*†FÅ™×KÍ"ž¬²âû²Ø{^ŽJ¦òlU¾Tvf·ÛtÔ ¶ë4—Q„k–çG®©lõ ÜXC›K™öš3/[(ZTE]˜©ÀÀ š8º2SŽÛ‹3a4ƒÇ=û®¬ó0|ÔC¸C"Žàðeü‡”¹¡84=\ßuWî=Ø"¼Eª o`j:¢‘Žº7t¬+›3Uª)¤;>ÁÊqFÚ”} )/Q íkÜÈ¢À”é„y‡Y¹¥/ŽÒ|q„Õ=L¶ ΄À¤?ëô—ˆ0³¢ϼÒŸqœšiÑ%uCÛzÒ‚ç¡/ =»HÖP!áOã œ˜‚ «caÃñ‡ É Ü˜ži7²?W²IH˜ϾQ˜Îg_|Õ9 ”t„‡G–…c 7ž‚ùahk€XžhIϱiBepÐNÃÄ@WRåf—†·ýêq2uó/Èègá„X?Ð$|fJÂñ7å1ê/s(3Eáã3Uÿ÷KßÌ”±àÝÉ ç7lú^–8XQó˜_|UÞ¼}}UÚŸ"«?Ôÿ» ” ÜRp»¿ùžw~NŠè·¿Ñãq¶ô="‡àéUð×£øóêEä¤ÄNYö\+Ê­1t°–¼¤äKsª}Qá½Å_ÿ÷efÂ{×<&ÔUcœªöÇí™»^^p=9ÛYbü¾7õ0Ñõ°|OA—•¶ Çá “ ¨Ä’®ˆH-éù»‰åD endstream endobj 224 0 obj <> stream xÚ½XK“ä4 ¾ó+ú˜†ioüˆ“pj—‚*ÀpšÝC¦Û=È£IÒì ÿɲÓv&³; UTw•_²$K²ô9›ß7|“Âorÿt³o7__o^½Qž²2-7×Ç ÏX©6;œÐ›ëÃMòC?˜íN•*¹3ª†MÝ™jÀ~–˜‡Ó`Ʊ÷}·y2UuWww47áÌû­(’ž&úÚÖ È’ÓP·Õðøm…Üåív³}wý=(îô—,ˬþ Ë8 çýdÛ”Èi«”"9V?)Ag3 ¾DS õtßš©ÞÓ¸?Œ"ãOý02+êÕ›<°[ 2 –I+óõCÕž3Zº××de¾ לe¹%Û]&Tò96YòpSïøÕ¯_ðw4þ‚8uÙãÍo1ÁbýO+< Mñ6Ù‘$qõëÇÙ¿ÝRÿ5ã¹ýk¢.Ú Ûë¿©­nǷɹ^M¸-:w±áœ•¨™)•L «dšñíŽs`ñK7žoÇýPŸÈSy–ü±Õ]QÝz[®ÆªÈXVX~ßacV$Ó½¡ÎQ8ð%³2ˆ(Z«Gj«ŽÖÏ m`ém¦¼68“ƒ=ßßC„@8ÝÓÄxߟ›q¸¥ˆ¡½éîP·¦CyUóv{õL¬’Þo Û¹™*ºEªÇ~h·B'禢 «2ÐN÷ÕD!¼TAéÌ+Í>ì–²×eŒZwªöxé×݃.øÒ¹\¤ Ê®j#Œ®=XEg`m¤¹ñ< ÈX.ÝzíÖËMÎÊ%Ë5HaZY¾&A!ƒ™äjMFɤ~© ñr*‘; Ikjò„­ñãŠeÊ‘?§q¾Ð˜‹På,P¹[‘áêLònEe¸­œI‰q"{o³âoÉÑÏéÒÓ!7Q2Qx•ç‹ên÷øØbðQÝê*2ŠXQ¹9F;°FZÚƒih^ëU‹ ¸Û:ÿÔHRŸHšéO¤…аim”K£×Å‹œ ½q˜‚“fŠj0¤ÂœT\¥ßIÁp+|5çý"ÈB8Ì.eú—2ÌÜ…NlZ?·f°ž/ Ù6Åãíè/ù̡ӔR*npœU9ä8Ù‚­—£Ð¼8Ðbd­'¹ð,²„<=ºÞ|*YÎk'Uê£(\—I5R;/Íå†àÁº ðÂx8Î@MDFkT´5¾,ñ³æO?…œ/c5Ž$r_WP<ÈÑÞ³›¿ÚOgD¼¢®²4g3ÒÏ wI±X‡hÅ _Ø9¶ZáÞžÚú`¨Ö×ÇGâ^Ñ© AÍhÜš u7ùD“ ]¬;96¯*”C Bã`&3´PžG[®ØY€Ü€’+D‚R§L¨úH}¾›ï{ܺó¨ç«n(¥¸o3ž€lPJIu›¥‰Å©en¥âØaÕÁB‰ƒOEÍýæúÍópÉ¢Œp¬GLØ¡»»ˆIæšS¾@L6ù>™âšŸA~æqâiWL&•r¼î`@þna‚ÃÝd-wGVík5žç5Ä kü¥€ÇrùóÞ(ÁÿeèŒÔ=)ÒræB£Ø\E.€]5wp7ù¼7ŽÝáÜÚ+‡nMsäZ»µÒžÚvü|è›Ñ¹Fh¬–½kÞ ÐÕÊñUÎfúÃùŒˆæ KÍwRƯ.©æ§‹Ïsõ nƒÛ^Ï4æÉÜVB{¬¼`%3¶-Jeîx6{Àhþš ²H K9ºyÊDÍÙo× DwóèèýäEP½ÃÞ{ôH…eø‘6Vã‚6V'Dë:V’Ã[s4†ºð$#Kì'…ÙèËÎOߺÎp·òmGž;•.\¾øsa»×6fœ¥"ÚQ«4<°«;ó)ðÀ‰5àÙÇÅ—šåÑ&ü2¦ P€=ó°7§i6—+gJxp£ÌÝ`¯‰äDݨëy¿ÇG$;JSm5¹–Ëh "楮Ÿ µ2À.Rä¬ìR¤”+Rß`Õ›ìw…W§ÖÊ”`Ê—”=^úP†â"ªR8þx•R6€‚Q’A ¹T©2È¥ŒS¤J‹ø•ÂU) ì;ã:Gj)g”Ò—-Me‹ªK¦dôÕ%ü2iñTÙf¿Žë…¬€gH|y§>®=VÀ𩯠·k|xúÝêƒG_ÞÉÇU]RÆ}6ÍhžcâiîÖ˜ì )0§ºOÀÿï‰âG¹ëÒ£Ü}œ vÄ+|•ß®ðuø²D¹ÓôwõÞ^ ‡ÝÚ±áÜ3àZÓ9tÂ¥Z.^çLð…ïRo•ùQz©£á³1NÑ'ÌöàG­(gŠÒ“þøÙ?ÅÑ4{ endstream endobj 231 0 obj <> stream xÚ­Ënã6ðÞ¯ÐQÞF\‘z÷¶úضm€šY¶‰Ê’+É›¸_ßÎÐ’b%ζÁë!9œ÷‹òþö¤Â?ée þB¯Ü{ßÞzï¿=Š",¼Û'QÄ^€©w»þÿÝU« ÊS¿l›µLÛèš6jÓTº#¸zЦõ„Ũ'Èz$áÔê¨Æ’‚ðÄî7(ma ž6p«·Õ}§ùthé´çÐ,ÍæD;¶` °¿vÄ3õÛn]ugöËxØAx¤CœdO¢¥Ir W¬ð;ê —'ËÕZ¬‚\æþï»Ê]b¯f£É’l$‰Bõò‚•€½YÁ³Õ0ì2-œ*qÁÓÅhô«ËN[8bùAbÎC*¸tÀ÷Xšˆò$G ÙFÑŸ j)iqA¶\¿`ŒvƒI²i1ÏNÒtnÄ·R¤l5Üà¾~ztå„ör”ŒùŠŠ; üÄô/W&¥"¡òsiJ¹4}è€à¾l¡Ë„P¤0ÛîU%é£m²ÒÿY»O]»Å•B‘¬ƒ¬M?ôçm6m]·(ûƒi¶D@OE”±  (X¢‹xš3xçœþ¸8§.(ý‘Mj2Q L—}<¦xveáV^f L&’¢í°ä«Q 6ÇóÍ‚ Óû)¬äÎúØ/ñ ²PH5 ‰àí˜î õº~‰ä%çÍ¢Q+aÒÏÙ#ãóí‚hI(œdzM3×Iü?iúãýÐéò5Qð<. TˆÜñ{wEžEÇáòü¶p=Å¡'|=Þ] œÇ¥„Ï…,øœ‹ñ`5Œoè¨÷W óø²£Öæ³KhžŠ0µ-AEÜh±-pˆ¤ˆ¢l_`¶sd6ë% J¾J…•»n«¡ŒÆ*$ãù²@\†™È_òM!Rwl{Ð×Dz>ÁÊhÞÃ$>JöÔ‚†“ÒôLuP±ÐÊÔÑY—kgž‹\Ný o&Û´i¨¬Co›úô¤ÓZ?oôCÕíïVÏtôØ3iîC ˜ëk-ò¸¶Ã¬X/{A3FÛðÕY“Áƒqèj;û €^דÃs"šäH8œÏ^´·éÚýsãnµÁé¸P4ÉÁog¶;6A\@û+K­Ù¦X4™‘¿3 GÇÍÞ­x  Ä›ÈÊÓ#lòËAnŽÜtÑÖA¡Bš–ü“i IOFËa3Jt1Ž.Á‰2™5êl:‰Œžv¦žÀõE»»ad²$&¬:R:êŽÞWK™N{F2Ý¥c4ÀÃóåy*†§^>ÎSÏS?²—€Çÿ;Ñ3ƾÙxõÚ'yH-l[+ÀïÌž*^xNÀ¦{Eü̉'¢hö%$¾68hÐÅ-Í(þع™+Îòh5#Á}ð¿}‰"ì]AÝÆ}‘áõ#©*¯Ý¸qú‹>‹ÈbÎ\¦×?Š„±PÙxÅU<có(9FeÆdg½~ùê_ù ™ endstream endobj 234 0 obj <> stream xÚ•WYsÛ6~ï¯à#5c¡ÄÁ«ykÚLÛ™™ø­î$B IÙñ¿ï.¤@‰Ž›±g(,»ßžXDŸ#%ðÇ£\Àí›èÇûèûw< Ë2Ý`{[â"º¯þŽßõi4ýf+³,V›îî,ŠåEî¹SX”ŽûèGÓ˜v·Î9jw ïxôlM·ÙŠ<®LMëÊ ûÞžFÛµl³Í”ŠmIÊïz<þÕw‰O×þÀà‘m@ jAÖDeme*‡y› ¦d´å’¥ÊaµtH)âOQÄŽ ã=þØõÖ ?€4@R™}­{ØCÝê1º­èøáÜî‘U×kÌìe¯óbø“Ù¤L>F@hlûч§k&¹'‡Âì-}ODíïCuœ?º‹€õˆ¿Še§@Âu§@öFãê¬Á€ú‰ÖÖÔýÎB]õÏ´ìúÊôèŽ$ŸŽvÊ*Ħžg ]ÏÒ7Ÿ z©àwN] …÷‘Ç ÇpfñvžO“¢©=¬9HçTx3ÓÌ"ùÄúþ»ÿoAA endstream endobj 237 0 obj <> stream xÚ•ËŽÛ6ðÞ¯ð-6j³âC¯=¤m ´·{‹{e9ËÄ–\IÎ&òïá %ÊR6 v Éá¼8/Ò«ÿVrÁŸ\¥ þ£UyYýö°úéO™®d$ò(_=œ`}‡ƒdõp|½þù×Í¿J`ÈX$ð¡úpm7±\W]g›Ú!¿z ªfº%7«2"–n_wÝìTº®J»¤©ºÍNk³.jüêuu®.U½„¾8ÓTWõÀéM]iÔ7´³¬îðš–VlßÑÄ¥º Å1n»_&ÒÞÛÀ¤"RNÔcu*nç~ÁÆ•N }£!’HÄé ‘²!’¹!b¯`:1D†H¼!R—°!oˆ„ ‘8C$hÂz¬êêýÆÙ†8ÕL²¸^ÛæÚÚ¢gÒÇ¢/x©­œªè4ZıS©@"ï71,Ûsq8óÉX>Üá¨<²–=XM°Ã£Ø±Åd.bíÈ¿úP\®g°ÔsÇ'¥2# £!be@Ÿcŧ>‘w@(Ú²C(^?ÙþåEØm#°l›® fŸ#ÖõÕõ#{RRˆKñÁöUû™&Ž׊>q´åD_¦À³’>`BÞ5Š\»Š·ç×ÝNþ뤓)"ðV£ƒfÕ7§Oï¦B:Ͷï×vûn¿™" ô¤wÛ·_DúŒ4`™lµ›‰3ìå';%ñÓ;þûóv~H¿½¶?‚Â÷§ôûë·£œ!þÞþ'¶ó«í²µ|ô;¤Oûõ‹âP¾ØJ¥÷›A}­äöEy(^ì7Ÿa6 ]8ó.üàB óAŠ@ÑåC¦ŽUy†øêhT ÄÒGºþëD3ý@ëvèÊÖ^ýöæR¸Ë²µe"uãÙaÖɆ¬sUL$Z^.Ú™ ì-†Ÿ$fx’[ν@¨}²|NÉö.ÍmërÅGÞuz.ûw”<׉-Éä“ ¤H}n¦(›Ÿ‹–"QŒSô}k7Lq*Õ÷êp–« .;Š.Ñ»yœEa®OR‘%L‰‚–£å]ܶE®à©¶Dý‰ÛÀÖ 2Ü»ü€íiɲˆcÒA¹)؅щÓX h¥O¨ÈZ¤|ŠÆI”I_ÀÛˆ¡Ž|€|w¬ðuÇŠßàX£˜Ž5š×²ÈåŸEÃ岃vL²9¡'I…U©­–Œ«e"RýŒqs‘å¼Ü=6·ó‘Xè\§ßê¡”¢>$dõ ¡3’V :Jàê§¶¹a$}\ù…¯Š < TÆ—>’à¥!½ÒuS/:«T©H²¯{kžÍ½É–¤Hj7r–Ì%ŽˆÇ’,q*tò ²äK²xoÈ8×DK¹†ŒjrÉШäYyF—£+3"¿+¸ˆšõ_[Úþüs_éÊòÅ’ÀúÁ»0J€ùŒÀAÛŽ¶í×§†—*jL0—ÊÄÅ "ô΃'¬ ²@.E<«„Zf®—ä>Æ9(z‚NÍùÜ `OݲeÂø z÷Iÿ VóNn`Gvêï\÷÷ñ ?M{\âLÑBcr1‘ˆ¼{` +92 W~ñp3‘}÷á‚*.×Õ²iÁ‚äxM}´õvº¬‡FŸ5^!|½ºuÕq¿Áð1†Âk¾y„ú¸.üáRôã„/z÷]ñvɾ¢DšO¢Ï5GrÉÊzÌ€ÄEá¥àvÁP'u5è™}KµÔ"—LŠÛ¤… Ï…Yz“F ·œ-xí‰@è×8~zl:&óàJ…ïL’£­ ¿=ß*Ú;¢·«¿ÈyòxLA6vú§¹Ð“Ø€Ü%n€ââ|"•9„,Ï8¶ðE¶r¬«¼ ‹‚J´‹Ñçw,Ü=’Ÿ³ÕüuU4Ád¤tžÓwþŠK¾Š:ºÍüJÂ7^pxl‚æ¼Y3#k‚£ÇQ¾~ÙlßíGBqz ¢Ž“ãà:ðº$Þ€¡,ž)2°1œ%ïEµ‰©Ï‡—Œ`\0&Ç NqÌà´+?Æ?ÐÀÚýÍ=ù{Ö13â 2 :Oà Ïr¼Ñ3˜ÒÓŒRzÈ€zþ²´:ŠÙ«xé6¥•²Q®7ZzN‹Æ†«ÄÇ´ær½õîádîCqŒos4õ‘¸êó««êÈ¢¹*…]zkA\ž[E\[×U¼·GPPp\@…J8 GQ"´šv.ü~³‹S¾™¦¾¯ÀGŽƒ¦|¿L}·À’-³ÜÓò7SDôM}šº†Ó%tI—‘Í­ï„ô‹–5ÃÚ?4õPi¹©‡ÊŽM}ð49}~ÞB < ©m×&_륳ÔeŽÏgÆg8ºçåX‰\}½‹3B-\uš/¤)w¶¼HG”OûXSšBÈ9!bLÒÒ¸U<é!Má–àÙ“QšÒ"ÊfyÊhß}èÈ_-©¶ÃŒ+¹0.Ó×vÚåJ*¬ºÚŽØ=£ÏóTH>ò¬åÈz`TÓ8ÈS8lxã}m'9¨¶ëhúB;óTŒtƒÏÂák­ÑÞçÂ×Z¸ÇZÜjkZfÆ­iiœ»ÇÙº²t3rDÙû®žÜßaM£Î|6œÆÛ´‘tá¾~±@šøÉ»±†À>Ÿ ¡,nþµiø¡m›V|ñ%^Á] ˜îCÏÄZyÔ~øÂE›· endstream endobj 240 0 obj <> stream xÚ­XYoÛ8~ß_¡}мµXñÐÕ4Ú¢Z`»[lÞâ<Ð6Ý0ÕáJJÓ Èß¡HÊ¢¬ÄÞm‘¯™o>rÚûæa/„?ì%þCoUxoνçï1Œ1DYìo`>À!Êà{}á3DfÆ„ùÏhèóš¢õ,  ó›–·¢¥šig—ç½wçÞ7Ñ,õn•’ Œy…Çâ‘Èösïïón"^¥(¤°P}“a»H£K<(Ì: ’˜°ÅáVaê”?ŸR‚H ÔšPdJ}žKÞèÏuUpYšŽŽŒ"FÍÖù„è Q+™·m-—SBH† a®ØL# 8Žu“@3! Ž'Šž†ÉÚuºw^êÂhw¶?<ááÂ:B‡«ûƒsâƒõIb/UwûŒ<’xÒW Ü´»bF9ƒ+äW¹\éÙݹV½°½2[{UO'Ø ´ª§(¢š´î^L`ŠÝÃTÛVV%Ï D`½ü¢gr Šy>×½Û+ÀKbÿJu‰ßlÁŠÔ+¹1#¡ýeÆ&z´MÔMÎES”ÄG%˵øÑ›%~lkÑ40ÿŸ,ÓMs³lVµÜ¶Z²78¼ÞPvÀP xxÃ?:½$ë½& ,Ûóµ®™ò(Ò]çð€‚ E½ßÕ =‹‡BOï½i;:X¢…qm,|ôÆ–Rá¿­Š‚ÛÙZ¬ÄZìv¥Å~Á•_Ü©NÔ¹Ðßá RŠ"u¨  _Uȶk´˜C×?w|þµ3ð T𱕻íÂZ“,[ñ’Äpù5©4à ²ÛÐ]œÄ½8Ê—yû˜˜ëi®\$ØÞ)=}$!Òé\Ê’×w‡0ÊPòk@j…ðE‰ Lº»bÙEºC“¥ô— Ü‹².ØQ<'&©>ðza_ä\]%]¨˜E¡¯ÃÅ!h£¬“´€˜"j1•Ͼì蛈oJØ(¾UeŸ)^LåF– ØºûË ™ }\8ûcÛšàåÙÄ~Œ‹ŽpöÿôÛ@tö˜þøH¯~ZÀOøê' üýÐ ˜Æt!ÐGÉi29lU•ki.yçOÜd3H‹$Wmó´£Uµ‰Wva! •?•Çž¨­ÇVÆá‚7›»±²ÅÓ±„2b ®¾ H]ß‹­—hwÅǺk£¦«¹1Aֵ݈‚º”±G(£†26¢Ì)C5”±>Ú´0¢N#J4¢ô%™ªƒ•‘/Î~-}Q©ù }ßgQõà}º€ð/¥X žª™†¼õWíñö´õ °†:$¯Å†ßäíÊy‡‚c>ƒê Ø{„‚LQ0KA†‡d†X¤)€!™¡†5ÙäÕiH8¥ø>ë†ôHióí¶®¶µ„W®°æ­ÆMŽ ‡±£«Å2}2çË|ïš#FÝG±RŽŒ&*² ¯’lYöî/¶ù2Œ¥¡zí^ÆA÷›H¸¯ùí\õ#¨*×ú b}׆§ûö ÙÞÃ>##tþ ?<½ë“^ûÂè ¡nm}èÐÍKÓÅ¡‹ˆe¯ªb©—ž”º]]UU#ô÷×ÝÞ—V¥Ñ‚Ð'cÁ×½™ò¡Ç«4ãa'7ȳÓ^ÕS“F8½ùº¹Eªì¸(<ÿàK=ôl»ž»^_HƒêŵÜRÞ\\_ÎáÍì|{!çjQ×±aÅé?t³ð¥CÅõbvEU¶W=4]=ïë:ù“߸&ÝÃX}b€¼Þî¾ÕÚ‡Ó©jÂxgÿh:WÞÍb'«nÿ#døV ÿ‹U¤Q½H…:g<Sšú6zœëUƒç³µÏg5%=VV­Yë¾Ã•˲,éâæÐ`w9Üå9z¹KvtÀZøÍŠx( Ülm~¨@I}+a³öX¢)ܰóÒ³¥ýT=+÷×ÓÁZ—Mÿˆ¬kó†·*z4ñÈ8`m3y)µK?ÿö/;S‰ endstream endobj 243 0 obj <> stream xÚÍYÝ£6ï_A߈ԥ€ ˜ÓíI­ÔJíC«ªûÖíƒ7!·¨r@n/ÿ}çÜíÝ^¿´+ÙŒíñx<ó›'x$A IP¤ðÛCðí]ðõ÷2H⨌Ëàn$YTÊà yp·û-¼{¬67R&á¸I‹ð|ÜÜ@cHzûúá4VÃæ÷»SR¸¬bèÂ~È¥nÇêmÕ›iî†2Žb;ë+%ÒŒ?Ô­îÏ&BF"Ÿ˜ÜÈ\…ºÝù¸‰8Ê,»á|xèšzëa˜ÅQ.Ì´w'ÝÔû³ÑÂ3êèöئáûM–…º9ZÌ=ro«[î<À:ëpgèÁn seí¨‡¡~ÛV»Í";ÓâÖØ9ê^ªÔ Ÿf3yxìP¦§–?X´ˆyøôжJ’Ïu“Q¦øz§cäaeøÙ[Ý€”yøÍBçpÈñ»»à]‰ROw™ãm‘e‘(ìwüüâ18³(Ë£X’H÷aÛæHF¿Ûú>Ndµ»ß€L"™Z’g¥a‹'<ª®’2^˜@ìªúºaª4ʬaþÜ6g–¨¦yÍK6¿a¶ŽWÚà»n¿gbn:ó™|Ü6Ï»»Ñ¥b çl‚œŠ/æ|À1¶1bkC:g;+£T‘½åÉ'yÓtFg$•e”$fšc¦"NѵØl o½‹>ȆÔlCLÕM×¾åîè{ R£d ^¸7-™Ð.'Gù¶ª-ÿ&õÈjPb˜{Ý©1ª<öÕ¶Ú×ÖMcn×Þ·\ìKNl ZE™p ºtí®ë®åOGC²—2fRË£ÝêÆËÉ L뫘nG³Ú¹pøNäÂɈ\¼Ü }RÄÊf¨ôXû³Å==²&&©ð¤„ƒ×à ³pÉ£ÅDƒ™2ÜwMÃðÈwÖ=œÙ—õv´ö»ïúÃðÊÌŒäº JþÚÎJœYå†Þû£Š2Ã[Üú±‚F…°<°¹' çäÐì M1m±ôü$Σ4s•üúÖÇN4ñõ +a¼øLiyB¶ÐPj™ÞÇ©ô –DYr!ØÅÓ"Š…{ÄÛ—ÜF”«ç<Ê­¨·/Ò`*f>OƒÒ¯ÁÛÏW‡Ü7ÿ[ Éþ. yóßøë¿v¾×o^r…Ÿà_¾ÈF0ò‹R‡¹gÓøSýC.t+Ó¨,8iIiÚÄâÊÇK¤‘ÌŸñUèS „!2)BšÓDC'|Qà„I\maŠ“_y¤ Ñ~öâ(rL¼!¤ŸšQS"‹QÒë ᨰ™E_¤…4Þs»Î ¹¾*R…k¬ÕÈzàÄ”_ÄÒ“>!µ¦ÑÌH 7+‰ é@ž©ð›þ¡{L¦i¶­ÍÔB=Ðqb¹d—¹Õ,k3àk‹âá²oÏÑÝVU’,3v~¨é‡úP7ºçBlÉÏ ã:|.xä¬b².(pØ V#w¾ßOÝ`Ê ‚Xâ^Ë EB‘HåBÍ)[ÍÍp22ô´’N•_УjZ[³ð×ò"a*¤‘—皀ìNwgœ=¸Ð€Îì„+£c=—syšÅ1¶läØã3|&p‡*ÚpÊm,nNІèÌÍo9YÅ_ØN¹ª°–›¹/°A¤ZIx‚ ǃ\aÚá+á¸YQ, (t47,Š¢XÀ"Íšo¾èF ;0skL [Xľ ‹ø]YkcX$Y´üº€3@U)ðgTtn›sjBH*å÷ÎcÖò©®qÕjP’ž ²X”¼ 9¿••`_”úL!+£Ò¦ ¯n}–̹ ¾»[§ÌV¾¤jn–G°˜N¢üpd'ðÛø1,¤ʶ;§½Í.³iØ—Qº·à„LÅyµ2•Z„L ß‡õž{õÈ(8)J}°Ü<6—kQ;8ØõvíÀ3•sÒõפ˜ölyX÷½¦pr¿‰Ö¨‚¾"…ÍE9Ý=]è†!‚ _š"½™ÛDK,2ËØ>ÔK>"ÛÔ>ðÁëÑMå+4Š)fqü`‰û €ÂlÚVÕnà ÛŽI;=j¦ÀÍÑ °ùbÓúzO<ïë…öÖÒÂ剤¡ÚšÇ¤LÅsÊ7&¾cø&”Ê¢—ñ *ç÷¿B]Ï./Î"KûR ª6‡È8~`Ë[-†æóÉBˆ ªÀèÐa‡s¥ 3‰½ÿ§“4Jío'»j¯!Tû^„'‚0_ Ø™ï,‹×¸È 5`²xÆÚ[(œ~á¼Ò Ÿ”I œ÷—'Êæs/ÞT“koªÜ,ë$˜MuR‘úÉ‹L ¾éµ³Ï²].0‹’ôÊIEi°ôŠeªØ€t̆ã+ ÃQ(ˆ[ˆ•–R°Ç’£Ál}­§'sT&+§9dÖi! E¼ òÒSíÒuÑ5[5$F?˜àÚVµóbnmüÆœÈø#¹cv²K‘|¨A~j–V @~ªí ÿVÃýy¬î#û»Úê§²4U¨„›\òowBÚ©¿|ñ'¥ ¹Ÿ endstream endobj 248 0 obj <> stream xÚ­X[oÔ8~ß_‘ÇŒhLì87+-+XöKµ/”‡4ã¶\†$CÛEü÷=ÇÇÎ8i˜Â µ’cûØçöù\Æûèq/„?î¥þC¯l¼§§ÞÃçÖ$‹dâ^À~ÀC–Ã÷ö­«›€s!ý6¹ð‹¾*Îkµ ¢TúÃXŒªQí&âþ¸ywúÒ{vê}ôX”gÞ5^#R–K¯ñd’0Ûyí½ñ^è˜ð‚8ca„ø-2Æ- —z(O˜£pn’^ ƹðSÑkÖŸg™Y&@¤h‹Ž"¿¨«b Ïm×UkNÎ8ä“‘9z²ru΢ÄlãØWçk—ˆœI±¸DÎ/IÍ6û& ) +·oby\¤ô»DztÇ[è¢0>xÂÎ]o¸®:9®¥¹ã5W> OSewܵˆ'2#^eœTà8»m6"õÏ7 ¿««’v~í.ˆp¼2 Ÿ6ql±úhÅ`q xÆâˆì¦¡±"VŒr/Äj ÛÝXumQ)Áðí%íÔÕ¨ú¢>¡Ùõˆ,ÿ §Âv H櫲: ¹T‹K'ŒJ£V4SKWKKë¨5ƒ¹«W”±4ù&½ªv«n&ÍÔÍ®WÃûߥ Ãþ|(ûj7ÒÍF8Ç…“®ò~’® ]è/|˜æÓó $ˆ9½6÷í­=­(d¡\{[rN$,ƒ¢$Ž%ÌÙýˆÁ9ê‹£ÖÉ]ß‚E$Ï„ŒÄïñbÉ8¹àç'+¨¡‹J|‘›˜ûô*ïÕ#IYBX?ÕtþTåêñt½AÁ{Wnßn¿ùÍ~UÁ,g‰Ðb<þ± F! /ý÷;ªŽjw4©|M»"Ž)Ož¬¦ëœÿ?Ý æ%É1ÝHR\ºQ[–õÞ`ò›­«O`)Tšõ³›¢ÙÕ÷(1&Ú -ˆ¡‚¼Á!FDë1$n¡š&ÚÛÏ/N^~9FÑÔç]…YÇ]¿ýrb—t8™ó,! VãÛÝ;³þج7EÿAáú1ŽÃØõês_\›Ãœ±ÓüË1­äü†?Ws_˜«ÞÏ—_..­¼´’wž1ñúT;53§ÒÊT¬j0ÿ趪¬!] D€Ø‰ç(‡<‡¡ÿâ‚¶ s““Åa:eq ¨Ì]mg6åÀ‹†85à‹çY²•Õi2µ¨!*ŸÁ¹?”¨‰ì”MyÒ«þºl‚Í8=S)s·^à) mq´V<%(mÛ Œ:LõÈÙ÷6Þ›ôU=YŸ(çÊTø"„øœº>}6?(îA°ªËÅ0tÚÜe¾Þâ"Dðj¼¢/mtù±!ª­ªic¤8ó« úBƒ!  Ç‚–­Ìñƒ4F”®7ÇFs®QN ¯úá+Î&Æ2J5ceš1޶õhÍ‹¬°ìzÀ0…Ã7RaæÕ£.¯àÃÕq0ÚÍï¯þñâmîú(Ú¸èz-ý¾.°" 0¼2ߨrtÂ7µØÿf>úË»;(ð´©(8ㇳxlåØMåœÂRV W\ªïà,¡Qã³{’{yǑƤsæl±! ÿÏnD#f,FúêÚú–¾ —"œƒž–Šrܵ=Ó« Õ«¶Dã\» Æ¡k §²k¡àƒÛKÚíÃŽ*ÍÀÈëT¼€;ðÿ{ôÓ'<55&ýT9–õ~ks&u%Nî·ÐÀï ÔA`aMR]+ø.U Í ÜZº¯í4‡°Œ¸6‰KîpYr/ªÈX65§N©½ð¸ÄÖÜt'ð@Ö~à,µ%‰SßicKdk`#¸Õ`Q§ôQ‘ƒE€ÌxNË«:3Þ™@pGyè›—$0’Cë>s®u)(“ØË%y®s–ä9d"3´mB¶M|E[“m‰BX^IYR†¶QË:JžN'—Z/T/ó÷Ý~˜ ±«®‰r}k½2â9QúNIb`›ËÄe©ó^f‘›9á1ÃðhùÌEqfÒaf’FBs} 9”1)anîÕüX1ÒX«b0Ÿ]k$tZ2Zо górk™ÄÅ¡Vu„ަÂÀfØé©<6@Ö²¿Éòy$gþê£ ± çÍÙ,Rs&my +“> stream xÚíYëÜ4ÿÎ_±ßÈ­;΋$@-*©…ûv‡Pn×w›’ÇÖÉöî¨øß™ñ8‰Í]Û !¡])~ŒÇóÊÌÏÎê튯BøñU*à®¶õê»óÕ“rÅC–‡ùêü¦7ØIV绋 mTw¹^od˜ûb-ÒàÝZd¢‘¦…'ƒªÅ™[3£q* ®ÖèµÇfw"º–Ö”×´¦ î»u,ƒB—ÅU¥heÙVo¥V;¢ëíVÄwÜ¿Ù4ê¦èËw(€2[‡Þ²øSi»ë‰„¹#áú·óÚ‹c£v·oìEÑ´#vÔÝ¡*·e_ÝS¿;Ðì¶¼ ¹T;fxñ˜åøe,Ž ¿ó=®yp<ØûÂ0OIÓ¿ ƒ'/xê¸$ŒÇ !²zöµ¥p}Æ9“º ·*ú^—WÇ^癤DÛ u޵Òå–@O­º®l¢»n­ÀÛ¶>û²¹±›Øy_/>7î†óœÅÒ5q{Mì÷Ö´n$0p‘Œ‚oQ¬ž¦ë¶³-ˆIjx›Žž²Æ„¾kH[#ìÜ£ŸäÁ<Tw•QhdŽƒ¢:s‹ÞËB&¸uÎ’ób–F®ï€‘+y-ù.$ßÁ¤ï;÷|ä»Ð÷Œ3ΰŸÁÞ4~»†ÀzO‹ÑOäʳ,s]I†w8Š„y‡ÑäÖXÆlHãKžiÚþ#œcWW­ÑVÞ–ý~GFAG®}~N9C”,’ÉôDÆBa’L®!d… ¾o›®×EÙ¬£ÐDb*ƒ®/zU+;dY¾]±(ÏV·†¼‹õJ& 1õªÕ¯«× «ˆ–f@‡ Q‘pnq`„Á˜H–PZîXÏl$e¡HYšØPjŠZ æ* k÷][£.K)&brˆÂ¯XC+Ní<Ø:d ÜbÁ¢ÛmýõÓl }bÊ?ÀTXê§‹"ŽGÓäÃ{ú´Ì³%Ó9eôOã:˜& Y–þÇMóÍ?nñÔüó±E)Kâÿcñߊp·a c§Þ nÍq«æ™SÀì€S2ÿ¸ R`Í'§B‘3‘YG @¼»¯eX \³“÷ (Ê©ÀoÇšŒèðé‚ý6´Ÿß(„‹Yt"˜…‰í¡‹••P¡Ž(¨Ê^颲.$ ” -m‡éËò;Š%)fäuó^W³(›^¥Ç5+›ºu›Ðã'©gñÚñªÛêòÐg+œãÆQ[ù1n$mA‚‡¥9‹¸£µæ¤)$§5ªÐ4äBdœ;vˆ-qÏ™8BXYypŒÂ´Qä#èE¹QͬݫÐU Ñ/àpð}[×…eyÝVöLŠ–7Y’dwpõ$¥µrmNà÷ä(·uÙ÷´á1fG£]Úà ýaŽÉ÷æÜêÝR6Iò “9YZβôž  ¹F‘†°ïsvÈgAä¼Q[0h ¨œpº+íÜ·ú1®"™"Ù"Ïx™§ Y˜û yàŠ%Ùz8]¶EU Æò"õ‚Î’Ÿ‡<¿+êC¥:ÿ8’úIUÂ1KÊÉ Æ0ú+RæŽ_ÒãÞëýyFO¨,æÚþ3ÛçOOï;ªtzo­o¬!dìü/»aw¬ß[CÓ½û‹Zuñ‡ºxsÖÿæoTw¿ÑÂvsgò«¢*š­z_úÛèâÖ*ÐûVCâuiî•‘Ú“Ó52RÔ}mß'ƒ8&ñsº=^…ZP5 ”FxE[ `ÜÚ<;z"Ü2ÏÁú¸•H1(4Ä9Eb‹÷THeGjq.6FÀ’ÎÁ’å_6³?½zòóËWÔ>èö œAëVÑ!ßôpò22¸EÙòö+䬊}/øåÛÐ7§_  2‡ÓbxJbÇŸÖãÒ…U©ô–Øò{(nÔ'lÍÄqá1J>¸3çœÅ™·èrM½Éc–xmr `:cdyîp, öˆé=*cqÓj-õöà¿·¯!®ÂˆÃ™ `e×Ï]º,BÃÈ$ J†·â)¶šmuÜ™<)EÐ6Zâê Æ³ÙÜ Ëôïzqx§ Zæ ¹BÌŒkŠfG “Í_ZÙÐ3Ã]y³x”„À‹‚º+?[b²„èCI2>ÉsôˆäÓNß|è“‹ùîgØ~O*»ð®A²%‘ëS¦DnÍ„_ÉÆ²hR~Í2Ÿ-pnúô…crÀ g# x‹Lк|ç9SÐŽTQ8­ # ŽìÚ#}˜ƒ±¥Ðt¬wDê¸IdfÆ·òõgŸG- endstream endobj 256 0 obj <> stream xÚíM“¤¶õž_Á‘.»eа_’²SÉ%åÊÜ290´fš„†Y =»ùõ~Ò“hAÃ@ÏŽãJ•k§¶Az<½O½)øÄAÿâ ¡ðÅ)øÓ]ðÝ<ˆ#’EYp÷Ó{ý"ƒ»Ã?Ã’(²Ûsβ.ªóAu»=c4ì­Rú1ÕççVu]ÙÔÝ·nÒNÊáR8xù"¯qâa·§Ih¡rœ¬ÊZåíü‡/ÇÒáªÔcjº~÷¯»¿Â0× ¶|:î`!„3Ÿ75²Ã1Ì“"1 æ«/øTï¨ Ï'Õ–Å”¨Ž˜EcA2 §D0³ð_T­Ú¼/ë'øBpK«á©1kT…拏ŒÂ¶9?ÍŠ0Ú=£Xòÿ‡O”eß!pdôm^Ö†AƒOdZP…¦û¨_Y˜·–€¼zÑp¹þïK‡“êç Ì«óÞp³wì\äØ+#È4|lŒb2'ý,T¸niˆîüÐmùÜãë¡9iÚŒ€‡`!MÂø@¦aó8A8á¡*• k<cıþÜÖv¨o,1Ž“aD/pe ¬Ö¢vGÑz+"ÿ­ŠÞÚGw.4)Gk¤nT¡¬á“ç¼ÍOªW­°vÇCä·-ó‡J-ÙÊŸ ¿çª6•¡±Gý[ôç\“•&§€ñ±„pÌzèÁ½áW(Txn áäf»>¯ Ôò(²¦‚ ÂìýÿýnÁ*Ц7@Smꃕ ª‚¡3Ùôeq®Ð¡y¨€ k2†5èx9+²³ß£O¶`x'e½9·sMU5ÚÈ_–dûW0.J­ÿQ*®D§'ßJ/†OE >&Ê^/öE€´ÑÚ*ûèÈÁwíR7”Kc—¾ák”ˆZØ-,_¢õ³·Ñ,èà©üY¯5ìÌúÜÊn|ª;W lg)sÙ^¹a´û`p÷c{ æÒ,Ea(ËG æ‡ xЏ–žÿ~ %1µ¹È‚„d‰ž$‘À ‘¸B<‡“Vt Ÿ¯pHBÙ ŸÊ”°ä‚â›7Ñ™xkÐ:Ù |Ç„N¹FgDXléü°ÛÇRâO~˜S'‚[èÍlÃÀßõ AäŒ~<$Õ3tf„nQÛjHѺ‚>Z‡JÀ‚“‘GÍÓÇ^µrFœ®hãD¦¿ùïF¾ÅÈÁŽâ­†´ÙÈÇdì„LjáÎŽyþ $Cj‹I,-=¯%_4JGB|;·†ÔTl\‚nXbÏ"´‚Vcf—§ ¡ÓõçôÊõš’4»`mš%ÓDG²Á³ÆLÙº‹~­ÄÅÖ%6JœODmå¿*ñyw”+wÞ¸ÇYGÊÞUŒ¯øê«b䯊Q®ît}OŒn0\c³®ÜÕEƒÕè}Ë¢T¦îçíWW¦„ÓQí¸fbÑ:iPNÍI ÖJÚ¨ùU¦ü³4Â!G.q*»T{‘¦áÝQ™Ú*†lÞ”f^B ƒ›Çy¢7gþ )µLœ{,3î"Þ|º’ Ž\éŽKÛ–XÆX£é_,©i¡ìX¶ÂxWD @›]7U ¯¡’$†5¥ƒ`)ÐPúÛ-ס‘;2 ’0|Ì{ô+Ÿ°N^›’F§U& M*¿«–@i›@¶ÁBÍÒ!o®ÖlO˜}d7!Éaà¿©ùò>œÄ”ߺ‘ ïûDWVÄ}E ©Roõxu²µþ2+oÊE ßèÚ–.H Üøæàô+‹þÄF7ˆm… ™²'Ü›µ0—1c‹m­‘|›n‹aãT`³Ö3<-zO\R·ud$ÍȇÍ$sX>ÌïÊ…Í]ŽêH1i¾ûÑ}Dùõ.£bŽÂ”ð4`B‡M –]ùý5‘ (Z8Qv[\ý:Üœ$Ì;Ë2×-o“ìñ˜¤éÐd©p±OÌtSmKЃ’¶%¨‡‹àМ*‹cÚøc&ŸÓUÀ´!òÁ@ÁpR’ /™ðÛ».t]º~òºëçDz+¿ˆ±Sp™t1CÉôò¯uCÀ„â­m†øÚ 1G¬·²ø·n‡ÜHç­›üF¶oo‡°µv_i‡¸ñ^ z{;*ßä1ýL⫦½3¾›¸Ì9ñá^¾8&Ñäüî¾ùȸ³Dw†ùq3æG•™†p›‹êf™ç _5kz‚¾^hì9lãrî<ƒH^¬Þö’4´çBi¨ŠÞîQ•Ùu%"WEIwì—DÓ"B¦¦ˆ@ #õ†Ý žíÎ OæÌ~/•†þ¦AüÞ1‹ÁàU<ðj]gÏB­%üëOt]Ò¹jÁÔ%l\—øeÄ¥.a—ºD.~áÖ"|½¹êtfº(1ÆœŒô.FÞë¬âÍ¡Y®fIâg6•y[ àë‚¿_qòµ™ }:ƒjà+_|5P¼VJH¹Í–ÜnvžÇ’üV?{Œã'¤?Üá-›8Ò' Ìô¹„L÷N¨)¦<ü;ìR’™Ë°°È\FI¸öÿÞì,¶½ @û) ,Kƒƒ-5}·SÀ¥Ô}A7Pÿ~º@ØËƒ úEƒI†t&¾HP?"¢„cAp*ëòTþפ>÷áΠêüd·.ÈŠÝy=Þq‚ó×ɘ&)åñéX5"µó:lî„çKf<Á&¨>³Žüs>þ2SýØ«§üóÿ!#¾Úµª#á)Ô Œ”ê[‰†”̳;à©?×£B@(É.’¸ÞF äPÇ‘»´‘Û+2_N:¨ÙÈ[áõ)æ‰ïþxqλ|cs¡3BÜãšÞ=ÔÍ q‚°+âl£¯yÖi†aía-Þ¿¨ãT›Wö&Š“ bóØ”:²« ÒÁHl™çg†990—,1ghö˜Y›ÏKõž´…»²>¨Ï—Äó&m*âßïâŽ8OÇ|«:‘ãYÏà ŽQŽéó ÝñíAž;w…ÈÝR*šÓó¹W3œË›JF[þÈiªSȽäXe°Äþô‡_OÁç endstream endobj 261 0 obj <> stream xÚí]sä¶í½¿BÚž—'~éã.}h;—6&Mz~Ëf:´Vk+ÑÇFÒžídòß Ô×.û’{ÌœçD‚  bƒDð‰€¿(Èëào×ÁëÏ“€G,‹²àúË[œÄÁõþÛð݃©UÑo¾»þWðîš°ùºÈ˜Ê,z]6e]þTl¶Z¨°½ùþ Žtø@ŸWôáLÓàÏôÙ…«õŸv›·–!Š"™ÖDÛ<,hí`ªÿ»öPŽIª>Ò°lè{ìö¿Œ#ÄüöøÝŠsm~(FÜ^®çâše ø§LKËÿúX«,…cÁf~_äCùa#’Г°ÌPÔEƒ @û"¯Lê³M³ / °Í6“iøÅÁ!Ò§?ÝôyWšîÛÚ”ŽDéH6­[ìáäH)/wWÅþ X¨(@h<Ûv<ΤNß)„ ÊBF(ƒYØ—hïÂ>7pžÝ†æÞs¨( ÿl»û²/ˆT9¾% _ãÔÍùBß"L¥`r®ñ$FÉiy»/AÏ}Ù6¦r$»Î tˆö@à¢"ƒÄá@˜>ëõŒT$´dÀjaòwÕdOÜ®¸ôœ´‚ Q\…¦ï[à’†y ®°'à}9ÜáH[cØAÝZc틊æ—Dië.,4B"¦µ;| GëLDæƒÅ ÙÆÉܹÍCÿ„3ÔElî뀉̴c/3bo¿n=ç“Ú‘•Ìd˜·¸ûÑ*¡mö„5´´ë¶hЉÀªl ÓÑ8o›~èйQÕ½ãåxX­áàß_¿þò‹¯i ×ùŒCtm·õÄ $vªÌnx’£ÿHKÊð=j©mưFAñ¿ÿpƒî–Ý*Dš¥@_D,!œñy?nõíâKäjÛIp4·Åǰל¥jE(~ž»NØšùnƒWTÉðŸ-ºÈýìT|°ÿwV0žšªüÁ9!Î/@2Š]]¼lnéx“yìS÷†`8º ‰6™ëжÙ£7&a{jöÅåÆ}QùïVºXÓrNcòMüæÃÉ:[šÌÒ|}‚•M^öxciF»è˜½Í®B oòâ c]Þß•9Rº£ÕÝ}¸þ+7+.AÅá½Ò^üúM7”981Þ`!Îã‚ÖìP(E÷ÔСlã“ š¥¹òñ°Ô^ÈB¼€ÅVi2òF¾ãf^ö2šKÏßfVI1K€i¢g:챂E¶®4Rú·þH’²L|l(QO:Às*qø5 ry¦ëçTž}ôuó©kQ¾òø:‡=þ¼q|‰BTеªfeî¿b[%µ]#‘faw²ýÙ»Žƒš" í7à|_P_ɾŒ—r¼ð);*š­åQe¶T±k”Ë4Å`Šô‹!ær¡Â÷mõa##K)QómÐ0Rû1`2Kƒ{$¢"ˆÈ2¨CXÔ  Þß̘LÀŠÔLp@µ@ƒ•Ð.ûøœb¬‚¬›ÒÍëA0wì·‚ óH/XL€%›•Ü€©øRn,òôß•†Ã©¹/£Ä 6ê>ºè»Ëˆ<]F²¬ÓÙ. Û„An{DÑtSiB±×)øYC@TÛœGPÓ~¬H;\P0EXùT+Öôý©.\eÎý¯h\“;Ü«•eŒG„¾X8¤ÿÇ EËSˆ,»ˆåÊ Èßö0n[qÃ…–¾7Tj/iC±§´K vaK Íúxrí;XY•ïÈÞK;A£ öäð…HýT7{d,÷âb÷SP€µNÌçˆoçX‹d9ßH«¶¹‹µ¢%çMc±ø¤1ܰp€Ÿ» l'Ò|±ÅÔžèz[ æ™GŠ=¦w}·Ù%idQñYog+ÍâÆ£é€Dõþ /ùªÜ£Š,G#Z¾c¯–oe/€öÖ)ïÏEô8Zµ݃ n(ý´û&ŸÂ‰+f°ëaÎï,¸¬K·ö»ÈJýWT´”Ì^uÔn……R’BF”SíoGIf]ÕuºgË#žý½)ˬ*.XèïÚSµ§ñtDt%…[2´fDu a9ºÙêº&g¥×:÷¨ÕK*Ńoc•ÚÓËtDýæOÿp’r endstream endobj 264 0 obj <> stream xÚXYsÜ6 ~ï¯Ð[´©W]IÓ™IÇyé¤vûbûA–äD‰Ž¤µ½Éä¿ H‰Òʉ۱gH ‚8>­óÉaŽ̉8üûNV;¿ž;Ï^3 IOÈÐ9¿þ–ù^óü•^´Ù2Æ¥ûÛû"Ûßý¸ÙŠHºýE]4H6WçoœWçÎ'ÇIìÜ¡y‰tjG†¡Ç³®œ3çí$çqgÄž/@ç<ö˜"Ë"ñ´Œ&éleàÅLY—MÕáÏ^Ç– àÀ”ÉÛ:--4S'b/2RÏW´À,0üâ~×mæ}_¶«Úî ¡¥_9½àÓeÍÚ¾°í=ãÂò­-ÇØ†‚|™›ÝWÚ×M<jË^1LÜ´Á×ôÝv7ÀµÒŠVe“÷eóŽVxuºö b÷î}™mxè¾G±Ûï6p ·ÈÊKŸÉ¢§]) ýþºÏºr7ÐyÚ8:ó†Æá}AP¹e í#É«(ÛªËlÉþ-^ Õ%0ú`Çðbåí0ˆc#¸úxrþv¡œ¹†“k`¬Úwe¦<‹É´ž¹‚­¹„è‚KUYÛäå0jZ…{ "Wo ÝÆ#¨9÷6ÛRîÒ=7Z³¶Ò—ÚÒ=,µY‘ãS»H‚?ù,¼ýozhŒî:E·àtÁ•½±²W·­Ëa/7Z… PU˜'z¡4½ºOë]~ÒérœòøŽ¡ï…Á”ïÏÁPîqÜi8ÐðÓK i“ÓD ÿ¬Ùþ‚}X°)¢|Û“TjÔÉý¾þR’$Æ2ŽþuúÇWšöûÝ®:\”W´|i¨õ—ó=¿¿:;×{ò¢[.>\ͶîLçÉqïé •Ìó˜ÿõ9-Î.Ê“Ws¿G»ö =œþ3<s`ŶžK…OÂe¦"i옑H÷VU‹|×ÓzÚ¹UyAê`”Bbí«Ò¶h ·›ÕìµV 15yMù„D;5‘©r1s1'jÙ4žªRÆ\rô÷ì"mR ÷ô†â›2YHÛ0¤—ýZûà‹LÁ½I«¾Xñ1gK´Ì e”*³Ÿ ­•qLÖâÄ*¸4Eç¨ǦÕÌ¥ÛT E“®Ù#")uèÝMÛÕèo¤µMuÀY³¬w&~ìžeòæ âÀXûÀ‹Xæ‹p2_D:Ä"bȳM Í T£„V ¥†Äñ‹¤ô5NŠ[ À¢;˜&Ïìê&0oºV'C4šØÛa?hì%7..ÑgQ ÝSKŒzžyŒÙΨR¨°>4Ì´Çô™L˜L-Æ÷çÝ ˜Sáö±ÉgÕ>×Ûò}]kOe¦ÚðJJ…®U¾Í÷¾­f¨1k;8†\MMÅ×0⨦M†yóÒ¿À¡‚ZˆÆˆþ^ö»*EÜyx$€ô ÕMhJVÀ(3FQLðïÁQ¥&‘+ÓkÍjx" ¿ƒHcƒSàÎk:¸Ä–e*Êq„&ž0G@Ô±0¢!t½5mðc@Ÿ¬Xdiû–AÁwñèø‘`;öš )™ýšDx‹X¡ìo£ãØ ¹ ¹O•˜ÏÐ1Ÿ¡c¾DÇ\hH)HüE=Uš™BÇ|ŽŽa9¢c®Ñ17è¶Pl™f l¬¬·2ìØX,_mÖ—`Æì¾$¦0™‚&Z øÒ‹W¢T>¤igº(ÈêF§Ð0ôÀº´=`°°”rÄ BXXM'è«4 FŸ¡ë‡éHâÿ_P ÆÿÓÊ òxl× jŸh¤úò‰Fx÷z|rX0†ñyÁø¼"Ma"üú©. $~ú”F¾§×™ŸÌËÍÃ'>¸¾1 µ4|=¦ ÄêŵZ<ª ‘,ÒFľS0I…sÀéi šŒA™,¿îr-ÐÐH&ý%ÆÔ‡ Ýu%!Uf—‘G8©O2ßsGPhŒb8¤ÉÓ.×!ºv{Ò—.à?i«B»4Q¥f:÷1)¥Õþ#/î T¹Ðb—+ Žå NO4…#•ìÂY'Zθ34y(÷Kíþœ¬ÒS8½Ñ§é‡ Mö“$LÕS‡þ0·øqžL€àÄÆ™Ì‚hÀÊÒ}ƒs}Á2…¤±^àbqÉôu7+a‘kø>iïÃàSøÖz,ød”dæ¢ÊÒ½xÖ.Æ»F†£q$ŽF¡ö° øD"Oœ‡Àt¬¢(="Lä ‰''„©P2*„„©tÖˆ0cƒ0 ŽÕ–!À—ó(´ÑàUw_ÿ”©øñ¨çhÈ« Ï­Ÿk`‘ÒPk¤\T´nA(ÝE6ÐîKô1&| íÒ.­ ðª^ßjU]™^W…&fmÓ]ª‘¸"F¶ÚòVE“îPÇán¾#ÓfÝ;¦MÍZ4qû6”Ô§DbDßþð/ÙŽ±ö endstream endobj 267 0 obj <> stream xÚíkoãÆñ{…jÀ= °>–yn¯@ ré‡$ˆ¿Åš\Ù¼ãC!©XNÿÞ™ÙÕ’¢ @‘/ÁÇ}ÌÎ{ç±Zý´ Wü WÛþ‚UѬþu·úêk± ?òÕÝ~&~.V\HWwåGïÃ~½‰ãÄR¯UCKÕ@+’>E׎£¼¯mw÷ëM’zŸU1ÀΫ|å¯7" Í™A ÜÓÂAö²Q£2Ó¾[G[ïçªT%®ï©iÏr$‡¡zh Ǿº?Žj·¾YºûDa‰b?I´Dt. f ‚˜S?¯@Uå¨É"¬fcežf V,Õ®#à¦êq.r¯ìYµ„I¶¥…æ¥jd*E×"ÒÏg³`u”§g 2u!L·'4 ’8 ‰ƒ’®Ð²ï%R{Þ­:HIÖ`ë•Õp¨iKKW"qPäw€·ªupaäUH.Șd?À£j»‘’>‡€¹£oFÚµõ³ÁÆHŠcß+RŒÁ2WS`]éBÌx` úRý@>#‹ñ(kM*޽Õªž- ÓòØWí²KÅ^Ó†Ì+UMsôAQu­Öañˆ­Ó³‘3ãy™ŸÄÎ]ŠÏdÌ]•l™àéÐ+ð뮽™±vÞa,äÜi?ò>Ä>2z8y¬Giõ Kæ˜reK~2½¿£˜B~,R h‚ ÷E®¥~¾Þ„a$¼ïA³ëœåÞ o·FÑšA÷ÓÊólõ¤±D©/¶«f%ÒÔ»P¯~\ýp†ô#ØÉa'P=°Ô€[7¨24„~B<€3à YøêëÌ3à!øÄ[œùÛ”¡Þ. €Qb°ì»¾‘ã"–Ä ÔÍ–Ü ´øÃY}Yùq[Ï_†…ëô`í–"r”æ~¢ ý$úÓ˜9Þ½Žl„¢V-¤ã%D"ö£hj×8Š0h»ÆÚõ³ë’a!Á೬¥12‰í‚ƒ'A ÓÐ ê´àDk—Q8AÀŽÅ¥¸ºŽó³<:g¥‚’g{ݳ´¬iµjKu¢³ib݆ÞÓcU`š{¤³ÃAg~UT¨%5Ъ¤ÃÃñ~(úê0ÒÔVz0ÖåXjr;, ïë4Ë:ùmø¦hæ'u ÁÞ.X.pKˆ‰§Oô!0¦žõå9Õa7<Û¢аÄÕË“BæOÝ è ©vxªu²èà;s¤Ç¦V뻚OŽX\é’2†¢íŽŠG¬‘,‚…*Ñ>¤A¹aV®ÃqKh¡j¸úÒ%Ì=Yvº¦¡ ò¡fûÕ.^2WÅ"óÓÜ^Øâ|¿ÝÛ¾t™ãÀÃ×n³K(hIl+Dy¿(è…ô{%a‘jöÎêhm‰P¶¾Ó[¡÷¨UE­ ­ŒŒ×ê '¤m]J",%©Š#dÎ1utêDì½—öF-ØjxìŽ5ßSSí©ôÔØŽê«â†,ª=8å²=˜‹bêc¯îªBr­>jW8P àÿžÕ/b¡˜†Â$s–p9™ `l:—ê¥@ÃØOóãÄ»1ªb\±H›·gÁÌ£î8B+F$¡’d4%4±Ù1_×4GZ‰|XLbaˆ9ZPLsâVðv£dˤŠ^A'E19#Ù2¯UO4PÍa4÷îIJ[  ²pÙ+ÜEQæçÛyZœ½wˆíœ?è`l¶´\"= Qi‚™Nk²«B[N¦€¯NF!†Ùj`QƒœeÑ1¥~@ÚÎݤ1{@ȯA>w˜R÷Ц1„}Ë„sæ©Çè×2sdO@JjKÙ—“ó=õœ®o*ȧ»µ¹NÛ—®Óû“l5xó¤YœÇy€1Ä©7 ´‹o¾QuÝÝà<¹ëëò¯»]ûæÖeI8§ÞÒ±«ø}®ýxKÃç—6~¹ØBWLùÄßç› ð;ú\Q í§ñêöRYÄÙ¯±†ÅúÀ¨>ÓÇ,ûÛ[Fº¯»'îû®a¶ú¢C¹óŠ¿×¥Ãte(!>V7Ÿ?Ñ3ÄÖ3—Çw, IòŸ½¾Q¸ð7æÆnsqú £ï›±1kQ^Ê ñ€&ž 1›_/TåÊõ²â¿LÙú7»:}¼>M¬~5‘y§¸ˆÂü;}6ƒ~ÁÓ'ÿÉgU=°æ®®®Ì‹ã…ƾܜ1ß.Ä MHÏöQÜÉ´†Î ?ß~„…ïP5U-{šè$Ì£- ܪKLI$ ýÈù„ÿ)~ê䊉I¸Ÿ†‰r‘@Ñ ÉÈQZ–__© Uü˜Káéµç²œžáãß0µÅwž‘ró‰°—±R„&Â>)6%Åæé…bs~ Üꤊ#=©ÁA~±Ô£ãx qüGKmÿl Ù Éu–K§=Dêô©WÈã 8YN>æ-8M§œCÆŸs {]Á­˜úg“C·"?3©y© MÏíéf<jfÀ0k9:K°Å÷|];ÄÞ‡–“%Ô‹q~YÐGWc}ÙÓ¸¯Úm[ïØ^2£YÓó†Ÿ(!±åÀZQK>^›Æ8¼Þ+«B+ö*Ó¦hg,…*í±Óõ@†ÌÚµ¶;™D§¯œT¹/x³¾Ô"V.$öe_7L¸I m¢âWÒ–S?â CÜ o²Ôæá²£±…¶Ë7±ôŠ2é-¡Ã7eðüf1«íŒ'rqÍ#!G}ÇÕQî}ÐææGhøâ/dƒ,R=lÛ¡˜Û!Ü¡vW¨Œ­ÈûÚ•ŒrßÙö‰îì+ûg‚+в—P÷ì.;X–žJ¢ØÏLõ{½ÔÉù[ó*ƒé°ÅNNåx”ûi4ý­†³¢;TÔ€EÞ±¥C²} %Ó·ñ/@º1ä Á‘”l¸MÕ×Gh…¶ÎYt4ô¤Ã/ô¯V¶›¬ê0«ór`B—[õ‰Y!ÒmR‘Ñoýá/ÿZ\a endstream endobj 270 0 obj <> stream xڵˎÛ6ðÞ¯P 6#Qï ÚCƒM^Š ¾Å9(mk#YŽÙ],úïá%ËI´ØH΋3ÃyÉÖ'˵øs­ˆÃ¿ce•õûÖzùÆ·\‡%Nbm÷€Þà!´¶ù;[|^–}Ú§ÃjÃ×Îê¦í‘]Ÿrç¶x<¼-ê‰ÈŠãú"'h¡°ÝQ¸s ÚÝÏŽÝvi'*A°5Â{_7UÚ*ˆðÇNOJìCStƒ&E×®Þoÿ”¦x,¤) [_v)Èì¸=nkã=»«ÕzT€ºïν¤õA­F¤“rÝ€%>ÈŽYàIÙ¯k)öóŠÇ¶hÈë bí‚ œXŸZD¹pIÚáŽÛUмOÄñˆ¦oÑkHSœ4—B‘G™Ñí]S—êÚ®‘¾@´De°–e @t+ zùÆŒØhçåŠÌ ”€E¸Ñë%)1ƒ(#|ñcìûevþv-þÍw±{®Â‹Sþî»Ø‡Û?vû_cßø±'ÓhAŽç27T”í—±Õ&NB{{­@™þµØGÔ1³…Á)¹ÒJ¤£Ž„•Êâ"kN †4A-7®Ïg<äôkZÎM}hÒª’y‚ù]¦§CŸeøÝ– £ ÅÒgž•1a~"%úÌuV×å>ºA‘?Ö/ÒU ûd1/‰­)ƒ‡Ì¬ÊòÃñ`”ÖßÖÛ‘’qÀD€‰T€,Ôd¤ùX.C“}W™6 =ZlÐq‡Å::òºJ•ÏæO1¤ŸþvA ì‚X‡†²¸[ä',ÔAòJ½Ž›°(5aÿ_4 ®hº_¸%a°.â_±‚Ý CZ"›-¹ÇÇÀ[–\‘zX².aîÄyf,aü8%ÀŒ”Ièe›¡G#¦âÙ(DÌá—O`ºÆKFc ÌDºê ×222ÉjŽˆ}8fòó’!Z"J‰·í?´YSœ;‚*m$ªÞŒª0ž$d& \À{…¡cï°JQ$’æF™Èêuà 1i“4/¨"âV!¥iž±¡‡ØÐ‘ghèr ¨Š®9Û­bÆ1'Н…¢oø¯Iõ”bØ»&99D'ã±=Ö}™“>åÄ£ÈúNä$©BLæ iÆ~6(I_ÜÿjÁÈ )ÿ­–†cŸò ÎÏO.ë¥Ò³$ú†¬æD¦+#Oº–V|êÅ)t’&#ÔœN%‡€º²–ÃÒ`XâšõMùDMáC“f¢Ý­”FÜ£€áI’†fU)yÀœI3Éû/éÊDû×IªÎ5?t¹yBðop˜F1õ‘~ .8Ð(‹»‡¢;ŠDÉÖºñ™n·Ä^b“«„\>®‰./Ús©ò ¿„ê[8÷  ›Ë‰6=Õp{3¸FWñèZFÞ=¦Õ¹ít>˜‘{žÃ¼±§mPõygë{Hy84ÉÃzw«Î´üü+­÷ÿ\~¹> stream xÚ½XKoÜ6¾÷W9i/#RÔ+î%uã"E#ñ¶9Ø9È+ÙV«•6’6vPÔ¿½3J"wé¸ ŠÀ–¢†Ão†ß<(ï£Ç½þ¸—ø¼õÆûaå=?å0'Y(cou ï—<`Œ‹ _2ÎKÎ…ôW‹LøùU].–a"ý~ȇrS6‹ûÃâÃêgïÕÊûè±0K½;T"–IoãÉ8f"ŸkïÜ{;Ë1»ñ¥$ñA¤ŒR„-ñN!6ª¤·ŒX®ð îþü45CÁD(P¦É7ˆ9 ý¼®ò^K[z#ÉâQüõ‡>1@ÑUŸÊNkìQàßèÒT°`TÉÀ…q<ÿ8ôKI-:ù¤Ó¶?ÍzáP³ä‘`1x\EJ¬/§¦˜%ã†ß/ɘ ‡F!Ђä.Ne‹…:rø"caìpE2¹ÂÖ&»­-ukû"¢P }@ë„Sø3oñ$Á÷n·§£¶7¢äÿöQ²O—¯õÑ7´ëX @¤'8·ä‹Â¯S5,ÚM^5®}³ÉûÙo+uL+ß.fƒ¯Ù,a<4c¶¼ß:ÏK@¢Ì¾1ÿ·XýVF#¬@AdšqÂ,6féâ`V ŒÚ¥'Œ²d"ÄaÈ’hæñ¡_EÆDª!VšÝ9þ@)ý¼YˆÄ¿Z@äøm]­éíí5 ·zBÅÓ±‹L´ÍH§CϬyžˆ…x½ßv¨Ú&¯5¼¡«šzSWCÙåõ=ÝÝVû·”aû-Xú庂ƒ’åžÒ)ª¥¶'üWö(˜†=VF0 !—ÇT5Ey¯Š‰e߃‰– Ù’‰m‡¤Ã‚—»«~ÝUÛÁJPn³.ýv7lwÃåBŸŸi¦Eà%¡7ìœÚùH²)óF›Ù•y1Q‘šW×]»ÙCT5çI0´fN°ò‘k ¹ëªá `h÷HL¾y’j“”ʘF Äa±;Ââ}"$Ü"tì$B<D‚jUañ]_Z¤¥ß|½ý{ËÝDÃðÒ¿n;­¬òªÖ²}I)dI6¥áåVcjŠê~ÌtÔÔ¿ûIºÊQviW†ËHÍɼW¹$,M­5:X¶ùMù6ÎìcþäÎ<€!·V].œÜ%lgõΖ֌ÅÜ`‡Œ"•dùŸdÁi‹,2M² ²}¥yw³ÃûH 8#Ás½b¾E†¨_d…+p8ó Joʹ¿º­(…/É ³½ŸÁÆSí0™­³Öm»« ]WZªf]ï Ån£4}ž2fµSø^b/F+¹H ]'˜g4ßH¤Ý&ÙÇ“Œ¾Iu%Ä)L±8CNN­“Kü¾Úlk½wQƒu^×eáê…`Ù˜Mר¿µÍ øÓ¢>Hn¤Ð%J£EJy⿞öjÉ9LƒÜTÃ@Ÿ@l17âü]5ÜÒ-¥Ö9ãx²Æe]m°êº2µŒçz·8‡WùŒÕBæj¿étÌKÚÆÀ*¯ e×DúŠŠ]ð€g^‰âÈö)’€hÿq—wúÓÁU—«rûç}4ŒÊz[—y?ÐTÛ”;\FU£ŸÕ‹=šj«Ûòœ:¦”e†Ë¯Ûºnà*c‚êˆUÛ¼ƒexð¨u¨mG¿fÜ¡zJ½ŸxгySдâ (ÙŒÊF¾(Yâ Î_p¤"C¨ªñ%vD~.±[k‹É, ­æ})cɲÄtÆåV$y_îÕóÃ~uÝvà *XmSL ئUàµ<˜™ór=f&xtEÅN®ßÛm>L½õ“yg‹¡wîÜ“†®ÞrGÚØ <(4Ýxmh»/  †Ž:«õ£ D¯îsLªýX¶?Ê“%.‹«þ2R÷~‘ˆ°™U¿ÏNΦ‡ø–­ûOÏ^ÐÄ9ýàÇ(ü½8}wöëÑêìÃ=?¾>_½|sòЍÊáÒœšD]?œœ¯ô'ˆƒ·,0WAïu¤:sÔŽ,W þ¦_lxÓBóõƒBIÃÃêìl÷°×‡‡Ó_ÎÞ;ŽwÉÕgÍÙé*eÉ4œº‚Ôøà Ç9ÐÛ|ÌS==O÷| ïãJºàHOLZUG}-=™‰‚F`öÅnÌ €Þ¸/Ç÷˜Úè"üÜkøàfÙC9Î;º…stôf”C²Á®©¬kÊ5ùáÅB‹ƒkÎaÒÝcŠe?³mE›HUQŒeJÁÅ(úö»øÆˆ endstream endobj 278 0 obj <> stream xÚ¥ZQ“Û6~¿_áë½È3kV¢HQJï%I“™vî²Ó®§77ÙJQÄ2)ë{_E!˒źøÑrE\ëeùÝ®\®b%‚¶kŽ›îØ”ËOë_AŠXà¼0C!‘d™X¬¸dRiA¯ Sê3EL ЇãEÞå VFA§5œŠS‰á®ZàåIèyuS”MYÜ.‰Ô–½Ô÷“ª%ãVw³”aP.A÷ÿWÃoí„ 1g 7³®P¼ ž¶ •4•ùf -þ’ASnÀ$ÙÔ‡¶j»ÖY¤ŸÝÖLló½y;,Aäq¿äip·\Á{Ù\XÅŠÃÇ€WÌ;0ê6ŒD¹›´Ç,K=ÛcÛ‡öÅ‚,WÚr !4¤·:ŽƒÇ¦F–¯UQDyªº-½åô8ª/Ç’¦µß÷ÈN‹¨wÕ†X´RxÛä»]itàFœ®.Ö‹ ýu¡‡(2é ¡2ül¹Bï—iŒxjå·|ÿ¸+_é©+žÄ,–ðTLdzÎûªiÁgx *n<ØäŒÁ2+÷_9°èù̇‰§{¯‡eÆâ±íš.YÈ{“$ñÎã„ î w„˹àLø²þåfýúÃÛw§2¸¥2_ƒ%\Ö‡àûÊWñöúf}"ÞAcÅ÷Xyâ'±JìD8ÇËM"Zš6 mœÚcvSæ]g®ÎIx ‡÷eÞ^Ňòiõߺù|e«£‡ý¢.¦¢Îäyˆx‡ùEñâ^<øyŒ­ü4Oþ)h`}4844ÉY˜=4§bˆâ,h½Š·Ûj“?Ôç1³*F ÎbÖ«€Dî»!øæŒz<<ÎP kòpÓäùê¾êð€-i»2ðvßÔ{z«ÇŽ^ϵj¼îOJ`mMÕo'ÃkgkMì$å]¹/uó££òs“Û²µE–5 xI@6&¡¨­ôˆõ{Pn*]F#Mqß”æ;T÷ÔÊ=l€AºHUñõaS¹PØäà" å·ŽVR·yKÄ;2Öbxòâ ^i[;eƒ½þ>'Z%(òëRÊ ßK#»Fø´-#öi[·ÆBì‹´49o ­†°ùû3?M6c¬;<#Üõ‘$Þõ?ü¨CøÔH% 6䨇k¡ë_S‹©eóPbK!¶ÕF-wŽÍ<ÛrŸ¢ún°i.RÈA’g ôÇFqÉRÿ³¬;?L¯ vÐF`× -*ée®`ç}AÐ[n®ÙÄ|íHwV±”Œ+ÿ|é¬×¶àäHÙ Þü¡›Ó6‘PÁÇß;†I£Ô™ée„tb9·%‘û 1‘ΝúÒ$#s²ñ1¯"ÜSÑ@¦ý…p®ü¹îØ”6á"Çí±ñ < º)P¯¹)ôVÖ4Dçƒ{Gð^œÚCa–H o&ì‘LÅî{††WÐ÷^Êþ¸—ÒÐOú–>y ô§I.9xÆÄàÓ`êß BoPýËÈú²Pý§¶©H 7¶^T\ÞSðÆx7¾ÝOWd"}£ÓÍ×ÂlzÓK»I<{¬e¿…É%jt¯ÛMÅk¢6Ÿ½M…ŸãxòhByb7u3½©ü囪f7Õ^špætÆâ.Œu§ó p•mÞÙ7ý¥;tW#Òì÷ï0Øç.Hé@aRŒy" LhršãÝ(0Í$ì8`v¤RN´º#ÊDPÔ¦Œlëk°Óì~œ—b¡Ä6h$6§Ùä­¹ñ]þ×Òˆ—Ë´¦Ìò„ÉÎa¢Ls™†—K˜¼IàC5TÌ–¿“ªÄ’Yöjl Ôÿà_!4UgŠTá©Ú!áY»—ԨʋR"ëg‹nž©0ê² xr&¯1I˜À#Cy³©ÕêÁ»Öf\QOʦ¶ÞZÑàƒÑª=ƒú­ö«Ýw¼2uáÁÛ›?ð%´Ñ$ ¾½y}óŽþVd–mGŸ÷¿ÁÄš°ß î $›*÷¾n ¡_=§ÕkÅT2½*¸` Ë/;ÃïvôRÑŸDDpZªV 8ɽ)•hÉWìZݱ}gÓŽ©rR·–^”e ë"”ñ`$œ"†ÃE½Ï‰5¦¢‰å¡lÀMZ¢CY@t›á;nUWš™èevÃ5‘œB£Œ¹ÌåAF$Mš%•6¥éè¿™ð«@ÍßÐÀÔjy<ñ°Ž¦lmÕcÎ;ÐËo@o«úй§~.EiºúÅÏðläRŠãÅ$D<Ô†½N=boGª;ä:÷¸T=vÉYÎ♚LŒ½Eo¦²Âç ™üBèÅbŠ˜ktaÜÞ!æORRL­M‡ÍîX˜ðY÷{¯eUÁîo(H ÛVi¨ê.Ž{GÛpïZd=€ªPK(àÚb°ßàaV7)Ú¹J5ùDlYûÛÿ§~Rì endstream endobj 281 0 obj <> stream xÚ…UËnœ0Ý÷+PVF\üâ‘ì*uU«Qª.2Y0`:H LÁ4©ªæÛëkBÒ(‘l_ß¹œsîÃÞx¡þ#^Lõè'ï]æ½Ýr„8 S/«<"pʽ ‘—•7hë' u½0ƼÏOçFnìI¥ÝT]Ót>Ñ]Ý~·¦nTçQ9¿üÐ8ÏAåJždëÓ©Kÿ6û ¿OâbA5€ f¸_ ÊQ/‡±Q¿÷¨Ú¨½6êÖ®×ìºûšÙÍÆøâÒí—ݧ=¨‡lç¶÷7:ÒíÃöãîÛ•³#æÑL‘ƒ4ÁÑ]_+ËW ­èúre"‚ Æ/ëÖµréb÷•QTod^€ïÑúžóÚÙ÷h‡,Qb.tKЕ(Fj>á8v¾ „µ`¤ZŸ%˜Má¯W" ¬KÇ^ol Õ¹õèXΉ#¤ÎH¢»£ìå?œá SL!ã aBOBqÂPѵC=¨NZËÊZÕ±—Òšö!á²){Ñæ'Y®1# Åt¢ێRœ’™ÞJ îî³ÝšàÊeÖåí*šâˆMhtõ½€Æy`+;:Î?}­bތұ†JTº©Ì%dŒ³0kjð3úŠ1æ“/°8Ôã“Ü­ë"ÀË…2UqTŒ}ƒjWØVp†dƒc9žNS?isÝ–u!×iÅ ¦ñÜϤsC¼”ò˜bµÞlÑ11 .Û‘É7<àH“w¦]¢¹jWIŠ9¥6"œLLêÁ†Ìg¿nD4]Æu—¥ñ2S'iT=øžÅ²_Å'SÏÜÿ_›µqÅpÈʼ2¬¢©ÞoÝRÙUO=ùÏh¢§iéÞކñ0}}V²´Žç¼×ý¯¤{­ì«5µK_Ã4ÂæÓï³ç/¥ HD<1 8Ÿ\?¿ù ÔlÊÒ endstream endobj 284 0 obj <> stream xÚ­VÝoä4篈xÊJ]'vœpO€8qH'8Ñ7znâíò±{[úß3ãqvÝÞ¡êªÛó=¿;ù”ð$ƒ?ž¨~YÒ É÷·É7oy’g¬,‹ävÇÛÉmû{úÃ^œ™7Û¢,S¹ùxû3p—I.˜ªTà–°¨=÷û ³´5= ¨´ÕN™*᫳e¸dµ¹Š'9Ƀ˜(b1‰IÉ”ƒ(ÑMl ðs•šÞ fÜäeê4ªàej³7@æ<}ÚwÍ&W鞘õ쥪ôîîq#eªû£±_ÓÙ´£ïqäUpXOÚ²T-í¨ó8˜´“âåÄ>xv:@eçËVqVVÉ–L ÃÙ<È9Y/YWÁ:¬zÖƒ*Xæ5…ôñjQônÜlE^¤ïµÛÿ:O¸©Û I½{Ú@l‰´Ý]Æ `ôá8Ú|BZ#׳¥7‘¼Õî8k´ÅiB.LS0ˆ¹@âì;­Ÿ:·' ‹Lñl—€N™ùeĉ,ösQ§¥Û ‡þ™èÃeQ+\Å…)´ß£X£¼(å Â%½K’ÏçW½ZxÍß½4ùy°5¹LP‰8À%¼žˆ¥bÅi""´ ]èD6hP@&ÆB{~Àà”ôbZ~‘GâÔŽ¨f ¶ƒ¡Ö4=b˜-ñ~(aß_é÷^K–åqž'’0ÿ€”Ù‹„va£™†aÉ6aÉì@ïßÃô¼÷Ð}A| uvæu¥Y*œçÿPY3Å£¢ä5ÎCüÊtò¹ÅfÇUÆïïèë+ƒD\\¯*Cœ:Èúʨ¥2híJØ{Ž”=ø7 Ž}ÑÐ&fÕ—§R,“qy¢WåœôϤo£BŽ_¨j 5XSiUÕÒ8–V‰¸÷‚†‡^7¾Ä`Àt4:p¿ ÌÓùË…‘öawº`_݇¨ó4w//&JHÐ 9 ­ö39àŒfÇ»]¦a»o Åg}q=El`ðצ~‰h„‡º‰}ºY€oèø?Šœ›ê@.ÙE›¦vSßÓ¥ƒûñ6ù”ÀK­Jž^W,ç ÎeÆ‹dHò²ÆÇß²Ñ'¿%ÖìØeY² ¸—5r ·€Æ=—gŠIx)‰B±Šû|Z57ž ýÆUÄ/ÊÐmo^h`¸Åã¾NQÜÖð´c+,à% bÿQ){É6¬Œß5¯±~á8"ã¥ø²K&¼7àñÙû{¤ùóEKŠqþÅœy†ÿGñ:‡9“ü_'ñ?úr–Û7WGHËú Úe½íUGÈRE퀫Ýqò¼BóÛRTÞ!>|õ7¸æ}ö endstream endobj 289 0 obj <> stream xÚ­XYsÛ6~ï¯à#5 A2yê}Ì43iüV÷¦` …¤ì¸¿¾{(Ñɤ“‰'»‹Åî·}ˆD”Â?þÒ¨é¢ï¯¢—?g‘H“*­¢«ÛHäI•E[$èèj÷W,“ÍVWyüÛíf›‰2žï .Џ6[YÆ;Óò{Ýïx±«çšW“if;ô“cä¾­³cu¶gÚ¼‘Eü¸…4Èî뱞 ³]§"kÍôÞT`ƒ#Ÿéo†nO¶ “q6ÕÓæï«ßá^îz*ÉsºÞíж=½"–Ÿ®¢Q¢ª2zŒD¦’LDÛL&:‹ºH‚\Yø÷6z½]2k`B'¹nOîÒs“¿Ë…¿eR€Ê,°òa¹ôŠëWg7껺7+ù ER„îì ›\ÄÏiÎ+ÄñÉß2®æÇd>Lß|ƒ˜Þ2Õ) f:½Á0¼w²ˆ|>lrÕh‡mäཱ«glݲLãÇ{Kb÷îÄÑ8ívjõk<‚µA{F·QŒ+(ßË>㦠¨YZ’‡¶RæF3â±™Ó´ðxé37.ïÛ§Àó»×2û#NòÎwÜ¡(åJ|õxc籟6¥Œ‰;ûaÆM÷¦1ÓÎkŸè®‹:îp IYw”„°´«|-ß3>›aÍäf Þ!ØÂ‘ ß0-×ñ?`û´€:Žb‹އŸ«p÷æ|ðÓU™ä'´n„w<И¦žðÙ8Mlöåˆ4$ê•vóKvÝзO ±‚ü êélë¹ã‹Ëãƒíú̸3S3Ú½³ x †¢p^Äï‚T†òÀóöŸ¿¸Åx·2qÀ<‚S µv›<‰£äš”‰P !„„–ñ¾¾3_rzž%¥\(ª>ºN©OB×w¾M $b.Žm'_)è4',ÎÆu¸‡Ž7oê  MÄÖ|´ 5 zK˜útð)Mjý¤ïl êÄS‡|˜Ž:ZT+Ë,î6T*÷ÈpèÌÈ›’{Ž,çóHHÁukg3Ö­:k€L–ˆÛ!§ç;êBü:j¦¢‹_‡ã÷y ÿG'å“¥fWùEaªùtLÆ’±­*8€´?ÐVo¹–#·Pà ­¸°Ý~¤÷àªD¦ÞÕ7néÛ,rQ¼P„ºs •ÅvæÁÖ.P7VnFH]Æ2s'ˆ•½½¼µDyô·*Žþæ ¸Ûd'Š=lÑêÊA=~_/âHR„˜e Òd­í›ö°;žÃæÂâÐCç˜ ŠšiF:`c= ö®ŸÖf ˜oüôíJ;®’¬tÛ¤5gfÙ®5ô¤ð“-h½¤8ÃÌtMc;?Rí©På3‰å0Ý|bÌ¢_;ýÔˆÃÔppbÌIÍ—=K´“&(–@oÝôèíÛ ‡›Ö\o8y5|»©Ð­0ßNÏt™ïÚs%;KßcÊUy˜û…Ïý ¯µµ§L€´±t1¤Pïœ÷pá§«`”Fõ4@UÙ±§=+ËÐXu²sž­C|®÷Î^­ÎoƒF©/½0Êú־ǘ.Ê®·µo­Â Õoà§ù¸‡ñaâ_n”Î|çÅäjƒBµs¿g®ã!¾ÓYõÆpE·«Ó ´hº L‰.ÅóéTæøÅü©|*>ŸOZ~"Ÿ Mݳ9àøTr¶qì ü6ü¬ƒ‰ªHÏÆwEr%š3•)àžkÙlg‹]еd Š´œp ¬`ô¯'4µRÇê Ë 2µÝñú”Ô•‹>+™ÍvÚ×Û`•AíÕNÒÿjA5=ïpè𠸯·•:›æé´ðÆ(øã÷Tø•ë[^{‘à^OþT“0#ÔÓÌ$מDx¡Ìå¦YámDÜE0󻆘žE »89@+`c¸ëí¿Æir“ÈæáÏœŠ>á«ZÁ}8Ì> stream xÚ½WIoÛ8¾Ï¯r©ÜZ¬¸ii0‡v¦¦ÀŠæç ÛJ#Ô²\I™Ôÿ¾ïq±µÐŠÝ „äã[¾·ò¾{Ô áG½˜Á_è­Jïí÷ö†Âš \DÞíì4$)Ðë;_6 (eÂÿ’·³€ÇÒ_gm¦©å¦‚ù«§þ·Ùýí'ïã­÷Ý#ùó‚6$0"ÍB-“6/öТ0Eó(H^ "Reb†¡ê·7I‡…$a`rl³27,=Q,%,1…åŸZpr0Îö‚ñ•“0VßýÞãì¢@%>w|ÄÆ% µZmƒ¦øº-!+H"p¢uƒe¦s>R9®vü榿Ÿš|­—ê<ß–¶Ò»E¹«+<úÏÌBÅ@Q¶Î–ŦhQÃþzÐéGÕÂw6ã”ÚJÇÞ¤Çu½ l”šq1{JÉ5ï¤C¹#xy£³*ó¾ƒ*b± ¡¶¿46y I?äj4¥ß”r7~Åv؆•>œª.³vj¦¶¼sÝ̔؞ ¢êâÇYžpÆÉ¿uD«»À!I(Lδ5„[œË)È.žþ‚W²2=áK¤v íRèŽÊ-EÔÙÖœ®Tá¢õií+öp(ž…ÿ×A@a´¬²&]U›jko6ªøžU[c‰8²}Ãõ|ÿŒe U滛°{¿-?:>–°K$Î.a»ãADW¸GDªšd¨1ýø#ÃÔî"„§btxu¾¶ÊjÛ>")±_ªñ´;EÜäKMü4ïwµ]Ùæ§­N­žó.ñW ÷jnh} Aúõý5WSzÞßñ9ȹï{²ðéœa2ë ›óãDtwøœvÙX—MtÙ„½üO›ñ ìx50„êõ®áZt®â"{\Òûv˜[3‘xMtdR-1Ð\oôØads±¿9ÉÎ5ûP¬95bƘ™ùàìø!úØ|päJ7A蜒§Ÿ$´ÏÜË »f:9#k^ÏágE 6ï­šø±¹3‘ú«Ô)õ%Ðþà”@/r†‚3xxO¢óúV?ÿGAÁ~9°´ ìTA˜JÀ/ÁhT ç–€•€;÷å(™O]¨ ¾àd‰D×BlY?ÿö Ȇ” endstream endobj 297 0 obj <> stream xÚ­Ërܸñž¯˜#ÇÑ` ÈMåà­¬SÎ%µYUåå@ÍPËR&9Öêï·_àkh­œJÙ%`€f£Ñïnì¾ìô.†zç üwÇóî§ÛÝ´ßéXåq¾»}ØY­lº;à‚ÛÝžþÝEææÝÍ»»ýþ`~äAó`xHdï¯ûÿÞþc—Z•@‘(k …ÿ™‡Cø…°ñÎ,Æá .ÙÂ'Ã_ü‡éìN‡Ü«Ä†LÙD.õ±Ù’8Ž†Ç²/yZþVœŸê² ¶äZyTàÇç¶7ŽI´ÊµÀTýþ`ò<*u_!f™—OÚ‡°Ù|ªË¡¿Ù:X›D%V°¾ß85ß>ÑNÕ¹lúªmŠš—Š®+öÆG/ ÈÇëèÔ^îùxøé¢¢9mÒ‘[å?½NnR+ççbCÊÒlâΉ0!bÒ<ºê ‰QûCšåÑߊ¡àûº²}tÜ}îqÑGmÇŸƒ¬/ÎkÔE'{å—KõuomTÔe³7ðTÍ ~ÚôòÍðX ãî‹l?%YT«‡—kåd,IHÙ‰o3:*I£Suë¤ìOt$os.àê`jˆU[•§s¥½ÌÌ÷lÆwc”΄÷|çÄ'fÄ7GÇÏ"s^ÅÙL}­£K_žx6´<.®K+Ç9à%µ‰Êº<ËuHá4i:*•vÑócuÄ­GÞàÃLTô}õ©Y(èù2uU¼T 2ŠŽéØ*³V1d}P1œ—ú.ä:i ,µì‘ÖÁF5ô¼p.ÏHæ=©ZÙɪ3n8ðU`,D²3#C™†¾¿Û+"ûç[ñÃÿú»LºOì‰óW¹g_’(‡Ò7]{ÑñcüN>™Ë3hLêUÆüûñVì'‹H d?>ŽDµwáÂüc8(iJÒmS¿ðŒ­›¶9 \†âžØ ›½x’ÌE•*ÁŒ­×á‹Åî\%`瑸öͲdâš–Oa%Ë  R$ð<Æýe(ƒ¤¶|—U’ˆžKŒZ1N«4xwV–`ªÉdÏǶëJáMÛœÀi &2Ša´^‰´( ²b¦ø#j„ ÞÆGR% YJÌ0È6—1 ø ðýËLiÛØJË ûxl/õ‰ç÷,[Ùxb¹Ï$mÅÎ)|,‹SÙñ¼]“O®f[83Ÿ :Gºà£—ÝsÕ—¤9›–}à@?<òCdªºž©8µÙrnèx{ õd¥Y!Ÿ~›ŸððÓÏøéçü§®Åðôµ:±Õ€–W’*´K•ÍVÎ*èÉ⯺êž!§S  ¿Ü÷G‹H®÷åSѦøç½xAu.Æqš”ͱn{÷$\ÂòåB‘Pt‹ÿ”|Ž%wL ÿO¨¯£4TÇK]tœ\¬é”qàH¢Æ ‰š’–¹<0öƒë¼ PdP—3º†m|sÑï HzFÏ6L)É’NîW4ºr}ÉöaåÆ(Àô;¤?%}‚µgÐs+‹ÑÕáW\ù¨…ù¤Mˆ”ÝÊæõ)zuâw–úª¶³‡÷hÕˆ|§M°8w/Ñp@6âL`ÛãŠÉVqE¾ëêÈæÏÆ`˜×4l_. œ%/sM6¢Î£®—{êiÈ3aÀéÊá°€dH‚áù;¢-ˆÝÁ8£L*•ÈV¬…< "Eއ= f€º¨LÓ‡((s4Äëè=, k§1óm¶‚ß=¸‡Wò<ûìÐ$$ßœ`2u˜è•{ ™þõ€¿['f3߸1SeìL; ˜Æ:.@,z09@*Q£0Ïà<×@ú=Ó@4uEþæ<Ö'6ÚîpZŠ3Ê%è¼3¹[H(ãRª¸¯jÈ kI’+ïçq)Øñ”—¯²£Qs6Åžx0¡ØˆýWˆåÿ]êFÉ=F"’0…+9#¿CîZÍëÓÄq®ñeyt-ºç…îkóT öVùáˆéšzí3•.é×Q¹A™IU H’Ã^ÇMˉÇBÈÁÞÜc9òX$óø–êͲì[BGULSREÜ|,úUÊÿÐÖâX$õ3àyőʋ¸7 è,Å$ó`bÔÆ¥éÍ›ó}á˜ìOŽÊ*õ–SI°:(S ü 7ÿËzv†yûéò/Ggµs<øHm2'E‹Š_¥Ø¯(N|ƒäf³ƒ£ÌŒd©±W}"ã=:t’[%ñ ‚=ùÐWx˜,ä”.\¬Ov#Äæ¥6PÞx„yä £¦Ámo€Ù«L73šM%`ž3DÑ•Ô9”Q¡ZšWËó2}ªTR`?&™g4?YU§HyÒèØ2Nœôì§qJõ/NÆXƒ? Èã¬ó.Ühe\å]ËÍñ¸¢Ê®ê?ó¯íp›Ø™E¾Û`¤UÞŒádæ\Ìù±ê· }oŽ?^ôI„Y~)ÜrÊ—;‘L„[¸7&ª¹›%ª° -¯Üqª7Ç3¥Õ)¤]ösÞVÓ êÕnS½NróбA 6Ä­¼]Ô«cDû)²P9’Gö™á”[ãPìCêŠ6e´ô§ÂùÚ_7Ã\hgù1Ö€„·Òé2°Aivê.Ô½ÛÓñ„:QÀòØ?ñ`•ËC{é¾i{ùÖ§× 1Ï Ò½tÏÖ’@"îI=u]ž&¸ë\Å1¹»1W8$Ö¯j²¥N@26¦â) .WF¯[§kAšD}×#囚 H‹MOI!5ÓÞó¼’q_K à( ÜÕQ?÷6»Ç,¶ó¦‡“úe—b¤…±ßI7-Q«]„—Øj•xÐÿ Ú¨D¥…ÈV"$ü VE3eâ—³Ñ'ÄUÔ“'¡ 6¡@É× ×¼JÔµ ƒ²˜*ÂP*̾5S1ˆˆ‚â/©xx‘“Řp—[sjVª´àTj­Jò·‰+ô÷\ŠñpÆž?–MɆرëÙT êþÆ£Ø=ˆ«Ç …s{aVA†‚™zªõ¼ÑÏCϹö€µ+ŸêâXŽN^Ù1u?ýÔýÌ©åÄ/t¯1ÚÏ{B×2Nï³™X°Å'ßɪ )>UÌø~QB`9Ó_ê¡à"bÓFÒl’ü›BÏ x\9®ÜXWUͱ¾œfeÉvIã7J‰OP}~ÙMÙî}¹õ¹rfw†:Â㛇ü®w¿î~‘254!Ǽ•,:›µPé¿|=`ØRøÜ9‚…«å›Çø$Þ’R5—Ë}ò¨hZìÛòg$\NNÊ ôr#éG>>¹±QäcypÜýAØÐÞöáI÷ê– Ö¨sú-Ø=— Ý¼lâdîLY —5ù§ª?^ú~lñ•§Gn~4á 0‰šò·—zˆà.ƲåšË^i»ì1íd̳gG=ƒµ»ÁÚZz0`gRJó©B¢[!iÈžL÷P1n?6Õ‘ ïTvgŒG?ÊN-Ë©—˶²~.éAñÈ»gpÁ¸6õãÒ„BN†ùFNA) 7U!gÒ„@¿n8çlZ´L†fvp)+bšÐ_þô;’‚D• endstream endobj 300 0 obj <> stream xÚµ]sã6îý~…åéš?D‰»Ó—vÚ™ÞÌÝÍMóv¹ÅVÖÚ•¥Ô’›î¿?€ %J¦?r»d"Š„ñAdõûНRøá«\ÀoºÚV?>¬¾ÿE­xÊLjVϰ¼Á½zØý'yZoDžTëÌÒdW=¦\µÕŽ­7ʨä—u!’î‹Ê$ÕŸåᥩÞ!¨JêgúdØ»oû¦ÞVù˜¬ÿûðw Êy@–)S@©–D¤Lsð˜¦2†$cJ;"ÜšbEæ–ù…ϳû>w~žÅ?øWqö×$¬º'ùÕ-=Q²ÚNÎe»£y±N ~zyL¢ÒáRŒ"þ°Þp­A¿ç\–É \Tí¶;µk0‰¡:V;·èX+-®Ô†IF$Y–Y,ý驯~?Uô!K‘ìʡđLŽÕ¶;îp?R9{±³ý©Êé™dãá¥n·ÍigY°o‹Ï«¦:8zeCûj »€‰Û¡Ì3g†¨†(€ü:3ú‹¬P¿QÉŒ4§ÒŒ Ô\‹¸ô€ò¹òÇWäY²/Q¬ÔíG|—IÛÑ|ÙƒMÔýçž^롯šgúÚ;·TÒì¶C‡1T±MˆL0/ã6¾FÛ¢e² °Qèäu_o‘½=ñV{fFk¡7b`Ø»-Í­ÅÊÖ™63+®’ÏÐ@)ýXYaH¡’®µ^Fý r”TÛ÷n Ux£@qè4š¥Èw¾j4[–\Ã7G‚, ¢­^ÏtÇÊz€îžiÂ8=5åÍJê3‘©u:á‚ßé({êÑû ü³P|šå€£Ôº}|Z›€o6¸ÔÓó\.vµõ¨8q‹SÄmŽÜêä³Õ³9[n­Èb„)’œ#Ô9^B“€×òè(”MãÞpßÙ]§á†½¯(ûþtÀ­#ÄÏ5y±âœ¥°)5SÜ~‰I8}Dú[} ·–æ”#r{1÷BBËŠñXžÁ Î{OÁHOÂóq{ŒðXüQ4œ‰Â¡ ŽªÌ 5êc4ÓÅ[Ž'a³nŽeI‘mXz"»lMû²§Y5 ž»Ì´ùJG¾ì¿¸“»@Ñd·F.B¢‰ä<;çƒ3«œ™Ü†:L˹ÓÎ<“z5‚¼‹‘‚°˜;¡Ü¤!.ÐÈÏi̽ºô6ÁÈ÷ÛGž°>®Xæ#ݽsq‰å˜l„Ö,/¬³”Æ‚½‚7‹Ú”äèpoÊGÍt0Œ¹ZÑ é)vÞ$!â$dHÂæ=KIÛG”¼(˜È(PÔ˜°¾L*w‚¸`¿ÊíŠY? ÓYÍ2:ÿ"K~.½O“wóeKäŸÈçÓKI x:¬aÁUGZèܳÿr@Zì—¤°ZYp`ê‡Òå}ŽÐ`]¢®ª–Ò¿¸ˆÐµÝ·ÝËPw-¥‹Þ Aºx°ùÎÂ2m?8ÔÃp+(ˆÌ Ê…”ñþó›Å„O›ŽB–ŽBÆÓÄ»‚‚f+åT¦ÞpV!l¨×¼®ºìýÀú‹E1G×°™Ä*/?>a–w•=rÍ•»áÒ¶ƒ”šª.c‚b¿£{ÄXX(–ùTÿ»¸éEbw¼p“0Bl¢\L÷Za‹âWÇå°·—l¦¯®Œ¯ƒÜºÛÁ®jj¨¸.l"×Ó&ÞÇ6áxä•sca‰¡RÉÒ™ØÉü©hê~X†c³á:cJ°ÌÓ³ëEm—úÈæªšb¬jäD&ÆŽBm·Ý0«~çÕ)a”Ô(0µ<¼·ŠøtfXQ?ª™¹jïá‘®?]è›46R¤^¿©™¬œûë_œ=»¬N±ƒHi‚}á±^¡]ª±Ù&TüòcRLA¢¹…ïIâ]–b¼`ƒ©8·AÇéf?EpŒ¿ÅK[Û÷KÏbï4ÖÑÓ÷©í—)¼| ŽO¼¿$ó×r5SËÜõb"8‚¸W$¨¬G&\Ÿ¢Á=D…°M–Ëä×çhz¦¾úpwƒ«¦æB®ýí¶N^š“Ê“¾þØÒÜ$ÅÙU0Ÿº|ß]w¸k4½"wmÄ95‹Ô#]¸ÁtI¦k?N¾lÞ@–Xa½áºÐ‘¶ÿà)äcß f¼ N}µ³VË~nìÚÑÅÝH…ͼVâÂe$0Xt}çÔµÛè‚'ÿÂø÷Z÷È“’yŠ–l¶uðµjÎõ\ÍÈŠcS&‡š’67OºFþãº6œÝˆ­2T5¦f¤j¤5ªñ'"±ÃNŒ}Qz›äI"/lË!y¼¯~¡/ú[m»¡Âqx'c×ã â½ šÅft2˜ëÈTíÐRÏ•&®„uÛíǵ~߇zÛµ½ œøbûƒ -O{8Â0ì#ò Ü#ÑmÜ1Ú±ƒs„1HOÿF/b³«ÝÞ^6Ï/ÕìV¦@ [¢_e<è¿ÿö?]šÜ endstream endobj 303 0 obj <> stream xÚµXKsœF¾çWpd«Â˜y0Råâ<ª’S\Ù›åÈE6 2ËZÖ¿O÷<`XÍJr"—T =ýI¾$4Éá&ŠÁžÔûäí6yó-JIUÉöÞg4'•L¶»÷iA)6¥¬H·›Š§£îw›Œçéphvp£Št¯§±ýfïwzÒönlêaÜm>lÿ "Ažy…hA*‘d¬ …2B¶·#+2ƈ`  RLã¦ÈS#º (/(½‹ô¢ôÒáÎ0dµ9¿YÕFpRQ'çVà8çé*™››¡ë† “é}ÛÄG,=<ô¦ÒI×S[{ªqá˜SpÏXEÊ.”HëÑ+0æj³É &Òù Žˆ’•Ó§vU¢H¥Ì[±Ë€›04ÆqÂx2Ó<˄ŘÐs`¦¹€$Ê^¤¹ð¼˜YS6óæp¤ ˜÷1·PðŠ ˜ÿÓDT˜p%˜š@8FL©ž÷G‰*Í4ú“‚(2‰sa„~—¨[Y޶<áÖ\òož8±“ž€ çkŸ¯Ý‰ Š ÿ"w²×p'{w²éNö_Ü™KÂUèN'­ti¥Ï¿ž{ˆü3ªˆ(bÙ¾ÒÊŇŠý“ñá+Ï\f×®¹,þM<EƒG‘Õ«‰`/ñ(²1¹`¼¡à>‚ù+)ÉA?HŸ–ÿì=ô·® Ôú`º€XÚÁ®éÚ};5cÕ˜"Ô·¬‹X¯l-Ý{×Xʹ±Mç3ö—æá/K]ËÊÕÒ¶\Oy,IRGä­î¦vèugé~gMÜk”ö`[Üõ\”:m0xjvÄI€Æ- £àchTÜ5pd.*ßþñεsïßÖÃþ®k¦¦{°¿5¨1|Žîõ4¸+úo|k?Ïù*=4ŽX[¥4ã+:¶Á6+*žn-ÍЃh[lvYŠ­ùV7Æ3È…z²w­yâóŸØ¼À»F×8Üâ/š6]³oìlÍè*'B¹h¥yÊÈw×"‡Eƒ>®1(¦¡ÏíÇÞ¸´Ö~†‹Ô¥Öýmë 45°›»Ru ôÑ~,ÆO¥ccö?„ÁEg7{›e66z§¯Û®PÂÃå“( w‹Êõ>ÚWæ]‡J›Û1Àe–ðóŽ”P±d£Zg£ðn5cìZýd,$'¹›%:ÝöK<%^I§qñgŠ»b¡…._²õôŒ³«ÒOÁÑ®D _šÒ±Óã‹ì‘”½Š1NæysVp x I&Ei§úÜ“¾ûé_¼[ endstream endobj 306 0 obj <> stream xÚ½XmoÛF þ¾_áo•‹XÓ½è-Ã>dk2´èŠ­36 qP(–Ü‘%O’›åß<òä³ädí r'ï9ò!ï…™ý5³~Ä,–ðÌÖÛÙËÙ·W"ž‰ÀOƒt¶ÜÀø?¢Ù2¿öV^ß®æó…J”w>¿Y¾íÄQV‰¯R˜‚º}v»¯²v‘g}fT/—¯ "ôS=[Hí‡ÂÌêv󅌽b]®¡‹¾¢ÄëŠ;±gÀŒ¨¬IÒßÜi³ÚÌN¼¦+rÒb#HcÓ´Û¬÷ç -¸òz@(;ê­³®àyuÝTMM²MSUÍŒ{(ë(ЬZâÝ£¼x|˜ãêmÎÔLˆT~ºD’šKˆŒP…Üf÷t+åÝ/ø¡½f[ö}‘û„»¸çëVKýP Ë¿³í®2Ý0Œ‹#_P vY›mç‹Pjo‰MèO­þÎ@¹âho›º¿;ž!¨y“ÕÔ‘Ô\·ÔQÔüŒ12+Ps±ãïÐŽ?~ñÒ×â†:/`õg,”V& Be…`Ç ÔVÆ Âð ùøây“ʺì?t}³¾?¶«l&#öóQ—ëû¢bJB?ù2äë—7§ Ïþ öºézFE4öÉ‘¸&¸A®ž‡û”Uûâ)ÿ¾8a#¬õ$&Š£Äo‘ó)!"öÂt-@€…Ò¾Š]pc’Á¶À ¾‹06è9Ó­õR¡Ø( ¡{ˆ2páÈrr!tâ§â úÎIµÍئü¥Þg;­Á,9ñ™LzÞYƒ>rU:u\ ”¤ÿÏÕ¼ØfuNúy±Éö»Pã™:ÀÕ˜svûêý÷^].¹÷öâ÷þxýŽ ÿmùv˜q9è]g‰”#coÁ¾ŽµU0M>·bÄáhHNqš ƒij¯›²²¸¡AÁ^Úžd2¯š Z8sºkª¬/XA¸&›Tµí€!'^™ÝƾHžˆ ¹?&r2åúåÙË3CæÍzŸ8ÜÝ‘»ÞOïÿäôVÁ-ö=qÔ6Œ‚U¢)¯?¾½ü!¥dµx mÒ"&Òª¨)ä/¯—K†éØ!ÇfÛ4Qv(<œnÑ„o“d_ŸïÁ=qiD=“ɹã³Zês$1µ$‰øYÂ¥žBÅ 6SÒa™à9ÂÍÖûê„kqȆqêDcß’èáÓ OÇ„«1ánDò<áÑ¿®ÄppéãÎatür^Àm„¬$~¨ÌrKxœOK 7UÂ7Õn ^žøw[ô¼9µ\dhnxðãÅzb=¼óRÁHXA¨Ty{Sy`¯o°ÕNA³y$ɺÁÇ8˨G‹¡Êñ·9YÉ*”®<;> tðzÒAê•{¿Â•uô2at¨²¶ ×H¶ÂÊIŠåV¦¢ATN·¦ÎÁªœVsŸt*ÚL¿bC¢¯±º7¤`YUó(­L'ìiSW†¦ÔÒ‘xuS/³=˜Tñäc ¼ˆü®¬H9ó&:w¥±ëŽÙb7²î2ý4g•„¥‰•¬ëÊ5Ù÷my»ï™§•wªØðxHlšñ¶¥ðµ}š’z‚²AÀTiÛµu>ÄÃM iGͶ¨Ñü¾óÙ=aŠñI˜´À·r^#醼šÄf]8øø™ãK2“YØYÓXna³Ž[öE½æ%š ›ÂØðÈ-ÀÝœçäE·šiïäOŒ‡¹*ÇøëÈ»Èó²/›:«0“àíÄn®¢‰ 3ijmšâœ]kÐ?•9¥h å?Vš8ÆÀ×ìhÅS© àåÚ²Â>l§ù µ¯#ÖRÌ$nÊü\9»‹…ŽS8ˆÍñ¨õ±)#è²›Þ´ï ñ1©±Ýññ6ˆÙ—}Gmáø‘ÚÃ]QÓxÍ€Ù¢¼kKóVF0-´¦ÅŠNwhmcÄ5iŸ°ç©ÿwI™ o¨‰q0Võ×oþtHÀ¨ endstream endobj 309 0 obj <> stream xÚÍYK㸾çWø(mE$E=vC6Ø&‡ Á6ÃÌÔ¶<F–z%¹gûß§^”)›îÇ‚4i¾ªÈz}UZý¾R«þ©U®á²ÚW?߯þòkºRI\&åê~Óü‘­îwŸ¢]5UëÉ“è¡í×G۵΢oñzcmÝêõ—ûÀ *÷Ž(tlPï«S;É2ŸPšÆÊȪjš†æá4ÕLl[u]? a [D2qëÝt‹$jö<ÔȺfä¶j‡ºÚ=ãÄt½m>'*­w<Út¼t:8zý0Ô´¶ˆún×t_‰ßÒYœ¦ÐšØZbô±ªc=Õl4&§jªu·"SL›~¹ç7UÅJ©¸Ä}ô¨¶ˆ3>ÃÆ&VëRÚFÇæ+±cçǶÑPG»À›)—À¶±-謳 o™V8/O+t‘ ]äѰ¶ <ªU PøÓø7D±Èðê|Ôç($í4ÖnÁO ñ¬ât>a ämF¶â¦ë» r‰BÙÓkâŒêÖ{ÞMªŠèãÄ{ŽŽ>ó²YIp•„{{¸Ó;>=®BÙÒjIõд ?t Ü”qžûï÷,iôØ ´„<ú6¾,ueà—žÅ®E쿵Ͷþ©ç/I]Ç…3» H‘HQ:"e2 ^¿*x»ÃÈ´²¥…Ͷg }‹¹0Žv™çÑ÷CC>âÀsbUÎç“®ÙWy§åÿלé4NÜ:aSÎÊ…"¡a=)L„^+e ¹C5²Ô ¼\j|©óq ì}ß¶¤8ßIqŒÑÑøÜáý¦j;4zvü)dªHã4óOþä–)oY›Ì]\æËU—9NÚXi8!ÎRZ ‚76ðÓ-¹ûÊ£¡ßN#]’È…<µÊ2nò(¾MÛT–ßâ8¿à^âË]ˆDkå/–!:äh5UÆǼï‡z¨Cü€)Ï®ðÕ'T¡ˆçæ)eq–¿WJ/‘ %ž¥pn²0y Q¼øæ:ðæéÍ'¯±£mtáUÜùȦãü«X\J–_³ÂlÀz4Úe[CçýR‘×ß’&iàPÇ3ÓÄò™ØÙÝbà uæ?*nȰOÇ5L<0px¢—v|>"žD÷çOÎäªüO3~ã_á¨i¬g<¤¤¹¨ 2˲„ü¾c43º—î;Ѿã‘ÇÊ—HrFCI!€Ž¼uý©Ýqÿ Ä’Ü[ Þ–{ÕxqήÐ=6½œO’ö·Î®#»É¢_×…¦Çd®[uÛUXF{r8^0¹Êtž2¸€¶â&ÝÌŒT-ÙeT¸Ã{‰ôp½\Ÿºr}Üs OkÁ0»ïOB1 Ýx'Í™–%†ø,Ä“(Íx}?’ÐÙFÌ,!èRl³ÙVmKøVÖâ+Àˆ³q{øÀ枨®1‡àXÌnaŽiß0ùž- Ì›zK Mñå =‚»ó>r¿‘vr»%Üfn ðeÑÇ=ÏUA‡h«pQäôG3¾ÐÇ Ÿþ9jâš(æŒJ½Yå„ïƒ &Tn™ÝfBy Ñ,gÀÂô˜©\¸H2èYË\`§¢6`+ ›8TCKhJŠ­ !jå¸ÓÃXÿ~ª¾àXáíe7ò‘³â/¸Ø?ŸÚÍã$|² K>¥ ìJ—õìA3°Ñ^òFÌÜùÖ÷5YN0<« \æû5áŽãæ›C!ýQÎ ‡ŒÃËŽüCÅN´Õq¢|;ùÏ¡îê'¾EˆžÔý¢&AêèÔ݃ÑV‚-Ýmûû!x+æ8:ÇNZ<Ç(œ#ƒZAïçapnä¡¡~l«-ù g_xÖ­ô¹H05ô„?sŒ^GµŠz&úÚð›ŒA ä%@Ï”WorÇžÓ¾6Ü¡J»šÉòua°ü ú*?=…E¡a‘h/V¡ý£:>¶ªlÁ:lÏ^x£’"Öjñ.ýKÂùÀ°YÊÕYa—WΜCùœ$&¨J˜yð’A¤X8ÍU7¶Û·m×oÜnÃÛ=þÓ0û_ü +ߨ9ÔHA¨ê¤¼³° øm¸Áù Û顇PŒˆ:ñÐ,R^˜°'lUg.ÄÛ05³§ÆY—2‹›°fƒù'"‹¶ž\Ü÷ì~¶Í8±›ä’yÎ^6RÞ“›íGñ¦RÁ¸pª¤áÙì’yi#ùS8*ÏP¢ú¶ÉYAÿßµ“²¢‡pÄpVøE<º±I¬¬ïÑ©š 3q“9†[.CÛ±‡$©èü"–Òr™pþ6#¬‘I¡ ÷v²wˆRRývšë,Ú.ö4ÖížûÎß jžV!íY«Ø]qµé¬Œ¨f„% c\û^US½v¬yB@‰Šºú‰‡bÌJÏ£gh­<§Œ3}×>ó¸lCìØÊäÓÚBìjOB…‘‡ E ;aùº»ÏÒý¹9PïøÓ.ÃQ‰éYéì¢$B‹Ïh0ÒhÕ ìxe%®¿_ÒêNÔŠR*¿½%d2Pg¯µ¹!eòd”µdÑ?{Ô ¢µÔÛ±ízžqè¸`ÇŒm¯ìù(YîªÐêâ£éX‰9öJ.à ½ðâ«!F€A(0äÅŽ³™;_ÒsU<\5ާ#^ý¥:nZÌ3\×H÷_mÕtÿƒ:nâ0à£@S!ï(ÞësÁ÷ G©$YD•ˆ’(‰¦náÙ±ï!žÁå{53$T­¨to0n„º÷D¥,ôyªxpéÀí2¬á2l~» »ˆñã—Htº*®¶‡×ʬÙëeV'»Wiüx™5{_™Õ¾RfÍ.8öJ~,¿¡Ìú‘§p6C¥c6/ßúÄ?\†-ß-ŗ˰™zOÖûòv™\@}Y†£]¦GÙMP\¦g5~ Ÿù‡,•PÍξ%¥¼Ší‚¾ìyc¥¶]ŽJvfñÌÔù›r œ+’ô)‘±tn»ðM=XyCÒ»¸Ïþí[‚W6ú{xIl¦ÉÅŸ+ò±ã(C,ìQЇ6YÖ³ŒZVK”\PË…Êas>ZÍŸ6aÖ4e' Ÿ0¹¸1ŒóÕµ˜§ñ°p~I>æ@}_°FäÕËP¼øô–Çn²”?[í–þûOÿG‹?Ï endstream endobj 312 0 obj <> stream xÚÍËrã¸ñž¯Ð‘ªañ&1©\¶jRÙÜRñ-ÞMÑcÎR¤—¤Æñß§!P‚)yÖ©ÚÚ- fw£èçl~ß° …ÿØ&çð?ÝT‡ÍÏw›ŸþΊ cÄ(µ¹{„ý£ÄèÍÝþ?™"‚ÈíŽ1®²»­YùplËa»¹ÌöåTâHeC]õÃ~ûëÝ?›Üà÷Ô 2¦ˆ‘›WDåáÝSíÁŠŒ3£b $˜žI°<¶ŠfõV±¬Â?ý€S$ #šy\ûúž2ÙÕãvÇ‹"ëï[žgõP¶náûV©¬lõø Lž½<ÕC{&«Ë ŸÎ Ý´ÐóÐ#Ð÷f_ïÝÎK3=¹½ w^¶¼ÈzOþø0VCó<Äò½cÜiàW”½bBÌ"µã§Ò/N =Èì±o[Kù¥é¾âÏÆ×nË5ˆ¯ššÊ-=öÃá³ËcµhMrP ÐuzP,ÖŠeËI²òf““ã®$p‹v liظؘ$!á)$¬ÀÛ`>ÃuÔÚýäöGPP3p ø¤ˆwIIRÄÈÿ–âU½PÔ8й*ÀêD­¼@¢HžÇHÒRå_ìíX’bå•¿"Vªy· „©sòH|~Ì]Zœ`m$rÏžÝ&Nþâä"Nþÿ'ÿqE´Š¥ ä´£ªavmÑ™¥œH•ºì ¦ê9¼C=–3É.Ä“£}¤+ È5 úV ü:… µ&RdÁ^Xº]ÂSíxN‰@÷Èg;ìüO‚ 0fÅl‹o¶=118†<ãSŠFNèÍ$xš„ˆIì„.2âDEœàü,Imì9ýë7nmÀ ˆ8(Ñ• ÍàÙ€§<Ð?€+Æ*>ÈnÿS?8¨ñõ€p¢o=xᡟÝb·wîÖ§Þ}…€Î^,4ÍúG·ê5‚•mý×´FÉÙ{Ýëš¼×Uz•Ä©4h6I~'¥ "mI•Òì‚ÔS1„](–¿©XNOŠåIÅÂjR±°nk÷Ûã¡óè¬^ù¬WX°zMžYpG¦ïôðñi—O’ŠF‹Aßéÿ×hÀ©Ä{kNô9+†=¥S¦‰æJõ¢užH‚,ù"îªÛúP[µc½“Ff_0Pר ibX€œ¡*;7@ýYí&˜U¨ärûö»oR nOë1ïëª9”­Ûð׫q¡¹ãð>K¢¢(0u% q)|%nû~k®Õ/ÝÌŠM>¦LVzÂH¢Š…#÷I…äÒ1/!¯Û×msh¦zHÆÇ”>ßæÏ)-r¤áöŸí^Ò‚‚{JnÜ6ãäFðDÝà6N8†%³Bœ~v¡èìËϤuvœ´dN„^˜ª²ëúÉe^§Ë“˜œê=¹ßÚO}’ yŠöÃ/!u”œ/ndê%"ÌêKŠ˜æ[ÚïQ‹ÆJr1XœRjƒK©qù¡µ‰if™ýÍ1{Êe2R„ÍΦI )Nê»Å!éÂ]‹%¥Js[ÊÞAé[‡!yñ)û¦OÙ3\+ñ¨aõWpáT!øä/¥¢ýG—ÒW(„*fóSdˆt'7 8ÜÌB’w~s¤Õ$Î^½8‹ ¤{Ð ÆF°7nÑ€­W9‚@[ɳXe$Ä•‚oÉ`%f L¤bœÆÚqp’®c¤œykÏyÓ9P`ûÛ±«¦¦wšÝq-0™‰a =‚j\šgÕBŠà{`gl›ÊïÙ°~±&sþYxnëÉÏbýÁÔÙK_úµfï©4¨y¼M¸_ºÍçr˜šÊ—Ð`~¨#fÝÀÚx¹òå8Ÿ 0”‡ÍðNRˆ‘‡¡D ¯ÛÂFœÌ/)š•t=(«¦LÛœÑÃŒž÷ܵ;ÎÂzd8s×h$˜ñÎá¢2ž¤,›—Ëql¾vx  ªÊþZû ƒ…@ĹDçb¸¶¸!ÿèÃûÆÂ#ü>¹° IŠOå—cʬ‹æKñ 9?H„@Ƨ@‚’e âÙ Ÿ]Þ!Yxä&®–3òÇòØúˆ'’:xÙÌÝ Ê]_ÿa ïÉ{þ]. %iŸ¥PsýSÅÁ©/ÃèܧáZï¡®a§rr®Ú‹@HøÖ4ªÌu½'›ñá#WÃUõ¨’îRĶ|(›ÎÝì>ö$wü»é¬¹1s¥¢ãS9Ý„Š=ŒBy`Ÿ]‹El$expL9:&\X˜NƒõgñT%GLAøðhЩcdæ(–ºA û÷ãO$âÕ$‚…adaÛW/g¼î©?¶ûD¼Æwûô:‚5/['»/wéÖ‡È9–dæÞ‡Š{CÙ¡F$Žf®"ñæê ‘b­!ÂOÁÒd[–66>ÆÚu>à…êˆ<8/OF‰f O6K˜T¤˜ ·ÄEëó6C~[›a'ÉMÜg¸‡Ó`0¤ Mö$\fs½b!nè9ˆÛ¬÷Ä©ì—ÇÕ?AÕzÏA¬÷"#ýVÏA¼·õÖäQ Kf¥Z né9ÜŠåÍ"¹Z+Õâ"¹IsQ$ë=<ùã=‡ Î?IÏA§ß%εžÃqRí {¶¦Ãúùঃ6F‚ß@âB³†É·ÚúzÛ¡°QbÔvðu$kúçtUŽ>œ î`½RÄsÂøZ¥ˆž²wïXŠàX"§ó›íÑ¿ºð#8ѳªTŽ×ŽÆ>å’ ×§Œr>Uÿ<Ù(ÀÍ\Æ G<ø Çú³µZxnM8sQ—Œzö2ÏçÒ ŒB¡ Æóîœæaà‚óØè¿öG»]¸¬#Ï}ÖƒPµyõ=dصû¼ô9äl²a‹¹ö‰*‚÷Ð>¶Ü!êÿVµͬŒr:û'§"ƒ‹$Uœê^š‘0¯T¿¸§[ñ£å/ÞÊåŠÿHuÁ•ÄËSÓÖg7T;0oèüâ[Õ/õãJ0d.ùgzÂíü¹v/ŒBÔê²ù¶GœQò’óljmø×9kÍzlº}S•“Ío DD]Ùܧmë¹€KTÿ~ nÌî»çþ›£¯w´*äÔUòÙ\j¡QFaÕñ-ªª;Ÿ'ØBˆ™‘‰ ’{ëÙNWõž•z˜Ó°9•XH,1ø±–.ÊWbý×_þåX÷ endstream endobj 315 0 obj <> stream xÚíZKoã6¾÷Wè(W|“Yì¡ÚCoE}ËîI”ÆXÛÊÚJ¶ù÷Š”%Ù”-ÛŠÓl°-‘óà<¾™‘¢oŽ2øÃ‘$ðŸE·óè×Iôáw¬"Œ‘æ<šÜÃýgH‹hrwsD‘HRŒ '‰¦±¹¹™.þNR*Y|gJc¿ñø¾XÎM™|™üÔXd÷gÚÃi¥„#.+‚“‡¶P?š¥™çe¾t?=-Êâ›Y‘¤DÆ· ñW{ÄÓ…[UÂnÇDu˜h$n”k ¹ì—K¤±ßñ`V õêË}1!€ýwG $X½,ª4·åô¶^µœ_yÚX¶ˆ§˜Ã¹Yµi­v¥­×4¿7O³Z(ŒÛRÕJ<[ñc3ƒƒÈâ§< ÑH)¿ú*DK QS[ö+$ù®íÈßô÷u$‘–ö&GLƒ–HÐj&ÑzÁÏ!4 CY0 ”á¸\# á>d4V×ǦǑØ<PµGìeFŠ6b_} ñȬv)bbÍ!1¤IÅÍ-À=†@"Z¯ +¥ ø½Rû¹¸ŒmŠýRoÛŠ!ÂüöEHˆ<@%ðaè!æÁذ]läÝ>û¥Ú‡n˜·#ð×{Tª¢òdE|˜§³Dy—QDÞ>ŠÈy¢ˆ¼Ë("犢MÍR‚eûgßU÷KS @¸P œײ ]µEÁê“…@çŒ:^>ß:fia=ë/v¢{<gGŠ@FáµRÇ•‚é ëÁÃå6¡š«“ ^Ýzaä{¶Þ•Â¥,ÐPÜ421 EâÊ%)c¬é¿Ú^+ùžË»'©š:¾ÛAµ™1ŠdíæÆ’{qnª–2wf1Ÿ–e~çî˜Yáz< Ý^ùàVwá94cfO¹ë}[([má´D•)†† L ÇÎ}Ëâµüëen÷8 ŠYÝ=. û ™EiDõ°ÆÍj(†¤¢¯†k¸îuo ¸Ýi{ýh£Ÿwbmõ¨Wï—Ù¬&47ž½YzâÅc9-Ư0‹;w¿OpZ ŽÖi{ÍÏ9‹àõ¤¾¹I²“YM àZ5)€Ï²^ÞÌ `ü< º±zpºú ÆȺâsâ%,ž®ÜÖühýg/nqþíi Îa[ôÜÍÜâ²èp[G*üÔÄùŒŽ4ÐÔ}¬®zBNw ±Êƒ³’5³ §œfðÉþçx¥#{PeçI»Óo"÷ÈTÙÅ»™H{ÒÛ)Tô¤Pf[ïl$™w–fAlävïšÀç$I9á=F²I÷G¶8Îï…É FbàklÚ'óN弄ëçaF ‡Ú&h°Jpëåakì0f9Ë,ùƒ=aÌjv€=±<¢›\ËR„iÛ\=”RÆlOØÊÙn‚’Æô;†¢lh1»cØÜ®•Âóæ®Sj¤dƒÀ²Í¢çúä4yBjæ½ø!F÷¹Wƶ'5µÜñK03Am.N`B¬6\®ONÁç( FÃ&¹·€àc9ÀÉØÔë|ðx IÄ[³·îúmðžN“€Ÿo#WAtx#Gä“#ç$*“_•DН䂝|='¾’ãñ•žÜû]ðõíñ•\ðõ‚¯gÂW2_7çù2³¯µ@ ÁÁeYvÂgð%ªj¢u,¨‡ÞÉaCŸ‚Ž‹ê*€êT]Pýÿ‚ê;E?Vƒü­Îù§ºÇX˜ÿVîAÞÞ=È0÷ÀÝ·PÞ]=ð#ΓÙ zD}yðS|‚2¾‰ú¿Mܻᗎí3|èGsò9«—þùÓ¿wö} endstream endobj 318 0 obj <> stream xÚÍXKÛ6¾÷WèHkV©Wo)Ðz(PÔ=Å9p-ºf"KŽkèïCÉ”-?é!H‹ä¼ç›OÔz߼Рà_è¥ü¼õÎûuéýü1ô¢€& ó–8^äzá-‹OäÃ~ï/X@dU¨#<%)ùà^þ:‰qšf©Õ‰a‘¿[Uý£eÒö« L޲µ:Ü š¹Ö cšsoÁÊ™Ñûk^°8%kQ里¼ú‹(#}+ |êj”kd×(ùæG Ê$D…êT]‰%ßü˜QöhÎÛ¶66×Jtƒ¹ƒê¶ø´ÃÃB–èÕ%^KÙ¾èÄY×UÛ5BU~”’vu~ ›RÈh›”D¥­3FjH"ŽÉ¹î†ÚR£3¨d4Æ* åÍÜR…”'Pd}nK:SÐ(£Qj¥t|ªítÂA@êþ ‰Àå Ú(›(µ¦ŽÑ<£<³FéŒÓ˜”ðxåû ¹n견uŽ_»óQžC¡R'teã¨êjÑÈV6X+øU ÊÓAÿÔMAµÑˆ|ô³–("b·/¥îEµ™ <Šs‘Ï•+·gªu‚ I§ýšÈëv•CaƒØmk¡vêk&"ñ‘—¹h€Ñdðxü¤^¾|¦åë\=c7,0-ðÇ­ßAÓÖz#>ƒ—ò[?cCÿnÍYJt7lN²Aqœ©º7øYƒ•¥„Ô ¨Ñ\<Ém.5@}¦ssêƒ ÎdÇ8e_p2[Èümq¹²þ 1'­G"`Ü!´DOzö!òætØÊÆžªÊž÷€0ݪ7Jõu` 0-p³Ò[cqa/±“l¨l˜‚ÈR€#3pÔê†0RK§[± ¶·ÄVèßüs:جóô@¿EAy'E‹_æªÌ¦4Îp@ç!iøbѵ錰`hÝÂ\wQÛi.í9éõKcôÀÞï¡íD×·¼X!“ƒ²«ØÖe¯_X³Àµ Ê¿¨AIh ¯dq-ND_E ø¸Š&BšÓPyßâÐ%ÄùºOl²glb™ƒ8é ƒüžÁM#å0}½™m*1¦dcȯy`â ¾ç@ø8Œ«û:}„Žxx.º†}£v†° —ïaãI0ýCïEÃ÷ n'E¿ÆÔ9¼•ÛËyf(Ÿ†5Æ‘Ò$zÌ8×Kn•u{qù€Á´d8a%ö.VbϰRþ¿°‚~sQ®RUR4CtÍîI(}y98pzo ?4ÇéÁ#L‘#i¶kâå…ã]lwËè´1ü®E~×âÀwÜò]êPçÀwŒ46‰TwiÜ\ÄT§Yôdï/“á|ßEy1jŽ/(èGaÆÇ£îè-^¿&Ð?ênd5Ñ]àLÆÙøÝssVy@ƒ|¼ÏÎØHh2|’ÝhiÑ<œ^‰ÅüE)Jé9¤µg‘ó (ª3…Y|rçÞ\WåÉå89Œí(Îøf†’Æo¼ÿ¶Ä¿"LÓÊ4N Ç«i¢þôm%5Õ endstream endobj 321 0 obj <> stream xÚ•XYsÛ6~ï¯Ð#ØX(‰‹dÚt’¸Í´™é5Qžê>À%rÊCIÿ¾»XP‡%Ç“±Ç¸»À~»–^ü·H1ü$‹TÀo¼(ÚÅûÕâ»ÉBÄܹXm`y™ã`±ZÿÍÞívÑRƬìÖõôLÊÞGÿ¬>³ЧYöhä~ÏOv,QÔ0Û­iÏX·%õ6SWŒuß A‹Z$1Ïãµ$JòÌ€*Í¥ðªn#‘²GØ){×­]y}Å~³ÿV½«» $IµÄšgŽ„ ~hmÿvÛM¼wÛ/˜\&Úp£¡•\k¿…-%û¥¬;Wx„ŠŽð "cS+ëÖãÅCˆ„ël>DEš*>ÕTøMo·í_—t¦ŸW€Fq©Lð©Ð1O ˆ÷<‰–I"ûãv´uWw[8SªY19Wv`4â„b…m-ëhÙ{þ‚«5Ïȹ”^ÿ*Ê$룥H ë½êU‰t¶Îiå`— aœ§)`4Vº~»×ウò¡Æ!l«Â®9..9SjÁ¡GÎܶÏ\I‚çÒ Ä£¥šýŽZÙ`®ë©µné5,U,¸:F;µá–~KBá RÉ\9N®ó³b>·d^vj1nq†•Ž$ú eÑwë°­lìn(ƒÂ¡îŠ’æãøµÿ¥…¾£Ù–´[÷HÉ´™bIžÆ¾«Ù5Þ(c½[×äÝÚ_+>¾Ñ箾‹üÁÛP¯(!ÆoØçÕõMÄ)­>ø p´T>Øv×”¯O#4}âqHW)4O)_wÖÙ6Zjðý4Ôyý†Zî†ÝDß_LÄŒ+áMy?B¡ã!ò0~v ³àk¼ëâQº‘áŠAŠ‚z¦GvÍ4ãeª òňT1Í‹iIHÙ Kðdfª¦tÌŠHCÈ5” y°¸O=Ša‘ò<=†Ï3` Ö•¡á y\²Ã27p[`²~Âf]é=‘§äGX^—céÚº+Ãt:§,[Š¿CË XÔàA¼a…Ó`2 aIzÈ0dæz¶ö'¦Gñ,¸gDÍ ¢3m ³Û7q"‡r¤ùë[ê…è@^Ú¹rfžÇ  ŒîŒsLáSD@H‡ÁTTÙ¹ÍY¼™¥kf}ëÉ!yŸ_·ËX³{D-È$8®l­®¤NÕOŽz¶*í:¬n¨õ×ÁÎXÙ‘zE  ;OOÄE~½Ÿå‚ÚðH£®½«pô*yjöMX) »à$a‰`CÿÜÝ€TNâ©èä²0>z½@< ¨ ½‡3³'±ßÚ}y =ûf,˜Ù‡oxÊ‘¡¨MÓŸ§ìð¢ø0ð¬ÆŽµ§5“ÌN2Gœ:LŠ 1£7h¾©ÏOßÔ¥€³¤'× ÂtÛÐ5RRéB€“xG{ï9©ŒÖ2ç±e´eôuï‹æ»H&X)„z¢g¡D·qL £Û—Ûž5±ìþÊ*[Q•í…ªòKÅ…]sÙ¦…Û…òA'è· xI“âjøêÂþœgó'Êæb•Ã嬂ýüz9|þÍÉiÝ5Ð--6ÀéþêȥɑKð–•ÞRÏJ¸¼£ì.våc,‡¯A¨É†ðÄå†1œëúÄÀ)õåÂþ‚' œSÙOªç¹TyÂî«ý—¡21€/›5õ÷Ì„Ö[ \\‚çµ½>£BÉàÕR‹òž°sˆ3”'.ô §z´·Mmú `]=Vm9‚ª •À#R¶M1a~Ã'8¤µ–&¥ÑO@|q-$r0ŠÖñyéCÞ›CéŒ}¢-¼ŸÁÇ×µžáÀTÀÿ © Y’'Qy EŠÿAydÑiÔ·î€õMD¯|çËcO!ˆdbÿ˜×ÌXâÃ(6¬#–iX",é{iÆò”NŠx‘¡ù¥QTWh3‹þõÍÿÂØ•& endstream endobj 326 0 obj <> stream xÚ¥X[Û¶~?¿Â`@b­Hñ"mqR ½'-Úì[Ý®Å] GW’“n~ý™á’¼ÖvÝdñ2ä ¿ùf8ôê[%ð­4‡¿dµ¯WßÞ­n¾+–Äy’¯îVLƹXmq@­îŠß¢»ƒÝlÓ$:ÛŸªÚí~E´o› ×Ñç Ï"Ûõ%taœƒìpê[Ô=Êo¤ˆLu²ý¥q)§À87ƒ;¢ò- š i,¥Óúpjöžoá‚ÇJ{ëëŽê8'ÝE½E‹µO§ûÞN;¿¿ó.úõ{ßè—œ¤ÑÆX2·Ý·1›㺥%:9›¯z‹äÑÑ<Ú¿¡š'2æb¾T¯*çLÅLÎí6ñf+~jK† 3,¡«XœçWQD0/V´›-P¾°Ñ´ÃÂV<‰µòû¶ëÀ?ä,bغ7•m Ó[RÍãLÍÙâlܦY2'ôÚŽ´SÆ¢ MÍpC?+¿¶Eïä<*c @ÉLOQλa¡9«2ì;´ôM’[÷G".aôƒqQz2ò\çó»³\{Ñr QS}AQã"–àKæ£ã` ¥i”ÄN ¤Œ,–©ún“AŠèHÈþiêcåΓ†˜…FMç.lEý~0ƒ­mƒÑ8ô·RŽJgîKEœÖY†1‡Úަ35`ÄeÔ¿õß§ú¾­Ê½ïÞþ›¾o}ÃÄMžQ—¥·B¿ùæò³‡óÿv£ª7ëúf]ܬŸ¨»þávýñÍn³°kQöÇÊx¹á›ÞmýÙ&$1¹8ínbð¡­€;0÷…(‘r. ¿ö4¼Ž “ÀZRãOé™'‰€È“«Lür°}æÜ1Μ/kJÑ£¿)oÿs{ëk@œÏÓ vIÁ] Æîˆ$ŽHfábéhbD—0CTð˸CE3>¡‚ã„ .(½Êç̇Ä% ” •¿Oøêöï¡òñ*T’<ª©0; ®Ÿ,,q°Àg‚:˰À&, •ÐÇÁ_™Yt:ƒÆ=,Ð*½Ê ‚xÏ,¨üù`ùt,LÃ+.ÖÛMè9$Ù ÀÄ Md©„ Éõ=B’yHôSÒýBâsäÓUIHcÑ€)Å]lÐÃúªuÁ«2ø ¥Õ‰^sвÕ4?e+ínuJM™G;äPØeèæD& CSæÑ9l¹ÛEO·Ëö¡)造d¥•õàV ýè/l…E\_áç%érWárÅ¥Þph&~ª%Q•Qßt~ÞÕÛ

U2m·@Úð»‚3aáýןuá%%ÎÊÿðkÈÙo}ܱb«½¨¤¢¿üëy~äà endstream endobj 331 0 obj <> stream xÚ½Y[oëÆ~ﯡk½ä.oúГÄAòТ‰ ©ú°W2qxQIê8ίïÌÎ.o¢mE àÞgv.ß̬Wÿ^ù+þ*àÇWûrõi»º{+Ÿ³”§«íaå‡,•« D«möOïÇÃz#¢ÈkëRS+SiÅžª²»º¡Ñ./íè¾.OëMxu¥«u{ÝÎkwkœ =ÕØUeÞ¶yu¤ÍyEƒÝ“¥q¨›Ru=•[hÅ!N7¦´éËËmyu:wëm‚Ø‹†æ"m×=Ø)eD;d ½Ã¹Úwy]™Mw~<’Eš°8Ùݹ"­‹,äLJ»ìÜêH!oˆF¦ê\tÔù²¥§Š3­ @ZM£['°Ìˆ×u5}9¿7?ê£æû“2’=«æ…Èù·öÚ2eÁøÚ~s—@–ŒH¡•·ýJNŒxÄÑžGì^}˜-~AÚZ54·4ÝS’n¥¸âØÑâ²&syŸ;½k"¼[šÕÝž™+;E',æÆ[²þ¦n£Åâ}Ý‚4ãÐ.3ü„©§N§"ß«ÇÂ’AMáW5öªÐUfăÓprKM²Wîì•{ªŽ¶9è{µ]iîY=#ñ^ÏÂgr¢hιoõTÓ7÷a ?ê™#Aœßé½.Q `s Æ†¦…oMBrìœé]x?4úX7¹²'¹{’¾ßšø€0’ ¡ü8BIÊdjXüÄÄzãû`¿ß7‚ƒE8èb9ú;a ¶júîqדjÔ¾3ŒÃòëÝYÃR&ƆÁ£· C²Ð9=ÒàügW&c·÷QòváÒI‚E¿]ØŸ2ßàay»p¨àyy½”ñØÎïÉq¾¬C@šhm<´jãñX¨¼jhYÔÑû|Ç}©3}Ä£^¨ÓY‘‡ š¶£ŽjŽçÒBûÂÅ‚X0?šIF¾&˜ðïù)ßãqOdÜR–¦ð~ªÏE†+ÝרxBBˆR7p Oÿ~XmAÉ·¸<6ÔoCC· ·XC2« b½Œœ¤.èÜ1,4¶[3‚bcU85Õ’&Rˆ£ù®©‹„7åã;ö‚të]nAG0Ú‡G1³ÿ±|)"¦&6ÖC„B¶æ(^«ÑŒÎkz·¶ÈKÊéÙõV5ÈW¯ì(Ëߥ qvPsˆ2_y§#n ['Õ¶(3Z/9‘/"ƃ™;/á|ÂçMOª%²F$xv«ÅR«ŠŒ:f]›°ûÝ›Ê1æÔ:9ñ-Úœ³DŒMãX¾ŸD<Öa«­9?‚{Í”øýüƒm4Ç…Ô`P{㧉EkØ—ö΢xØcM䤎ú#”£€Å£SÂè}Â2Q2l!w”ÒûkÝiçCj—˜…E@ÔrðžÕ*Û%´“Ìa]U/¡Øsõ@ ÉÞ¾›øx°èãÁ`ôÆ;DÉè-ŽKŽh€ ßž#EmN„#ì¬ýÒqT„ÌŠi”VŸ9ËIÎb×S‹Ó´*žÑŒ•±e“—¥ó̵µ[kÚ1Êg`Ô$ðä­xˆÍgø‚0fÉH¸6±i ( ï{5È\,&* 8ÔÈm™pÌ+[=çÝÓHi³ۚ½Ë ÍhŸ4O$&'ÉÜ,UÓC]fÞ ßñ•ˆÕÁ´Í%,dTÏ[¡;ØdS ÁÌ.kÅÁW⑯1Eï‹ÉZ0zeä¼r’[—·åÕ¬ä9—Þ/IÏIM-%>K+·þRêñ±Ñ_r€¿Ìé$ØL¤éDlÐ]ëÏ™ÂÛZVö°Å …¨äxó—ky:œ‹â’fg¡ùø_ÈA,Ëaöñn>}\j×È;ímàÛ«¨¥PèX§<›ˆ›Úª>uåaj^s"|ÍÁ§1ž¸W"Xa°y¼òØhaë¦é`}4N Ó˜ÿŒÖ5n·y/X¢ˆ=!ðKž½Wùœ¿+«ˆìZEL ïí×(a’ý®dàþ¥I¯`­>Ñu¦*»þ…VÍŸg„IëuÆõÝõwêzÔ±Hv 7K-0¯4—Ë»›ìîæe)°…,q½R½ÄÌŸr¯ÿ')òÏAlUŠQiéb¡œ%Ûð},{†÷¬cÏ“O*Ëh¸¸!±PÕgl>J÷ï«ßÿÐM½,?¨`¤óðÿÕí?67åfQÐíàmÇk¸Ç'÷áÑ{CñÏÞ’ži†z0ޏpA½—CüŠCÒÙúª©»ó¢)â@ï£Øz册¿†±—¦¦È ý.EÁ =`ƒô z,À }p‡Q“¿a£, 5ª]Ì’ ÚîÙbÑçFa9´×§Îqã燔BégƒÂ(PFs £¤I¤,NÆ¡‡†%¶Gz¿ùõ®ÃYvgS¥¢®Ží G¦}Âè]ŸítmÓJÿn½Ô™ÖÅÿ9–þQ!'ùXÛi•M°åLpëM$íËDâ–þýOÿ£óìQ endstream endobj 334 0 obj <> stream xÚíYÝoÛ6ß_á—2k¢Hê£}Ú°vM Ýâµ–=(–«±¥T’›fýîx'™²åXkZ´CƒR$¼ïãôäÃDL<ø'&¡Þd±žü<ŸüøB„á¹±OæW¡ÝXMf±«¢É<ýËyòëôïù+ R‘nÁVH0_fÓ™ •s?õC'K*ìIgQVUVßNg~ä”Eš×DՔܶËNÏ_ÓÇYŸÝÐú{›5þ ›NV¹Ó™B`˜×´b™Ô;›ÕÉš¿®Êj4ô)}|œjè­6™Ñɛ̄tµ6jÀV¤gßÒ­¢Oþ°„®ÒLpL„r²O‹ì9 ‚`4¿¢–D…)Ò[ôô–Þ‘Ñf*"»pê,’Ñ÷À­ŒoÈx1%6—Æ1Ùª,®k¬Üð¶Ê>æå†§K£È>±n­¿O Ë™/C ˤ¬¼”vhHß1î“ÊÙÔYJóyQ7Y’ºCêÍ(Øf"vµ$%—£Böåp€¯a÷àÞÖ2O.˜.`‚a鄸*†6êÄ{9V¼e¹©:ñŒIê¦Ù"_'+ê dÂIk@J+Ü€_ÍÚM•³X•ÆË \zC¶¿pª¤¸fþžG„Æõ¸Z^LöÁVÉÓo§¤ðÿ“’¢¯¤ðÇ+ù~¬’i‚ìï‰}yÅÛY;ü[3È3¨ÙT–J ü&h´ÕIÁ1¥¶Ùs3F)%Böœ‘Gêv"ãˆìˆ žS2j=g6 ¦ O\¸ë9[å7ÆVƒu.ŠÜP¶ÙúòH¶žÐ†—›†Xß&iŠåïòfI£—«¤ {̤ç¹"¶ëW•€ÙþPË úú'«Ê£¦öIÈÕ·3u—$7õéwmjŽêõØT]—&ÉP,LÖ#E)8–+0g£¥Î©44Ù{§øëx| ¹="öóܸs`3)ÝP1ÕOCÚþ”‚ Êê&Ó-£7g#0™†Z»<Ê T³ÎZr…†ëü£I <í;M¾æ @ŒÚ FŸžrÎò´È¯—há†h šÁ½ª,i  AŒY§•vÃp¬ö„Zaç¢dÍÙjW£°«ŒÙéap£,vE{ó(Ï·%%Y?Úó·ëãUIê°ïy>1u{6ÃÀÏËí]Áx^n=ö=¯lÏˇ<Óþ+8þ¨™Ž:žSþ÷ÏÀ{F(1»Å+/ÆAJ´ _ï˜ZLx:XcýÈ ÔƒJïëóÑ׎lQég^"(Ô-ØS# õVäùX‘9îá«E¯=Hûu=¦ã­DÆcOmñvÜAuß›/á­Kúð;>¼˜òuç "Ç–„/êÝHŒ=£ÿ£¸F–j~ǤÆÆ$HÞ´ë›ªÊ ®‡8°½æàFh#M¨él„{ Ú©:a©ÑHØ×ÒXÉb§n’ª161 ÈÜ{Ñ!ßy°©'TUcÑöbç|cÙ×#¼ãLÛÔ‘ Š€HC ФqgF¹v~!&5ís[e‹ŒO¡ƒÌX´ŽŸI:¦ÞÓ®ÿ¤’T§Pxê<ͪ,í£;£ö¹…&í öÁÜc¯5oG]kTLo\J™ ˆöÝôæòƒ-5ÛËŠ/êb;ƱE½±ÕæIcÆ¢f멚¤1±Ä3ƒd§$Æ£9×üÈÐ`>ßrpÈ ¯H:  ø»iä·F""©I(XœP×Êè!¶À–² >ºH1ü¬”©—¹¹Ø±æUÔZ+œ5°û¾¬ò†dÛÓ‘ žvò¦¦t¿)1º{ÒÓ(n€â>k'r^ضهMÎè«DäðBŠHÝ–VÝ‹B…lJJ’\ó´ó*!ç'Õ=)4¬öаr»”.bê²ÿ¼ –ˆcÛÈ1T0¼hâ°Å”f¶Úcïª*×DH&…í㨽­É}ŸKkÛ~Š£6á œ6qs¡ãa‘óz+Èž’«Ä”Ø6\8Ú§qóŠ ¨Ó‚G®¨e@ØÏ¾:°Ë ô2 +kz҆ќ™+ÆŠ5QXA=2£Å N›ì®ÏÁ¶ðÓb Dù‰@K*'ëã“ t¨BÓ oº•È‘¢ BäÌ197Y3¥-ÏPt¥Íщ°Ÿl¨ÀˆK5°’,¢º»¡IÝ+¸žíkitÁsžšÐg] }bWùo¾ó¤ÙT„$0´ýÚÄäycï«:¤×<&~¬­´$êòª}³á£ÅŠ©,¯Ž;Xî¾O°æõÁZе˜kÞX°öî°f~·ó-DÊ>ùÕ+là >,jßk¡  8@*m°¦ßk° Ö ;¼Ã®hyqH©½ß¿¬©°&‡ÀÚpBŽkZ÷£ÀZh—zì¡›Jó¢Òc4Œ-2*ð,F*Ô„×ÚùÐÂk@<ø ‰[¼K0l°5x &ãØ„î~;ÅÁœÙ4K^Õ‰ºgòµ ?'ݬø¶,ZK=ŸÓ¯Ý½g?Â…³€ìÖqKúÛÿ§¾¬þ endstream endobj 337 0 obj <> stream xÚ…TM¯œ Ý÷W°y ¦•ò%âÛµéGòvMÜ4.¨23&*SÔÅüû‚›ñÅ´{9œ{ÎeÐoÄ ?†JEÍ€>ÖèýV"FIE+TŸ+H%Q7$ªÛøé{ö³~ iò!K0¢uÀŠ õÕf¹ß3^bk|\ql¦ø•Ø@°µM7˜cÆ^†Œkü+Ëã)ÿ"ËԘ΀+ñWo/Îwf„ýÆôvl'‰×Ž~Ìr¦I!€ÿÓøؾ›­@¥ B¥ì#´Šˆ2…›¨ÁÕxÓ4`˜kIJÜØ'\¨ÑÃô„o»Ñøû)ƒ²wPˆÚ¯´9;?˜6§ÙÿÏø”0uí¿'åÜ­³mBpŸ7÷¼–~"‡[w€P}Ôtµœ« Ÿ(“~šaaüeìÀ•EmfAÆÜ 6–ç73M‘̺ïÒwÃ=/c3wn> stream xÚ¥WÛnÜ6}ïWy©ȲuO‚"‰›¤—$NêE_’¥%z¥f%m)É ßÎH«uå8E`Ã’ÃÃá\ÎÐÎߎïxðã;‰„_ÏÉkçùÆùá¥ïHOÄqàl.`yáÀÙÜgûýjx®nŠê¤8qOVŸ6¿ÂžØ‘¡HÒ„÷D0ÈìžÍ*ó]u¾Ó¨»…©.µéxWèøžÈ¼ wùa Ò¶F"vëùJ&î ì ¤û¬)Œ¾B9tߨÏekª†AüdŽâE"•`<©UûtÛ ¢5ÛŽ\ûQ,⾈"»E5¸?ëª1UŽ&”d bÈÔrü[*Sô‹FH_DéhDIH¥èòrÈí¦§ÛúZzÙ¦,qâ¬CÀ ?lJÍŠéLQ‚»B>£'‡IÂ^Ž=ŽúUÊqà*úìM»5ª¦AÝ®Öp¹b°ˆ0qUNn`e]V…¶(ÒíjººêûªÙ’N¡z†>·`ºÇ-Wè4­Zy£úòlM]ûž'¤œGÂÚ÷Ñ;Šz PQäþ¥ó¾£™)VtJÖ°˜~$²Sñd0NÐ~ÇiÕ—š6¾zýî7BÝ+{ÛÏ«(vÕ–—KÕ‘pÑfvmAŸãHìGö誤£ÀŠîx‰é‚ÿܩʖÏtχjׯ!åíÑ'g|Á†Ç÷™ 3‘%_iÂA÷Ø„ëçÏÎ^|‹‘aú•FtOz~rëÔàÿœš|­ëYñÍÍÙû×_8Pù@¦¡˜Y0´€€N„¿Zû¾ 9xI4‚h‘X— —M‚HÁÄëÀÊO&(?™ÙF:ªë†+Õꕪ%ÆàÚ9©Xßè½Ñ׌.h‡MD5ajZj/h†÷;5)ëk>ù£ç‡;ÍUÏ%:ý˜^S]N©þÑÍÛºVëNï•Qd dÜå 8AíÝ}\±"ásµšÚÞdŬ´•›êܒˈÂ,µ³Ìvu}lVià")…©K„H Õv'32k4ª±KqŽâÛ¸È\Œ,† ªY/„3ÛÞõpçš#Aà]Ù»‚d¾ëîi”Wè ]Ьê–ZUAýòþ`!%t¤±u<´8²ÜkC†¡8ê SèÚ†X\o¶ÃÁvœm·òdîÅÍ­è“o,û_0}ÆÌ‚ά[‘Ï۽݃šíJGdoý*  …‘ûÒF•9]_«z¿ÓÇ$~ì/¨o|¤x)vßYïdĵ„Ò/oéK%WEÞ]>xDB/>RËX³ô­§kŽ®ÿ 0_“7j5{4MYAA8¯ S››U*1ЍP¶Ü—¡.mw6¼Rõ„Wqß3Ë~š£Ö·¤0túVÐŽìùs)éBhö QB¡K–rNŠÌg•ïçš æ9Å—„mª §‡‡ì´zé1À2Z‡Ê¶6§U眉:·ž8¦;}+H*¯ø[^˜Æ8À€‹%–¦"oûû‹“·§÷—žuxwÑ剭xVi6Ç›ã¥Øãľ›ž:´‚ñ3-Úù¡Æx3 ›‰ ä˜7èLW³hx} ƒÿÒ ÎV¬:™Â±æÿø3>‹G]]Ø {·HÅpzQ¶Òhªix æý v‡ Ñ#½Ü?î 8]Ž/ù/4'[’߯(™?æõŒQvU×ßÍ(¸:g”‚j…'kú~°×úôp‘p–ž?ò\¾Žù½û£êûïþi:œT endstream endobj 344 0 obj <> stream xÚ¥WÝoÛ6ß_!äI$V¤(QÚ[—&C‡­Acð얙X¨>\In’þõ;òH‰nœ¶kÑ‘Ž÷}¿»£‚ øGÁàTmðË:xqI‹€RRfY°¾…ó˜&¤ÌƒõöŸðüúÏUœŠ,¼í‡VN«׿k«åݯöa¸C=e H)´A Mƒ8'93zè"©…,?´¥¤Ô4#%â4'YjDÖ;¦ÓÔú7aÕ·­ŒGµ—ƒœÔV“yøq•e¡lj¼Yi sΚÓzDa‰ö¬;<™ÔÃd'”7Öš/»Uú¤CC bt,MÓ¯XÞÄÄ¥SVŒc¨dsÎà Y­˜w(3¨ª¬ç(‰YV.”4ì­kÖY¨e¯;9Çšº­g±6ôx§f¶‡ƒ’ïOYx¹*ÀÈ€êA¶ûFýìJƒP^MRNÒ<ˆEJ RÊh³ÙDUUÝÜtsè)ÑÈ󇇇èññ1úôé“;?.rl5êla•ïwjP–óØ6ÕZÃtZ £U²±øâ†X:—iè<©tÍvÑjRÃ)›T£Z•¿_~ÅæMxJ'̹<$/Oè`ŒÌ*V ˜%%ᙟfa4·A#G Ë#,uøwŽÚÇr+=`¸²{Dv½Õ¹3Ô+À£–V³ê¶uwwŒ*kT1«ž};ª(gDðÿ‹«S ‚¤qæç.ÇrˆdmÀ§%Ç]htÎÊ Ú%¶a–Øj@Û)¹U’l”@•û=òÊs F<ÃŒ—˜ñÁÔ¨‹l‹Ç–/[*DS6_É([Ë6 mDxØá¸d¤ÓLÖ‰‡Ä˜gäà I–àRº$è¦Còp‘Èʰ/FäƒuøÆ’ƒ §e-ਠK5[k ñHÝqb£öÀìU«oºôÐjèmŒ9ã*ã˜AÆ|q.2›Dæ2 sœl.óJÏKé}9›|f‹ëÍÎ #›‡NÿgÎ=çg|Ši#¿4nê'ê{5KSR–˜T‰Fú—™ßôdcýø@Ò{"ÈrþUO;“ ábl)Ðóe‹jY”À2£Y˜QnúWøS èKá¥ï,Ko·ý`¼Úˆe›Z³O¡¹WØeþ´Ù¼MžX"Y€%’yÙ`+奋9qà‚§Ó@‡ƒñýÕ6ô‡;°1¹w«gFJ–¥áõ^VÊJÈAÍÞŒ5dZYïä B2´âœZó̌œzí¦i}0µ¸ÅÔ. ×w0‹ÔV{·í¶Ê™¯ŽbänIç^¹so4ån1q©uÎÜÍK„÷fQm‹­$<˧šâþЪJÓ‚Ï5Ì×"s¦k7%͹ÛÁ'sêsêÅovqÕô£»øºÝ¿í·ò?úÉn€ï"pÝ'^øÎ Þ³è "†_ˆùì䔀é`¦L‹oMJn> stream xÚÕ\ËŽÝÆÝç+¸L6=]Uý ~@, Û;à =FAD Hþ>ç¼÷r¦[¯™Ò•½ÑÔ%Ouuõ©GÙ–¸HZš,RÉy‘¶hî‹ôÅŠ-—Tꢲä*‹êRj^Ô–Zû¢¸­á'yé ?)‹ÄŽßà1ÒÓ¢míeQ<+ŸprL‹©Ä¶˜Qt1¤”Å0cx~Äà · ~lx´âÄ —%œ8¥%E §¾à’–Œs4O¨œC„^pž]qŽG¤NÐ çÁÎ1Ðy3¡{_²ºé‚GZŸ ü 縿wœW@Fœ7@Fœã(ÐT‚‹’ŠR@BPbª,EjLÉ€äß²@T( !TiKÖŒsŠ!µçŒUŠ€ªA„ŠsˆÜ 'æ#Sÿµ@„13¡c†DèmÁKж´hè3]ŠàœÐ˜lÌ †‹óhLZˀƤ´h(V(µáQ9¡²šr\•¡Ly-ó‰1RŽjãÿò^Ž¨ÃˆÉWÎQRiª(´¡¶jÚPšGID)IÉëï¨RõOæáˆ6¤ ©0Uj$£‰zUÌ£ÒªQ´¨š(hFj†(m«V‰ýÖ†YÐÂÙéÔ gëHIvœŒF©×fD£ÖÛJÔœ“BÀQâ;t§œÕIªs'`\å¬v˜Ž8cFªåüö„Ñ(ç·g¢uÞQ°öÉïÒ+ýg4>Çü꺎,r>3ÍU©Ñxã‹ O6ágÌ´Q‡‘«‡£û6Ì ,:0¬(˜8Ç1c ÐwÐ%i'•wº ŒÚ8ïP8=Êj)XFg‚©‰¤zÚ ŸÇÙ†Šð;º ¡0¬HXf櫯nž¾yý–Àãð?Þ<ñn`Ja¤…²Y5b†P<Œàù¥†ÄXº' f#ƒ% ÖwÀy1ŒÆZ Œøˆƒ¨$”ìA/GœRC¬›Ú¬blу nGœlijá”röÀy5âÀÀ¶¯8 c‹¤#qÒ’n¬c`¼”= NdÐNÝhFèуvD _ÛÎo¢ƒeÞˆg'8í ÁIÀØŒŒW 0¶º0œŒ.H”}@ˆJªK 2z cËñ âñŒ.AtÈm2ŒÍ%ä‘Ñ!’ ÌdV °v,.@£BÐŽ nã9áâ<øTF7„¬QÜFtÈ-Åy<jE·1’'„q.L7º"d“¡ÙTch.®UF_„$9hÛ(Io@bå4:#±Èn@ Ñjq¡ÔщZ`·F'L§£7’ØülL'Rýô{Ù[9¥ƒ,lG§„îšiœŽ®Bö˜6²©=ºÐ§Ž®ôXžZ¢"qIäFWš„ž6²)­! ñ \)-Xß*F§d££ƒ+9…–6V+ExŽ.®$ÄÔ}#›’0:u]\A@_ÓF6™q­d££‹+‚¨ºodS£S²ÑÑÅ•ˆ”!mdS"R†êB6£‹ËÈGb߀2ó!õ«ttq¹"iH«e$D¹º..—¸0rY«£wË CÞËUȆRs¡¹Ñ»eäÛ=îõ*¦CæBs£wËÈF,ï@H‡¬¹¬Fï–cF’°W¬˜™ ÐèŠàKÚ[) CóàSÓI-©î:¬@L‡ÌƒæltE é7a¶¢R†æAs–&U+ %î@L‡ÌƒælRîC>ó^†CB› PJ=IÀ>}¯[)Ë1ìc“‚ˆûd àm—lØÚ¤¤TÂ^é™yÐnÈ`e}ç9CÒÝ›ýسII©‡´óœ« ÏÙè† VÖò^#CÚÝ|xnRôss×i«)\Í…~&U?¤Ýuç9DX¡6ú™”ýÀܺÛ6 Yj.ôójR¼ýì<§Õ '5¥¸y¿5Öc<è'¾HK ÜòÞŠW¬ÇxðBšÔýÀÜ1î@™õžK“ºŸ‘X÷r\JÈÅ©ˆÃ^?hKO~1m¯É§6¤Ù¥'¿œö×ô}ã>ecŒít;*”û™§BEcÉÔèÕ¤ù¥²Ën¯T$ŽÒ£ÓjÒ\ÑŒmv{±"bD ¶Lš+J½ì@µ„Þ=lÑI± ‚ì5„b!% ç´Ó÷ˆ×À{ýñþ>âÃrñkbÁMZ›×¾yëàø‘K ÅÐÎzÞÈä ÷v2ožv¶‡o‡Â¹ïÇŒÐã~̆ð{¬¸ÊöïÓ1e±ý8³iܧoö(ÅQй@…‰Ä8”ó°/ÏAƒGÑ2œq 6NÛAì•ÏzúA/Óa]6»¯v8êð¡‹ìc4x?Hç:êàFæÀÿ·‰i~„©_“s±§õ¾õc^ù8IMdÛVri9€¥ÄŽn½€±ì‘60pvÙÕ”nÐÓXåË!5”¶¾šg0QM.X5¾;AÇvnˆ=[P›­›£]½ƒ|´x6¡›qû„Å{¤ÞwðôwÁwoöŸóž28_©?¤º«.­6 Àê¹¹p2@ÉÜhÎ`›ž±6”Œ<ÿ\´œ8à8%«_ÞUþçҩ²®Û«Üº+|5³Ÿ1¯{‡¥8÷›J»†¸?Ë}°‰z?¨½wNÁeÙ»x‹Å^SqïA§^sÊxAGGy\óh‚œÏâA‰/ã8H|‘Æï³»°Ÿíܵ¿/€Úw¥ËZ‹â^K^ß'Ía}ÿ¶"ùñií¿€qÇ/?ŸÁ7îƒ=ÌG~|.sŸ=7™/?ó#…¯oð½ÙÂù–BuÙi›Pøl§ð»`ˆ3Ž´=QõU³¶w{”Ïï:B­ï ÏÇú,#*ÛÞ9_­ÏJb×èg N`»õÝ{t‚ðþh¾TüARæDR ë;ú"ß Ï,‹3ô»~Édƒ*-”~ê½aÈ;–×ï5‘?¼L¦ë†»÷|5³¹:îûÁwÛ`íÕê V”?,¢±†Î/И­N\%‡è’ÈÁÊ=°Z?Âpl‰G2ž®T¿z×´Ð{§º{`c{Ô¾¦B¸‚½c@ŸøS(÷ÁÅgŸO2Ôõk*¡Åº°'ŠøšK ž\%ßÔ’3”¬¯“—{X_lÞœië3ø]žù½~û…Û¡.Í­öKê‡[{õ>ÖlñƒeÏEà±I35„/4Ñ•1¿²Å ùv]äñYPçÉf°Ó’ž±Tñ·×{X'Ïã‡ÎÄã·ª~üa®ÀüªÐ}i;ôðrÂn‘È¢Œ­ñ y ɆK%åT@|Ã!n@±©‡}¶ɬy ásG®Êú|ãHR­Ê¯9"!X¿Çì2#!H½»b)2÷†‰>a)<7Cô»XïßÝŸ.ï«åU{L.-†8±ðUÿÎÊCâ·0?òGåò~l9T="_ßá6/7¥øF„8ÀNqd·ÚX?èðèòŽ•¸cæõ®É+4°˜e^98Ê´¿GWæ¼ëԳ̈́Ϟ2:ï‹7W.ÒÿáäùÜM;oÏù¨þ*§2§¶~’é\IÛÚ±×JZOÅ©¿xzƒ×æ÷jï–íÞ·²¾†X?O|ÉG%t~ ~YY×WΜµ´¾‘.`˜’ÂO%±uUÛÃsÏ–3ßöµG“ÌG®ºéŽõU#¡KË?tD ªXàW€S üBz~Ñ´¼‡EÄ8å!œÆ Ÿ4àÿI&æ endstream endobj 351 0 obj <> stream xÚ­koÛÈñ{…àjêÎ\s—ËWrh‘ÈvàÖg_Îú!ZZ¤,â(RGRQŒ¢ýíÙÙ¥–mçCaCûšÎkç5ùcÂ'üñI$àß›ÌW“÷w“Ó {’ù2œÜ-àÜåK`ž}vfLL]Î…t¾½w{>uý(pºô¡Ìiš5Åשï9y3ýr÷7@%'xÙKX"'®H˜ï+lwK¼æû=2˜d¾$d"Bd°NÚ¶›UÞj¸eÚXg°di— )4|ÛÕMžÑ¼¨ön²ìaA³{KsuQ7«´cŠ”BÌM÷4özê 8s¤p‰‹È©Û7CBŒ͘Ú#šð1*Æp]t-Mªt¥/"‰LýõXI»|•WøåŽ.¶ËzSftüCìèOµkZÍ ä,× i«ÕÃ#K?Ò‹QAžâñH‘~4¢Fé1˜Ô‰:we(Yˆ|ê ­PÖ2Ò2–±’lÓv´H›Çâ t:‚3¨yOôâ‰à{,$!œÕ Š­Bý¡RÍk’RZTEõ¸G‘)›º2Ž‹i,œºÙƒ¨7ÝzÓõÐs×ÛÚaÞh{éY€y¯ËÎ"‚4D/¥De¿9’® µÍÓ2g²ImÚÕz<S¬G,4z½¸`Œ]Œ*6`±è«¾¼UÜ t¥ï3)l¡\Œ ƒ2ñ!ŠÄwòE6jœy¾†žÝ;$¶=gÒ0R¡7î§#ô,ò-=8,æh†K¤Nì¿MsJ½õ´Içzº¯ Ô˃s4I˼zì–†>n}_x‚Å|9`¤iÈÑ(Gå æ©^·¬ä¸¨>ÍN'#è-I®GDúøË+Ø¿KQ\+*ú.E©W¯«+ÊAùR `-kí‡f^kïÿ¼âBZÉ Ò„7çäûݺòÚ¢®F1†, _`¸y:÷àN€¡' ƒY¾H7e7†3™÷ NßzŽH£w?¥ç O²ˆâœq@‹º,k$a«“Ð÷¥£#n[¬ÖÆ%æßR³¶ÚÔµ²Ü´]Lߟ7yÚi¬þNt°›õŽ0ÒoÝçw:i±Í ½uq*¶Ýui Lù¿ œÊâÈãÞh~óéŽ&&þÑbQ×øuòš»6̽û2òé¬h×eú¤ÉÈ«ìíÐTöò[yèn(Áõu‚{sö~öÿÈo¥j\Ò‹ .Ü´³@éNjÞXKç*TùœÞ†ºZÓþíÇ+ÚÀ|÷!ms ¿i{д¢Q=J“dÀ3«+E‡#f¤"}'3Í=%Ëx;oé<§GŒÕYL]õiMfÀ]唽—térèIóHêJ&f—>#ÎB Ó÷¡bwïé+{¾¾Ï¸TðgùCâñCî|¸þtzüùÜÙ|cc…w‘˜xü©ÊT%Âå z$q¾á–œi)rÙÛ†e @o”ñD߃ÌÎ\ œuªÜçï®VQdgÚùÉw |{”`8äÆàýQùÙB! ÕG¼c‡â(Ù±g°(*(UÊ2ž¯Ó盢$/+*u`òáê׿ÓÌ0? äsux0wË!~mظ3O«:0¯öá)!鈣 ·“îÙñAȃô¯^­ @½v|ð*!ˆ*ŠX‘Ýd5ù®tݹäUC9-Ê⡨³‡¹p3x2‡VˆY¥Ú}`¾®;t"§Ë`põq܆ÇÇMCîŽSxF’Å™’lˆ’ Q²YMc^i/wW <ƒ†óÄ= ½I›§½ïÔëÎd=‡®å_¯äƒ®KßwQ&#âˆ$“æMëìc¯òŠLåµNÛÖTýÈ¥biIJë¼7ÅZünÈY ²¡ ¯ZeÅ×"Û¤%­-?„qO õfˆ ]ïæª„!ÖktÒ>µPÑãé¶Èr:Ü´J/ˆ±­uüÀg±©Nón~ŠcPéŽb:Î]~:ZÒAÆ4,éz¬h¯Ï`N"´y 4òCçL ŒÁ÷ú8VW¨À×*3ƒ±×.6JOÿ€r@‹ f~xˆ6XjtØÐnÚè­Ã&¡§œ!(ali¡Åéåvcÿ²^™žR9|W7O&bI.‰wU{A A€YÖ‹Jœ n£zAòöC0Qtú\!UÝbYñ/ż©Ûz£0pþÆ\cܶãÐÇ‹ƒ(ÚÆK¢sÜ _òjK7°`jG@Aºß¿·÷…F@E‘¥5ã‚bíOJÙ÷çT1RÙ½Sõ, èØ4ù^Ÿ¥}Z!Yd—uùº£¼{aHÅP–U®« ÷ŸgW×ï~9×I/ª’¬,Ç:/®Æ·SÓΣùv/©o=ÛÊ$Oáʸ7 n×ßôDZPÉšÒP,ŠG¶|¥Ytl*HÈ£½Àfã¬oɶõ¦™›æ­ ÓÎZ•‚†±¯Eºç®ße+xªxÔæC‰åjÝiý6õjïúL·›Z'¤¿â2­òò¥oÂG:¼‰Ð†šôŽ[ÚÀ>lð&žnðŒnðÂL5xcñöuqÐà°>ÇJ¸•Û˜>H4hð&â¹/$FµÇHøñ˜-bg/DìgZPþÎñÏ¡³»Å}¢ÿǼR<٢ЃÄcA> stream xÚ¥XmoÛ6þ¾_áo‘Zµ©Ë ‚ÁÌC·¶Ò hú±˜D˜,9’7¶ß¾;I½XA² 6@Š<Þï幓z½Qo¿QoÌà?ìm¶½aïý…Û íÉpÒ ïz#Ïž¸½.ø½0új…¢?pÇâùý~+Ò>[%®0+‰ 9s­¸ šb×°À›øf8rE¤NDu—%I†ç…Ýÿþ º Fí9MAx4'ÎÇR#«Ôô›,MŦŒ³”Äe§÷´·ãE¡Õ(3Ú7—³ç4KâÛœçÏý€YïènwYNÔâ;ßîñA*üþb4®«¡ÿÉl}uvŸì~?½^ÌÎö…ÈO?ý:;C Y( cŽÍÆÀÏ¿#U@n‡¤"mÈ[-¾ÌWg¿<¯?_žÎ¦áôãt=—D·o×MÆvÀ”ä–Z« ›¡C‘Wžº`ܼDg =+»£‘l ã˜ó\.úV!à/¥C`ýy=¯BlãM–d)„ÆÀuк¾á»¸äIü‡ˆ^ðI"JH¢ ÓÇv]…U'Z¹VWçlÏ5-ž4žÌͪ®wÍžetQ•>iVštmÈûtÕqŸÙ®÷fÅPuc7Þ%Ü z¦}¯E„««˜ö-™ÆBfû¬ÝÊ5ò\û®£„È^öe¶å¥j¤À{‘ ™’/d€ >æºÖò:ÔÑÇ\Õ#3×WчK2úpÒŠ><-£÷À R9§´“¥Š# òZ°Œ${QЛ ÜòüwÙ_œñL\Ö¸%÷â…päX œ:ϱ+yÒLr“q¬;Ÿ9 p¿]·¤'ùž%—ÔÊ!õfží!ƒ$¾A-$?Ä…hБû‚l õkHHÒ1ãÔº#®+W8¸¸‚þÛäb¢Ò¾zu#Äy5B­½@Þ—2Š º1=@RÐŒ²'•xxR R'¨œƒOÒáª@Ë›¡6-ÎAí­»Î¥;”Ï×Ô"(`cW±B ¸Ðn¯æXƶ ÞuÙDgBàšö çµð^]¢Ü$¯’D[ú®E¦{±¼|Àƒ|¯¤­¯¦NUè^ûâÅþw¿/™ÐIum“ßêMzM }·Fà¶úz¯š‡ôQ§ý¡Âí!}ÒQ ”±áÇVíO`p¼\žOÃÅòjMÑpF×S7l z‚/N'dž6_FÔw œšoøÐü>Ñ:»Z~"¹ð>x9WåóßëPi—‹ ï´‹Çùj> çG\èÍo,Åy¦Æ«ð1M¾LWç?MW7ó¼›¾Úý|=½¢Ùlym8ßô;õ`Ëc5N¾L/¯çë¦N®’õ£µš|8¥ù·¹‚:ú¸çi—Ï_“o ¼Æi#~2X€Œ¾HI?ÿðÞUû endstream endobj 358 0 obj <> stream xÚÕXëoÛ6ÿ¾¿BØ€EfFêÕì7v»l©Ó&κa6Ùb¡²äŠrÓ`ØþöÝñH=mömHR|Ü‘w¿ûÝ1Ö{˵øq­Èƒ_ÇÚì¬ç+ëø·\‡%Nb­nazŠ¡µÊ~¶gE#ê2mò/²Eñ0™ú¾gç ¶¾½©E†]n¯'S\A÷uÞ4¢¤E©¤ö¶*Šjâ…ö½|6ùeõµX‘v7ª÷Æ¥¾I׈ <]lûwj jò’Úó‹ÓÙêìbyEŸPsq½RŠÜˆ¹1\ËgA ä]ÌŸŸ©9g0>¿Z~µ-öï²õÉõÙ\uRÔ'¯ßÒÇ>•ò¾ª³Ñ½—¯Iïjöü|AݳÔ.~<»ZéÓÕBŠædLÆéåb¶Z<‘B;¨ckÉsÝ.W_´F Î³ËÓog—7¶7=ûæz¶¤Þü⺕|3=)<¢5Ïú ¸Z Íÿg«X+yHË&o~.~¬@åz LœÍO”ô!§.ó8ü¾k™—ÛÉ”;±Ûi#$}ÞçÍõ~Ó‚pr¡zpx”ò͈ª€E¾ž>B9¾-û=€9¶«ºÑJʪ¡NUb`ïlyµ¸œÄžÖÇmëƒ^“²¢Þõë9†Ílûöj¡×Íç ýÁmÑlØd‘ýUµ:!Úc^Ò7¸ø˜ÂµÅ?ŽºÌÿFØ©E}êW‹•Fl;ý5™ŸS“zúí·‹ËÅ0Zô~~òŸÎÑÅ–óÍEmWÌ–óñƒŒÅ§K:tŠ“¡ûÉ9óyhx3Œ qž23×ï¿z¸zsØÍj`tß±E=nÀ®hØ'ð­îQ¸]# Ø^ Cò¯);¤Šç#ày“%ÊRlÁjkõHG¦ëT Éôy¢Ð|u ¹Xç)˜‡öËåõñ9 ÙwíÃG6v³0Ö1~]fxL60B°o„@v:|Ä!¼4Îécò΂< —ÆåvI36R@ÓzÞݧÜþn„vº_ÏR~¾|©;õ–|XK"¼OûX„äðn#îÙ>MèËÄm^êœüê'8ï¯óóåì•ΑŸšˆaYQ|:*Zd禿EF†\ÀKÃyù蚌01„ëpÄXdјFÚã â6ß²»‘#ó€Å¦Î<"è€áæýkgðèHQpEö•‚)ö¯ ΤMµ8:È: >Ä$uÊt'h5Z` ©Ý>m RÚÁà D à·5,N·†Åm’Š`±ÉÑF"£QxÌé);©ó l’hC;qæÍd¼—ÖÛCw^$ñ"— ¹ÎÀ÷éA»W'7y jÚU„[kÙŒk}¢Ck¾#Át0¢%nªG…Ž~(§Rô±Ú.â6ÔÐZ]ƒ‚ ( t2«u÷Ÿ#€öbGs]Q©â»-É©/cŽq‘£¡gôX¿ôÊUî­;óÀ3fŸª§’ïvuK-] :²¡ †ýT±ŒÚRÀ–”ò7Œ¯ÕuI–»|SU)‘À|x:§m±KQõÀÐÀðHoj–妴à ™Ÿòd‘©È¡ îy,`j‡‘ž‹…D~H‹Ã˜0/b±QÛ¿º"3}õ>ZÔþ…†B¾-“X;L·5uï2Ò€ØÄ)„&ˆà®üyoÁc1¶î8¡ãâKs ˆ˜×~Ö•õF3¾Oå$Š©¢fœã¢˜¹É° ¥µÜŠYªw f(xɆ®§Â37°š¹kgt‰²¨ÒLý¦j¯0QãžæiIR#ƒå;M˜¸¶ò—wM³v| ¥¨þ޳ДÉc5vüµ‰£þòÁ Ì½.õbÄÅ4ä”òÂÀ,}óÉ_ó¥ö< endstream endobj 361 0 obj <> stream xÚíWÝoÛ6ß_á·È@­Y%+ †ÁM\ÌC·‰Ò ¨ûÀHJ"T–\‰j– Ûß¾;©/+M0`oCð(ïówGròeâLæðçL ~óI´›¼ 'ß¿ugnÏ'áíÄñìc>™áÆ­«¤üš”ÓOáÏÀÊ;œžg;ÈC¦ ˜¦laãÌu™UÖyžæw8á–¼Op­XHq#*=ÛZqr+êL¶Œ­d0²ÀŠDv_Tr;=ÑÚ{†ÎHÿÌ lÏUFœñß¶5;mAqK£67¾Páõúì]uEq•ÖŠ}÷ëËÅîEU=`ä‹2~©ø¢”ÏÈßCüQ¤¤°€º˜ÔÝ ªÇ^ÔÜAòë6‰uݹ¿ÚJû¡aa+0*r­Q”wõ.ÉQ¾Ô_š¥,#â¶È2Ì·´FÛ´,T¥qR’-ÆnÄ4ÓÕûs­Y ™(u¾%+2tÞµ‘8ýy‡ «èÛN˜ðÀäFÅøŽUíËDÄDÈ (`¸¿`¼öò{Ç­×dÆÌcžµ¾%nŠ;ÊD%‰ŠPÀ½(E$•L ° K"×c7Ž*þ¦Ò]Ûó”oi¥ãj²°K£"+r“nZçVšÇiÞW$¹Ž±©+Ñ‹.ïÇŒ‚kŒ€À錚œ9ÉÅ%H.=¹ÄJù‡5È?ښ칓=Dª™6†]Õ^D „›»‹Öä+¦¥–¬EF¬²i†på x©Ájwe²3h¨ÄO„dÙì­å aiŒC¸©˜'´'¿'Q-MaÄi™D2{œ®5ü·ø½@p1f­/fÐ(XaFÖ¡­aÆø4´>E ’@´ÆÀDè«óÕi¨‹ÝŽŠ)·JÝP`é!•÷ô½Q‰}*E–þç$K$”G5Ö%]׿\7¿#cƒÇ¸u4Ö)Û3Ì6OÕf{Ô!ÔKÝ‹<+¦ã,Ñ哲)ê°ù3b—ã3›{/6 :ê±fNµS´ý>èé>È»ˆàT°à…Î-°©ÃR…Ó3ÛgÝx¶XCÐänØH©%7í¥–ÅNHh!YöH ï’/iv«l_h "ñP¦f±,j¨ Õß@`)Ò*l0È}B·i ]7TK2˜q;,aN¡ûàúâju9 ˜&ZëqÕ`õ!níÊ_ª<8µÇ4[LEU)­z˜é¦Òeh“ƒ3•p}@+ÏPE¢äÀÚÎ^ªnØ•2ó€7g tcc׊Bph_k±]-íÌM%À‚¹?!ÝÈSÅÇ7¶š¼V-¡ó8¨ s+å=b ê²’ÞÍ9Õv÷¦K!ªú™·÷½Eç¾×@'7g›Øí³Þ=¿c„ñ­ÜÁýäµ2b޼‘Ào¸ˆÙŒ×°)KAWµ?iÈhÀƒãùæt®7W4ý‹hgäî‚®ÃM@~y„`FúÈ~Ì>õ8Ћ“‘Szf2ݹàAiÁ 5¥{ õ<¦p¬”:‹ÛÓzaNklu2Ñ€Õð-T}Á|ؾó!˜ÿà—#˜ŽÏû×ÀÓ,¼·°>;éA¢‹JÆÔ7óy ”ú¾a}ÿÝ?ùÉÅ endstream endobj 364 0 obj <> stream xÚR]o›0}߯ðÓb¤ÂÀ˜4ª*:¨–)MšÆ¨U¥9ÛE£@±QUýï5\O-OHç\ßs?|}Ñ ò«?EDÿ.zxF }¹¤Ès©;Eìy3¥ÈîBÄvw8—ûòɲ©K±ÏuÁ•`¾îÕO`?¬{ö]'ò¢a&MC¢ëuYÎbX*p"߸']˶®-›Ä¸j”)RV HU`óå&»±b‚Ù „m[£á…¬€åשE"œX±Yfti¶ÈŒA±PŽe‡A„/;QÕôÚžO2íÐ ‚¾7ñ›ëk‹ÓÞŸ1Ùè¦.²©ï¸´—+¾-„eDÏ‹wà7€`_.V_6_-7`¾¬rÖò"Ç‹‡mL®›õbÒ;Ý‘#åº&—â쩨í¶³|žö´•¢™]ß‚Qs)_«fw,VÂ2¨ßÙ ø&c@þºÏ&Ÿvz'FÆ}û-»1qótOgÿÕÇ:O–£<çÿÒS=¦H–éñFL«§Ãvà!_Z^ª½:Ü÷'æg£î2!qw ;¤qF¤ëO6Ø, endstream endobj 368 0 obj <> stream xÚkoÛ6ðû~…>Ê@E“Ô»ßöh‹li‘®0`ÛFfl!”èJrÝüûÞñ(Y~dMŠy¼;ÞûŽ>"àð'‚\Â?ª&øå6X¾ä,ËâàöŽ£7ÁíêŸðçívÅ<Ôíªþ «,[üwû;ÐdLX^äž&…Méh>Yó¥n׈……¯WÚôØ×ƭͶ·ÆsKÁYÉKä&RV&À±dyê8Þnô"’Y¾»¾ùƒV[U-d>,Ò4Tkí¸¼¹õÚýùÎ/º5éW9+¤‚,σHrÁd⸋1Òy’#DƤI™t$u[™ÝJ÷$Ë0Š·íìºSWIäs\2‘{$Ró8aqæ‘^ϼ ±îÕ®"elëﺾY¾¿ºñ‡`ñ…ÌBݱE”H«lÙ‘H‘L%+ƒHÄ,%ÃVªðÏ`¡Æ ڵκ½Bï;ÛЙÓ•m‰ÈMÝz°ír¢ßhcèt°äÏébá‚v,x¾ïêaÐ-mj/ëÄð݇¿œ^|®Ò{5ln@iˆ±8&Žr¤ˆQíz!í5Q°4¦X[qˆTeN`Y–ÞÅš$î<ÊF G(%È¹Ý tú/‰ñàʶH8¨ºíéTÑç #!B\U]½j p€G¤³;Ân5:Å]mé¸ß’óªúþqÊßi‰Ë…xŒFÅ'ÃEQcQ†ó¨Lb–Ç>*Ñ hEw.¦8p¶…8ÀLÒð­³cGpýU5[£_™FE'?‹|Ð"TÌ“$Je:Éæ6÷Ö2Ø^ݘȹ7?ÙFuƒ™—IXøMÃÚï[]é¾WÝ#Ñ¢ÞõÚœ–Y©A¨×yÁ[£*t‡ãéaÞVujðôÒ‰à3 ÷›šÒ ·`I5^;:Ü%홣…Ç(2ä‰zpHæ1Æ"ÆÞ‡ü”«ß7?0b©|žùý Yf<€Ý%¿xö¿|°Ã$7&®êûMæ‰c6áZ™ÞÖq^ÅcÅA$ï5@ò^{uzçÁ›€ä¢Y·¶Ó«' ÄÕ(n*‰ ¿Àt\yaü¡ËÒ|ÌRR¯;ØÀ§•+ïx8×u¦áTÅÎtŒtÄ0xiîÅEÉ„øqç çýK'ò©¸8Ë×+ŒYŽêñã'ÅNÜ(=ä¼G®{ÈPìŒhr`I°$»pèŒ5Qú+¡ÃºÑë_ðnL5wõ½Ú™¨I@€ÚÝ€åþrªbŒ$poïÙâ.§î'}™v Ý5u« ”ÎX¢<Õ}$¢ºï°yBˆÖøü„™h†ê: ~U(•Çܧš‚WS’Ñ Hx\SÎzî³ëK’ÆLæ/ 1çÃÇÙÝ=?”|÷ÌNºgÌ9å%| ˜} ­+ |ô/Ç0±wF7<›—lä½Q=aùù GÜ®u«±ø¯ÆS2îјpÙxc§ÚÞ¨Ávî®|ÞöËÉA—ãì´ ÄÿÓùsÁÒÂwó(Ú›í¥9T¢›Gù:wˆþûŽNyÌŠâEŽFI&øE©ÎÛÈŽ„û´Ë4XQMÀU¼<=HPªK)3&Yúò{Á|lÃÇAþIQã_C‡‘ yþzsýæoZ^ßÐuP¤Œ8„õ»zPwÆ íÊ7¢|©û2~~Ï9+â¹ãTǾîŸèU³ñGæÂ?îë÷˜ nš„u£;mií&KøúG@…ýìA>/þ|jÍÅÉÔŠÌ­¿­߃ŽõH?KÜŽNz¢Ž¶øþ©h¶LœÛ)Ú© 'ãì°)k°ù6SñÇÇÆÑœüÌl‘qÎ 9¥KÖx¸4"sÆËÃÃòå¥ 8-2–^ªŽtëeÜ÷9`qY{¬Ù<{Ó$hQäð–÷&ø|ô‚ÅX?/Ü£U²$A¤‚‰òø­ìp¥ VâO€ ²ÃÛ24>n†aûz¹Üï÷lÝî˜íÖËÞÞ{Õé%(÷°> stream xÚuSKÔ0 ¾ó+rìH4ô‘¾ö¸ zc9¤mº)M†6Ýeþ=vîNhFŠŸŸíÏ.ûÅR–À/eUÿ„õ»oÙ»‚¥ o’†µ#K Þ£¡díð#ú4žâ¬h¢ë)«"·¢RGV©¤2‰¼#÷ó¬½"Q’ÇbÂ:©Y÷”´8³zí,E¹ÎKmw˜ƒ¯çÏŠŒð„v5‡;xHRaÔ[P*qlo’/pM´.¡/ÂatƸSVFÏÚ>ž~¶ŸaÞ0v΋b»wÓ$íp·¹ß·DTZÝ0• ž—,9OÄ–òh.Ðñ).²"ŠãÉ *(£sÔÝãVYý« “°ÊqqÀOk^便D ]ŸQèþLj/q@QV4 ¯L£¦zqE^#r‰/‘êæË²„çx1Xûÿ}Š‚§uˆÒ\Òs1r·xõÛS»£›'éCŸ«ö²3¡kðð¤—UR-XtÁEs»i¥¹.zá[À¾¸–Z$!9nðb”ß4½x²»‘,ÈÖ?ÆN*Ì6ú÷ÐyÍÓwAª—PTZBïàÔê(´2ºÕd×–LþûøõÛ’f5ªYÙ>$Áùá–‘ Ð3ÈìÍ:ÀC[eHÈ /r¾#ƒA`øYwÛMðÃE‹ÃÂë ²õX6{è÷7ˆY endstream endobj 374 0 obj <> stream xÚTMs›0½÷W0ÉgŒ‚ø4íÉnÝL<‰ãºäÔéAµQ ‚€Ü$Íô¿WB‚š|x:{fµËî{O«•Œ;¶øa#tÄß6’Â˜ÅÆégl86 ׈7â³ILjÓoæ´ªF–k›ÀRú VAhÎGßã…¨ ÇCá$Ô5¾p¢¶fþ@Š*™˜E),6SÈ•ŸB“Ô´â´d-Î<Ö „*¹^ á{‚Gá!<²0v<óR‚9,ô`mྦœƒv¨¶—„g«ºÜjÝžmÙ‘$Â>Š> stream xÚ•UÍo›0¿ï¯àHªBŒÁ¤kû’šÃ¤©\¦¨Lâ0ÅN—uêÿ>ƒM  F‰d¿g?¿ß‡ãÙp ŽáCùF”_BcúÃñ Øs07ÂD®[U03Âxe¸ÄÙÄBÐ3“›Éc¸¬—]¡zyz¥×JB7[QȤ¹c–¦¸ä*(H©&æä$%¶lÏq«(£)ÑEWÓ¦%ômçPôvÞ_«ñ©›^¾©qq«ÆD®Q®èõÓ£šOÕàFÈŠç¼`¥¦1~B¼á£Y°äcztØV^Èž/¸TM’½ÓdLjð--2’kôÏ{œ *h#~sbð¼ÍiF_‰¶Dj±P{ù>»rÔrB›s¨Sc^0S­zc ”åïÞðËÍàÉmakÕöE‘þíq{kñ>CðÐ"øYûƒWtŒ[sR¾æèª³š§RumÖc‘âÆKú1ɤ }¬#þ ðhîÙz5ê—¦ðDcW»à3\îˆèÜ¡ç!ÆßôI©Jϼï>é ‘jõpn}£dÃFê—ÝúŸäõ›•;}ÝÒo˜ BVÝ”Öû Ÿg2r¨kgn[®#Ɖå ß3g͋Ȫö 5YŸC å[Ìt!èr$"‘x¦ @ß7EOÕ¶ïÊÕ* }¤ñ8®S¥[Ö´@ioõV½SðŽ¯æwD"£FÓ#!Å»îÞ–¨%£gBõ›ÈiD¾ ýc.ÐÀƒù˜âg ôd ðæ¦V"8lQÒµhú·†ä±J~ÕÙk}! *´ÖÌ ê;Ólýõé?Tqû\ endstream endobj 380 0 obj <> stream xÚ¥VßoÛ6~ß_áG¹8‘Ô+è4Y6tHÒ´q q‡I´J¢*ÓuÒ‡þí;òHY²d/Ýœ$Ç»ïNÇû8ù<¡“þè$aðL–åäx>ùé7 ²ð0žÌï`ß§Ia~{í6õ)e¡÷»¨D“)q;õyyg—8Ö¼)D‰‹¼Z©¬ZŠéÇù`6œhCAª­Òˆ¤áÄg)áÜX>…œ²ÄÛÀQJ½Ñœå+=2O=œ4bµ.Îå]o“zªÉªU‘©\V£ÌYYvQÊ©NoEk€‚™w»^šÈ@t£Q=YëÎÈJ_´\466št‚ iBHœŽë¾¨Ay$~È9‰!”“(2ºY¥}rîmš\)Qá"·ãÉåÙéŸzb¶At'›2SöL®pQ‚HÖ&#Yø¼Ñ÷7E=‚ÍHÌ­1û§s[ ][P ÉŒp a±x1õ#¨K,„#½Šð³Ô8±XcpŽ%„šcçy•—ùW¬”ˆ$¼›–¥\©#´úM„±§ ïJdJâÇ ±ùö—l>-¦¸Õ*Óˆ”Oòev/A×bÙú{‰¾à\Ìçæ²Ÿ²‹ž¬úök.îeÑ3½´G·øvbañˆv‹J»ñ1\ýÀÕÕúæo±Tèp.G“¼Z×uñÔÆ¹˜ö3þïiþ®ÜîM諟qäQ0<Übtq¡Kþ.Α,B:LskŒ`½%\ç…·Eñ_º7˜_\ž îöún£Ûëz¼ÊbëøPÐ.O{ýŽÞ¢©v^Yí”8öS蜽µÃ`ÐI˜Z ã–ÂÞB{,³¢O`Ь׮ùlÎJÇY©å¬ÔñlÉÖH[fej«K½û³ÂÒƒqˬÚcV³º“ëÊj·lN[‹‡ÙÊ·qm?ã^Îâ3K‡™ª.2œ‰Gõ¹ŠG„Ñ–«äZÕk5.ŒÈŒÒœžÁ ¦-†4% ‹aËR,HSGS®®ÛgÏ{¹YaÛŒu¡“Ø–¢u´Oàû–Õʇö.dåÔ:4SΆJW*Skc%ÖÅz9sþúl¨öÖôöü‹p¶4]âm±—èĉ姅wþæ"/×¥íypM(ƒ¢¦$¥C\ˆÏTY)¬ìJÙÉkí3WO\¹ê2Ú7XFëC]ïˆ ï> stream xÚTÑNƒ0}÷+ú‰­½·´ŒG7烙KŒø`–=àÆ&ÙFqaNÿÞB™# Ó $”Ós9çÜ´%o77ÍÃÉlCú!¹ºE =(EŠÀ$á|âŒ5s©Dé ôz·Ií86±KKî<æf }é\Ïòä=É?]ŠÊPFzo-ûEïÒyÅzʲŒÀ¹sm—I­ÝixGhe¸qUš åU”yÕøˆHçøþaê|¨°€‚I¯î¬øÇä1Žò|_Žã=}ÖÛÕ´äûœ)°|Yòû%¬$ LÇ @òÑB¡ÈýF\lŠ ^“Y´Ô--U×1Á+5Éþ¦&šj¡ÎâUÔ!6uä¨eµ²À?@Œ e4AýŸÞ·ƒ(¥7I¼ÔÝí튌¾ü{dÙ<Ýâÿ§æA;µ]"ªmâdçÏË,L¹ªoäa±Ù A½°«^ïòl——ôahOrƦ9 {LJB•×+ë}q >\|¹x˜ endstream endobj 386 0 obj <> stream xÚmRÁnã ½ïWpÄRMqb»ªª´U«U¥våÛª‚qLM ÅŽÒöë;€½Ê!²%æ½y3Т(ƒ¢2‡?CbtýLᬠ¬X£¦ƒ|J3RCÜþÃ÷"aÆúå¤e»“{iüf“·æÈòð¬ö\º"uÒ¼&Œ~ÓË$eU†ùqê­ý %ùÛ£ncN«!ÉK<#'ASÏͰ„2ÕÚzìI™]„’4¯°´-¯à¤føÔÏeZýc'yò9vïg€&¹œqÓFœ°. ƒ¥ó,”‘Õ*Ìâ¤À›;‚ u¼›bh;¿S㜴¡9q z%žnBiïpEVÑ¡—#7ýȶ3óÁ:LJiyfq m•PÂso·¶#饕éÔÝ…‹I#íL÷7¨É¯¨öÊ…onœ4ßJ^®JRÓE¸ßo¶jw°¦%àçEÉH8“ük·[5ûö «Ñš‹JŒ¬ÿ+¹@Úp19õ ZÄ|Gµ§&>ÞsÍ<¯üm¥ë¢ ì²X ~ýTçÉ  endstream endobj 348 0 obj <> stream xÚÍY][·}ﯸoÑ}迆@` ±ëÖˆq ´]ˆvu×Q»+Zmj÷×÷ É•x?¸^+MÑ—¯xçÌðÌ™!©ÕÆ5¢Ñ&4R„F“j”´ø¤F{ƒO×'ñrøÞªÆi…Oj¼ðøtç÷lhBÐvª‘RáG¼á|#µÀ+^bàEÄ•&\#‰€ð5¦1æNçôü„y Ah”àp”EˆˆÑhÓ(%Uc ‚ÖxÑà=ea EZbà1XXYÏ«•ƒCãa=âS1 ËÄ-­lH 8˜5$±^IcœÀ€YRÞ™6Lb^Q‚(DÖÀâ]Úzއ9’üæw0å0o80vê•ÆÀ1YpÁ™ñ ÒH¤"p¨X¶V€¡Ž'&Š!À–‘ j°ï _†à]„°X`|/FtŽÙW¡Ã”ŠZ&æß*vÁþ4»€˜ZÍ–0å÷xFá=© ¶Pœ*6çµ›+ÃDÀ<æŒ# L–À|° ЧÀ 1)ì(.€“Ëá:x&Áƒxójð ?°l< °¦×3:‡Áèœ8ø#‡Ü F)Ù\ Pà£0X0à0‘>ò‰x Ùò!5ŽðeiˆoƒLCÕòI.uËg9 GàÒ}uBÇ3ñ¢ µ|¶‹CÛò,]ËǺ8ô-Úâ0´|l‹ÃUË·W—íB‰ÂÕeËçÂhsÕòÉ0×-ßuâ°où®‡×-ßwx¨Z>‘Ç‘hùî3õ¤$<¹“'<›”…‚¹Lœ(Ýòý(MËçÃ8¤–¯Fqh[“š0£ñ‰uêJdOßmÖw|SÅ+ñ¢?¥ÈŸ~.JÛu¥oùZÝN•* ÂT„©0S4‡ß· ]ÏFeA§J$‚„$Ú…i;_h¦“ ÂRWc0£çD¤!"]ˆÏ|o‰6 S'5èÔÉ¿:ûǪu«69¬Ú̉HCD¦žùÀmÀ‰IœhpbrXµÉ`Õ&€Mò0¾£Ï§'zŠ©5iß?+ÄO“SœºÇÈÖ@€Æž¢Ä3ßÿ£?ðI)`>)l¥€ £0 ø:ƒï€_HÏükB´Ÿ6‘hÀ§MY4àÓæÀ˜Í€1›cvNE*¢BExæûo´Ÿ6±ˆ˜mòOàÓ%ÿ„U»äŸ°j—üŒïÄSOQ¡"<óõ,Úß%Nœ¸äŸ°j—ýcÕ.€UûVíe%?ÑUÊ-ù”K›sìr޽š  ,R‹Gþ]!º> :}„ù0˽«ðsª³h(¶€Ç³ÉíÜ‚ÎÜÎ-èLí|aAgj; Ârï¶ ,÷n ™0'" ùÂØÌÝ7ÊÝ÷Ùÿª%‘ý_¶”[·k)wn6šSPh×'7Œ—Ø`¸D£%ÏW-¥ž¹X·”[vßRîØ×-I]IÉõ1›!7Ý´KÅ_éâgjðÙ4½*C.b™®ó«Çu\¨¤ëå_ÿöw\Ú«e§›íýÍÍ;Ì%I?Ì9t”ü‡P„³çq2%tÆL‹ 2ß™“Y’ýœ·á ôP7SÚvÐyž”I:ÇIïpW¥I»aÇD÷8u'Y=ÈhjÞ†6>¥®˜áÆÞUÙ 9Ùn ~kç)õ~¸'8ÓYªœe,V(ee7©·}­}Ñ9GÑ(f¨Dc 6!Y™$qÁÀ;e]YmÃ=Ÿû›?ímº–ejGEÃ8¥*O4\!º‚=•/ K G«ßÊVOãTgN+°¶zpÑÒ=í”TÎTѶº­¹J踼èïwñøñ7»ø ôæpÓ/^o¶ýjß|ØïÞïW··›í{_Þô·íðGgÉ¿9¿Yíûí!þ?=}ß<ÄŽ@ÿ¼[÷7ÍîòýÕán„£fpÞìû_âÿ P5}{Øß_î÷}³»nn£‡uwµß|8lvÛ‘]÷2‰öÕö°ß­=… ór³¿;Ã{½º;†·|¾»‡ƒßë“+_®AOÖðéörw³¹j¶|o9£2ædûDc ïïoû=pn6‡~¿ºCÙ¨¼|SâÚ’YXW‡¥Öa¿ë?ýk·_ñ|Ï–x~Œ÷¢¿á[r¿#†:¢+ÃñùîöFc¼UÏO!ÖÌÝç¤iJM™RS¡Ô”k*¹Tž_¨‹u¹œô[èÔD«/îoo?5›ízs5‘j?ƒ“âËÿ+Ê f ú—íÝýeb¦_7Vè9ýL¯ëøe]èI]¼} ºuø²<ô¤<^Þoc›höýuó)3RÖ±ËÑ“yÅã¸ûöýÝÜLÀU¼,=£Mä‘#_Ý<†¯ëøeùèIù$›Ÿû»Í¿_©{([§™(û›ýæð3Ò qï>0S»i^©^–™lÚqõó'Þ[ü\ð¶Šoª•Xçâªh¹lR#È׽ܤ8¹,wH£ÎPç ãš²V©nVU¾Ã Zæ£,SCgò½ªã×£}D|®`£Ç+U/A漯t¿,Z¢s{¼2uåöJÓÓg¨6EuÔrc%w^³Q¶Ž?è#}¦ìì¹FRŸÉ?ŽT;{V¹—“ÿòE Ú<•Uj'UúC³Êª©rfð27e¥ZyŽàWUp[–ªUg ò²î¡¬W;©××»÷›«Çˆ¹ª#—ÅjÍ™¢\×ñ«Á>BD¹æÌ%a¦§w¡.ËÄÒã;É/«ýfuy3ÙñÔ ëÛ²t­{l©j1˜9* Éú3Ä©e|ÀF8¯kUÇ/ËÖ‰sůuÝCY»NžqâÖ¦ îÊÚuê<ýkªãËÊOYÈ¿/䟵‘äï?ç¸yùO;ñª®.˳½, žpÉüøã ý?õ-\ˆ endstream endobj 675 0 obj <> stream xÚ]PÁjÃ0 ½û+tì#N;…Àš.CÖ1·¥WÇV2ÃbÅ9äﻡ‡$ÐÓ{’ž²ª96ÖȾÈ)zc5áäfRƲ|Ú¨°U)«Qz–U­ôŸrDÈêëéÚÞž«VˆÃ-ç/—s¿ÆþN:/a¿ÕÍQ,SÀ±±½ƒ¢`Ù÷:s ´Àî]»Ÿ"v"dì»K%"fïqD€³²LãòûUÊiœ¼THÒÈ ÎK(êºdhõ¿Þ¦èzõ#ie~Dæ¿&î†FUtø0¨f¢uozCr—‹Oyç£*ů©n- endstream endobj 677 0 obj <> stream xÚW XçÖžœŒJ±¶LZÌÄ¥uGܵ.umQkµBŠhÙd5d !@’²±/Ê&¨TVW°*®ím­]èíS»JkµÚ{«vñ ýxîs¿õ–ÿ·ÿ“g&“™oÎ9ïùÎy¿÷“0..ŒD"yü¥ k7¬ñŸ´l¯ïRÿiÞŽ{³–óßöVŸeDO‰8r¨Šî.#Fâ7Âq– §gææãŽóDzz2þ ÆE"ávj,ÞÞ3¼¼½§/‹‹OQE†G¨•ãC&(§Í›7g²rº·÷<å’˜PUdHp¬rM°:"4&XMÿD+}ãB"CÕ)Êñ "Ôêø¦NMNNö ŽIðŠS…/š0Y™©ŽP®MU%…nS¾«V¾ª|¶×ƒ‹eq1ñ‰êP•rMܶPU,u˜3Íe‰ËËÌJæ•AëßAÁ\´‹Š¥˜'˜'w†gžbF3c˜±ÌsÌóÌxf"3…ñb¦2Ó˜™Ì,f6³”YÆ,gV0/1/3>ÔÊ*f ó*³–YÇ¼Æø2~ÌëÌf#ãÏ01šÉÉ׃R}- ”~à²È¥ið Á‘ƒdyöökÙ<™™›ÅepY3äøÐ‰C+†É†©\—¹Öºþã1ÇêÝ·—Ý:†^óøðÇ#?=bÙˆó¢ÞíáP-Jºï §¤=p =£‡´·»÷Yþ-]ÅVEš•!„È¢ì»+±mE¥Íy¦ïߣÕyÿ%ëæM–ál¾ÕV× x J­ÚüýJ{¿pû¤C`thBœÊcÐwõr`—"Ûa2Ö+ޱ׋×/òÑ­ô¢`‰Ýç=m¡Ñ”GgÏ 5À˜ù är=/àÓ¸øÃè¡€ßVûÕ±†KpžÃ™dLé*2ÒgB¶rlÙ&£#8¨FùMñEšö÷p¨´Ëùì4ÐC §r&Žfû/ö9óõÛYc¥ýPkFQ„,Ža[4%aŠ¥ìNHƒL5Gžè[ÀãLì,l´Vr&r‹uâ§ÇÜ–|ƒOá34)^çÑŸí4Õ6ÔC] @Ù¨]9!¹(Û\klPÔÓ|–ÕÕµ7Up¼8Zˆ†— C¾ÐÛô6dƒ!7';]­Ž—}‰08g}ÿÎF¹ß?É… ò´œ[ï ð©qe•DŒíø´£±tš¹l2ÄBÚ›$¼ïŽ<7ƒF.¿Ê-ình„²Cí(•ã¶iRI„=ùxœaËöBƒtÞrK¹>F|ž/?VÚVЙXk Ô·H“œÄ°=˜Ýá=’ë8 »P¢Ð»ŠÏÔ„ }·îW_ûw|¥W €£ˆPf»QÝu®pèC"!XA¦“<†ãY;rú)„%OƒJ yŸÇl|BÖŒ~¬R(¸õúfÝKîHÞÅñÒ^wÃè,yŠˆ]EFÑR^€ NÄ gèÏ\átF4$Úr5k«Õd©¢HM£%Û¼®æÕ²…ô =A†-1à“„Å<á*t•|z¼Àj°ÐŒ6C¸Çn,þŽc®’EýU|ýø"㾟,þ‘¸–¬¢–ôýÆ‹{Ð]†Ñ…Ä‹¸Á2†DR <Ðð¶ÜÄU÷¨aZ!Z¤H+؇¥F*pÍÛìøB¸æZ8!8‰®o$ët~Ãé\œì¬Ó2Ù 5lWlÃFPÁXcŠÑQ Y?£ò6Ý–ü Ça¦I{ÇSO}¡VA‚Ùl!SX.˱æÙßwV›ã““æˆÛï7ôr¦pMÇᤋ~”úŒfZVK~áî»r“ÕdÓZc*–TÒñ»G“g‰Š>M¤˜.ü·î«åÜð¨îU%¹á@˜ÝûŒ“ØýÙÙ;åŒßMüîˆWÝOÇ^<"{Ôp¼í_(«5î R¸ýêôq‡‹8\*žÆ/ù$ÿ°©Ùœ‘Õ¶lý9©‹¸ãGòÔÃQÜÜæœÖÄ2“¬xóq"­[‡i“ï~³šè·vEw¼,/ª;ƒžözÎÔW椇/ÞrF9‡Uʺµ¿^$¡á¹ÞÑ|Ò¡Gz=ÚyI†ûúT‡€*ðøq åxçÊÖWc”¹õ®§Ý _`™£Ça¥£×´XÍãd§Ýü€Vè¤ —ˆ—@ÌÌ1ºŠçy|ºtí ÍjòŒ@ܰŒ&¢D¬ý…6Ôjm„kÅ5|¢uM-%Ñ«Wó›çàdÆÛi&£l`5›ËË¿“çPJ7CѤ*]Þ¼ÎêÜt25‰¬`ykОäS;³®¤œË¨É­I.ʪN‚PnÊ,ývÅXÚp<³Äy”êsõú´´™rå7ÊÂI¿†[ —“ÎêÉ7/ãTÊ.s¿Wëd6ñ$ÁG…tˆßò}-à‰-²ct¸þpûêþÔ1]ÎddËë`ŸÂ­×’Ø#Þë/4<…žÒÞ™*ó¾äè›#›@ÉÄpÑQˆsÖáL Ƕâ“ÈâÒ&ŒQ¸‰5šn¼ó¤‘Òý|jP܆ñ8L6(6A@žO\’6WÐÙ^3e›r¬¹vÚHfú9züdÍ߀;S±}!‹ å2nŹ%ß MðYQçG\²ìÏZ‡xþÎ{M}p|K›þ‰‚}Ÿ‰.i¨÷kÝ\E'Ð×ÓpÃDaëà[ ÀÔÞpŠª#ýNž\OÖ ó H›Å™ýùÒ’µÀÝ©‹—Àdâ"ƒj¯¦ŒºJÓ\Áo®HZ ƒNòPœ×a(å̆¢,EÀ¬¬Ô´M[ç7î¼ÿ•õÛ»Â%hØÕS¢É§ä[ù…&K~AÑ9ŠžêÔ‚Àš˜¢”>&x­ ËÈ =‹q’Ðï˜.7í+7™ h8ê_§ QÌû8§æK–m>`¦†¶ñ{#Èëø†pŽ–íàÂʲšªGÏÏyHml²j—Ú Üópã³Ïà&ºû¡!«&‰:, §t¡g7N·¡T*.Ãí|í^Óqä×ö dæ‚id2™{k>NÚà¼õƒƒ5Åv3”€]¿ßX×h4iÁ‘ MÖ:ÿµº( ƒ!óšþ}ÎÔś߭úì;øÊ_3/¤ôx­_ã²n‡–bœø‚}(ýQÂÖáKTÊVi«vÚ³Íëíiµ%QÂ-&®©d¢0ÿ/Å'%dk7AIG7®í–88Í|WŠ›nðáTƒ¥—äYRË¡ì¦|“­sÇE¨îΜ'À…Äfmq%4ÃaÅ`7˜+°ÚìXrë EyuŸÑªÞÔ¸Ñò&pÁdú^Hq@Ûöø0ع°Ó¶½:>-gc ¬†èòïÅžßqÙØ ÜEôÞtá&Ï y8”_¡o;{ÖÜþñÇæP??ý¶Â’Ìu$=܇°¢„;¡–º@sçÚ_ïÐÂXà¨H=^áÙrø9Å8z)=Ž3RÕñè.p²áÙwŸ>Q¤öW}¶nX@ÍϪº#iSyHïö®æû[,ª(£Uqš=Õô“¶­Fþ50óKŽåÀaæ/ûòÁàÞ{T—û!-tÒÞΰ–ƒßöð•»~šm† ›·G«“£tiœñ¤gä}«.ÿçï¶½}¢8iƒçùèA†‘ÞѰùÅŒøÿßë_fWì¤aÁñ4¶ñ4¶în”VI¾Ç§¤K™éÚ˜iú7NdÑNdsÕ2M%ž(ªˆ}¾åÍ…p NWTZ/ì†=`6Øsªs« 6-%£1'G“Ÿ \BZåŽyÔ¼+ÊÿÜÈ¢×€™dÉVF¬_î›SÖ¥ÀÙýGÎvk•)/Äüªh€O ó*·cÀ‚é&êûÛXR/úJÅq*o-sˆnŸ ÒIl0hÒ´qãÉYùx<««ÖÕ‚G›¦‚8Šƒ5‡õ –—7Ânà>uP%’æ´Z×»ZÚ".åõû¸ 2õém!Þiëgc—<§FWDùY éjmÚ²$‚ ™-ò¬&MñVà’é&2 ôq¿÷¹ËKƒêa/•-l'”ªý¦…ÎÄi“In[ŒL/ÝTnÝy¸Ù£PTRÔÄ=DV'nâÌâñ9|©¨Ä±Çñ¨I¦èÞdS ÒÓrsWÍLUÏBFžZ­1©ÛÂf$B¢:º%ÊÆIÄGN¦“9º¼\ÈöH¬¡{£ìAÈ7×ìAwù]2¶,¹„®Çزjº²@AžEWȹ%Öˆ›+1®†%[KdŠ¡.sª\‡Ø]‡š\‡ÝŠžÃL®nèYìú˜8Èýß}8pu endstream endobj 679 0 obj <> stream xÚ=”{TTׯÏe^2‚V¯Á•dîh(AEƒ Ñ‘‡"P¤øX†) £ã bTT‚KØ€D¬b%¨1¾ðE#ByX¨²*†%¦i´Mº/9ãJq­þ³ïº÷ìýíßùö¹‡#r9á8Î50&":>q~päÚµ‹ü&¿¼CË~ÖO+¤7ˆô&'½å$idÒëò·á|¦MF™‹dtêdœÏ‚*ê7DÎqüö] Óùúètï›·äYLiéV­—a®vÑ’%~ÞÚwuº%ÚÀ,£ÅdHÎÖF&[ÓYÉVö²Y»Öl0­yZ¯€t«u‹ÿÂ…¹¹¹>ÉYÛ|Ì–´ås½µ¹&kº6Ö¸ÍhÙnLÕ®2g[µQÉYFí+hŸW`sÖ–«Ñ¢4§-ÙŒÓ͇èÈb.”DpÑ$–¬#ÉÄ@ŒN&’ÍY¸ïF¦Ì$^Ä›, ‹ˆ/ñ#A$„¬"¡d5 'kH4YKâXåL'Â9KÒÂÍâ¶suœÍÉÙ)Á©ÄéGÙ YµlX^*?/¢˜¯ˆUÜP<—ºb% sßËpù°°té°ÒUÊøÀ&uظ‹ƒX8(“‚qX€–âŸR¦ …Õl„Pˆ1dEd®Þ¿ æ@p™ï…å—ßïÙ~Ú¡­á\Ïùû Á·ŒÑõ1:±–`hsÑ$ÀxOÇh)s?¢xMfZ?âXÉlGë6ÜÆÕÛq©]†’Nˆ®ÛTš|ÈûO<Ñ)çláõýMû ‘ÿ}0ìÑ îhâ…üÕî-Íû®³ëÈ­~ E„[æ†U§òË–üewéú£ÐÈ·t@¥¦ .åžÞÅN^nA+:ªÿï…$èée`|VlXaíe Úõt@µì´±Gs¹s›Odt—‚ŽaÆñÚãJšô±Jã"Ï3««]JÔ¯Ù\_»[®VQOÁ{3þf…D endstream endobj 681 0 obj <> stream xÚE’}LSWÆÏímo¯0nD˜´ * ˆHÅR(  ¢‘Aœ|X+Œ!"º1ìÁ9ŽÈ†4?@ a¡ˆÂDM?—eq›{O=Åí2³ìŸçä=É“çù½y$•"†aÑëã#×x‡éãâùMþèéái6³Œx òCfJˆ'K¦Kg"ĸ;‹Šèk“:6mR½E‘]”aøÜ=X­ö÷Q«ý²sòÛÒMªù) T‹‚‚ªüÔê Uh¦Á˜‘’œ¥Ò'›Ò ™É&qØ¡ŠËNÉ0˜òUóCÒM¦œ`_ß¼¼<ŸäÌ]>ÙÆmË,Tåe˜ÒUk » Æ\Cª*<;ˤŠNÎ4¨^•öyõ„egæì6Œ*}vªÁ˜%¶:ŸYˆÔl(Ò p¤GkQöæÙ#·ð¯ië#M×°ßeÛº…(âÑGÃåE¸È\„ywâäãG=ƒ=Ý×ð#ØeϨ›'E8^“ãSŸ‚VÕýÕÐ6ˆùÑvm€oÈ]£àÿŇF+]eàå(;N*„ºë]M½˜ÿ¶5K§ÄÚÄøuE%樒b33 ÿ½Î?>xSt˜2‡Ô'þ¸/Ö­Ço¬ Mäœ2öô¹'ô->Õßx¡ßàGƒ{¼<—`M’A̱y` èÚ‰ s’Œ³„µéŽ~2¡“ r· Iç¸Aš$çèU›DGú·Œà¶xÜNFÚ™‡÷‰û}ö¡èšÐÁQ9,wð†µ°Î?¢¤¡./9¸?§rA#);‡ Jù^LnµByó`”%™pS°ÒoàòJ\i®»‡vÛC&´£pSÌ{€-¶Y5ÌÓarh˜ƒH¹ Ý0™(㎭†Åöóø[Ü™Q"ÚêÛ|™ýå°MG9Žr´kU¥Î.NœaæJ¿ØÛ°÷Bþ|¨à’ï Vh³Â±Ia‰·xfÀœîƒüoªŸé,OºoBwúAÍžöËF9ûrâ$À1˜%§ÎH­~Ýjê¢TØ|±…<ëc Ydq²É…1î?ŠéÝö'Qà69—‰óØ„|T<ïôb+,ø¼:˜æØ,^¸´¿„÷ûxÆà-…›²Ë#Üšë[ª;0ßr1m¥òù–ƒ1¥1yZSjÞÈ'þÉóÜÿyÃi>mP¾Üœ‡wmÏËy?£tæ×¥jèeU—¸ç8ºµƒôÖ0d‰Vp‰ÔaMø(Œ7s%ëÁí@ÂÜB8ˆ¶Ç¦«woÜS’gâw?ÞQY®s+7Ÿù ×â˸ $¼"×Bb« ÁRmáhògrOi`ã”#ŽeŽS­CS¯”;:ut‚ךN“C endstream endobj 682 0 obj <> stream xÚ]PÁj„0½ç+æ¸e)Fö$BÕ v[Ö](½Åd´š„þ}“({è!ÛÉ{7“TmÝ*é ù´šwè`JXœõb9B£T$Í@Hîö.V>1C’êÂÌ•MIW~5õ±ºÜRúú¸7é㾄lïÛº[g‡S« yN’›7œ]áð&t/aöaZ©F8<ª.NºÅ˜_œP9 ¤(¢]ºEâZàlGËÔˆ$§´€¼i ‚Jüû;mŠ~à?Ìzfê™YFÏ…ÇeP•^ìñû†OÑcg·°ösk¾XëóÄÛÄMC(©ðy>£MPÅ÷¹úqí endstream endobj 684 0 obj <> stream xÚ­ztSײöÂ:',N"“äÈ”ÐC¨5ôz3î ÷Š»-Ù’F’{¯ÂrA6¶qì€M‡@Jè5$´›$d³¼· Ü]^þ»î{^^g-Kûì™ùfæ›™½-¢z÷¦D"Qÿµó¶lZ¸`ìük&N>˜êˆõ/•í±füωxy/ÞJÌ¿ÛûŠU ž¢äIýãmáù!yŒÙeAID" 3 "&y³g ý¦í&L?a¤ù>¾¡þÛ]Ý­F9޶š8cÆ´qV“&L˜a5×ËÙ»£½·Õ û@7g/û@ò‡§ÕZÇíΡV£fºú~úñÇÁÁÁãí½Æûø»~>zœUðö@7«5ÎÎþ;œ¬úxZ­´÷r¶êT~|çs¾—oP ³¿Õ 'go¢n_Õ›ê+J}{5W¶µ—ÝàòE¢H%êCyQÞ¢¾T0ES õÕ‡êGõ§Ì©ÔÛÔ@Ê‚’Rƒ(–z‡z—’Q–Ô`ê=ê}Š£†RèáÔ‡Ôj$5ŠM¡ÆR㨨ñÔÇÔj"5‰šLM¡¦RŸPÓ¨éÔ êSj&µúœšKÍ£æS ¨/¨…Ô"j1µ„ZJ-£–S+¨•Ô*êKj5µ†ZK­£ÖS¨Ô&j3µ…ÚJ©© ½(ÁˆUÔw¢Œ^Ó{}+>Ú{•Ù03?³6ÉhI ä äœä =–.§Ÿ0ÎoÑoÙô±ècìûVßœ~ú¹ô;ÞŸî¯2Ë\mþl€Ë€ïÞÈ \;°Îb“ÅnééÑAï Šfç°/ßÙÿî¨w eæ²C–Qƒ{ ¶¼{ð™÷,ßk~ÁûUÌøÀÈõåþ”‡ËÏYM¶úzH¯!-Cç-6uXÃð¡Ã¯~È}õá/# F®ygÔôQ+x•yû%¸ÒN‰šÛwˆù•í+Ùølur„:!> ?øóSYB,¨AÃÄ¥@×¾T’—irЂ.!é°â±ÈÐQkÖQ#1oçùõ½"j¬8kDŒg+ÄÆ_‡¢Ö~Ðâç[ЃMF‰9L¼™ %D/ÚKÛ£Äü:~8‹hîƒɽ¯š÷szÈ…ÜøèÄÐ(ðgó‚Ë*r‹JjÜv¯å¾[ç„DïڵɾÀŒÃÌFLɱd¦çu|•¶QÀbΓ®ÒÒÔµý†›èÅ Ø/GW‘Ëëïë´Íºòúf¨'ßï çª3k丽`‘ýøVã7Ü(Ñ£¡ÃÔÁQàJ­Y¬* b!šÁ4mηvZà¹Ñ÷j ÄŠå—¶I¢ÛÄŒ¦Ô(9Þù?ë‹il®!?`)½­Ö¨!’€×™IžÜ­ÿšÛ51Ej¥„3î¥Q…;wæí:±®qîxÜwqÿ†±¯TD‰EŠN]Û¤y)Qïï^äÿ¢]•fÒ›‰ Ñ&êÂo(ÿ­¸qýÿX½¤Ûè§?ÔàJ :¡ÌÇIÁ”^À˜ó*^^¼µyaQ…ú. é_è#þ.{2`¿[¨¯Ÿ_¾o W9))ZVK‚O‘‰rðˆŸ¿|Et4ÉnŸœ˜œyû êá ïüg/š·™ø÷L(Ï j¼½ç4zψN–‹Û—£þ¬jæ2wX[<ö4ª?Ût½®­¸úž–1Ñ.êõ¥bšÖ·ßpOºÉâ/‡˜„xjÝ›Ev¢r±}`‹èÃ'Ï^6¦)üö‚s× áÀ>e~õ¤ cd6Ûü|a=3åÖò'Ü÷pbomÕ¹U'¿‚+pú˜î.ÓáŒXߪã`bîÔWVŸ„aj–|:%À±ûŒ5Xçzí]QèS³±ÖeÙšñ>ÀL||X7w×neÌÑ®WøÞí„–Gÿ1´æ¼ ë‹_®-=9.Fwp< zÐ…åãÈ­ô y{Ð<4 ÌÎè™ÔD½’‹‰‹¾ÄÒM¸W4Ã4˜•‰ûÁf'ñ€»K3€IIÒ§Ê_ïÂÉæHÏÂ5ê¿™­B¦~Œ21Q)¨ Cu Oì x¶ ^€ßÆQ]Ê*“S¸ ¸ö’¶ ^YH wHjL/FûëQS‘ˆ7«ó¡0UJr ¡¨("‚«’ä@ap0„Dr¸ WÑ‘!\9rDþ’DBHQæpP¼¾Ðbè[€ÚjÙ3 ޝð̃¬”Œ4N¦Õj"å°Ìg¥­µRI-±ˬë×M6Zu\”‰ Ĩ­bã‚Õ4Ù^ˆî¾£u‡ØŠ€oï€oï’€ŠŠ’’ ¾ª £ü»b~i»5›œ-àÏdƦ+¸HHŒQÅàü5O–%€Ä(Òc3¹HÊÐgydh—Du·QÚm1o‡.²p#á†Û¥m?Ïȳ‡U0ÏÏa¼Ç„YðÌIšØ0{遼Àa¸R¼ï§ÊsÉ×à:ƒ]ñEÖ ¾4†þ¬8 Ié;mi‡ QßËéF¨‚¶ÐÂQka6,‡9°H±,bÜ/db«5í#®õ½$FÍíƒØÐr+–M`<é"²Uk)Ó‘K»ª¢'rž’jýP_ÿT2ñ 'ª2kåÂ6WÑï¿ÿj²8ø;²}ào$ÐK¯²/ž£ ˆ;yžZ"ÉÄØ›ÍýxÒÚƒ Ï¯Îj( -uãâ„ÐÐìüæpíq`ìýt†>Û½OR¾ L+ \`l­°9ÌÕkÕ¶„À®ð)濹*:jü願÷å_°é338Q‚ÍAXHzAwì@ºK}^úéì¬Ô”kM t”(ÂgbQûDüž;–Ç:›¦&ØŸÁµÐpD$ípÒΜ»û¾îŠQôí1”O¬>¸•î <(}Œ¦ñÛØm»wC>sê›Æ ÏlœÏÁ§­«ÜCû]íVR‘N:6aä§sÇsª³i´ÎŒ®õ7†1Ò竽§®…QÌg‹Gf?ÝþƒƒÅ~çÆâðŒeõÌH{ ˜UÒì+-çÎÙ8cêü¯osp¼òÌ÷Í]úÔ<¼³“.¸aéCätŸŽ]`=h5lÛj. Öë|w3ûÒ*òM¹Aá^±N‹;|XdŽÞGÄ È€é³“¸u°%ÔÎÆÁ&Ðæ0xà£QoNúÇ)hhÜyœÁoΆÃ6ð<Z Aà«æâÚ²ƒ{²«‰Cª¶çÛdy$-‡mÌôíc&süŠ|º)–7ÿWŽÅ×zÿ+ïv2>š#¼iq÷EˆAúë›_–> 鳤#žµln|ÜëÒùÝ ÄT¨/­U’‰ÿµÚTm¦.-U¨MȲ¯mÿHÜ>Ý`s{ÊRÇÏ’î2”+çÂØî‚!ïø‡$¢§@™·Ç’üßlâ—‰*ÛçŠù¡íËÙ„luj8„ƒJ™‰;~’…nrŒX¯!d»S»WWcjUW }Úfc©ôÚ ­® ½+C 9„?"í­-½Ö‚/éëjôçaÏÞ&M#YJ¯‚ÈTEƒ |™ð53D§MD6ª3Y ùmtüñ¼§„›ýù^,ÒÐUºÔf½-y\ýɆe[¦a±üA,û¸ðܸÄüðñ-ü×Ñ˳DrU§p•w”ÐÒß q}ÎxòïKåý{ÿÃ3.cq³_gñ@‰µ:µJŽJÑ—ô“Æñ‹lœ1œ àdjÿÈdqô9ïQM ã£è';¢OðD´MûÉ“©Qœ@©‰‰Ãìf`0+ñ¦Ý¨EN<ÚŠ6î>Å!Ü›P„Gè"A•Lè‹å(†Î‡T—‰„(7Ï•¹Ôl:8é#¼ OÅ“±‘Ÿ¦v‘I„¸»¼ô©¸º}6ëYB÷˜ÔcP/ š‰84 }‰Öà÷ÐD<[ŽýiÅvZÄïéBê©äk8Ô²`ï—éSa`qÈ*×-Á¾kV dÒ>“}Ò„ªv‹Ðû÷Ð#kÔÅèýklK’F”IŠ˜?8Ï!í¿e7dE÷éÇ™ŸÈ¨À_2Uá9†›ˆâ%]îa%¤w+[—‡ådŠõAAf'{|bÞnE„6›PS—ÐuF4Ì(毷Ïd;š^9®¸ÇJRº¯A]è!ñâNƒìj9ÒÜ¥Îè=-Æ},7¥t‹î'AcÀ¸6sD´y»1È[„üMü‡îüäž[µ4‚¿šÍªw$ìŸi¹r4®KJþ†#Ý·fÚËñp%Ýw%}_¯p‘/£¥Í¸7–Æú,Å[ªQ ñíæª“Üð`bù·®õ¨\xl%þOÂöØMÁ“ѹ4â"Ü(Ý}‚éʵ¯Mh·©ŒÖ{b¾ÆÖè2¯r%&‰›j.8;Ï7¢Nwà(ÜŠ¢è¿Yñ:Dx—`ÏžË}Oý¹P¬Q.jŹ·ÂýÙ~ïߣ A}æu®T6œfv +¥¯ë»…©39?a«ë°§îzçV~ôL•°Ÿd8Žzó;L¢Ô¾+FGÐ(öãÍk7pJX®Ç™Ö¬]¥5>E>AÛ#mç^XuOþ .žÏ¼¬M#´¶›á¿¤rà4q­ÚYcm?œ‰ðúˆr#±TðZS~8?E‹ÑÜ´´C-7µ–&ÚOå¾®k`»0JÕkR!Âcbââqn•¡ ÿ çÓ¤…ë…–àâ”Øô(ˆ¶ôr‚`ÂnÕ»Uïéd7z=ìHòÚGœlFœìXÄs]Nþ^w”ÉúKFâx03ºrŠßEŸ¸*“ÄU5œf½Y%¾@bþrT·éVå|ÉM1R¶fc * Mžõ*T´/XÓÐUUP FÐá¹LÎ×hi¤ü³WrTrlXf‚>-)iÚûË´$=Æ×êÏB]Ý·PûÚx¾¤8'eÁÜår~F¹E´Obc³4Ú¢Òçž’\(Òäjvª´a: ÿFµ|:9A«IRòã:ËÒ£µšT`r µPΠˠù9 7͵»ûý¬}å³iaæ.mŸV*"©nû\ÜÈ%̽/Âá)Ødáx<-DKÑX4Ùpø{ü#;þå ,4âìíа8à¦},ï"É=¥è´ÀÇ÷Pós1 FçX4K‚ú!êæÓ_Fýˆ?ãÿTtþ&rT(ŸE;»¸ùžM†![¬Sx²ÌxÃósF4ÀÀW-Ž>Eã hdÃó§þ&éQèr»¾÷¾(ŒAÙÈêæÃÇèý©8ƒYÑxÈYAG=~ Ì&O;9øf‡hÕ ú8ƒÝâ‘HÆŽMqM¹ÅUuòÃ`°Ï\Í4„°¨Ï¡ïÑ @c™AÈ%<µ”3AuJE:#ýK‘;.çãGÀ<+D–-©Ç™9b”ëí½ìÀüwœ!qd X2 VR¹¹»HƒÌf?ÿ¹”4_‰_ ;!Ë ÏÐU@0÷QïDüá€Oñ(ùÓ(öqɵSpùKîà‘þö xÖè/`¼ÐY z21Ñ´ôÏTŽ­é0ˆÏ$V—š Z½¾êiû×{¤“ëÆ/¨—\zž.¹5­ˆàîBâÅhn­¨ÆˆÒî¡4£¸}¼pÎŒ$!8ˆL9hjn P êâDP@ C€Ý‘C9Ga¨{MMÏ;‡:Gz(ä천8)§ )SW…$L ×=Oí,ª±­w»È¬Ý$Y8‹‡Žùlœ5îcDk8~àß2kA &¯sˆ†ûò‘D_éPÏ ‹tì²ÛU³U½Ým«ÎõUv R‹Û‡˜D…í[Åí"þ›S[VqV82óT;jü¼Vëü„Å­šb?B‚q*¥Z‰—uìáµ¼N™CŠ‰Î²â…ÍU Áy«]׿ßãrœQDÇKYjH²*òA—œœÃ˜¿Ìê’Wð2@ür‘WploFy^jO—÷².yßjŠÜ!”ª8"oL‡ƒ Oá£4IêH¶ÜuJ;å-" Øé„õÇ ²\ _Ȱ¼c.žÊ+Èš ú7®½ I Y.Ⱥ£]¦ÕÇd1#5)Íà“eèÓŽ”®-»>e^ñoIû1?‚‡E m†ÊÝ•÷„j褱Vû;nÇ®jh"(ŨÕñ ,Á³d˜EëÕú„4H²$)š¿WÀÕM5œ=Wh]È…ô(Œ/ôA˱I†§ã„È`¯m#À’4ôÚF]Uí‘Τ¤·iÃÊH”¥ë“R3ÑPä"C“pœ.QŸ*Kˆ ³F†jýEØÓØ5„ÐaGòÓkíÑ»bþþ[{êDR%tû×׳ۿ y!ÁrP(£•x.–á%è«ø âÞdËbcÒþNç“ý6­=Y^@Ÿ…4EžrÁ?ÉðÆ72I ý¹*£NŽÖ 'fX_ÿr\½õ©£4¬gëǼ÷¸ðW-.s/† Öà" ÂÍA¨ß%á!ý ùµliX™+ ‘1J¥F-\70jÈI’Ceêw§¿Îê>½LHJPLŸû¬*±Ù[]PV*œ.ÿg/þ“ª}‰ª“ÛcYüãã¿ÆqDH„sÚU¿ëT’'Cæª$1\a3!Céý‰› W·>DÓÎ]4J½¡»WØ$Ç2ûf`ŠOåÜ”õ_K¯öW*Ü÷'sÈš&Ä\çZëT·9o+ésZ/ñ* +-/("sbVBÕ6mYõLâåÇœ&É]héÞC›T_¨–{ÍÙî¿l™OûŸæˆ”6hª/lfâÑtv$=nþv›-Õ98ÒxÍHø[aPóà ȥÑâÅ9”w[æðýYtžÆÃfžôù´ø-òŽGFZ«MË)kf¤r7_"lÚ÷·_‹¤£Ÿ` iÌgux(£Çy,r  7h3óêŽI+ýPãWâ\ê _à¢^åm³ÃÓÙ}=Ø€kI@md1è¡€hò¥ÂˆªÖ-vßFF §Šo!oM»ÕxˆK‡ÓšjW•Ò ¢¿‚àòÒ¢ü]gg×}Ž~Lš€·9éïxГQ¤·\‰úedĀЋu¢Zé=~i´ ™ù “÷¢©òN‹ƒyËN‹‰¨¼sd¬yû»„F#3ÍLôq©äÒüoÿl?ö¤½kìJ× —8CGcK…«ÏÀþÝÆJ÷Æö4„‚ZæµÕ&ÈN0®4`_ƒê4@­îdÅþbÓžªÃP &›Ì0PCh·Ñ^ÅhžÁ¢ü6ŠmëŽʉ̓ƒhd¾‰ 3ât ‚ÍJuœÛð‰›ÁqW`­×WÐ5Œ9:Þu×6åNšA„z·=üAŒæóóYÄÐ?~õÕ¾7ßeÖºTmøâ“ C8Lÿ?wPo¸›D—‘Ä$¤:v؉Ö¿³ÁN‹òÖàËhÞåêVÛãÒ?ÈÍa§ÀÓr(ÓVæÓ²v–×óŒ $—Æ#Â?.:ÐÇ‘€Ì8±;ó‹ê|T…À<:wîªjÃkýwÖì®I.X ôEb‚¢™°ì輌ÂÔùÑ•N$Im•ööUözÒ½_¸ðs9Øœ;¢"BÝÁ‘¶Sà™íl ^æaŽÌü'ë9êó[Ë5ª#[6•o(_ +Áì ^ë‘´ÃÄ»Ãñ9vÄ–CrhÚS»OÏœÜE½aêú›GË».1;ÃI„zCÎçĨ×¶¨jm‹®¬´U½ûõeÜrú· GÏœÎ\¿†Ã‘ô›Öm$â5»´–†»`ò¬‰Ìw/Z ÓÀvU˜3ƒžÿs` GiÄ­¨ÿ ‹Ë/¾h“>B_ð+Yl%¬ø&]IB×Ð#£R{XWR]Ý%cIbr\úk¿‡­ô/öñ òõó5ø™ÊÅ•„"c{CÞ|@美[_ÚFzQaçqÂÎWÓR°¢mb§.ãH=ôËÎM*Ê2¦4´ÈÇ'4ØoãQŸc—¿>ó€$fûø7æñ%]áè×(zÑ&~ñ °*Y»ê5õ¯{NŸ9ruHãZµ K !kʵ'tÅš a ó!,E‹d]B !“¤ '3ÒN·4ꊅZ쭊׺H¡j2Á‘Ñd–‚Íe|à¿ Ù."Ž·‰ÑíKÙæÀüÿù†µûθ1È`ÑäWz€Ì¹Y\Lÿobáÿ"f"˜›ióÀÚÎg#½ù;i#«¤ºŒîº…­»tÿÿ…âoV¨G‰«¯”Øß­„Jaä'D„wÝóÈEƒF¾ÀýñÀ1XD(ým,©ýýI9쇭Y;°-ömòß§ êàpɾ²¦æâzØ{ƒJíJí`58ƒ+¬² ²±õÞ,\´â &Ò€ð–þÆîj÷˜T»~l[w\HUÚÊ¥7;ÜzLÚ­mÕ•–µtØ]¦Ï¤ÓéäðÆõW^—À1Opo¹ôñ,°· "%0—EtEËŠ`.žšŒÍpÿ/¦Í•;‚s‘o)xZ Ã_Ò­Í#i6º*ÑMþíS,^ô?KçÑÎ̤£ÊN&0åÐ1ø<ðñÄÅÏCÃ^C£Gž,BƒG¨OP@T¤‡¯50óVÞ#•¢ïùÛ—n4NÙ@¯Çë/Ú^Ü•^EŸ¡ïYÔ‹ÆòW/Ýÿ:ÞÄøãé'÷®wG Ó¨4ÁÑàÇøG ŒY••žvœôêçúÒûõ;WÔ¯?×§÷´¢~o¡»ƒþæòµ endstream endobj 685 0 obj <> stream xÚ]Mk„0†ïùsÜRŠQ[é‚[E°°mYÝÃö¦Éh5 QþûšDöÐC†g&ï|ðyUTRÌ|Åjœ¡’œÔbB‡ƒ$Œ€ 6ll5 òs«?Ú!h¾oÍûå1?×·>]›2L€cï%ͪ¢=¯Šzf+Ù+HS\¶‰ÓlV8œ¸êðÁÖ> G#ä‡k^»J½hý‹#Ê(É27.ô71ÅqÒ-CÓÊIJiiYf%ÿ÷—øŽ®g?­Ù”ŦŒhQd$“i¿nœD¶Ó“åØó›ågÏNóâùèöìíFëÍݶ³Ýì tnØÃ…Ä»ÇZiÛåÞVSyh endstream endobj 687 0 obj <> stream xÚuV p×ÞµlimÀ rŽ•iÚp„ÙЉL9s†‚S!d[X–lI>±-Y’uý’¬ûðep€Ø ’Ô¹iH›„mšNzd(43™É´oå'Ó>Ù»éhõöíÛ÷ßßÿ½¥©ôtЦéì’Ò}%w>¹vË®}ù’ÔJ¡ênÉØw‰î NBqù4WÆ-ãqóÒÙ¯7¦ÿ{fÚc•V<;5f?@Fúöƒd¤ž ìÁ‡¨œ4ЦfQó¨Ç©¥ÔJjµ•úuˆ*§´T e¥œT„ê§©‹ÔkÔuê#ê úyz }@ªÕÉ5 mUµTW)ShdJy²N;9“©kš4:¼\)oÔÖÖÊuJ¹V+¯­“*+4r)œ˜K5uƒFQQ©›˜Q7¨ªr…J¡k’+åÕr•N%¯êj•V)ÕVÖ©õrVJ”*ˆq•N!U’55"µrYj§R]¡I•jM¹R­Ö(å庉Ʉ™\¡T¨*R‹÷¦Ëé‘”ˆD²,O")X›ò=µœ»P¶(7ÕªKr $’U¹kªI¼2©*w ‰XNÂN åîRËr]SîÂÂJ®æ™¥Kò¤ÕÚ<µ¦â¹EKrºÊÜr­\S/?’»A­Òån•VËs'k—7y[«®®©#1änQ‘kT¤B³I­h†Tå!j=ŸT&Ÿ~šZ™Všvˆ:œq”RQ5¤€§¨3´•¶ÑvÚAí¤]´›î¤=´—öÑ~*L=Kè ¢Ãt„ŽÒ]ÔªŒ:HýŒî¦ØTÉÓ©EÔYº˜¾ž¶ ÍÏKãÕò¾H/Nÿ{Ææ {Æþ*þQÁQÁ“Íb¼Ì(ó¯Ì…™×²J²Z²®Ì˜ÏÙ²½¨9NÅ!^bjöôB__4‹“çùÍMÐÐÐ =b²)ã¶ôÑh×ÀãrР@ûõa»Ë9ííFƒÌ.{È€àƒ"LƒÁnsŽ!h ²~p¹Âa´í!–¹>‹rÂþ@H .è´y.¼ åﻆ6¡M"·+âñ:]àcB¦€ž5Õj00Ùœí•÷0q¢ö*æV Q8Y Ç ­ÍÝÆ´ ¢x)žsËè±»ÌÓÚÖÚ*†cAkЂ~ô¼³/3™¬Ð’Ói‹²>bxà8JÿRÔ‚ 3ê{-þp—ï8Û‚ Ñœ¼€Åe÷AN4Š¡ËèÑ{·½d‡Â_!ö†¨Ûïï„.¦«-ÒÊšÁšFœþŒˆägå@Ãôhj$/QŽÜB´/F‹ð&¼/ÄOâx3ZŒ‘@·¢…èI´‘Ÿ‰Ù¹h’ø<, ÂB”oBB<3ˆŸeð_ƒo ñR?ž‡2ÛÑjðÑ͹íx5áLœg" ‚챬Œ'nÅéÑxb8Î[—2ÅeHŠ-ØNJ"ÃaEeXŠ,ÈŽ  ³ÉíÉç„X‡‹ÑNd@FâÖvT‹t¨ïÄl$noǵ©êãÇâ(/ÎY Pâ'Ü­)œà~>.Âày¸ÿ±Xˆ~&Fýü©÷}|ò†‡2‘=Šøä·TŒ}ãÅÂûèâz§vÿ`+Æí›å îaÈã÷@x 0Z­öäU5›lf0ÑkŽvpWqD1»À L(‚VÀêmö'ûCÄy“ “×C‹8yŽßR?ìÿ1÷4ú\õz}€ Õ{Ì—FQ«ÏJjÍèM) ëý–…ëÇ Jöah0:LБcC¬› *âc¸³øàÿ17Ö’j¶Ñ±,^âSÒl%Қæ¶² ¦Íà`ôað³=@ß{âÛ·ÿ„2®„;Ý.ð¯ÃmwêÁ³®ÊQ¡-ìp7cÒƒ^ öÀæK/ôUŸ©|µŠ?ÆošÌh¯˜´ ÞKü™ôJsœ‡N$ž’å†hjbÇ ´çÕ§5Ç·^ÙLi§£ßüaã…Ššk%ám^¥Óⶤ’àô¹ý(ãã/PÚ`—ÇÐÃø!¤gm°Ý°óðQMMu‚!q†¸œ!z´Ÿ›÷[n^?ó “ÂÝê»”».ïêÝ Î\Ó^7 b$€¯¾ùÃχ[5£e£M×€A™Ÿ¡4ÁÄÃ1ÀJIé³Ì‹ áÅo~‡2€ùçç/zá™eâPv©>¦9¥Üú{fÃ/…‡×®y“ ówÿ·oo|ùñ[pY«¨9¡|·ÉNäÉâ$Lw‘Ç]þ/¢+ä‡ÑÃHpÍ'.H¦!·€OzìQ</Ç˹£ÕbT0í½„çÜÑ£‡™lÀÊØØ$ãbÎÊKd%V ýQ‚7ãë \¡[‡¹5¹{|\dj%X²1&Ÿ>†ÁíõE µ½Vã$q¤í£{Ç '~,ô„ˆ¸‡ š‚z¶ :ôVÃJ\#ÂoòW¢KÔhK1o{;Aؽ­È5þ¸ÈÓê1F ¡Î ƒ 8‰ ðI\±qO]4w(Îãl/ÛÜUlrÆÏs|ÇÜÔ3âp<ÉŸö~Èí~™´MÞ_cè0Quƒ¨Bè“{ªš§m­Ã»øMÐÔ×½½lv¢ÞC—^E ïÑ\%ú^w·z-N‡Óê´3í~ðtöÄXztNÆÞêt’£¡»Ë¸}å ÅdÜŽN3aÜÚU]h`G¨$Xá;›`›nOUþNÓÒA6§ÅχwÎNE.Dú?$ð= ï®/šÎA˜üBî=[î]^À,àï1V[âè7|³éÀRäL»}íÆ•ëÛ Í`&º¬>6±`Äßìn¸ ¿1]± ›o˜FàxûâЙwßèý¼Œ×ê´°°MeTu4¶+”•ÕP KÃû¼EÁ=ÐZh´¦XçÞì#ìÌ©R)ãÞžêH|W€ãUEllìy幸§4.¸¿%™&ÀKÐSÅh69(þ-`ScÜh|JãƒB´?õžMbY¸/`“<Áý »´­ú”½ ï_W|^JRWÃàqÁ´¥4~F|ä®ñ¸ï¸_ ½g !cÀÀ¶C‡ÙÜ‚õÉEXÏ27¥NYƒ1ň)ê‘+ùŽÈßìµ nŸ7…êíØ+"=ñsâá\ìvÅî±".“ð'ëoaï.TuZ‡ØiM„·úe©=\$˜`Òt‰Ñú{HLIÄÆVÇïÙH”N³±Ž_eµV‰‰ö¨Ÿ rL"˜&òƒ‘ ôâõü)õEw%üûB):uǸò“œ‚x¦¼ÁCç¸q!Ä_¼ŽhŸÇI¾T¼äl»${kÜ(€#P%;Z©’Ûë‡ÕJ€Ðî… ãëpE¨Ôm 9«`p©¤P5,¿Pýá9·³Š!H¶:7w–µ]³œcP¹®˜zª†êcª ÚÿÇç®À[Ì=¯*cœ"6é•g AV» ÓæI›Œ!öpkÄùƒˆW`(þòÙ3ç]ýÎI¿'­wî?g±…&­¯.ÁÐþó²Á A0FOxÿ¾u¤*²×mœôžxuÐßµo”›Çã~‚ë…„½Ú#?œÞ.pYÂøöX‘¨£Çækæ>Ô> stream xÚ]PMkÃ0 ½ûWèØ1Fœv ÕmÀ‡vn¡WÇVRÃbÇ9äß/vC;H §÷$=Œ¸5Нà”À±:à覠Zì%å´Qq­rVƒô¤`'éÏr@(nßìÈÅ+;ío%}»^šò4vÊeöÛµæ1n;UEŠŸeâà ›íZ|IØgÐŒíase"#bòþ´(©ë<®|ܤœÆÑK…AÚIEi UÓÔ­þ×[m§î2,Ìcbîé.sW4©’¿§=5…°ìÍOÈŽÒrcñù'ï|Råø··mn endstream endobj 690 0 obj <> stream xÚ•XiXWÖ®¶¡ªÜPi+BbºqET÷˜¸¢H¢hP„€¢ì»ˆ-›Ý}ºÙWEÙA@JÜи&N\Æè'‰KM41&z /™ùnCLÆ™y¾ï›T?Tݺ÷œ÷¼ç=甌13cd2™…ûŠN¬·`©£û$Óé+IÚP3Cg¢¹ô# •Io÷’”ri°ÙÛ #óD¯L×ÓõÁ@Óu,½XݳdÌd2>*¦Lpp˜¼ 8$6l“@„͘v6“fΜ1Þf²ƒÃL›ù[ýÂ6mô²Yêà·Õ;‚þ³ÅfeðÆM~±6cfDD„¼;qbttôï­á‚ÃüçØ·‰Þ`ãêîåçk³(8(Âf™÷V?›«'ôü,Þáf³4Ø×/,ˆZÛׂ™Ðw¾™3óã"_ÙËñæÍÃXú€À d1–Œ‚ÌÌÌÆŠ±fÞd†3#˜‘Ì(f43†ËØ3˜‰Œ3•™ÆLgÞa™ÌBƉYÄ83ïÓ]3.ÌRfó!³œYÁ¬dV1«™5Œãάe¦ôbdŒs›é”M—í‘ÝëåÞëòåÏÍ´f?›og{³qì .†ûŒÇÿµ÷€ÞËzÝ'¼Ï×} ú>ìçÝïEÿ]ýÿaácqw€Ë€ƒ“>ôΠӃžY-;«<}ðwÂ8Á <~#yÈIkñÒD|&ªÏ^ÆÁ{ë-Ÿ#ƒþôo Œâ„¦ÓC&”gB€Šüe‘š«13¶´´éjûIã8²0E¯=è¬_1Äö ûÕ_¾SVAIjYB\JHlä}«BëWU4ŸÜp™ôR¾Ž;—oò<ê QÀŽŒ ýU¶óÔ7ɳÝŸ¡ÿºËFÈÖ'ì7·j¾P–@¹vüG I[ 4iAãx ¼è »ƒrÜy[h ¨óò ðòª hi©«kQZH×IZÉ˕Ų˒«\2v.2ò! |ñ¶¼íÊ(HÝž²½kÀß'X¥î€ÐóÑ{4…ô Œ‚ÌÝ<}YS/}[/kÅÁƒƒåR%^ë1‰¤=I´c Û0“÷“’¤Qð‡•¥ 7OÂ/Ð×á“ì“ù®æ–ÃahŽÙ·¡è#3a%8$»mŸà²}+˜QJËpö•ã‹N¹P ¹¡J è 1yŽëH~ÑêbvtÎíã» ‰JÍM{ííÏá(EŠØp¦mpžÅa ¢ì,ŽÄEH²Ã5«N\²=Y“2¶Ñ@زbãÉ–ÖCÈ~uY„ïyäFü• #ýí—NZ~,¾¼¦©ô¸Nzï‰O¯*oÈ«þn›ó<,òsvZH<ˆ·UÂjX4+Í7ªi©A{4o¼Žo74ZC{ÒU¨Ä·é¯½‚0ø+þ*|Vrã,ÜåoͽHOê;{É{^Õ! ­5‡•ðñê¼]†ºG³«ÿ2mÉf$èÉ)>:>U¿S¯Û )¼¢K› {•GY”»FP…‚[úúƒ‡r** ™o ¬Þàâ>éñ‡( óŸ¾UÒ³¡#è.U݃1ÊDɉ‚|É¥è <ÇJ3ÙýºŒ`ʽ~G<ù¹ë+561Ss ißBKÓ=¨£åKß À"à%ón·/àPYÿ ´<‹o¾s 7ãpŠЏ‡€Ü¬‡dŒ2ÖhÕ[o¬*§ÎŸòÚï–¸lúíé8P©xSŸ|ƒªn+ñYý1XiŠŒ—á ªèBü^ØÇ²%-Y»ËÅÓõ`/ÔjË"üScC`+¿©,¸±±¼²á¢÷¥ad(™9d(/aVÎ{͋ĹŸ‡_¥Î¨~ø¾‰6£oЬVtERR{Ïå%—7iLÚ³­nÀ^;¾‡y¶£aþhS:jJ¤L$»,þ͇Vé¡›F¨ã‰Ä6c{zTº>G—˫ْe.²¹Ÿ¤ó2ï@=v6»jñ8b¶€¼dŒµÓÈÜ#f|ªlãàXÚ±,1çJɹºæîÔm‘îP·ï®¾‰E7WßUÜÂõR¸°-'¸jù«ßd5}uÜÇY ëB7m↠Wë«ÂÇüÏ­„%*§Yã”°a¯Ëí ¼âÁŒ6¸Â|ž2šq§ôšzç>öR23Äux2×Y¨‹C:¶ ;ëùöÛ\í\OÜVÂíS-uÅ=¶”à öz|nŠÃPš¨âÛ”-oâY!’ÇÄåñ›â|½<A,ø·ç§.„V¾6 ox¨Ÿó W”ã8é+Ì¡q¸˜Ov’ácÞ%oåóp zˆY Wy"÷ÆÃÍŸžÀ/Tç lMúÎüͰ6ñ.¡£f(-:;i&Œ¥ÅŲæÎýr)¨sª ©Üq »’’c‰¡ëG«”xmÒ\à£ÔlÕãêÆ3p˜&§› *0¤å DZ¿–°çÉhóñtUÚ÷4Uî¿J•GR €,©6'1¬Eç9z`k=‰–h‹Cð4'Ú*$¬–ú X„‹¹§{gyÌY¿t¬ Ù8™}Ÿœ‡[üwS¿ Ó”]‹ÔÈt=`¿F-ù²øîW÷Ÿ¨à‡iWHß~¹,lÅ5l1ˆPëuÈ›ÒPÃï2˜Œ¤Î^ÓˆÒKQví%m»¼3«s’°rb•‰ Ó%%°Üjéñ÷÷:SQ4{bG¼‰7Õ/;4Òð˜ã䊓 qªH}\2źÿ²Ñ0f”»]PŸÝq¾3iÈ\úô“Oïå¤t€ïç–EZŒAW|¥ÁX©²xiNÅý(£®•† ­m;Bד7 8\‹cé1›1„ŒE¬Su9ªYÔv=¤8šû¾ŒiwªsÏv† @d;Öz®wž²m-»(ªu"æž2m=§‰òNÜOÅ>’(ƒ'“¥Ô§ñX×Áþë5_%b­šŸè5V¹ sq<‹Ó ÒqéÏ‹ìL1ÿMfùKjS§%kñr¨Fô/A_Qê#Zš‹Ã×µ+â;‡ªC·f_»Uèñ…Èh§‚ïŠ °ºßH5ŽÍ)DZšƒ|#BãSaL«ZwÑ«#á| hVüñáö¦ã·ÿ/þ* ä^ãÇ rݨz2‘Ø’d=Ž"1O¥ˆ?ÏŒÇ/Ò¼zÿp‡ËñY‘õÑÚ‡‡ø˜Lb)Ô¬škN{mmO ÙT,Y΢ÓùÏ7ñ<ÅnH7vI‹âÈdBù0’âÿ–ÈnЬÛ0üL{1=a»ÊY¼üü÷×Çœ’~3ÉX Z $YªÔTh ¬I˜iõy"õú`m¸VG“‹3åÉYhR"Td1‰{•9`4fgµµY}ºîa -á8ó"š?U)nÊß½ã°ÚÝLãvûcÙ“)“(#:g¿Mc£H ­}9hž{G«ë6±W³§ÓPçÎÑËiì¥ÛŸs8rßË%,Íf‹—<Åá§bKªSòÎHé…ðß®?GÃ"[G[ :rF)M¥DãühNyyٽʃñ±F†Èp#º~½iý±jV‘TÒÉŠ²ò¡fò—§%"dŒÕiÅÆØ¼È…ètž~KÁŸîÁUÀ1¨Òy]+­ˆ“äiþƒÉ*{ðòôù]®ÙÔwüúŸŸaòo²Ìmé;+ÀºÒs3÷ £´Æ »Ö¼v— Ä™”ú­"~xíë-k°÷Zx§"«ˆ’úܶ€Ç/Êclq>”—%@‚j™  Œ§:ô`á'ÄΕXìš²¡.fuMÉ%¤7Ȭ1ä³Î{®jÕº…Z’•d?Æ~¦TD}bsé>' ã¹qÂÜ7Ö5u 8¹ðxš‰¦Ô éíz\ÑA03p°"7K£lãˆS’¹š»˜¾ª®Ç"×~Æ\ÑžÔ¾úeŽÝ³oh[mmÿˆŒ¢ èkƒÂ£ùLÒ!`:·¿îXU]c¤¿“ Ô°*Ô7ÈÇCNà{z§iÉNi’4Éè ãH »¤qBì6]$ò¯|¼KøÌÄy>Ôxbýh$”æÂ~T§ÜX{ü£ú5{Ñ=¦NI‘7‹ÓprËó¢½1ªŠ]jʶ¨õ®‹é’az´>¡:dfl4)9TÙÔ”_ØŒdˆ!€Žœ¿tÏÑR/£Ügà9ö–– ¿O¶l¡ÕØÖp¹[©§ÒÉ–Iÿ§öú<§B™¥‹×$Å@ ïUSy°¦¤ùˆël;ÂxóîyÕ£Çÿp­#š-k9ÑÆo!M÷ûNw/4˜®Â¸ÒÚ Wî߇÷==áý)*b±Sh ?¡« Ùq›$†ŠßspO‰1Ï KÕ%Ò *¬(¶²²h_yY\‡2ÔÚ ±ùÞ%ó©·#Wͦ¬ñ)ö©‰àLp@Êf:qƧ¯k LÐ:F ïÞ1ÕètûÜUšI—Þ¯]yàCT!Õ°!KÓ@§‡ÜôÝ™ÙüE²ZÀÞl5šÃRßÕä Òo][ÛùKP¨¢ ßù!£ÌgÑ Y9-Ø…ì€á¼±¡ñœî@÷ØïÇ¡ìnû¥Ú’¨¹JR¶Hͽþ8Ÿûuu£­r¸¯ˆØÈã÷ÿL(Ó÷Ÿv<@ËÛè@ú £xˆÒ8šëfÝEºgµ¡Ýxäà )JK9ÅÓ\éŠpÔ¿ÖûÕçƒ#õµGi8žõÄÚ­Cö9mÕv ’Çk™zœnvØ ëëÞl*¸ª²ìÌâ§ÄÒ*gÇžhÐò‰tžSª¹ƒÆ{†ŒúZ½éóFçÚô„=d6ú[áO ór²®€5Jm„†,6F˜„² Ò´ÙIÝß9h§Èñ&3": ÿjÃkŸN¸ž¯=O;üë-»ÁöîùS´Ó_IèFàßA¿×~±¶4zÎýÿxœÏ=so©t·µ¡Ñ'¦ùÁTpõ táwáÈ<“­Šöž™ˆðO¦Q(Zÿ7³þ?\XãêÎÓï³Z{Î’®SåSôˆB–éN#U|sâS2ƒ¼ã0ŠX“÷mñ=œuï)-c$›¸DAûž ZáDQí¾ÃGJÚáÙVP² VÑùn*†(ètaIÖˆ8¬^’ullúCÍï`þM€}CaaSóÉÌR௜YF,É0'·ÅªíT=Ok ÀûøÙf-Gwšú‚±?w«»Ã#2R5Öl‰ˆåÛÿ¤™ŸªËð¯¾sÒVŠcŽXeª%Ìs´ 0nÀo4çÈ»j¬ Ô×5i§¸uµ-~Rêõ±Û ˆ÷©‰®ªª)i:µºÊM©hu‚k#\¨¨®M©—Þª±l8â} wÐ ØEᣬÅy òÂ>åMhÊXeˆ7¤¾ê¨¾èi¨v|cB 27¿•Ð fˆ 6‡Ç54¤ÜÚNçêú”› °œŸ7"•à ôÆŽ–ÔÂTØþª‹’õtQY`„’Ý´/Ýfl < ÅÀWãÀÑ*h‰® 8@Ãî[˜9»€¼’Vˆ8·XöŒÆ£(& È~Îæ^äµÏ[ÏÞPžR»sÎáÁ+àr™«è(LFãJ5§·]7fŒ–÷çº ™ÿ)ÊÏ?Ù#-¾.ÌæÐé2¦h•(Ó–ü òJn¦ûÇ9ÚŠÓJ|ôÚ“íœÍÈ•Š˜J¸m·©‘Ïv•HEY¥tB.¥Iý„ÌÂô¬Ë¦)L¤ ó4F™2_•6IE›RÝ®DZÓ¬ˆ+ÍO‹ìfÝ$ÚÈ{MÝÛetõË+ ­‹uä¦å–ÐJ|­gÿŠÎSÿ×OÈ(HÏ>gÚ?B·U¢6FšöÏi×kT Õ¦èµÃIŽañù‘ Ô»é¶z{·Ñ5縒µ4ŠzØeZ5‹¬²Žy¦E>:½Ï– ÆM݋о«OVÜWVÑsÌ·zNò_»Ç¿ÒRY©t^Ž?¢ž |£ 03ëK“êèÜô©akÁ&Û !_—Ÿ¼+t»vͰ·²CμIdCõ.ºÀ@OãfºäGÕÝ… !¶q1þ°¬)Ç' ëŠMß*bc22U4Ë YÙQf…½Èæ¾j¶ÒpÁx¨¦Uwˆ®YÈYhò¤å9èY’›Ç,Nìƒlߦ¬~ý=Я¿²ÙŒâ~½ ý,$Åàÿô¹G endstream endobj 691 0 obj <> stream xÚ]PMkÃ0 ½ûWèØ1†v Î]FÝ—SØÕ±•ÔÐØÆqù÷‹ÝÐÃèé=IO”7ÇÆšô+8%0Bo¬8¹9(„cI±mTܪœÕ(=¡ü$ý‡¨à¿‡ï÷G~j›‚=ÛºxýÒ.a¿ÕÍQ,Sı±½ƒ²$ôg8ŰÀî ]‡ û ƒ±ìÎ\dDÌÞ_qD‘ªÊãŠÛMÊiœ¼T¤”ŒUPÖuEÐê½MÑõê"ÃÊ|KÌWöœ¹šTÉßÝžšCX÷æ'dGi¹±xÿ“w>©rü´–mk endstream endobj 693 0 obj <> stream xÚ­X xSeºN†Ô*”`*ã9•EAGD@(eoÒ•6M—4mÚ´iö´Y¾$ÍÖ4I×Ð=-¥¥;k e7@Š:ΈsïÌGçO9½wæO ¢óüÄßç<Âzä‹Gc¦ÄM}bª(daÈ•i[¦ý޳yúCÓUmäNáž÷ë‚ýgèXoåõ¼þPzòz£—)B_žíb¡FÿS´›½’î0hµ†n?¸ïÙÕµ_E{阈5hH9 …"éñÛ< 2¡ÞM Êl WÑ;\£ÕdÁ¿sj Ÿ¤ÕìŠ/«þä:‚!´ëj…{UBæ×y*Ú?¢'¤ X‘  gæ-à®cç+@,w@uŽý&=¬ŒRDÉ£B5™²íI ‡,U4YÜ5PExóJ$Banòîq+ùô Ù èi"Ø?t¼תðüãↃ‡_à˜¬Æb0@HÈvN†X•Ì5°¡ÄP›P.tòÍ —xŸ~ƒø^,«é¨ö(ö(¢CÕ©²IP"£¼üÁXzÅÈßC/z²Í:‡>à"Ñÿ?›ˆnpJÏ{nz:+ŽŸpwz¡Vœ©‘‰@Lˆ*”ed”»,%„‘C¯z(øÎC{Å»Ô~^=Jí³ChÕZ Ø#@pò/Hp1»E:N¡à†‹P—«2Ü£·ÒWÖù!ý0¤“ëá-õ®i šD!= µìh)˜û«Žuu`P]ßU¿ßÛ|ú ç.’ž±¯å>7Ÿ»–¯„<™Ê1«FªhU´<:T•,‹Jˆ@ú *ötç$?ÇL„5 9ƒè=.Ò²×Ò’‡ëòò·†ª…‘@’’JƒÐZPZYì­€úÑÛÙ"þÎ3’.òœz¿ÄÝ>X‡0h"…Ÿf~Ь,ô çT‚Ì¥&«Õ ÅD© ë‰ÞÁÎÅ ÕÊô…Eb("p´dð°|ÃLsø­›,ôú5¯P½É=a¡³l¶ ¡'_ù+Í¡è‹ìÑÿÚ¡ÒWùƧ×J‰kÓ­6c ÿžq-š~Œ‚Métø’9Q›WÅ.â)v*˜mXÍ%X‡ÃÀ‡ûPßæðkm,týŽs“}ÑQ   _+ÑJôƒt„Ü Å¤ÌFKå)$à‹°N9èHtEyy«$—Xξ€Jí-BÑDöß½©oR¥ë² îè"n0›*ö£Õ\s]!ä1²kŒ4T €ZE4Úúñ‘îýIÀ§:ºÌ}‡{ƒf9J¡2LJÉ~ì. ŠÁTìÁpÜ"’úüOû˜è™ÏXÃo¡DŽu¿©¤—*ìZ‹ŠJåéø1Ñ1A³Ô2ÈU8ÁCÙÙ.(7¸ Õ:»¤ ½:Cô¼^‘–“°UžÄü¥¿E¡ Ô n Ö¥?þ±ïc ¾=øì‹dñqz”%`MOqù ÒÒcÅt› v%©Ç@¥x{7ærDY$tͧE´œþõßf¢YÔჾÆ6G–7ɉKÇd5;‰à;ÓÆ´ðÛ;¯²îLñû9öf»ý<Õ¨p©1Õô4¶Ó­È£¿9ÇÝâÐ{-/”ý1IÐÓFJ¹Ò-‰òh=¡VòTVj:`ö5·ú‚fYK¡¢Tc”S›Mú:ð€¬Åe(ÔßÀ5²G¾6åƒÆ¡.°Ø¬NÿÄa&þšž9r~ŒšÐï¨i;dnoïl šeÃë¹4vF°ò"CtnØÇÎößà”]8mn4æRcù)):>Ÿ—4«Hb…Ãà Nèí¹X*½F¯¦Ç¬çÒáþòÂ2ƒ1ãœòNÛIP$£×)iîH=WºuŸlÏOÇÉñ—rä¶¥À¨wC((V8Ž÷\íuè<.È音лè2=ÇFSÑŒ¿¢‰Ck.ÐLŠîÿÑdÏéønÛ;͇::=˜œ€hÝÎu/Çqиf?e_9ž¹ž‚Ü‚y‰{“"ÅáX0SÙx‹|˘h×%´÷kxÒðrÎý"+Â}X¥ˆÞÂMxw•1ßóÍį ìðnXuÞBö¨”{¢À®+ÏsJ"H"-Ÿóüë¯ü û-õf'˜Œ¦@¿VA!îëz½¶`ÈÅõ¯Ã/´h­¤ Œ&{‰³´®¹ÄÕ¶íBÁ pFXèq4•‚FMgf³Ð'7Ïo[RE&ž'¿:‰O>þý­Û kViÐhE)÷¾b (#{ —kôG?®Œ´]*?åß)ãyÚÏåÓœ™‹±cë?Pàµ4[¼ñÏæÞW4NIC%Æéâã‚fÊ~ÀÚ³#Ó¹j>žJ‚Zs›D!€M¯Gã°S°+¼þUzïTĸ„~3ò1úëŽ3ª-§~úH¼„j¹Ån0á¶YoQ’|Ðð EDH¯¸›_ÆÇ”±èIô|zö’¾ÕQ!„žêŽ£ÄIdãì¦#Ôü ¯l…ÐÝê3Mó¡‰]µƒ}Ç:è©ÝKÞP¤/Ä‘ÆàHxѾ.&šð¼ËB§‡sŒf“‡ç(4«I( :Ã\5WnPð U”€ûˆI£$A§Ã|îÅ5è”qH¼Ôµæ4MDÏ 9?N&/‡Ç't#ÁaJõGô8ZÛV&OUcGûv zK6ó)ˆГÓ×Ë…1«wÂXT¨ýZ¯—‰Æ]A±·Xþ5þ‡9‘…zBâ”쯯ñ¶i[O?JsèYôì¹gÖ~ަÝü‹Ç¢vªI-N¨Z¹bÁóÚ| ¶ {(è¯ÿ¦îÈÁ‹ÇZ{Á ½zOÜ]’îBe‰å?ùó GÐ2nOPûcLü,º=ÖbS GºqÙV ~Èšö*2J$%éØUè Ú{Ü!-Ãib_FEí,¤FN¼k>Ry­»&Ñ·ïÐúYô“³éÕ‹,ùêߤhâ½C´—ôÚê «—Ó^þÚ\DÇ~o&½R¨`4æìýbl|7fþÎaWß„Mß'ìò’»Cf9Ûý¡¹ÂsÅÞæì?ˆC®Ö»$iEÒ,Èu_µµU­ÝqûãÈy ¤§kx9ô8l¿pËËÅyõ`ûõÆÈDùe\aN¨š0ÂØA™žìWtwNù7èDûl9À•~|Ûëöârë\ ùý¡Ÿ“ó’<²0'ƒ¿; @© pVÙK«¡œp©*3óR¥ ñmyCä7põ·•WÓ¿Ž[ìÁÅVûIˆ ¡'9÷/•.x/¥–ë)¨sµ¸Ú. ßpK1ÆJâTbí¾»ûfÈ6¥ïãô—›8œÖ½eîvzŽæî£Áh-«=ßq¢Z“(‰N¬•̙•mOX¾ò@j×[æfÜwï)e_[Ny®_¬¾E„|^ÊiY嬬,YInMM­·–«Çôú+7\cL¾pæÖÎtØLŽãh/·­èBD€´:).[ =+ ÛÈð¶8+½íîÁ± è½#Û)^³~ûm F‹¥Û+\Z]ÿ¶c¿»ººÞwâÌ¡¾cP 6…Ñ«)Jõw躼Ñävˆ‰åÅo^+‘$çc`sº˜·Ïþ|\SFt\ƒ¶( ˆÑ­a;TÕ»jË[ÝîE]… +Ò¹ù«Å±ßïÁãd¢¤A´qmÇ5”VrƤï: ¦ÒêÆcÝ—èƒ4ézÕ:ÚÅÕаQØ ªÈR(·Ù*;ЋÜ{ßP2CU»ÉÕ¹7m¯úòŽÊh‡¨ÞÍQ^S $An¶$M/Û„‰½WF‹·âJåQu®¸+Å×éþ ·º3ÿÊÀ†ïÃ?ÆòFwMïGW©Ê_ »Âeâ_,tûÝÐñ4/½Âò[‘óÕ¦Ë/ÞßOßp=Š8hšCÒVºŠ“°Ï÷>ž€uˆÕ|²mðHn¥Gön¢ Fô?<}ëÎ言O°ÓÛ}hþèÚþðwY_ÐÓðUë „Jb¥ÈFÕ7ššì¼ ï• Ý Ö¼›µÕ—D³¹¶üÚ¸€-e¢Éh.šð-TÄ$¥óäѥŸ†¾$š âL6Ç~àܵS?jj"”·ì¶°¸dFÇÖwcóÁò«ü¿þ®šÔ&©€¤dI†¼1³u׿¢ÚêêèÅ\EŒA»Þ@ÈðžatãÒÜjni9Øü R›É‚÷ízTü3ÝÅRE5º|̓3;z'êÄö"Χ`¨’&+tüÀYî>÷¡ëœ)ä›))ú*SþÕàŽ×8š¤ù ï;×ÑÂKǼS¯ÞÒœFSßÙýAÈ(’Ó£ìUÂ6‚/Xö)‚‹äøq táìUÊ\9ÙùÑ’ÞCÏ´£à>>[^ç B¾Í°&Ù¡›¨©¾t¬‡6¥3¯U pUXókÊëJ»ûâ­¥'Æ=»ƒ ¹¯]”6à< [ŠÑC¯•UX!¸ï¹°ç¹Å.wÞ=NXÆnCsÇ\zè¨q‚2G[@¿À]ò¯C¾ë÷ŒE¶ÄŸøŸã÷ªQ`PçåíŠ}3nÕP[vïˆ.Øßr·hžD‹±9-ñÏœ2Zp»tª=¹dà§~ƒîåå^%g¤§áv­êi¡`°å‹ÚKöj‹ßc)¾˜…ÉôÜÂû†¯ÝWÿÕèðÕeâá«H2Wg®€Ä‹é'É~8ÐTÓT±­»°ògìW¾ÛM0Ñ¢A÷i´ø(˯ôqZå¾ôlav6 2›Æª©É4óqSÊØMÓ¶)޵0ÐüYýû–2«ç'G›º$7v‹.¤ŸA¯ö¡ÿ­#ƒ‡çß}øâA´pññÓE¯r4†ŠÔ—·¯†]$œ¬ûÐ÷‰­ÒòÓIÿ 2A<;¯.«9£WWÍÐêj:îÙ×!8g¡«³é½¦K‡ÐBè'~-Äógåljvðãö)éì¢Àa¬qöt¡W¹VoIv£œ¦ƒF WãDÆ+¼îë(óºÛËìBdžXþtÿ3œx%ì»{¨¹ã¥éäVH‰RŠEg£ìB æl£Ë`¡FÇRVÿé‰C@4VfÇc,ò(Õ>EœA«Ø#Y—³,od³ ßÝdwÔ‚‡¨Ë±Ê„œ”„®ì>ò´´—7Um>ª¨âëãèñªóT€ù"‰àב xË“+(=AA³Û~ÀÙå9goqŸ¨?uÌP eR !Žõô_ïóúŸªRx§þùVú çtÈ·h¸Ž“H/]±7ˆ]Òv …›‚ÑfôYJ롌¨–8óä …[vtòNa“ÿ‡¯kÿüß~rì`øÙæ†üI“¾é—‘|È·}à«q¹ˆ`‘׿҉²Le^6ëœà›ti²×DNÿRUÐD4<íŸÖ†¾ endstream endobj 694 0 obj <> stream xÚ]PMoƒ0 ½çWøØiªªÒDÅÄÔ©´‡CbX¤‘D&ø÷%)ê¡[òó{¶ŸyYïk£=ð²²A6Šp´I„{mXšÒÒ¯UÌrŽñò(ÜI üëð{8}¿—ÇËÇöv­Ò(ì„ëì²µ®÷Í¿ä¬ ªwŠlË endstream endobj 696 0 obj <> stream xÚE‘mLSg†Ï¡´=@q+óLT8=Ý0vPX¨8ÀÈãÄÄmµ %åØò‘Rmèu) Lªƒ 3 ‘ ‰a.èp¸2?–Íàï·[ÖîÏò$Wòü¹ßç¾^’ðõ%H’”¤Ì:˜±GrúáÞ=&ÛÖ&VÏ ù‚%yƇ— ø ¾¡A¸¥^þöŠ— ¯z¹Íß° BH’¢ÀRcý^u>§T(Þ‰P(¢“µE¥ºÜ dž«¶³Qqq±r6Z¡ˆcw¨u¹*e!›®ä4ê%çYòÙL­*WÍ•²á Ž+ŠŒ4 Ê‚â­.'q»œ5ärö°ºX­Ó«O±)ÚBŽÍP¨Yïá^$k ŠÎpj›®=¥Ö) ‰pRá©YGøþ„”"^#Ö4áçC„/q€è"þ!ËÈ>1>c)o^·æs‡6!Ö‰ÒI<áN½sÕßI/¢îEoD34¬TNå}÷ÑB|×ÀApâm£6g%>€}¶7GÞ½¶û^É8ŒÀ|Çèƒ3¶E˜¢0‡§è\H±ë—+'á\‡;ðCëDçÒO-=p î”9mG`¤ÂûeÊÔoI1æ÷mpñ®o<ÍLs4½*¥û,õEÌIÕÑb9Pyâ>¸7û(w‹8Ûl’3š<Ѱm®^} Ã’­.Xnn”yc~A/–w‘ãˈ{.@—ÑÇ´½ãŠËÞ~{òÖüJ¡€·îc)–$(¢UÓÞy±cèz˜˜þ»Ó=ßõt$!Va{’°?ÄAøõ`“÷Çu/õ£Ta¾Èl¨Î2•|Rå@á‘WÛw‘ ½¼ÙKÞ[B'ÿ ÏÐcznôÐ,Ý›}TæéëÐŒS_öt»¸îÓEÚ2•|)‰ÐƧO^Èàá¾Ùm]sÎ[ßÃêAÔd()»§¼÷¢£«ŸÁÓígê¯LÜ·}TïlõV¼W¨4–äs–Œºkµ*(ã9¸Àüçmpñz$Îü(à™ÕÍ´šõLX­UF<ãVç¡Ë;=+.OôÈÖ““ ðÈc'š[eÿr½!ÞÅ i·7‰×é;ùä¤miîae«Øå?àl”Hfí’@Æß7Ö!ñC+ëÿ¢lòý endstream endobj 698 0 obj <> stream xÚ•X\ç¶ŸuagDÅ: ÆÌ‚;–M$FQ¬(ŠŲ HS@éݳ KïEDXEƒ‰¢&5ÑXs}Fc&=C>î}ï›ÅÔ›û^Þ~;óíéçþgdŒ™#“É,]–¯pã:ÖÉe¶û¤ÉÒ7W‘Ì!f¡‰æâkŒ8D&¾ÞMäâ³×FÜ—^™—½¥ëý>Òu ½ ñíǘÉd\x4ØÛO™`o?Ù)x[dˆŸo˜Ý¦Ñ6“¦Owg3ÙÞ~ºÍ¬@ï¿MžA6.ža¾ÞžaôC€[ð&?ï°H»¾aaÛÞš81""b‚g`è„àŸwF³‰ð óµYîêî½ÙÆ98(Ìf‰g ·M—Õºþ9nÛæbã¼Ù;$ˆZË e&0öÝgq‹z®c<{‡p Áôfú2ý˜þ̆g2ƒ+ÆšÌ e†1ÙÌHfcÇŒfÆ0ã˜ñôÛ{f3™™ÂLeÞ`Þd˜iŒ3›qbæ0sgf3ŸYÀ,d1‹f ³”qe–1nÌ f%³ŠY͸3k˜µŒãØ‘1fL“ÍtÈÞ–5u[Ô­@î ?bfgVo>Ò¼H!S$*>gíÙNàÒ¸ÝwOµ`Qۣߞã{žïÙ뤥ƒeVoÛÞ»ûôéÝ竾«ûžè7¤ßÃþKûçõï9à8ïÆØ`êÀ/¥:kekcme];xÔà(1ÝR¼bÎÂá²&œz§Êqºx‰W;nuqÛ˜¤Ñ@—˜ŸUøã´þtëI·Û¶nö©ñiê ´('‡ÃÄÿ°%~TÓ.ÇWøæ­õ›7o ðò2:d¨o,ÅÓqñ‰AÖŠ=1{ÊÅB¼Â?L!ñ$Hò˜±@â0ãµýD 7ñþZQRU —à|ÎñÂ'W²+¡ÎF:èÝá-X$>:&00"b[B(pT Å ck¹Œj1—ã“–¯Sƒ¿0k‘ÃàvªÊ =ëp×YI”*¶E÷´µ½€–žÃäuV’€x­e§Ð]q€\Ô¡?ï©HOvNHJv„hàÈDESÃןå¡üË‹Çà‡6—‰1³hÜ*ctU}cÅ{´Td~¯=³¸‡­ï:)Áq•“—Š’«„DPC$·Kœ&i;|ìwàhi”ÝÀnè‚¶r,Ä;<šÁ0 `Ke8,ÈðØoÔÕÃ>®9¨ÎË3(ÈsâӕاñõSÞùŽL¬ýªöã³ðwÝéQ³é®o­9µ§î@µ¨*aÿºì–æ‹Ü}pTB`Úz¯í~ÛÕÞê8M„&M’É4Ỳ \0EFq! é?P&çâ$þ±qŒ8KQ£É "©qÑäqçR+$ "S±uº'иÿ ÔÒ˜Ža‰L æÉe]n^ƾ8ÞðšçS‰Ì{ŒVrœ óû“j¡ªáC¸Ð\_vüTq»!?NÐP ©ë£ÖÆ»ÁrðÈ[W’¬K×¥ »”¤•Ý ñåB.è´9¹ù…­wi¨aü 'Fz+·ÀâB¿¹ö‚ÕÛk·n\7õ ìßÇ>h9íy]¹ <’TþœÉ<$†h±·QÖ†<ú`9ÎÆñðqÆÙ½'*[ŽúÊ 1½:Ä;-*¶q>µa { %­g6}<”ô%ŽŽ¤p>"L@«ïo  ÚŒ¹Fz°6½É¡ŒœáAȉ´œÜ=‡½ÛŸ~o²ƒ·‡™º¤‚v†…7´‹ñ¯§®#>Šd £wÇéB2Õyê\ÎS±•€y‹B››s©$OŸõ%‡ „#¶±Q®®„Kœk¹ùÇ G¨Â‚ìì‚bȇVÀñ…hvîz—Ãâ}êëM(j¸ÌÅ*Þn}ÿî¡Lyª–gÆçê\`+77ÈÎA°ìx@KÛÞTÚ↎é|r©zw(„€:59’h;_Z%G:8=$=MBŽH•bî ÔÕ^…*Z×ìð†à¼ =èt™í8Ð +爽ùx•¢A÷š~„zlKî‰Qm<ùIãø®…µÍh™›1 –‚+%#½.zWmÎ}£ï:%ìÊHÑ¥r8'×Àæ]ëéíxCQ]]ù~åQ¨ØZ¼ŽFæfœ!܈ ØhìgŠMÚö÷HÙx­ÑpNpO‡Þ!.B§ù¯±yNcóÓ«n:Èö{(CC\åö}~ÔâùôÇë˜ßqßÛšJà~ÌPX’”«Ü šdMlꚀð`Jˆ’/$=äúG§´'_# å7¶å<éŽT:dLw]¡™JÞ¦ƒÄ<ÎØÁ–}€WÈ1[\ÌÛU¦_Bî˜áôcá1Ü[WAe„ƒ¦ ¸ ȨR¢+[ÙÑB2¤kTk­B*ÖC«|ØÌID¦„ùë cŽ¯Þ›ò<ìéŽ|uexAl]0¸sªðÄL˜D¹/ GjJ!ƒ¶F8¤‡ÑéD9fr‘ Zm®>/O_PSóÑúÛ±g(ß²ÿôÅ %|ëò€Èjh,«h“}u\†7$°ØLIÅ?G)"H¥iz”åÜÅáÀÝêüŠŒU)nêžÁþ?‡›ä¿ºÉÒ‡9zÒM?ÅE± uÄ¡ïQYbÿ×ýåø—ýÕ—%ÃF.#Ä) $ˆÓþ '±Äêé†ëÑåúý$B”XÑÑÃ(ëðí`ø¬‚ÌÜkÀ•j'H žcRCÑö ìO±"ž¾$@L0ÿƨðWo;?`±îŸ=ôzM1XC.è+8Ë!fš.Ñ?׋ÿÍg—ê²îgd×P_4B%Éù_AŒ(ÛOK$3:—[‘yb€ùw’ð à0ÆtèÛLòz'CœéÃo¥y5|üÇ™4ßa1ñŸ\Ö®ŒäJ°®„Œì¬bœ-zZ¡S§gV”énìÎÌ.ãLË1 íìr)À]Ûñ\q;¯»a8{êˆ>G«…LN—›3ÂX/0¬8ÕZk8ÔÒ¸N‚Èè¤$i;þû‡-EcнjqªA¶åè%íQ*<Î?œ}–غ‹TφÈÚ}uM”%—îÊ3è«éžÁ]löž®ÜÄÒY3e#‘Û#ñ™òð~Ky+·T?Ç9PI§IŒr±–Òÿ*ŽÈNñã"ý×zè²÷52õßï¦eižbpå1Ùóç˜G÷oÜܱ'³’ÌUìÙlجìü¡…-)+)+.?¶êdüaZØÂ‹;”¡¾>þ]\aÝN/n·àèñÒú´þ ”°–‡n ðX—àó`ËјJêkzJ£8¨QÖD7ýyÒÔóÅî|~<$Q Ñ¤Æ%ïÜ6"íF[ÀqGNkqÊ>­N¥™×hÔšôôØhá<÷睊h*h»Mج•Äy.ÝiX2仉8 'Õ#—-üÞ%IS )>•8f—?d»£lc3U4täbC†=y­•'¡­ì[Í¢s–¹‘uI†CJQ¤+jçÞs‰{¬=ß°ÿ§Jhƒ*›êOΪ¢ ÝiØH]ËMiD·:|Ç «§:ÊEwÜÎWeAö%__ßæÙâV°Lb¡oŽ ýˆÍ3{‹c¼()І%õ?=%vûÂáôÈ ¾vJYg¦kÖªh,k8Pi„— '=µk8K|D§ÕÏF 5ÈÐüù}ää(Žàé"Nz-sì‰Ü›pˆYªkägg[¥»{ënA5š©ÒNÖ7àä‡×0v¿¬þ6†¾Èº-Ǹ?ºýÝÀiêOþã’Ž5ÆåÖWg–èÒSéË…îܳ§°¬¢:²ÁSPWxx¤Wõf½;õFXñÎ\%äzµøíÚé > ªÚRšâË9×Oæãb|ëΉë|µ¬.$ߣzL¡«ÖFHÕª²ãšh±çh‹ò 8ì‘ÅO…ÏÞ{>»wœ×¯ç©ÊSă¿z)vµ¯ï2bE¬|N5?EÒl hkaªÚU2Ü õÕ^<Íçõ>é&Œ„µsb9 ~¯ø}¥dŠÉJmº69gôc‘¹Ù~þ`EèLÔþù1+½Ü2¢xì.eCŽ¡rÓ+.¯?oïz¿fÓ+.2‡, ÕwÚT}—LB>ƒÚ½çMqwÇR1È:ƒxÎ$gZܧ’ò¨¤Ãþ ›6ùûoÚÔàøpCÃaÌ7I*J(RWÒÀÓwÚ±âÞY"ì„ØÌDÝîŒòbØÇ5n¯Úêê»ìlà•;ß&ˆI4¿ºJÇCêu9ÞEý~ÌÏÍÓ&Qçíêزݭ Ìó«Ó“”–’¦V“…d¤•¨bÿ=RÔ‹ÚÏ^Ej0[œ_TPYнˆ½Uv¥„.!b({®Ö} µÇ M/ÒØ(ˆ€xmLFZF|¡éå ¥žÇº‚ø'àéRr™*¹üK¼v4åµ+©»þäwibn>NgôHX7/Ê?êî¼¢E0V»„{Ð$wSÇ_¥¾JÀŸ’,»uüÜÁÊŽ‘äÿã1ûK­ýe¡9‹¯ß»φÿµÐÄÓ;w¡K¾ô–´ƒ)›ø„L"S‡‘dÐÃñ8 î=¡óšèÈ2ž ì~ÛWe•‡”áChÜV\î«Áƒ›;y /É*#Ž0HÐüœº% d,ïŒ+5;ZC$2óúË/q$ î“×(æ»GlòçŽÿ¡"rþh³³ØÌ<Ú^|¸ON»ÒÞáä¾H©Ue@…Ë]!{þü™`›qoÈÆ)Ø]ˆ‰OÞ‘œ—aWM¡¤ùØê½ ðsŽñ¤A”+È´?ñ¶”B¿Í>YÓEŒº(½µšÉ›_ -ÇèÄ´ôøäÔôàâ-YÌÉ •0ûì¨O­M5¤dÂáÄÃ!àɽcá‚;,.~œR®Ñîú…뱿p=”ï)³:â{(Ý:‰}óé£Û ¥^ûý²Væ.Ê[šG¹OîC…€rÈš« ÑÆæH»¹‰‡ZŠ h6Y#Î,—ýH#Þ«EŽ>ˆS¾7Ý<;;»tnë-RÏÚÞ»r­õÔ5¡Ýs5» 0(`)\¨z5å¸ßÁ¾—ü:ãÜÙ™–8¾›VsRÀG,qþ-j ì¨ A/…j¸Æ[œö-ÎúmÞ™I ‘Z!òF™˜$ZòÙE™9ç$:æCé˜×6JÉ$l¨­LM–è˜&5t'¹V„Çýæ'%Ò9¶-ƒíôÐ9çtöÓïÔ¥VI\/G§/§d£½K6¥¬½øì’Œì$ÙAêXðñŠ5mý¬þ}ˆ5ÉNKJ ¬‹MæJ¯E\a›»ÖÐ3§ÙŒ¤Ýë2RrC!ÔéÉšô™d™a°L:¦žÛü= ÐtÇwöÍŽÌ”(^M@Nù ,¥ä¶X¿Cú(‘Á¬ìRîl”á9´Î+Ðç|)Á¢uÝ/HÁ’ye’ëêÔdµzêh+;ìeÞòJaàJÓ‰Ë,Ú“å´GÅÅ$'Ok{F§ƒúºØ+ÁßÎðÝÙJЂ6;ç)š[¡œ¼fî©RTë.ÀÞ}í¦3s¥$Hó࣬R‚“$±7ŸU˜™s^Š–Ÿ:í·LhÛ¤h¥§§hÒi&v[‘¸OÊD(µ(8ÈÕ”‰ó,ºtŽH‹ J³ßàï<Ò â³tÚ}ùÐÄB+BÃýÖµzžnÉk”BRªb 7ât¹¸XÃë)©€,®,v ä_Šxò.]\²¾«l¥åÍ=PúN61žvY²u„ʱ‡¢ך{*’lw¸‘~ÀÙ+,ãòEW=n,ÏÍWõÙ¬Ñe=öë{öDYUÏ^‚…™CyÏîÚž–bÿ“óº endstream endobj 700 0 obj <> stream xÚ¥Xy|Seº>i  P£©KND@@¯\¬²hÙ×RJ׺§mÒ´Ù—“¼Ùצ[š4mÓ½¥”¨ì‚(ˆè¨WÄq·ùN=uîýÒ‚wœ«÷Îïwÿ9ý5Ë÷½Ëó>Ïó†CŒCp8œØe[W$®ññ„Õ«WÌ›yeñnÖòSûj,óÁ8 ÅÄs™{Æ®¾2æ?c¢ NÎÔÈóÞÉøIümJäù(~Ä}{ÍáDO¼C¡s§¥ï¥ 3sRæÎ}rÎܹóòò%…ÂÌ,QüŒÔÇâç-\¸`Vüü¹sÆ/ÉI/¦¦äƯNe¥ç¤ˆð?{â×å¥ ÓE’ø‹³D¢üEOQ8FEpôD%‡&&“ˆˆ)EL#¦3‰Ç‰ÙÄâ)âib!±ˆx‘H ^"–ˈåÄ+ÄJb±šx•xXC¬#Öãs7›ˆ-ÄVb1ŸJŒ! œ8œãQ£¶Gù¢¾äVŒypLûXÃØŸ£KÆM÷G28~Ý„U§N<“Ó9éÞIc“bÿ:Y3gý®¾p¶%¢ûºÈXækvO=Z`žðs}ϳջ{ÀFÖÈÝeòŒª,ö¡áø´ ` Ë=òA=xkÍ««òhšÓ–? ÷ÃEØ;ÐÐìÚÑ× V·ÕtUž3éV-P‚QOW”½"IÜd>ÝèÇÑz:;›Á·T¹{¬U¶ ¾ÕNÖV¸Ê:(0ª…ÛÙ×øò-ŠZiÔm›»È-EíoPv4;šqØï(èï'9=o¢æs\¦Šϫ삎†P¬8š}œå² Ù‰Ožzù:š€âÐ$4‡‚8´§ŸdóØ¿ó¶¦v]¢ ÅûI穾 §}@~ê\±‡‚í¥ …›Ó7¤‹ZàGÎÕ¹hý /\Ô›[T”›ÛP74„ø]vC=záGZà¢dï|áÞ´ìÒ¼|A»À •V·Ëb6™L@šLÆ –d½–­Pà:ҤƦ·y>þ/ˆªM«g:üœ+ â-`t<¯ÝaéQ¹¸i†°>¾B§ÖäNGÇD^¨Ô˜Á¤ÇåòPàÑØäöá2ñcšµÔÿ´ÎÏ9ÎÜÃeVmçÙ*Á ¦Ñ5 ¡i-ûÍßWóu2Ѓ‘T¸TA%XöòŸ¢AbžÇæ´¼j›Â6|ùø2NH…J¥ @eÓú4L€5ñ‡ñ£B£Ó‚*nä@ ˜¡ÒTA+Jje^ÆøZ†ÆñR—§U$Ór£ @Ljm:§ ©ÕÒÜÞÙ3Í^ u•IC‰ÌEN×îqú>@wñ‘5Ú\âcï%™³‰.­PB©Â fÁ¾ý–}¡³!üM/ø=JQ«tøÕ¡±|ƒ¬exô­’dÅÃ+xh ºÒÆ^;dÄ! ½­æ‡/¸è©yÊ4ƒz1e‘“]PK¡¡h4#gÂ_(¸´æäLÏ÷u?\†/ÉË+α1öóhñè'ë(3ÔA¡Öà2.§‘¦åd k潉L®N³e?Ä!^ôµúÄä'ÿmK±ëØk¼ ÜT­Ii¢MàÄ4Ûj/ 6>Zýçº%;gÌŸÉN b‡v·Ínå¹Î2 ­äY FƒÑ¨P¼ü_åKzŸåɱÅl[Î.DXšM}ôøâ“šë`!ÝJ0´ 3Ôª\ÑKK×,]·ªló<ŠæRp¢=ý æÝ›‡?òÛSϱ$©´WYé+†D$4ÜÁ{p¹¶¢t}Èû*ú}§4— È59QyAm×Ûn‹­öÊá[<¸ûÒlp)#ïÓKKžIžrnô9äpuš¬ý¸0üh49˜ý"ÐÓùÙÈdè,—À&»¹Î–ð-M:(rX]z«âÝÍxÆ1p : ËnäßnÄr/X¨ðeK¸ýJ{Ì4—·œZ3àJð%Å€Ï2çZh+TâøìÖ*L$+¡uˆƒ0ùŽç겸?²Á u^è©Ü%tn΋91Ó4²Ñ»ûš@LáS {ßp_•A+ñÝ"Õ ñÝïYÂ-—[b¦9ñÝ^5SüéRs‰Yo8ÍN3 æHqà8ŠbÊZ9ï¡(.ÓÃüçl7»ŽYí:—Ö¢¦ _¥ ³eÇLSÉñÙNh¤‚à†¡vÐPZƒÆ fÇ 'ó‹f.Û¸ `£[zÔbtà¼È½-mùî2ÉVù²ÕƒÛ?¢nÀ÷çC_ãN.þ%Ùo#ÉznÙ2š¬ŽÊ^Hg&+ÿ]h³÷wðÿyV˜Ôè0½æ#´‡otÞDZi Wî¼F*|"™f—9;úŸŒýiÇhL?Íi€Ùý>A×È8—Q,?ºŒ s†ßæ?Ëœ¥ƒœkû@´8Òoü9ªj^cµÁNƒâV”wÛùÊԲ݋0œdF‰ÊN;©¶NK{G†&C¿Gj­Iᇠ8L6‹ÝÏôñMÑW&Ìrneœì›ƒ™14 ¿ÌN¾8šuÜ/0k~ÇÒ¼oÿ¾Öò{T ÎÈõÀ<;’3„Çwn3¦¼‹¨ü"w(îöëðË+¶­åÜzOðl ;ŽDÁ¢Á¤#åËãw«Ž•ÃBrÞÂÙ­d¹4E ¶“ÝdÅR‚UcÒáS 8Q½~+Æ#£µáá³Éäõ½~‚¿Í;'D÷ß .;Ê}¢`¹u~°ØžéV™ó]Â0 ’ÿññ¿¼rf';F»õÐ’FPyñ›,Öˆ<‡3¸§•óθC“™÷yî}µ-[H›×Tg·ŒÊ΢… Pm.npR'Œž«Ûä6A é•c7²k'R¸ºð—È+©Ó`WºŠ1…¶ñÙL¶T¦Øºq»t3'U)̈•‚–vKk÷Þ®Q­q+MJeÚc†f¨®ªöV~‹ÌŸþòWVmU˜Œ`ˆµ¸,M¯0ªŒPFÊ#lÚ|ÑÒ:ƒµÊ¡%¨©å&ƒ¥¬7í‹åh®èô;@ۚà = §-•&@©³ '›Þ“‘ž‰£Å„I×F;Œ.c«ò B!S«0Öþp+ñ›ÌyžÏ×ÒÒÞñŽ-Î9£–tê¬jAA.Ÿµ{ä ±Âm´9† ÊDz?ŸB‡µ¾ÈäÆ5¼nŸ·&Rª¼—é¼ÑRÉ~)•Uå*D“ÙOø&Ú‚Ût*ûo:‰l½‘~ÆHŠÕ£ÒLEÒm¾Ô<’îÈxPCfBÌÇ^À`«ïDòmu&‹Ó…“)Ìì§÷].3ž‰åIºs›vàñÏNae™}lŇ”[O¿ëLéÌ>ô/šL³ÓÓïé3»]=](žïhÆZG­m”ÓÅä+¬—§“€¡¼,yý.iv™ÇöRp¸ +ÓÖSݽ@¾å[¨¥0ãj:ç’‘8QFçài¤¸ÄEê¡çy#Á‹êƒÚ¨0‚„ÄÔTuȬQ @£êJ²a7«—B9kpõe<š“Ñcè¡ë/<#H‚]¹9{ÈÒçxö˜]ž×ߨj²«)g%‰Ùì8Izöò¤LìH…ÙM—)<uÕgq$/a Üq­7ÀÙwå~Áeâ™)<)ֆРi¹¡ 4dQ­¢.ÜÔÐûúöî—ØûØ8v:û༓‹¿GÓ?ýÑk×:´1hÕ‹g°ì,ÉUù¯Ÿ¦`Ÿÿ«Ž7[OÛ : GæËÇW¥ã«òè™çÀ%TÓÎE¯!)/ —͇ë/¶ØNìOß·{îÇg² ŸZü—ß»âYÕ§mxM­UgH{€·Íú.’ëÁ¦\átö)ØEÅ2lJ î“ߊþ¼6À¼Þ¹Áe¸ÌC¼«Ñ~÷-aø÷èzm­÷½k÷ƹêjªê1ñ6B$Y¯ÌÂì ª•×5†=’‚»BX%É™¡-¡•EìäÒÛÊQG~a˜’Ì,›» âôØeˆkX\]PE%^qAnqúŽþ¢}‚cÐ{ª¶§ílM2EÄ;ÇçýãÕ3-Àyï—ÙÍLâa·bÇ(²”¯ÑgJº³S1~£1~ãÙ‡fœI¼D‚ƒÝ“‘_2_¾ z•pƃx(²My®—§óSµ¢.¿x·$uWwéŸh*\ú°ê4)F›xÚQa±¸D²G’‹1Z~´—‚Ca4¡éHÓëû{û€<ï[¤ÃÆcT÷–¯F1z÷çœOï?ÍEÝCcyþŠjQ~~A¾ØWÖl ¶žŽáyÃ`v79ý6¦›ÝÝ[f§³«”nì­±˜mÕM7{[ðrä¬Ý”hJôJuÁ–”îTȲ¡„ÜÞ‘uèf7zØukÖ•KVe¿ºû;HAÈî žÁU{WÍýc‰Jvåžå2â°ê*jŠD9¢œRŸ4ØÔÔØ$`“~^À?¿mí:Ðb¦—¸Z!þ‘Òæ–d¦ö\„/C_ß`¢ø6?ø°Ó<‘Ò¹åáµ·cwa-tÖ…Î8ƒ-•¯VŸ‚-&­Ð—á8j0’OÿÉ;2ÀhÿÛ'±ýïýߘ.e~O?â]âD~ ã*—Ýks  ÕöPý‰V`3¬§•¹A 2±7õ(ÞЛªÝ¡~ϱ_Té‹¢ÍÉ@Šež.¼‘ZƒÖjk ¯ÞZ~ÚÓZÛÖl84x`ÿë`ǦÊlôLk£Ù@n£Ui '¥q†÷ÞQûA$©ž¦§¥¦—ãÞQ†x}œg¹Èó‰‰ILãU‡L*u$±;†iZaЀ4nmÖAA;„ü5]µ=Þ“ÿLªâD æhóQÐ`²Ùê°o‹%ì¡É§«Îq¯âÑåZèH‰OU…·ßZ§Ão2{ÚC?ñí{À´Ö8Ã&kUëàõ/pedSP¨ÉSçä±$¿ôy}©Jº¸‘¯·‚=älóïF¸öZ*Q â¹ß#̤`m ]ºQU¤ÇfÜÞ™uÃïç?À¯|ãî—Öÿ?Wƒ+Pw´qáùVjß ‚`srÆFc%Ý‘×PX¿ÛVó`ëÊ2‘îDJËHqšJ"É’%b_u{Lö@Í»þC]ØžW©ÓñÐ Ù&Œ¥Ñ1ã ŸþX½•½KºS%2F€ó[é”.Ë^·õ×é ö¡(œÎÛ;{·‚?¾«5i$x¥D*¬Hýoï÷Ȳÿ;x`7¶¢Y# 0O_â°±<µÐ ÁДc~TÛôNª)Œó޶[–Y [°ncöîC ¡ÊÜæ¬#Øf’h*z=zsíùç©-°-3;MùÆÎúŒÛ•Ê^ûÍJÖø"•Ês ž£©©¹¶ª³5쨲·!+ñ¶ò _Þ–ä Ù{ÄBš-^û&E=:óy%.ýŸ¿øí›­è~k­³½ö¢½ÉZÙ|°!àt„÷c‘¨’› GW\#sÔÔìêÜݲYð $oç©2Û¶ÿkÁß®d–"0x Íxï Ž'îzì—¹™ÀË3–C1Yá*jöìÜ÷<ËÏx8YÏ^.k**`=Y ZÀÆ*à9 öèB-ÐL¥Þ’‚œ’kO¤^EOïE“Ð%ɽù͹¶dW¦3Õd¸áÌ5AkªÒðÔÿŒ¡׊üœsxðwa±¼y[,%Ô“Ñ]h&Jû?þª—Æ>ÉŸYªÅrlÄ©kÑ l·¾ ߆žô7¾=¡ô‘ŽÖ)vNßX$²DYÙŽ Àìˆ,Ì…[ð'Îy°Æ|wœçÙÕY°ÿwYÅ:ñ²”ÛgüŸ?ÿ‰_LfäúÔg^r“r ›‚ãÍ5^ð¶ü"V³2~-V¡Ïzº{€tU±X)rµå3JVÃVrÖ…Â7ç¡k &€ãߊ›sÎ}Ýs“Ëd1$ï‚jIaQA±d6­GQ_ZY™dÊ«¬„¿YÔyTÇ›Þk½â¨ù]© ÿu0|[* •ùI2KÊ’`'ÉפÐâèÓ£‚‘_.+?G)ø†o ·opÑgèÏÞ¼qlÐõ²<]i! 3ÐVÛ{4Ñ'¬¬rQáù nl¦¯ey…‘«)¼F›Í®Žχ°J×uªÖP°§ly/]•’ŒT%•![ 㪩ØYžSX°;épi¤-voFWÚi ¿;x¡H«(¶%Mvü²¢Ý@¦IÛ:p«ìO?.› +xßµ¾è9SÆLåY#kƒc´uJjUåz^¢)Ðäków°Ëùúò/¯r³¢÷ð@Í›ת÷Y=XÒ«‡¿2…Ê8õAÉZØNÎ?›sJ°:jš›e›ä[S7Ós“°ÝÝa)Û[ •àóº]îJÜœÖ|«R”-ݺ¥?ãMÁwðÝõf4vÄþí oÀù6Ó+¼7N†C]­`zs°«ëË/‡ðb€+`hð«Sål+‘AÈ«ÊkÄÁ26/$Í)ÑY´.Ê…W|³½îÀI“ê¡NT÷–{0±dî\ –Î[À_¶> stream xÚ­”{lS÷Çïó¸€ «U£¶×.ePZFS:Bi§µ0ˆC P ÍL8±ÇNl'~_ûø;~&1±CâÀ¤³ÕJiˆ œKˆêHØGaZ’ù}dóÞwsrèx´œþ–£³SnðØ=öö«h‹Ê3ÿ°9Ü¡Á+'Ož¢Ç¯®aÊD1ÃqBC÷B1$šÂÑùç¾c¡©Ô ŽÍî`à —¹£•4ÃAJfÙfæ6Z´VPê ø§Á¨#b£¤?ú=׬#X‰æ :L&À3ì zÇûþî?küRE`“EKi,jfÌ>žÜórú†áÞÑ΋L“ŸVØhVjJ6–Ñ`Œ0Øü®¨ÍÉ …n/éÞå$þÀÙ3S£Ó?åÑî0@ “·±KéŒMHGv“[agyQÑÖ"I[‹iþUm,ާ®±PèeKõû)=#iѳ’ždàš™‚3W N8AN@4á‹tÇC#·SnŽ2YI eRRmª­ a%RC´—a‡Ï ²þê±ãðÔÚ+.&o ZÃq„¼cŽÃÛÞk÷Ú]ñË“ñD_ÜbôPc)¤FY[™¡¡y£±^µ…kj6Ô2¥’…õ²B~·ßÑîI¸z¢ßrŸÜ<¶h<~ü‹É/é‘—ð`»ÎR|ªm    оO|ÿŒ{¥k„"-zo”QOÄ{846‰²àq}çH>ùU– ô·6wï„R(lÙžo¸øi¬ª@"o®––h‹ÁB<µµÓÝç?Þ}aˆ¾vI#”&…¾Æ¢W}lVï§ß`ì`”€ù?ù‰ì÷Ie’?{¦2?­(SQ¬©a¬¥ùiE¹Â}ÿEÑZØY\'2œ-Þ• ‘µdTìþ¨HJµ=èÄý£g&f"9¾ ß„wÒfwØ\ŽŽÃGû$\ÝŒu»­ÁÖ=:ã~Ð=õéç#‘ ´L^ßtmhÿ'+kÛÔÿ‚wÜ1O‚›ÑÆB÷€™h|ø;tk†•´$_ã”·Yö1GgÓG]ç :÷“% ª‘ík<½3¼—y†ñBzx61Ïv—Ãýúâô) > ‹+yÐÔZª?`¨k\eR¨wT ËÀ óÁ83JQe°±¾N&*=Þp’< £ŸwGŠÉ¦™'¿ˆÄfÆ{Ò°¦E;¶Q#ŒóàP{4xÎ=¹ë O™˜ôAó(É{’ù^ŸÕ÷dÒ{¼YäÜôÕ‡ØsÜì¹6ö¼á¹ßÌ‹9Ùltç…áZ" endstream endobj 704 0 obj <> stream xÚkHSaÆß³Í£.ÍËÈJÏ·YŠ·iá­ ¤f,QÃÝîäwa]–·I¢î-%K‹RfÒ´éT‘à-”Få‡L +4° ã}åjëËž/Ïÿÿü( ‘Š¢d§ss Ôgâ²ó‹R}9ÕB:#%Îí?¼àH G‰0+Æ{$Q€!>~ öqe·Ñ^ˆC„¢áj›Ju(Q¥JÉ6šêÌeåSË%gd¤Ås)*UwBÏ›+Jµ._+”óz­à UœÆXZÁ u\ÌÑrA0e&%Y,–D­¾:Ñh.;ÏY*„r®ˆ¯æÍµ¼ŽË5®@«ç9ßω>dõ¦7sùFo6ïd1¡ „9ð H@˜¡4”·aÝØîž´SÈñYŒÈv°ÜÙõ¬:/–AFG;à8?ÌìÜ¢+a£’-ÑIg»–àÜÜœ•)Ý%´Þw)|5_ÑwÖÜÔ{PÏ/1G…ò+ÒŽ«º¾ùFk&l€ )”¢ðßcCkžç^§óÙ4|Ç â·HöyrjBñóÖÞÇOú'5Ž^f§ž¾…ÌÖܱL̹u2X‰>ÂjµÙ`ƒOI½Gk'^#)\ˆÚšqQP‹ÑZ•¯¾,Š&"õù,… *o_zåîzè€CÌXõ`¥IMƒD†b676Y¸¨ù@üÄ,'ÌñO9—Qâj²;†úÇY8RÓoêšzñ Þ…Ì´§:]ÏVÅl­³™:Z ÕÖlƒõÌõ^ØÇþ׉BܸØNa°"Æ (]î&þ¸€„Ýf¶v´·4‘Ÿ;#tÈsÄ«´)5è¤ö›ë““ëív¯Rï¹Ët:> 'É0T;€³ cÏ)ÑöÒÀÑn™l¥O¶‹ ¤Ùeþøpø?¹é, endstream endobj 706 0 obj <> stream xÚX TTWÒ~mK¿ƒi_D'yMÜwQG q£¸kpY”fÙ𽻫›µÙeohhÜ ,.¨$n“h̸‰&ÍNë‘Ëäü·Ád2ÿdòÿgxpÏáœ{kùnÕWUW ÌH$kWçÍ«W9OuZçâhùî’ñSEo’•ø'F|I"¾a{½½‚ì×yEøûzEДö›‚½÷úDÄØOZèòÚÌ™QQQ3¼Ãg‡ù-ž<Í>jo„¿½‹O¸OØ~Ÿ=ö+‚ƒ"ì×{úØ[LžaYœ‚C"#|Âì×ïñ ¢–ÚX3c˜I’i6Ë'fù UÌ+éNÆ‹Sc&‰bžc†0Cfó3œ±eä̆g^dF2vÌ(f4ó'*a3™ÈLb¦0Ó˜éÌ f&ãÀÌbæ0fæ2ó˜½ÌëTú_˜åÌ Æ™YɬbV3ë˜õÌf#ó³‰ÙÌla¶2Û˜íÌÆ•Y0ˆ‘0ƒ™RÉXI¼äö ƒ&r”"•HWHÛol¶Zgõ‰l™ì=Ö‡-ã칼笞 "²~Èϯxþ®µ‹uÍP›¡ïØ$Ùô söÉ _ Ã]‡l»Ì¶V%Gl¡æ_ç»_œø¢y¤íÈ.»Áv~vŽÒ^;ú¶¨¶¯‚Y´2ãð'õFÉÓk¸ïšï‹+ø8-ýV#68Höý“¦n¡ ަÃ÷¤§*! ¬Ž­ª­(3uon[0‘Xo±ˆÕBåmò7Ö]«%Û¡/ÓµwÒž´gfW© ]ùlGvün©üÏ»ÄA¬˜'¾\K‘‘àH#:¥è ~Ì_ mñò ) i ¡03ß ×ët:àôš¤€UëÝ<4µÒ¸´ì”œ¼?Dkw¾øß´Ç}ÅO.å’o/Kñ Iâ!K‘šCx²W:Î¬Çø ŽÎÌÔg@—“–™"$À,§-Dâ65|çÁÉ@dçȷɰǯ—“•™£ø§hL ²Oc&OÀAÛPº‡Íø ¸DM²ZizuNÊ[Ûpy ÈQ cC‰Oþ¤Q§§ScÕúä<¡^?‹’Î/ª¿´ælð(Ùò ¼Õ¹Õ%<ìÇ%NéiÚ~óïÞÄ!ï…Ùó *Æâb`ƒë.Iò±VŠGq‰Ô®c©0 ‚>AFŠÛÏòuáÆÀÀð° ÀêðúúêêzŠQɨøiS¹¤[+·õºñ}&drÅ 9IB¤«ÒHÏÏ‹íÔIštH礄ÈÌÏ,àèáHc¯­Qrü>Ý—ŠøWÕ÷ý?ô|²¤ú ØKÂ=§¬H{ –Àjý”Ö…ónŵÃ_ᆩå³ú«ÙÂŽ(Éû| 8E£UâÛpºá]¸]p®üÓ+¥p.G•ÍÈß ‹`-¬ƒù‰÷Ù²Ä0°(§ÁÄ,Á¨›Rìî•óF­>LX·f&(S²epÎÖp}E¬¯:a† ”5g| 'N<„fªì uÁ…EÈìù¾Ç,9ý=|&wãr>X¦‰OÞ—š´¢h­}ý_Å1» g²Óîa„]äà°£5ÍPY_Ò\¿¿R)¤ÒµÕ×®4œ®§iÚ Œ_üªÛ6²†¸Ú©T N”Ë,˜™n#ƒcjpÈ7—Œ¶­(Á—õÈÆ·ðþqÓ›À{ÜÍyÆŽ]´qɾÊèººŠŠº¦ðâ½BMËÅò“ÀÝ+YµS©na>JM&L£dàäÿHÒ&kAÅÅçÂ!¡Cöàèòid„³ßvE4LÉò¸Ñœf2B#w8¬"(,ð€×ìÇ+ÃáöòŸáÁŠS+@ÅÑfÑ‹FöÅÒ:ÜÎ+±f.ÅPµTˆTÊ.g¼9Y×á2Å0’]ªÎ?¢¸ßc/º²åMSG«M:È‘Ã}¾<‚(³ê“±ý£ä+Ì8òžätS©J¿Ç¯øP ¹‘™m¨oé¬>ÜS 3üô×{„xyEï°òHø dkr€+¯+l6G–†ìNðvøÛL”âÐï¾Âpèܯ‰Dá®qþ~î`ë“ÌifàpØõO ©™i Å?)mg´{²ì\÷²Ä, hK€ÄXE¿‰¢Âxï³ãôBaàãÕä}8?â¡'¿»öLù‰“oÝ€rhO¯òã|ã¢CBK£L¦²ÒúóÞ]„'¯9 WÈ"Õh³ò J¿yŒv(Ÿù±ä}`—ð_ ·xØ×‘Pݦ½%ÜU32_Ðd: ëÊ|ÀÜèçí«tñL éðÈ ñÒI·ùÉc©/>å ù ‡ ŽèeÄÔ…ê2.X¶øX™d™U¹ç r²oCõÛW6•Œ$/ç2\F©À£½Þ,N²€+‘ëºÞ/ÝÔ;Œú{6´M¡gå7q©èÊ–EÔÂî¯ï{çæ¥-ËX¾ÁÝ;‚3Æñ§ª?8w¹'ÓÏÍã¸t¦>E~ÕA‡¢³ÓßòåäŸÎñÚ¸¹W~XIÛûêïÈðå²Î°UnPiB7~¶‹ªœ €õ£.p[øç×/Ýàú© ï7˜s䳌â+–+XýÉŸŠÃð]>’%j"Ýå"DÀöÌÐÃ\¦,Ws,Žs51åÁÁÑ1«ºv=Dž~v,ÈÂjbýÎ,ÂŽŸA16é%<ýŽw•¶r„ÿ G‘¸}”âÞI¿SGëO+l¦´S»"3±È7s=ìâ^ß7vº0Àžð+ƒŠCùúðjJ¡áAÕa”BuùÛà§ÕÞ|šGnfѹ\ÒØë"§÷®áÓ Õ¹qšÔÔ8Ð÷È.a_„ÿb-媣ñ¦JíyKuÑÅš¡ ú,}VòvX ;K¦f&êhu¸ BiÕmË8ímpˆe×ÊhâÈ|Ü• ‡à+›ÞØHsït³¤»GL«•Š=âÏ|€ÙåüÊg[É«d.ñ »ñ527ãkßáËø\*âR´IÉd±^6¸ydUÆ\ÝuOñ5ü°´šÌÓÇëÒ +¬ Ƴ‡À ¤€ZšÄÙôn n_0ãáF Ú?DO“Tìí]È÷]WVÉnêU¾Š¾2ÖW£Z,D(Åe­˜o, #3CÈj—½l§&§QeÙ¯ ”s&, –ÍMPNf`²¬QŸÓ!àh:€iK ±çL2›ÞÙT_‡Ûô¹R}_Xô½õïúdm— ýø#h꧇tJÿ¨yÈ~™0o@Ó4KÅÏ1ŸkÕ„ƒÄ–8÷çøMì‘Ì‚GBƒYæ¯vo÷u¿o“X'³ùiÙ3‰ãÍbó]i¯G¯Àë´V}W5üBÆU(ξÑ_ñž.Vþâ4Y(Û)C"ú®Ø‘ñBr¹V£ÈÂ_#0 ·ñÔ­sú"ÝÉÎbíY‹[㡳V!6°:jÿÁdÅg&À¨|È2d¸~öðÓ,.5KQÕ;‡O.PSä9*Ø$ëc m~ûšÿ@t!+.ê{š›Y0ªrËb[ =4è¶hhÝ\ãu›,wÚn!о%,ȺÞYu–øŽè‘öÆàg<î"3qÙ@¿™d>ñ$žè@)c=ýp6z äsò?(>Á|TãØÛ_~‰cRºÎ'Š9|ÐlÂËÔ—1ñBT‹Wy´ïyðÅ×ã…‚_úã`I`ÕxŠïOÍ/dèd‡]Èk 2ަ§:Ò¨6ãi#ž6Û☘ÿͺž¯ÌòXŒÁ§<æ±P£7”eô PÜ}”™<×s-yI’üçµ·Þ†[Ü×dè]2Q ×Ǥ“ôï7&e°òF´–]‡ŸÌôz_8•àÙéÓá{òû¨øAu6ô³*mÍÒÖ*ÕªòäCI•I禮%_JºJ¤M´ø]¥dí`’t_Á»W¤%Î㔇^7¹«g¯|$ g¦MÈˆÖ¥Ñ ¤r(ón¡W®…|´Ú”„ø˜¼Â}ÛbË·šNCä¹ùã°¨Ã-+­Í³4 Ÿ¾mÐÞ«Ó6úÂFÎÙu©ƒ°ˆ¢!µÅÜAHŽR-l$9 Óå–&Æ>siÃíDÚs¢ÍÝož* {ÿ›áõ»Îyä¯.¦QKprDrÄŒù1Ïl¡DGþ¬,ŠDÒŽ¤Ëëp -eu§)M×%BGÝ Æ{,í8¢½†Æûòø ¯óô¶uù%í'KŽB+¯ñªÙ¥ßHƒ~gêÖPïÈ€ÝÊ­à>ÕáGV€ʸ¤Í¼ÙóT0™ðyôŽÄᓾ%Ö gØéÂÉwâU–LRY)Ùw )®Š¾Ç&:PìT™°ùQIÒx=ik̈/óûÓ£BZUSSqÈ|iùÑ9dÄT{2œðßO¦-‘¢‡ T T@[°Øˆ›B··Æñ NB‡;…pVs$ì™sfñÅ~ç¨ã5ùaqZóêû•îÑÞtˆð®m mÕ¼ БÝUs¼²á„¹ ZàøþZŸ‚8:[Dsù´l®E4'‡ÙO¦sÂðo&àóŠ ­µ´‚ú¶†Å©ùVfÖ9)ç¤Büþ·ŽÚˆîÔIÿj\l”ÔÝGõ»RqÆð•YPñݦÏÉb=},yŒüa"­¡6'ŸVå¤e')A¢Mß;~¶æ%v×F4î;©½-œ®š7àŒ‡%&8¼tdgƒÏôF Z]{ü©»Äq¼™‡7/rÜHY’ý—×¢.}¡îôñj­¥LF±¯[C¼a™ýÈîZ\{ùN-¦ÔJêÎã›ç¥8ycœù@;pŸ_÷¶N7Æoî€H£ÍÄpªœèª¢’¼Š²ƒfo!³Ü÷†¼­ßìÿî‚fÀ®ƒéÉo~Éþ¿-ÈS™Ä)ý Þ|_*Fã^GŽýž #ò ö4LJ? ‡¡üÛoq˜@¢Èv~x#Ž…¶h» Ž@·ñDýéSÅÍ”îO”ï­òÒm/ð…7Â<ƒÝÝ£¼,oWÉV3N3Š/šcM¶Oo`å}Ê©«ðS¾ñ­så-Àݺ0‹0Dæ<ç5%æšð¦ørÐSbv\Ú¸ïò²íäoÈÅØé³›“¾üŒ­®e§îRôùÿ‘—~Áùéµ§ŸP”WP";‘Q&hY–òK8R[UQU\ßXï!l/¯ˆuý`RRó;`þÝØˆ“UFÑ¡RÒxãOKñKñµù, 4Ÿ Ñ$%¥¦)+•Ù{)Ûí{}»ŠB«"•GSN'N<¤®ŒÍK6Fƒ7gÆCèÇ gÕyÚì„þþ(FAF°±T dÓþ¨´,3;¿0+«ew»Úhyij½~UmQµ‘U{ûå,+ Íz½º¹†ª–G2óª>L—©…ýý[™å™Þ½ÜŒ¯–K~¼£MR¼ÕO¿ãqm0«ï?nŠš {@êX2ønD×Õ¦+ׄîà-ì2¥ŸßJø¤TÀzö—JeÕòk‹ö¸€Ÿ½cÓ«i­güˆ%S-èÝõl™ÂÂjðj÷¯‹:‘rÎÀɪº œÏÍ576V_˜¤C È'fÀƒbMa2õ .I•–ºf¡Ý¢¯S =䌂‚ü‚*ËnM¨ÖCã{,»ß½¦}ãw„·‹ ݺ*2lÇÍ~Ë+w]F-Ô54h,é–¡>y†¢âÒjsM½±þö»²Hþ© JŒ·<5µè«u­ún8f9à i²ØO¼Œ%‰ø¥¸äS‹èܨçj¡‚B㪉Òz©ŸÓeš‚œÝÇÚ…mŒÜä¼F…Al¡ZŸ«3åB#W]âÑâ{Fø+´¾U}W‰ ìòkJO\ÑSßÔJˆÿ%Ú5àé ¢Fò’dgY): üìJÙ]Àš‡ÜxÞ˜mm}£Äz¨0dðürëçðóÿÕU( endstream endobj 708 0 obj <> stream xÚÅW pS×¹¾²qÆX/b-O‡K'•1OÌÓæ;a Åe¾N}¸5ü"¾Cœ—ž®¼9x%îÏ ® ðòÄŸ$Â9²°Ì°|ùʸåËWÄKrJó2ÒEÑKŽ.~áÅ×,‹^±|ù‹Ñ¯ˆ…yGSŽEoK) Å)øOvô.ÉÑ aAiô’ÿä¬{þùâââ¸q~œ$/ý»K—Egˆ¢w ó…yEÂÔèÍ’cÑÛSÄÂèiìqÓk¼DœSX Ì‹Þ&IæÃ(#㈠ÄFb3çub±“³‡H O‡åa¥øb!K,&–ˈ8b%±ŠX‹ßÇ;6›‰×ˆ-ÄVb;ññ&±‹H$v{ˆýÄSa‡ÇÛNrV‡aç¸}á²ÇRx/ÌàÌð’KHëã¯<Þ7sÛ,Þ,DÃì¤Ùƒ‘+#»æì›óÁ\£Dï"8hârQÑ5~SYƒ$]œ!.¨+jïíèî "'Ó €Æ[P_€Ãüîm¾ÅWŠ4ê×€,¯„R™jit‡bÑL4ãw4üxÇ™ÕnD¶Ü}î’ïîx—%)ö¯ìÁ«@­ A]ée™œ½@z’wÇ¿3ù¹VÄÒì^ö—ü20€Â.°Y½¨K€6ð.ž¯Yú‹Y.9Y IN€3™ô>mz¤«<´%¢ ”/£l ý7`üÔÄA ¿äýöú–GCbûÒ¦gvoX·ïy Y.ïa(dää LÈXèæ ¡ŸòÁ»a+Ï¥¡BW¢¯0ê *Г²j°R^0Y­µg‘D`²™m`!=2ÐQ`ÔiŠJ7ä—|ȵ¼k¨ÚÑí€NÌÀ\ŠpÙFƒò´™F¹@ê;U&»¹® ½)ðVB95•Â+—ã(\Á(4•¡(¤ì·§zq ¬Ò9èËàñ±Ñˆ˜*øŽ<Äã}P³+‹™Q¥“Jw)Ò ‡\ôߺú¿wWË@OÉÀ ×ËK¶gKŽYPé¡Ág6×XmÇÁ2úö5’q5ühÞ8ªy`\7x0 m/ëσL(ƒ#%/'§% w)ɼW˜\ÞÎAÇ‘dœ;9ÿÏf—œRƒÑ¨RÜ)È<›è9ˆ½f.ÎÎbIb~.öèÐìLAƒf´âÉe«—­xy}÷ï)h²5ZjÁl2™¬V€ƒÖt¥{Ùã›TÛ´ª Ì–*gs»¯Ùj?±õ}-ö7ô"Ñ<4†8™1”(µ­k|Ý'HõöÂùÁî}Öº1ž‰Q¯/ÀGñaØhª(7XM¶zœ€®Â†É8]ÌþÀD«gÔê2Yà$›šÒ–è÷ded?Th.ã°2@®,×*Y×Tº —QëŒí7LQîêÅ%JÕ§g‰Ä1:)Ö¹\ô X4–J“ƲTØ õšJV7µ ïUýƶwLQ^œôNµUE‹„Á½øFm¨0«éQ0©M9S¬ÀTÔÍaw£.Æ&hÒ›ŠAíƒ('örއi¨la·pPØ—Q13ù8ñÍ`%ëdîrÌk¡J#Qøs{±+a]f³±ì³±®Ó—`ôd}ƒ;¹'oN@à£Î×ç9E­¼¼®¤lKéžL KÔµ-48qùÉ×ëùÊŒï7Èý{54œê@a5ý­WOžò²sšÆždÔ+0®ìi\(mwæË(‚‹.L>÷x±êð(Íe†…JÔ¨0BYP¡º1P))PTõâ©…M¾^ åäšÑÿ…xhZŠÿ:áÒ&j7:¬R“†©HþÙù~ú]}õ·m~W¯ÙrüæhN’ó°VCÃÞ,–”e‹ÖîÏÌ€Ôs{Ž…Dp™¢/ø:Ò®Á€ µrç†u…8}÷e÷_§aØÿyïµ·N~ªaÄP—š¬5AGkÓUÕjŽx•ÇÎgcØØ•gÖN} ÷Þî¿ò•ÓQ¹ Ùc2ÿ½5A7ØÉ þe:¡¬´3CÞDÆ!.’¢Rþá´£×;Ñî< äqáЫ±ì3ϱ[Øð«[~þ ÚG°÷ªâ'=Ø¡³öioáŸ@«>³xm‹±+a+¯cSZÐk-ÌÓø¾pÌòk)[ åRm‰¼)7„© ØH–b—F']Â%ÕרÑ^´F ߯-ÎÊdeWŠ rm2«ÅÔâ…·È©»¤T\!L.¿C!¼w³î]²%a.¶½2ÍÅ-ÌÅØ[ˆ[7ÐñîØ@W«u4胶ó—êÝ¿äÿ¿¥¬4xzY4uK «ÀS–Ž”ºeõTì-UÕ#`v ¹G<§=î!GGMMW×ìwfbßq˜YvHžiÐ@™Ø/ú´-®ª~0cé5EŠtÉ: \%3µÑÐ\ÝéhôB\8O¾st`•Éy¢4OÀ!àß¾ÍAó/ ]æ¢÷'¹üZy]Q~~Qž¤Iãnilj¦ª§ øëð:{“;àísÝp÷'g“»êÉdtZ–ÆÆ*åÕ` ,6kuUkÛo.érðÀ˜¯..; ŠhJËSôJU‘2Šÿž¼o‡ÜiraN†îçOs¤%K½Šªl~ÏY[½÷ŒÅëèòMØÛ¬žöÓÍÍÿ¯m†ýBQ’êÂáöûòSv+O [ŽàN—W\*,UìÂ’ÉBc*Xm~ÿíú¾v k]ÊlŠ4¹F]<;$øû°ÍU-gúÚ[»«;€ìð¤¡T#ÖË‚í3Dóôt> þÄCRrn–òí´Ö”oôCfÝ-.ãCíüOßøÑó쿱ßb°ÿwaÃ'h>îÆ±hźY/_”Ü|‡†ÿ—ã]çOuãÊïI•Q Ë;´9kÿ¬” o¬l`žÅ”¬ºËEµho®Es>;´CƒT¬Ð惜,®‘×·65†4%RoÀÑôüŒÊã¢J6/ÔÛxEŸà¸æP¼Ÿƒ"®q‘YÄÿ÷ÕúÓr¤¨iGÊÊB]Y*»\°:4Çáïúg¼ìµ¥ :8xñ‹³(Öå `X“ ɦ”Dl`•eæ?yr$3ö€ÐÆ—¹ŒŸy2ä|6ÒWá’RY Ê6(7²ƒuΑï¿ä^Ýilègšntßw6YÝàÿÇõ˜W)V—dç(Ž@2¹ôfñ jú껇j’{Ë»¾IùSÿæ ãŽËhÕ).Ìãüs9žò¢œ¢< f­C‰®â$ÖÈÎØ®=ßJÁɆë=¿r6~¸ ìÈÇF.…ƒÝâ€dX×€ç¼u§Ð'#¸]hƒíbýôÕi«™nÓ´•A™R-ÙÀŽGíß‹[¸öí¶†¶wå]T=ôXz;3Ù¥vAäxUoÙLxª#ýåÕ¥e™•ûvgœ£P|Œˆ¦ûdda#ïF¦ÚF›âž˜91«ÅAÍ _ãxœáÎû_I9ÓB endstream endobj 709 0 obj <> stream xÚ]PÁj…0¼ç+öøJ)KK A(¾ |}T…^c²Ú@MBŒÿ¾&Ê£ôev3;ÌlRTçJ+ÉÕÑ ‡Aiép6‹=ŽJšTÂ]¬bâ–$EÍí…OI]w×K{_Ôï_4}èÚ’>ƒÄa§´«EÈŽ¾:7ëìqªô`€1|nгw+œÞ¤éñ.Ì>œD§ô§®hâ¤Y¬ýÁ µ‡”äy”£»'a$Ζ t\HXšæÀÊ2'¨å¿¿Ç}£Ä7w„=f–Qšoøå~8Ý5vP ¹o±ÅâÜæ''& ¦”ÆÛý¬±a+¾_$=r endstream endobj 711 0 obj <> stream xÚe‘mL[UÇïöÞ;lq[h(æÒ^37èðGÜpˆ²"Œa˜/ ¥½[ZZÚ ]aNØ ”{. Ø-Ëd` ËŒ‘/“™Åšùi&J4Ùt1sdñå ó-9§œÒxîCðÃ}îóüϽ¿çÿ<0:È´Ûëj÷?UißӴæ)%!ៀ ÿ8qVŸ`ð“oMÃyé8[—Ë0 {“Ýj±y#Œ…ÝÏ›#ó–¢òêF)ÔõÛÂRKÐᔼÒ!YÜOƒžÃî•\“[äUùA®É>kU§E¨ÃçsÈ›,‘.O(àuDA¿«Ã)?¨l¶§ m¶âJ rÿo1ßY î(--Ù&Ûl¥â.¥:m¢Ý!»% ätxÅ¿Ó#É1ÿÍ^YQQ8.tøB…þàኂmbØ#»Å}RH vJ.±Šk>I\ÞXáò«Òï tÈRP´û]R°.'ýy}ÓТ`( ‚!0Ìd¤1€Ñ1¯0#Ì- ‚aJs§-¤Ûq4sÑ2ŸO,Œœ… éXM0ÁŸ>B ¨ m>{ZUá(?®¨AK7KZ _Aê!Éã“»¹vU™²\g§TuÒº’•âLÿ=Ç»9ˆò*P=iE<”mWÙ #ª2–¿kš-šj¼¸†×@Ù« Du*Û4¡ªãV8ª¨ýCÞñÊ«oý꺾 çy TÔ€¥† (J»•Z‚$ÿ&©G­„[ÂYÉ|&DêÈKdã±^E^V•IË9yÕSƒë‘"`|^`o?ĉ k'+£“›P3‘‘€:Qî稢 žêkÌ•s°$B\d/{ŽkݵéÏŸ ûú•­Ÿ–ÃbþÿíTañ¼=Š\h/ÏÄ´ÛÐ6Ñk«úâÍ?\·Âwá]—¯mF=ãUÒŒd"N’ûi$ƒ§úÚK›Iýr1wàÒä´‰ d͉^eöçôÄà¨%1ÇÞAƒú |±ºö¹¶î¾ªɃ|r'‹îá]#±Á!8œ‡õTŒü€÷™±È"¢®“sä5~‚}Ó/Íi†¼ÖLA?!,FçÝŸW€ û‹æ&dDßS¸kËã/Î×ÙWÐNöSú=¿ù€Òß˃pèäéä¡Ä&3¾Ì¢Çà/ïÄâ'æ»~<0ÑýÍÁKe´1¢Kz´°2T”è)% À<¹ä6'Ï%ÿî}öAey LA·D;ǽ!PmÇÐötA÷•f'Αïg×­‹×¸¯/^FfK\ ¡FåL¿]cM]ã^m=HÌ–Fܱò¡ û_ }WN¸Ìð+È7›1ûÈ̈Á@£%Cñ6 ;Yÿ…' endstream endobj 713 0 obj <> stream xÚz\SWûÿÀÍu¡o…Ö÷^Ü­Zë¨V­uk Šu ÔŠ"{…@ {%Oa@ CëVœ8‚Ú¬ÚÚjm«mmÕÖ¾'öÐÿïÂ0ô­¿Á'\>w=ç™ßçù" ¬­)@`»aÙÒ?^7i‰‹«ë´©æ+3Ó°Ü´çÅJÓ”i¤Àô¯~&ÎÊ4Âú_%¨FŽÔÏCÌÇûCÍÇQäðf»e-02˜:uÆ”©S§/ ‰ûzûHßÜñ–ã´9sÞ›ì8}êÔ9Ž‹½Ä¾;¶9ºl—øxn—“ÇuÁ;|½$QŽoÎó‘HBæ¾óŽT*²=0lJ°Ø{þ[“¥¾ǵ^a^⯎˃ƒ$Ž«¶z9v+=¥ûÏ’àÀp‰—ØÑ%x§—8ˆhk5ªß¸¹Û‰‚ý(+Êš¢)!ÅPý©Ô@j5˜²¥†PC©a”%¢†S,õ5‚²§¨×©7¨‘Ô¿(Žâ)Gj5šC¥ÆQã© Ô›Ô[ÔDj5™z›šB½CM¥¦QÓ©Ô»ÔLjõ5›šCÍ¥Þ§æQPó©ÔBj1µ„ZJ-£–SRQN”3µ‚ZI¹P«¨©ÕÔj-µŽr¥ÖS(7êj#µ‰ÚLm¡¶Rµ% Ê»Q ‚mS¿‹V¶V›¬ôÖ.ÖÖ_Zÿiã`³Î¦Üæ ½™~"t~Éø3§úÏê¦ÿ‹.4¾8q`å qƒŠ7¸Ýv¥í±!‹†œ:hè–¡ß›:Ìh·ÀNg‡Eå× ήbw¿6赦ÓG”Ž@öÓìýí«írè yy}ËëWߘð†r¤ïÈ»ÿšó¯zîm.gùLþªãRǦQ¢QûF=úË1þcž•ýzœç¸´ñýÇÛ“»:Ó(­ù<±BWLmìiϬÄDÏ´ øfãw2ÜUž°3ÃSZE°2s3ögœQ]QQÊ: §™ÎBk}xEppxxppE¸^_Q¡çlÑmtLð_TìŦŸîüd…‚L—ÙÌc¾¹± Añ™EØÃ^%ËŒÐC5d—©4 Z‹¶ýÏOØ‚nGãÛÑh­ É´ÉÊÔ½Ç~I6AS“ÄñNtosÜrÁ‹.FÂìæ°|8@Z2N†Û}åÕùtœøø4A!ÿ9…ÇÛl²\ø”ŽÁC ”LTq´Žk€ÌºŒÂRdkÿÛ«n0ø5ôû[—±´íì64º ¥·¡1m‚¦Ö¶Ö?ȯ•iÉ‹alV~F6ä0e2” ƒäÈÔ8\ó×2û´E*$3‘¥1å\ä”e0è»ßÙ».lܸkõ¢EÍ«Oœh¾pƒ{w)Y{øpymaayˆ‡GdH×›n±·v¶nÞäµf៮;Þ²ïüÍî'õ‡”Õ•zzDÇñ¶ñtÝ€^3ôFuëÝVdO´zÏD³ tI5Ô7„A ÿ-C`@hø¥~3C6ÄêJä (Ê{ã:FŠ­Ùœ˜r¿bIÅÎìDMØ® Þ©r`Ü.Õòp¼ ðØ)ÆÕE ¶ OìbWD&ô£)…ýjW³§_ThXˆVRÏå@¶*˜,HLá!2}ɼ­I© ©ÃDiäÅU‘g;G÷"ŒTÂ"£•Éi= %ÉYQ…xèÝ­È5<Ù‡xôú¥9YPÂä¦jCƒð6ló8ÀNkÚxzñÍuUÀÔdksù^Y{Vè9ºÀ¸õω ×¶†#N‘&ñ +HÎNG³± Ïg˜° óø©²„¤T1IjiuÚ†ìQgû@aZ‚]BC.]ÓÚ]5Ùcég¢ÿ‡Ž 5kðÝ¥mß^“¹Àh‹ÊJxÐÄå)Tb͇»C‹uÁ¾0§(ʉåu;8hGó‰ÕÒv+tU±h´¥ñh4†.„&RXqƒG _ÖÇÐqàÓD.äl1O©ÁÃtvh ¿â2‰gS&+sÙ—–• RFV­i|võ3ìüÔc‡$Ðß«N¼›SCŽ*'ƒäCU» Õ4ÕÊ4‡(aÑàš¥ªm éìЭ6¶9°ÆßK°«>´q_uCg;[÷B¢œ7M¶2¹¿Â攪€äfWµ†C²,%û×rûä%@U­å* §D]ÄÒ2å'ŒèS’FAè<‹VC#p?l=¿ŽñªgxꇬŸ ×‘3‡}p.û3€ÞDã¿Þ¸Þþž€ßtÆ> :L¶†gÄŸ©$‹.“â.…ê@.RâRã¼f¹ÅG*b” fÄe©%\9PÞÇtÎ*Œ ƒ€Àj(áQ–¥ §ÒféÁ©›¨Îhõùy61)%äL@5”rè!½;'¯‘¯–C…¯Ds8‘¾pò盇ö_j=z¾aРñ7±-0oά]úx®R£ç 0µ(1§ä豆³ÀÜùjë –mZãäjöʸˆÜ v‡;>î@!ÆFÑc“ºÇ¶îÕŸƒ3ÌÅŸc!´lór¿j¹¶[XqJ~zfCÃ5Èæê owe>!áþ¡b…·bmš ˆýF0©”;Jÿzò£5«Ö­œÊï€ù¡Ç²³sÔ eª"µbI¸Ìúã5hñÝÃGœè1\ÛrÁ©ž4¢ ¦þZA];·ZíCélb,(H>ùå%7p(S.´ÅyYœç‚¨[–³Ðszwr®/L‡Aª2VÊà÷;‰Ñ3üLHlo½‹8ši°;Õ±Áˆ”FÑ¿Q½ÉõdÏps¿K¾”†+h¿äD— £@ÒÈ•AVvn~mã2¢?ïYìüþÒßãƒaEnðÙììÜbg¤4B˜¸söÝeÈ ûõ²âDÿ~:ÿ<€3û¾¹ Í1ØþÉ;ÜŒ¤€†’¶TŒFýxç>ìÒøìTò“QLX™´¦Z«©oñ>3‘äçëx0vçDÏq²^ü+ür BôŒÜ™ÜÀ-ÚÝ“AŽøë ;[¤…Z©V¨eUÀ‰Ac”9 émmO|yûôG‹f:­]BtÒ™š ‚ÃÆs¤,›Ž±x^é‹C÷cäàפÑÔqÙ¨½.hË22 ˜1»‡ÃßÒ)¥QŒ/„GòÛ…‘¾§ Êõ]vfÐV’cFW#ª$ÑcT‚:ÙÅ.GZOµÿúÖ¹Ínk]<ó_°ßÔisÌY·ð@<è½ys9X{tãס$£F¬X ™‰f aÈîáýÇÜt¾°HÇÌÃìl§V£áü¥ž[¹j¹ÓºÙ]ÝsNj&î5ºu Ø[$±Ç¢6ýàÍIÞªˆÒ¬ìl5h˜ª(m¨Xè_¶ '`>„,°‰ø¥`+ãdl5~6q8}:"þ}| NiŽ`ðØ,vî†ÏoÜ»Öúô’Ri_á' ¥R!5+×õkgsfCN(3YÿËðëâX‚9]ïšAvØê ¢§¯~]ôhu§5»Þ+R–”’.O&-Ó ¾?ŸAÖŸ6zy‡ûk|Z8ÛVÉCÛ»«M1lANQ.é;•‘…1\"¤+剸ÞaŸ˜›D¦¼ØÜøüdô=ö²/NÌT’z/-/¬ä¡œ\ÏÁû‘“½-rk¿Ó.Øgrµ2¹ 'lánã»@Îã_iù.ã»Íã9žÌ7“;~f€ÿ“Žó#wš¡˜ï«ÍZœ<µY(J*HÈÁß#/ÒíÒU‰ÀÄDÆIH·#דÑ~ìdÉ!>Ù¬¢ƒ¤<®”˃LUqÓ5'£ß vmGŸLûæsAïG),+=÷èd]isœbšÅ÷° µÉi•L׋ù©êjý±œOyö©¡áq‘ xÜû0v0;!v}¾zqs>^Ìþs”N1œ4 zrný¡-#ƒÚXS›ž\æÌûÎ3± Ø>÷FËÏÑ¢+€bðR<Å#ðGøCd‹・çêôÁÀGC:$$øø{Åûƒ©‰ˆB£Ñ[OŸýÆëáHBå*f¾ÆnÙ~ñÖÝ£g9¼fî\÷µÛÌmèw2ÞÔšü¬Ñt›MÜ'W@4ôƒ;uör@Š">%%b™ÀÐpÏè²*oRðæ+·A³èÊ16ÞR¬UPÆ?£55PÏCQj~\vJf8Ȉ:KLᬊ¾‚6ØÞÜ©P„ÁÜ=~0"™q³ÁÞ% †ÑßU¸øyú;MäÇÒh}0{¹âð)hc®¯ºƒ­8AËCÉÐJ_Û)§EÏCè1Yµ†dRÒÈæbÇ-Œ›¯Ì-gœp!‹E(qôwõ‹Ý7í\ý.ßÓ½÷ÑÕ‹V¦ÈÞ–dVLV¤"Vì§ßªý„èËbë®~¾‘¿è5Ä|ßñ`wÄó‰ÄŠ ä·æ†y3uæh"zëÞüE8»µxnftFL=0M Óv5x¹ApLjʌVMˆíѵ„¯è”‡Ó/Ï'FÜGŽh&zw&šˆx,ì<Æšä? ‘M+vÀ î¿ÁVf‰(Ü€< vh„ñˆq‹Qôçchfâ»}GO£r˱V(êDáh„Ðbšö@E9÷¨çvŒ'Gæ¤Ø@wã®NË]6¤äûrýi™ÙÛf©õ]!ó3ÏŒh$YÚ -@z¤_)s$òC™¯9Ì¢éîN¹_'L±ô_7ÚŒÁ3 è°A°ÏˆjHKY¼ØªJh¨ö’—Rþ ‡­7mÙÌÜ$á' ·¿ùíß—$LeD«ãjz¢xaW°# 5^æëS¿£d; ó ±ø ì„WþN*i Ök+™pv[ô2O÷ŒÈÇÌH’V[í«H5vÇ>Èýïw_ÕrqŸÑc å)1IQ!¶HúÛ]º'‹P$ñø sPt )¯†.G쳄QrLõ9ß×ç9ÊìQópx­-'vL"‚êéÒê^‡:YÞ»Ó9…ž5'5’K‚ÍT“•• ¥/箕ŸmyÒqûÌ\Z­V¨ýÉ¢ÉÈÕf¯ŽÈ !>Ã,. °–”%öÆå6¨¼BØ¥Œ˜˜4¡{-swÕÁ˳'ôËg‘ýõ'£H¦ÍË’¿Ù}_A¼"+M­Ì`z}#0¢âžåĪVº¸¶×êY7wÊwYÎLƒz‹D :’±ÒR$)Bs¸Ç  Ú[Q5±ìɆóN J b”t±¨P¡N¨!¨ëºã¥ƒF¾S.ôè‘|§;tàÏ›BU‚­—±kVl®¤È+;YT˜\EPœ›[œ©þ© O3ªÎPú•/Ë…foЉëH‰¥ÉC{Í}ÔŠ"ˆrkM_°q»e™!À|Ø' ͉öòì>™d VÑhegz‘O©²ê 3÷ñ&uµePÕ7]ƒ•tZ¶Q-I3×9¡'-Ð%"Âu!È­¬¨E9ìIxÎ ëâNÄ„{pÚàjÁÑ¢ …wà&4%–¸n…° \`iüúøu¡Ó¡k`_i@$- œ)Hç"…¹ æúƒG=ÀBKú€P§¼Ð!Ö’ß´Inýýó¡å6l[>‰Xbž€þÝWý÷1Ï–h œµto|ERQÔžä¢ÃeeMy·Õgàs8ÊüÓ8®¡@¥Ž==!#-7®J b GkXzHõ gOÂU8­ðUþñ¢³Ú‡Ðúèç¼OàCXØK*—m¾gŸX¢TI‰§åQÉCª*=3ÕL¡6ö`ª'ãv£Ö(ŠASIA?<¼zó&÷5Sù%4rõg?k.7ÀæûwÀËþoÀâG‹Nܢˡƒ+" ¶ƒ3–ûkõ1{€¹TõÙ¾FsKK -MÈ$)vEÃÑÓ\‚ÜÄʸ:‰N^ÐÃxíN]A¥W¼®ˆ¡TËêS¾•»ŒÛ¶Õó¸`Ø”µ£v{mÚAe™R£,óÆÜvxl/Œq=aÎêâ¼Æý†˜ËÀ æ‹û<\ö>Wä¹?$çƒ2FôtnÙöB¯&8æp²åø5 €’·Õ™á)Ú^ì¶ïÆnÂÆ¢“=›Öº“HX-œ7‹‡Ž:}ƈe)KŠÓ{k¤ÆˆŒÈ¾3í_ÑŠÞ ý’’üøÅ—wN#‡N¹›ÐÄ‹þ£'™ô¦Å›Ò (Û'Oñ´£“›ÛçSÿæÐõfè{ÕS¿ÒxȽwž<¹÷ ál“t¦=A™IÖ-» KÍïŒë~EMü||!vCä‚ämJ:µ)M“Ø<Ñä`ßô'÷‡ujò½J¡jÉXœ×ÌùˆôÒAIie &Kôå¼>éD{àï“V%»)ƒÉ")—· MJub¥„ОBBxzò¼%Õ…à!d+˓ϸ™íûô¼yÝȯ‡<^EÑ©Íö©‚BpÈ-äk3sΠجýŒŠÎr?ƒ£TŠq äûUÝÔ¹}&w+t}Í"$±©°ù˜nX«„J~)?·ÑVö ä‹[+i4‡“¡Icn1ë÷n1a ᢠ¿â 6’ð¿ß2¯ éÛl É9Æê,–õ,_Uüh/?9ÍNÐ9TUXTèMÞÄlð ±ðÕ=­è]è¢Ñ¼…hÚe:Äæ—€ò™=áÉá{¯ÈÍ!¾Ó• #D1ÁÁ·Ê9ó6…¹=´ÌzK°^h;Ûðb 1BL$üb0kHœºw"þZ! P'ìáSŸaeò‹1tŸ}14üÅ;lj~’&©,:Ї¤¬„Ìt÷¯í³r£+€Ñ–hÊxÈMËOW3½kÊIÅ}1Ší*1óXñÒ“ÿƒ'÷9wêÖÝÖä¯ki ½¦§l\N ¡0fœ˜ŠmìeIIiÍ$çûWqY VæüÑfÿǪâÄ â*‡ªüÆ4‰Yq9ŒíäÞÁÉÿ͆`ŠÁÕ€¦žìηu £(ÂÔ¯‘­8®ÜŒ¾7ŒÛ!!;)“AÂkëïâ±ÛÆÁâ@]LWúå¡åûf4.‹1+¤CÈ€lº†yµQ$CsMö,rÅfs¤SMK!‚Œ¤ÚjNÔr`û¡ÄF‚¤‚Ç?!2ý—Q¼H¶Ü£|¼ÑúºðÂùÓ—nœ_üî¤eÎË>ð¹ÜÌ2ÑWÁu# ë Ɇ¬>R¸HP$KSb#·,fÖ’öŽë‘½¡ûy•O¹¼ ˜*¦îúpÇ ?Æ#gàA?ŽCvˆßó‹¦Ç¡W»ôßÛ£ÿŸ'Xoïç®÷⢜w7©é؃§Ó¢¿:ÏÒmÅ“&cú`âÄŒV8X«¯c¿õRá:÷Ùó—~|­ãçö+í—[Ö¹v™1ò"nœ5¢*’ÜóÐ:VW͈^ñ ~ œ4°$Û§ãücªÍFòQ”žþÉúÄ`2,<ó=£ºÈ_¿p¶³çíCÚ hIß•ÆÇ÷¬ÚD³È¶OmØ£o}õ\ZÞÎ&me©þâûóþü­ïr&»Ì2ÉSÜ6¾Ïø]eÁ•ñd‰ºˆ;{m½hWw>Òˆ\Ÿž_ó…èßñHŽ–²ë·;}îðáSgnÙ°ÖÃßæÃf*öIZ€yxý Ò0ëë¢õºÂª¬"•:¤29Mea]edÃz>6)·úÆø”oæí¥ IOܦñ+‰dD˜ŠI ‡@ð)çÅ-r'CI<3óù*4 ÞöÍQ'>©ÍÙ^1 ˜etÄBR†_âŠã‹•ZÈ€¬Œâ¬| Ä—Ø æ¡,¯±Q[]š×é@60Ócá¶ ]¼´+̃œ+‰Ìt”}úÉ¡yÜGàîÉ U¯Èj¹Gö>ƒ.îþ=Ð2úÉ}'OÌaéÎn›Éz»ÏStwÜn?±C^O–ÉdÒfz½xF÷ „ nÃûÌÇ-M‹žš¯ø'Ž4nLDï@#ÌŸ›¬_ ŸN¿Œ9z­óm¢Á+Ô'Ä+€T{ÄeÈ2T™Äw9Œ^¢‰„G-ø q{Ñ Ëœè‘é·W¬×Iö#“ý~”Ë¢!HhÓÔ‡ÂMéCfh< O¶AÏ»êlAÕ–Nù¦>Û‡SoºMsƒòî}š.åXÄüÏüüï¶v…è5B0Ù>çwúTÈk=Ñp5ØnEÍÑm$0cõRˆÆß2œà6¡wDODïw«Þ<úP(jé8pì@eq´3‡åÂÈÞ°ßüÛCÿë#©„Õ!z:ž±Á;e{º¶ÒD·ý!PμԳ+UE_ÔÎ6BÉŽ¿CTÛÿœ¢#ÿ‡ôD2º«D_õÔ@ Ÿ3¢jR!Þ(€P)¿bkl=åM< ‹~šŒú¡~?ýŒì8¼Ïd¹Ü|ôÕ+×¾¸ìóÏû}R‘^Ž»vÓœ9‹œÛ,„O™šÆ†Ÿ¸o¡803TÝÐCAŒ½ $M®HöÐy@$±ú}ÉoÞyýPNHKÒ7±°ÙµËo*·Öˆo¥–¥„öС‰Ýl(JU…Í-Þ§zéßçEOáwÌêü³»Räªá7­Àì‚é¤ÅæN4»O;C¿œõæ¼ki>÷q:=éª÷õ·u”ÎÇOÍ)]Ö&H€™§ª{úu[oÚG¢?Y•¿Ê€éÛ®IQÿ³]û’ŒŸ67ÎìnäPå?¡çÑ“Œa×9Qä8߬glÓN¡›A•)ÄÊ´˜ØPßÇ„þ–àèi,À7±Ý´Ñÿ퉗PWO#!~Tè«8”C%ì&Âuh‘Y¥¦x+ÓV³|3 ƒ( 騰.–PηÐñI%V{4î@Ô¥ôBb"!ž˜˜K“ã†NÚ´tofK5ï}]õüEÜ‘%É”í‡ý™Wf¨¾¯*ά ä%Û­÷ÏJ*Œ.#Ô¥2K³*zPEPkò5÷˜E„Øìï³Õ¿—>Ôò‹Æ/xjSÓ;qâþ–Ͳý4€ßÄCñL›–«¨ï¾Pÿ=Ò‡Ø÷²rïå;èž¾%8tïqûì»+%*9ÀÌ$ËuÉåSPr_×7 4_d%€” ω¹z+dJPeçBSU&‰Ž ݾgG ÷Ž û¬‚^‡´Ñ®íÛ¬NKÚ¢¦‡à<ê&8[-§eñÜ!U¦Ct7Á1 ¡+Ô„:–0ç-Ç W˜):aþôö+ Õ°?3·lßýŒ&`ÔZuUƒ9–ÄFÏP¦ÀFf¦ ÁdÞ1Þ²JR)Ò”°À*e>_£D‚ôŒõ ž+$Ó’û© ƒ’³ÉÇ!yÑP'V%òxd&ì…ÍBuú×úƒÕ%»UÕLaêþFÄ‹7Ø—_€økÐò…‡ÿTö z8âV·¹fe–0ѤŽBËÓH 9ÑÏÁd•%þ‡$ëü[ ÁË…d°ðÆã]*Tƒ†¿?iKn«ÔpôÌ!Ñ®doéޒ㪪nëëÃT |˜ ÷ËP´2¶¦84ÈùŠÝ=ô›è;““éK¶TVÃÅCJjrJ`phŒœFR^lal‘Tç !#‰–Ê‚Â!Љ)‰)å @£®××”C>ä&ÅÅj#ö@-èK+5Ú’º (clã LKòЂGå Œ ƒ æXGêoªþÿ2"G endstream endobj 715 0 obj <> stream xÚcd`aa`ddäõ ˆˆÔvöõõ4 ØNûÝ'Ãrógëi†2Œ?d™~È1ÿg‘{èÅòŸ‡I–á½ ˆ|Ã"_€Hu Áx@ˆ…‘‘£´ªÓÀÀXÏÀÀÈ9¿ ²(3=£DA#YSÁÐÒÒ\GÁÈÀÀRÁ17µ(391OÁ7±$#57±ÈÉQÎOÎL-©TаÉ())°Ò×///×KÌ-ÖË/J·ÓÔQ(Ï,ÉPJ-N-*KMQpËÏ+QðKÌMU»]L:çç”–¤)øæ§¤åÅ$ü˜YÎüèàû9µqõñÕŒ?–Ýdþ¾óû;Ѷë®óR»S» K*³‹’êúÛ9¦´O‘›ÝÝ3iÂìù·¯^Ýͱ¾;©Q¾»º1¹%¿¥ 1©­´¥¨µ°¥¨%¿>²»•£tNÃ\¹¹Ýs¦OžÕ;qʺ ó>•˜´´îÄESÖ®;°aÃüyÛVìæ8ÝQ!ß P×ZÕRÝ]ű3ýЇ½ß%övM¯”«íîjk­¨K Œèæ¨hžµ@¾{þ¤9SÌÚ´ã;k÷aŽ»¾kíå"»½«½m8øÊüpž:mÚ÷‚l¿¦²Ëq±˜ÏçáœÄÃÕÃýŽë÷º~žïEÔ£¹Ø endstream endobj 716 0 obj <> stream xÚ]PÁjÃ0 ½û+tì(ÃI cé9´s Ûѱ•ÔÐØÆqùûÕnèa ôôž¤'Z·ÇÖèôË[É1À ò8ÛÅK„GmH^€Ò2lUÊrŽÐú$ÜYL´;üTÕ¾>ñß÷×K×äo px0ºÕ![Ýù:œZ3X`ŒÐïûÀ9øv•²=¾DìÓ+ôÚŒ°»Ô> stream xÚcd`aa`ddä ñsptÔvö Ž´ Øæþó—aYøs>ëY†rŒ?ä™~(0ÿg‘{èÅòŸ‡I–¨JH2üá‘ß@¤:Hxƒ##¯HcÛÔ‚¢ÌÜÔÔœÔÜÔ¼c=#çü‚Ê¢ÌôŒdMCKKs#KÇÜÔ¢ÌäÄ<ßÄ’ŒÔÜÄ 'G!8?93µ¤RAÃ&£¤¤ÀJ_¿¼¼\/1·X/¿(ÝNSG¡<³$C!(µ8µ¨,5EÁ-?¯DÁ/17Uì=0霟[PZ’Z¤à›Ÿ’Z”t"“ƒjgì``fddq[ù£ƒïû–- ~Îg\õ½ùûÜy¢fôOêžÊ±&wa¾\rwCF{íoá?ÎíõÝÝ]ÝM;§vÌmîíîíîëžØ=ißÏïß;AˆñÉ.æ7¿—‹Î^ؽhQiwµüŸ ¶ßå¿s|ý®ÓÍñÝ’ .ñÛ†í·ÇoÕß ¿~;Wû-ÿÝ]þ» ’¼%Ûoîß_ë¾Ësð/þi¿€í·Ütv9.æiªÿy8'ñpõðpïäÚɽs.ó~(g8¯Q endstream endobj 720 0 obj <> stream xÚ¥Y T×¶­¶éêRA-ÅøREâðÕ¨A1£â,aÒˆ¨82ÍÔm3Ï pšy»™Qq 5hœÛ[yjbp|¾¤ÆRã¨ñÔj25•šF}LÙRÓ©™Ô'Ô,êSj.5šO-¢SK¨¥Ô2j9µ‚ZIÙS_R”#åD9S.Ô*j5õµ†r¥ÖRnÔ:j=µxa7€QÈ[¨'¢¢‰"ÑnÑð_bñC³¯ÌZ%£%õ’ûô:>&.­b¤Ì:æÚÀ‘½™ JÔ3xÁàgæ…æ? qÒ9äW‹-š‡ê=ôºåDK••³ÕÙac†e·î4üň #*Ø!¬’½52häÅQÓFeX[[—ž?ºÜâ3͹Z„èÄÂʵ,T$å%çcëGˆƒ_àŽF[säÀ΃ÇZòsó ¡˜)JS‡rr˜½ê«OÖ~=–Àв)W¦t.¾ç¼ ˜† ¡í\>䫲TŒÒÜlÅÂl¤a‹÷Aû>HàñU:Ñ|¼Û¡„·ƒéábtïÛÔèèÓÚÚÞÐÒÊõgé¬0E,l~cÎT€ ò™ÚÈò(.’#Ó“ð·¿-²N‰LHeäÕ±U\Vå3‰Z´¢ã:ÔF2JҜƣQØ K&à÷°=vúBfHò ½‡ì9€sØ/I¤ãÐøkÿèî¾6ÃãñÀ/ˆZÖþL+•döªp—-‡†@.R’Ó⃖z†zîŒÍTd@0£,N¨ãÀ~M­šéýx†4&  œG¹ty´¶…A ?ƒÖLÔŠN=Cy:ñÕ‹lJjj*Ä2 PÁ¡é¶Â‚Ý|“´j}|`{(‡ô×G‘YÏ®Úö½ÝWá' žø-¶Ä?ÿüSÏÖ¤ru}e3š”üôÜÊÇëOónÓ,–º:{èvh‘›VtëY_%èûúðÒu«]fña° Çï8ÓÁYVV‘JYÃìRjÂ"ä±þ3Ÿ¯FVhä£'/8¸ïxf£æÖ©ü+ÐÀÜ]pKðЕ–×DíÚ¥Q×sP¸³8=¿­A yÀÜ8âãÁCH¼‡WxXtTæÆ^J}ŠHåIÀk­ÀŒvŸïCÀ&ÇClgd9qû8¤çLÇ…@`@_æVÐe$s¡Ë;¿ÖoìÐÏôî”B?NF‡CZfüvÏì¥YˆžKðs©>ìZ-š®}¯C)¼ÐÁ¾[ŒÕ´rŠ7K¥JÛÃUAnnAQóÞ#eÀÜ;¼ôËùË\æðžàV¡èP©¬ó‹TYY%ý™©WªÃ"C¼çÞ_‚$Èê_‘øçy/ñ@.<Ò·*äзyÓ4K+:ñU“œCÏÙr4ºçÁc(„]P“–º3‘Ô›¼RÞÔ ®n>xn<C~‡bwœˆÄ A¢=@CdÆclÆ­u‘¾L žÄBáŽl¨b¾ùæäÝïNÙ/žóåêÅ*Ðg‘¨Ú´¢ÃºN¬„ë²Ò}¡ß\7l‘‚Á&&|Û÷ªvWp9HDhÙ/¯ª«²³ œÑ'„ÃwéÔŠhHÆä‘üfi$ÈÛÛAÓÀñsV‡JI,ÏÑölåÕ#p¹?û6Çæ³çÍá`ÙÕMgcì#íÖÀ\fÒÓ™$äaO{^rð`A—C3¯•]êÜqúD×±;wº6®_ã¼u)/˜Íu8såÂ7çýxÆÙi¥ÃWsyýn³® &’9ª~(>Dµl<>oÆ ˆ™JYž“›“ •Lmt­,T¼©ÕÑh І#7”ˆ©Û°dülâ–¤g:2ãŽÀ×¥‡˜D4™U¥fÅ–XµzÝüÏݴݯŸîæ®Âî5•k³ÒTiªt@•ä'3à„ùX=7¡¥F~Ä$(üÙIë”FðQˆÏEˆb‹òË @ÃìR”Ær1‰øö²NHIL%(Ë’ ÒQ´ÎßY©¦J]^˃:¾0)ïAË­-КÛwo‹Ú…µbÁ½d‹÷õ‚8¿¤ã¼ÀÛg/óè5žÂ–í‡}í¾ÈcNô% »ÊxSoV¡:¶¤ 8Ô Ž+LÉÅ=(Ð:5;E• L”2V΃²4¹(íÁË­ñQì²cgJDޝ‰/çr!7+/‹!¥û\+X©E‚ŸÝ°©ÍI…þÀ$Ñþ”’„õVYGѱ¡¤€ë¡‚G"õ)À×<— i´fªÄOñ–EFbŒ¢±šÉb+ºIÛдœýŒŠÎ’¹«RõÛ¢P-Z§õè\'¾$ 6ÖÀ|}¯"Œ~w‡2iDŸ{r—‡s>×§ïºSß|:Ó},æð0\Æ¢uÈBz_íäº|2ÿx‹BÑéýÆ%[Ü}VÏæû[Ç:vG,D¾å{¤%ÄøË«77¸ƒGb1þ^W ø}d$=ß¿Ø I|:CFX òaF"0ÓçüJ:ʤï_ÿÀ×ÀÃäjl™¾ €i‡Úê¾Î¢Ðоӡ"øœiHš^Åv“5Øõ€Kv8¡Ñ‚yD­¹6ù%ÜÒœz;ºhçõ˜l¸¬¬^þŒÛÖ¯ì8ð, ­ØÔ¸ã`fufE¦Ú¯¯O+yÌJc!´•«ÂÒ|¢"´‰Dý!¦ûÇÇ<´&Úïulc±oÁöÜE•ñ9›‹}÷Âa¦óرk’Bù´œðœàÊÌŠß“Q½Yé?ý•lõ'ô0J/žüøÒwOºU¯bÔXØKŒ…½N\z½Û­C±jëˆÙ&“º¶¦cBûK¦ ?¦Ç9¸­]ëpê5‡7Iÿâ­ç4¶ê±}õªç ²âLÈGp"¶ÕÆ­?0ª4¼ÌÑ[¦x2tÊgd%»Àhêû+ò#!©i4Ÿ–àå&ÚýwXYN[|¦}3†ì'Óï÷f Kêí~lO$§øó¿­”$ïæ=m|6ù͘w+Iй76l_6É*£ØüÛ<ÙäÞÞÀléz%ûT+úZ׿|´—ýÖù[l³i,”ÕDÕU´ä糫ˆºdî pâñçØz#Lb\w|É•ÀèÚ_çßmÀ4ê™HŸÓXØ‘ùŒÝu–@~»§Ò7z3ìÆÅ£í¯v#K2‘/kÑ€¾"Vé‹X¸bð{ÑÍý@+ PPs-Áû£Š_¾ pð¬WØŒßÛ¢ýd nvî\ç…ëç–2Ã~Å¢%^?Åé7¸ªÝÔ¡ gbÁ‰XMl¡‚‹‡8HV¤ÆFo[ ̧ˮ?:Ùò+ÁWBYf¨3T™ªälÿ†$‚ݵºáöx؈íœð˜™ØâŸ‰ÛòS9oô}wŸï¢?óO¡ÕžµkI!Š?ú[á¡'#Š?•{÷2A}ˆ»cœ:¶Ðvh$ëºyîÂe.×õh¯Þ:Â͵/ ö2BNè[TDTÃ\´ŠU×À>ÄØÿ³ØbÊx<[þ2@ïy\§‘#Š6Y±úK¢ WÁìÝÊŒê2[}ÿÒþoàÜ”¿°C»´Èœ€Æž$¿PÀ¢FoðÀ£ô­ ªf.;T£¦º¾¬õâˆ?wëÇüú¤}%£ò%îš`Òv›Œ%2¶À‘—ÑÜ '/£µ—EZrѵ^#ßKl ñ/%;†`"±$¹pg)”B”ä6Ķ$·ó\wëG=Ë4F××””g•©òÂ4)eÀÔVWÕ5(ZÖòrØ’æ# ©ò/&t5ÕnÑL|J«"’c’“nÓ„de,ß¶ÓžŒ¾3ÿíL´ö°_ÏÿHêÏdÜ$e×míèêêè8y²c««ëÖ­ëx^Â>F"øÌséÖ “ìࡽõàÉœ¾4{‹RýI£#ìOŽÌá6¦hï})ý#h[L*íS“3Fvô?ïìéì,‹pápD  ­M6E‚ápîý,êënZá,Û(¯ ‘ËCBjåµµvÆ#¢Ip¶0Ù´Ëx¢»tŸ‹X©vé͆lI,Ò?5¼Uoø];Ù;‘†ðó ó—‘jŽƒ4ˆUÅd‘y¢ s@a0Šð˜Àùÿ‚hü>4è/,2d¤aR‚0ŠÈC(ŸEƒ‘™d‘ô°­±/·Ñx +A?V¯4‚êx¯ÂÝb¶ÆÐÜoÓwo‘Ø'JõÚ¨‰ %ÈÜh>ˆþ½|ì¯Qü)mŸ4¹dâÝÈþƒ/®|GnI-lÀ“­Cf%ú§+I.R›”§Ân¸"Þºœ$9/«47¿Êâj”~qŒL¿8R/)r3šHäè}ü‹µ*#'2!S>/V¦ð”%†gäW[gì /"\êÙ²õº.6ýð6K:ÔB¼Ü„~cËJAÿO’v9(9ÜcOÜãI=J”b-îŒ#‚ G¨9ôÆ ­/¿ÊðÆ…R‹ÄbaqZXLãÈ<©vn°ÖÜ\g>„db>P¨ñßJuO endstream endobj 576 0 obj <> stream xÚÝ\ëÛ8’ÿ¾¿m‚Åtóý8,Èc³wØÉ&;ÉÎ!Û·:ñÛnØî™ÌU¬’ES¢£$‡;à`X¢%òWïb‘²í‚R¸àD0p Byç(´ópNÂØ$\”ÂZgxkü¬…WÎF‰g+B‚þÑ‹÷\ "9¼…’8¡”…+@Ei…KR(°¡…²Ø9Á-g€z²À…ÆŒ p[E$”4R¥ä” ‘‚ðR ­"6”Ð:`C m|‚†Úà úiçPå=ö±B`ÛK/tî<ÑÉ[hDa$Hì¥F^Ia Èí•‚ðë•ô^a\ÀQ 2ïP?V˜€W@“‘a¤IAB# +öqÂ*àǃ$V ‡·ŒxP8ð¯PñÈŒ† Nƒ:aD€û^[„Át –²€®¡¡áàµG#Y*r¢AqÎGT<4@ç xá<ØE¡Q\VÖ¢µ7¢µpØQ„6AF¥»9” È(ì§ÒL8 o #*èçQù µlŒB(îCÜD×y´›7è#Ú>x0©7Ð9à'ïh‘1xg~Ð){Dïó€|…Ê.€²:³} ˆ«ÀôÁ8΢Eí$‚Cû§Ñ}¤Ù}Àš!»(8ä B@d ÃcÀ>@"‚yP~@³jà0$`ʃ2£Ù5è(*ô>€ˆ üüQD Ú•ˆhP [G[ID ªÕ@""?&bLi쌮ê!£ D ˆ "Å€fŠ1#‰¤Ðp+ó>’¤°P’Ȇ7"a¤Cˆ¤ÁhØM㬜ŒG B|Àp C1¨’65&aXhHɃ6LNÀÊa1•¼kQJŒJí€gƒ[c6ó`1ha¬æ±mê9*L;H üMàÈ„˜^$z¶MŽÆœrfHY[€e%d]ØuÙ)á¤à4æ9œ&J. ô† BA~…ø݃kœ† ¦‰-Ì>A§<5Áüv óÅU9ï@r è5!&¼‹ýô†ä-L¶^4| ³&‡™úϾ|³:¬»GWÝAì‹Cw×m/ŸÀ«Ë¿nßl/Ÿ?2áñ÷ß_¾^ìàVžô¤øñòïݧCžjáÃ÷ßÿáÝwݡ۵áâÜë]÷«pyþ>b‡ûíb·Z¼_wmèÔ†v%t¬¡Ÿm7ûÃn±ÚœQâ JðTƒ¿zÿ_Ýò°úõ ãïÛØ±À—«°¯¶ës¸Ë6n*qÕH!»å/mÜ›&.±Øãê÷ùj¿^üÞFîÚȪD6#ÏÛõnÛÀ·m`]󿁦íÌV¶QË@‰£@yÞ¼{Xv]«KÜX:oÅÅÝâfµù n‡…¸ÝmïÄjsÿp$Q› `fØ—TF!òÏÝêp¤rØŠíáI͉„–" VõbµÛŽþ°Ø9¼|¶}"ß™†FÖ¼ê íkñ%ÎDLÉ•””:’R± eN?3Ì`£=¦ƒí¦ÕŸh­ŒÏ4ŠÏ'ûýêÆàvÝr»»©ÑNÒl*c'bçj½ZvçÀÒ‰ÊàIcu¯îî×g¡mè2‚Ò(‚^.»Õ§sÐïÛÐåL“üÈ'w‹Íþ~»ïnÄÝg©,ÛTF<ã<›¡Þ¯·Ë_j¤Px ë•<8ì=ÐÕNÂÔJLáË=æ$õ¦rNKé‹=ævŒù,f4\1Õy| Óðd'ÛÈ©DV™æa½ØÃV-lf´ÇÖg<æðy2ºMF•dÌ„ï‡T¿ÝwÖØ¦­ÛÕZÛ)oJ§ŒƒS2w½Sú†Sެðr{Ó­3½š’+)ÉÒýÃtª?É¿eaŠëËŠìO{ÔÛþáövõ©«s¿;™°N`ã‰O¹qmwwEèåÃ._.ÖÝæìXÝÕ£+S<£õÐa¢&ýµÛå9wù µ¤ªz‡`þ=K'LÐa'ð%ÑxŽhI S¬¸¨‰Æ6Ñ‘pÏa‹Í ß>lòŒ8²Ká=çì|ñó.Á^ÐË:ž’¯ÞRù"nvPïjâ‹yJ?P#¯þôôÉÕ_΢½Ÿ@#6U™ZÔ(H_=úì,ò²\f5Ê&/¿úÇg¡oÚÐzº#œ‘!SaHUÄ6sÕÒ6 YFвS‹ ôØ;L-{ñÛêðQ|Xßï·ëš®ç•}]#kuûånu®*~ƒzøÐm ÖP‰||½ÛÖáË™Š1{£€øk·év7â‡×â~·]buñfY‡·WÀl–2¼Õ(¼_ïw‹5Òí_Ÿ×>-R í—yº½ç`² Y÷o«›ý;â†æ¡ØJúèýTßã.;ŸŸ5Ÿûñ–ÏŽÏžÏ=’ÃG2^OP1žb<ÅxŠñ˜#¥¯Æ>9¤âˆT¤©J¯J7ãßUñO~\h¶_°¾SÃ54Eèh éºÈñeª’³S#Ù™B¬¬n „Ù¾@¹ž®™Ï®§8e)ÊR­ÁnÒo;§YÅ©‘9‹âšêLµ( u:3Á5Ôéül×@H³â9NçÅS‚rlNÞÊ…a:äü¬8A+ÎЊRt¾%2ïÝ û*,Œš ‹ æÒL0Öa°³Ê*€Mµ˜¡eS4Ïb'LųГ¹+Ú¹$b•»Ì¹YA×â“'ð©¢üòÐT<“+ž Uèçr}LÅ­`…'½>uô®Þó;¶ol%-ãkEùi„$g#4rE2sR#W$?ÁÍ‹tS¦ÞØÛ·/kÙ÷’\¾O±iªBÔ²ˆá”A-«ÑÄ©ÈÖÒÎâRs¡¡e˜d2ÍÆ¬ã2M2IuÊ ­’‡¦ÊæzŒàf#Øys*Ë’ «U¿21ó÷Ä+¯R¸ºÓ\Í1k¤p®À´š*ƒ´n…Íõ¥téTá¶ßÝx§ûõa5 7—•{ 3`)ú'ÍI¥"iô\’4k$í¤™¦ ®´Óndâl„0Ïl‘Â5¯Bµñ_îFš‹u}\ózÍNW5Ú¶R‰­r¶²`g#¹ƒ×ÃÚNæ›fcV¹Ã†£Ÿq%¥ÝÔœ®]“íª¾Ö®šÓítzra6àÌ‚…%Ã:N.Î}…Wðv…æ mûär¶RUiº*àß×ý¼–ðÃBØeŠ~2¨}+¨]Ô¾ j§'•ïÝlÀFPû8azƒK7ËãBóÊ'KàtÉE¿æíÓ uÞlÑajA C«®q¦f°Z¸éTÚ,½Ç€ÓKCõ\„ؘÓcÓòu2ŽC}¥c¿'89“6‹Ð1f5“:?«ÞgéȰ¼·¥ãÌ|â\ßëÐ Ä;yU¬nVÇ®®Ê†êÚ¼¡Ê›^5fœ*uM–£¦YßÖ€FNOJ¦YÐŽÌWÄ"—ìšwuê7•uƒÖÜàRÍÎôºÈ(9!5Ì\ÕBµò‡—5‚k ¤ÙqÞÉÌÓ~*ï\¾<’ ܆·K o2k_ºræâƒ#½÷»žß±ft+új‹Áèc"„6 ¬§¶²³1«Íl¬ÖMÿ¼d²:7f6Ûuuî'§Ó¬ÎÇ€v^àúrÇ÷ª ?/2¼1ÆL›¥Yê{W³3]˜f=B(VzÆN-¿Œu³±ªå—?î¡~e&>×4h8]mÐé\îÜlÀ™kn_T¶†×ÆÍ\sŸxCÿhËcÃå±*<à*Lª©™ÈêdêªJ“jjVÄ#@?]™f oˆ7(ŽZ™ÜÇ/öwkC–.²_" _¡¸ˆ÷\ö:½gÄŽ<ÆFöq&{)«;›Ú8vî[="Óu¨éˆ¤Ñ£)Ž|Ž;ïrŒF 2‡üCIŠìAø\2)Ï÷ùZKíÀÑ…za|G4ñÇ©Ø?ÊB(}d¯4CX ¬¢ y4D߃ÕDWõ 4…ÍtìM=LN…&§Rzy—ئ6‰2Š#<œhu°è©ž©ûè«)´]—‡•¸Nµs–N9vÜ/Ž@HÞÐ"½Œ½-?[Ô˜\œ6­—Q é7û}:>zU¼À–£ǨÐÙyRH9ÑKü›NI>ûŽ’ù”$B ó7èL¯æÊ?LޓӔs‰»Ó´Ämð7˜¢œb©è*II)¿ÿDÚãQÇž8ÕŒ—Î4ß¡±$cnƒœÏžs¼Äo-`Ýv&OúW^©rÒÉ|–I9ÉXJ­>ô¾B<ËãÉ$›5j½Ìïá“‘ˆ9\£ÏÃU.TkÒ ‡ŒÇÓ¶ŠÉ=L?ÚûÙl$œHàlÿGŠ®ãÉXóñDf£0ßMÑÖQ5cHçÉ%v_y”Óu€Bü*£Gè……`m‰^‰bD ¹@È›”1>¸‹”ÿC2ߎT $a>wÜŽ&aÈàÓ£ÆÕ{&«è»Zýd=Hí,F@þ«ÌxVèC<)²x•ôÁWéJ2{ }±ÀB¢6÷¶C<Žd§6óÒÏ''E,õè‚úF¿) €a¢æš‡Q¥AÙ>³ƒ¤/kRžI¨¬ô\”Ë“²Ì³úØ—çQ#•ðuAÑÎ:¡ïêo½Jļê6éYˆ6œyE'ô˜ˆÿ3!©ès’x´Ël,òb_¦Ô åÄ‹„O ‹W t©`¹ŸE‚Ï`)‰ú.|óŒtY>g ÿTµeºu2ÞÚcƵ!D‘¹ðL žÑã9¨/Y²©ÓÅ’I)W@‰9ЧÐçq!@mñ-GÂ9É÷àAyÙg5eõ„3™2[ÀçÞ´…¹Cã·d _‘É#õO4‡#P„×£·¤fÞ ¿…‘‘[![Åw¾©t†>`1 Þ'1»“ó}‹Éˆ¸¡v>âr b,ήº(„\­øu¸îíbÊ‘ B†lÌ2…ã¼·›tg—Ë:KëÙ@ÅîpEž\+Ǭë˜Ý¥T¡³’ås^=jfÂ#»<æÊèìqŽr”<.׋‹”PUÎv˜ù-EùéÿûûÿLZ\A-0Ï‚1s…†‹ÌÂò¹“Õ'ÙèÕßi÷87¦<Êÿ=}^÷3_l7‡Ë«‡÷ü€WÔå›íO›Õr{Óau”7÷þ¹º9|Üç¿ ¢-ÃÝþðìãb¡YFm-/Ÿ.ö]F|ñöÕÛ—?ÿéÙË««§?+™É<çßÓmwù¯{N¿FqÚáòÙâþ߻ՇÈ¿öòÉ~™÷l¡‰}ºü¿ðá?‹õjùdóaÝ yyuèîÞâE._¬ò—”#ÒOqóõ;È™ßé¼7€ÿ,åu¾÷bµî`iÃzƒWpã³– bµRÙQA±Rõ…‚Tôä{ýÓfx¸> stream xÚµ˜Én9†ïy ÞM³¸6 €Ë‘c+ZÚŽ¤`ŠÓ°8–a)ÀÌÛO±µ˜dS:H_ öB²úÓ_­#”(ŠÍa:'DŠ—’HÍà.ðR‘\i|“å€×8%ñ9ÞáÕ8W(üc)®ñŽ! í$;0ø\sJgà€Ç;@·Ïí@û#Lá#°ã^œ–;‹N¥¬"â ì,p\LsI¸Ï WÕÊŠp-0:¼Ë µw4pF) ·³pÀŒ`ð«•}Òà I‰ÐãA"ל|øÿ>•Yý¸í•›ÛçÕÓvýœu—OŸÊÕÝý–(#²öæ¶|Ü í;vÜ#³Ávù°ºm?Þ=”„fÓmùó†h•õ–w¢ª5;õ?ßZ¸c‹áÞÁíÿ®õW%'Jüµ&Õáòg™µÇŸG×ó÷Ý«éôÇïܳé¯ï[{aï@öuõc{;áGWK¬ž7Ûîýòd—Ëýd妬æ†7Åçñnq|t%\'ØóTD:Ô'RbP !TˆGÅ üu*Åúúqu»þQâ*¬ZåȉœÀÅ$^0M;‹Y¿‡»M€Ö)ÉdJ9%e"”P©•v€R+êc>&7ðtJÒ§¤J®˜P5GJÅb^\Lìo2aR¿‰!QP Ä_Tì1¡ºw˜4u8¡Ý´ŒBNè`DkésÒ>'/ôtP¹Ê„r®žè ©Ù¸{6˜âvYŒ”N'¥Þ$(Àˆv¨˜b ]\RíeJÔde¨Ë‹?——a!.vÂ¥¦ÝY{|ŽÛƒ®üO矧.•ÇÔ…•h‹Epñ ÝøÓq —NånÏ;‹ªEÝ“m*«¢uJí³J0ÛõzHXÐç¹ac|ÿ";â endstream endobj 741 0 obj <]/Size 742/W[1 3 2]/Filter/FlateDecode/Length 1679>> stream xÚ5×gl•×Çñó{l†1`À°Á,›a³·Ùà0mFÀ&ì=BXa™ö2&l1˜°gfo\¬VQ^ä©:¢*R[©R¥¤RÚ*Mª¶éõ÷üyóÑá{]®¯Ï9÷Ø9ç~þ9pAŽ»‰ŸcGüVF ä\¬ss1.ògUãÈl'f£°šœºÚ3b6›^ƒ`Fc5¬Žþ™šƒµ°6ÖÁºøÆb=ŒÃxLÀD¬ 0 b#lŒÉØS°)6Ãæ˜ŠirÑ?ØOׂŸ® ã–˜Ž­°5¶Á¶Ø30Ûcìˆ0 ³±3úÿ¥+vÃîØ{b/ì}°/öÃþ˜ƒp ÂÁ8‡â0Ž#0߯‘8 GËÅü×>“1|&þ½Åq˜‡ù8'àDœ„ïàdœ‚XˆSñ]œ†ÓqÎÄY8çà\œ'[iïp>ï°'k2ýêZÀ¸.Æb&`}L’KL²×YÈëô¢7’K~b}½·\ú¿­,¦ôáÉd¹Ì™Ö—ÐûËeÅYYJÉ‘ëžaå=ʹ~­­,£ ”X`å}ŠÿÝ-ǸWÉ ój«yr(ï$›ÉåoµÙ˜&WXÇÊŠÿí¯Åur³–ÙìzfýzØ€Er‹’mv#³cä–Ÿ³ò!e¬\Ñ›óaeœÜ¶/¬|DÉ“Û÷w+›)~µlÁ­rGOØì6f'Ê•¾ù4¶SüZÚ;å.äÚì.f'Ë]¯ee7eŠ\ù+{(~¥íÅb¹§ûmv³~í•à~¹×gmöcfýj<€ñ–ûr„=y„'gÉýz•£”Ùr_Y9F‰¬Þ?ýhå8e¾Ü_ó­|BYÈøž”ûþ_6û)³‹—â)¹ŸJlö4³K$ýÑJů¢3ø™T;ÓfÏ2»BJ`åe¥”ü••ó”URz´• ”5Œ/â%)£¹Í^fv­”ÝÊÊÊ:©o+W)륜ÑV®QŠ_ÇÒÅ6ë¿¿6I£²­øïµÍŒoám)ïÍ*ºÃìiê!+å”­Ò¼T+w)Û¥¥¬Ü£ìV[¹OÙ)mœ`åe—´ãVRvKÅ¥VQöIæ[yLÙÏø >•޳ÙgÌúÕõ_HeÝlö%³¥KßYyE9,ÝÂÇø_ã3|Ž/ð%¾Â ô'­?mü_ORTFuûSÔŸœÑèOKBúS±&ú“Пcþ ôçž?ëR0ëc=ŒÃxLÀDl‚ 0 b#lŒÉØÓ°6ÇTlþ/£–˜Ž­° fb[l‡ØoàhìŠYØûa7ì}qŽÂÁ8‡c.ú›s>âxœ„8§â4œsÐ߯ ¿«ûÛ~1úÛµ¿û»®¿Qû›ðô÷UËÝ‹þ¶ya úçïoþfxý Ðß²JÑßÁΠ¿]Uÿg[Q·$&Øø¶‚e6¾£ ÝUßé>±R® ë7U%ïk+wŒo[U¦]³rOÁô?T•U¿´r_Áj^g×?¬. % % GLPK is free software: you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % GLPK 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 General Public % License for more details. % % You should have received a copy of the GNU General Public License % along with GLPK. If not, see . %*********************************************************************** \documentclass[11pt]{report} \usepackage{amssymb} \usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, urlcolor=blue]{hyperref} \usepackage{indentfirst} \setlength{\textwidth}{6.5in} \setlength{\textheight}{8.5in} \setlength{\oddsidemargin}{0in} \setlength{\topmargin}{0in} \setlength{\headheight}{0in} \setlength{\headsep}{0in} \setlength{\footskip}{0.5in} \setlength{\parindent}{16pt} \setlength{\parskip}{5pt} \setlength{\topsep}{0pt} \setlength{\partopsep}{0pt} \setlength{\itemsep}{\parskip} \setlength{\parsep}{0pt} \setlength{\leftmargini}{\parindent} \renewcommand{\labelitemi}{---} \def\para#1{\noindent{\bf#1}} \renewcommand\contentsname{\sf\bfseries Contents} \renewcommand\chaptername{\sf\bfseries Chapter} \renewcommand\appendixname{\sf\bfseries Appendix} \begin{document} \thispagestyle{empty} \begin{center} \vspace*{1.5in} \begin{huge} \sf\bfseries Modeling Language GNU MathProg \end{huge} \vspace{0.5in} \begin{LARGE} \sf Language Reference \end{LARGE} \vspace{0.5in} \begin{LARGE} \sf for GLPK Version 4.50 \end{LARGE} \vspace{0.5in} \begin{Large} \sf (DRAFT, May 2013) \end{Large} \end{center} \newpage \vspace*{1in} \vfill \noindent The GLPK package is part of the GNU Project released under the aegis of GNU. \noindent Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All rights reserved. \noindent Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. \noindent Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. \noindent Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. \noindent Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage {\setlength{\parskip}{0pt} \tableofcontents } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Introduction} {\it GNU MathProg} is a modeling language intended for describing linear mathematical programming models.\footnote{The GNU MathProg language is a subset of the AMPL language. Its GLPK implementation is mainly based on the paper: {\it Robert Fourer}, {\it David M. Gay}, and {\it Brian W. Kernighan}, ``A Modeling Language for Mathematical Programming.'' {\it Management Science} 36 (1990), pp.~519-54.} Model descriptions written in the GNU MathProg language consist of a set of statements and data blocks constructed by the user from the language elements described in this document. In a process called {\it translation}, a program called the {\it model translator} analyzes the model description and translates it into internal data structures, which may be then used either for generating mathematical programming problem instance or directly by a program called the {\it solver} to obtain numeric solution of the problem. \section{Linear programming problem} \label{problem} In MathProg the linear programming (LP) problem is stated as follows: \medskip \noindent\hspace{1in}minimize (or maximize) $$z=c_1x_1+c_2x_2+\dots+c_nx_n+c_0\eqno(1.1)$$ \noindent\hspace{1in}subject to linear constraints $$ \begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l} L_1&\leq&a_{11}x_1&+&a_{12}x_2&+\dots+&a_{1n}x_n&\leq&U_1\\ L_2&\leq&a_{21}x_1&+&a_{22}x_2&+\dots+&a_{2n}x_n&\leq&U_2\\ \multicolumn{9}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ L_m&\leq&a_{m1}x_1&+&a_{m2}x_2&+\dots+&a_{mn}x_n&\leq&U_m\\ \end{array}\eqno(1.2) $$ \noindent\hspace{1in}and bounds of variables $$ \begin{array}{l@{\ }c@{\ }c@{\ }c@{\ }l} l_1&\leq&x_1&\leq&u_1\\ l_2&\leq&x_2&\leq&u_2\\ \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\ l_n&\leq&x_n&\leq&u_n\\ \end{array}\eqno(1.3) $$ \newpage \noindent where $x_1$, $x_2$, \dots, $x_n$ are variables; $z$ is the objective function; $c_1$, $c_2$, \dots, $c_n$ are objective coefficients; $c_0$ is the constant term (``shift'') of the objective function; $a_{11}$, $a_{12}$, \dots, $a_{mn}$ are constraint coefficients; $L_1$, $L_2$, \dots, $L_m$ are lower constraint bounds; $U_1$, $U_2$, \dots, $U_m$ are upper constraint bounds; $l_1$, $l_2$, \dots, $l_n$ are lower bounds of variables; $u_1$, $u_2$, \dots, $u_n$ are upper bounds of variables. Bounds of variables and constraint bounds can be finite as well as infinite. Besides, lower bounds can be equal to corresponding upper bounds. Thus, the following types of variables and constraints are allowed: \medskip {\def\arraystretch{1.4} \noindent\hspace{54pt} \begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{39.5pt}}l} $-\infty$&$<$&$x$&$<$&$+\infty$&Free (unbounded) variable\\ $l$&$\leq$&$x$&$<$&$+\infty$&Variable with lower bound\\ $-\infty$&$<$&$x$&$\leq$&$u$&Variable with upper bound\\ $l$&$\leq$&$x$&$\leq$&$u$&Double-bounded variable\\ $l$&$=$&$x$&=&$u$&Fixed variable\\ \end{tabular} \noindent\hfil \begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll} $-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Free (unbounded) linear form\\ $L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Inequality constraint ``greater than or equal to''\\ $-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Inequality constraint ``less than or equal to''\\ $L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Double-bounded inequality constraint\\ $L$&$=$&$\sum a_jx_j$&=&$U$&Equality constraint\\ \end{tabular} } \medskip In addition to pure LP problems MathProg also allows mixed integer linear programming (MIP) problems, where some or all variables are restricted to be integer or binary. \section{Model objects} In MathProg the model is described in terms of sets, parameters, variables, constraints, and objectives, which are called {\it model objects}. The user introduces particular model objects using the language statements. Each model object is provided with a symbolic name which uniquely identifies the object and is intended for referencing purposes. Model objects, including sets, can be multidimensional arrays built over indexing sets. Formally, $n$-dimensional array $A$ is the mapping: $$A:\Delta\rightarrow\Xi,\eqno(1.4)$$ where $\Delta\subseteq S_1\times\dots\times S_n$ is a subset of the Cartesian product of indexing sets, $\Xi$ is a set of array members. In MathProg the set $\Delta$ is called the {\it subscript domain}. Its members are $n$-tuples $(i_1,\dots,i_n)$, where $i_1\in S_1$, \dots, $i_n\in S_n$. If $n=0$, the Cartesian product above has exactly one member (namely, 0-tuple), so it is convenient to think scalar objects as 0-dimensional arrays having one member. \newpage The type of array members is determined by the type of corresponding model object as follows: \medskip \noindent\hfil \begin{tabular}{@{}ll@{}} Model object&Array member\\ \hline Set&Elemental plain set\\ Parameter&Number or symbol\\ Variable&Elemental variable\\ Constraint&Elemental constraint\\ Objective&Elemental objective\\ \end{tabular} \medskip In order to refer to a particular object member the object should be provided with {\it subscripts}. For example, if $a$ is a 2-dimensional parameter defined over $I\times J$, a reference to its particular member can be written as $a[i,j]$, where $i\in I$ and $j\in J$. It is understood that scalar objects being 0-dimensional need no subscripts. \section{Structure of model description} It is sometimes desirable to write a model which, at various points, may require different data for each problem instance to be solved using that model. For this reason in MathProg the model description consists of two parts: the {\it model section} and the {\it data section}. The model section is a main part of the model description that contains declarations of model objects and is common for all problems based on the corresponding model. The data section is an optional part of the model description that contains data specific for a particular problem instance. Depending on what is more convenient the model and data sections can be placed either in one file or in two separate files. The latter feature allows having arbitrary number of different data sections to be used with the same model section. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Coding model description} \label{coding} The model description is coded in a plain text format using ASCII character set. Characters valid in the model description are the following: \begin{itemize} \item alphabetic characters:\\ \verb|A B C D E F G H I J K L M N O P Q R S T U V W X Y Z|\\ \verb|a b c d e f g h i j k l m n o p q r s t u v w x y z _| \item numeric characters:\\ \verb|0 1 2 3 4 5 6 7 8 9| \item special characters:\\ \verb?! " # & ' ( ) * + , - . / : ; < = > [ ] ^ { | } ~? \item white-space characters:\\ \verb|SP HT CR NL VT FF| \end{itemize} Within string literals and comments any ASCII characters (except control characters) are valid. White-space characters are non-significant. They can be used freely between lexical units to improve readability of the model description. They are also used to separate lexical units from each other if there is no other way to do that. Syntactically model description is a sequence of lexical units in the following categories: \begin{itemize} \item symbolic names; \item numeric literals; \item string literals; \item keywords; \item delimiters; \item comments. \end{itemize} The lexical units of the language are discussed below. \newpage \section{Symbolic names} A {\it symbolic name} consists of alphabetic and numeric characters, the first of which should be alphabetic. All symbolic names are distinct (case sensitive). \para{Examples} \begin{verbatim} alpha123 This_is_a_name _P123_abc_321 \end{verbatim} Symbolic names are used to identify model objects (sets, parameters, variables, constraints, objectives) and dummy indices. All symbolic names (except names of dummy indices) should be unique, i.e. the model description should have no objects with identical names. Symbolic names of dummy indices should be unique within the scope, where they are valid. \section{Numeric literals} A {\it numeric literal} has the form {\it xx}{\tt E}{\it syy}, where {\it xx} is a number with optional decimal point, {\it s} is the sign {\tt+} or {\tt-}, {\it yy} is a decimal exponent. The letter {\tt E} is case insensitive and can be coded as {\tt e}. \para{Examples} \begin{verbatim} 123 3.14159 56.E+5 .78 123.456e-7 \end{verbatim} Numeric literals are used to represent numeric quantities. They have obvious fixed meaning. \section{String literals} A {\it string literal} is a sequence of arbitrary characters enclosed either in single quotes or in double quotes. Both these forms are equivalent. If a single quote is part of a string literal enclosed in single quotes, it should be coded twice. Analogously, if a double quote is part of a string literal enclosed in double quotes, it should be coded twice. \para{Examples} \begin{verbatim} 'This is a string' "This is another string" 'That''s all' """Hello there,"" said the captain." \end{verbatim} String literals are used to represent symbolic quantities. \section{Keywords} A {\it keyword} is a sequence of alphabetic characters and possibly some special characters. All keywords fall into two categories: {\it reserved keywords}, which cannot be used as symbolic names, and {\it non-reserved keywords}, which are recognized by context and therefore can be used as symbolic names. The reserved keywords are the following: \noindent\hfil \begin{tabular}{@{}p{.7in}p{.7in}p{.7in}p{.7in}@{}} {\tt and}&{\tt else}&{\tt mod}&{\tt union}\\ {\tt by}&{\tt if}&{\tt not}&{\tt within}\\ {\tt cross}&{\tt in}&{\tt or}\\ {\tt diff}&{\tt inter}&{\tt symdiff}\\ {\tt div}&{\tt less}&{\tt then}\\ \end{tabular} Non-reserved keywords are described in following sections. All the keywords have fixed meaning, which will be explained on discussion of corresponding syntactic constructions, where the keywords are used. \section{Delimiters} A {\it delimiter} is either a single special character or a sequence of two special characters as follows: \noindent\hfil \begin{tabular}{@{}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in} p{.3in}p{.3in}@{}} {\tt+}&{\tt**}&{\tt<=}&{\tt>}&{\tt\&\&}&{\tt:}&{\tt|}&{\tt[}& {\tt>>}\\ {\tt-}&{\tt\textasciicircum}&{\tt=}&{\tt<>}&{\tt||}&{\tt;}& {\tt\char126}&{\tt]}&{\tt<-}\\ {\tt*}&{\tt\&}&{\tt==}&{\tt!=}&{\tt.}&{\tt:=}&{\tt(}&{\tt\{}\\ {\tt/}&{\tt<}&{\tt>=}&{\tt!}&{\tt,}&{\tt..}&{\tt)}&{\tt\}}\\ \end{tabular} If the delimiter consists of two characters, there should be no spaces between the characters. All the delimiters have fixed meaning, which will be explained on discussion corresponding syntactic constructions, where the delimiters are used. \section{Comments} For documenting purposes the model description can be provided with {\it comments}, which may have two different forms. The first form is a {\it single-line comment}, which begins with the character {\tt\#} and extends until end of line. The second form is a {\it comment sequence}, which is a sequence of any characters enclosed within {\tt/*} and {\tt*/}. \para{Examples} \begin{verbatim} param n := 10; # This is a comment /* This is another comment */ \end{verbatim} Comments are ignored by the model translator and can appear anywhere in the model description, where white-space characters are allowed. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \chapter{Expressions} An {\it expression} is a rule for computing a value. In model description expressions are used as constituents of certain statements. In general case expressions consist of operands and operators. Depending on the type of the resultant value all expressions fall into the following categories: \vspace*{-8pt} \begin{itemize} \item numeric expressions; \item symbolic expressions; \item indexing expressions; \item set expressions; \item logical expressions; \item linear expressions. \end{itemize} \vspace*{-8pt} \section{Numeric expressions} A {\it numeric expression} is a rule for computing a single numeric value represented as a floating-point number. The primary numeric expression may be a numeric literal, dummy index, unsubscripted parameter, subscripted parameter, built-in function reference, iterated numeric expression, conditional numeric expression, or another numeric expression enclosed in parentheses. \para{Examples} \noindent \begin{tabular}{@{}ll@{}} \verb|1.23 |&(numeric literal)\\ \verb|j|&(dummy index)\\ \verb|time|&(unsubscripted parameter)\\ \verb|a['May 2003',j+1]|&(subscripted parameter)\\ \verb|abs(b[i,j])|&(function reference)\\ \end{tabular} \newpage \noindent \begin{tabular}{@{}ll@{}} \verb|sum{i in S diff T} alpha[i] * b[i,j]|&(iterated expression)\\ \verb|if i in I then 2 * p else q[i+1]|&(conditional expression)\\ \verb|(b[i,j] + .5 * c)|&(parenthesized expression)\\ \end{tabular} More general numeric expressions containing two or more primary numeric expressions may be constructed by using certain arithmetic operators. \para{Examples} \begin{verbatim} j+1 2 * a[i-1,j+1] - b[i,j] sum{j in J} a[i,j] * x[j] + sum{k in K} b[i,k] * x[k] (if i in I and p >= 1 then 2 * p else q[i+1]) / (a[i,j] + 1.5) \end{verbatim} \subsection{Numeric literals} If the primary numeric expression is a numeric literal, the resultant value is obvious. \subsection{Dummy indices} If the primary numeric expression is a dummy index, the resultant value is current value assigned to that dummy index. \subsection{Unsubscripted parameters} If the primary numeric expression is an unsubscripted parameter (which should be 0-dimen\-sional), the resultant value is the value of that parameter. \subsection{Subscripted parameters} The primary numeric expression, which refers to a subscripted parameter, has the following syntactic form: $$ \mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}} $$ where {\it name} is the symbolic name of the parameter, $i_1$, $i_2$, \dots, $i_n$ are subscripts. Each subscript should be a numeric or symbolic expression. The number of subscripts in the subscript list should be the same as the dimension of the parameter with which the subscript list is associated. Actual values of subscript expressions are used to identify a particular member of the parameter that determines the resultant value of the primary expression. \newpage \subsection{Function references} In MathProg there exist the following built-in functions which may be used in numeric expressions: \begin{tabular}{@{}p{112pt}p{328pt}@{}} {\tt abs(}$x${\tt)}&$|x|$, absolute value of $x$\\ {\tt atan(}$x${\tt)}&$\arctan x$, principal value of the arc tangent of $x$ (in radians)\\ {\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, principal value of the arc tangent of $y/x$ (in radians). In this case the signs of both arguments $y$ and $x$ are used to determine the quadrant of the resultant value\\ {\tt card(}$X${\tt)}&$|X|$, cardinality (the number of elements) of set $X$\\ {\tt ceil(}$x${\tt)}&$\lceil x\rceil$, smallest integer not less than $x$ (``ceiling of $x$'')\\ {\tt cos(}$x${\tt)}&$\cos x$, cosine of $x$ (in radians)\\ {\tt exp(}$x${\tt)}&$e^x$, base-$e$ exponential of $x$\\ {\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, largest integer not greater than $x$ (``floor of $x$'')\\ {\tt gmtime()}&the number of seconds elapsed since 00:00:00~Jan~1, 1970, Coordinated Universal Time (for details see Section \ref{gmtime}, page \pageref{gmtime})\\ {\tt length(}$s${\tt)}&$|s|$, length of character string $s$\\ {\tt log(}$x${\tt)}&$\log x$, natural logarithm of $x$\\ {\tt log10(}$x${\tt)}&$\log_{10}x$, common (decimal) logarithm of $x$\\ {\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the largest of values $x_1$, $x_2$, \dots, $x_n$\\ {\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the smallest of values $x_1$, $x_2$, \dots, $x_n$\\ {\tt round(}$x${\tt)}&rounding $x$ to nearest integer\\ {\tt round(}$x${\tt,} $n${\tt)}&rounding $x$ to $n$ fractional decimal digits\\ {\tt sin(}$x${\tt)}&$\sin x$, sine of $x$ (in radians)\\ {\tt sqrt(}$x${\tt)}&$\sqrt{x}$, non-negative square root of $x$\\ {\tt str2time(}$s${\tt,} $f${\tt)}&converting character string $s$ to calendar time (for details see Section \ref{str2time}, page \pageref{str2time})\\ {\tt trunc(}$x${\tt)}&truncating $x$ to nearest integer\\ {\tt trunc(}$x${\tt,} $n${\tt)}&truncating $x$ to $n$ fractional decimal digits\\ {\tt Irand224()}&generating pseudo-random integer uniformly distributed in $[0,2^{24})$\\ {\tt Uniform01()}&generating pseudo-random number uniformly distributed in $[0,1)$\\ {\tt Uniform(}$a${\tt,} $b${\tt)}&generating pseudo-random number uniformly distributed in $[a,b)$\\ {\tt Normal01()}&generating Gaussian pseudo-random variate with $\mu=0$ and $\sigma=1$\\ {\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&generating Gaussian pseudo-random variate with given $\mu$ and $\sigma$\\ \end{tabular} Arguments of all built-in functions, except {\tt card}, {\tt length}, and {\tt str2time}, should be numeric expressions. The argument of {\tt card} should be a set expression. The argument of {\tt length} and both arguments of {\tt str2time} should be symbolic expressions. The resultant value of the numeric expression, which is a function reference, is the result of applying the function to its argument(s). Note that each pseudo-random generator function has a latent argument (i.e. some internal state), which is changed whenever the function has been applied. Thus, if the function is applied repeatedly even to identical arguments, due to the side effect different resultant values are always produced. \newpage \subsection{Iterated expressions} \label{itexpr} An {\it iterated numeric expression} is a primary numeric expression, which has the following syntactic form: $$\mbox{\it iterated-operator indexing-expression integrand}$$ where {\it iterated-operator} is the symbolic name of the iterated operator to be performed (see below), {\it indexing-expression} is an indexing expression which introduces dummy indices and controls iterating, {\it integrand} is a numeric expression that participates in the operation. In MathProg there exist four iterated operators, which may be used in numeric expressions: {\def\arraystretch{2} \noindent\hfil \begin{tabular}{@{}lll@{}} {\tt sum}&summation&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta} f(i_1,\dots,i_n)$\\ {\tt prod}&production&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta} f(i_1,\dots,i_n)$\\ {\tt min}&minimum&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta} f(i_1,\dots,i_n)$\\ {\tt max}&maximum&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta} f(i_1,\dots,i_n)$\\ \end{tabular} } \noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in the indexing expression, $\Delta$ is the domain, a set of $n$-tuples specified by the indexing expression which defines particular values assigned to the dummy indices on performing the iterated operation, $f(i_1,\dots,i_n)$ is the integrand, a numeric expression whose resultant value depends on the dummy indices. The resultant value of an iterated numeric expression is the result of applying of the iterated operator to its integrand over all $n$-tuples contained in the domain. \subsection{Conditional expressions} \label{ifthen} A {\it conditional numeric expression} is a primary numeric expression, which has one of the following two syntactic forms: $$ {\def\arraystretch{1.4} \begin{array}{l} \mbox{{\tt if} $b$ {\tt then} $x$ {\tt else} $y$}\\ \mbox{{\tt if} $b$ {\tt then} $x$}\\ \end{array} } $$ where $b$ is an logical expression, $x$ and $y$ are numeric expressions. The resultant value of the conditional expression depends on the value of the logical expression that follows the keyword {\tt if}. If it takes on the value {\it true}, the value of the conditional expression is the value of the expression that follows the keyword {\tt then}. Otherwise, if the logical expression takes on the value {\it false}, the value of the conditional expression is the value of the expression that follows the keyword {\it else}. If the second, reduced form of the conditional expression is used and the logical expression takes on the value {\it false}, the resultant value of the conditional expression is zero. \newpage \subsection{Parenthesized expressions} Any numeric expression may be enclosed in parentheses that syntactically makes it a primary numeric expression. Parentheses may be used in numeric expressions, as in algebra, to specify the desired order in which operations are to be performed. Where parentheses are used, the expression within the parentheses is evaluated before the resultant value is used. The resultant value of the parenthesized expression is the same as the value of the expression enclosed within parentheses. \subsection{Arithmetic operators} In MathProg there exist the following arithmetic operators, which may be used in numeric expressions: \begin{tabular}{@{}ll@{}} {\tt +} $x$&unary plus\\ {\tt -} $x$&unary minus\\ $x$ {\tt +} $y$&addition\\ $x$ {\tt -} $y$&subtraction\\ $x$ {\tt less} $y$&positive difference (if $x1$, the second form should be used. If the first form of the indexing entry is used, the index $i$ can be a dummy index only (see below). If the second form is used, the indices $i_1$, $i_2$, \dots, $i_n$ can be either dummy indices or some numeric or symbolic expressions, where at least one index should be a dummy index. The third, reduced form of the indexing entry has the same effect as if there were $i$ (if $S$ is 1-dimensional) or $i_1$, $i_2$, \dots, $i_n$ (if $S$ is $n$-dimensional) all specified as dummy indices. A {\it dummy index} is an auxiliary model object, which acts like an individual variable. Values assigned to dummy indices are components of $n$-tuples from basic sets, i.e. some numeric and symbolic quantities. For referencing purposes dummy indices can be provided with symbolic names. However, unlike other model objects (sets, parameters, etc.) dummy indices need not be explicitly declared. Each {\it undeclared} symbolic name being used in the indexing position of an indexing entry is recognized as the symbolic name of corresponding dummy index. Symbolic names of dummy indices are valid only within the scope of the indexing expression, where the dummy indices were introduced. Beyond the scope the dummy indices are completely inaccessible, so the same symbolic names may be used for other purposes, in particular, to represent dummy indices in other indexing expressions. The scope of indexing expression, where implicit declarations of dummy indices are valid, depends on the context, in which the indexing expression is used: \vspace*{-8pt} \begin{itemize} \item If the indexing expression is used in iterated operator, its scope extends until the end of the integrand. \item If the indexing expression is used as a primary set expression, its scope extends until the end of that indexing expression. \item If the indexing expression is used to define the subscript domain in declarations of some model objects, its scope extends until the end of the corresponding statement. \end{itemize} \vspace*{-8pt} The indexing mechanism implemented by means of indexing expressions is best explained by some examples discussed below. Let there be given three sets: $$ {\def\arraystretch{1.4} \begin{array}{l} A=\{4,7,9\},\\ B=\{(1,Jan),(1,Feb),(2,Mar),(2,Apr),(3,May),(3,Jun)\},\\ C=\{a,b,c\},\\ \end{array} } $$ where $A$ and $C$ consist of 1-tuples (singlets), $B$ consists of 2-tuples (doublets). Consider the following indexing expression: $$\mbox{{\tt\{i in A, (j,k) in B, l in C\}}}$$ where {\tt i}, {\tt j}, {\tt k}, and {\tt l} are dummy indices. \newpage Although MathProg is not a procedural language, for any indexing expression an equivalent algorithmic description can be given. In particular, the algorithmic description of the indexing expression above could look like follows: \noindent\hfil \begin{tabular}{@{}l@{}} {\bf for all} $i\in A$ {\bf do}\\ \hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ \hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ \hspace{48pt}{\it action};\\ \end{tabular} \noindent where the dummy indices $i$, $j$, $k$, $l$ are consecutively assigned corresponding components of $n$-tuples from the basic sets $A$, $B$, $C$, and {\it action} is some action that depends on the context, where the indexing expression is used. For example, if the action were printing current values of dummy indices, the printout would look like follows: \noindent\hfil \begin{tabular}{@{}llll@{}} $i=4$&$j=1$&$k=Jan$&$l=a$\\ $i=4$&$j=1$&$k=Jan$&$l=b$\\ $i=4$&$j=1$&$k=Jan$&$l=c$\\ $i=4$&$j=1$&$k=Feb$&$l=a$\\ $i=4$&$j=1$&$k=Feb$&$l=b$\\ \multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\ $i=9$&$j=3$&$k=Jun$&$l=b$\\ $i=9$&$j=3$&$k=Jun$&$l=c$\\ \end{tabular} Let the example indexing expression be used in the following iterated operation: $$\mbox{{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}}$$ where {\tt p} is a 4-dimensional numeric parameter or some numeric expression whose resultant value depends on {\tt i}, {\tt j}, {\tt k}, and {\tt l}. In this case the action is summation, so the resultant value of the primary numeric expression is: $$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$ Now let the example indexing expression be used as a primary set expression. In this case the action is gathering all 4-tuples (quadruplets) of the form $(i,j,k,l)$ in one set, so the resultant value of such operation is simply the Cartesian product of the basic sets: $$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$ Note that in this case the same indexing expression might be written in the reduced form: $$\mbox{{\tt\{A, B, C\}}}$$ because the dummy indices $i$, $j$, $k$, and $l$ are not referenced and therefore their symbolic names need not be specified. \newpage Finally, let the example indexing expression be used as the subscript domain in the declaration of a 4-dimensional model object, say, a numeric parameter: $$\mbox{{\tt param p\{i in A, (j,k) in B, l in C\}} \dots {\tt;}}$$ \noindent In this case the action is generating the parameter members, where each member has the form $p[i,j,k,l]$. As was said above, some indices in the second form of indexing entries may be numeric or symbolic expressions, not only dummy indices. In this case resultant values of such expressions play role of some logical conditions to select only that $n$-tuples from the Cartesian product of basic sets that satisfy these conditions. Consider, for example, the following indexing expression: $$\mbox{{\tt\{i in A, (i-1,k) in B, l in C\}}}$$ where {\tt i}, {\tt k}, {\tt l} are dummy indices, and {\tt i-1} is a numeric expression. The algorithmic decsription of this indexing expression is the following: \noindent\hfil \begin{tabular}{@{}l@{}} {\bf for all} $i\in A$ {\bf do}\\ \hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf and} $j=i-1$ {\bf do}\\ \hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ \hspace{48pt}{\it action};\\ \end{tabular} \noindent Thus, if this indexing expression were used as a primary set expression, the resultant set would be the following: $$\{(4,May,a),(4,May,b),(4,May,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$ Should note that in this case the resultant set consists of 3-tuples, not of 4-tuples, because in the indexing expression there is no dummy index that corresponds to the first component of 2-tuples from the set $B$. The general rule is: the number of components of $n$-tuples defined by an indexing expression is the same as the number of dummy indices in that expression, where the correspondence between dummy indices and components on $n$-tuples in the resultant set is positional, i.e. the first dummy index corresponds to the first component, the second dummy index corresponds to the second component, etc. In some cases it is needed to select a subset from the Cartesian product of some sets. This may be attained by using an optional logical predicate, which is specified in the indexing expression. Consider, for example, the following indexing expression: $$\mbox{{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}}$$ where the logical expression following the colon is a predicate. The algorithmic description of this indexing expression is the following: \noindent\hfil \begin{tabular}{@{}l@{}} {\bf for all} $i\in A$ {\bf do}\\ \hspace{16pt}{\bf for all} $(j,k)\in B$ {\bf do}\\ \hspace{32pt}{\bf for all} $l\in C$ {\bf do}\\ \hspace{48pt}{\bf if} $i\leq 5$ {\bf and} $k\neq`Mar'$ {\bf then}\\ \hspace{64pt}{\it action};\\ \end{tabular} \noindent Thus, if this indexing expression were used as a primary set expression, the resultant set would be the following: $$\{(4,1,Jan,a),(4,1,Feb,a),(4,2,Apr,a),\dots,(4,3,Jun,c)\}.$$ If no predicate is specified in the indexing expression, one, which takes on the value {\it true}, is assumed. \section{Set expressions} A {\it set expression} is a rule for computing an elemental set, i.e. a collection of $n$-tuples, where components of $n$-tuples are numeric and symbolic quantities. The primary set expression may be a literal set, unsubscripted set, subscripted set, ``arithmetic'' set, indexing expression, iterated set expression, conditional set expression, or another set expression enclosed in parentheses. \para{Examples} \noindent \begin{tabular}{@{}ll@{}} \verb|{(123,'aaa'), (i+1,'bbb'), (j-1,'ccc')}| &(literal set)\\ \verb|I| &(unsubscripted set)\\ \verb|S[i-1,j+1]| &(subscripted set)\\ \verb|1..t-1 by 2| &(``arithmetic'' set)\\ \verb|{t in 1..T, (t+1,j) in S: (t,j) in F}| &(indexing expression)\\ \verb|setof{i in I, j in J}(i+1,j-1)| &(iterated set expression)\\ \verb|if i < j then S[i,j] else F diff S[i,j]| &(conditional set expression)\\ \verb|(1..10 union 21..30)| &(parenthesized set expression)\\ \end{tabular} More general set expressions containing two or more primary set expressions may be constructed by using certain set operators. \para{Examples} \begin{verbatim} (A union B) inter (I cross J) 1..10 cross (if i < j then {'a', 'b', 'c'} else {'d', 'e', 'f'}) \end{verbatim} \subsection{Literal sets} A {\it literal set} is a primary set expression, which has the following two syntactic forms: $$ {\def\arraystretch{1.4} \begin{array}{l} \mbox{{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}}\\ \mbox{{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),} {\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,} {\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}}\\ \end{array} } $$ where $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ are numeric or symbolic expressions. If the first form is used, the resultant set consists of 1-tuples (singlets) enumerated within the curly braces. It is allowed to specify an empty set as {\tt\{\ \}}, which has no 1-tuples. If the second form is used, the resultant set consists of $n$-tuples enumerated within the curly braces, where a particular $n$-tuple consists of corresponding components enumerated within the parentheses. All $n$-tuples should have the same number of components. \subsection{Unsubscripted sets} If the primary set expression is an unsubscripted set (which should be 0-dimen\-sional), the resultant set is an elemental set associated with the corresponding set object. \subsection{Subscripted sets} The primary set expression, which refers to a subscripted set, has the following syntactic form: $$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}}$$ where {\it name} is the symbolic name of the set object, $i_1$, $i_2$, \dots, $i_n$ are subscripts. Each subscript should be a numeric or symbolic expression. The number of subscripts in the subscript list should be the same as the dimension of the set object with which the subscript list is associated. Actual values of subscript expressions are used to identify a particular member of the set object that determines the resultant set. \subsection{``Arithmetic'' sets} The primary set expression, which is an ``arithmetic'' set, has the following two syntactic forms: $$ {\def\arraystretch{1.4} \begin{array}{l} \mbox{$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$}\\ \mbox{$t_0$ {\tt..} $t_1$}\\ \end{array} } $$ where $t_0$, $t_1$, and $\delta t$ are numeric expressions (the value of $\delta t$ should not be zero). The second form is equivalent to the first form, where $\delta t=1$. If $\delta t>0$, the resultant set is determined as follows: $$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$ Otherwise, if $\delta t<0$, the resultant set is determined as follows: $$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$ \subsection{Indexing expressions} If the primary set expression is an indexing expression, the resultant set is determined as described above in Section \ref{indexing}, page \pageref{indexing}. \newpage \subsection{Iterated expressions} An {\it iterated set expression} is a primary set expression, which has the following syntactic form: $$\mbox{{\tt setof} {\it indexing-expression} {\it integrand}}$$ where {\it indexing-expression} is an indexing expression, which introduces dummy indices and controls iterating, {\it integrand} is either a single numeric or symbolic expression or a list of numeric and symbolic expressions separated by commae and enclosed in parentheses. If the integrand is a single numeric or symbolic expression, the resultant set consists of 1-tuples and is determined as follows: $$\{x:(i_1,\dots,i_n)\in\Delta\},$$ \noindent where $x$ is a value of the integrand, $i_1$, \dots, $i_n$ are dummy indices introduced in the indexing expression, $\Delta$ is the domain, a set of $n$-tuples specified by the indexing expression, which defines particular values assigned to the dummy indices on performing the iterated operation. If the integrand is a list containing $m$ numeric and symbolic expressions, the resultant set consists of $m$-tuples and is determined as follows: $$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$ where $x_1$, \dots, $x_m$ are values of the expressions in the integrand list, $i_1$, \dots, $i_n$ and $\Delta$ have the same meaning as above. \subsection{Conditional expressions} A {\it conditional set expression} is a primary set expression that has the following syntactic form: $$\mbox{{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$}$$ where $b$ is an logical expression, $X$ and $Y$ are set expressions, which should define sets of the same dimension. The resultant value of the conditional expression depends on the value of the logical expression that follows the keyword {\tt if}. If it takes on the value {\it true}, the resultant set is the value of the expression that follows the keyword {\tt then}. Otherwise, if the logical expression takes on the value {\it false}, the resultant set is the value of the expression that follows the keyword {\tt else}. \subsection{Parenthesized expressions} Any set expression may be enclosed in parentheses that syntactically makes it a primary set expression. Parentheses may be used in set expressions, as in algebra, to specify the desired order in which operations are to be performed. Where parentheses are used, the expression within the parentheses is evaluated before the resultant value is used. The resultant value of the parenthesized expression is the same as the value of the expression enclosed within parentheses. \newpage \subsection{Set operators} In MathProg there exist the following set operators, which may be used in set expressions: \begin{tabular}{@{}ll@{}} $X$ {\tt union} $Y$&union $X\cup Y$\\ $X$ {\tt diff} $Y$&difference $X\backslash Y$\\ $X$ {\tt symdiff} $Y$&symmetric difference $X\oplus Y=(X\backslash Y)\cup(Y\backslash X)$\\ $X$ {\tt inter} $Y$&intersection $X\cap Y$\\ $X$ {\tt cross} $Y$&cross (Cartesian) product $X\times Y$\\ \end{tabular} \noindent where $X$ and Y are set expressions, which should define sets of identical dimension (except the Cartesian product). If the expression includes more than one set operator, all operators are performed from left to right according to the hierarchy of operations (see below). The resultant value of the expression, which contains set operators, is the result of applying the operators to their operands. The dimension of the resultant set, i.e. the dimension of $n$-tuples, of which the resultant set consists of, is the same as the dimension of the operands, except the Cartesian product, where the dimension of the resultant set is the sum of the dimensions of its operands. \subsection{Hierarchy of operations} The following list shows the hierarchy of operations in set expressions: \noindent\hfil \begin{tabular}{@{}ll@{}} Operation&Hierarchy\\ \hline Evaluation of numeric operations&1st-7th\\ Evaluation of symbolic operations&8th-9th\\ Evaluation of iterated or ``arithmetic'' set ({\tt setof}, {\tt..})& 10th\\ Cartesian product ({\tt cross})&11th\\ Intersection ({\tt inter})&12th\\ Union and difference ({\tt union}, {\tt diff}, {\tt symdiff})&13th\\ Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})& 14th\\ \end{tabular} This hierarchy has the same meaning as was explained above for numeric expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). \newpage \section{Logical expressions} A {\it logical expression} is a rule for computing a single logical value, which can be either {\it true} or {\it false}. The primary logical expression may be a numeric expression, relational expression, iterated logical expression, or another logical expression enclosed in parentheses. \para{Examples} \noindent \begin{tabular}{@{}ll@{}} \verb|i+1| &(numeric expression)\\ \verb|a[i,j] < 1.5| &(relational expression)\\ \verb|s[i+1,j-1] <> 'Mar' & year | &(relational expression)\\ \verb|(i+1,'Jan') not in I cross J| &(relational expression)\\ \verb|S union T within A[i] inter B[j]| &(relational expression)\\ \verb|forall{i in I, j in J} a[i,j] < .5 * b[i]| &(iterated logical expression)\\ \verb|(a[i,j] < 1.5 or b[i] >= a[i,j])| &(parenthesized logical expression)\\ \end{tabular} More general logical expressions containing two or more primary logical expressions may be constructed by using certain logical operators. \para{Examples} \begin{verbatim} not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S (i,j) in S or (i,j) not in T diff U \end{verbatim} \vspace*{-8pt} \subsection{Numeric expressions} The resultant value of the primary logical expression, which is a numeric expression, is {\it true}, if the resultant value of the numeric expression is non-zero. Otherwise the resultant value of the logical expression is {\it false}. \vspace*{-8pt} \subsection{Relational operators} In MathProg there exist the following relational operators, which may be used in logical expressions: \begin{tabular}{@{}ll@{}} $x$ {\tt<} $y$&test on $x=} $y$&test on $x\geq y$\\ $x$ {\tt>} $y$&test on $x>y$\\ $x$ {\tt<>} $y$, $x$ {\tt!=} $y$&test on $x\neq y$\\ $x$ {\tt in} $Y$&test on $x\in Y$\\ {\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&test on $(x_1,\dots,x_n)\in Y$\\ $x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&test on $x\not\in Y$\\ {\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$, {\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&test on $(x_1,\dots,x_n)\not\in Y$\\ $X$ {\tt within} $Y$&test on $X\subseteq Y$\\ $X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&test on $X\not\subseteq Y$\\ \end{tabular} \noindent where $x$, $x_1$, \dots, $x_n$, $y$ are numeric or symbolic expressions, $X$ and $Y$ are set expression. \newpage 1. In the operations {\tt in}, {\tt not in}, and {\tt !in} the number of components in the first operands should be the same as the dimension of the second operand. 2. In the operations {\tt within}, {\tt not within}, and {\tt !within} both operands should have identical dimension. All the relational operators listed above have their conventional mathematical meaning. The resultant value is {\it true}, if corresponding relation is satisfied for its operands, otherwise {\it false}. (Note that symbolic values are ordered lexicographically, and any numeric value precedes any symbolic value.) \subsection{Iterated expressions} An {\it iterated logical expression} is a primary logical expression, which has the following syntactic form: $$\mbox{{\it iterated-operator} {\it indexing-expression} {\it integrand}}$$ where {\it iterated-operator} is the symbolic name of the iterated operator to be performed (see below), {\it indexing-expression} is an indexing expression which introduces dummy indices and controls iterating, {\it integrand} is a numeric expression that participates in the operation. In MathProg there exist two iterated operators, which may be used in logical expressions: {\def\arraystretch{1.4} \noindent\hfil \begin{tabular}{@{}lll@{}} {\tt forall}&$\forall$-quantification&$\displaystyle \forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ {\tt exists}&$\exists$-quantification&$\displaystyle \exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\ \end{tabular} } \noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in the indexing expression, $\Delta$ is the domain, a set of $n$-tuples specified by the indexing expression which defines particular values assigned to the dummy indices on performing the iterated operation, $f(i_1,\dots,i_n)$ is the integrand, a logical expression whose resultant value depends on the dummy indices. For $\forall$-quantification the resultant value of the iterated logical expression is {\it true}, if the value of the integrand is {\it true} for all $n$-tuples contained in the domain, otherwise {\it false}. For $\exists$-quantification the resultant value of the iterated logical expression is {\it false}, if the value of the integrand is {\it false} for all $n$-tuples contained in the domain, otherwise {\it true}. \subsection{Parenthesized expressions} Any logical expression may be enclosed in parentheses that syntactically makes it a primary logical expression. Parentheses may be used in logical expressions, as in algebra, to specify the desired order in which operations are to be performed. Where parentheses are used, the expression within the parentheses is evaluated before the resultant value is used. The resultant value of the parenthesized expression is the same as the value of the expression enclosed within parentheses. \newpage \subsection{Logical operators} In MathProg there exist the following logical operators, which may be used in logical expressions: \begin{tabular}{@{}ll@{}} {\tt not} $x$, {\tt!}$x$&negation $\neg\ x$\\ $x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunction (logical ``and'') $x\;\&\;y$\\ $x$ {\tt or} $y$, $x$ {\tt||} $y$&disjunction (logical ``or'') $x\vee y$\\ \end{tabular} \noindent where $x$ and $y$ are logical expressions. If the expression includes more than one logical operator, all operators are performed from left to right according to the hierarchy of the operations (see below). The resultant value of the expression, which contains logical operators, is the result of applying the operators to their operands. \subsection{Hierarchy of operations} The following list shows the hierarchy of operations in logical expressions: \noindent\hfil \begin{tabular}{@{}ll@{}} Operation&Hierarchy\\ \hline Evaluation of numeric operations&1st-7th\\ Evaluation of symbolic operations&8th-9th\\ Evaluation of set operations&10th-14th\\ Relational operations ({\tt<}, {\tt<=}, etc.)&15th\\ Negation ({\tt not}, {\tt!})&16th\\ Conjunction ({\tt and}, {\tt\&\&})&17th\\ $\forall$- and $\exists$-quantification ({\tt forall}, {\tt exists})& 18th\\ Disjunction ({\tt or}, {\tt||})&19th\\ \end{tabular} This hierarchy has the same meaning as was explained above for numeric expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). \section{Linear expressions} An {\it linear expression} is a rule for computing so called a {\it linear form} or simply a {\it formula}, which is a linear (or affine) function of elemental variables. The primary linear expression may be an unsubscripted variable, subscripted variable, iterated linear expression, conditional linear expression, or another linear expression enclosed in parentheses. It is also allowed to use a numeric expression as the primary linear expression, in which case the resultant value of the numeric expression is automatically converted to a formula that includes the constant term only. \para{Examples} \noindent \begin{tabular}{@{}ll@{}} \verb|z| &(unsubscripted variable)\\ \verb|x[i,j]| &(subscripted variable)\\ \verb|sum{j in J} (a[i,j] * x[i,j] + 3 * y[i-1])| & (iterated linear expression)\\ \verb|if i in I then x[i,j] else 1.5 * z + 3.25| & (conditional linear expression)\\ \verb|(a[i,j] * x[i,j] + y[i-1] + .1)| & (parenthesized linear expression)\\ \end{tabular} More general linear expressions containing two or more primary linear expressions may be constructed by using certain arithmetic operators. \para{Examples} \begin{verbatim} 2 * x[i-1,j+1] + 3.5 * y[k] + .5 * z (- x[i,j] + 3.5 * y[k]) / sum{t in T} abs(d[i,j,t]) \end{verbatim} \vspace*{-5pt} \subsection{Unsubscripted variables} If the primary linear expression is an unsubscripted variable (which should be 0-dimensional), the resultant formula is that unsubscripted variable. \vspace*{-5pt} \subsection{Subscripted variables} The primary linear expression, which refers to a subscripted variable, has the following syntactic form: $$\mbox{{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}}$$ where {\it name} is the symbolic name of the model variable, $i_1$, $i_2$, \dots, $i_n$ are subscripts. Each subscript should be a numeric or symbolic expression. The number of subscripts in the subscript list should be the same as the dimension of the model variable with which the subscript list is associated. Actual values of the subscript expressions are used to identify a particular member of the model variable that determines the resultant formula, which is an elemental variable associated with corresponding member. \vspace*{-5pt} \subsection{Iterated expressions} An {\it iterated linear expression} is a primary linear expression, which has the following syntactic form: $$\mbox{{\tt sum} {\it indexing-expression} {\it integrand}}$$ where {\it indexing-expression} is an indexing expression, which introduces dummy indices and controls iterating, {\it integrand} is a linear expression that participates in the operation. The iterated linear expression is evaluated exactly in the same way as the iterated numeric expression (see Subection \ref{itexpr}, page \pageref{itexpr}) with exception that the integrand participated in the summation is a formula, not a numeric value. \vspace*{-5pt} \subsection{Conditional expressions} A {\it conditional linear expression} is a primary linear expression, which has one of the following two syntactic forms: $$ {\def\arraystretch{1.4} \begin{array}{l} \mbox{{\tt if} $b$ {\tt then} $f$ {\tt else} $g$}\\ \mbox{{\tt if} $b$ {\tt then} $f$}\\ \end{array} } $$ where $b$ is an logical expression, $f$ and $g$ are linear expressions. \newpage The conditional linear expression is evaluated exactly in the same way as the conditional numeric expression (see Subsection \ref{ifthen}, page \pageref{ifthen}) with exception that operands participated in the operation are formulae, not numeric values. \subsection{Parenthesized expressions} Any linear expression may be enclosed in parentheses that syntactically makes it a primary linear expression. Parentheses may be used in linear expressions, as in algebra, to specify the desired order in which operations are to be performed. Where parentheses are used, the expression within the parentheses is evaluated before the resultant formula is used. The resultant value of the parenthesized expression is the same as the value of the expression enclosed within parentheses. \subsection{Arithmetic operators} In MathProg there exists the following arithmetic operators, which may be used in linear expressions: \begin{tabular}{@{}ll@{}} {\tt+} $f$&unary plus\\ {\tt-} $f$&unary minus\\ $f$ {\tt+} $g$&addition\\ $f$ {\tt-} $g$&subtraction\\ $x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplication\\ $f$ {\tt/} $x$&division \end{tabular} \noindent where $f$ and $g$ are linear expressions, $x$ is a numeric expression (more precisely, a linear expression containing only the constant term). If the expression includes more than one arithmetic operator, all operators are performed from left to right according to the hierarchy of operations (see below). The resultant value of the expression, which contains arithmetic operators, is the result of applying the operators to their operands. \subsection{Hierarchy of operations} The hierarchy of arithmetic operations used in linear expressions is the same as for numeric expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Statements} {\it Statements} are basic units of the model description. In MathProg all statements are divided into two categories: declaration statements and functional statements. {\it Declaration statements} (set statement, parameter statement, variable statement, constraint statement, objective statement) are used to declare model objects of certain kinds and define certain properties of such objects. {\it Functional statements} (solve statement, check statement, display statement, printf statement, loop statement, table statement) are intended for performing some specific actions. Note that declaration statements may follow in arbitrary order, which does not affect the result of translation. However, any model object should be declared before it is referenced in other statements. \section{Set statement} \noindent \framebox[468pt][l]{ \parbox[c][24pt]{468pt}{ \hspace{6pt} {\tt set} {\it name} {\it alias} {\it domain} {\tt,} {\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the set; \noindent {\it alias} is an optional string literal, which specifies an alias of the set; \noindent {\it domain} is an optional indexing expression, which specifies a subscript domain of the set; \noindent {\it attrib}, \dots, {\it attrib} are optional attributes of the set. (Commae preceding attributes may be omitted.) \para{Optional attributes} \vspace*{-8pt} \begin{description} \item[{\tt dimen} $n$]\hspace*{0pt}\\ specifies the dimension of $n$-tuples which the set consists of; \item[{\tt within} {\it expression}]\hspace*{0pt}\\ specifies a superset which restricts the set or all its members (elemental sets) to be within that superset; \item[{\tt:=} {\it expression}]\hspace*{0pt}\\ specifies an elemental set assigned to the set or its members; \item[{\tt default} {\it expression}]\hspace*{0pt}\\ specifies an elemental set assigned to the set or its members whenever no appropriate data are available in the data section. \end{description} \vspace*{-8pt} \para{Examples} \begin{verbatim} set nodes; set arcs within nodes cross nodes; set step{s in 1..maxiter} dimen 2 := if s = 1 then arcs else step[s-1] union setof{k in nodes, (i,k) in step[s-1], (k,j) in step[s-1]}(i,j); set A{i in I, j in J}, within B[i+1] cross C[j-1], within D diff E, default {('abc',123), (321,'cba')}; \end{verbatim} The set statement declares a set. If the subscript domain is not specified, the set is a simple set, otherwise it is an array of elemental sets. The {\tt dimen} attribute specifies the dimension of $n$-tuples, which the set (if it is a simple set) or its members (if the set is an array of elemental sets) consist of, where $n$ should be an unsigned integer from 1 to 20. At most one {\tt dimen} attribute can be specified. If the {\tt dimen} attribute is not specified, the dimension of $n$-tuples is implicitly determined by other attributes (for example, if there is a set expression that follows {\tt:=} or the keyword {\tt default}, the dimension of $n$-tuples of corresponding elemental set is used). If no dimension information is available, {\tt dimen 1} is assumed. The {\tt within} attribute specifies a set expression whose resultant value is a superset used to restrict the set (if it is a simple set) or its members (if the set is an array of elemental sets) to be within that superset. Arbitrary number of {\tt within} attributes may be specified in the same set statement. The assign ({\tt:=}) attribute specifies a set expression used to evaluate elemental set(s) assigned to the set (if it is a simple set) or its members (if the set is an array of elemental sets). If the assign attribute is specified, the set is {\it computable} and therefore needs no data to be provided in the data section. If the assign attribute is not specified, the set should be provided with data in the data section. At most one assign or default attribute can be specified for the same set. The {\tt default} attribute specifies a set expression used to evaluate elemental set(s) assigned to the set (if it is a simple set) or its members (if the set is an array of elemental sets) whenever no appropriate data are available in the data section. If neither assign nor default attribute is specified, missing data will cause an error. \newpage \section{Parameter statement} \noindent \framebox[468pt][l]{ \parbox[c][24pt]{468pt}{ \hspace{6pt} {\tt param} {\it name} {\it alias} {\it domain} {\tt,} {\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the parameter; \noindent {\it alias} is an optional string literal, which specifies an alias of the parameter; \noindent {\it domain} is an optional indexing expression, which specifies a subscript domain of the parameter; \noindent {\it attrib}, \dots, {\it attrib} are optional attributes of the parameter. (Commae preceding attributes may be omitted.) \para{Optional attributes} \vspace*{-8pt} \begin{description} \item[{\tt integer}]\hspace*{0pt}\\ specifies that the parameter is integer; \item[{\tt binary}]\hspace*{0pt}\\ specifies that the parameter is binary; \item[{\tt symbolic}]\hspace*{0pt}\\ specifies that the parameter is symbolic; \item[{\it relation expression}]\hspace*{0pt}\\ (where {\it relation} is one of: {\tt<}, {\tt<=}, {\tt=}, {\tt==}, {\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\ specifies a condition that restricts the parameter or its members to satisfy that condition; \item[{\tt in} {\it expression}]\hspace*{0pt}\\ specifies a superset that restricts the parameter or its members to be in that superset; \item[{\tt:=} {\it expression}]\hspace*{0pt}\\ specifies a value assigned to the parameter or its members; \item[{\tt default} {\it expression}]\hspace*{0pt}\\ specifies a value assigned to the parameter or its members whenever no appropriate data are available in the data section. \end{description} \vspace*{-8pt} \para{Examples} \begin{verbatim} param units{raw, prd} >= 0; param profit{prd, 1..T+1}; param N := 20 integer >= 0 <= 100; param comb 'n choose k' {n in 0..N, k in 0..n} := if k = 0 or k = n then 1 else comb[n-1,k-1] + comb[n-1,k]; param p{i in I, j in J}, integer, >= 0, <= i+j, in A[i] symdiff B[j], in C[i,j], default 0.5 * (i + j); param month symbolic default 'May' in {'Mar', 'Apr', 'May'}; \end{verbatim} The parameter statement declares a parameter. If a subscript domain is not specified, the parameter is a simple (scalar) parameter, otherwise it is a $n$-dimensional array. The type attributes {\tt integer}, {\tt binary}, and {\tt symbolic} qualify the type of values that can be assigned to the parameter as shown below: \noindent\hfil \begin{tabular}{@{}ll@{}} Type attribute&Assigned values\\ \hline (not specified)&Any numeric values\\ {\tt integer}&Only integer numeric values\\ {\tt binary}&Either 0 or 1\\ {\tt symbolic}&Any numeric and symbolic values\\ \end{tabular} The {\tt symbolic} attribute cannot be specified along with other type attributes. Being specified it should precede all other attributes. The condition attribute specifies an optional condition that restricts values assigned to the parameter to satisfy that condition. This attribute has the following syntactic forms: \begin{tabular}{@{}ll@{}} {\tt<} $v$&check for $x=} $v$&check for $x\geq v$\\ {\tt>} $v$&check for $x\geq v$\\ {\tt<>} $v$, {\tt!=} $v$&check for $x\neq v$\\ \end{tabular} \noindent where $x$ is a value assigned to the parameter, $v$ is the resultant value of a numeric or symbolic expression specified in the condition attribute. Arbitrary number of condition attributes can be specified for the same parameter. If a value being assigned to the parameter during model evaluation violates at least one of specified conditions, an error is raised. (Note that symbolic values are ordered lexicographically, and any numeric value precedes any symbolic value.) The {\tt in} attribute is similar to the condition attribute and specifies a set expression whose resultant value is a superset used to restrict numeric or symbolic values assigned to the parameter to be in that superset. Arbitrary number of the {\tt in} attributes can be specified for the same parameter. If a value being assigned to the parameter during model evaluation is not in at least one of specified supersets, an error is raised. The assign ({\tt:=}) attribute specifies a numeric or symbolic expression used to compute a value assigned to the parameter (if it is a simple parameter) or its member (if the parameter is an array). If the assign attribute is specified, the parameter is {\it computable} and therefore needs no data to be provided in the data section. If the assign attribute is not specified, the parameter should be provided with data in the data section. At most one assign or {\tt default} attribute can be specified for the same parameter. The {\tt default} attribute specifies a numeric or symbolic expression used to compute a value assigned to the parameter or its member whenever no appropriate data are available in the data section. If neither assign nor {\tt default} attribute is specified, missing data will cause an error. \newpage \section{Variable statement} \noindent \framebox[468pt][l]{ \parbox[c][24pt]{468pt}{ \hspace{6pt} {\tt var} {\it name} {\it alias} {\it domain} {\tt,} {\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the variable; \noindent {\it alias} is an optional string literal, which specifies an alias of the variable; \noindent {\it domain} is an optional indexing expression, which specifies a subscript domain of the variable; \noindent {\it attrib}, \dots, {\it attrib} are optional attributes of the variable. (Commae preceding attributes may be omitted.) \para{Optional attributes} \vspace*{-8pt} \begin{description} \item[{\tt integer}]\hspace*{0pt}\\ restricts the variable to be integer; \item[{\tt binary}]\hspace*{0pt}\\ restricts the variable to be binary; \item[{\tt>=} {\it expression}]\hspace*{0pt}\\ specifies an lower bound of the variable; \item[{\tt<=} {\it expression}]\hspace*{0pt}\\ specifies an upper bound of the variable; \item[{\tt=} {\it expression}]\hspace*{0pt}\\ specifies a fixed value of the variable; \end{description} \vspace*{-8pt} \para{Examples} \begin{verbatim} var x >= 0; var y{I,J}; var make{p in prd}, integer, >= commit[p], <= market[p]; var store{raw, 1..T+1} >= 0; var z{i in I, j in J} >= i+j; \end{verbatim} The variable statement declares a variable. If a subscript domain is not specified, the variable is a simple (scalar) variable, otherwise it is a $n$-dimensional array of elemental variables. Elemental variable(s) associated with the model variable (if it is a simple variable) or its members (if it is an array) correspond to the variables in the LP/MIP problem formulation (see Section \ref{problem}, page \pageref{problem}). Note that only elemental variables actually referenced in some constraints and/or objectives are included in the LP/MIP problem instance to be generated. The type attributes {\tt integer} and {\tt binary} restrict the variable to be integer or binary, respectively. If no type attribute is specified, the variable is continuous. If all variables in the model are continuous, the corresponding problem is of LP class. If there is at least one integer or binary variable, the problem is of MIP class. The lower bound ({\tt>=}) attribute specifies a numeric expression for computing an lower bound of the variable. At most one lower bound can be specified. By default all variables (except binary ones) have no lower bound, so if a variable is required to be non-negative, its zero lower bound should be explicitly specified. The upper bound ({\tt<=}) attribute specifies a numeric expression for computing an upper bound of the variable. At most one upper bound attribute can be specified. The fixed value ({\tt=}) attribute specifies a numeric expression for computing a value, at which the variable is fixed. This attribute cannot be specified along with the bound attributes. \section{Constraint statement} \noindent \framebox[468pt][l]{ \parbox[c][106pt]{468pt}{ \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} {\it expression} {\tt,} {\tt=} {\it expression} {\tt;} \medskip \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} {\it expression} {\tt,} {\tt<=} {\it expression} {\tt;} \medskip \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} {\it expression} {\tt,} {\tt>=} {\it expression} {\tt;} \medskip \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} {\it expression} {\tt,} {\tt<=} {\it expression} {\tt,} {\tt<=} {\it expression} {\tt;} \medskip \hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:} {\it expression} {\tt,} {\tt>=} {\it expression} {\tt,} {\tt>=} {\it expression} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the constraint; \noindent {\it alias} is an optional string literal, which specifies an alias of the constraint; \noindent {\it domain} is an optional indexing expression, which specifies a subscript domain of the constraint; \noindent {\it expression} is a linear expression used to compute a component of the constraint. (Commae following expressions may be omitted.) \noindent (The keyword {\tt s.t.} may be written as {\tt subject to} or as {\tt subj to}, or may be omitted at all.) \para{Examples} \begin{verbatim} s.t. r: x + y + z, >= 0, <= 1; limit{t in 1..T}: sum{j in prd} make[j,t] <= max_prd; subject to balance{i in raw, t in 1..T}: store[i,t+1] - store[i,t] - sum{j in prd} units[i,j] * make[j,t]; subject to rlim 'regular-time limit' {t in time}: sum{p in prd} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * crews[t]; \end{verbatim} The constraint statement declares a constraint. If a subscript domain is not specified, the\linebreak constraint is a simple (scalar) constraint, otherwise it is a $n$-dimensional array of elemental constraints. Elemental constraint(s) associated with the model constraint (if it is a simple constraint) or its members (if it is an array) correspond to the linear constraints in the LP/MIP problem formulation (see Section \ref{problem}, page \pageref{problem}). If the constraint has the form of equality or single inequality, i.e. includes two expressions, one of which follows the colon and other follows the relation sign {\tt=}, {\tt<=}, or {\tt>=}, both expressions in the statement can be linear expressions. If the constraint has the form of double inequality,\linebreak i.e. includes three expressions, the middle expression can be a linear expression while the leftmost and rightmost ones can be only numeric expressions. Generating the model is, roughly speaking, generating its constraints, which are always evaluated for the entire subscript domain. Evaluation of the constraints leads, in turn, to evaluation of other model objects such as sets, parameters, and variables. Constructing an actual linear constraint included in the problem instance, which (constraint) corresponds to a particular elemental constraint, is performed as follows. If the constraint has the form of equality or single inequality, evaluation of both linear expressions gives two resultant linear forms: $$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r} f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\ g&=&b_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&b_0,\\ \end{array}$$ where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$, \dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ are numeric coefficients; $a_0$ and $b_0$ are constant terms. Then all linear terms of $f$ and $g$ are carried to the left-hand side, and the constant terms are carried to the right-hand side, that gives the final elemental constraint in the standard form: $$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{ \begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$ If the constraint has the form of double inequality, evaluation of the middle linear expression gives the resultant linear form: $$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ and evaluation of the leftmost and rightmost numeric expressions gives two numeric values $l$ and $u$, respectively. Then the constant term of the linear form is carried to both left-hand and right-handsides that gives the final elemental constraint in the standard form: $$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$ \section{Objective statement} \noindent \framebox[468pt][l]{ \parbox[c][44pt]{468pt}{ \hspace{6pt} {\tt minimize} {\it name} {\it alias} {\it domain} {\tt:} {\it expression} {\tt;} \medskip \hspace{6pt} {\tt maximize} {\it name} {\it alias} {\it domain} {\tt:} {\it expression} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the objective; \noindent {\it alias} is an optional string literal, which specifies an alias of the objective; \noindent {\it domain} is an optional indexing expression, which specifies a subscript domain of the objective; \noindent {\it expression} is a linear expression used to compute the linear form of the objective. \newpage \para{Examples} \begin{verbatim} minimize obj: x + 1.5 * (y + z); maximize total_profit: sum{p in prd} profit[p] * make[p]; \end{verbatim} The objective statement declares an objective. If a subscript domain is not specified, the objective is a simple (scalar) objective. Otherwise it is a $n$-dimensional array of elemental objectives. Elemental objective(s) associated with the model objective (if it is a simple objective) or its members (if it is an array) correspond to general linear constraints in the LP/MIP problem formulation (see Section \ref{problem}, page \pageref{problem}). However, unlike constraints the corresponding linear forms are free (unbounded). Constructing an actual linear constraint included in the problem instance, which (constraint) corresponds to a particular elemental constraint, is performed as follows. The linear expression specified in the objective statement is evaluated that, gives the resultant linear form: $$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$ where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$, \dots, $a_n$ are numeric coefficients; $a_0$ is the constant term. Then the linear form is used to construct the final elemental constraint in the standard form: $$-\infty= 0 and y >= 0; check sum{i in ORIG} supply[i] = sum{j in DEST} demand[j]; check{i in I, j in 1..10}: S[i,j] in U[i] union V[j]; \end{verbatim} The check statement allows checking the resultant value of an logical expression specified in the statement. If the value is {\it false}, an error is reported. If the subscript domain is not specified, the check is performed only once. Specifying the subscript domain allows performing multiple check for every $n$-tuple in the domain set. In the latter case the logical expression may include dummy indices introduced in corresponding indexing expression. \section{Display statement} \noindent \framebox[468pt][l]{ \parbox[c][24pt]{468pt}{ \hspace{6pt} {\tt display} {\it domain} {\tt:} {\it item} {\tt,} \dots {\tt,} {\it item} {\tt;} }} \medskip \noindent {\it domain} is an optional indexing expression, which specifies a subscript domain of the display statement; \noindent {\it item}, \dots, {\it item} are items to be displayed. (The colon preceding the first item may be omitted.) \para{Examples} \begin{verbatim} display: 'x =', x, 'y =', y, 'z =', z; display sqrt(x ** 2 + y ** 2 + z ** 2); display{i in I, j in J}: i, j, a[i,j], b[i,j]; \end{verbatim} The display statement evaluates all items specified in the statement and writes their values on the standard output (terminal) in plain text format. If a subscript domain is not specified, items are evaluated and then displayed only once. Specifying the subscript domain causes items to be evaluated and displayed for every $n$-tuple in the domain set. In the latter case items may include dummy indices introduced in corresponding indexing expression. An item to be displayed can be a model object (set, parameter, v ariable, constraint, objective) or an expression. If the item is a computable object (i.e. a set or parameter provided with the assign attribute), the object is evaluated over the entire domain and then its content (i.e. the content of the object array) is displayed. Otherwise, if the item is not a computable object, only its current content (i.e. members actually generated during the model evaluation) is displayed. If the item is an expression, the expression is evaluated and its resultant value is displayed. \section{Printf statement} \noindent \framebox[468pt][l]{ \parbox[c][64pt]{468pt}{ \hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} {\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt;} \medskip \hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} {\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>} {\it filename} {\tt;} \medskip \hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,} {\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>>} {\it filename} {\tt;} }} \medskip \noindent {\it domain} is an optional indexing expression, which specifies a subscript domain of the printf statement; \noindent {\it format} is a symbolic expression whose value specifies a format control string. (The colon preceding the format expression may be omitted.) \noindent {\it expression}, \dots, {\it expression} are zero or more expressions whose values have to be formatted and printed. Each expression should be of numeric, symbolic, or logical type. \noindent {\it filename} is a symbolic expression whose value specifies a name of a text file, to which the output is redirected. The flag {\tt>} means creating a new empty file while the flag {\tt>>} means appending the output to an existing file. If no file name is specified, the output is written on the standard output (terminal). \para{Examples} \begin{verbatim} printf 'Hello, world!\n'; printf: "x = %.3f; y = %.3f; z = %.3f\n", x, y, z > "result.txt"; printf{i in I, j in J}: "flow from %s to %s is %d\n", i, j, x[i,j] >> result_file & ".txt"; printf{i in I} 'total flow from %s is %g\n', i, sum{j in J} x[i,j]; printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"), k, x[k]; \end{verbatim} The printf statement is similar to the display statement, however, it allows formatting data to be written. If a subscript domain is not specified, the printf statement is executed only once. Specifying a subscript domain causes executing the printf statement for every $n$-tuple in the domain set. In the latter case the format and expression may include dummy indices introduced in corresponding indexing expression. The format control string is a value of the symbolic expression {\it format} specified in the printf statement. It is composed of zero or more directives as follows: ordinary characters (not {\tt\%}), which are copied unchanged to the output stream, and conversion specifications, each of which causes evaluating corresponding expression specified in the printf statement, formatting it, and writing its resultant value to the output stream. Conversion specifications that may be used in the format control string are the following:\linebreak {\tt d}, {\tt i}, {\tt f}, {\tt F}, {\tt e}, {\tt E}, {\tt g}, {\tt G}, and {\tt s}. These specifications have the same syntax and semantics as in the C programming language. \section{For statement} \noindent \framebox[468pt][l]{ \parbox[c][44pt]{468pt}{ \hspace{6pt} {\tt for} {\it domain} {\tt:} {\it statement} {\tt;} \medskip \hspace{6pt} {\tt for} {\it domain} {\tt:} {\tt\{} {\it statement} \dots {\it statement} {\tt\}} {\tt;} }} \medskip \noindent {\it domain} is an indexing expression which specifies a subscript domain of the for statement. (The colon following the indexing expression may be omitted.) \noindent {\it statement} is a statement, which should be executed under control of the for statement; \noindent {\it statement}, \dots, {\it statement} is a sequence of statements (enclosed in curly braces), which should be executed under control of the for statement. Only the following statements can be used within the for statement: check, display, printf, and another for. \para{Examples} \begin{verbatim} for {(i,j) in E: i != j} { printf "flow from %s to %s is %g\n", i, j, x[i,j]; check x[i,j] >= 0; } for {i in 1..n} { for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; printf("\n"); } for {1..72} printf("*"); \end{verbatim} The for statement causes a statement or a sequence of statements specified as part of the for statement to be executed for every $n$-tuple in the domain set. Thus, statements within the for statement may include dummy indices introduced in corresponding indexing expression. \newpage \section{Table statement} \noindent \framebox[468pt][l]{ \parbox[c][80pt]{468pt}{ \hspace{6pt} {\tt table} {\it name} {\it alias} {\tt IN} {\it driver} {\it arg} \dots {\it arg} {\tt:} \hspace{6pt} {\tt\ \ \ \ \ } {\it set} {\tt<-} {\tt[} {\it fld} {\tt,} \dots {\tt,} {\it fld} {\tt]} {\tt,} {\it par} {\tt\textasciitilde} {\it fld} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it fld} {\tt;} \medskip \hspace{6pt} {\tt table} {\it name} {\it alias} {\it domain} {\tt OUT} {\it driver} {\it arg} \dots {\it arg} {\tt:} \hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it fld} {\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it fld} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the table; \noindent {\it alias} is an optional string literal, which specifies an alias of the table; \noindent {\it domain} is an indexing expression, which specifies a subscript domain of the (output) table; \noindent {\tt IN} means reading data from the input table; \noindent {\tt OUT} means writing data to the output table; \noindent {\it driver} is a symbolic expression, which specifies the driver used to access the table (for details see Appendix \ref{drivers}, page \pageref{drivers}); \noindent {\it arg} is an optional symbolic expression, which is an argument pass\-ed to the table driver. This symbolic expression should not include dummy indices specified in the domain; \noindent {\it set} is the name of an optional simple set called {\it control set}. It can be omitted along with the delimiter {\tt<-}; \noindent {\it fld} is a field name. Within square brackets at least one field should be specified. The field name following a parameter name or expression is optional and can be omitted along with the delimiter~{\tt\textasciitilde}, in which case the name of corresponding model object is used as the field name; \noindent {\it par} is a symbolic name of a model parameter; \noindent {\it expr} is a numeric or symbolic expression. \para{Examples} \begin{verbatim} table data IN "CSV" "data.csv": S <- [FROM,TO], d~DISTANCE, c~COST; table result{(f,t) in S} OUT "CSV" "result.csv": f~FROM, t~TO, x[f,t]~FLOW; \end{verbatim} The table statement allows reading data from a table into model objects such as sets and (non-scalar) parameters as well as writing data from the model to a table. \newpage \subsection{Table structure} A {\it data table} is an (unordered) set of {\it records}, where each record consists of the same number of {\it fields}, and each field is provided with a unique symbolic name called the {\it field name}. For example: \bigskip \begin{tabular}{@{\hspace*{42mm}}c@{\hspace*{11mm}}c@{\hspace*{10mm}}c @{\hspace*{9mm}}c} First&Second&&Last\\ field&field&.\ \ .\ \ .&field\\ $\downarrow$&$\downarrow$&&$\downarrow$\\ \end{tabular} \begin{tabular}{ll@{}} Table header&$\rightarrow$\\ First record&$\rightarrow$\\ Second record&$\rightarrow$\\ \\ \hfil .\ \ .\ \ .\\ \\ Last record&$\rightarrow$\\ \end{tabular} \begin{tabular}{|l|l|c|c|} \hline {\tt FROM}&{\tt TO}&{\tt DISTANCE}&{\tt COST}\\ \hline {\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\ {\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\ {\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\ {\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\ {\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\ {\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\ \hline \end{tabular} \subsection{Reading data from input table} The input table statement causes reading data from the specified table record by record. Once a next record has been read, numeric or symbolic values of fields, whose names are enclosed in square brackets in the table statement, are gathered into $n$-tuple, and if the control set is specified in the table statement, this $n$-tuple is added to it. Besides, a numeric or symbolic value of each field associated with a model parameter is assigned to the parameter member identified by subscripts, which are components of the $n$-tuple just read. For example, the following input table statement: \noindent\hfil \verb|table data IN "...": S <- [FROM,TO], d~DISTANCE, c~COST;| \noindent causes reading values of four fields named {\tt FROM}, {\tt TO}, {\tt DISTANCE}, and {\tt COST} from each record of the specified table. Values of fields {\tt FROM} and {\tt TO} give a pair $(f,t)$, which is added to the control set {\tt S}. The value of field {\tt DISTANCE} is assigned to parameter member ${\tt d}[f,t]$, and the value of field {\tt COST} is assigned to parameter member ${\tt c}[f,t]$. Note that the input table may contain extra fields whose names are not specified in the table statement, in which case values of these fields on reading the table are ignored. \subsection{Writing data to output table} The output table statement causes writing data to the specified table. Note that some drivers (namely, CSV and xBASE) destroy the output table before writing data, i.e. delete all its existing records. Each $n$-tuple in the specified domain set generates one record written to the output table. Values of fields are numeric or symbolic values of corresponding expressions specified in the table statement. These expressions are evaluated for each $n$-tuple in the domain set and, thus, may include dummy indices introduced in the corresponding indexing expression. For example, the following output table statement: \noindent\hfil \verb|table result{(f,t) in S} OUT "...": f~FROM, t~TO, x[f,t]~FLOW;| \noindent causes writing records, by one record for each pair $(f,t)$ in set {\tt S}, to the output table, where each record consists of three fields named {\tt FROM}, {\tt TO}, and {\tt FLOW}. The values written to fields {\tt FROM} and {\tt TO} are current values of dummy indices {\tt f} and {\tt t}, and the value written to field {\tt FLOW} is a value of member ${\tt x}[f,t]$ of corresponding subscripted parameter or variable. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Model data} {\it Model data} include elemental sets, which are ``values'' of model sets, and numeric and symbolic values of model parameters. In MathProg there are two different ways to saturate model sets and parameters with data. One way is simply providing necessary data using the assign attribute. However, in many cases it is more practical to separate the model itself and particular data needed for the model. For the latter reason in MathProg there is another way, when the model description is divided into two parts: model section and data section. A {\it model section} is a main part of the model description that contains declarations of all model objects and is common for all problems based on that model. A {\it data section} is an optional part of the model description that contains model data specific for a particular problem. In MathProg model and data sections can be placed either in one text file or in two separate text files. 1. If both model and data sections are placed in one file, the file is composed as follows: \bigskip \noindent\hfil \framebox{\begin{tabular}{l} {\it statement}{\tt;}\\ {\it statement}{\tt;}\\ \hfil.\ \ .\ \ .\\ {\it statement}{\tt;}\\ {\tt data;}\\ {\it data block}{\tt;}\\ {\it data block}{\tt;}\\ \hfil.\ \ .\ \ .\\ {\it data block}{\tt;}\\ {\tt end;} \end{tabular}} \newpage 2. If the model and data sections are placed in two separate files, the files are composed as follows: \bigskip \noindent\hfil \begin{tabular}{@{}c@{}} \framebox{\begin{tabular}{l} {\it statement}{\tt;}\\ {\it statement}{\tt;}\\ \hfil.\ \ .\ \ .\\ {\it statement}{\tt;}\\ {\tt end;}\\ \end{tabular}}\\ \\\\Model file\\ \end{tabular} \hspace{32pt} \begin{tabular}{@{}c@{}} \framebox{\begin{tabular}{l} {\tt data;}\\ {\it data block}{\tt;}\\ {\it data block}{\tt;}\\ \hfil.\ \ .\ \ .\\ {\it data block}{\tt;}\\ {\tt end;}\\ \end{tabular}}\\ \\Data file\\ \end{tabular} \bigskip Note: If the data section is placed in a separate file, the keyword {\tt data} is optional and may be omitted along with the semicolon that follows it. \section{Coding data section} The {\it data section} is a sequence of data blocks in various formats, which are discussed in following sections. The order, in which data blocks follow in the data section, may be arbitrary, not necessarily the same, in which corresponding model objects follow in the model section. The rules of coding the data section are commonly the same as the rules of coding the model description (see Section \ref{coding}, page \pageref{coding}), i.e. data blocks are composed from basic lexical units such as symbolic names, numeric and string literals, keywords, delimiters, and comments. However, for the sake of convenience and for improving readability there is one deviation from the common rule: if a string literal consists of only alphanumeric characters (including the underscore character), the signs {\tt+} and {\tt-}, and/or the decimal point, it may be coded without bordering by (single or double) quotes. All numeric and symbolic material provided in the data section is coded in the form of numbers and symbols, i.e. unlike the model section no expressions are allowed in the data section. Nevertheless, the signs {\tt+} and {\tt-} can precede numeric literals to allow coding signed numeric quantities, in which case there should be no white-space characters between the sign and following numeric literal (if there is at least one white-space, the sign and following numeric literal are recognized as two different lexical units). \newpage \section{Set data block} \noindent \framebox[468pt][l]{ \parbox[c][44pt]{468pt}{ \hspace{6pt} {\tt set} {\it name} {\tt,} {\it record} {\tt,} \dots {\tt,} {\it record} {\tt;} \medskip \hspace{6pt} {\tt set} {\it name} {\tt[} {\it symbol} {\tt,} \dots {\tt,} {\it symbol} {\tt]} {\tt,} {\it record} {\tt,} \dots {\tt,} {\it record} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the set; \noindent {\it symbol}, \dots, {\it symbol} are subscripts, which specify a particular member of the set (if the set is an array, i.e. a set of sets); \noindent {\it record}, \dots, {\it record} are data records. \noindent Commae preceding data records may be omitted. \para{Data records} \vspace*{-8pt} \begin{description} \item[{\tt :=}]\hspace*{0pt}\\ is a non-significant data record, which may be used freely to improve readability; \item[{\tt(} {\it slice} {\tt)}]\hspace*{0pt}\\ specifies a slice; \item[{\it simple-data}]\hspace*{0pt}\\ specifies set data in the simple format; \item[{\tt:} {\it matrix-data}]\hspace*{0pt}\\ specifies set data in the matrix format; \item[{\tt(tr)} {\tt:} {\it matrix-data}]\hspace*{0pt}\\ specifies set data in the transposed matrix format. (In this case the colon following the keyword {\tt(tr)} may be omitted.) \end{description} \vspace*{-8pt} \para{Examples} \begin{verbatim} set month := Jan Feb Mar Apr May Jun; set month "Jan", "Feb", "Mar", "Apr", "May", "Jun"; set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4); set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 2 4; set A[3,'Mar'] : 1 2 3 4 := 1 - + - - 2 - + + - 3 + - - + 4 - + - + ; set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1); set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1; set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1); set B := (1,*,*) : 1 2 3 := 1 + - - 2 - + + 3 - + - (2,*,*) : 1 2 3 := 1 + - + 2 - - - 3 + - - ; \end{verbatim} \noindent(In these examples {\tt month} is a simple set of singlets, {\tt A} is a 2-dimensional array of doublets, and {\tt B} is a simple set of triplets. Data blocks for the same set are equivalent in the sense that they specify the same data in different formats.) The {\it set data block} is used to specify a complete elemental set, which is assigned to a set (if it is a simple set) or one of its members (if the set is an array of sets).\footnote{There is another way to specify data for a simple set along with data for parameters. This feature is discussed in the next section.} Data blocks can be specified only for non-computable sets, i.e. for sets, which have no assign attribute ({\tt:=}) in the corresponding set statements. If the set is a simple set, only its symbolic name should be specified in the header of the data block. Otherwise, if the set is a $n$-dimensional array, its symbolic name should be provided with a complete list of subscripts separated by commae and enclosed in square brackets to specify a particular member of the set array. The number of subscripts should be the same as the dimension of the set array, where each subscript should be a number or symbol. An elemental set defined in the set data block is coded as a sequence of data records described below.\footnote{{\it Data record} is simply a technical term. It does not mean that data records have any special formatting.} \subsection{Assign data record} The {\it assign data record} ({\tt:=}) is a non-signficant element. It may be used for improving readability of data blocks. \subsection{Slice data record} The {\it slice data record} is a control record, which specifies a {\it slice} of the elemental set defined in the data block. It has the following syntactic form: $$\mbox{{\tt(} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt)}}$$ where $s_1$, $s_2$, \dots, $s_n$ are components of the slice. Each component of the slice can be a number or symbol or the asterisk ({\tt*}). The number of components in the slice should be the same as the dimension of $n$-tuples in the elemental set to be defined. For instance, if the elemental set contains 4-tuples (quadruplets), the slice should have four components. The number of asterisks in the slice is called the {\it slice dimension}. The effect of using slices is the following. If a $m$-dimensional slice (i.e. a slice having $m$ asterisks) is specified in the data block, all subsequent data records should specify tuples of the dimension~$m$. Whenever a $m$-tuple is encountered, each asterisk in the slice is replaced by corresponding components of the $m$-tuple that gives the resultant $n$-tuple, which is included in the elemental set to be defined. For example, if the slice $(a,*,1,2,*)$ is in effect, and 2-tuple $(3,b)$ is encountered in a subsequent data record, the resultant 5-tuple included in the elemental set is $(a,3,1,2,b)$. The slice having no asterisks itself defines a complete $n$-tuple, which is included in the elemental set. Being once specified the slice effects until either a new slice or the end of data block is encountered. Note that if no slice is specified in the data block, one, components of which are all asterisks, is assumed. \subsection{Simple data record} The {\it simple data record} defines one $n$-tuple in a simple format and has the following syntactic form: $$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$}$$ where $t_1$, $t_2$, \dots, $t_n$ are components of the $n$-tuple. Each component can be a number or symbol. Commae between components are optional and may be omitted. \subsection{Matrix data record} The {\it matrix data record} defines several 2-tuples (doublets) in a matrix format and has the following syntactic form: $$\begin{array}{cccccc} \mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ \end{array}$$ where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols corresponding to rows of the matrix; $c_1$, $c_2$, \dots, $c_n$ are numbers and/or symbols corresponding to columns of the matrix, $a_{11}$, $a_{12}$, \dots, $a_{mn}$ are matrix elements, which can be either {\tt+} or {\tt-}. (In this data record the delimiter {\tt:} preceding the column list and the delimiter {\tt:=} following the column list cannot be omitted.) Each element $a_{ij}$ of the matrix data block (where $1\leq i\leq m$, $1\leq j\leq n$) corresponds to 2-tuple $(r_i,c_j)$. If $a_{ij}$ is the plus sign ({\tt+}), that 2-tuple (or a longer $n$-tuple, if a slice is used) is included in the elemental set. Otherwise, if $a_{ij}$ is the minus sign ({\tt-}), that 2-tuple is not included in the elemental set. Since the matrix data record defines 2-tuples, either the elemental set should consist of 2-tuples or the slice currently used should be 2-dimensional. \newpage \subsection{Transposed matrix data record} The {\it transposed matrix data record} has the following syntactic form: $$\begin{array}{cccccc} \mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ \end{array}$$ (In this case the delimiter {\tt:} following the keyword {\tt(tr)} is optional and may be omitted.) This data record is completely analogous to the matrix data record (see above) with only exception that in this case each element $a_{ij}$ of the matrix corresponds to 2-tuple $(c_j,r_i)$ rather than $(r_i,c_j)$. Being once specified the {\tt(tr)} indicator affects all subsequent data records until either a slice or the end of data block is encountered. \section{Parameter data block} \noindent \framebox[468pt][l]{ \parbox[c][88pt]{468pt}{ \hspace{6pt} {\tt param} {\it name} {\tt,} {\it record} {\tt,} \dots {\tt,} {\it record} {\tt;} \medskip \hspace{6pt} {\tt param} {\it name} {\tt default} {\it value} {\tt,} {\it record} {\tt,} \dots {\tt,} {\it record} {\tt;} \medskip \hspace{6pt} {\tt param} {\tt:} {\it tabbing-data} {\tt;} \medskip \hspace{6pt} {\tt param} {\tt default} {\it value} {\tt:} {\it tabbing-data} {\tt;} }} \medskip \noindent {\it name} is a symbolic name of the parameter; \noindent {\it value} is an optional default value of the parameter; \noindent {\it record}, \dots, {\it record} are data records; \noindent {\it tabbing-data} specifies parameter data in the tabbing format. \noindent Commae preceding data records may be omitted. \para{Data records} \vspace*{-8pt} \begin{description} \item[{\tt :=}]\hspace*{0pt}\\ is a non-significant data record, which may be used freely to improve readability; \item[{\tt[} {\it slice} {\tt]}]\hspace*{0pt}\\ specifies a slice; \item[{\it plain-data}]\hspace*{0pt}\\ specifies parameter data in the plain format; \item[{\tt:} {\it tabular-data}]\hspace*{0pt}\\ specifies parameter data in the tabular format; \item[{\tt(tr)} {\tt:} {\it tabular-data}]\hspace*{0pt}\\ specifies set data in the transposed tabular format. (In this case the colon following the keyword {\tt(tr)} may be omitted.) \end{description} \vspace*{-8pt} \para{Examples} \begin{verbatim} param T := 4; param month := 1 Jan 2 Feb 3 Mar 4 Apr 5 May; param month := [1] 'Jan', [2] 'Feb', [3] 'Mar', [4] 'Apr', [5] 'May'; param init_stock := iron 7.32 nickel 35.8; param init_stock [*] iron 7.32, nickel 35.8; param cost [iron] .025 [nickel] .03; param value := iron -.1, nickel .02; param : init_stock cost value := iron 7.32 .025 -.1 nickel 35.8 .03 .02 ; param : raw : init stock cost value := iron 7.32 .025 -.1 nickel 35.8 .03 .02 ; param demand default 0 (tr) : FRA DET LAN WIN STL FRE LAF := bands 300 . 100 75 . 225 250 coils 500 750 400 250 . 850 500 plate 100 . . 50 200 . 250 ; param trans_cost := [*,*,bands]: FRA DET LAN WIN STL FRE LAF := GARY 30 10 8 10 11 71 6 CLEV 22 7 10 7 21 82 13 PITT 19 11 12 10 25 83 15 [*,*,coils]: FRA DET LAN WIN STL FRE LAF := GARY 39 14 11 14 16 82 8 CLEV 27 9 12 9 26 95 17 PITT 24 14 17 13 28 99 20 [*,*,plate]: FRA DET LAN WIN STL FRE LAF := GARY 41 15 12 16 17 86 8 CLEV 29 9 13 9 28 99 18 PITT 26 14 17 13 31 104 20 ; \end{verbatim} The {\it parameter data block} is used to specify complete data for a parameter (or parameters, if data are specified in the tabbing format). Data blocks can be specified only for non-computable parameters, i.e. for parameters, which have no assign attribute ({\tt:=}) in the corresponding parameter statements. Data defined in the parameter data block are coded as a sequence of data records described below. Additionally the data block can be provided with the optional {\tt default} attribute, which specifies a default numeric or symbolic value of the parameter (parameters). This default value is assigned to the parameter or its members when no appropriate value is defined in the parameter data block. The {\tt default} attribute cannot be used, if it is already specified in the corresponding parameter statement. \subsection{Assign data record} The {\it assign data record} ({\tt:=}) is a non-signficant element. It may be used for improving readability of data blocks. \subsection{Slice data record} The {\it slice data record} is a control record, which specifies a {\it slice} of the parameter array. It has the following syntactic form: $$\mbox{{\tt[} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt]}}$$ where $s_1$, $s_2$, \dots, $s_n$ are components of the slice. Each component of the slice can be a number or symbol or the asterisk ({\tt*}). The number of components in the slice should be the same as the dimension of the parameter. For instance, if the parameter is a 4-dimensional array, the slice should have four components. The number of asterisks in the slice is called the {\it slice dimension}. The effect of using slices is the following. If a $m$-dimensional slice (i.e. a slice having $m$ asterisks) is specified in the data block, all subsequent data records should specify subscripts of the parameter members as if the parameter were $m$-dimensional, not $n$-dimensional. Whenever $m$ subscripts are encountered, each asterisk in the slice is replaced by corresponding subscript that gives $n$ subscripts, which define the actual parameter member. For example, if the slice $[a,*,1,2,*]$ is in effect, and subscripts 3 and $b$ are encountered in a subsequent data record, the complete subscript list used to choose a parameter member is $[a,3,1,2,b]$. It is allowed to specify a slice having no asterisks. Such slice itself defines a complete subscript list, in which case the next data record should define only a single value of corresponding parameter member. Being once specified the slice effects until either a new slice or the end of data block is encountered. Note that if no slice is specified in the data block, one, components of which are all asterisks, is assumed. \subsection{Plain data record} The {\it plain data record} defines a subscript list and a single value in the plain format. This record has the following syntactic form: $$\mbox{$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$}$$ where $t_1$, $t_2$, \dots, $t_n$ are subscripts, and $v$ is a value. Each subscript as well as the value can be a number or symbol. Commae following subscripts are optional and may be omitted. In case of 0-dimensional parameter or slice the plain data record has no subscripts and consists of a single value only. \subsection{Tabular data record} The {\it tabular data record} defines several values, where each value is provided with two subscripts. This record has the following syntactic form: $$\begin{array}{cccccc} \mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ \end{array}$$ where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols corresponding to rows of the table; $c_1$, $c_2$, \dots, $c_n$ are numbers and/or symbols corresponding to columns of the table, $a_{11}$, $a_{12}$, \dots, $a_{mn}$ are table elements. Each element can be a number or symbol or the single decimal point ({\tt.}). (In this data record the delimiter {\tt:} preceding the column list and the delimiter {\tt:=} following the column list cannot be omitted.) Each element $a_{ij}$ of the tabular data block ($1\leq i\leq m$, $1\leq j\leq n$) defines two subscripts, where the first subscript is $r_i$, and the second one is $c_j$. These subscripts are used in conjunction with the current slice to form the complete subscript list that identifies a particular member of the parameter array. If $a_{ij}$ is a number or symbol, this value is assigned to the parameter member. However, if $a_{ij}$ is the single decimal point, the member is assigned a default value specified either in the parameter data block or in the parameter statement, or, if no default value is specified, the member remains undefined. Since the tabular data record provides two subscripts for each value, either the parameter or the slice currently used should be 2-dimensional. \subsection{Transposed tabular data record} The {\it transposed tabular data record} has the following syntactic form: $$\begin{array}{cccccc} \mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\ r_1&a_{11}&a_{12}&\dots&a_{1n}&\\ r_2&a_{21}&a_{22}&\dots&a_{2n}&\\ \multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\ r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\ \end{array}$$ (In this case the delimiter {\tt:} following the keyword {\tt(tr)} is optional and may be omitted.) This data record is completely analogous to the tabular data record (see above) with only exception that the first subscript defined by element $a_{ij}$ is $c_j$ while the second one is $r_i$. Being once specified the {\tt(tr)} indicator affects all subsequent data records until either a slice or the end of data block is encountered. \newpage \subsection{Tabbing data format} The parameter data block in the {\it tabbing format} has the following syntactic form: $$ \begin{array}{*{8}{l}} \multicolumn{4}{l} {{\tt param}\ {\tt default}\ value\ {\tt :}\ s\ {\tt :}}& p_1\ \ \verb|,|&p_2\ \ \verb|,|&\dots\ \verb|,|&p_r\ \ \verb|:=|\\ r_{11}\ \verb|,|& r_{12}\ \verb|,|& \dots\ \verb|,|& r_{1n}\ \verb|,|& a_{11}\ \verb|,|& a_{12}\ \verb|,|& \dots\ \verb|,|& a_{1r}\ \verb|,|\\ r_{21}\ \verb|,|& r_{22}\ \verb|,|& \dots\ \verb|,|& r_{2n}\ \verb|,|& a_{21}\ \verb|,|& a_{22}\ \verb|,|& \dots\ \verb|,|& a_{2r}\ \verb|,|\\ \dots & \dots & \dots & \dots & \dots & \dots & \dots & \dots \\ r_{m1}\ \verb|,|& r_{m2}\ \verb|,|& \dots\ \verb|,|& r_{mn}\ \verb|,|& a_{m1}\ \verb|,|& a_{m2}\ \verb|,|& \dots\ \verb|,|& a_{mr}\ \verb|;|\\ \end{array} $$ 1. The keyword {\tt default} may be omitted along with a value following it. 2. Symbolic name $s$ may be omitted along with the colon following it. 3. All comae are optional and may be omitted. The data block in the tabbing format shown above is exactly equivalent to the following data blocks: \verb|set| $s$\ \verb|:=|\ $ \verb|(|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|) | \verb|(|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|) | \dots \verb| (|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|);|$ \verb|param| $p_1$\ \verb|default|\ $value$\ \verb|:=| $\verb| | \verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{11} \verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{21} \verb| |\dots \verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m1} \verb|;| $ \verb|param| $p_2$\ \verb|default|\ $value$\ \verb|:=| $\verb| | \verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{12} \verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{22} \verb| |\dots \verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{m2} \verb|;| $ \verb| |.\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ .\ \ \ . \verb|param| $p_r$\ \verb|default|\ $value$\ \verb|:=| $\verb| | \verb|[|r_{11}\verb|,|r_{12}\verb|,|\dots\verb|,|r_{1n}\verb|] |a_{1r} \verb| [|r_{21}\verb|,|r_{22}\verb|,|\dots\verb|,|r_{2n}\verb|] |a_{2r} \verb| |\dots \verb| [|r_{m1}\verb|,|r_{m2}\verb|,|\dots\verb|,|r_{mn}\verb|] |a_{mr} \verb|;| $ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \appendix \chapter{Using suffixes} \vspace*{-12pt} Suffixes can be used to retrieve additional values associated with model variables, constraints, and objectives. A {\it suffix} consists of a period ({\tt.}) followed by a non-reserved keyword. For example, if {\tt x} is a two-dimensional variable, {\tt x[i,j].lb} is a numeric value equal to the lower bound of elemental variable {\tt x[i,j]}, which (value) can be used everywhere in expressions like a numeric parameter. For model variables suffixes have the following meaning: \begin{tabular}{@{}ll@{}} {\tt.lb}&lower bound\\ {\tt.ub}&upper bound\\ {\tt.status}&status in the solution:\\ &0 --- undefined\\ &1 --- basic\\ &2 --- non-basic on lower bound\\ &3 --- non-basic on upper bound\\ &4 --- non-basic free (unbounded) variable\\ &5 --- non-basic fixed variable\\ {\tt.val}&primal value in the solution\\ {\tt.dual}&dual value (reduced cost) in the solution\\ \end{tabular} For model constraints and objectives suffixes have the following meaning: \begin{tabular}{@{}ll@{}} {\tt.lb}&lower bound of the linear form\\ {\tt.ub}&upper bound of the linear form\\ {\tt.status}&status in the solution:\\ &0 --- undefined\\ &1 --- non-active\\ &2 --- active on lower bound\\ &3 --- active on upper bound\\ &4 --- active free (unbounded) row\\ &5 --- active equality constraint\\ {\tt.val}&primal value of the linear form in the solution\\ {\tt.dual}&dual value (reduced cost) of the linear form in the solution\\ \end{tabular} Note that suffixes {\tt.status}, {\tt.val}, and {\tt.dual} can be used only below the solve statement. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Date and time functions} \noindent\hfil \begin{tabular}{c} by Andrew Makhorin \verb||\\ and Heinrich Schuchardt \verb||\\ \end{tabular} \section{Obtaining current calendar time} \label{gmtime} To obtain the current calendar time in MathProg there exists the function {\tt gmtime}. It has no arguments and returns the number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC). For example: \begin{verbatim} param utc := gmtime(); \end{verbatim} MathProg has no function to convert UTC time returned by the function {\tt gmtime} to {\it local} calendar times. Thus, if you need to determine the current local calendar time, you have to add to the UTC time returned the time offset from UTC expressed in seconds. For example, the time in Berlin during the winter is one hour ahead of UTC that corresponds to the time offset +1~hour~= +3600~secs, so the current winter calendar time in Berlin may be determined as follows: \begin{verbatim} param now := gmtime() + 3600; \end{verbatim} \noindent Similarly, the summer time in Chicago (Central Daylight Time) is five hours behind UTC, so the corresponding current local calendar time may be determined as follows: \begin{verbatim} param now := gmtime() - 5 * 3600; \end{verbatim} Note that the value returned by {\tt gmtime} is volatile, i.e. being called several times this function may return different values. \section{Converting character string to calendar time} \label{str2time} The function {\tt str2time(}{\it s}{\tt,} {\it f}{\tt)} converts a character string (timestamp) specified by its first argument {\it s}, which should be a symbolic expression, to the calendar time suitable for arithmetic calculations. The conversion is controlled by the specified format string {\it f} (the second argument), which also should be a symbolic expression. \newpage The result of conversion returned by {\tt str2time} has the same meaning as values returned by the function {\tt gmtime} (see Subsection \ref{gmtime}, page \pageref{gmtime}). Note that {\tt str2time} does {\tt not} correct the calendar time returned for the local timezone, i.e. being applied to 00:00:00 on January 1, 1970 it always returns 0. For example, the model statements: \begin{verbatim} param s, symbolic, := "07/14/98 13:47"; param t := str2time(s, "%m/%d/%y %H:%M"); display t; \end{verbatim} \noindent produce the following printout: \begin{verbatim} t = 900424020 \end{verbatim} \noindent where the calendar time printed corresponds to 13:47:00 on July 14, 1998. The format string passed to the function {\tt str2time} consists of conversion specifiers and ordinary characters. Each conversion specifier begins with a percent ({\tt\%}) character followed by a letter. The following conversion specifiers may be used in the format string: \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%b}&The abbreviated month name (case insensitive). At least three first letters of the month name should appear in the input string.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%d}&The day of the month as a decimal number (range 1 to 31). Leading zero is permitted, but not required.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%h}&The same as {\tt\%b}.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 0 to 23). Leading zero is permitted, but not required.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%m}&The month as a decimal number (range 1 to 12). Leading zero is permitted, but not required.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%M}&The minute as a decimal number (range 0 to 59). Leading zero is permitted, but not required.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%S}&The second as a decimal number (range 0 to 60). Leading zero is permitted, but not required.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%y}&The year without a century as a decimal number (range 0 to 99). Leading zero is permitted, but not required. Input values in the range 0 to 68 are considered as the years 2000 to 2068 while the values 69 to 99 as the years 1969 to 1999.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%z}&The offset from GMT in ISO 8601 format.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%\%}&A literal {\tt\%} character.\\ \end{tabular} All other (ordinary) characters in the format string should have a matching character in the input string to be converted. Exceptions are spaces in the input string which can match zero or more space characters in the format string. \newpage If some date and/or time component(s) are missing in the format and, therefore, in the input string, the function {\tt str2time} uses their default values corresponding to 00:00:00 on January 1, 1970, that is, the default value of the year is 1970, the default value of the month is January, etc. The function {\tt str2time} is applicable to all calendar times in the range 00:00:00 on January 1, 0001 to 23:59:59 on December 31, 4000 of the Gregorian calendar. \section{Converting calendar time to character string} \label{time2str} The function {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} converts the calendar time specified by its first argument {\it t}, which should be a numeric expression, to a character string (symbolic value). The conversion is controlled by the specified format string {\it f} (the second argument), which should be a symbolic expression. The calendar time passed to {\tt time2str} has the same meaning as values returned by the function {\tt gmtime} (see Subsection \ref{gmtime}, page \pageref{gmtime}). Note that {\tt time2str} does {\it not} correct the specified calendar time for the local timezone, i.e. the calendar time 0 always corresponds to 00:00:00 on January 1, 1970. For example, the model statements: \begin{verbatim} param s, symbolic, := time2str(gmtime(), "%FT%TZ"); display s; \end{verbatim} \noindent may produce the following printout: \begin{verbatim} s = '2008-12-04T00:23:45Z' \end{verbatim} \noindent which is a timestamp in the ISO format. The format string passed to the function {\tt time2str} consists of conversion specifiers and ordinary characters. Each conversion specifier begins with a percent ({\tt\%}) character followed by a letter. The following conversion specifiers may be used in the format string: \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%a}&The abbreviated (2-character) weekday name.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%A}&The full weekday name.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%b}&The abbreviated (3-character) month name.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%B}&The full month name.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%C}&The century of the year, that is the greatest integer not greater than the year divided by~100.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%d}&The day of the month as a decimal number (range 01 to 31).\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%D}&The date using the format \verb|%m/%d/%y|.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%e}&The day of the month like with \verb|%d|, but padded with blank rather than zero.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%F}&The date using the format \verb|%Y-%m-%d|.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%g}&The year corresponding to the ISO week number, but without the century (range 00 to~99). This has the same format and value as \verb|%y|, except that if the ISO week number (see \verb|%V|) belongs to the previous or next year, that year is used instead.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%G}&The year corresponding to the ISO week number. This has the same format and value as \verb|%Y|, except that if the ISO week number (see \verb|%V|) belongs to the previous or next year, that year is used instead. \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%h}&The same as \verb|%b|.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 00 to 23).\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%I}&The hour as a decimal number, using a 12-hour clock (range 01 to 12).\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%j}&The day of the year as a decimal number (range 001 to 366).\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%k}&The hour as a decimal number, using a 24-hour clock like \verb|%H|, but padded with blank rather than zero.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%l}&The hour as a decimal number, using a 12-hour clock like \verb|%I|, but padded with blank rather than zero. \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%m}&The month as a decimal number (range 01 to 12).\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%M}&The minute as a decimal number (range 00 to 59).\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%p}&Either {\tt AM} or {\tt PM}, according to the given time value. Midnight is treated as {\tt AM} and noon as {\tt PM}.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%P}&Either {\tt am} or {\tt pm}, according to the given time value. Midnight is treated as {\tt am} and noon as {\tt pm}.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%R}&The hour and minute in decimal numbers using the format \verb|%H:%M|.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%S}&The second as a decimal number (range 00 to 59).\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%T}&The time of day in decimal numbers using the format \verb|%H:%M:%S|.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%u}&The day of the week as a decimal number (range 1 to 7), Monday being 1.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%U}&The week number of the current year as a decimal number (range 00 to 53), starting with the first Sunday as the first day of the first week. Days preceding the first Sunday in the year are considered to be in week 00. \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%V}&The ISO week number as a decimal number (range 01 to 53). ISO weeks start with Monday and end with Sunday. Week 01 of a year is the first week which has the majority of its days in that year; this is equivalent to the week containing January 4. Week 01 of a year can contain days from the previous year. The week before week 01 of a year is the last week (52 or 53) of the previous year even if it contains days from the new year. In other word, if 1 January is Monday, Tuesday, Wednesday or Thursday, it is in week 01; if 1 January is Friday, Saturday or Sunday, it is in week 52 or 53 of the previous year.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%w}&The day of the week as a decimal number (range 0 to 6), Sunday being 0.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%W}&The week number of the current year as a decimal number (range 00 to 53), starting with the first Monday as the first day of the first week. Days preceding the first Monday in the year are considered to be in week 00.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%y}&The year without a century as a decimal number (range 00 to 99), that is the year modulo~100.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%Y}&The year as a decimal number, using the Gregorian calendar.\\ \end{tabular} \begin{tabular}{@{}p{20pt}p{421.5pt}@{}} {\tt\%\%}&A literal \verb|%| character.\\ \end{tabular} All other (ordinary) characters in the format string are simply copied to the resultant string. The first argument (calendar time) passed to the function {\tt time2str} should be in the range from $-62135596800$ to $+64092211199$ that corresponds to the period from 00:00:00 on January 1, 0001 to 23:59:59 on December 31, 4000 of the Gregorian calendar. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Table drivers} \label{drivers} \noindent\hfil \begin{tabular}{c} by Andrew Makhorin \verb||\\ and Heinrich Schuchardt \verb||\\ \end{tabular} \bigskip\bigskip The {\it table driver} is a program module which provides transmitting data between MathProg model objects and data tables. Currently the GLPK package has four table drivers: \vspace*{-8pt} \begin{itemize} \item built-in CSV table driver; \item built-in xBASE table driver; \item ODBC table driver; \item MySQL table driver. \end{itemize} \vspace*{-8pt} \section{CSV table driver} The CSV table driver assumes that the data table is represented in the form of a plain text file in the CSV (comma-separated values) file format as described below. To choose the CSV table driver its name in the table statement should be specified as \verb|"CSV"|, and the only argument should specify the name of a plain text file containing the table. For example: \begin{verbatim} table data IN "CSV" "data.csv": ... ; \end{verbatim} The filename suffix may be arbitrary, however, it is recommended to use the suffix `\verb|.csv|'. On reading input tables the CSV table driver provides an implicit field named \verb|RECNO|, which contains the current record number. This field can be specified in the input table statement as if there were the actual field named \verb|RECNO| in the CSV file. For example: \begin{verbatim} table list IN "CSV" "list.csv": num <- [RECNO], ... ; \end{verbatim} \newpage \subsection*{CSV format\footnote{This material is based on the RFC document 4180.}} The CSV (comma-separated values) format is a plain text file format defined as follows. 1. Each record is located on a separate line, delimited by a line break. For example: \begin{verbatim} aaa,bbb,ccc\n xxx,yyy,zzz\n \end{verbatim} \noindent where \verb|\n| means the control character \verb|LF| ({\tt 0x0A}). 2. The last record in the file may or may not have an ending line break. For example: \begin{verbatim} aaa,bbb,ccc\n xxx,yyy,zzz \end{verbatim} 3. There should be a header line appearing as the first line of the file in the same format as normal record lines. This header should contain names corresponding to the fields in the file. The number of field names in the header line should be the same as the number of fields in the records of the file. For example: \begin{verbatim} name1,name2,name3\n aaa,bbb,ccc\n xxx,yyy,zzz\n \end{verbatim} 4. Within the header and each record there may be one or more fields separated by commas. Each line should contain the same number of fields throughout the file. Spaces are considered as part of a field and therefore not ignored. The last field in the record should not be followed by a comma. For example: \begin{verbatim} aaa,bbb,ccc\n \end{verbatim} 5. Fields may or may not be enclosed in double quotes. For example: \begin{verbatim} "aaa","bbb","ccc"\n zzz,yyy,xxx\n \end{verbatim} 6. If a field is enclosed in double quotes, each double quote which is part of the field should be coded twice. For example: \begin{verbatim} "aaa","b""bb","ccc"\n \end{verbatim} \para{Example} \begin{verbatim} FROM,TO,DISTANCE,COST Seattle,New-York,2.5,0.12 Seattle,Chicago,1.7,0.08 Seattle,Topeka,1.8,0.09 San-Diego,New-York,2.5,0.15 San-Diego,Chicago,1.8,0.10 San-Diego,Topeka,1.4,0.07 \end{verbatim} \newpage \section{xBASE table driver} The xBASE table driver assumes that the data table is stored in the .dbf file format. To choose the xBASE table driver its name in the table statement should be specified as \verb|"xBASE"|, and the first argument should specify the name of a .dbf file containing the table. For the output table there should be the second argument defining the table format in the form \verb|"FF...F"|, where \verb|F| is either {\tt C({\it n})}, which specifies a character field of length $n$, or {\tt N({\it n}{\rm [},{\it p}{\rm ]})}, which specifies a numeric field of length $n$ and precision $p$ (by default $p$ is 0). The following is a simple example which illustrates creating and reading a .dbf file: \begin{verbatim} table tab1{i in 1..10} OUT "xBASE" "foo.dbf" "N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A, "?" ~ FOO, "[" & i & "]" ~ C; set S, dimen 4; table tab2 IN "xBASE" "foo.dbf": S <- [B, C, RECNO, A]; display S; end; \end{verbatim} \section{ODBC table driver} The ODBC table driver allows connecting to SQL databases using an implementation of the ODBC interface based on the Call Level Interface (CLI).\footnote{The corresponding software standard is defined in ISO/IEC 9075-3:2003.} \para{Debian GNU/Linux.} Under Debian GNU/Linux the ODBC table driver uses the iODBC package,\footnote{See {\tt}.} which should be installed before building the GLPK package. The installation can be effected with the following command: \begin{verbatim} sudo apt-get install libiodbc2-dev \end{verbatim} Note that on configuring the GLPK package to enable using the iODBC library the option `\verb|--enable-odbc|' should be passed to the configure script. The individual databases should be entered for systemwide usage in \verb|/etc/odbc.ini| and\linebreak \verb|/etc/odbcinst.ini|. Database connections to be used by a single user are specified by files in the home directory (\verb|.odbc.ini| and \verb|.odbcinst.ini|). \para{Microsoft Windows.} Under Microsoft Windows the ODBC table driver uses the Microsoft ODBC library. To enable this feature the symbol: \begin{verbatim} #define ODBC_DLNAME "odbc32.dll" \end{verbatim} \noindent should be defined in the GLPK configuration file `\verb|config.h|'. Data sources can be created via the Administrative Tools from the Control Panel. To choose the ODBC table driver its name in the table statement should be specified as \verb|'ODBC'| or \verb|'iODBC'|. \newpage The argument list is specified as follows. The first argument is the connection string passed to the ODBC library, for example: \verb|'DSN=glpk;UID=user;PWD=password'|, or \verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|. Different parts of the string are separated by semicolons. Each part consists of a pair {\it fieldname} and {\it value} separated by the equal sign. Allowable fieldnames depend on the ODBC library. Typically the following fieldnames are allowed: \verb|DATABASE | database; \verb|DRIVER | ODBC driver; \verb|DSN | name of a data source; \verb|FILEDSN | name of a file data source; \verb|PWD | user password; \verb|SERVER | database; \verb|UID | user name. The second argument and all following are considered to be SQL statements SQL statements may be spread over multiple arguments. If the last character of an argument is a semicolon this indicates the end of a SQL statement. The arguments of a SQL statement are concatenated separated by space. The eventual trailing semicolon will be removed. All but the last SQL statement will be executed directly. For IN-table the last SQL statement can be a SELECT command starting with the capitalized letters \verb|'SELECT '|. If the string does not start with \verb|'SELECT '| it is considered to be a table name and a SELECT statement is automatically generated. For OUT-table the last SQL statement can contain one or multiple question marks. If it contains a question mark it is considered a template for the write routine. Otherwise the string is considered a table name and an INSERT template is automatically generated. The writing routine uses the template with the question marks and replaces the first question mark by the first output parameter, the second question mark by the second output parameter and so forth. Then the SQL command is issued. The following is an example of the output table statement: \begin{verbatim} table ta { l in LOCATIONS } OUT 'ODBC' 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' 'DROP TABLE IF EXISTS result;' 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' 'INSERT INTO result 'VALUES ( 4, ?, ? )' : l ~ LOC, quantity[l] ~ QUAN; \end{verbatim} \newpage \noindent Alternatively it could be written as follows: \begin{verbatim} table ta { l in LOCATIONS } OUT 'ODBC' 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' 'DROP TABLE IF EXISTS result;' 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' 'result' : l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; \end{verbatim} Using templates with `\verb|?|' supports not only INSERT, but also UPDATE, DELETE, etc. For example: \begin{verbatim} table ta { l in LOCATIONS } OUT 'ODBC' 'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword' 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : quantity[l], l; \end{verbatim} \section{MySQL table driver} The MySQL table driver allows connecting to MySQL databases. \para{Debian GNU/Linux.} Under Debian GNU/Linux the MySQL table driver uses the MySQL package,\footnote{For download development files see {\tt}.} which should be installed before building the GLPK package. The installation can be effected with the following command: \begin{verbatim} sudo apt-get install libmysqlclient15-dev \end{verbatim} Note that on configuring the GLPK package to enable using the MySQL library the option `\verb|--enable-mysql|' should be passed to the configure script. \para{Microsoft Windows.} Under Microsoft Windows the MySQL table driver also uses the MySQL library. To enable this feature the symbol: \begin{verbatim} #define MYSQL_DLNAME "libmysql.dll" \end{verbatim} \noindent should be defined in the GLPK configuration file `\verb|config.h|'. To choose the MySQL table driver its name in the table statement should be specified as \verb|'MySQL'|. The argument list is specified as follows. The first argument specifies how to connect the data base in the DSN style, for example: \verb|'Database=glpk;UID=glpk;PWD=gnu'|. Different parts of the string are separated by semicolons. Each part consists of a pair {\it fieldname} and {\it value} separated by the equal sign. The following fieldnames are allowed: \newpage \verb|Server | server running the database (defaulting to localhost); \verb|Database | name of the database; \verb|UID | user name; \verb|PWD | user password; \verb|Port | port used by the server (defaulting to 3306). The second argument and all following are considered to be SQL statements. SQL statements may be spread over multiple arguments. If the last character of an argument is a semicolon this indicates the end of a SQL statement. The arguments of a SQL statement are concatenated separated by space. The eventual trailing semicolon will be removed. All but the last SQL statement will be executed directly. For IN-table the last SQL statement can be a SELECT command starting with the capitalized letters \verb|'SELECT '|. If the string does not start with \verb|'SELECT '| it is considered to be a table name and a SELECT statement is automatically generated. For OUT-table the last SQL statement can contain one or multiple question marks. If it contains a question mark it is considered a template for the write routine. Otherwise the string is considered a table name and an INSERT template is automatically generated. The writing routine uses the template with the question marks and replaces the first question mark by the first output parameter, the second question mark by the second output parameter and so forth. Then the SQL command is issued. The following is an example of the output table statement: \begin{verbatim} table ta { l in LOCATIONS } OUT 'MySQL' 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' 'DROP TABLE IF EXISTS result;' 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' 'INSERT INTO result VALUES ( 4, ?, ? )' : l ~ LOC, quantity[l] ~ QUAN; \end{verbatim} \noindent Alternatively it could be written as follows: \begin{verbatim} table ta { l in LOCATIONS } OUT 'MySQL' 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' 'DROP TABLE IF EXISTS result;' 'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );' 'result' : l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID; \end{verbatim} \newpage Using templates with `\verb|?|' supports not only INSERT, but also UPDATE, DELETE, etc. For example: \begin{verbatim} table ta { l in LOCATIONS } OUT 'MySQL' 'Database=glpkdb;UID=glpkuser;PWD=glpkpassword' 'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;' 'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' : quantity[l], l; \end{verbatim} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Solving models with glpsol} The GLPK package\footnote{{\tt http://www.gnu.org/software/glpk/}} includes the program {\tt glpsol}, a stand-alone LP/MIP solver. This program can be launched from the command line or from the shell to solve models written in the GNU MathProg modeling language. To tell the solver that the input file contains a model description you need to specify the option \verb|--model| in the command line. For example: \begin{verbatim} glpsol --model foo.mod \end{verbatim} Sometimes it is necessary to use the data section placed in a separate file, in which case you may use the following command: \begin{verbatim} glpsol --model foo.mod --data foo.dat \end{verbatim} \noindent Note that if the model file also contains the data section, that section is ignored. It is also allowed to specify more than one file containing the data section, for example: \begin{verbatim} glpsol --model foo.mod --data foo1.dat --data foo2.dat \end{verbatim} If the model description contains some display and/or printf statements, by default the output is sent to the terminal. If you need to redirect the output to a file, you may use the following command: \begin{verbatim} glpsol --model foo.mod --display foo.out \end{verbatim} If you need to look at the problem, which has been generated by the model translator, you may use the option \verb|--wlp| as follows: \begin{verbatim} glpsol --model foo.mod --wlp foo.lp \end{verbatim} \noindent In this case the problem data is written to file \verb|foo.lp| in CPLEX LP format suitable for visual analysis. Sometimes it is needed merely to check the model description not solving the generated problem instance. In this case you may specify the option \verb|--check|, for example: \begin{verbatim} glpsol --check --model foo.mod --wlp foo.lp \end{verbatim} \newpage If you need to write a numeric solution obtained by the solver to a file, you may use the following command: \begin{verbatim} glpsol --model foo.mod --output foo.sol \end{verbatim} \noindent in which case the solution is written to file \verb|foo.sol| in a plain text format suitable for visual analysis. The complete list of the \verb|glpsol| options can be found in the GLPK reference manual included in the GLPK distribution. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Example model description} \section{Model description written in MathProg} Below here is a complete example of the model description written in the GNU MathProg modeling language. \bigskip \begin{verbatim} # A TRANSPORTATION PROBLEM # # This problem finds a least cost shipping schedule that meets # requirements at markets and supplies at factories. # # References: # Dantzig G B, "Linear Programming and Extensions." # Princeton University Press, Princeton, New Jersey, 1963, # Chapter 3-3. set I; /* canning plants */ set J; /* markets */ param a{i in I}; /* capacity of plant i in cases */ param b{j in J}; /* demand at market j in cases */ param d{i in I, j in J}; /* distance in thousands of miles */ param f; /* freight in dollars per case per thousand miles */ param c{i in I, j in J} := f * d[i,j] / 1000; /* transport cost in thousands of dollars per case */ var x{i in I, j in J} >= 0; /* shipment quantities in cases */ minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; /* total transportation costs in thousands of dollars */ s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; /* observe supply limit at plant i */ s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; /* satisfy demand at market j */ data; set I := Seattle San-Diego; set J := New-York Chicago Topeka; param a := Seattle 350 San-Diego 600; param b := New-York 325 Chicago 300 Topeka 275; param d : New-York Chicago Topeka := Seattle 2.5 1.7 1.8 San-Diego 2.5 1.8 1.4 ; param f := 90; end; \end{verbatim} \newpage \section{Generated LP problem instance} Below here is the result of the translation of the example model produced by the solver \verb|glpsol| and written in CPLEX LP format with the option \verb|--wlp|. \medskip \begin{verbatim} \* Problem: transp *\ Minimize cost: + 0.225 x(Seattle,New~York) + 0.153 x(Seattle,Chicago) + 0.162 x(Seattle,Topeka) + 0.225 x(San~Diego,New~York) + 0.162 x(San~Diego,Chicago) + 0.126 x(San~Diego,Topeka) Subject To supply(Seattle): + x(Seattle,New~York) + x(Seattle,Chicago) + x(Seattle,Topeka) <= 350 supply(San~Diego): + x(San~Diego,New~York) + x(San~Diego,Chicago) + x(San~Diego,Topeka) <= 600 demand(New~York): + x(Seattle,New~York) + x(San~Diego,New~York) >= 325 demand(Chicago): + x(Seattle,Chicago) + x(San~Diego,Chicago) >= 300 demand(Topeka): + x(Seattle,Topeka) + x(San~Diego,Topeka) >= 275 End \end{verbatim} \section{Optimal LP solution} Below here is the optimal solution of the generated LP problem instance found by the solver \verb|glpsol| and written in plain text format with the option \verb|--output|. \medskip \begin{footnotesize} \begin{verbatim} Problem: transp Rows: 6 Columns: 6 Non-zeros: 18 Status: OPTIMAL Objective: cost = 153.675 (MINimum) No. Row name St Activity Lower bound Upper bound Marginal ------ ------------ -- ------------- ------------- ------------- ------------- 1 cost B 153.675 2 supply[Seattle] NU 350 350 < eps 3 supply[San-Diego] B 550 600 4 demand[New-York] NL 325 325 0.225 5 demand[Chicago] NL 300 300 0.153 6 demand[Topeka] NL 275 275 0.126 No. Column name St Activity Lower bound Upper bound Marginal ------ ------------ -- ------------- ------------- ------------- ------------- 1 x[Seattle,New-York] B 50 0 2 x[Seattle,Chicago] B 300 0 3 x[Seattle,Topeka] NL 0 0 0.036 4 x[San-Diego,New-York] B 275 0 5 x[San-Diego,Chicago] NL 0 0 0.009 6 x[San-Diego,Topeka] B 275 0 End of output \end{verbatim} \end{footnotesize} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section*{Acknowledgements} \addcontentsline{toc}{chapter}{Acknowledgements} The authors would like to thank the following people, who kindly read, commented, and corrected the draft of this document: \noindent Juan Carlos Borras \verb|| \noindent Harley Mackenzie \verb|| \noindent Robbie Morrison \verb|| \end{document} glpk-4.52.1/doc/graphs.pdf0000666000062000006210000064270612175147600014470 0ustar maomkpasswd%PDF-1.5 %äðíø 7 0 obj <> stream xÚ-MOÃ0 †ïü ‰š8_m›`“Ø4)ãÂ8T[7*h;²"þ>ù@Ž,Ûzýä5|APÊð{˜;xXHÖ*pg¨* R5ÊÜé-7{^(kÙºÚ†+Á|î·~¼ø¦ï»á%[uwÏ(J”d"Q´ Sbm2Ð7×°AŠ5Ã)šmÚ‰KË~ccòŸY±¦ðï-ƒÍŠJV uÎÚ,]®·«\½riXëoÝ8äF]ÿ[S@•¶ÑY WF£Q‰w`»ÙÂ݇­À]½ûŠ­aR:ð„yrðr÷Ö‹Q¢ endstream endobj 13 0 obj <> stream xÚVM“â6½çWø(ªÀ+YþâÈ&™Ô$™Ô$Ëž’4¶cYÌÖþûíVËØ,s˜‚*äׯ¥þx-“üŸˆ„ÃG$U_ž4§äã6ùð'‚§k¾N¶;0¯rY§¼H¶íßl{Ћ•”’ýòûóo´:«f‘Uì¸( ¦öÁœ13ŒFçq•3»#Ä_wøã3Yž]¬Àù?ÝD®ÓVƒn‰xé[ínœs¦ô~<³´W2åy²)ÿpQDÖ¼8"Oe "%ãœ/!±Æ¥ÀeÆq™M¨œÐ|Z¡œÐjBë ]_QÁ¯¨˜Ní%Ûô­Ó_BÈ«²HsE‘iA]|Rǃu¦G¯ª`?ilÓI÷X)lAY²Å’—ÛœÏ ­(köØ~RÞ4Cô}²CcÑï ùm^ ˜mOÎýà¿xØåŒÝÿº ƒQ)ô?/Ø¦ë® ¼ÆJƒ¸R–Óƒv¯ˆèö~?,j œ(ÃOvçY ÁAë•‹(p2fAV!Ò%}“.I\… EžSý±3}ÜÏ/£ÉìüØÈ±.º´ƒÛJö´¡_ž Á!-°>Ú¼þsHÌ ”‹˜U"ÌRVel¡„J`7Ðà-NêÜU}KpkïÌ TŸž_±Ú½@Ö'¢6öltÜÇýa<ïDÇ]TGì³ ­{5í5€Cܺ¹™²*NÙM{ ª‰£B¤y¦)ÎÙ9Ôp–9‚7>..Σ ™–ÚB|à€€‚#%öŽúJ^Ò]Å«Ûú¢닆]ɾJÁ<¯/>Ÿ°5ÀpYä:’H©OÈ?ÜW¼sGÇY¡‘1^x`¢ /ÄзƇ]îJK³*ùxXì0"ccL¿ºû¾‹ÈQÝ`iåÊ+^´‚ÅKÁPõ9Žß¥ó°=B fjE¶ÆIÃQ8’™º+f¥j ¸Þé<u—’‡}w¿«w ‹17¡  ÐH rƒM{ýuäÐNôÈ!Ìu 7Íg%FtMêÀÅ\Hóà?tŠZ˜X°„¨™ Ÿ hé@Y°jèÔ©~×íò¾v÷ïK(ÞKÐ&µ/ÈÏdž£”äb0Þ AÌT¾Ÿ·÷ÿ2)Ò¬‚×N^Ó‹qdþùÃ7)n:Ó endstream endobj 46 0 obj <> stream xÚí[ËrÛ6Ý÷+¸”Bˆ7±lúšv¦¦õ®é‚‘h…D:7~|âueÊì©;Í$3Ä‹s)œƒƒY¼-pQê¸Dÿ/‹õ¾x~Q<ûV„!YÉââR_^© Q\l~[|ÕwCÓ Çåï?è8Yà©R¹8ÁÅc^®á‹çõ±]/W´¢‹ïõÕkûñËŸ¿·~éß m×X´o.ܽüòûpØÚ»Y˜ÀHÒb…9CJ޹x¬njºJ TÂQ¡ëˆ qbïé;Ä%!á¾(]\úí¡Þ›[ô¯–+Î4ëa¹D-.—åÿçÏ<'ì„‚8?iß|N*‚Jé8!SNÖ‡¦ÖÙZRênc¿Þ÷Ë©›öòƒ»H¯¦eâÑ4&SêÁÚ;¶]•lo†3uGÂ÷2öÌØb»»òo DUU\ #.l FŠ}¡ªX(ïŠ_‹Ó4 È¥l&èX;L‰<&‘*…£\‚mTËß@4ýì®J†?í¾Û#[ ¤T‡¾7ö¾„HY× Zpåy-€4Çf˜ AcT `c¬u)Rà1* [ª'ø¬D˜@|Fõ¥$~ˆ ø]½oNtVí¶³Ÿ_.ÖK"¯ënÛ¼\šïT¦­Ë8}¤ú?3_?„ ‰ƒ~h†~t ¼Ä•ú‰iêÍfÊ/¦Æ#66CKF9ô÷K"Íah×ã ¢ ô»AvqYÊG½û÷Ѩ­Š³û%Åû~Is6)-ÍHû¥-'úeL“ØD ð~{p?F…ï§Ø”"¡ ¶^à(‘ÄQ»í6~õæ&€pƒòtG ‘ùzBà§Ñ«*ò¥Ä˜?[2RÊØƒ45í]9!¥˜æe‰Yw~($€7Ë;ÅSø0J„iWìÎç]^Ϲ€œ¿2ø`?·ÃÑm6BÂFØÍ—¯‰î’±­hj”Ð]l9!‰˜&5ê{ø0žÏâÃ(2ç.%‡ØÚ7(Mbƒ(rÞ]èÍå¥8ç.Ôד²zRªÀÙs‰‘ôî¦smÃ=[xv}hã!cœ5p*ÿ·gº¾ÙA ’ì\ñð bYó]ÃlˉÓ"ÏXº@˜p³¤K‚ƒ zÛœ}LwsùôW»ºíìuÝñ†èÿ;cèD>rÊ{ù”« Uc¼6À) -ÎsÌvuì:ñ,2ˆ±Èëõ¦ê»tô3D#«ýûõ÷?~i&v_ýêöwvíÛwͳu¿ëf´1?bŬðôì“Ûv¿ìûZ£²'õÄÂ#ö3F¸™¢ú¤Ùš¦ E;Ë8Û4(ÐôXLh:ä˜÷2íMjñÛd=ïdÓ1Ë®FÏ©šÜ¢j=®>«ú!UÍÇĨÐì§í˜Ð¼8Uóét¸îê݇c{¼9®>µyð¿LElU‘í/U‰°7ž3EfR‹cË ‹‰i®Çm‰úÍY›ÇNŸ`<ÂH%ðA1Áºß_ݲãÁõnç¬gÜîªßìÜvǺïºf=4.΂è;í»Æž†¸£ÓþòįÈçG÷`0”O«¢HV3fÁ¦$u,&8 9ŽÃ¡wŽ{ºoÁÇíMI5Ì΂à y>í=X6é-lJǦ¸M™\݃¿HE6}¼”ˆÄ^™1•55J@ +Ï3Ò ýÕ™‰Í刭oÂ<É–‡Qý؆ Mº±wíúm»®=‡:,lxjêõ=´»ÃêMëŸSQì±Ù/$íüÃk7^Sàû‡Ýˆ}Oá§fXR¬½ÉHóðÆ¼ ?\ í¾ý«Ú¾;yq wxqs+1<ûì‹3"áͅۮ݋|·÷ïçm¼7—®Ã› ¯vÍÞÝ'â-›}.͹^%{6ÂØý¼ßlµ:ŒM²Š<‰¦{¸3Ê{Ð[6Ÿ I厌A×ÔÀдm9aÚ1ÍìDwû óà ÈïÛ.väÉ6Äþ´Ó“i§¶Ó“ØéGwKÀ³ë¸Ïÿ¸+Ž”Õiúƒèq‚HóNíaçâÅÿ\¼÷^ endstream endobj 78 0 obj <> stream xÚíZKÛ6¾÷WèVù`V|J:nÒ$H› y,ŠMŠ­µÛ’#k³Û"?¾¤ø”í¹ §Ý´F‚HtÈq¾oF3#FŸ"%üŒRÄÿ&Ñl=¹Œ~xN"˜€<ɣ˫ˆ@@h4?°èrþ{Œx2…x±ÞNþ¸ü)zv}ŠÎ³è&Ê! ¬_²hådD×Ñûèí¡;Gé¸i«®< a.„Ñaød;“”ðMUÏš]7™bŒã/ò"ö·ü¿«Í¥ñõFþ`'H mÄÝÈñ¶m>®K5m^t…¼«jq%ñ/__ˆÙOß÷[™XÆŸJû'¹jÚMÁec0™Ò$9_œ‹Â_RôÝ uÓ.Ž”¦€ßMJ–»\¬\ÜÉlœÄ2›ø™S9Ì–Ãqf[š|ÜÆPd…CLAš{¤›IF<jKk©[ ~ž ,.ÛžÅHœ)‚£P‚w¼¾z3™æ4ûGu@¢¡ÀR4ÀR?°|X9Öêð«…kÌF¥;“”øf5¡4.Ö‹AØÚ5ëÏ®ã¡ë²L"‹†ÈÞTÝR¦¹î¦ÍÕtU­»²•Q‹æ€`7jñ‡hx¸\òÅ,?®2šQ£ÓPF§H ¡™ŸÐ|>u-‡ã„6*||Ö²5UG…;“¤ô¶\·d«\F~ k.c©£è*ySvKÓxlœËÍ•¼>á±rWr#q±“SÔjÎ宬ò‰?Äïž½ºømúò×N†¿%þå iœ„ò&d†€iHHÁ C_¨uÔe·(ëA¼ûy]Õ‹MQ¿“c>Eò€ÿÓ´«#¡K(Û¢kZþ° DÆüv››Ÿç¿˜ûgöç+ ucV‚à  ¾ 與8(óÉwg)«Q„w÷¼¢K³xgï=÷¯j±bƃIÉWÏnã`ôxàÌ xyx|Aê`×=Ћ¶šï{ømº®VN”í Ê8qˆBøHƒ™Ý7öçý,ÌËË1¢½ ‰ð€Püº¸¾u†ïÇ6fçôfk]œß@–h<Tò¤˜ †®ms-ÞÁ$Cß„áHž?0”]ïDj²$ ˆV|v_5rì‰WVM[ó# v„‹ÈëîLÒ™^q»ïÈ_t’X¨wËfèúh¼dÒÝ¢º=ø°Û£úNçnÏW£u–Yã,”Ø(I³ÄhdŠÄ!¶ÛQ3ÞË4ÒuŸr\¼;‹ís;ÓÑ‘¦¦$7Û'÷¹•ùh[™Ô›–×gˆçå©%w@/S¬ .¹åØCn«fH¾Ã^_;Z ÎD×ãƥô úšøX_ß3€Ën&é»™H– §|e?p»[ƒçWlèqŠNKH=ph+Æ1î$©„kÀ¾>çHû:BÏ'¶ôÅÙ. Næ1ãïHë½ɼX‘¸Þ+ǰ­/ØZ¾qT;KiÈAwbð¢mkÓ#'oX’ô|òæäN™8ŒÒS8ü”`žl)pöA¬€.…åØCa«ÆKa-ßsT;KiXëõ bñr–Ô*ëûXm‹¶sÈ]ÿ*\Vµb¼~4cfE;¯êb]õŸ–ÿœL3’žD» š†–¶$Á¢C%A$ª´}Ê=ªšÊÛB…3~šrö*/ ŽmYpÚÀTRr®kO‰‡5í=ðÀü—ÌàP׊if£œG9GÍl»½»ÓËc‰ãœÄ8§Û{béƃ¬UØñ<:uV%|¥€ÈÈëØÑøE[l……2ÿ²íªMõ—<ÿØÿrñ楼yÇsŠWžgLÏH%A¬JÜQ$,¹:žÓûøÑ“6³uõéºÜƒ÷ÿqÊæ\±&eÁ9 £úËÇámO‰‡5í=ðÈ™X¬ñ‰¶9/YmåØm­šþœŸr´Ã¼2Œ8:D¢™#Ÿ;Ëh)o‹Y7(‹lbyä#Jz·¬Kñpj Ä©‘Œ`ì–Bèî*ù@Úm‰0‡—hŒÈ¸mV¼ýîo"(ÿ” endstream endobj 90 0 obj <> stream xÚ•X[oÛ6~߯ö$1'Þti±‡vhƒlÁÐK¶—e›±µÊ’+ÉIôÇi‡NS´¨IñðÜx¾siò9¡IhR0ø›%‹Mòú*ùù-MXFòœ'W·p<¯Ì&¹ZþþºVÛQ÷³9Ïó”Îþ¹ú ¨ó„ R”…£–°©,õk5Ô ¤=ïÕvm–EúêÝ.>t»±nõ`Ù¼¹BÑeBá"wÌXVÆ,7JèlN)³B¦Û¾[õjƒ›îf6ÏyúŸ^ŒN5‘ÐŒTYe¸QI*+¹exÑâµóËw¿ãj\k\ܨAŸ % €yºôÒ]íð·×Û^º±"µD"]u*ð«fû‰D+1´K>”_´R™Ú<לC×Ò¯¤Â쀄ÿ»ï>Ž^ˆVˆíû5T0}Ûƒ–ÈÅ vZ°pb–Æ?&vnï×]£Ï¾eQa‘þL‹öÄÆ¢ÓAWv„24©HªMÂ2Í÷‰8ÛÏøÉb×÷ +Nxñ\÷ÄÆÀ}Ž ùŠl_ÔcÖ…–ï­kÆýÍ8²Ë½¤Ã(ʘCw}Õ4@•YrÛZÛ¥ÏÄXæ»êÁõõ 7õ¼ÛªÏ;ý£Ñ•fiM4™Íh€’Í…í¶©ø†Ý¾iÏLZjqÝ4ô§–F- 2“R®Ÿ ‡±o@®›åà'„¾Û­üð0†î½FGé~0*–"]wSk¯ïL¡{w‚°PíªnWØñO#Ç¡œ@WØù± íF74M c‰¬¾Ng¸À'aÚMúÛ5pY˜[n¬.<Ñ(Ý߬à³y×ZML¤Ô£ƒ8½ï¶}­FwÑQp„ž‰›ðˆ Ã"Ã,Ìà­>¸?'„Cµ¼OhADiê,¤!–lF Ó¾I>&ï !×€H27iLay”8ƒ&âÊ1b,%ÃX›ùJôd>”„zx­•CÏþÛοFœo“ÞÍ$T­ºQ7ÓËŽ—!ÚcžO1ÿ"^N ó±"ôøb ÷\Â4ýS«6úåéÙÜA(||Øí0\ºÆÎöE™šûfU¥jêU‹ñX¹‘¸ô!^ù§˜Ë’¦#bhW8ñV e¾ŽÓDdÓîü4T›ºUnL.=Æzµ˜îë:ÀU~zÊBŒ7º]ù¸¾í» ®(:Ö»žIéúÄ L2"½pé°íð–sŠ)k®äÎ ¸¦Ï3w¸ö—\p8Ákqêvˆ=³`Ù~rþãÏËËØ¬Êöm?‰ÆŠ™éòƒþªnG •öîYq2¡ jcR Ë1=`ñ8šR,|pì—X‹ ÞÔz´w‘&4cžà:c2¦<5‰I²¸CLÃÉò¸CÔ7¿Ó!P^‡°zÜ7DG0˜P|³ßª¸#¸ønG„Ùð’gÔ¼ð&¡%4HÓ>ÈĔÀRÁ$í&aˆJ“Æp¤0ƒTyîfC íBNÙÁ( ³ïDRíG¨2þ3I0ëÆÒÖ.ÿéß6˜ÆzÐ#9Ù_1ËLNÌNüÒS¾ÿáåè9ç endstream endobj 93 0 obj <> stream xÚÅY[¯Û6~ï¯Ð£\Ä,o"¥.öe.š¢h·ÈYô¡ ÅÖ9*K§’ìÓì¯ßiS¶|éé"‹MgÈ™onLò{"Db%üåÉj›üã!ùêŸB&‚³‚ÉÃ#¬/ñ‡IÖ¿¤OÍó¯ûª«?ËLêôË/÷[|xø6éhÈX¡a_Î2åöýk!mÚÕíBæéXõ‹¥Îl:vøÍÓ²õß¾/‘î-¯ºeÝÖí“ß²©ˆ¶©‡‘FÝ#}÷H G«WÕÀË\Øô›¦ÚVÄÄRð蔊sf ¸ žp?sŒ™Ü/ÿÂ?˜z oÛyù»¡Z;yù-yBZÆÍòf̸òëõÌvÅlàþá[_jmÀ Še™›~Wí*˜Ô~×{.õüÁ™´'‚cùßÏ¢»;„˽Y,Už9U+›¥%}žË"C RV#ˆfÄåœñì>U-Ç qÚ#_me•Êu˜ÃÁS_>oÀÔ™åéÝX…år¤à•λ^;À⸭^hÃópòg,¡,S6¶—“0ãÒ#Ÿ+аÐU³ž»µé+ø‚FØ\‹ô#¨6O½€²åVkú±ÞU^~G}U6MçèWåXw-(Äd*ý¶C~/èàÕÞýÛƒµ(œÝr²›E» sG—&gyöy|ƒ.Töþ¾äÉ0Xá7eûT‘v—ÊXääeS7hwÔ]ßWƒ¿\ë-ó'††™ê¬pX·ô%L)0å/ÇÝåY­Û‘¢îþסþOuWà}„ ©°çâ'Ìa~]Ž%­| vEŠßg>d\ux«0ÏgÈs—¸ Ì4ê~óüž0’¼$R‚%sÌ96ÙÂ/ÃTF¿šä]ò“OPèi˜t\A;pFV3GöVœŸP_8 Ì \Ùô}ú®ªHe3t4";ÂàÄ+cC a™"¶ÏEBf‡xÕ’a¼‡±ß­ÆYŒ¨B01 Ç =ãDö…ÙûÅ,K«˜³°+ÿ,ìt¦}z†ÍýŠ„7Íà-×îún5Æ[~o6gÅ-¸EŸ›Ð,/ÐÙ,3—æ0qtY.n£N3«n Î)'¨Ë¹ ¨st¨Ã‘¯‚²«¨“‚éÛ¨ËM„ºˆ·¾Šº¼ {OP‡>—¡!çg³1;¸¬‹²ô·3Ci œí„uKø™ÉN¬t #” èÇæ+™ YæB´¼¢ˆL“ÎU¿30 ¶Ø”ñ=ä€Ç3*fOŸDd0ì@.Uï™I˺)?† ä ˆc2ÌýüÜÔ”•iãsßA‚Ù~=Ÿ_Ðy̬§×w9ù=d½²¸Àñ\vßm1ót…š«ò%å-}¨Ôî"!¡gg|¶*Fk™+®-Õ•ºNzyoY .i¡D¤ÒoB¥^®ºQùsÍ”¾^ÝØÕ¾^ÝdQuÇpîký2Š!àˆ©æ<—%g™Œ½~Z‘Xw'%ÎÄÞHñ²éØ.@ g!䪦ù’Qr–ç÷Õ|ó–„à”å1¤W›²÷m[nïÌuŸ¶xp:r¸ÀÂ1Åý8‚raê§+jüåôcBé`â‚ { mÓ·#-¸þ÷Óç´Ž&1'"6_¬ú-èw ²}…Û—«Ã~ÀEãZi¼/mÜTí“ëÀ}·¥‘ ‹[Ë,óEq,Ûp ñí#-¶·3i† K먡ˆë!® WÂÎ}INH,ëv˜3¸–ò‡ø÷÷ßÏåĈd5ÚV„€}W¯=j0Ó¾îEDf…»¹4)ð¥NLK%"¥ùÉš,Œ„/5 7;íáÔ_Ø=8íáR ¼‹L¨ÊÝØm!«¬ óûä§¢D lÏг‚vq$|qw-Ý&õÄœO[\o×4xì+.¨©†©5„ØÀÉ_ÓËApyû8+,àËE`a\PZ`„ƒâ¢(° ‹ÀˆÌÆ­‡:'ÐÊÂ!þŽÚÎSŽ€æ¡Öçç†Æ9‡uøºF/=Õ¾êQÜ0=)ÊH—ÜEÇl³î"xþ?p¡íew«íó]îòó"Çlñ½B;v ±–0 tá Q_9”^9=ÛÑÁÖ|òã®§AÙFŸw½7¸·E›T:ʸè _tÑU9燇†P ÎÚg]÷Õj„£ÁÕï|"u8i·n_Š”É|^ È4؉ìZH×ø4e¼›¢GX¤r 0S·«nëó‰Ážop9Íç˜òììÔ÷A•Ř7»K¬Þ„÷2JŒfÒþL|ÙXçعÀ õ¢ò»ÝøJíç>æ¾÷ÐSíÚ×>,:íãw7>u¤²\´_¤ý˜ÝDû°@Ú‡Óþ «ì }÷*á´ŸgŸ]ûö–ò/õŒ™Ì˜VÇžÑÿ¾Þ3"‘!Öpû¹fÄI³¨þD³x¡]Ž^|§¨þÿ¢ÖôÊ4úäÿÀØÍ+á~è´+æê=Šê6Ýyˆ–(”6Vízšˆ°{> stream xÚ¥UÛnÔ0}ç+üèE]“ع ñ‚¨BT,âPå&ÞÕÜšxYÊ×3c;Û,MUÔjW²g<Ï93¹!! à’”Ã? ECÞnÈ«÷!'aÀò '›-œ¯QHȦüNuº\­cÑ—¥4òõêçæ#8D3û0fy>‹…õù¼â)ít»â5jX­ERÓáÊ©t"sŠ«NÀ²@¯kw*ÇÑ+µ4ªtʃ6•s1•òÁ†‚Áí‚€n*=:Ý9\Œ‰é "wÔà‚ªª9giâó¿¬òŒgx÷l*"¹:fQ‡µíŒçkÜ ç,âsÌ£Wú##U—N(PÈb¤nÇ °y+g)Kýu?}=?_®(½ [ ±y‚·˜õ÷l&Œjúÿš‰o«LÐn¸¶¤G"¥½-ßNIŠSD‰ ‡Jp ­œU#ñøÖ WÖE¡ÑýˆM…;ì¯úÖï»Ámd;sì÷ƒO7ª:,sHö} c`46'*ú¡Û ²qB!—&cW²Ý!å‚/³ÑRª0p5(ýlÿ…iW÷—v‚º—­úmžöæð<°o®ú®rʇì w¹Ç:E¬Ñª’£³°­ŒšQ6Ê«¤®Nµå)u>ÅÑWNÓµj±hÁS–%te‚̛@WŒÞŒ‚nKdO¹þ‡GK8df££7ªõSÓm?Ç“Zæô¨Û›]ç(Ðd㓬žC >ô[ïŒÅD`rJ X9ÁÂO ž)Y:ݘâèkaÍÃæ,æj2'0æÇȳ)Aá1 ³g¨Û¢k„ï…ýœ\V„Œ§dD™M˜N–/þ:Ò endstream endobj 99 0 obj <> stream xÚµ]oÛ6ð}¿BòP³¢HIöVl-6¶fOË(–’h“%WR’¦Øßï(S¶w[ ?ŽwÇû>Dð“AÃ? 6ÛàÕEðòµ ¤J§ÁÅ l¯e$r—¿‡RÄ«µ”±ßôÅînµVYnúªëö–fE[Ò`ÛÁ7ËúæiÚì»{€¬†Õ??\5™RŠ3»QbÌ£é6>÷ 4r°ZÉà: ‰4,ˆR[=ÒÜ"€ÛÆ© ïêÍ*ÎÂ;‚©Ûz¬‹¦y"Èš1TÛ݈PO+£C>Y‹J¬ÖZ&á]Á`mGXV1œéÇzÃÆ¾–© O*¦’§(ýfjYH³+úb[U¿$¦L‹ÔÝ›4¹ ebØYXmêËHj‰’íq»ÔÝÐ÷/—©>Ò¼,Æ‚F× ÞׄV€ /p5¦k+0P¯GÌUâqƒ§À•‰³Ë(Öî~‘o;R$ÓýŽNvj&>XûÂxßÍâ>‡ND’óÝ$ýo0®äƒgó‘Ê×EÌÓ\GNðõ°„DÚò™ Þýööí$]Œ¨•ˆA*ÃRÔ.“¤±ËÍþS8µ'úb°e Ïêc=PË‚³sÀåéŽP!‘_k.‰.Éùt_£E&§àª>§±Ñ³àÊó³­ÍD§(Ëãàš 8µÇ»>çYÜã~ÀàæJÜY ,¹´å6TÎA­>×ÿ0½ÿµ6ÂPxž ÀÖÕ3q:NGZ€ÿºAO z~çãs¿Ôù¤BM¯,]üjª'[g®—‰TO…6Uý¤4ÍáG»zù¨.™…ÉÉÖôCïд×C8lX²wÅ1ÔÇóΨyDðbÈŸÐw‰·BqB|دugT-ï [z;rêðuÁy~o»7ˆŒ¥ë˺-šØë~‹„)Tý0G텘ͯ…új[`ÅŒ»÷-h¨¸òŠü{¾ëð V 0\Œ8ÂÄb[Nu,ݾ°†e×¶ç <´GîTeµÑ”‹FÔ³y/57èR]oGŒ¢íýf\ìÓó}·÷¬cä‰Þ÷ó—!%Y¿ªµ·èÈúí'}_ØIÏR1fTÞWó|Åoãš+Îýö«ŠÞªÐ>ÉàpXî…gÖúâzpß®ÁZûOé™@ó3EÁlÕí¦.«o3RŠß¿D‡™ÈõdÊýŽºúúÜ (µu¸sÐÖÑö‚ï"²–¾û7½UŽ˜8¬ú¶]»þTõÝ *‡&Ð) #‚¢oãTJ÷|Ýr—¡^lvˆrÛõÀg[m»þ‰Æó;àš¡$åì<8â.F7X9àÀê.µºƒ#¤;Xžé6¬¶QaR[÷iæ¥fÔ®øCàkŽ1¼ûÀéEù»žãôÌáñbZù†Ÿr;§¹ºƒ]K¿-}©Æ€Á3n-!¸çVó‹uUêJJ+:÷i߆ªBú¾ý@R[pîLÄî5 >SáÏ€¿¬|YTøšvHöH­ V¢f‡‚/ÛbÀ“”52h“¤/Ü碞ÚçµÓÒIô¾tµî‰½© # X5´©úL-‹|‰_¹Ì€”ćuª©Ô1ò—oþƒu÷û endstream endobj 102 0 obj <> stream xÚµXÛnÜ6}ïWèQ.¼¬xÑ úPô‚A‚4îSÊŠk+ÕJIkÇA?¾s!%í®ìM ^˜9œr†gŽ| dÁŸ R¿(XoƒŸ¯‚~K‰<ʃ« L¯ð! ®Ê·á_vØwMñîêO331‹Ü€h&bM¢Wwöb¥rví~¨ëÖH5[çBj°€ò·õî¦(Ë›{Û ÕÚ.ÙÈȼxç°Ø=®oì'|–!xgK·²eÔ€~®d’‹-☷Ó»;A“¿^ñ©Ê$Rä(@Çš¦BñYI¡„¹XI©b<¿êc tžxN™¡‘¶A¢E–úÇ:x¼^00 9#½NgRèxRœÅBgçOBNñý…ŽÜ9ë—J‹HN¤‚N|ÎÂLÊ™hŠ-„J§&ü›8,ú¾ºm¸®Ñƒ»¢¹µ×,6ó‰žIgÔ<¹WÞ”ŠEœ‘©7M»ë«þ0t󬕩.…Ã3|m‰sônà )‹í§4{Mƒ”,óýï—Ü©šÁuÜÀºmz7´¾+:'NJ.~\tß¹2Þº_l¿îªÝPµÍ_Rëç.i “Î.éÑö–ÌH%¿„#Õ³™‚›Û îÜG `¬Âþq¼¤iØÖÕ‡:È_‡’;ûOáýÃgÇ<°FpdÅz°]OYÓ5]Øì?Q6¿­ÕÂ.b‘z°Y :­!AkEH‚ã„$Z›°UÚu…˜‚pÓ30ýJÎCð¨0&g&ŽÂìbkaK¾ÃåKrçÕ§I'RõKJ <Ê8‰—¿xñ„åDÚŽ=´ÛÝ€ûäÇ~èªæ2פ3ï}"ñŠ®èÉi¢h¸µŸª$nù‰cŒ²p” ®ª4›0ÿ ¢D`lb#¢dß)nÏC²Ò™PjÄäø<&ãŠHM ìžÏ òÌT•SXN¬štç‘ùYÝ3)¯»[3DzÔ,KîP£/A7 ZÆ©¨ñÚ¿(U¦„ÖS‘G“l¾äÃÈW€ä8ðᛂ¢>ŠÑ1sÁªO‘øËR=«ngƒ#Ž„vØ6aŠ>)PŠÜö•© M‘*löÌåÊÆÙ¢)¯g$’ĉ|XVࡈv‘â.6ìÓ¯LÏX[6cm™+è:‹m.£´ýN\:VTn!ºH;[”¼Â6%[m« Î@š$ÔÈ4¡Zð)jEde‚#x§ „«8|ÙÖOƒ ”­7«º¥hÁÕpKš’ãJ5n_Õ®¶\=@[ÏsEç Ô°äpÿ¶t5ã8C±f(@O>ÁX†}õÙõˆÛBK鄲 –~ï\£ZùOσ§ÉEZn×-¬ñÉ™‹HÐXÕsÛ´Íê³íZ K’Nžõ€œªûÖ÷¼3Åà¸þÊos<~d P¶vÛvÜ?ÜŽe%ª ÜÇ¥£°«ºîY¢œWƨ©çµãz·ãFu®ílÏŠG|f”T°U|­@?èâάT /âì:ázñ"È=ã ;…l¡&'"kòÆ—ºœùÄxhl Ý~=,¾vEPgæàµ\ ÎKQÒ›ð(爵Ҷ:¾'áA?(7±W¹+áò„Àί|æl ŒŠÏžMl&Ò㮣»—Ë4Ð}ž)‘Ëñž#F_ÈGâœ'¸¬ŒÄÁ=Ÿ!3;¥­O‰ƒB‚0é"DèŒî™”Ó ¯OÒÃãÁ{µ|Ð÷ïX“Цk·gh„³õ?h„Ic±ôº. ¾€F4 úº5Mï·oß}Kbaù,±Pñ>ÞÝÒ'‘d*À›žMÌ ŽvÕ-±n˜|¨ð…Æ$ q˜‡ªf]•–ÍÉSuÂ9+ö¿ƒ©l¬xctÔˆF²’%ž¬¬’H‡¯|µÇ‰åj3„êÐnGg¡}Ï.ðoÞ™ëïÚ}].Híêbí…ž¡ „q‘%™(›Þg1Aä»…Ph#´BtËs„M™$ܤ¾¹\|'5F‹è ú¡!LÖ%[±D)ok)¦´hN7ÐØ®ºu>kbÛ¤Pë‘ß9ÔÔ×Ц¸P»,Í­'¥ªê%V¨R‰alϽäëïþå·´F endstream endobj 105 0 obj <> stream xÚµVßoÛ8 ~¿¿Bö0kÖ/[ÂÞwpoÃòv ÏQZb;³Ýv;Ü”(ÇJâ6Û€¡bQÔGŠâG’|!ŒäðÇHÉá?'uK~ß7ïXA£F)²ÙÁ~Ærj ²Ùþ0Êi™fŒq•Üíé§Í_äÏ ùB¨0š<e¨–þ@Y–‚êr^îÉGòaÅÀ¢ŒlíþXsšóX4/®/J¸ê4¥Lþs?ʲ“Åï°§’Ýзøu7T‡{ïÉ›w%q0¹q¸Y抪ÒüÖõ‡±g·Ña%ešdJÑ<öÍ6ÍÆñ<¹nüíú½Wï_/JÞE/­nÒ·kŽ+LS%¼•?ìXÍajú.èËØ)EŒÕ7÷.²L†þaj:ΜܤȩN?r}¾(¨ŠéÁ«Îýêr„ƒhBt2ÒŒëÄÖÍMΤݢ¢ M3©õìk3õ(øŒGQˆ–·¸Ó¦¼LÆÉ;›1)hîÂ%¨KpÓ~mƉž¾â9„qé:“AàDQFlÀõ5:,vìPöÝHÊM„n4ü*z¤ÐC¶¹„´@{üg )$X2YüYK¿îx¡ŒL jô 1¼/ȈçÉÑt~<ÞŽÍ¿ö\Zy鯤Œ,Ô‹”áÔ°ˆ2Ñ¥VL˜Ü…"_ž~DÓlɽä±{ Èó …ýîLë’AN:3HË|qÝ‚†°õRx¸Œ-"&JïÀKçžS&ŒIGo3s>ƪµ¸U…­fw¢bŽù²'w§þa¿Ååg4€j ‰b3ÝŸÁ¼{¡$•gõ °ž¾Z¢_u[ €T9•<˜†kKa’z°•÷MBH«Î>¡½t2|øxÁKVÊb/õy/-fõ×ø\‹Aûµ¶˜¿Á~5¡OGO05ú&äÑà¶µ¯Ÿ³ÃþÚ¼„þ ¤<)B$ƒm«¦qñ˜*™Tûf‹Å3b‰Œ (ª²LŽka(õBäòÊÝÅùóœp¨Ë3Huä¾r1xLCÇ> stream xÚÅVKoÛF¾÷WðHÖ†ûà’DoE› ½¥ñ-* š¤¬E)R&)%úã;³³W6#9¹6 ÝÙy?>Nðð †?¤þã Ü¿ÞïÞgWL*ÜoàyÅc–ùúr&£çB…úb¿V2M¡.ú2’q¸5í’TØw‡Ñ´õý}ÿgðû=iå:àœåIâÔª˜é|R˸Uœ„OÍ~’z˜Ì³àKä,SV@åÁ.Ð’eétm‚OÁÇ3“3Röu1Ö¯tó8f<Ÿ•óX1!oi÷¸œúãkÍ\0.=Í\3~ÓoËi6mU¥¼þKw¡Øó3_÷ãÄÒ;÷BrèÕ»÷i€EŒs´°šLˆ„%™5ñéÔvûÁ¼¨—ð„xÊx¬2ÅHâØ™*Z%T°rèáø`m®-í‰:Y~þ°Ž~Yô„´òŒ%Òªý­ÊÞìGÓµŽ_ùN$,W>ûýcÍÅÔpNæÂs Ý% ßÿµ¯KVâ”ÉÔI÷@VF2'§$i*7]Á&Âa­DÖ¥YÇ\ÕñÙİh¥…˜°ÑˆN1 mÃ%ÃŽð Ó¡AO²4,Z÷{øjSô'ºVÅXÐiûC9úú.‚Vâá—­)#‘†ÛK=¦EâXƒ…Š^ÆŽ^ž$ðOs¢‡uhXnlj ¸šî©è͸ݳ%ŒfW¯#:cÐme£ŠýxލZÖ”6±R„HA;RböLOGLÊÀ¬‚…Òc *áçÚÃE„%f©”ú‰Ú4 >#ÑŠÖE"º ±¥yþ±q¤­¦bãÉÂji 1ªÑë¯fÌtæÉy~ñ°êÈŸÁÙ…sÎIÛŸì*b ò ™â6d¢D,gÌt÷ éÙñjè«ÏRÃ2«Ï¹…ºê=.§ЋûèåÎY]¸G¼ŸèlƘÎãó`&‹ßt2(•›¿q†º 4ÁÃÑú³€swt(»vp2å¶èÝ+:ùV ü«†ám‡7ƒ H³k ˜dØ3zQ,˜È2¨˜ãî#ÖÂH¦ò°ë+Ó ]ì vô7NζãÚÐoAÒ0÷š*y‡Ã9PÒJ"M-(Yöa0O-Î+ÞÖgt˜<  ‚^M/`òJø2eжsøC=ºè¼Î¹ü@Ƹ±€¦SìpXv¤žv æ@‡]±-¸Â¡ÔR;Åß0.Ë'Û€J‰Ò•ÐFÛ9[‡)sRë3¢Úûdªg¯ýû0Âú"S¥zãëH$“Ô_Þäm$B {s÷HäÙ©ê¦^Øßòç`VÏcHßÔï³]Ùà8S©¯†/¹­{æz¹Â%¹h&„ãß½ÂY?€k° ,®päÐÿ´Â)•_]áöè<¾—¾~c…Ës'AÜY'sî«§é«Ç}_MwpçÁ;m]&R*›Õ\ñ‚ÔLeþˆ½qÿÔˆlä|a?ƒ0›¾®‡ó†D‡]½ëìê',$MgÁ·$‘fw9+`œ¨¿/ƒÛáá¼/Òܯò˜¥ù¾%so¯Q±Û·à0ï[–êö-`·ûÐæ} ˆÓ¾¥í[ðîRŸ+Ÿ+óþD<Ój‘7/­g þÐæu‰Æò®´¢¹á|býøÓbë> endstream endobj 111 0 obj <> stream xÚíXKsÛ6¾÷WðHu"˜x$íé¥Ó:ÓÚI£›É0eÑ‘H…¤¢8Óß]`Á‡DKNzé¡c±ûÆ~ ½O÷øá^$à7ð²­÷ó»º=®˜TÚ[¬`{Ζ½¼ó9S³9çBù¯ët·žÍeúuž.‹òáêP-Œ´Xía’7³w‹ß½_V.×ç, C¬¦'˜q#:ô6;wê“Çd{/LX¬Ì•x[OKGnºñÞzo&ôL¤ =‘œLŠ^rއ—$÷L$ù¡Æß}P,5Ø[ÕÕÖR»MZ”–ló/­¥î®6¹±ðê6ò0ìA‚úæ¤P„,ŒÂ·OeµkŠ£ðŠÁ1{óX1{¢(AKhÃû­{o »7s²·|ýÊYU6t$[§5í®Êt›ßÏn¦¬$•?¢Ë ü@xdÌýújÈ\ ‰å(HC³›ÍEìçYgò¥Ýý0‘ÿdìœsÍY€ÞK†5¶è½â‰¿KkØæõ”ÿ‘`±&—L.&Ü1ÓŠxØlÒÿ£jQº@MÚZꃵqUÕ´EÙN–i›º´Ÿíë:/щÖZ %bf¸»ÅjutŒâŒd:Cí?æÙ@ -†³p¬Úî6„ÍÄNJ?¯ÓÆÄèCÑ®-etH©ÎU × Å dŒ¨çkª²‹±MÈ„©Q]ßÎbéWõÈ鮯¡!¨[Œ3ÚÖä´¸\³€¡BŽNÄ7„”,’7°Ýžwƒü8º¬Ršf2ð꯼Ý×eó’›úÆdxI§‚¯SòÖXic9›}–åM³ÚoðþhÝu>Û Ù`&_óºbØw¸ÿ'°×‡¢!¶¢µã®.l’–”TçumÒä´¦9•9Ò•YZRMõŠaRVåÜ*?‡^"Lôð%.ÞøEó 6Ðcr~ aŠ%É@z’°@\”>àÏ¡˜Õw cmõ} æ~3ˆ‰D3uŠbƒð߃1yÆ^~“ôùo¬tj=Ži2#-ÂÁÔ%Hv(&‡(‡b@ŠIB1 ŠE#“Ç(2 Þ¡ó(TôM(6]OšÿßÀ.7°qÜ‚’±â±^ZßÐ6:ÀC:ƒÇC‹%‚* ©LqñD+Å”zù€Êpo ¬UT“Z%TñHÚŠïí„´ I]š·¶çÜŽ5G¯ªÍ¦š ï xÙ§€JŽ^mEiEs}±)­Yd¿¤Ê϶•©9ŒdÞñwv÷©‰}Ñ틉}f7»aB@™v<ñi<@ç×Sé“?¡ç×d ÁçKŸ°ÁÍ‹|ÿýÿâ‹TCí[ŽŠîègÜÊë¶ÈLëƒ#÷Pà¦5Á‹ªoâG¯>ÐélJŸ±IlŠœMqoSllŠŽl‚®PgÍ´Þ î^ÅÝÇ©Ø Ñ³¼rB‚a{¤Í‡ h÷'0…Ç>Ÿ’ÙSNÅ .ë›þñP¯! endstream endobj 117 0 obj <> stream xÚÙrãÆñ=_òK Ô¸ì¼l´GÉI|­Þ,×A1 ppµråãÓ×à ¡•KªÂ==}M_ô>yÊ áOy‰†ÿÐ+Þ?î¼ëw*ö” ²(òî6°¿RaÅÞÝúW_60W+¥täo÷Ç«ßî¾÷ÞÞyŸ¼Àd©÷èEYZ:ÄÞÁ‹M&nº÷>x?/\0É%m™¯/0ga`ôˆ9:¢—0@‚¹(ÖyŸ_­Lùÿã]F£m›w<Ü´ÍG}ù¥çÑ}¨ì¾äqUó÷Íí¿__åß|À¹õ‹}õéT^;i«zKL¬"h¤ÂYDŦiyO›×ïÉ 3¤weU ¼•Ž‚(!ÈOusìªÎIƒYÔ“#* Tê­â,©j 7bõ|Dæ>2Ó÷´ <âþßÞ¿âÁpâóÇÇm/‹ESw²\ìòVŽlêüPÞ_}·D»P¢Ò 2DÉ›²+ÚêØWM-ðvJxdv ~·áê$óÛæÔWu)gfÜFiF`‘¿d~™bRx„&VpÐͧf2Å:@Á7yÞ•Ê‚8›`WÚJ¿ˆ~ð‹^JÅ$U ѱHrþˆöpÈ:ÙcCÅ‘3T£¡â— U'd¨:I/ •q’]lµ*Q3h¶›í=¨¨9mñ‰¤Öïw`–0Šœ9Ә׬X·Uï÷O¼¾.»j[—kžõ ÛòØ–]Y#e„Àøò>­@£aààPÕÕ!ßó Ÿ¯tì—-°ÍGV4¯Yá”Cþ…ÏÛX‰x|l›‡}yèÀöm¦ýªçåCŽw<á$ôPF¾8uÈ ŽüެÄ~Ï'¶e]¶îºS½®Ú²èÝ9$óeÒ0ÐqA»\_äp5°h¬ˆÅDÃ{¡Uyƒâ|DECFÄRÍ®ÜoV°¿Ò©~EN %ˆç€çNû¾:’›ƒÃåz[v×y[èïQ–ǡЀú^—­ 7üýLÀm_ewÉOw†*4W2 8Ã:Ç›ó£­Mt Ó Œ»Ü°Ð‚û+ºeÙ¯˜ÌúǼïÕ ž%‰Ð;óÃ{¿ä®Â 4²O´§í(œÌ™)Üãâ¬5 ¶(öÿ  †¿ŒHÊÐW«Ø„þM/›ý.ïgg@F%/Œº…‰<!„Ÿp‘PO¥^œÚv|n Ypó4ÃÅ”Í3á#G‘ã*1´¢9€Ýô%½xÔ`›wN­U¿;Cù'o" ÷+^Þ$a cà ܽŠÀ›ÄÉ0ÎO  ‹ƒh¼@oC„z‚Þ‚ã¶ñ‹ø§`r îÒštÄV8k!º¨øÒpAI_7\D© ú|cz àãCViT2,<²&`iJ¸!5XböÕôY$³gÄç5X4])vwfbš‚V¹_Ow5Ø#à{´KÌ«$ÁÔŽï_7'ðâËA5s"ª„œábç¦(Ž@*'ïh{ O™øúôß_ñ6<`R—¤jö¶wÕÔg]X:{à^owöf¡ Ž>IDZ|“ଵþífI Õ³ê×:bâZÛ@п6àÇâaá9ýOÁ¬9Ó¿ Ï @Ëý_ò›*ˆÜ~øê’ñäŒñxdÜP+²«ñO$ĵ¼måÕ½ú¬xžzŽ}͆zê0=îsîÿõ‡›[Òï-o¹¾‚;`¢¨ýÛžÁ]^ç5eS?)Êàö÷ ú%“ÓÑ›ÉÁe])>—ʨä,Äv¼¶¦Â]ÞáZâµi/+,7bÿ1àÁkÀeÌž­F$¬“ÊÊ·œ œ‹ ŠÅÞbrX«Ê“áèÌ}þØWA’ (I´ðÔ €f<Ï]‰Ôpõ±ÌÐbS³Òd_æË„ëÒåyý»„ðc^””ßÎÊ”ýæEvÛʽ†1Î%®ËÕy|2Zêä¼wu9E̲ג¶W›§Y~a‡[Í\—Ár5$……É\aaæÍcRxÇŸN•¤)V”ìˆð×mUõä§S.dõçL²Ì8SnËVÀ8Ë™ßæõV kަ&ŸN²¸û0 ,>E—N^ûÌ'D<ãZF-¥3)® ï.±c êÏ_ÍS"È©ÆKža†»–|‘úMŠ„(Ãtjžuºjýý¿~ú§ØØY`d—úr&f&qW"^¨Þ®8,5Õ´l¤6Çé€iš¨¹í^tô7ÍáVŒI4;9r\ÁëYDÎsÉ)¹[[qwõ·{3ÞØ±}æõ ó¦ü³ ,ª9zpT……œYmȃkW¹ëI‹psTCèÖáÙÖ˜wJú@$ÎÜ¡x•$Æ~T~‡V ,ÄÌx<°@‚CîùQ.6[M’ú¬©§GˆÚ%«”éM’Iè€[ÈÅä‹¶˜‰MîäSsç ✈oÈ–tE©ÉJò,ìÌœ×B¾˜eyY‰Å‚’# ²Óøkým›ª¡wÊ‘æŽúÔ¿–oî:×ȹô®÷cáëÍꟸˆbÈèÔ’]BR1;w¢I $tÑ"týDžˆàÎ%x¼î ÍpT£µÆUýÏ"9ÐÓ£ÈØjR±ž5‰>¯¹‰IVË L´[s‰»ÚxcãGkiâ7ím:W’J”Üåݬˆéšó@Ò*tÜ·/j:2 ;HÜ‘uÈÄàè‡ß¼ýÀ÷oÞÃðRE—š•r0ó%S™[2®—ý3&¬B$Η՘…aÜ+Aºøª2×*‡5÷Íù3ªX‡bt Øp$yÓœÚ?ëI›ÎNr†VJwI ‹ùbä^ä˜o8–´ Y¿8~bÀzA6')+ÿ¢`#uv'8ÔØÍÇÕi'€‘ ?L¨;;4ðqÑ5ðqCäáZÑÙ/w»Åî‘&Kc†Ù´*~5 eèQé8šgè°b)‘ÅŠ]=æ:¼ñù*ï´'bc;iož˜ÅX q<-YÖ4´ò¦ðøuÝ"ê«ÂJ.ppClIëçx7iŒ½Lfl|LÓæ„ ð×VÉ—vÓiÓȀϒ”æ ,¤šQF?wÎ*.†0»Šc‚ƒ(CØÛL¬"z!*̼¢ 3”ßé&‡` 5/±·Á1G‰fìYa~#¶àÈaùf¬(a&¿c ÷Òá†wW)Õ7X)‡é´× ³l éxzØc*Lo¼uº†0Zís׊\ ¯ãÐ/×±ÉDRŠZÝq˜bOïúþøíõõ^BÑí©Çœ:(×§ë›SBÝ-–º3¤!†ß)Þyž9âKZÅ–ý²2ôç¿ük¸Bk endstream endobj 121 0 obj <> stream xÚÕYKsÛ6¾÷WðHÍDñ @¦§N¾÷QrîìÛ8ö1b–¼Žx®„'ÖÀEK) &<ÚFö‚ø¡™ØN¦Èôçn a),™ˆÄx’p¸U‘·3hí)lUèŒ%²%„[íÍBí îj‰g·$u$µMj…5ße’,ÔJ ±ÊÓoOÓHÓ­ç0£­ÚÜð„ÛsÆ\;bIž2Tø\ *&44‘0Þ ~-Nù_,>È2øÜe9G¯±4?1ÉÌh’ÙÑ“,'®¿]°©:xŸÖLŸML²ÝSR äà ÈyÏ|õ† Úƒ àüÄp¡a€rÛÖ0&Ÿ}nu‚Ó |–Àw%¢mf¡ß=)(žeL#\y€.ó>ìwD>Fü^9³¯¼úù’éjQËSÇ“d¤“(oÚ(úFrk}Ë”ÐmrÙo\0ê´É7 ¦㼟øè„ƒw³`Bøù;Ý6%L×ZœX1Ùÿ¨m¦SmÓ;¬%„ëØ3åüDÉ$ƒù1’L½4æöèlÚ»a*ËQï~ú“vêÇÇ k@6ǹå]˜ï¦ú¡†<|Åa§0¾ò0ܧ%~>ÑÊÓ{õèï°•O¶Ý¯Ñ߇‚I>Q“­œJ‡&=ú9!a.*ìD˜ÂE•ØQ`*=hy5vŠ„¸‚ÓxÎ8ö,ÑØŸa¤ð‡¿þ—-û´òßð•û¶ñúç§(óü;pÜV¯ÊÇËývhO茊zxˆPŽÇL£¬Öî7)¥43Œ%‰©¸¦Ó X¢ýµ#ññZ†$J-ìÉ©ùká~ºhÏ.ðÏ.ðjõðæ“;qÅûnWøtyØØ–ô°*šâèÚ•[ …ŽÂ{ÿ£ÏˆÌ Ò%©¡ƒ0†¡Â^?I¾$yôƒ¹éø>ƒzÆTâS fŠ!;Ê ‰AM1d½¼S½ÓûÌB§v‡ÝÉÇÛþÜ6,Ê endstream endobj 124 0 obj <> stream xÚWÛŽ›F¾ïSpW\ųÌÔÞ´M¥RU¥Ù»n•²xlÓ`p¯³Q¾ÿaÀ8Æqµ+1‡ï?ŸÆÁÇ@üÉ UðÅ.øé>¸{%ÓÀŠ,I‚û5\/e›à~õgèËX™Ðà'ãÅ_÷¿~ `o²«€˜ÉÏnrÑUDr‘Þ²#½ÉÂÞÒÓÞd‘]G—þ)˜È5kºûåÞÇ4 ¤L<Õ¦"QD!…)AȦÚd¡3ƒ8Ö0…QÁ.H´°é¸¯‚wÁÛ”—slËÞ]pόȲ ÷,‘ºÉ}‚òÜ‹b•÷ùb©Ó8ü—?,–›6ßoyÙ7þë>õ¼zˆ¤©<°¬ùûòÍo?.´ ~‡{UùñàjÚ²ÞË8j¡篛v—÷ty÷* 0*Q†ú.2XªXÄ)!ß=×;+»ó © ‰L…´@bb‘0MY÷œ ¥÷dÜ{¶úN¼øîõ ^Œ$Oï›ÞMÝùãb›·žd]ç;÷°ø~N{¯‹´"Ö¤ÊK×m¹ï˦öx3U=™™Âï·èÞ8 ÛæÐ—µó4gö&‘H 3>—…'=h2…w{Ï\ úˆý ²›@0æèû„†•• g*pg\¸¼@’-ƒQ6Šž25ƒ@ÍŽ Rz¾»™È~½òÒD¨ØWÖÓe{³Ðý Úb¡l?‘‘®¶Ÿ Ìð“ÚüLU+)í…ᘎuϱj#èTX†ÆœHOÃ7^Ú|vmƒy”dáïoeç<5±ÁwFÉm­c…r/Ûµ- >8ÚØ|3¤™·ääÎÚÊ“dØÔM½déÓŸ+gFYd±LŒå•ñ}ûÍÑü$› endstream endobj 127 0 obj <> stream xÚíX[oÛ6~߯ÐÞä¡fÅ›Hm{ÙÖµk‡kìe Õ–cµ¶äJrÜûñ;ä!uqè¸ÛŠÊižûå“£÷ø£‘bðŸD‹môýUôø©Ž¨ \¤ÑÕ Žç4!¬—¿Å”ÈÙœR&âgM¾[Ïæ\É8¯òÍ][¶¸kê}WVE;ûýêEôã2¤iD)ɤtEBÒÌs$Ôò”ñÍfço½ÏttˆdF´°Dm£”­üv]F¯"'ä0ã4.òw÷¸gœ¨làž)¢ù9î‘㾨·;c»ˆÿ@\'TTKçœÍ CbtØÜ!í¢®ªbÑŽÎ1¡q]•!íZ¤«WHpcn xüTE&$IfÔ™;}˜$R[}.ïªzgâ1‰Ý¡ŠP͵ x£¬ºÙ\b^@É×Fk»E¹öô«gpÑÓß¾®öÛëÙ7!½œª‰äVÊ“¢]4å®+ëÊÑ‹±N’dbL~µ.ÀrÎ}F¹;CÒ„$ÊÐOtPšÀi1B-òÇÁâ0cªìÇ!²["¦1D@jCĆˆ‹¸ó·HW,J#Èß·ž$V³9嚀%Çæ *â]ÞäÛ¢+šÁ*…ÌuFXç åœ@Â"ÕDõš´F„©X|Öð%o‹ÎíVøìPÌãb³<:5–ß9¶!©†Šö:šL¹¯!£DÑžÍî¥ÞÚ(4]ñ–y—ãÉ›Mmýº0ï }jô(¸ÁFÄmW7Æ-fí(Dl£ ¾…Ï7 1uðÀFž9>& “N&„éÉì./«²ºñÚåÞì'Pd`áóUÈÍÉØÔq*Ðdœ Œ0å<ým¨ê ÿ2wž<Â<­êSùŽéðN‹7¾ŒW—.×4(y¿²“ìDEÁ2¢IH–õ.™Ä1ϼySvMÞÜá¶n–6Z°\5õWÙº\9ò$ƒ>اcµ{IøŠ2N‚¬<¬A“7®ˆ’2¦_»äoQ¿Î{¤«»|sÒtgáÊe|*Ì¥ó§:êP<^Õûjé›8äX§„™fí›#ÁÂf¦eY&§-|Ôa ¨¢ã·¡¼'Hï¥_¬´™Ëxü6Ô↶O‚³GJ¢ÒqÎ]ݾ©Ú¿5xp3a0q L`ÅÏååçìð磶£mÄFhü€9ŠoÚO _ò äb*!šõ˜‹Ç\æFÊÐåögP×HNÛ55ô·cö4¡$å#þ4‘$MÏ “9 zÉ¡êÀK~:àÕëóבt’ñûØ 5ý¯¢¯‘ö:J~„¿˜Ç_b§F_¾8øÃèKLÑ—ÈLÈ>£¯ }™Ne£ׇ¦ ›}ÁÚQ¨ƒÏD~…ÏÜ_îÓHÇéb´ $›b/³Aì«Û™‡ØKú{}Æ^ÿ{)5`/­O`/Ay{¥g —TèÅerzIÂÅ'‚^s ò§ÚTÍÁÀ–âÖ~6Ö\å\«T8• !¬J8[çÎ=—]S»ÖÞ`4_§¾|­«×àÂp=OáÛ›9Í«å:ùHÒ¡tË€ÒÁG_}ÌÍ8=íD9 éë*bKj<ÆÜèŸü°ÝkYŽFø‘P¯rx21hÑ}ŽÍ„‰#«§¡Wé õ}¯¨Áiƒ2¨ã¨ç}-?Ò·ëz³lƒ/ ,ƒwú¿|Q8ŒLý"uQ¬ ÏV‹â£œñºY|éžOöÞ#¤ˆ_¸/vÏ‹¢´-Qòø»ÍMÝ”Ýz‹-K²ìk½PÖ¿`ÁÚ&¼ïr“õÆ¡Í(±\¦ˆ¿ëš2¯nö›¼Á=´„­—dñÃKäq5Ó,nòª5ƒ>3èßw´«o/ónmÁ€ˆ/ë•í;·¾…ÐLéë™ ÕÙãt endstream endobj 132 0 obj <> stream xÚå[ÛnÇ}ÏW,&cs4}ï¶!` É‹áDo¢ 3äRZh¹K“KÉJàOuWõevª—Ô%O sûœ3Ý5}©êÛ,~]ˆÅÿÄÂIøo\œ_-þú|ñøG·ãưx~ ôILØÅó‹G?üvvu½^¿|þwéF&Ì4Hý`T’>³<>‘^]n×ëí±tGïW›×]ßl_ßœ]aâfyvqê£3D€»~ƒÈåÍ–dg\¯ÏVDvËßvžŽB¯©¸_È8!ë¤à]¢e)ûaÏ_ÈÁÒ}Mo.ðG,eSL]¯]í¹ÝÝl7¯×R®'J»Áy¨3ŒÙo7›åùn ¹)¥ yu<Ún–›X=»Û!=úÃsláêÝR#Hø”ÑW›óõݼ¯‘úèûÛÝÅÅòrxó4==i®¹rµ} p½ú×C”¯××oCI·ûp½³PUsw¾‹¿ÍÑðÏjCéÍÝÕüõ;þy÷êâlwö¤ÍRbÑßjC%¿[Þ@ûŸ½;=ÆÇNá>Šé?'èôøäiD!y<Ï“ÌÐGWЭ@½]]TY}k0ZZPÁë¾¢Þ™Êx†fJ?HÝêËÛ­¾¥·<2ÏõrÆ?1ïs »%qzt»ú÷r{™_ëô˜òO'™a÷ŠÇ¡”~FêG¥»?Ú{؜ϬÀžü*öКÏöòòv¹«æ|[š/Ö,“ñõ ÔÈí•ðÕÅééæQ©öÙËíMnÕÕäaA}…Ðï ~vòtó.Sß|CM(ô oÒÝÕ‹¯.^bÓsvåvËÝ x÷bõ2v¦ôÆhóɬ„X}Ëõ²6â3öo–»»› µ'e6ëE¿3jl}ìß.ї좯?²#Œ¿YGhÆA}¼D…^ ÆÉmDd.Uï{øÈ¥Ì¿K9+9xp„Ò ­Ù°°ðª*¨Ì%ËÁá°|LˆIE2’=³—üu1(p‰ï¡Õ  ãZ.®†ÁËœ^/þ¹ø]ê$`9°+jTöò‹Ûå¡|Sí’£|¸Ç. ?½›¦¾´aR„AÉÆ0mbŸ›Ö–(!”E‡À¦SÆÐÛÜr =-ºÍ媤¥‘£W'Ú§ÙES'𩍠ŒVÅÆÿdû ë[טƒ ¥SáÊBëa혞… ^GÂO¬ûiÞ”t¬+Ä>õó 6:zµÌ2–È0X‰FÍö€iÛþ„YŠíDà¾Z PÙèóÜÿ¬Örƒ vuï0¬¦ù~µÁ{œ÷¼:`\æ ¦fÜ_ÐWÆYê ü‚©9„2°äK=;Óí½§)Ò…Ïé|–jý =“ª>ÃË•r§9ÞçljËÎËAÙ:^>Ò4ãàWk„ u¯e^cãUËÄÈ™ÕûÉ–?m,%eŒ4÷5–qth©k?ÝûN³¹ªÀ8Îô*FI°ÍO+†›e˜4ð£·üd •ÓZX€ƒ è.£x ‹Ë8!y Íg»ºb[f¶MÚ® Gø+&^˜+×1^ìDcÍÂ6N ¢2¡zU 5ÿ×Ú½†iªhc=¶s>®ãbMjÂØ½”‰-¯mr`Ë7rýbµ$¹ñ`ä:³ä¾ŒÜk\’»äS˜É]¼ihh’ë 0rElÎܹœfÄ6“¨öÃXFˆõšäª39¬Øˆ ‚ä¶ŒÜXb³1¡ŒÜ'œ}¤3yˆ£/±‚Ô¦¤±Î¤#µ¯#ÿ‘Xƒ‚€)¨¨À¾Ø1³äºŒ\‹×Œ¥8¦ók‰ÕéMa†>V€‘ÇpžXGrU™\¤Uxd"¹­#7™ $`äžX‹¯*cf`&—iÖY'Hn*ÀÈuf-É}¹#×F•âüÜ ;fÖ“<ú5¹"6(’» 0r›YÌ]cyH¬¥ÁrU™fN™ $·¢ŒÜ+rÜgs‡~^™ÜÄÕBb¥&¹©#י͹û’fÔI…yƒ %=[¢IuIÏ¥ƒBR+»’fÄ”³ö$¡ŒÚKCÎQð²ìs¼,…L¹&Ö ’û 0rGµ‹s(ã)x%`&÷¼,F#Hë’fÄ*“šÔ®ŒÜf«1ÔÂ<'Ô$4œ/Ëç@ÁËFÏr[Fnˆ ¤%͈}&Ó‹Ú±æ/ ¬ þ‚cSFŽÁËEr_Fî2›|n\ËV`&‡h’Ù@r ^ŽsÀ*b…$¹«#·™Mµn%¯0òÙ@rU™\¦Ydd¥$9¯0r“YCòPFî3‹Í¤(V&`&WÑW&V ’› 0rYMr ^Žs]ÀºÌ¦‘g5¯Ìäš‚xRë’fÄ*“ŠÔ®ŒÜf«ÑPèJ#™õ$W˜É ….ƒÊm¹É¬"y¨#÷™EÛ-…®Ìä–B—‹ë”› 0rM¬%µ/iFì2‰×•Â,ÓyQš´º¤çÒÚ]:¤]I3bþßЗ# Hbô¹¦ÿy Z.N‚Pl*ÀÈufÉ}¹Ë¬¡íWQ™<¤-Ä:’ë 0rE•€qWFžë,©ÝHQ+¦qȤ µªÀ¾X™YIòܘ¬É¬"y¨#÷™MÕè…­Ìä"®•µ$7`ä:³Žä9lyÇÉsØÂé¶“%l1Óm`Ç}¹>(W™ $w`ä–XT«µXq0S±ê‹U Y¸†ÀV€‘›}y8(÷™Åþ¢KÈ LÑ%d¹9(×ûrPî2‹½ÑÔâ˜Þ˜–ùSyŽY¼\©=¹;(·S¹-’—‡}¹: ·%hQÍØ´¸š±%hy8(÷S¹k‹›ÉÓL¬í3®'8yZEîÅ!y[ØÛ}‰ZLo÷´ \ÅúX‰Éõ¥(Ïʧ ôG¿ÂTš#'†…ÂÄm…á€×‚eÂÄ%†·8—JÜB‡ëÇ·‡ lŽ[èÎСëÎU¡ ¸Ð ÀÚІ"/jàœ<´a.žàtÃ\¼ 0 ¡Ø~Öø6@|7@ë}þ½,q‹ ÿÀ清“ ŒëN.€Íq §.x׺ë\3+òª–6+ڎͳ-´íN¸€ÍQ gr8ÛÊ›£Î½.A’™&‚<Øv re»Ðxg›É-¤sಜ8Ç-œ8Lwâ lŽ[8-÷¦„IfZ¬0í¤cº“~`sÜÂ%^w—À清 oKÜb,Þ–¸…Ë!´î.‡¼¥íؼØò¶§8¹mrÞ5 ;F&‹DP«þ"Ñ;ÚŒÍKPl êmÆæ®wµ8ÁÉsÔÂå³÷%j1Ëg`sÔÂÅ9FvçÀjÙ.ýð²»ôÖÉvcÁ‡¶˜`sÜÂm ´èn[›#nŠÄc\ÑÝÖŠvË%Œ¥¸‘5&ˆvC'Œ9|1û9@Êv³Òý½" M»éÐ݇Ò·›\A ²»Ç¤h¶Ï ™w%§U¡ÝšÀ…îÖ°6´ARœd7þ@ž7c1\…î¶"°y37-°ýMK`M»! éÐÝ ’WÞl Šâ$»ÙTÝŠ$7¾»• lÞ‹Åbò¶$³Q ¬sí6tйØmh`G×nr ]w“XåÚ ô KqšÍÝN6çãõ ÛÝy°í¶?È•íîû+m{¤€µÝ3`óv¬Ì¹Û=°Ö›ö8$X ^ìq°Â´‡-Ó=lV›ö(oºG9À:ÓWŠcŠ€u{ €ÖÝc¨àÊY".‹‚£àÅrWÎqâ|)γ¹ç³DØžÂ{@¬œÿ`ûÇÁ·g‰(ýÃE`½j.C8tt l>KăQŒìŒ›Ïið _ì±+°ù,1êÊq¤hÉêF6Ÿ%¦#ãhÙ;2Žl>ºLÒÀðÅHGÖŠæ¸[Ž‚ÂwÜåA4‡éQ®Dï0=²R4Gõ°¢wTY#ê5€˜[‘óÍ9ÊAöîDR4—bÚôî.DR7#bÚ÷îED²½t!GEá‹»tÕ!4W:¢\…Þ•ŽÈæ‹0YmCçºH$Mh®¢D „ÞU”Èúö¢‹5…/î¢KdE{&¦{&²Ú7—t"à»—t"›oÝP§5¥8Õ½˜&GOî°^LSìP]ý'ß6ÔçÓyg pøÊ9]_ûø qùùr›p’_÷*£À٤ȟÖ|ä ÊxaR·ï:Éðž»m;höÂqœ0~¹ûÆqw3¼M@èT_îñi è4ŠÌi¼ž)L÷ý?±æË­¥iòåÖÃm3‚À¦]Œôe[þئ|ÅÛ»ÝõÝ_K{ô¿„Yoñ+¿·È­Woã—2”Eýræö»Cÿirƒÿcyv‘>³‰Ÿ.5ߢᗒñ×/åËž¯‡a`>;Ëé£7g·ô]•©ß;­Î—„¦Oã5ps~;ÏP Ìm½Úä'ß/o–ø+~“Öûê¬|{¥ÅÝÕ 1ýBKñ*ù •zJOU’W™åe¨LQ¹åå¤ S•˜t©‰·‘>R«ÉÕ”‹Î?ÿá¿‘b& endstream endobj 135 0 obj <> stream xÚ½XKoÜ6¾÷W¨.‚j‹EJ¢à8‡¢I\Š4¾eƒT–¸¶­´‘äWÒþ÷9¤»´c @a+’óüf8ÒûâQ/„?ê¥ü‡^±õ~=óž½¢©'H–$ÞÙ–ÂÀ;+?øÍÕö ?®‚8âþ©ú‰}ºúxöÖAFG-Éø=dì²x"ãS»È^žïR÷³Ìª $&lP <õÎr}ñË„wãÅ\3¤±·õFDj‡µ÷Þ{çP0%C{(XpB'¹BÊ¿'w"2rû¶VK¹ÿ·ú‰µ¢€E~[·U‘×8«Èªæíó⮨«euÑå»Kmä³W©§° 3¥30J£˜Ä©Vúþ®iw}Õ/Žf<4%T@€8'!Z5† þF~R&­õëÅ_^ãÇH~ý b»^¸ ³Z‰™Vò›ì‹®Ú UÛz>7*&Gr®ÉÏ.%8/b¿k¯ixž$Té5ýÜt‡ü4"3¤„Hø²Û´Ý¶G%:209‹ŒHf‘Ž ü^¯¢˜‡ª†Ù® h2ð)a@TTërYâìR”U ­ hª0”YÏ5äD¯ÎPa*œr—wùV²sá’&ÅÆY# ŒÈ^¤Ù³·W* üma’õr0£ þhIìk–ºÜ[U ݱ.©ˆ µ6ª„:´0¢$¥#º=jµQ·¸PæCŽ+çu«CY(ŠÏ²œ©ø"ÚŒE 6æþÍe¥)!É M i4¦ ¨ßm§£ †‚*k‚bm”ÀtŸ£ãrä}_]4²$Ê–Ô³q% ‰GÐh8ZDBnˆž»¶L‹Yx¬Ô' ¨ŒÉž=z”wÆù¦fŽ—˜ŒA”AQLÒ‘¥éþ¦€”• ,zGÀÒ¦k·øE‘É„iÏi* hWñHT0qYù,D´8Ì{@|%©Í9ã ŒÚk¶¸'Ö°€õ[8Q)¼7ÛçP¿9Ñ4DÛÚÓ¹Y=ÜýÇæ|¦*óü2E~Õ«}ÏÌÆ³é«>M¿öìU¶œ’p¬{­ëŒ„RœYÀMAœÝ`²yéþCW]Ó?ÜŠ!éUÓ2[¹àÞ  ¦¦æ&ó¦9: Fšùº^H:(“Y%LMá<Μcý’Ñ4E$sâ^ù”MJè ëì¯ï÷‘ãnë „PU"ÿ«ìZuÀsêÿ®Ü¾©z©#Õ/o ‚‹_ĿȞ¸ða€4¬#ËÔŽÓB±!aÎ3I'%Ú<óQRu{èÃÍ»¡DwC0ƒ!|“³h'|̣˜ëT’å1&|E¤F†ãa£È'=®³%eÓŽü_ê3 •ªBÁ±:7 ¹ê—g»âåm¾ÝÕò1È´I ø_Cw ÝŒ>8 !¶¸Þɼìñ3ÇnÁ^ýÝôKfN÷:ǶEy; ‹jÈk£ðOWÒ³0œºDìB†[W²ÇTÝIîg£Xom¥zï¥L°—(sµa r‹f{º]AL·+Ø”¬†“fž›dy™]¾•pè$Äù§ª)ê«RâSÃó~(K¹!—/ß$)«ö‘„uuþJ¨#Ÿgtp™É"|m¸ÛI0 Éú¡»*ÌmúÛÞí2ÿ¿þ±×muË9™‹¤¨äéâ D^ëƒpí_«¼VlkøCVs_¯ôÔz¼P³0\šiÌàþR ¨ÛªœÈ&¯¿©ÍTohf$°ôŒô£w•yL(šáäPìk\<ž% ؃Dk¿¯¾ÊvcýZ¯Œ°Ð>F,„)vµ³,³}Ç8sÿÈÉWX[O]¯#VJ»ÙÀåx2æxŒžÖ!výúäGûòŸ”ëus4á²Ç[H—P kµà¦&YÌìs3ý:xÑ\Û¥§OM )T3æ4J½Ö=)—¯u Ãlàlž‚ëÕG•M³× »Y—E[¨B$\àãž°¤ï~ø0Z[í endstream endobj 138 0 obj <> stream xÚåZÝo7 ß_q}ª½ÁêQßê¢(°Û[·¼5E›%NÔ©ã´Ðío%κ³t¶ÏNÐnX±øx?QE‘yÅÇŠÿƒBQüWçÓâÅIñä%¨B#eqrYPM(/FP"¡8¹x=¸šÜ¼½OÆËñÛ«ÅÙÍûÓÁñéðçᛓßU„[Œ—w‹Ùp$¨”þýhÙߎþä%/,­4vFËEÁà×Ëáˆ16X¾û§%ðIõû]5h4\”„!'ª•,¿,³ BT¸ÇžÝù|6¤j°<»žÝZ ³òÁå|2™Û—Ÿ¯gWþcþÔ¯ (a —§õbCÌ×Ê쌆 %¨l yRAPï5¤¬òï~9)>„]|.Œ"†#%ìŸišjÂó¤ø£xå·.^"hI¨F&’;¾4!C±h_±Àp;°–‹Ò’@B¬xBJT„ûIOK*:æ^ƒ^½Q¢àDz[ú©Ú "5¤ˆ[áXþ7jÚbZ”1²F7¢‚x6:vÿQj둦`ÄŸ¶^2¤Ò(o©%Þ2&6U0â‚PÈ’o<«‹ñj?êÐÂQV £ †¯‘È£z!_#™GµÐ÷‹m*Câ.[7D´ÇˆŒ*˜õB¬‡¢R&l\ÑD ë†Ð×"§@ÈøGj$QÖÆíxË”h@0fQ´çƒÚ*µ±@«QoìGl®o$œ ŒpY¹[PÞ¸zÝØcçµSŸ®ÀíÈlFšðÚ¡¨„„˜60Õ×8ªÈ £…¶¡”µ‰@ÈÅN dš7$Ó‡– ¨qñy%7v·6‰&(AbÑLæDÉBÖætÜ!ÛqÊl1§ApÂîË*‰#(Ò˾`0ÇA¤Ò;±j ¦*¢°’Ïzžuìȳ´#A7…ÿç>\üN88j©“TÕ¢ª$uëÔæ:Á¸'ˆè•RÊÒ¦«Ñ©Ð.ˆ&NEcRnZ5²Ê¢cÞ"«ßZ½ÏÂñ™Ù³ ²­‰‡·b“ 7èX|eBÏÊ)ª¯óA¿ÈE¤f*xåVºÔL…´‚¹˜É¡3SóÊ”š]@°gÆëdêu µnšhÓ¢2GÕ[a»8˜=8Üß.ñŠ[wWã²Ü?¤®›LÚ´r¯äR%rK›µ‡lâk”bŒê@Ó¦ªƒR[©eIJê ¥?óÐyÅísP†Y&¹Ky»ƒ4C7$¡¤U(Ã#^U ø¡…®O·â6ÅÅÓY-QT„\FŒÁ‰YW«”MÞœl©lJÇE޸ݤ¤ãi ¬xÁ‡\Û—ÚQ[D+8®l+ê® xjüvÐöfðm© ¹ý”½ËÞñ¶ÆÐÅÉØ6]@é6L¼ÐÓ4L™ ‰ÌÞØ´>llr×KbÒTÑ¢ò°bo,0¾ëVÀ\˜P}Ü*ºm"+¨ýj§!Ô~52U…‹êÞɼÐuÍøf1¿ZœMýÃünys·ô¿§gC*ù‚îd>ıƒùÿnrýÁ|+«ðíÓ°–µZyi˵íý>>»pÕbA¹¯ûbøåb>õ¿ÞÕêÇ„õúqÄïÏný\­ûûi¼X^Ÿ+êÙìÂÿ ¬",Îo×Rî¹M®gaäçñbì-PÞõ!ç³¥sT•ò×!³»ékxÓ@é%jm¢Lšk¢ 3%oÂx%ZÌ “-MÃT –Fé&*ÃË4Q,£Ø² iÍBkd†[k £5hïAŽ_kTÖÞ…ÜbÛÛ 2¸ö>¨M}¤“à âã>_,Æ·7þØÏ.n«VÓÜ÷|j÷‘hþ|²~Oàø‹v£»éý‰ìÐm,ë=…¡>­›C©B’{ûîÛ…)K[YqÌ,!êùç Ý!Ž5Í–‘ê ×>í¡  ší•®Î!” r¿ö†L,êÇоÀú+šXµ4¶¦pð÷Zt/`+“¶YWw†’U Ìúz;=d½ÝUST‚¦·ÄmAÃU¶ˆí¶¿@›àº“¿Ò&F+LŸ2¡»¹WåüUáN8ùVT~ØdCÛFY¾Š±Ï-8ô…^~KfýÆÙTMÈ^6À]P „²£¬°²TxKÝhmû˜o«)$탫í•ôo ù›÷äÓÕ3ªLeÛrU¼8·4Ù¯)öë¼TSp ¶3ÄOÈ6…˜»F¢Ñƒ‹Æðò ±hlh“h‚û¢ûJ4–îe²=›BöÓÚÉcè-›-¾Fwøªš° ÞÓïs@?‰¶¸Íà@߉ký)…?O»ç]eèE•N0sVÐÜ Øa߉ÕZ»G£O•½z=ÌÕWÆ^e®ëÆÞìõT(%IP>“މɌríוr¢U×Ú8Št” Š,6![AÇÅÑ:5JU]¥ªzBlT¼Vuè÷t«š¢÷áv‡h}ÝìSSìÜý-.;ÑP·_Qe’*:¨lìþ³íÏ7–·ÕΠ^Ù„u|Žâ Å„‚Ý¡>r'¶'¶¾ °=t ¹®}/”m°þ=÷‰Úê00‰„M1ÖV(µnf&Õ`¿±Œ[:ê¾®ÒBãÑUÚ?ç2YÌsm/]hak«Q*ÑÏá÷ÒÏùþ{,ÿ§~íÕÏ[e[Yf¸duZf¸cE–)²ß8ì×ÐQ ]Z7ßb“f¿TÒ X(‰ìÚÐäÊ ‚Kí²‚Ú£FV í•fwZÛ ÓHr/˜}õÿÿ… endstream endobj 142 0 obj <> stream xÚÅYYÛF~ß_¡G °zÙ7' 8Ázl‚,0Ø—<К‰¶DÊ$•‰óëSÕÕ$›RkÆNXÌ`È>X÷WUݳú¸â«~øÊ øÍWÛãêÛ»ÕŸßò•È™1ru÷Ë›«»‡ÿfßí«ÓàºõF“‰õOwÿ„Ýf%³… »5 J¿û7¬ež=­%ÏZ|ë>à—:kOC}¬­†ºmpÆfo~ü½tíy¨×{Ú½#yŠWL*8ˆ¼`Bx‚ñõ†s¡²ïë¦>"“ó(Y•mÛ~À7Ýç\·$‰_9uí»ƒ;.Xp³âœ•Z<¤…ÑÈ#pÑÙ·Õµù°9›‡`µâ9+ó?åš• >×Lþ뻽 ÛÊh›LÜpDÁQh„·kg^pyÁŸð]€Ð~iü‚­,˜,ÅûìûïÞþx¿†¹ÊêŸ2ë‡jp4Wõô|l‡v-löÔ³õÆ:û—hiØ»ÎÑ—ïÖQdŽæwõÏøkh­¢Ù‡ºs[$¢m¸µÌxJ¦É†»®:íÁúÚ€tääJ3 ðô#øÓv@pR籆¹b¤áßR&,Waý Ì‘U’’a|4ÕÖ­³×à] ÂU‘F]¿ÂÙ“7L‚®’,—ݤ€fä‹NAÕ+|جG«ãKûHó`c“¹n¨·Îï„ ÎšÖûáÁõA°þƒK ƒBV£V:ÞÀ™E½Ï…HáÉKu.hÈr¢‘ߢ‘È$MâƒJ `hâ ªº-†­RŠÂVJ ÙIªÌR!ž0è=“íÒRJVòQŒ„ª3-§ÕÌÙ ŽWãz€Ê4Á åö°2V¸VÑìÇsÕàôPBŠìS’9ä’ÒòïÂ9g1,ÑÄïðX¿X@Ër¾švì+4ÜÏu³#Y@d2éœ-¦µ£«|E.F2®YÁtàö˜¹dæyË„À †©H⿤ŒÎ™}š#\ò5iî•fŽä÷)n°?ßÀ ˜œ§ïâ‚*BŽ©õºnð§}ýùt:|JÐ’‚c¦¬"ö,dÉr}ÿ ‚ÌŽô‚%Ÿöõ¯\dý¾Å0}êi¸Ÿ²;p>b[ˆ]?Zä~ØznêÁE©KUJ^X&ÇhÙ¹ºÍA-‡TVš‘”öö†öX^™°qfIƒdNwP¦^BÝÇ3 Wƒôˆ-°ð.)¤·àÃyÝ¡eºFÓ\õ ¬zDnØCc±ÛÓàYŸ -çzø‚¼]{$’Ð]õõƒ»_¿ˆÕR׋€ÅÇ¿ˆ-Å ¯op#Ö7k±#ý#¶\”.ÓˆÅNz ßw¬’]£Ê™Õq̱gcVEù Ä‚%cÄš|XΈÎba) ÖÐj>!Z¡ˆ-¡ÞÉì€Ílª­š£s¡pñ;Þ(="«(Õ7Pzp*xUò$Ô,@*¾¤ªÀÌòHGC í „Br¶¢êyˆò?Ö@—3Gü7”8=µŒq¸tK‰ÿ9ý´A¢Ê[ ™ìàÏ9UÓ÷ûúttM*zìÜoM( ‚ú`Rc2>ÜU ó‹ú £TÛ¶é]GG›OKd5sØ^–𮯯 §s*BÕ|Ø)vQà5ÔƒJüÌï ÇÂÙ‰SÃZúöÙֺܴ¿sVLu.a¤‚óiHX{ë4¤çÔSûƒI¦;PÏNG†u"cÚ9Ò_j’ߤûµB\6É2Ñ$ÛÐ$Ë¥‰Æ0êB¡¥&Úb]»þ«d ÀMµ?*„‡k I&LŒ¡÷É€‡=Ó–~B7G¸fÓ¸]5EðŒN2µ®›‡ó Þ2x-Æü0)½ÈË—Y ƒÆ–vº0å|þ|¯¿NÚN”Ï7‘íÎ×¶3x ý]¶ Άf—B¡‹c´ öQWö!¤_¶VÁ>ò–}rÅäKíDŽK-8Ƨ˜à¹ëÔgycßÛné쯂ª“ïv·õjô5ƒFì¦}›<öÍ6U¬ø ߨ[q=:fƒ­M…Ë7¬gÿC¿ð²˜»—ü"&¿°PJá¤lUlŒ;/T‘OW‚0àä0xú*ü5œòaVÄÝPŸPqÆÇÀù% ù’©!ª¨Užíìåî É\ ¢·2Š<*tѸ ÃJ±ˆL[f=$¢þñÓâSžõÁŸÛŸïôõ!Ó!iÎP=ÝÝVÞHðB¤àe¬ªx>/{Ÿºª¦¬ÜÓ$u@äp —ùºë]ãNäýiý«»`6´C¾]Ę爅x£•ÉþN¥%|ˆªå±R“Äz”XØòBbœ+¼À}@¹]÷C¼ééuØû­¶$Qý‰*æ€ò¢"YG>áĈ3þî#ñðäBdàšoÊýK³møq¤›šîË Ÿ §ÃÙ¿‘ð%Ü&øe”—ë°-Ò‡Gøì¯©aû|? KÐj£j8øYðjãZ\½[´à8qÁ»¼‹Yk\C­¯|-ô® € Zû<åµŽŠ¨Od´q)c«™óUGÐ|j“û¥:žîFÂóáê v¤‚0&Gu‘ E”†¤šêFgYžoë£7ÎÿÊXœ³õ5FÑ#D>ný÷Ÿ~œ#`” endstream endobj 149 0 obj <> stream xÚí[YÜÆ~ϯàƒap‚VßMfã%Ž qC‹ @V¨Y®v6si­däǧª»Iv{®Qò"XÀÍbUuÕWWs}ÈXFá?–ÿh6šfºÉ^üÀ`…”&»¹Ïe¤(²!SDðìæî_9§ƒ77?#U™•¤ÔÉ$‘@Ä5)-Í-eÆSÛ– …m?æÝcBU¦-Í+K4$Le!çh¹Ø^Å`K””´D¦ª$Tƒ Í,Ýdž¦Û¢"¼„ íó†BÀ“ÒÖ  c‘qb,EcP¢•ßÝu‚'ÜøÇ,õº!‚÷ú7N¿¿Üd2"@«§Œ™‚0ôlZgSЖ)›ûIö:ûÕû5ð纡@¶/ö¸ëEO"g‚ÙI ˜…âB jJÉ‚òV,Ïzû‘0"µF”õœ¶÷¬@×ì0bCò$ä§D;.hE#¹!ª9/H‰¨…=—G[$l2dŒ”" AàÿLpóóÀÍúP²sнÙëKqž;^â–#BÝ•$ûœh~‰äPœg?ÚßäAœ6êîÍ EI ~Fr0†(øíDtÉIÁNCt±3Uc½’ìáÏËÖºqH“§ ž[ÓáJš²D¿¸zJix—š­E•Z´”Å!Ê­"m¬¸!ÌùõÛ=~ý6¥8„¡R?K›ý;,b½Cl 9ä'!lèS~$8Øî:NiVy‰`M`C[«¸m|¬4lmw©Õ@2Н>Šø¶9GËâÝ£J¦1%½H—ÆÅò­LÅý¡’¤ü_ÅýqڟĶâžÉ’¨2ƒ¨?6èuÐN±#J‚>ηæ¼Ö3Q¢Kç 6X0ý=k%vViOtf¯qéDëM¶«é)Œm>„š3»<Ë Å—2¨2ìJ0Ôµ—ÈùÕk¾Ú)†`®¡ýv5„¸P±;¤—û&Ô"y™ˆñ!dS;{7—À‡¬Ôè4 =v—_xçúÒ}v3„‚È`··ûFpKðü Ü‹ëXš Ýœ°ö‚JeS)p‚Àí"»ÄÀ¸]g މMµs,„­3êáEnùÑ”âhA<ÞUÁt‘A>®$¾Ùˆ7‰mÓÈdÂæ I¼ ô/,²#(÷,|=v˜2Lâg?\‡õµï¾dß-‰PqŽ­ÚùΕç5&}Ò¤Iˆ.ZÈÊþ¸â¹‰ÙØ ÚJ ¹:û8%7›/?ÞªóŽ>Ä®0S_Ãì¸0ëœÑ%‘Ä‚ þ ”H ›‘I<$g†±¥ÔHœÇ˜›M'ƒ!ãùõ溯 '‹ÆÉ}î’p韎ú]—x‚#™v­9îÓ‘_ØyÎΰéh¨NJ¦ýg¬VnÌqWd2#IOúy¤A›© Þ‚)È9§%Ym‹ÉçF•Àïl¼©¦‡wwðÑB»ÎÜ’ÌÀòY ¶¸µØë µ€/Ìž­=,m³a¸§–æXDƆa$ÙïÿÃÄΤ"°Ë]=­fwžPFñ{WˆŸ²«~¿'ƒ¡"gð+¥Ê_ÎÜ}ý©š.&µ»™ßã¯Ì×~a:ž§nòÍx>š¯ÖŽF/5ÇGOîÉb97©§ÄmŠ V@<åªÂÍóYº‡£Êküngî¹ÍªõfYMÕöö~¾Þ:ßLªu}ç¸T+÷ÌoJÑdâÄŒgïÍ_ÿîy‰°›À²­í(í»j«úø·:yj[Åd ¥F9'þ–p °*<^¾kð"£È'²Ä{¸öáËžµ¬ËmÞ‡¶m¹œñõcŸI‰3„ŸÊÍë*x½Iµ<6ºIµ/S–(°¥ÅA± ÒñV²6< ¼Çƒ=AKó©ÏEcAHp‰ì ô-ÑmÎü~‡¢àÖ½Â~‹té ¥TþXÖ2ó”“ '¥=ØcÇ8Iïq’8ËG­‹Ÿç$8iŸyEl^p)ñ«YKrK)M‚Z£2j³Ç^ؾ²W»ãÇ˯Ç}>E×g>Ëfê`§m&›=œL[W"“PÔ¤%ü.™QîNŸw© Òáñ\RŠŒ¤@rt°†|™ˆ•Æ okÜyl½XaÚú)m„ÀXôÞÉyë ­f²Ôøg3Cašƒ»I *ûj[.ò)—»¬ÜÌû<º_3óaI?7ÇKŠÓ6Ø-MäP{цMìX;6©zl­ó${{ž²>*ÎÉÅ‘x™â¯&ŒÂË€–ÙõÀmTbùĶ 2³hR3L„ƒâŒ«üýdÑë´Uiûj|òÈ4Ó»¤æ>ì³C•—³¬«»ó’b'Ù1/¡T™TeÛ>ø^Ǩü?îÇ ´W®/ÌõEFæ­ë‹µ}‘‘A_ïªu宯3÷ûýO¿¼Dê?¿v•NùhÍ'@ì’ªµw ƒOÂg>åRõëϳùb5^Å~âqÇ‚Ð&›ÒÍ~㨭œ£ÞâþÞúßÚ•÷Ëjñà~ÿã•»h_ùøvù°Ú^¬ÞNæOýÅQµ¸²z1˜"ñ;D×z…T Ø¿;šÏV~}ôP-½÷³jZß®Sæ`„lS×¶€ß׫Ñr¼Xç³$Àq^ È]׫Š|9߬dz¶s -¨i×n›,!£ç4¥IWNÀº‘÷×°àqWQ ÷ŽàÆã®î—s»Væ~a]ê8H;,Àñ³À×Huæ·1@Û];¼¹É`‡‰ÍÕ<±®—)#ÁDÜvC?¦¬Ò=^-`@0y=£¶5Ú‡1o¸ðøÃËy×ï]áŠÆ†Ï>yzpNµöåÎbpã-Wø¹ßðŒºanVëù²¾ÃL˜üoóµƒÃ°,Ýßüµö[?@t”ÖÎ:`ÀÚ- ÇíÔ‚7N)ýÀ†K£ÍrYÏP˧«Dk\,šEœó¢×¼QðÒEû& úë9Šëg-|¹^V+œ±ðÙÓxí_G–¸+nhú!Â4 Ðo¹ú$‘˜Ÿ=žØšŒLV=@qqP¢ae³NBšàØñ¨*"T;“ÂïŪÆ(áÒѼ™8¹le=¹ó´÷nq^úìÁšR‘¨·^üÝ|ÀKéhð[¨¯í³H®@DjðÄ/Þó±ðäLÀ¸‹ò#ú!úqbÖ`J Æt{>Ð8ÖÏÞ«të¹9¢—•;{Y¨ZŠ«h¤þdë…?±Ú|@hW“MM0ºOÚXj,â}Ä Tp@ýÇTÞZ;zÙ(PÄ©:ödz¹2›¬àLOÙmÃYR~κK€¶^¦L(ðiW’DgIC8Û»{÷Ôe Xhጫî©8Îäðƒp.ˆQœ#¹Õrä.|âƒg=KVv8–Æ›$ŽyÙøˆ†8fpÜ߯¹ó\ãÊÉ÷аÜLÙJ²tJº0ß8`3WZºw¨3 >éê;qy~æB{ôÁÒü< ó§mÃŵqà½Uà Aà­02Ò}Éq-ã׸89 âV÷ÇÛ?ÛªÔYÒV\èî¬â*ªd0-|ý]ºûMÜE¨¹ Îâ¦(n4€‹j4vžºØà¡;‚‡ë(x:Dm;)xx×9¡p÷•¨uÛ½q»‡’òÎÞ5±$÷×”fl“[—¼‡Zº™·ÿ į¿û/£|ø endstream endobj 154 0 obj <> stream xÚ¥X[sÛÆ~ï¯@ýR0c®ì..qûà:ŽFiÓ&±ÞÂŒ»–$j P´œéï9{.”à(3i†‹ÅÙs¿| ï£zü…^Áàåïï·ÞÕ·Ê ‘™w»õB-2å­q#ön‹ŸýÛ½]­eùGÓšƒím»úåö;8F³c‰Jo£déÔ 'Á¦ÍIXazC«»ª‘©Ÿ£ø/a3…ã¼–*qî”BkÇò¼/åÅœí·Í©/k~èú¦—° Á܆0™ÔË™"‚ˆŠ,Á÷J@lסˆ%ðß %ÞH‚‡Á¤ÈÑYcÛõ©.{Úrát+çkø©É!°€èfÅþY¬ÖJ*ÿf»ƒD‰4]J” 3e"&úë‚a(tÈïƒÇLÚ–˜UAì×M?ók!86 D'à¬Th9¥ºr4dùžcºÃmËz·hR l6Ûjd)«¤ˆ²/¦¾‚Çž„'¾ãàVèmü5¤Uo?õ´ç*&‚Ts¿w7"m­)h»¬! °Áˆ\Jš³õ^‡Z ©ç9KÉLû¶.:ZË~O+r<,º0Œ?ÑÃ]%£)úb÷y)´‰GýB«ÆÐfzT×%+bºît°ëÒÐïè |È›ÃÊ©³óse6¸ZŒ]-fÊÏMg™4T%;&A2wLaGÞ¨”¾+øÝl"‡ —®ié‡b³b«“™ÕÁ< ²ý©­»%çpsI1¤R JA3Ê×ô¥ÓöÎØo *¨Ržƒ¾ÛS…u£Ôttê@øÀ:¸‡Ï¶m°ªãÌÿ7·ç²³|ÚÙ $G¨Ów¤aÙ¶m›–¶ ÖìF_’%£+M]›&ÉðP7õš¤?ã³·ŸÌáÈýüí-µ0ñR˜bñ@¬µˆ"GÝ?maÁw:RXÙ§œºP0|¿‚'cxõÒiÿÞ¶P´¦ö+hÿùZ~uå˜D©ˆ.&¨bÎ]Ïç;Øî»WOåÇÖOþ¿jŒ'£PdÀ<×Éÿ¨mñÛªæü’V¹9+èпÓ`=7Ø|Éà²î‰â`Êzãß7eÁe¶hò®:¾ßµæ¸gÛ®_-Çl5æä‚¾×ôòoôƒLs軽%Þ¿+?Ûf»á8mVlý°mx{³ZàÝÚþ wlêïeîÛø×Ì®Ùn(Mr^Ž9…‘qóIΙOGÌtDa¨F%I\ ®Áïàè4X¾è\‰ °àÅ`óz¦…ºÜõfrÁŸÙÄ”œÑ`ŸÇÕbúýVá<ÓF¾¹ùþõJ†þ›wˆã"t-¸q:Ѓ‹T1àWgzslHzG&ýmÓL?t#Ý?]ó¢Ýqš`[Ä8QAN§Ê©N§ñàî‹P])%¤¼ÄêÎhÇÎx.ëã‰Áô8Cq»cXË¿2„x¥ÿúÝ›7In\;ì1‡q ãȿ鉞ÊÖeC.ª*"s 4lËÜðÖÇ“aµúÒÑÃi§2œ› #2˜±;Ûvã«a‰¾5õŽ©ælÖ×H=ÙM 7Í G\žzܨcO­K†K÷¤Ô%ùHôjQˆT¿)D/Ñ——-XLB¾` ¬â¡|Ã_¨ •΄Ž]+ÿõ?øçX…U™øgξ2?‰×˜br/ÆÖ @Þz·&Üp)ùjLháð‚Û@Û= )ß4‡d1txnr®q‰Ó³`ºŽò)–)nw°Œý]IÝŒ^ì)?M½ÆÁnb’Гʚ¦áwDfdjã:x4ÜN¢Ùux~v8n೫ñ¶K‘ /Ú!w•$ÆÑåÐaÓJôhBL†Ç£ I ¦…9rá,ý$õ)Rg¸X:V2)=If£¤¸^Dw/ Í/ÜÆ2éÔes‚ nN¨ÄB7¤LZÑ7 ¾ÒA \6¯…»i–!X¸ü°2²ÉðÝE\^3¢G××ÔƒÙ˜ˆ8a^nÒÜîq´àjø5FËêTÃe˜ô„ÌRïŒöiŒ_ê¼0MD4>WÞ;ïGÖB‚†Y’:%"üÎD@+/ÁÑêébÆBCuÇT¹bQºO) iðU‰ÍŸh7óïÀ§-1CñQÈü£îŸô¼Ùð7•FaÛõ´K > stream xÚYKsÛȾçWðV™XÌ 9i%»Ê©d½Y©*‡8ˆ%lH€! õz}ú5à€ZrJªÂ<{º¿~Îpñß…Zdð§NöXï?>,~øà*K«¬Z®¹±i†õ±=Œu-*³˜úø\¾…F’g ŽÔÜ´L\’Ý­*o¼óØ4«9Ÿ4áw’b•)S]†šÍ;5j."V®SçÅB„/ÓÙiE»i:d`œ¤3Z‹ºµûÅ6XÎÀcëžwÔmÇ6sÃŒ­Y™u=¶°ˆV·Û‡ ¹ðŒbË–mÏǯ{v:?ý²•›Ôά\ B»59A¤(S—‹Àlk— ïý„Ãnçg.”uà‘ÅÈJ 9›'rú¬H~[æ6©w/ ¯Ä{×íö+ÛXdhUV<2rGžè·²À{ï0wF¡‘²ûþøŸTŒ%ËPÔ +h@²ÄW|NHãpø3PŒfPŒ%PÜ L„ @÷ 7Å–Nl` L(»†é ³½18æIaeË´ra ù @6ŠB¤­Âˆ8ÄR„ÊŠTy¿¹Ùí`“E•Lƒ¾§¨j5ûýÀS§ðnA¶Yx·"òÞqkí #sâå²d¯ç•°y%”s*¦,=‹Øä)ᄇ†—Ãa÷•wÖÝÆ¯ÛOí €áp•éäñeäå]?ò’ñXwÃðÜöl‚dã C¡P†Z¦Z †Òd¡}GŒTÅÜ; ÿ¥Ÿ±å`¦[ýÑû³u<ɲü0q_‘׿d D)Õ‚L3U°¸•ã¸ðôK¡_Ì‘…>¥ö@ Î~[ŸŠ›šc¿øÆË Dzåw¼V$<™¼½LÅúÍ©X¹*­Ø$¼ã}úçÛó¯qe4ÿâøò¯I•Šå©*-‹Xþ5ÎIþÅŠŽó/žÈ_Ê¿Ø •ãæžI|sFÎËìjŒ4yê<P$$äi^^„H þÔþ†ÊôÜ^pDžjJ›Zø<ŸÒhKï¤Nìø;½°EÜx<©§b ?ŽÜ9*¶J~%]ê2-¼îR&w Eˆº>\±.È4öF I0:†³-W Àù¾áüË” ´wpA”ãªÐñ>'­$öñ~hG9àó’È»æ"ÀÏNۺ橞$¥ò\·ç({‚+nI*µù„g$yi)«B¼áJ^½–·*ª|~µÑ%{‹†(MÁ (Í賡%AðÌÖQè¢`¥KwÚ‰i§IQ8ÐæGi™òØ ¯/ÏNòÙ’ÔÇ\¾Q›y5p~')þ@¨$K¾&Öï¹åÆÝý7Ðf©q{ó³4>ÁÜ·ƒ¤ .)¦ˆ_R `}CÌÓÌ,ÒL “±º$µ`~ÉüªgÈUÅ*­q|U ô¥ÃÌS1ÎQÒå&ù°,ÙAh-ËÛc¬oΨ|N¼,YXbƒäj’¥ýËr¥ —ü“ɤΜdg#£°…Áˆøô:ª:Uü¨ÑHÌQÎbŽÕ*Œ9Ø%+³p)‰Çf\«[#âcÒµÎß»",•©ñÙfË%^pÅdXÜ×i\Ê4˜YSRLe w†&¤Rïz à…„»J,$w ’âj ™nöK,™œt± ¬É…J¸æ; õÃ4}T™´t‚V³FyL•Köõï¦03ÃTIQ g˜ÂfSb £¦HU0U’¦‰bSH5¦|#¦f”¡ ¹âJ>Û¦ÚÇ]s.> stream xÚíXÝoÛ6ß_¡·ÉCÌŠ%l{h×µè°b蚇Ë)²’¨µ%W’›¶Ø¿;)Ñ m¯ÈëР”É;Þñw÷;~D"%ðGZÀ_U›èÙyôä×QΊ,‹Î¯axÉø¯þŒËÅ2*N±IcMM²‰4‰•ëýëü— ZT›~žPË©QV-?¥fç-&kØpëºôÕR_-©‰Äõ>°V…ºÌLuwmÆ~>·¨fç`-u°¢7‚q&aalܬ·NíCÄd‘GwQZ°\‘†æÑ&Ê$Ëõô{½ÞlxRÖÎ]ߌõƒÙ Ŋ›½(X"NÎîIÙÙ7M[uøXJ%â°‘Ö¢éáf³I¼Û`°Œ/žv8tG#Û¾»Z×\•cI34-õ<õúéBòø§·f-ËT³]‘¬PÆ“ë®ß”£|òBGèbR ÓKÅ–"ein$ß~n»íÐ û‘ž ׌ç0y–»ø6íH顺4 ¼´K¿0]7}¹½%‰ï^žÑǤóñ²¿îw–—ëîîagUnÏŒc\dfyiºïˆ€U«Xuí`û«Û²·\·å¦¾X|ƒ+IkËY*ÍÌÏë¡ê›íØt­UP>)쉟ßblu÷ÝnlÚÚêìá—qÌ“ÄÈ?,d$áLVÁdc$c…M$¡)‘´v‰C”H0tG:s"Á›H 6vÔ–væúÓ¬¯ÖvM A°ä:g*õñ7ùF ÿ–R ›nŒBÆ(IâmÙC(ƺ¡¤«¹]ôË*f ÉF7«M6ü¼ˆÛz¤ÅÃ]ÿþb±XŠ¢@@lCRÝdF¿«+L™€ømS¡Æ-I[hó¸®D£¾oТŸôQÞ¢Ìè䊜åÂn‡”€ï0–mUÅ ½?Š[Æ’Ôbc¨ÀN ¬o$c§÷&J(, ±N9Ô#õBý6­Yº¢õ©z½º7Š þl§ ¹Ès‰0ýU·BNæL;!SçŠ|6ümÔ=ä) P&ãÈÕº3–+ŒÈ{ªP#5K÷€÷BŒ ¥%ÄÀ¹œø¨*ëÉ•pF`…Æ1Å2,,£RÛ„ÖÂdMgnJ øvÛíúó“U½)[ÄR*Xdd¹ÞA.,•Rñ«ë *cZ‚½ç;D[h+ôC¨¾pĆÆë[3Úv ¶†Ý¦¶Î·ÓV²g •,TÆ”˜ú#©ñÌ>@Q!ûåzM=mgˆ¹ªf㜌Ë@±ÉNF±Äáh¶žP a£Ï}ÒÜ«™! –4øëšZ[/´Gô$itÊtv’4O(iÀ­ÉpÙWôaë>|ÝgËRrîqƒ@•)FÅ#Ï)¶(Á´ËƒõÃN.|ªR~R|5¹x\*D.y”\êq˜Â— “K9rÉ™\€×D+Íé<ù(ZÁáíZ=ŠVdG«ÝÃȘP_O«"™Ï‘°Qzú½Ç)wJÌ=Zúƒc&üÈ@ü˪¡ˆ\,€{iΑ{ûSžòÁF?8”­ìÅ'c¹i9ƒãÇçÏ~½|ýôT*a‰CûŒ®Y½”O\u˜¸ìiúhÔˆ¸ò(q• ›´Ì%‘t¿ÎdÎ[ž¢àþjà^ÅÌéB+ ¾’6VÞ w­Z9Ö++} \f€W ûýr)óãårZFâüÜC]M¨‹ ‰5É ù¡8‰iš=òt•~å‡N'^Šf߯ŸB§'ï@2! _¡6I}ð0/4P´5Pìʼníè\™ è<šbͨ€f‡ ¨œ¯³Ç èädcݱ†3Ê:ü ŠcT@óØL, "ÏlÍæªñªóuç’Ô¥@:Ÿjq*\•“¸ã”xWº–»Öd-OÜe͞ēY𨯧kbF'™9‘L(îåÃ>Ç`³J¿æHÂ-ÇÀ%Ã1ðh®lÐyøH’0Á‡'|ÁžvŸS &N!R†Sè—(É™ \ñ6g¶Y`V5ÒñÇÃØ7íMÕÄ{1Cá³ÈŸRÀfIÑ7_&ÜóT¸GøšU°·£–ö9Û‰¯> stream xÚíYßoã6~¿¿Bè=T>Ä\Q$E ÛÐv EÚK±y(p>ä´¶’¨k[®$'͵ýß;Ã!%ÊfâM÷õ°ÁZ"‡Ãá7ó GdôKÄ£þñH§ð—DËMôõeôâ Ï"ÎY¡Tty ýsž°"‹.WÿŽSÆ™œÍ9OU|³ÞÍþsù]ôú2ú%b¢È£ûH,—f€Î¢M” –k÷ºŽÞE?&…ì$›z»lºþH9!FíœK&Nª÷¤¬~°{.´ŒÇ/›íL$ñÝLð¸j{êê ¶ì7Ô`,2ò‹„«GÜSÏ®mÞ¯« uö ýž_ó_¼ÑNœhÊÜÙ’*¦´±åÝöÙuuçKö§Þ ®Ï£¹R,¡!wM½šÍyàÊ‚uµÞ-Ì;ZC½ÿ¸8ÅnÚrwkÛßÚözÛÓöÜTÝaãÝU{ hš `ι`J¬”ŒË«us8´¼Z–»@#ع˜½ #8ÓèÚÜÍðªê–m½ëkð >(Š’Ä…¿¼­ø\Çm³ïëmeÇLÌ8KSˆg”ŸB˜!—Lr+ü~_¯WéÇšßÑëy/b¾˜ý¾ˆÅbË– ïoëå,Íâ[È zÚ¶ê îÒ´˜ °¥rc1€hV%$¤‡²¯ ïëþ–žh­ÐýDìñ âÉ>£ŠØ¾„q8ynž¦9Ëô±ï’ä„ï »æVÕÛï|DzÞiµñ¶ê•{ü¯i?,fà”ÂxÄ6$e<¨ŒϰE[h$JD÷á„6¨3Ô(oƒ   FÈk9ËSßkc(?êm·¬Žb~’*Ná¦X&-6&?°)Ó¹(-ñ‡‹ËˆTìÿöšëždê.4cÎqQÖSçWÿú!4¥Ù@H茴õn=.üÌ\û®²uUäQ7kp‰ E‰ÆÚg5që{Š;™ ¹_™i=?ƒ´âà§Ël–[¨W%Da(»®¾Afª”¬ÑÆí¬Q£5ðèF‘5ð`òüŽN†—i¾[‰¢Ð¿¯œCÏa_$þ‚3Þ¼ x°I Ï|Û†~Cë„áÖ e[ÙOµrL—Œ«ã€-N%éŒ%ÊÚböîpÀÎ^ÃF=a#L‰ö/ h]ÕS« ÂfuI„”ÕzuЋ ~°jƒI0cˆ¯š=x3ddδª1jŠ|œøç€*­ú•:Ve_RÏûucf6Ûî*\æBj¦Rß™^N¢“b¥„¤áLN&[Ÿ«l/ìtšÚxŸeP˜qÌÆÖÐZ˜È£Aâl²_@Œìw»õËUµ)·+Š»P«\ï+Œ])1vC@Ê Ë¥cgOlo§.W|*¢8bCý‰µ­¶eDÝ ±¹ßTÖ8³Ï&â ‡ý“€Êpw$¾DOê8!®›–æ/×ë‘dÀôUÕYΈ¬`\“&ÉNV6‰ÃÑ”²!§Dî“æ` Ë ip¿óHƒo×ôk78í‘Æï=I؉àóæi4ÓÜ' ˜5L\¶Kz ¶àÓ![ :â7T¡Ð+yN±E†èâ`}‚¥ÊƒŸ ѳ2fm«ôAKMT6û­­Ëúæ *£Õ¥1Œš\ø¥ü x6¹x\2D.ñ$¹ä§aŠßÍarIG.1’ ðh¥!öÓO¥| þŸVŸD+1~íC c©|>­ W9ê"†}ˆÐÒû„SÚ~‹åÞZ:ƒðîÏ3™Ó-²r¢?þíOtr·m endstream endobj 166 0 obj <> stream xÚV]o›0}߯@}hâlèÖ—Jmµ©ë:-{# iiIÈ Y»Iûï³±I\®Õ¡VJ|ï=çÜ/œŸrBñ‡ŽÅèÌWÎÙÔ9¾@܉ƒ„1gºtp`êø(gºøæÞV›lU®çu»ÍªMêÞL…WT. ‰–tËu¹*ÿ¨bhÀѳ«0»?QÛÿFíQO©‹'4õÔIû°á#Ÿ0’I40ò½/šð/2|LøÀv¿Qyux>dÉ'ÉÀ—ì}qçS3ìêÆ(HpGþe7» ¥$¦µµ7M†ž÷FP"JgÜwêTw*„…&ÚÎ7J·ÐY›kL÷e£…CËS"#  8ªÎC #™—$(  ÿUÐ1°vOm0r¨kÍÐèÌKÉ0 Þ--52|I‚ c×}›®o«÷%‰HÄv‰ØÖ¨xŒDvÞ*a”¦Ù|}‡Œ«‹:γz·^´Ö*­w§¶Ýê­˜À> stream xÚíZmoÛ8þ~¿BØOò]ÌŠ/¢¤í݇n{-ºÛ-ºi8 . ÅVmdË•ä¦îÇß ‡”([Ž“î—ÅáР&Å·áð™g†#ŸDð‰€¿(X®ƒŸ.‚'/¹8gYWÐ>çËtp±ú ÆY<›s.âðºÚÎ>^üüó"ø0™¥Á]g,Uf@¢ƒu %KW­‚÷Áo ì"ër³¬Ûî`r]¤fç\1yrz¯—¿¾iæÕõl.cþâ°­«/3…UAˆr=“<Ü­éÉ”kìzGl›ú²*L7Þ•Ý u«wݼ¾šß–UW4f3óD2¢HΈBÔ ŒX›ö'/“ÅŒ2|®8ãÁ\Ä,NLç÷ß6õ¶-[§Ú«ð†ð„ñ4˜ëŒEÜ )7 sL‡õÉêõS} Ë.Ì£ë&ßÞP¿¾:£B?æË§æ¦Ý˜ªê»Ã‡Ë|{fäâB› ÆñXèkÛ«z³ë‚âçûj)_˜m¹˜=ÒWÒl›§,–fÕE»lÊmWÖ;@ùZŠY¦üî7 ‹HuØÀ™•›ÂŽ©66:LÿeN-EL¥v FmV--Rƒ\ë¼¢ l~gÄ„Zv5=íœ@„B¡ EêPˆM„Bhº£–…ØhPh Ç“˜)鉙\q½Pó¨Ç#s #‚8e ͵…˳S fà "c‚`'†Ñ8ÐŽ©G ¦ñ$œÁûmÝYÁº›¼s%€»)¹£¡JñyW6Eë„®\oÛÞëBñ$\å]nÛkú½D%…¶o¹™ Ð|q]4s«²^6§²/3°ç¼Ú+ÒË4‚d*ÃmÞäëÂü†à(‡¡W˜ÉX&l3nçËñG…ÖN±¸7E‡"ßÍ`us»˜Ù¥›º­©W {6ú½Xvôàî¦\â¨êÜnI˱YØÕ:Ú†ã[,ûAÉÃi+âHPž¶>”ÔÛvùfYP OûRó‚h'´›e'´«Y[õêšÐ°,Ël£‚d¤X"STQÖðP¶EGOë+ú%„A³R­öZqßì´S"ò|;bK‚B¦,éq°Á©ÓaaÒTÓ_©Á¢Z.«Ú¬¼Äù%6žK•°Xø§ã!Žà` ÿ9”9òµ ÞÓiìÒvƒñ+¦‘yÑ^Œ¸SÛa2 úgä& i1ÛÝv[}{²*ÖùfEÀÚ”±6Ë8~c ~ ɾFÉwä–#SЭZ“US«Q$4ô 7ùæÚEøÁJûR1 GÑÔy¦L9ݼ~{ñé×gÿžØ¿ŠXäzÙSQZ¡þ¼SùÛ‘éÓ‡Lï8å#Cƒáë«©ÙDÄô„yŒNìêô÷)¯ÆMÔY ïìoK¿yÛîÖÅŠlÛPùÄBÈ'p•À•fЏúb? #’áªnh}ãðÉÆ¸ÖpU´D2sed{4é4£X$­à&š‚|Ê0”ôŠ?€¡رà‡iŒ$>AQoë½]¢íÀüerôž$â(\kà(|Š,„¿¥ç¨¡5É$pZ}Œ£$‹Ä8ª²´âØ…µuáP ŽÂ6â¨44œ„e2%†£ôÀQ Þ"À$ŽÎ—Sl"`HÚ7$Ä[K¡£¨ùnC0î6€0´ï÷&öÂ8tQÒ1 êÓXå>ñHa9°p·wŸx$'_0¬çñÌ‘k”6ûúß¼FÌgÌAé£HXRS$F@߉=Ì©ðÏÑ[”Ï?<ÃÌÝAˆÄã“!’p€hëjB$Ô°8 Átp:{Î1ƒjbŽŒ\6÷íªÊâÕÏ#b¥íê†æÔC“:‹Mê¬ü23eõ­ª ›¦Ä!ek‰¯(’lÒ!wu—[-"jLÖÎèc¡ñ±°œ'øÚã„ÆÒQæ&~û¯7oÎ~l¦mok½™að‚›Ú²ŒÑÓÊ…ÆBL:ž,=éxÒÁñ|Þ†RǽŽÍÎá¯çu`YãW\v ƒ×ñ[Gê^GûÙ9á²sF>ãu `½´xÅtã„Æ}ïªM§á3àÖǤ7J¦œ’¿N†$ê;¼‘!ë_ä8{ãú#ùÉü‘Á[¯£}Ù´“íQø"cñ¼zâéçdȯm§2V"¹Øp“}†ßߦvE¿¤Ç÷¨õdT•j̪ÂwÆ"?ª-ìgŸ„6ûŒýéì³fQ:Âsm_“úYè>œx0‡Êq˜ãk#1¼]“|ê#çwOfz@ºƒ(}ÆD¤óª»‚B¢2¯ì€½­P®Ú]ÓáÁ›üºÏ5'6تºr[•”›ÖÖÏc@‹uÓÞë¨t¤DËõfUnð%¶Ø³Fâ¦-Ê—ÓûE)xX|Þ啽‘ýº&·q=[„mQ¸¢0ŽJHŠüà÷ýî²EÿQÛúbñSNÜvÝ ü`®ºJEȦǦXm›7ßf©°¡[DÛQÇ ¸—ç[PÊÒÊ‹I¼þ•VÖ¹•[dpso ?Ï—Iÿ¸ÌЃãji¢^tÂëí®+&£7(ö×E$â)tɇä%“qî!ŠBà™Ý²X9Ú®¥"y)o?Ö•øG;i ¨b¦GW–iâ———§#tcäÕØð§sÁžo¨áÝRðEøöSóxÌÔ|œUÅvŸÀv>P…IP(–—åŠ-f6ܵdvU²$ÉFzºª+›¦¾Æ‹5v ù“Ä“BP=zþýøp¡·KNN-îŽ? Àß[%½TÖ^ Ô»‚©#©ßE8yÍÒô'øvüÆÆ%Fß>%ÊÞ­Æ“å!KMéV^:DîßÒÓ‰)€?".ALIûî´hŽ0ÆMûþ‹˜—r!JÛd¤—.j}s›±Ûsùt6ç:™TÀ;éoí3vð)ðwœdͬÁ$€8úºÿ–„Ï’ÔL(0´ŸÇ‚ˆdüõášžimújCgæc‰7ï~±ß­·U±¶¤n=>GúŒ… $ð{¡½[ÌWEýÇV¦+ª_æ-ò±´Ù›Å2DjÂt'Ç‚ÜÖ·?Îæ)øÉ7ŒÏMðr–ÂlÍÊ~Øôsð”ð_rÑ&‡¯Ò^0 ©Î…ZfŠ]uK/®ZsÁU1úÛ—V¤–PÆÃ·ýg!~Òžý@úðõüÙÛÔõyÝl™™O…çÅ–öÒtV€¹Lâù»sj†Ïv×&9„5žia(G>¿É· l.þµ™¢ÿ§Y,~ÅHòªwøýVŸpl²êƒÅÃwôሑ\*À> stream xÚÅZm·þÞ_¡"ºj#fù¶/µkôû ‰“ØW @U¸{ÒJÚz¥•÷Åw‡¢ÿ½3rwu¢tgÇE`"¹CÎp8ópfx“> áŸÄþ‡“ÅvòíÕä›K5á!KÃtrµšpÍR5™á@4¹Zþ#x]µùt&” ÚMÖbKYYR£©Ê®-ªõÕv­$¨vùn*â mhæææDS]Og: þ/Úâ#ÒØÅ?N5®Ûå_C?AV/hÂ<äºB›Æ}Ú-iή2Ü–viË»µ¼‹¬læS¢Dɺ6_Nÿyõ7؜ݣdZ›=^ã„»éLJA’J)ƒº‚­íLG8v4+o8›«»†Æ b˜¯ózûˆÌ>–Ì0ûæ2i7® ÓÒp}“·]½k,™:$!†*4ßáÄBÓýqßÛ¬$ƃú±·ªº]Ï•‹Ñz3˜Ž+JbüòûŸÞ½xýãO—o=¼{N¯+Zvìkd‰º4lò¬)®ËüXä·EÓ6çeƒ Ï/®.Ήð÷]f‰Ô[ÑoÓfuk‡6ö[“£¹ÀlÐDÒM!_d]ãHª­míë ÝRg™µµÌ ‹f°nMƒ»Ê²ºwÄdªdNáØ’*˜(ÁÀv°ÕŠ~ël·ÎØ>WÁÕ¦hht1X0ÎrÃ`¹•fl8™^±":²QJi-@³éöûònšÈt ÁMn6éd¼öhnÓm{íy…÷Luä D!;XãwÅ¢HX¤ Eá;G‚8 ãÄÑoP»èjFÐlšª«Ö z§nœùݹòIÌ#ÁddMÇ/qê‘ø`ˆ)>ˆü̳)Ιæ–I8Ÿ~M2å·‹<_6>ÃךigЯ^_½ûáâϲ*dÐ *¿ÿÈH1‘ùЛ‹×/_œs¢+hƒ—úȪêìë|›­ååQ·y½-vYklÎ]*î] GŒi ŒOÚÂwÜ<™./^}nC6 ¯»©4ؘmÀ˜uüÜ’,ó.³ *ì(¹ ¬ëlK£eµ.à¡*å`t¯VŽÖ8_ÉWq1Ëqä¡0º"‰àn@å‚YCD?¤;À³Ý"·f´/\Ýý“Û áõ èÑ "¦«š§×Ýz¶.÷ïÿºÞu¬ª×^ åÈÖÖï)Ø8A b§LSð]µÝ‚Z%Ç[ݳ¨½SûÛí[´#!Ðm‹5*^H«xh<ΪÕì}Q¶Æh^¬ëªÏÞÒ4£^T+t ˜™;c ¸XE”»¼E]ßL®Þc” …øËÑ=..uƒò$®9 Š¿ YÄpO©ÐhF:æ P[žØš¥_‰BZ²37؉Z,â‹` o”8 ƒlÑv€¦ ¥"k³Êj½Rñ8£Ú-Ý7ú'§€ UÓzÄJ²H[ÁE=Õa°èÊÌ\üÇÛС–€6l³dKQØŒö/R‰G4ò$žy\BJâÎð¶ˆ{W½}x‚3Õo¯Úà #X+k¹1¸t]¬ñâŠ5Ù^ÜÛž¥­ˆ4;IsW´Ö¨¡G¨kÇFßsŠZ…d±ïì2„ÄÜðWUYVÆ7ŠÝºÇ|¼þÙ,ûâÊæo^ÚF½¦¬€>ÁUÂjº´@³qâúd&!ÊÅ9Ü…Ekƒéå²±Ø6¨ÈÆÝmQY}GßoðÞü*îX:%,vç‹Ùƒg Á™p×zëYAâfèó{IÈ”Cž0û‹¥;O ²þÂ…ÞØvFŽwG`ÃÚ1ôÇV‰CŠSñ4IÏ]òP83®‡Àלœ!mÌñ8ƒŠû³ÆÖèhÁ]làJŸ0ëÃÆ<ðj%Xzï˜õÁ1'eï·Eg” æ>SdÑôz/XÑÞí±Ž#ÄóAÇéLE!C\ã,ådÐÜzc£ÝQ/í½(•Aê2oú ÙoDr¶¸æ³Œ¾ÎKÇMlÖÓ¸ËÎy²ÉÅpµÜºX±µ©ãŸ|R¥j°˜/‘Wø÷>bR3‘LèOÞ¹OÃ|ÀÎ{üêóìÕœ•Ú$“ÉHmS‹c2Ôè#“æt!W\¹tv„cûŽpLÇ4ûMò³8Ögp,ü•8!Zö$Oýi]*G86dÊÑǰ¶C8†YúÇàÃ(ã Hdp ~ãp¤÷”¢”"€±>Ï}à®"‹¸ƒ±è$Œ=ÅŠÖbS…ßƼâ¥LÅ¢˜£˜ò­ƒ+F¡Ä< CŸÀ Séopѧêä¾ñ³ø¦?‹>Áäÿ¦Ò“àgráø)S3†œÊ$K&©¢ššHCWq HÜ$àð°»Êóå5Aç{K`ÊÚ¸ºdrìÚúÈÒóÎÈ÷}°fœ¡A¤ü¡GôÙòÃÐà/ „¨ÛÆÁªa "¦¢ŠÑ¨)€"At\"¥£†}$sއã¤Ðü³ãÐvGq项;Ô/àë'·óEc™/ÁåÒ›©iypw™»ãD)G‰!o¿0kÆÅ^ÜfÛ}™?¦2h Ò"ŠƒÜÎ1¾‹[Æ--,™±:Ï ÌFîá¦x…QMg&Ú–[Ï>óDq_fÅ^b %8úüÕÈà»·Ô‡pw›Ù髺ڞx-D—§W©4ø—·þ2ÞW#ÌêCãx(TýÁ 1>T•ô.ÚÐsTÑ'÷F‰c]c :£)ío$_‰X%hæ/ˆ¥ñp Y±èÑøÜÔEK²¥óÑ;p’ÒC¤l@§ƒ²ûE*<˜eV[8…Mì»–¹â¢b@…Rz•R1gds_Á6Ê òZ¨àiÓ.—ùŠmžõ5÷þû˜²¨IXסĢûˆÒž”|½½Ûç ‘5mÝ-Zlëà?ô³¬:SÄv½Áê5¶öÅjü—~>¾Ã—Ê'Çb|Êòeuc—_d{×;°ÍÛC–Ù!KÑÇõ_?û Ë]µÌçÁG¼qÒþ‘¬Ôÿã|j†æÓÙ3…îÔ£ËñŠ"̓ ä¡ÍŠÙñŠÙÑŠ`.&L¦ÉäW×IŒÕ í„'˜N¹~9y;ùÙÚÕÁé"˜éTáõtPà$Z=Ø 7X ´‰{¶ºreÛ¡xœyÝл8Œ¨#û' yHc‚sÏg5›¦&Fá|\b”0À®y6ŒLЄoÊ…ãÓõét¨=¯^H›¿Ç°"fMãDs•l\°¶>œœEC‡Uµø])Š×DâHþÝÿý…—u endstream endobj 177 0 obj <> stream xÚÕVMÛ6½÷W¨ l#7¡"R¤$g tAî) ®E{…•%W’?Ú ÿ½C‘²l‹Ò&F/Å.`Š3ó8óø8¤õ—…-þ°øw­ÅÚúyf½¾Ç:cß·fK0#ì‡5‹?ØIV#Ô^ó$‹ì]žÄÑhôqöîÜíó¼Véf¾*øæQ1ûÇé]íKB‡ÐSé·E%Úq÷Jöw]téÍ‹…öàgì4Mf'§•(η©Pež<¦ÊøVýÈ……à•PUEv™ü#ò%1yÅ£‘^®™æz:õ”`ñ|d‹¼¬"{ªÃóå²U‹ÛñXÊ$¦öNÁÚÞ†P;Í÷ǤŒ.Ì^ðMƒê~biySòõ&TpÓÔˆ:¹ùuÍóü‰§«ÿaå?€^†ÑØì{wнIZ‘t Ü h¹¹dò6¾;ª÷ÜÀVQ”Ý´êuô3jq™Ê!²“3 ¬г?éé)šd»ÆôòeOÀ.síÝî>$ïÌ{y,4Ëc¡˜¹ß@3Á®  ”ØtÜF#4‘œö—J¡T~¸C“|[颴é{mûíÏ÷ïÏ-ÚÀѤšgâPõR@Çöþ2äŽ}K1RPw¸:ü6F“š†ZVšÖ–WÊ×17Sd\ êM´üöͲ+@Œäï`ok•§A£F9gÜ«Itº+ûfWŽJï\_zNÀsûŒE*Úf<5î7ˆ[d*wxÝ×÷Ô’sîX^|˜9cé:Ì«~]Žç†ö'í tžx{ŽÀÊÒ±íŠX8¤q|¡“RýVBƶ8ÔjV¶ 5Š\LSí²,òõET¹}(Å¢JòLŠrQ$I¶2%LüÀ CÈå]dÈ{ŒŸjwЊ‡½zåšOJ}GRå9L·¹mµÙ‚><σ§Âˆößòƒ@[†ÓÚù“ü„./žTÜ#/Õ`Üê\Ïð,Ö”VÙ&T_WIÖDîE!š¾Íc£ UÌÛ£¨;wf³ öº'¸í¬ØÐXë8„IwÕ¶a4¡ÝfT#aÏÜŒà1y>J  2.ø6̶@reÄ\ µ)ïLï¿®Ïë¯åâ¡IØ“ »vÿ“õ`’o㬭~åþ±‹\¨9—kÚ&îC“ ‡Ú“‹\ág@ý¾ ñµ[Èúàìñk~?kÁP.~¿DéµGÐï߉`h'5ôHÜ!h2¾~›{ñô~&ð¨Ûù4T7˸qýý»›´ò¿ endstream endobj 181 0 obj <> stream xÚÝZëÛ¸ÿÞ¿ÂåvÍßTÒ¸ë]‚\ÓàÛâ€ì!ÐÚÚµ.¶åHr6[Üß©‡­“-Š"AL ‡äp?‡™½›ñY øÌ ø›Î–ÛÙ×W³ËgÜÎËŒ™]ÝB÷‚§ð1»Z½NvÕª˜/´P‰{2_ž¦É¾D‚Nþ4_pmu²àjþËÕwãqy½„îTe‰[ü9{B#> I§8RøÎž}“ooVy7«ïKOçìeÉ•EH?îÛ«°/3ãœeZ‡ËRë'Œ3£8Œ¾Ûìã¨w3&37»ŸéŒ9 sv¶‰¿ás3ûiöÃÄ‘©[d[î–UÓžLÎaSRö³s®˜<;}ÇÕÍ_›üƒš/¤UÉoø£“¦Ú¼ŸË4)ˆ ”[ü>l‰àåñœ×)×Õ\òäžzöuu³)¶Ôy_¶kjù5ò¶¬v~ +™!¸±h“E»®€7MV4¢º¥ß¯‹ºmŠ·sÓ¼¡5ò]à¹jŠÝ]#ùñÛ—_ý¼xñë¹_âò™¡ÕÓ w½PœñÙBh¦iÓ?=ìª}S6cC‹Ánw "Œ:Ž)w-9 ˜úM°ÊÒÞµ§ÝÕù~M,¿~AnÐû7õº9&æo6Õý)q™ï/¼d.%!$Óz,0ÁòÇC—uÞ¬qUÀA°èé2NIõòzþtJ™eÒ€$Žié%ù¦h–u¹ïlzùL µ§Y¦ˆ]yö«5ˆ¢OêêЖ»"Œ©Üpmˆ0ä?ÕñÔ*©eqx¢Ú­Z¤¹¶ù?zóÁ‹é»ÚЍmˆ¼[XïÝH ïÆy7tÝÓwônïÃÜ&$‡öý]ÒäØ8¾ÿ~.ù¹ìÜ–\{U¼ÇåŠMµ&h®¤>P;F„Ö!"DŒEÁ¢SJÿø<4ê»àæ€Ü,³¨@‰hãͪKpªØ¡Öa!f5ʘpÁºeóÈcGl¾è†wNíc]ÂX‚h y³,‹î;ÐâÌ6A+K©’Ûª¦®]Ñ’•àŸª~‹DA>PþÓ+ŸT2pJÚ뫪-h†v·±U†é£§zr]¼;”uÑÐW¾Ù(=ðÁÇ*oóÐ_寫$𖴭⮨ï½7‡bźê“Ït0{^ç°ÿ¢ž «™å! žODIÆ2ºýÖ`>”Ω$6¯Jt¨DÀQZº®€mK\ìC›ä×bÙá~].qÔš˜›=ísYb8a5R’‹‰0t@O8H BÍÀú])G¬xÉHÃå®ióÝ2ZïTËŠ1CXŸ´›eg´kXªƒú<†OhX –EjBäTKäˆ>kT@”MÑÕ;>üA·²YõúàÓN‰ÈDq4q€ý !³ e®_˜4U·Åê Æž› Ýóö"ݲL‹¡uŽ ¬Ã’ç`¨(r:Ôªè%¾ ¢Ç%Å {̰–SÛÁ³¢ã¸@ËE —&Ía¿ß<\®Š­ÇFa3Ø¢V>Òl ;¬QÉN‡:&vv>…ƒÈíþ—†Fïî‚ ¯ƒÔzä)°µîÄJÓ)s:¦\`yñêêÍß¾úybû*eit¹KÌ¢´b©šåÿμ›ÿÔ™Rɋ۩ùÀý;φÈÈâÀ$⪜:Ë!Þã‚éEˆò€É‘ó¦9lý™!{b!DŽ.˜ö­ìŒo¦xï[x›°.~Ùpè¨xÀéλ¢! YáÇCü8ÔôÙŒO §¼^ö`~Š4ÊiB„êiŠX‚Ô6 Ò!ͨ÷,Òdœ ui2fôiF ûK. H1.ñÒAŒv8Ë4Ä( Æ|b æe$ÅæÔ àb†nðëÄF,ò 1FÙˆ™pÝT]Òp€2XTÄdñÉ&þR²™…ÝëtZBhÙL8®Ñ$0†NLÊI]GÈ:Â#äõê.Hxä5êì8¼N/& 7ý™t ä„gŸ„=â£!‡¡> ¾Ð3 %²iˆä¥D€Ù;p)³æ4IÍphïu7Ä©Àƒk¾¢Ã8ƒ%dj‡y~ÝÒ/%jÐèóaïYtÀLÔœEÛ§«>±º…}|`#¤ÐÐ:N@’óXHÍÔ(9—€(È‚‡S€›þlp™ˆ©.O ÿ ý×ô}ã÷@Aß>eÅ_†»ñ¥;®ûIOš€ùó%8?häáz±§]Lhâb®[,d4øÕgÉÀ:Bì-C‰FæøP£ÝU'¤8Ø|=¥ZÍqÈÇÂëStk‡º*0cþƒ ÕØÿH}¡‡N”Kø(Üe‡ gÖ@JX}¤ ªt¯ÃX¶<iÍa„%”µz”B*âþ¶Q”¥ú^PPà´æ1”’,Ÿ€Re',l(±A(…}Ç9 ´M@)Ó£”Å»äç ”è’ðåT&kÅçFÈ%âFÒ$bÔâ°+["Ñ•[¤QÞs‡m%/JÈî.…ÉPÏ ÏÁ]ÊŒîRG¹ ö’šëÅ»”}ä.@£þŸïR£Ãû¯cÐú>R|úUj”'qD¯“RH š¡h[¬uAÝ7y'£U8G:5]6ëª.BDᓽ­ìs_¾ÏFElVÓ‹d¦z?6Ѱ8¼¬¶Ûb·ò•Å4V¥¯d“ų®Læº_uA”]áˆÎA²“FoèD†ÝoÓ••ý力.[v»à¿åå6V()…r}6´DÌšj3á"íbâ `RÏMOK¿/ŸÓg”óá© Ÿ±Äô¾M[Q5ž›žÃ—§µ/O—ïç>ð‹%ü¼Žå~R6ïñ9Õf“ o[µy(d_÷ð ¶sýX qŸFјGPôêï/_^Ä"W¨fmÍÆ·„áÖñ¾«à{=­ØÉë1¸‘ÎR¦¾C¶'ºïá˱œ§Xç÷"˜RÈdÑ F/EÄ«û×n˜U8?Rþç/¿ÿ+^çà”ßî!ðeÇAÞb)utËäi|Î…™J¡ ±„HG’ ¤œ>ÿB?-dÍ&NÎÓp…Í¢§¡.ïÊ·*ŸÍ±Vã0",cI/Zuð_¤uX&“ùç»ø49T@c—dÞ×eÛaêð”G$ qÝOø¦Ü–m]«É÷(£v÷êgèÕOÅW?ÏShà§7@tQÕ3Á'œ øº¼ o¢Øyƒ´jWí½"€ÿÛ%v½mÚ¢ ¼ñ—T ,û5˜ƒh/¼µ^}Œ]lä,£#na½%Ê4²þ𻦗© endstream endobj 184 0 obj <> stream xÚÕX[sÔ6~ï¯Ø†ikCVØò}B3JÈСBxÂT±µYƒ×ÞÚÚÍR¦ÿ½G:’/YBß:›ërnúΧsìÌþš¹3~î,¢ðç̲ÕìéÅìñsæ:$q’ÙÅbæ$ñgs¹Î.ò÷ÖÅ’ÛsšÄÖš5lÅoì?.~-—Ô"ÄØ–ìr§E††©C|_K´k0Y<+RÇõy+$«ðYâ×rnë® Œ#±”J™ßÚµÁÞ'mv*@7 ˆcüçõæªäAz ©**tÑ9fM†ƒœ †{We ƒØÊ¤û‡öÜsKÔ(v³,ÔúR9š{”’8h=ʃ²ìyžÕÔQTzÒŠºHôœAtqD|²˜B6IÉíP™9zÿ‡‰F„†³Nä=ê8|<¡\ŒƒZÆ~ƒóE½©rbÏ}ß·^,&ñu)qÃ=Œâ Ä®y2œë’À ïŒcóöb 16jmí °X¹ÑrE‹Ïªi$ tȯy3‡s„êÐÇÏ£A¾œ!²o¸Ø4U;‘Vƒ’G1­j?2Y~µÅŠ•:süƒZ;Aµ9¨K‹:>{ùúòôüÕëço§ ½ñt^ë²i­éRb©ÜpÖ²Jì…à[|W´¢½;ÚÇðìäâä®ÞUL9¢q„Õž­`ÐKK½×rIYR$E’Še”mZ#R¯ôhÝÔ`t…]²`¤2LcÐ*Ànƒ‹êŽÈÁ­#Uóý«.뎄¸£ Í&V]ó{óæäüìô>Ȩ _›{¬5æd÷˜>@xBU­r+yÎ} cëfŠÕênBBÄàtÇVëÉ.b.Þ¸‰ú¸Ð:0Id†®¡§âDG\š"-¥Îò·…±°*ªb%CÞ(ÅHW{ñÛ‰tðË[T†²‚j7].M­è£º‡¥ÖŸSÉõBcÓÜÕ :Mõ‚?)Sy·°D¶Ø@ EF¯+WrmÓbO‹=shW¹¦šŽ/}æUðº\_B4¨Ë†—lçOåÌŽh V`ðtÓ£¸ïJ6”À#£î®Ê”æ^u«eÉÔä¬É‘’p ¨ÚÈ¸Ó üäp£Y _¡)“IHÂDÙ}')7²Ô·ž´"Ïù‚,»KÚ}™ìKõ=Ëâê>’€ìÇuI‚·[|Zs ÅZÑl2!ÇõúL›e{„£ð±½”åêhè=øf«e}sˆ£Œ­Í ‡;ýl²±o6öÝŸè8VmRú®êœ§ÖV¶ ©”ƒÆùÃÔVK©=?–«0µ'°Z„ò•ZLtÀQÙ¾E6e±±¨Z[±¢ÿu‘O9þ¬Þ/|u/ ­—ÚÇ›ÆøÔÉK¹-oßiÁ­ïáÍѾu)­Þj”›ÐaVa’ÀÅD¶‡Ù„»6aè 7ƇtœAÉO¯¸Åß¼^˜Ü¤¶vg–Ù¥ò Çõ×TŽÔ:Óêõb'½ÝÃŽÆÒƒ4äúÄõ†ÆzÖ«ø’£]P“"Š¼Æªs‹*Rcò ¯ÄæŒó½Ø.ö`WËÿáÑýüˆs·—Ý·ø€KjO!‰„…÷ÇJ€ÊÁmHÈ:7‚ë4­úkpØÉM’R}ïaÅ)F†\í@¯>ÑËgóãjk¶=úB1Pg;²ŠÛ÷ÅGÓ9ÕaÈ6RÛΡ™i‡zë{½wþîåËñŽÞ`ócqYñÐá™8úç%è«óÐUžkDÿî_®ê+f endstream endobj 188 0 obj <> stream xÚ­XmoÛ6þ¾_! (*o'¾é¥ÝlhlÝ‚uÉ·yÈ[¶µÊ’*Éqº—ÿ¾;eK¶âf]Ñ "Çãñîáñ¡ww|øÇPÀŸïÌÖÎw×ÎW¯xèD,çzá(ÁdèxÜs=ÿÕýk»Û‰§…v¿¡Oâ¯Òdþ|òÛõWŒ‹þœªÎŠv1u?Oêê+÷ÉÜ;2F“咽èåsj‘r`:->?_ãÎ;ÏÎÈø¶k‚_õlê&Ó‰w~$Æ„öDÄ„ê[û‡ä¸Š$¹îÉý¾ê2¯næiž¶éͲNªÕÔ½èìôê´ÝÔ9áŸ^÷«WÊA™c ¸f1*ELK£ôýbâI?r·Êˆž¶dA+£b“¬«W¹UYÔåú`V³¹mÒY›•…˜6³:»ÍŠå˜Ã"YYG0˜5é|ž•M;âwÌY ¬:äTriV6ñT*`*É4å«Ü´Õ¦-)Ýu2¡û;ÂÍË Dß-ßbW¹yöS\”9ŒCÛ<3†_^Ÿ L®Ô,ˆÍB¿€Ó¸A@pÞ3Þ›d/òÒ–ª.oótM §Q0!ÄÖïûŒ=eŒƒè•µ¥Ü"m·eý–æ­’†1}Šbnñ^Ì©ÁÕî4dž…"³yVt3·iÚƒ›4ÍùfjómÊ|wn¹µ+¸<ž½+Ü;WG…@pßw¹<."À•N›ÇæpVøkzhMŒ:ôv{híÔVÁšü¾X“Þy4nMœ5=nM|ÄNÕ¨µNªöÎÃqçÔˆ5\Æã§ÍxÇ?Î;ñß@rʹàÁ´ªÇ$BY 9¹Sy ½óøF.5‡³â“Övõ8p8‡=k[¥§‚,g! “àV馽s˜Œ#gëè˜E gÀí;k', wýܹrÞŒ¬±ÓÚ­ux™âE…îoú¼†"º\'ÅÓ†ú 2‘ügJ¶ Õþ.@ °ÖI[Öö¾ {÷gךéÐ,yõ¾(«&k†¡€ñ®Cßg‚ÜFÄ–|žš¶á,4ôÅ…åH;å»›zÕ “›YRáÂ#nAyÿž•EcïŠÝ„*©×¿ò/¹þ­cKÛæ¾dÐìñž†GT†X<‚&]#Q"pk`p­‘@0?èq›Ícë@@XE¤Ih7ÁOè^üøókÜQ7†ù  \зí\A(Àg;AîPP}Z€ÖöP0æ)ÍË N4æ$¿E3ï-K•1:× ø‹š!3ÒÞfµ;X²7Dþ¹°zi‘‡&¦~hª |¦Hz?'Ú9ƒDð€…')¦ÈŸï[ra–X_f@)Ú´VÉ,k¡?'¡,ØØGcÀŒ²5FdƒG‡+—x+Õ%E׌L] "Ž´uR4ž –õn¬f•UkH:m§“3¢€fJE±†õ!¥gD#É;l4M¶,ÌLÈ0M³©l(Æã”±Dô'kx2Ôc  õkcH÷™ß7³ I9R74OT¨`”ñ¡ü+¸£¬)SG–“p¿} D Ä)}Kʹº„ú‹ ¥˜)ùÜê.HØš—’…Öè+3„Â`—Ÿ—ÀŘð°ëö‘ƒu%&€ì´é=öE(¹µo3ƒÉ·xê F¦LL%ÕõÑ»GÇ>µ&õkÍAò›MUåï-Öj’ÍÓõî€ßM´r“|“ŒJ|w½_Cÿî§‹ûÃ|‰î‘ûõØ™æLwðñÏÝ9B[ì°]”mows‹:GôÓÈÁEè‹ .ØÃÝ\ñc…+Y>Xyp Dòû¨3½Ò=‚êPJ£ò¨‹ãD]„õ}ºÁº†ybƒà†cGpS<ÞÃM…TÂ?ÜÌÚ8j/5ú5"’îixqçå^áà%‚×ÀŸÂT‡09@XŸEçÖ±'r ÙÁšÐõû Z:PÃÈ8"˜R¨ºrH(HWïa›ZCù àæðñ¤52ÚQ³“Øý–Ñ÷2©²´¶B{Œc÷;zÕnÚ?1ÖZ»—/¯/^^>³ÓÉ(ÜoPÜ×$[PAˆºKÐü¶ƒyR/Sj6³Äü ZCž‚«ïÉ\´gö¤ íB° Õ± %âáQ²#<‘!< jÈe´#—Ùkàþ”É2í\!Õ«Y–³”:·ö\‡Š(ˆ#®<á³Azú˜"ÂCá*2›‘¢S}óÙ¿ˆNr endstream endobj 191 0 obj <> stream xÚÅY]oÛ6}߯ÐÛl4ÖHŠúj¶—aÐ Ð5oM(2ã±EW¢›fØß½üåȱÝZÀ¢DÞ{.yÈ{.}ŽhDàrÿITo¢Ÿ¯¢~ã%qIÊèê.¢i\òh/²èjùqvu/æ‹$g³mÕU¡D7ÿtõ;Œ¢,–§1OÁ6ލnjÙ+Û+´1Ol§~;_°|&êæšP.zã£jͯ„—I/”mÝ™_e $3=d½Üû:{OÖìFZИsë)w·kqd£áÐÁqÕÕÆÙ²R•yº]KpYÌjtÿp/  µåEÂË8+a:“8MµÉÇûF÷¼‡Ž‰ )IfÜ©¦Õ >ë•ìô”Àßc«Ýˆn±ke^éyÖ#š»½Þ)|¹J%z|Œç Γٻ»©ÉaE—ùÔ R2šÛålj©£4N™ýN.Fr5™56²Vª Üel§Œœ«-â4 ¨cê*½ÈS¤dÀTÝLàcZ6]jÙÎa:UÕ´ÎRôu×lU#[óBŽç”ÏZ¡9öˆe÷`”æã­Y3d%ZÑUJ,ßNA]ä9NÔ‚æqQxÀɧ©9%<†'ÚÎX2Ûõb9iÙv§MÓOó͹~äA7ÅbÙ¬Ç ídߨæË\o-vWµK¹±ó‚ïwœ–[³ý:36pvLæ`¶ÛNÞž¬ÅÆ2lyØpG9ŽÁQRUkËìé ážR­93«'ááO/a{¿"ž^îºZ<æÛ×p ÖëݲiWf‚µïûûf»Ú°2ŒÆ]Ïω*¢jÚ‡W íý/1e~¿Á9|”9÷ „ëÃü ï¹ó¾('3ñÈ=ôj6‚ŽzH+w²óéä,ªBõõÕ×W‡Pú5Pýn{¯ ÷výtÖñJÐ)ÓY«NÙšGülÓsÒé Û훑Nm½c8y€“9œÍÓ˜VõÁäˆ ²úʦ)<à{±Êdwfèdò{Ám~㳕Ív힌™fê9+ ‘ÕÕö?Gæâà6Žd¬DÀEU7 µÈY(¹C‰gÈq˜ÏÎØCV¯† ä®]š¶ÝÖ|ð›ö9M=T8kN€º¿‚¯5! K-ð¬†ýK¨]×Nf[py¹û¶ä–rÈ“¶WU[ÛÖ#B¯zÓ§ßÕµèû»Ý,ýÙ+OÐßœ’ÁŠ+0¦´–ÅŒÚéY­·7 tÁÎØ ¾«:’ò·èä%xŠJpÙ=‚дš;W %qž„Ë·WZÑæëÌÞM²¥2Q‚Fè•=i.öJž „Jt˜?ÝQÔ.¨i‰®ó ëΨxb5I¸8J%NZEª«->/£Ï­’ ÑF‚g©ÕÛÐÌW"¸ÅRo²¨€ú KŠ2&friÄ„Æ$³Køf²L†'G†C’ ŒdÎÈO“F‚R0TÏ£b’qæJíËɘbîѡĚäqRz(À§bF¦œÑ ¾½œ°ø‚Òfr›Ða—Ìžßçí„Ø.Y\ÀiÇàè2‰‘!¥Hi(Å2Pб2¤~Û|]õ}³j76{à»b vÄ›쨼Uñy×tÂåóތч 6l»Oq¿;ãzÏ»má·¼ßÌa 7˜ìI>S^Äl4öFgù12e4‹YqúúÒ”gbz¶1ø‹ä $Α5vKÌ‘£(r@£Z›´:î W´ÈG„.p¶¶¢Ö© ›«®ÚÞ÷Öè g-+sCøªœ¯s63Dñƒ´=‘M¢÷fZÁ§ûÊ>X¹bóÍsÊt¢27f:Aä\/~°×rAÒ3Í ab«7¿æò\¶„G´¾·K‹ÃiOkøVY3âÑö› ä”’Ó]‹³¢4â ~EÛïô€gï½…SQ ë§g´ÇäIœî„¾U­vº@)ÉQ´&ÄÎÞm83м5×gð\ ¦‡X¡±©ð °]nƒËÔQ\+Xåô’º¯Ú½›²`Õ_¨ÔGnorï¯WæNšf¸UJô§Sp ZÊRÅ4.@òQ–¢ZqÃ>GpòÑc”–qÁÍRD›(Kâ"÷íuô!z?á#èeý*(4O ôLû”è{¼cÂnÖƒ¾åÒúÇüü±mªö{K5äñ²ê,¯ñþNØÇ9Ê}ÿä´AÈü)Qjý³5ºÿðÔÊ-ªñÄN«<¦td5óEâåZj¦Þ ÅÄ€W*Ê|Ñ·wæÙ¿4Zý ¨õëùå$>ãkP¿²'(.«´ØKJ7]Ξ Ý›·E‰5)qK…$þÒØ;$:èÎÞ¥2W’í+X…1Z^¼^ ålïByœ@3X­ÑÎ3ÚY¼Æ;Ö:x*û0쥟I]"»ž[©½÷Ç sc”›^i¼ÅíïïÍóçaZiox;>Fw÷ñÏ·ù.q]ß÷/6ì” endstream endobj 197 0 obj <> stream xÚXYoÛF~ï¯à[©6ZïÌÞíS‹¶F“¢§_Šºh‰¶‰ê*%'ÐßÙƒi• FD.çÛ¹¾Ýêß *Iÿ rH²Z¬«ooª«tRª›û ŒºšÇ[Ý,ÿªoÛÙ\)Uïš¾Y·‡¶Ÿý}óšP€#˜ÓÂÆÙ#b³ë·wEh<µB®ÈÜÖ ¡È˜‘ *aõ #Qsº½Ÿë2/é:Í3ñ„L#ogÙÍýn6G_·‹îV‚n÷yô£ ë¨oÕ®óh·ÙšÍ¢h3C[?­g„¾£9\Ýö"郷BcüF¢ª5ÔMß7÷óÔ(¡†hPø×Œè„SEd±%\}hÈ®8»¬—í~Ñw»CG_hëí}þ=dýXoÚCļÿmû^ѨõÑË8ð®[¶Ëlç]|ÿŸà~ûtè6­˜Í“”Óf^Ñ,YjÙ’!+§'$P”0&;1-†/šVB½‚=P®daß–P/¶ëu›´$J ¶qaÅB A{XíÞRhºóè'ÐAA Én$1WÚGêrûë‘"ÅLAýH~,Ènè{Ž‹eÕMù‘üih®üx—‰¹Úæ„åˆ<æ·$môòLÛ$¸oVÝæaÝl>"Jü]6ý2ÇûDÉç1^¿Ï̦t:²A`˜ú럷Éâe\D IÛ7ý"=[ÿB™_—gúþ¦ú·*øê}…TLB¬AFX[­+$5´š‡UõGõÛyåÒ´ž#ŠbI‹&­j*1s´ÎÖFJmR5¥,B€ÚÒmÒ/Ç܉Ð;2ÞСR´æŠCCȨÁíŒQTsP­™ò …ñÇúFâçœòB¤YJ²¸T#*²ÒNU6PXüUd;ç9£íÐ;YB¬htlˆÝP9U& SA98 ?©d(@¯¥qŠ55œÁ0šFŽ…F 9Ñ ƒ3Rs8ÑÁqDò˜"çãQ£–@_*ÆGƒF .8š†2ä³&F ñàYu‚òhñ$´çäQc£ÙÅ ŽK «š6&i,«Ñ3é € ”“Úxͦ#°”ƒèPƒã¸Š’K‡’G®ƒ’3¹Ê•Ó‚´VÅ?ެˆ‘´PBd=§S]DRÍóÞ9Ç!õE$8/©Žq5Íe¤¦Ø[Ì9A:øQùW*PÏwõânN»ãw›0Þ]ÖY*|l»AkØé~ƒ™ÒnÂL#‡tƒ÷iàâàÎÊTB¶š½?CƧIù–´Ïq[†3¤3'¤&$±“cŠ’ýT>¨`%ç§‚‹~‚Üd7…ýZU W¡”zÑÏȱà iY•ºá99PyªúN3kP™ÌA“­tê¸Ú¦9IG6ªÂ’õ2•±b,%ú ¥¢ÅAÏ)4FZéhÓeë› ‘ ££ž+©Z^D¢OÇgÎQ ‘q½+ô\p5^ÖI÷D¥ ·È´º¬ÓoùÒ¨õ‹ÈTTéä@;4/s5Œö £í‹Ðä'm³tPð uµ{ûÂ!4|ò!”ÎAzåÔèê¦vûO×RHýQ݃uh˜ŽAEuºgMT_&²·ÒÐÎÊUQ#/æ‰j/él9ì;i#¡@„8Ç}œO;ºHù4! ú3…&ÞM϶+„×A7€ue•ðîø>Ú¬&:FREÏCß-ã¥wNõ·þ/ÿıùªû'ÞYã¥Óå+¡’t%¤¡|%tã&Hµ›¶oÛž»½h„qIí6ÛݾÛOÃ1iï8¾šúõÙÔns˜ÍMŽÇÛb÷myivùÛׯòÃQúÝÛþqÿ|°y»hvÌàvx•l ;P£ /¶tçrúˆÍ˜¿àKÐßξæü¦‚)ü¤ãóݨßñÉ :Ï\ècŽÚCJϧ§³ÊñºØÅ«?…š<ÿõO¿¾ÉOïâu¼í÷¹#ûA÷ùÃa°åÈØÜÊ2ÏúGyðÄ:ò#½.Ûw ¾š—ŨQèIÀ·»Ü=+M‰¡ó{Î<ÖOûn“_úAͦ¿îJkî—~ÕmÄÀ²Üöüýº<ô…wP9\J€Ea(atË2ÓΞÐøpZƒ´bMyýwïãõ§*Jj\m©e}4dÕtò,k¨Z:l&KRÃJˆ.Êþ)È'튻Úwu¨_‹Rƒpfè©[•& ß÷ÛõÇ¢îNÎji…‡‰·÷‡ÝWWWËnÝ,J—i>HºÒýÓá¨*ÚåÓYvE4¼_mß_ýÝÇ¡÷ÄÈ«ñª%ó,î¨è OzKk,õû&šýãþaHRg¢(=ˆþöÙÿé}\‡ endstream endobj 201 0 obj <> stream xÚ½Yݓ۶ï_¡Gjj±ø"A&}j{܇tâÞ[.ã቎1E^HÊçëôï. A‰wÒÅNÇž£,°»Øö‹«ßV|Åà_iÿÙj{Xýífõ—·jÅYœ³|u³[ñ$ÎÕjƒéê¦ü9º¹7ëÌeôPtÅÁ ¦[ÿróOXÅE°LÃ2{ãŠwŽ`¶-‹™ŸïÖ¡#³­nW¦§í⣢}W<ÜÓX{·Þ$iô«ÙoÖŲhh‰èñ¾Ú®aK(‚Ŧ1]1˜ÒÉܵwµ9Ð\Y  ߸ö3þ1nƒ–f€¡È`5€Càq–ÁSÆIB¢mgÊdQ*ú±pµDÙ‹©¨mhÄ4¸ùÐ=á«—ONÊÉ™r4PõnmWôV ¬†{ÏÃ1ëÚãP5fÉ Ræ1÷Ǽ¯>Ú­>Ós£d`4î¨cRY±<†É ÏâDö—ì¯b™»­>ìîûvRÄ< 1Í0,Іž- ÊÞà¹8ÓÒ À€]R—ŽvGƒø“ƒÖ’ˆ\ëØŸMÙK2ê8ózTÍŒ¯DÀ¤`Á|Áwá3wukõ±˜üôÄ”=S ›&3…èÐ1™ÖšÞb­?1~|x¨ŸÖ:+Í¡hJúýy¨¨¨ÆbTFïwKG!4‹…^0gs{‰ÌýuéNó8ñðaoN!=¶›v´+êDž!nOQ§˜¸€ºt‚{ñq[<,YTÆL>ëy¢N±uömG³I"'Ôá(ÍÊ+P—©˜_D]ë$@ÝŒoÑméÁ çÎà¦x>ÁMiráßn–7ÎÂÙÛŠ´]g2z^\ çv9ƒ—¾/ñ¼fòSaòaŠÅzÁ¯iq1®©dÒ¤í‡eó©ç!†<¬cƒgàØ4Ÿ¤• 6›½ 1+uÆF!­gÓ|bLvÖ£KÓ “0–Çiþm0æ"A·96•söœ)&îfÔÊ#ÒžUÒ"ÇÇ—±˜¥q®—,8cö*$=õE'ó:C ½e]AH^P a“üÕÂ|"ʼnd çPTgÄ·{oO´1b¸®í>9ýZšô ‘]2fWß-Iº› ט5yyf¿,ˆœèX{­Æ{Ä´gic¢Ðf7æ—6ÔÚØrO’܉TMYm 0©ÅBNœHþÂQEuÕ|Ó“ª¥t ’ͪƒÄ®òù`ßë2¤<=ÒsÖlÆv6ÝcÕ›Wœ¸tB$íÁÁçxÀ¿(!f:ÆÆ8Éo£"¼³m_ Õ˜EÓY`Ökö¦»]¿BNy"^¶ÌʦlÌèõípi\¸ü˳zù‹Ð£+½g kx=Tû{Lü‚ÍÌz}m'AgJÊ H£ß—¦sÀx™Î¬{(>''.\ÆÂUùªsU—Îw$¹«r¸ÅÖÉW›¬oÝÖô¯à™~=O{o¯ç¨/qô…$°bo|B¾ïÌÅ{ª&6ÙEOÖE}÷^¡G~‰AYõCWÝ'åoÇ”B ë¿£Ò—ÓsM¸wmwp9š˜Í™/ÎW4îFT È+|üÅèQ·ã}ñÖ&Û·ÇÆÑ;_)ɃÚè(œô·k'?gl)CàYKÏô–‰d±ËáçÞz¦÷3wW$PƨsÕ/Æ7¨]î4 AG_ žê&+çzi˱Ÿüý’ù^傸øУl¿2ÿüÉ?¾|I}ùr5˦®Íµ8¼Ê€Êé4;?õàð¬|;Õ_¤…×àQÏ’Qkn“Q—n0ñk–S¾ç9fæï€‰rQ~@2=ÍÖ¾%hl=MõÇ-D±~w¬m =HT$eÓ./tîD*âD;ŒÌ°Ñ‚´igcþæt²ÛÿÇtí÷È2™’E'Bµóu[ËyGs^¯:ÄžÖ E7fxP`ôpcñø!'zóR¹7I‡[x/ÓlPP¢0]ç±±õYX¼`MZçïíáì%”£dÍn\_ûÃ;÷£ÛSg›ó•Æò ›a‘¼Q Gã>zZŒëöÏ6ÕV1×®f³U^εœyÓ[€Æ#¡§&sáFÁ´›ºÓ?X·°ê£ãåöÇàž¡Ó‘mR®£÷ãS–zS›2äÜ5·©Ü§ÆvrÒ!rµ˱~l°piöôN–ålžaû­{BT áÀí½±€éÊ‘Žœ\üØu¶ð€)SŒ–MNÏt¬Ú–³‰z슞åÝŽoØOžm#älì,·ô äA×õùû#\#W¹òÎ}uW4E4ŽÍ€ÞÑ8cÀ'ß)„ð-è'z»ÇêÃRÚäì\Ù /l³açlïªýi`¥[wæ © òU¥Áæ£r­O…wm‹¿&ôjB¯R³«€4ž¶pÏ][»È‰1=Myô¶êzû™'Í#ÇŠÊÇt±…3“G1Ýù”:.q*]-OIØàC…GŠ[ÆÄbòÇc}5±à´s$)üaŒ‘@ 5‹Þ®3m}òÕ™8ñÕæKqx¨­OgI”,h“üÒÀNu9ù7~…‘>Àƒµ²ÈóY)ŒïÖïÛ‰óÊ c…¥q´ô…ξ&VΔ0ˆ#ƒçB÷ ÷.NTý5Ü–€°8I¿ i| ‚Ãû}@˜±ùó\1dzþã›Êc™†Õ!?`ëÊ:åN|Õ0 Ñ@JRþZlÇÆÒ†N[ gOœ˜!&ÞbSßÞUl’/òlñN&þƒŒA>æ+'RQY0ت$i89}êÛ={(Sa°@¤Hçß§Œwñ4ÖÜ™MÙØÄc$¼}6ÉÒ32‹uE¹S‹ÍAG/ƒm)ó „›ú?¤6ðadBÆ´éÄØÍµ.ó›©OQt[XÐ<|Cqkš ¸Ï?vƒCXŠiwOiwyÜh71ûWl+‰þf’ JÛØàÌ”ÕÇòu!]‘˜.§úmË<[=¢ºI)«Z †ÆO°þ½^ý{õ“ËÓä "Îì6QK™ŒU>OÔˆ6YA”¦–n\Ž´:–a~¾õÓU6ráG*°žû´®$}ª‡©-¥“x–ÈåKÊ'}ºj_Q:¥¤o÷ô•ßÁÖ«0ñîÃû¼ûáÇx&î¬Q/2ë!RE¨L<éOúi|Œ† endstream endobj 204 0 obj <> stream xÚ­XMoã8 ½ï¯Ðm`¢Z¶åë;ØÝË`°¹íÌÁMÔÖ¨c§¶3Eÿý’¢d«Aâi1ÅÄ¢(òñQd̰&X ÿ+$ü¥l»glØÝWÍDÊË´d›Ø^ã"g›ÝÉýj-‹Ä®ÖJèäѶ¶¯F»ã«µV&ùûå*Ÿê4è%þȶì|,fYÕo½ÚkÝ4$C?†ü¨Ù7Ú’¸jFÛ·+À3Ö¿V–Lvuo·cݵDå­Oj½úãÞECB¾ú¹ù‡ ]òÜ0ˆ‘KåN~÷U”¬2¢ n“HC•;¯üM*Èê¼÷熽0®JÃ^™È ’­UÆuÁöL˜‚ë2¬ö/ûN9ˆ=ŠLr-Ø:Ï8& ÿHE±àwÚ~ï:¶²ŸÖZpab×qúE™r ”(€M®åJnf¤4¼Œ‘ÒpiÎ0Ã’JpYİÔggJªθò’§æJ¦¤ÒMSdbO‹ÅÉBòôúÓ™0)ÏÄÌ„JKn®eJ‘›w¸²3¸¢µÌùí|)‘ñ¬œ) ëåkí+½È¸Îv~ú ºPd"…4‰¨ê àåZÑÍèŠ3èÖJr•ÏIí°u\UFˆÖ—Q©¸ Ô¢Ýo >¿)uw|j@±µ+…>Sa.Q‘ÝL…ï@ŠÐ©p•é³ú¡RŸn†[-]‹Pê3å§sºÞÄ…ïzË\úÿÍןz^líbwI¹Ð1"=Ç…„2W7sáû^àB¥Ù.BûùàÕ813·µÅ¾¡¡U@½7õ/0‹o0ê–ïë<åÀ·€rCó"ëKÈ »'Èäg#“©ày„LJ ì²3-ÍÑzsG›»{díRCwÉN¨P ïT71¡áKFGLä9ö„åa©»†ÓŸž#EÈBM-æÈw„säOÏ}6²v¥½ÄTÐë t–Š ÚØ’²ñÊ 2¤ÔÓá¶sË]°ÕîHo²>tÇ~k}¦w¢€ÞiÕ‡³»õ§q BÑÞú‘©k݈<Ƈ®·4­¡Õ”½Â‹Š1âh'‹Üc(ŠŒäÉqù™°'î<ð4Œn¬ÃÇ…f‡ö÷‘$½­¶ˆçéÄ~o_Ž0Ç´_ð\ñÔˆ¼jN¼N>¦ÑÑ)xÀô="~£çc[C´ûæÍ…›R¤ÚEz¨žçº}]]&=$ Û#SÑ´4–$>Ôìâ•B6Ä G\Jbô㦠ÿÕÍö~¹ÿ{Ô•Äœ`dJé0 + è°@ø=ØæaíÇyÿHæçñ©Iéà@tµÏa}OàÙ;ó¦ê1¬êföâêâÇŠî‡Ð¥_P#"¥ëŸýLïï24Ý©^AÝ_GôìªL™PU¡hò7xÇªØÆnéçÏwÉm:P ƒ*Ÿ@!©¥œýMzµËù}ÕTí6¸ÄÌáçT$ç«ó]CxG- 9>4ƒç·†úÑuÊ&X£ øxHmWc_ß±èxh¬¿ÑrMo*ªßûp¬M´ endstream endobj 207 0 obj <> stream xÚíÛŽÛÆõ½_Á§€B­1çÊaÜ<8@·Eaà j´º~ µÚ]Úº¬E­×Î×眹qH %.´H Hq‡Ãs¿ÎœdŸ2šðÍJÿÙbýø6{~¡3**{{ ¯ç´ <_ý?g„Íæ”2‘¿®¿4ë/òûõlÎK‘_TnqáÁþ}·Û¾_-׳woÿ•ýý­…KUF)©¤t€EATåj@ËüÇz1ã4ÿx³ÛÞo® €ç"C*Š ¿¤’T"›3I¤6_¿½]ºmU´1@hpÇÉEREA-©øÌ€Ì™,òŽÔ&@U:—ùë—?_¼z3ceþ¿Ëp©‹¼iñ—åí¾Þ/¯ð™æuk¯·«ÕvÆTþÐ’Ù\ê2µÜÛWûÛåni¿|?›3/íúMóÁ/7zm·\5»åÁ#s*‘ür‚‚ÊnvõÝ-l• ˆ´z ve8Í_ðŸíî#nÙ¤EÌg!¨Û2ú” )„{ÿ¦ˆ* IªÝÆÿ×2jUeþ2•^¶³gT±üÁ&WpRð7I òxR€uŸ,óÖH¶×vý3*e¹Û7‹¥Ù)—ÍÖèájÙ:Zx^ãësògÞ®-Û‚p=Ðq?0íƒwfà¿sfMìÌð®Ù·v}QßÕ‹Æxå×´´*Rz.ïÝAšT%¾W„Aô3Ffä@IX™…-F¥ “†›ÍM‹öΫN§á‡AwBj°–" ôv{A”æ üÏ2A ç„QÇñ³ü,Å9SDzµµ ­i"è ­Éò¸GHïUw÷r¸‡Ð6›© ÅH)§rããÀ>iƒŒŸÃ&¥g5Âߣw 9@l®Â³Ëm ‰ª:"¿$m[㶆qHeaÏþòöͭž´–´ûŠÚø`ÖM(†ß½1Ix¤)ÃÔ·ÍWnm”b¥D©¶Þ7íõW›‘,0xhï¬.”„É˰j‘ÃsÀÆD|adEËÀb»i—»Ï3H €`‹L¥YÝïêfƒÏx3Å÷ÈjeºL‚L°ÂƒW¶i~YvÔ"WEÌÏ~»¯WqAed’ʇ–NVo#ÁŸ†å5`-¥Œ$®Qâöíõn»‹IT \3ÆWï¸`„)¼³Ö}*Ftù‹%(þi£*PêHZDPKÉcµ€ íÎÚÿ:^½NìêzYoZgRTc¦Upk?f/ë´ÂûåUI1H"Öå®ÙÜø¯L²…§V«»l«Íf±]‡1ë:DùÝê>é²Câ¿H†àÒÏlÙ\;d޳Æ! b _,íbj.s¢ç¢1E2Z#Ó÷­1ý¸„¥<_~º7²‚GލÇb¬©èË`¬–5þõÙJÂ|dˆ¤¼'Fó‹‘z1ÂÃö~³ ;1"žq1jÑ%ÄñÁˆÑ`u¿mAÑ¥Œ9¯FïHf‘X1 ™¿4•ˆìK½¾[-í&2rï§°`¢†‘÷Ú.ôDÇ™ÏæÏìÛÑ š•Pôð#.¬ •¡K×›Ò‡”Ï~C—*$aU”*h/»D1R_C ÕB*R(Äw‚Lv”L‘Y%0,¿Â'W£kømo­ì7Vø&º.šb70r˜F¡W-‘*0R°žÅÑ bg……Aðê¨-måOK¬è¶…®)zͺפÀ%eaÏk’¨^^zY×R•&yH:ò¤þy¿¤áð¦*µ5ARòŒa·ÐŸ|Ê ëì!£¥ÆþqN+¨ŽT¶Îh UXXeÿÉ~r‡ ‘àSa B~~Djϲ(¬"¤1¸cÄ U@*‹KÏN•à¦0Ü0Nñ¨bÝ-@¿ u„›°K ¢eIäJ„ÛRãî¹ôjVþNS6O({. :(þ5µêf‡’ÇN"HÇþuT4vËYr‰@x”‡‰V1RP+jBõ!TÁb ßµZ]ÍÎ1\¨Þ5ñö!Žê’“¦Ô±uè9´åþ¯ð»tÇÀœ#QŠp’^»#ŒSŒð kÖXubc_¶P²ho©¥ß‘ìw)¢ñcU9‘蓎+Æøt—s¨J+öÈL›ˆ´ÐAZ»¢bD/ ½À㧈Ìy`èS¤†¹§þÄâá÷)í rd϶RÊÑ£ÊAÊÕdr’„ŸæqÔ †2çÖ6¤1>"Vz޹O²°ßÛÜ'¹€8nîTRì*©)L§»J)…ÙS…A¿r‚¾¹¤)ÃBAôx„ö»ÎË8=(nÉÑ?ÇòN%±…ÄC#WH‚†¬ }FÛ~uŠ/›lö›#\½Ç ýP1ÞÃôÝkº¤Â|qΜ,=®F9˜ã'Úû”ÊêiKeH«ÀœÑ·o§íZ+—í¦FËe,ʸ\v ÇÊe·e¼êÀ æxÁÐÆO–¬ŽôD±È”»ƒíH®½»Sšh§­ò_˜×Üer¢Ô7³80iŒM8ˆÓ÷»#öü.ÁqÑc—‘Ê tYhÊ"=ïó“0ûjÄ`¨Ì-né:F9’LE²FÓk99Õ'kufR>a9’ü~àQBh6.bËA·Òy¯r…àñ áz‹sâ†7ÃÕæ©~åQ¡£œRÿir4ÊIU~ïx‹á7Â㩳Tx-Íy(ÈÞþÄŒá‰ÙØy¨pç¡üñç¡ön¹Ï®#*ÌŠ¤à0G àØÝ‹Úô½7§¸Ž¸M½¿ßÕ«ÕW»éz»³WnÖêv@7b«Ó«ÛWã÷†rH…2 äÝ ^%+i׉‡ãæ‹äե莀/sø5³¸‚åµ÷ïÍðƇåbïè÷×:LôÇ2¨ 5…uºŸÝrŽÞgìÃÁWû‘A¦×úaTxœ9¸Î£ë¾fÕà&•ÅqA‰ÁU~Ov{&{?uêtpã.{`P„-—EQ¤äEƒÓåy¡&OÉ+püaFóÍ!gµÇdÆÏ™:)²xHáXS™7©‹ÊY HJÍéƒ ;©iqj²®ü-\¥V>þŸž á&þ»2ì¯iæDw³ŠÎþ"9º„µÝ…ƒéQ¨pEÛ$/2ÂèÉ‹ŒÔ}ÍÚG!cŸ/’'÷¸©è•a}‘D\؈µZ%ïË(ÑrÀŽì³£OÔÐ##Oºû~s= òZ7U–š«y„}7nfç©D,ªÈA¿yåï“3=!qréÃ9«^Ï9ó¥X‘¦é&̘8uã÷eú ’wïc˜Øy#OÔ´Âa3gæ3¸)³Í䓌”±rªý¿Ñ( råµ)`“3„?j#Ûè/^¤ÈÁö`ªPªNç2=ÌT^ôo>}T_]58}a®òaÝŽÉìšú½¿Ã¾[™Ëü¯¡ÀqÅÈwÛþ=7ï^m»ŠÃÍŸ_àcT½Ülqæ§k¨­íÕ^v4 FxpEŸ²E+úÅ#lˆ.ÓwóGv¼6_ÙI37{ ûÐl«{3ŸÀX‡ËΩ8¹¤Fxô!Sç¬)@Ï\õ† š‘ê²4Õ¥M%›ZEj1¯ú%M–D®~²Ö'ê…=Üôú¦M„€Ês*Bù¤åM;ú@ô§KBStŸ™k±Q¶©2: +%a›ŽA7’!%LrÇ, ?aËaûÃ̌ãÚ3¸üí÷?ç[ûŸýÏö?¬?9 µol䑯æHvg!»ŸÙ,ü-ÏAÄÿ] Ôifh4*6¥õaÇZq¼õ©~ãÖG¶>÷Ùo|BþGµŒd?¤ ,ã~HöC¿E3$&4CâIš!1¡‡½½=4ýC5C•CâÿGB1¸WÛ†Ð`ox¸€ÿé/¿lÑ2ƒ endstream endobj 210 0 obj <> stream xÚÅXÝoÛ6ß_¡õ¡“‹Š‘Hê ݶõ-º]³§yÈYJÔÚ’+ÉuÒmÿûîxGI¶•¶À0 `’ºïûy¤óÞ þ'–ðï;ùÆùáÜ9{DNˆ4 ó¾{/ÒÈ9_ýæJ /dè^­·‹ßÏ_8OÎ÷ŽPiâì0‰6 qälœH‰$¶ÓµóÆy=£`$b%m‘­N$§¾Pr”œj¡ÂÏI‰Xò&»YúAØ,Tàµûþ„¤ÓŒ€¦Ú,”ïî6DÁ¾åضÍåºØõ*ë3U5ý>~þÓ÷Hýããƒ*!ÑV#ʦÝd½ùxö4vÐ:?Es=ˆÀñd(ÂØP¾¹­›mWu6䡜°±Ç‹Rᆥªû…Rv.Щ ð§\7û¥Y¹j³í5‰ƒ" =nZJõf%"‘§8I¾ '|Šmígã1¸2ƒ“Dœ€®5ù2â$eœÉ'‰E¢&8Iôˆ“‘bŠ˜ÌãÈ N=²uUýŽQ‰4ùw(éÿ” ÿ9F´/?s8EãécÚ7”¾º!¨"«ñÒ‹ª+zž•ô•¶jX0,ë­ÒWˆæü–ÅÎ:”Õ¯šbs6&"m¾ê#½Y›Ó€OøviÑŒÚßArt"šM,•Žé¤05Å·’cG|«ßì‚?uÒY°ì˜BÂÕ!„%J=ˆˆ49ðvÆÃûÁäNÆE@ ³¼¢ . rxóEø>:zšþë•DÕDôí\ߥdä¦ï0ÌD‘­- Õ! edn'ˆ†êȱD ÎrD5,…ÀÚbo1ëã¤ÿ2íò<Äez7Äqs%å±k$˜‘A0üfduœ¸`;NÃ×ÐïÐM!)]ˆp¹ª!A18°ÄjšŠìö¸ó¨ð`Ã3©4t‹Ú4Ô0¢®G” t;ÝÐäÙPA¦“Ä6)Wçr w"¨oLÙø£†¡Ó†qņd]·Û`¯elièwl-a‚ÍÔ 4d,Ï4éèƒ)ºÈ]ª@]qäÒ´9ƒÀøÂ?¸2­ŠA6ï#m¹ljßPAxѸ½'–‹™«”?…á/E¿këîK.P˜R¥mÝ+ØÐ)š;˜YÛcIdh ö!Iyö–»5’ís‘lÜjpÂ6˜ÉÇ¢m°Ì£ÔýÈÛ}ÕÌmüÕxkâ¡#ƒ2Ö]´mÓÒÒÔfWC,6À¬^ñŽ7h6GQí‘öÏÄìÉM†øá];v¨ðˆ‰µânÎãÛm±*J¼ââ®Úîò~ḣç†?!’|?{À—gÜhp@›<Ž`“ÏßñEùÌH í´ƒ!Ä©h>eè®mRX6o"lÿ›¬Î.ÐŒS"•Ó7¼éVõÒýÐT+†Ü¬w'ï æýÞì3ƒ}\€|ÍØÿŒ>~7>gä°'õ|{Y¢ÌßU‹¦\²CË…}kð•ú‡ï#ö=ä¾µï¾5°)KèF‡¸/ü¢±¨»×4 ~ÏÚãPU%IZŽæ}Íöùr2´Á- G³@øTš§P>lú,/Ò‰¡T‰%}ýÕ?°E¼ endstream endobj 215 0 obj <> stream xÚ­YKsÛ8¾ï¯P퉪Š` øÈœMÛy<¤#NàQ%Ï0f=vf×#håz!#Á³A„<Öþ aö|q ^ý¼ˆÈR/Ï[ëË*&¥óBc °‹Ã¢ÌaЮ'jã=iÕœ`€Á 1ƒ†äIhjÛ­Ö¦·äSðâ{ C#–Bú‹²ž1²¹âiá#3ÅïK’‹¤€óh) ż\¤¹ÝbhÁ–ÿ5ôC’¨ã¤>õË•g;8çÇ!ÍÈK·jÎ/óB’Ï|Ëv‘%Å8ûh9‹ÐÑM"¨£9j fLSÅ)Çy&;wõ\€fä5{P<žés¼òZ °nÓ:§Ûp,ñaÇtkjP*°çx”ú+ë‚ß5É­éir€™‡ÖˆÂ+øöUCKÈlÒÔmO&„ ‘¿þûÝûN3>A¬:µÏ©Y6Ó²œucÕ <Ùæû9˜NpKšÇØ]¡5ñv#wбÔrnÇÎ[pÄPw0³;¥s¼Uéý€Vvö$WÀ ¿ÒY6Q…EhÚ •˜K§Â_NTðLö(‚1ùdó(”PyÔĶéé×寙Ë_ à‚ž]uíØ¬‘z‚Ð8ð€þ† Þ¤äw‚xâFïgSríLLÄgí ¯*í´9£…¬¹f)ɽN¡ät€ð5F…8Ÿ&ènÄy\¸T'£T²èËR§’Ÿ,Ñjxx¡ë³œØà$+Œ¬4á2x$ð7¶¶;â`.#Gm÷§`ÿˆc5PЕ Ý½Äg®<ª´>QŠRÇJ(ᔂùë˜ÿÑD¨èž*%L[fÒ ÎϼꇎÖΩã(¤fo“,Q‹iœ(8›®$±¹ÇˆÛg”×kIÆ*^õšê1•ÑŠ<tp˜ìÛ§nÍ )ÁÁÊ=C`h`Í èr¸¸€ &Ù„N'qÂ:pJôÏ£¿ ÐßݨÝŸú(uÔ` I†í|˜ÙØî OžPþôÿ & „“dцÇõ;úýÏÏ×W?GQÙAò ‚´PÖõÍ¢EìïK3Ÿé§ålm9„¨œC¶ ýÁ»¡µ°ÏÁ$×gáO*xcøàª™9Z6Ö†«ŽÌ}êͧ4ô3ú; úØ4”¬‡¤<Ô,"¼Þaˆ”G"ãý¶–™%´¯Í¬Ø‰PÉ+°/ ‘ù©Ûïœ LM‰òœ_))’SÈž±;Ühb&s™s²dò;ÌUƒVi&…ÌÉ”`Íg0¯2ftøvÞþf€ —iw€aÊc4ÃÞÐ|g{Æ©õV¯_–EÍÂtRº‡óx7/ ¨’׺ ´Ïy», —‰É¢¤¼ðáHx•p‚ÒoœyðCvxnÉ"W"Üá´S¸ø“ñg•BV~IôÅÑNePÌ[Ñ©C€îì4ìcd6`¤üË™Æ%ÖEÂÆ›OWÔxwsK«Ë¯`ez+‹¬Ì_ÇJï^æû°RX™XYy„jø5)\f#\ªèòkm›ª'µ›#.wÑ\I%éXÁ¨~X®’,þ;'ŽoÓÝ’‹< fáE=Ì܇!{E£Í€X"òò¾§°ƒ]J³cgñIær°É“Ü)÷’Ï—Ï<ºP–n™cM-Ûl¦…§7ôX8´¥èŒÈ:n°ñ£AT3á<P5Í!²/G ø3臟ïpþŽèæÖmÇi\£fCå dÝŽ[8KЩKLAÉ©ÑUøíÓž-M5DÛòËøCÅI“<ª‚æîcDÆet ©:dâCr+R¯¯ÞL¾²®ç†Üª™²)?ýbõ«}i|p|”;uûL­ABì8œÛ¸âmÐW\Æ#3ˆsçU|^U‹g§‚"R.v‹¤È…úõâfñëLAvZº»Lëˆ@”‹âèû/ÑêQ¿ðÊÑ%8Ah¡Lƹ¸Ðv•©©G£€ˆÒl¨IÒ—ª°ÌkÆB/öïî(/‚¡U‡/t%—,È%ñ»pƒ=Ø«qhí7¼¬Û;¦BùÂþÁ±·ðz·Í£}˯{’hÔèXßNòèÅKÒT¸¾§!ÊΡq3S¥ëÿþ†Þ"ÏÛjx­'tEqÍþ龯‚õ 3CQ¾,5´ªš?Äùë_` |®d±ÄÈ€2l‡ýÛ‹‹Mµ3ë^tOŒPÂnž.ñû‹Ùü¡±ÓL;ÏOoÞ´ Z¸ØŸ¥äªô¤¿ýíSÉfÑ endstream endobj 218 0 obj <> stream xÚÅWKoÛF¾÷WðVªˆ6Ü_h{Hê&pРHãCºpiв™H¤B.á$èïÌÎP^J”ÕžŠYîò›Ù™oŸDðO©‚¿((·ÁË«àù+™™È“$¸ZÃ륌`\­þw‹e¬L¸->ãCæ´H³øóêÍZ5$-I¨? `­Öħ”¥ê´AS a¼> dUš5F瀠QFqÖŸ²ª˜5ªsÀŒÙI ™hTÉI`<¥GS;&ŒÏiLÙëÓ„'S`z˜1ð´×é4ùNÛ˜M€*úWYZ’lծݻŸ¯¸&’@J +æ¢P‰Z; %”€I —Ümv£Ø§@è< ‚8™! ©ƒmh‘¥ûý&x¼›¹ÃCñ=]m«#í¹yîiÏs©³Ú=k‡¢¾ŽdÜ.´ Kšðo\b¾×=¨Þ.t[‚°H4ŠìºövSm ½*lAOuCëÅåÛˆþé½óc§"3¤ÓpÝvÛ‚*ÿù«4À°D9¼4RH08qêï¿4í®¯ûi””'"S!³`©„'w2uc) L7έðh½i®ÝÑ]Wìî ñÝëgô°—éìáAqS»gÎ ©çVl(©Ú¦gPy_t|ź)¶Õõâû9w¥ÑÎz™‰˜tQõeWïlÝ6,`|gc‘‚Ó•W÷³L‡];غ©XfÂP"1G"‡?¢dî’HŠ8aîéK—N•R‚ÀJ8x ýc‚šžlK븭>[zy³aå.‹`½¸\RúÈ4‰ö‰†ô‚» ½–Z+Î&A™%Èè<ÜÄÁVÝEi"ò‘¢×³”ˆXñ{HF§Ð±aLr>áÙuØT–x€ÿÚîãõ_dHÀ¶$ÐÞBjÄᇪÄä2 Àïë%î ÝÃ'XeaUÖH Òbvt…éOýˆ÷è'Æ"Åà1ö­áÞMYQ¦½œÜÓ”‘H¦¤Ÿ¡,zÌ!çN껣µál‚kÚnU7ņ6 ûîß’TǨ5­,f¾º’U4­#lÅ.-3h5éqüŸìÿâSÝ|<ë‘¥(9ëQ4&¶k\3^iø^d¾[“ÌÃ+ ,Éu_YÞ­i%ëáÁ‰lVo1/¿0[s&Ê4éHëª OçŒLE:†Æu0kqÑ•ôÀ­žn7­»²Dî?B™i)½2sœj C¦8;8¾·”ÈhkäYíZålÅÀ“5Æ;­PXIØ­œfI…‚OÀAÃr.mæá°ãt´¿u»vhV´§ê ëð0iÁ¸ŸÁ@ü‹²¦ˆ\/t¡L†—ë•çlÀˆëA®¬øcŸˆÌï> stream xÚÅXmoÜ6þÞ_!¤@«-¼¬(’¢ti ´Í Z89ñn WÞÕÆªµÒF¢âæ.ýïrȵKÇMïÃÁ “"‡Ã™g^8dô&¢Q4’)ü’h½‹¾»Œ¾|F³ˆRR]na~IRdÑåæßqJRÂKJS¿nö‹_.Œž^Fo"Š<º‹DArnÈ,ÚE#¹tŸMô*ú)°ÁDd7Ù•¿¯*º£ñÝÉ”2’dÓ”J’mâQÙ]@ú%“"~ͺk,‰ß.XW½Òƒ\KRïôð¸Ã+Wr™ï}ß]7ÕY¨Ûó #ô—Ïd¤·ƒmA€¥“ DH#Á«wm·êÁ©ˆR§Þ"XBóh)IpÉÛ®Þ,–Ñ¿ñ¶MwwÕìWæ[Kƒ³_\œMd¯ûrcÇŸÛñºUØiË]5ž ¨3#$¥œžK0àF KÁãòj]îW‹ÇAÕ%’A›»eOªaÝ×{U글ûj Rp$g†üò¦hs÷ݨ궲kfXe”¤)x«¦ŸƒØ!ç„SK|=ÖÍf@þ`:ÓNvÍóxËÕâý*.V À…'à•7õz‘fñ&ÈÀwú¾ÀŸÒ<îZä•£;/…Âç±¥¨Ö5¸¯6F®%Á…ô1E¯K%zø#z h¯cÌIGÐ&XÜ‹ñ¾ìÁ¸ªêCpINÒÂ"p@¨ ©¨ŸrŒAÙ±Qe«EÒ‘BsNïy>Œ7fñoÕZY¶×„ýü`Y¿ìTå6+í"pÓV­†\õïpÇZY±Ö# oe1ˆáÜTǶžÖT¹‘@5Z1Á^` ì]­n°‡ºÂô<ŽfàE¾ËV…—Ku€£å–iš“LžØNñaÛe¤`–ÕóPü$D¤žñ4C£çIl³[Åm¥Ð¯à_×ß®z"×V².0VÆŠÚý3iÝ_Æ7H}ä×.SNëΙqgMï¹3F@ ·û›¼LQ·øÚº:q÷YnH€LŒ[HLÊ ÀÆR"sßçi©jD._ƒ“ ÷¶8X+¤©‡ÐŽ9%¹3Âóó‹«¾ mÉ “–è ¹)§ó<³×8TV¢áS‡Pw X R†¢³òYNÔš]Ž'‡ .̶žyZPˆ–Ke6¬4_‘`ôA9 õk”"Ei¤‘F:iÄ$ tÝ*”:&U@;>æ©",…Î…Dø}†hì‡m‘ø c<{°`“ž5ÀùÚÛžœž@Qö•íxª rN¨8uXÆÈÏ™KÀC0?³ÌMïT^üiєۦë7u[6Vˆ,ê»#Õö(ñ ÝØ¯« X±±1¸Ì)äÿ¦“ú¿èT··¥Q’=¨Qâ2±©€B1Ehî«5K•z‹RS~ƒl¨”ýÚb‹ÒCÇ,i6G³Ú-ßY´‚§¤>é`Ýt#Ä\HHIäá¼oQ¬ÃÆe¿ÆÎ¦T%ö®›ÎliÊ [,”zç‚Á”1¡ÏG/ôÜA\BNw²&~²©(-”!RÛF—x$Õ©_gr#çoE$I¡öt$Z°ÂåTYÄãÞ Ço,Dº±Ýà7ÖlÞT:³LhÀþåºF‹¬æ´ ö´øÌÑm¸\É}HË`ÂÓóÇ'ß_½øöç¿î8Ã#M·¶ËÆ©Ž8Ã’,`µ"#\~Ðjâ!«A{fûÚ’Ÿf´4Ì¢ ¾6p}!•>3¤KZ!c+OñµV+•NÙ†L,÷¯<ì30 ˆ`Žè«˜ž‰“s†:? ŽQT0“<“ßg‡”M5Îߌè1ß âÐ6)sÛõ˜E˦qGÞz ¡ x–¾·NÙôéïånL<ázŽCV©ìó1U¤¶öÀh\<ê±¾*õÅKw•ã0»Hé?ˆ9\k%ˆžÔiÃÜ“^|«i¾…D ÷NßE4ͶïvH¥cÒ*´t:,ôkÈØtT F3ò&…!áç¦ ‘.q¾]˜¼a 2æ4Ë%2›$£Phå)2Θ½©Zœ¿ëk…'«œXßíÝÛï/ΟþŒË6FšÑÈ´y`X¤ŒÇI“©,°·v¼µÏ!ógå¤È2[íñD†ÛZ·ëfÜTøLñÕ 6›jKn¾1Ëg[G”p£»õèR8ÆÓù›Çα•y“‹Ó »ÿê ¨Nž`ðî~)÷é_pŸ²> stream xÚXmoÛ6þ¾_!쓼Y¬Hе7 o.ÖuE›úÛ<Š­ÄjdÉ‘ä:öãwÇ£l:RS#$ïî¹{øTâÝ{Ü á‡{‰€ßÐ[m½sïÙŒ'žfi{ó˜xo¾þËÿ3{(¶Å¿ùäïù[/b w'ëëÏ?M%"ÿG|(ÿaáói´˜ÐÈ5 0bŠ€rÎRar|Ú_ÎW¥™×p”ñi–|GŒáÁû•ž¡ÉxÖS³6]pŒTcéÄTŽÁX5OáÊArª†rª‡N1OADˆè|«‹è5€eOMã1c2Ä­Ðaæ©bâA1ñ Â5ŽPêTøD2€H¦é0[<ÖšÓïSz¡Ç!ôQúˆt ùQ§µ_ÎÒ9;—›”/ê}µnG† úçÒê­BË ytI "¦—ÅÉ`xI ³Ç@}Y ŠK£a ˆÝ@õ•@G•½õ"N sT—W‘_IÕ—Å :L.‰‘?¿¨C= áø•÷ºZ›‰×s{ùƇI¥ìí+Ù» &˜šœCºÛrׇÝ{L¦Ú;x*e:¢¸Ñ·^,™NŽãÒûä}Áp¼,Î6{X„\ÕÉýÃ…sÉÂØá,onwaL·M¶ÛÇo¦ôrŒiºÇ†l¹ÊvÖ¸®÷À‰Í„NM\Ħa¥ÎëÉ–“}Y®öÝbòó<’¦5®™’&Ó«¼]5Å®+,¹Ïf‘Ë0¹îó ”&Rí7õ¾+ªÜÆœÑR Èý _EµªÛŽø C ‰ð2į¡®mVâ EqíM™¿«ÉÚõ‘ØDbĆ”ì(6 #±™Dj"à +-]–gÝëP“…¶: ¢HŸdÇz-Ñ'ùÕûÒÜZuÁgº‘4 B” Ä• ÆI\é)mÌCR›“'JcÆi!Þ×]ŽU YGõtPµ±õ«Cƒü~_4¹Êʲ³óGbp°ÎºÌf«Ér üòŽýb»ƒuÊIä6hÇF¢(é÷L‚GƒêEGCz:bçF2î´/ÿ:kó5m/òtRÞÔeY#‡‡¢º¥,È&¨Ó(¡¾ƒÏþ8ŽýwŒü¯Ø±³SŠyÛ0|K¤ŸÙ¯“Àv|úèyÅ0ejRˆ4ôOMØómJ§äb1+IÇ-=ßã¦BycyÍ];ýÖ4 íÎÆÌÏß¿¢Ü/ëf‡ÉûW9m¤ºéhò ïûàÃþóýí¾µs<áSsJ‰_n²ö ›ëwë¼ø„+´¢‘ùïèqð}7³œš #áï0 ¾ÈTÈÎTân!4îÏ ŽH#‘è]?~÷?W?*w endstream endobj 228 0 obj <> stream xÚX{oä¶ÿ¿Ÿb‘WmàeDêÝK\›ËáŠËõå²+KZ[9­¸‘(Û× ß½3R}v Eg†3¿yp7¿løÆ‡?¾Iüû›â¸ùóåæËï ÷Yæg›ËÆG, 7;\ˆ7—åÞåmµÝAàò.?Vªê¶?]þNqv, YŒÜñ„2s¶ ‹³ÝŸ¶;‘xUQï}V=r=eÅÈ®¬Û¼¡v+bo8nEê]Ó©ÎPh4ÇB¯¯ÛæŒÊÔ++¦õØ¥‚ñn”²(˜ÝÈ×7ËùQ9¿*ò“ãVgY:¿Vº¸ˆÈ[OÂbÐWÊ|h$ía¢4åÙî.üÑXË¥"O"–ÄF~)‡ë¦r)™°Äº¦nI­QpÞ4)s•Ó캑Zd¶ÿp‹œ{÷·uêÜ’Mƒ b¡£,Š4çB¶¸¯òºí] f­9˜}@dY‚»1pc1y¨þÙ !oFÔ+æ")÷†“±Gß9´%}+iF:à››Ã Ø>’¨û=mì'¦†Æ÷ÀýyQ+´ÈÇý–mwQŽê~–ŽÂ|ï¨aÛ£·“Ìì–5™©º!E}\Ð&b–ò¹ELjèòöÆLô/\@ˆÛðzûþòêûWÿv0ôLˆê'F ß\ü„Ïbô û_9¤qÎ" ;ÿ‚¤ÕÊŒ&èó¾ŽUiC9W.AÜç,ü$t§ ³`‚Î×Äã$ö ;£Lc’x½7¹C$>ãÑ:yðèÉä!,Ü{Ù8TB‹ÇSÀpä±×P:+rUËVGcF`†=ŠÊ¢>m…õNªnÍG¯dG<ã‰B(£Èû¹*T}‡,Ì­î¶°š7ƒùÜ“Wô‘º'ìí8Ü"ÉœPURÙÔ½+´s'.÷f,Øz‡¡R–D¶°H'>€Aø‰Ò`A£íýÖúB" ÃG" -O80µ$<ÞûÞ½»8+Lg–N‡9fÅ"œiÚBç7=}²:ª[²…Žý†Ö©2Y€yRõQ×ä.›Ë}iøþ‰Ô®‹s[8Ík C~9ŽÀ MZÂxq>Œ(½Âr“›wDÓT¥>ƒ®¤M­D=ÊdTi{Zó “§íB4Fm*L7dtdD =uò@O;Ç\wë+=žÚf4]ºLÌ]{Ú50–LGò¸  $³jý)²€Øø,ì²(a­—h-ša ÈËiè‡kzÁ\?x5^´r+핤U´jK 3Yëg¡ùRÁwŽy’„Z…ÁM*mM³)áÚݲ…Äôé\ ož(r$›U[œüŸmñ˜Mçî&÷9hxÖ!À 0-]ÿ½TÚr‰íá`F=.ˆ˜E">õäцrEïí‡x| á–«c„aÞÇ maa_–"™U†^÷_0Cyƒª å5\ïqɘ•èræG‰Ñµ£1òæõÍñ‚ÆR³'Ö´‹µvÆN_~—ÌœáÏ+Î?+5t­«2(’PÓµÓ4Ab+â߯ü,òÛTžPÚ!Pe 47ïþ~õúÛW—¯\­ôC›cw^J¨—±Wy§ÌÒ­Ùë+´<æù lxbûü,r04‰<šd`z¤Ó@¥ ™W¤pª¦8ÁE;œœÙ—¼_®”´¿Õ jù£~кü¡íÂ3ƒ×ùñäì- ÎÓ‰¼Êœ¡xÆD ý-¡°%B›ƦÖº*/ûÅ/$1ä߇úˆŽD´èÂà{´!R×-ø¤-*ûEã·o¿…'þò/:oÎÝ Ùtç£U_Ð{Iϰï ÞœÏÿdêàz}}Z»³ô˜œþ¨ûb ¨ÅèIZmä=Õ#ßæ'X›å*;†S“~Óœ®@ƒC#﯇¼¹qè’AÅHfT¡Ürî»ZUg²ÇØ¢ö®â'sÃÌÏ/iBæy}Ræ)p È>„¿×—ô(O࡙ű ÷ ÉXj¾Ÿ×mÑ ˜’#(B_õª,«»ýfÄûøKéš²–Ï$lêëçP‚]?Ìè oÌ(ƒ¨§ Ô"²^uC¡py¿Ò€}§ž@ÕzI³ßh¸»Â°9=‹¥y­×ütA³‡%÷|É}Røs`­[Hw-eµ÷î°:à¡=ü‘ZôýÅ~«—öÛÝ7¸ Ÿ[‡©æ!î½r?ò5Ç|Í1wqœt4F !&ëä˺t {ˆ¨ômN·Fƺ¶Hé8Ò#Ýiè5á±Ý÷/×Ü‘Z—RM‘;(FßÖ†OoFeÆ®RÿÎý±å`ü†6¿¦) AªŠn¹÷úú¿•> stream xÚWmÛFþÞ_¡"'ѬF£ÑKrg E›Eï’ôšnqÀ­Ò­lɶÙr%ízƒ6ÿýÈ!eK¶§Å.àßD>Cr¬ß-i¹ð'­Ðƒך¯­o®¬‹—2´"uµ°¼Hx¾åHÖUvmoëbÓ.ûA·G{Úþ'ý<ÌžÓ¢©Êá^&ÉæÁSÚØÓ=_2y>ywõ/p¢gaQÕÄØÅ@‘dLý“/éæ®;zò$™œªücíÚw} xw]¼#¤/¤qÃ7ÒØ3­n[6ÈG_óÙ›Ÿ_½žðAêLÛ›M~ßÝÓ÷üØÞ‹¬ò4;¸çæáþúaæLfïÈÛCл >Ì’I/à~ÁËYŽªOë9|w2q¦÷OIñ¦ÊòľCÒü–Sÿ ýÐÑŽº¤:'ØùHô“P<ÍØ²ÜÞdy™·ùͲN·«Ä¾ Àé¶Þîçí^¼ô-¤¹1[j#S$´2Lß/&Žr#ûWf†xô¸•B°ŒŒMºÞ–¹X§÷#ju(¼Žñ),úmW9.b;¿7ˆš¥mJ«Ä•~É,‹ºZI5·³&Ÿ·EµaÁ¼™×ŬØ,Çö‚PD;‚Á¬J7àó¢¬v#~ÇR>³C•TƲ‰§ïC¥„&¼ü·¥”½N'^hÀg—Õ¢oWïqëÛeñs:\T%œÃ~×<3Š¿»:­7˜Ü0îròœÆ4ç‹õíšrm>ì¶u5+s&S4 ƒ‰ ®~=$ì‘âC/Y`Ñᇆý·—¼¨—Œ(xˆ84Aà†hTìŠ@õv/Ž’,äõ„¯U_èù_0I­&åY“±Éßß5+áGC“Þ¨É@jH LxDÆ ¡Ÿ®aT­Ç0‚œÇP»º)7S”Šñ…s( FWÅÓ¤D4ÉÜ⤿@7Ò0‡>ôÁÄ¿ß÷{‹²@ â Ô!έwG—ŠXõa–Ð1ò¢ZS&Íû½ ;ºðð,xÍÇÄ÷/¾™ã¡µ&/èh^­alO±à¦%I!)­‹¦{TP…‹» j‹ ÀÉÐØd„S2•8/¶Í´ŒÄ¦À!ûž6pVøˆíŒ? îyßa,àQ õ½®†FöN<8^lÀá†N‡¾²Ø"Öto„†WR±˜Þ¢(™<%Î-r"=RŽô”èàq’hPú¨}2=¡2ÿ Úu…9‡Èã”*~ñ¿‚¯ó"¯ÁŸƒ$ùCµæ‹@ï›PšÏLÐòzù¨!§ßT1-1ÃíjýlâÄ2´_£ô¢t±áÛ :›¶XšCˆêx&þ—m3ÇȯêbÑRÐæÚ'2 'Ú‡1›üþ°eOJÎ ¤"‡—PW}€M)ÊII|š9ñÝ/ʉw.'Ô$×?Tfí#<‹eAáÐ.DÈ|L–Ó¡„¿o_¿Ä¾üî ûô@UÅrƒÄî>ÐújÁ<´6ïCØ~—mÞ®‚··³²˜§eÉ"\V¥iQ¦³’ý3¯Ô3«÷:öÝ@Drð©‹vûìâ"+Öéœ;½Óqõ^•·í‘g·àÙÜ`|@_ì'’悟¾H‚©i´öcî)èÀx·@ ²Ó/¥žapŸZ­ïw¬?~õÂo§ endstream endobj 240 0 obj <> stream xÚ­ÛnÛ6ô}_¡G­ñ¦Ë¶§ mÑa+Ð6{jŠB‘iG¨-¥”Ü4E?~‡<¤LÙlÒ‹ˆâ9<÷•|Jh’Ã&%ƒÿ–-…±3¢´CobjºÞ™r­ÆVw·¦®á†‰œ@XY5îÌÁAt>x5lU¯t3©õ¯1Q³²4ƒd"U5 ü.‘¹*Ž>ì0ªheÏ;(K˜¾_A»©e:ªùÜ÷xh¨¾ÃÙ|·FX:Vë«´Á-×»ÆÎ×Xçk Q@/Û*}µú ‘™¹yDÞ):Nªî«ú ܳ¸~„ÅZÝN7?AXxÂ-}„ò¾ë»}³[dðIÆü8[9³e±m¾üÛ2äJsF*i£Ö%æ5tBÜŒ3çðK“Kµp¹BBÚMMߺ·;õg<´­ÇÍa·»GðœN¶€æG*¾.ÆJ[Qæ5Þîn?@öˆ°”/?Ri§’ä«ÒÃoÀ"x–ú®•“ ÛøÎIÉC_œt.—'ss½Õ]Ðv=T¢±'…Sßiù *?¤’.ñú¡ÏŒ ø¦´´kØyÖŠD¼™‡ÎùsØï=§é„Î|v鯨7/ÜBoq¥0Úš:k nEø˜1Aj¤Cùñ´9¸ýîðË ó V÷ÀÉø)¶Òµ‰¡ÏͰƒkÐFÛçêôå„›fŒµ2–×ÄO]Ѽ'Ü ·j•ロ@bµY싲“/º"#tî­C.xù¦y•ç,JVì„B(­$¥oyNý«ôí€b5»Ý4l•‰[”ׄÆ,Ìpõ#Ãó²~6E\é©saÁĺ”—‘‚>¨2­@çÿ‘DÌÉ‚>߉ëJp¥¨9Â’eƸ{¨¦5êßà›ï7fÝíp“vNì ÌsX@–÷p±Ñ ˜wÝtƒ+8Üi\öªÛÞ_ àJ4"à ]ûözd× N•W+ã|pJ ëugÇÔLž ™(nU¤Ø¨gq+Óiðá•5;Ú-BEàu°µ©Â;`°Qxaõ {õeB:ÏÈ·—£@n:1zå‹èÂvo#yjbCÜ0ªóhÆÚxÖ®°(•r¾—šµ->¥têÀ•ž•ϘR¤;µ™èuU_b)‹ãiÓôè°­ÖOCsæöþe}¸uwZïÚE΃Ì5à$aÎc䑴ɬkÁ–VnâË>¶ˆE–%)aÔåð„n|¼ gºî‚å“ ÿžœ»÷›ÝÁ§ ‚[îYTáP3V0aê¡dÒ43 ­BŠfV‚ziÐižã»Ì=¾×˜O áu•Ü™¸/rj‚tŸÐ ÊËü¾KÞ&¯]1â O]VÈž€S™Z°œWWJ]v„(ˆ„ºR@ÖµË[„ƒëø­³÷'á¾fÝx´=–¶÷¨Å¹Ú8Ú"Ql’Âk (î®GZ¶3™’>vž‚ ¼ùç¹½xöjYk—ß+;ÁµÒ£¾þå?Ù”¢¦ endstream endobj 245 0 obj <> stream xÚÍZKÛF¾ï¯àa`vØïî rHÛØE‚Ý$sÉ–8'99žq°?~«úÁ‡¦¥™Ø›lX$»»X]¯¾j:û%£Y h¦ü-³õ!ûê*ûìɨ \¨ìê† Z ×›sFøª ”‰ü˾o¶í¡nW¼Ì‡UÁµÈïŽÝ»}}Xýtõ¯ìõ•EUF)±RY¢$ÊFY„:i2ÿªZ¯8ÍÞ»ûvã|öFdøâÒâJ*‰YÁ$‘Æ­þºv/åù°«µ¿|·*˜ÎÃͶy¿b*á–åUëƒøæX¯‡zÖ4wÕqh†¸êXÝíÂûi9S€qK¨…àËߦ4„ýð0þ<¿ÎS’¨"„‰ß… r>NIÇL °ÄÆñïaÇùç`D¥ó× ¥XI˜ s¯W¯@-Ãòg±„`Á‰`'šlQˆ0^nZš‰%Gå"(áQù*úmÓô·]Ó®Àyƒ[Sˆ? þ¦œ`äÀä¾z˜]²¼»Á_ž¿Çù5øn]‡‘ë¼íÀ &ßÔ½ßmiÏ)J¹$eÜÌë´4¦+K ¡D²K®, e£Œ2-c梤Ša¢Œ&l´òè]ÀE4I½ÙÖ=Y‚‹ ð°Ú÷_vÓÃSx“ ½wl#0-=h$ @®Á8Äçë®RJh3å÷:L`±Äj—dÀ¶€4áÞ)C¸}ŽSСˆ¸a¢]¸ˆ˜hÙC5¬wM»MÈа1–!ÿp¿A÷» µa?UvŒá„¿3lt†pØè.›`[~õ~_o*2ª‰Q#V!¡¥dXNÜ¿4-aQÒ7©tÄü†ŒM…H!¤Å wÁ ¼‡Ú¤ 6íêL9(ùµÒ”Û]5ø¹M|„À‡"\ò€ÿt³uarr# “¦ß¤K/‹&ëw´§Í¬»Ã¡ký#_pCýè0H‡…ZH‰aóÃXE%1^_!dÛ•ÚG¥™fÔ½ñ…ö÷qÈǫŜö.Rƒ\ª6¨»®Rqj ocøÝ­d ︩W’æk¤êR‚iM” k]ºÊüßïÐï›î¾ßX‘}*¯Â+TøŠu¨y\)Bå9+ œ¹\å|ÉZëϲÊÕTÞ¦!Q½ÃÕåR§íeÖ¢'ÒBŸ#-b·áM}]RѺP†Û¾;ÔÑ·`Á¦K')h-õe®ßô÷´ývž/γI‚Áâ’‚ ‘¾¯vu*ܱô)*Ü1ü&.½|§5¤Œ–ÞUh­Ç¼7.ïµNãPãZ ÃÁ?|¿’hWdfH$`÷?76>PÚúØþ),’³Eá}qjäüîÆ ê&9~ŠV\ïëÉúÒU:†§uà$¨u,¯¼d.žòÀí¡zlͯ1œün ‘úûÃ?bÉ^Ø0T—(¥þõšêzÅÉB‡ÄU…Bû´øsœ‰ÐíS!vÆãÞNËù ý™É–Då” hó,3ç™ µ–š“®sZMGð<)YuÔÓui>6ø"œ|uƒî,® W®±¯’DÔò‘û€?ï1 ­Èêf»h„BÖÁ%Þ “F0ww—3Ž1ØQ„‘îèÚ(ž77Qç}²™bØ4 ÄNO<0t•ôU47Dœ™'Ô;A]SOìÄ "z›`‰Û4mµo†~àÔ\ðhf.è÷Ÿ1/§özú2eÌ5×½¬»vº´õ3;»Óæe\7!Ü@à8c0ˆ=)æ´Íaäö ƒ–vʧõžåë9åÎaåK€K].ù pé9pñ9-rÀÕ´p‰Ü5t0ëž+¸< 5Š]±r^£¾l‘´y{¬wûÚß ­Â_'M€Kpö4'x´`™¶8ˆi ƒåõÄ ¨Îxp”òÕÕLx|:£7~ÕàÁ;’¯"M¡?©»m"MØu®.ÖÔ…ß7̓Rˆœ{‹Dq‹š]0N£ÂÊ)Œ·^(ŒOç’+/óÁ cÐâð£ðâ'þ¦­†û#€É ͺ·Ô¾_ƒÕÇ<Ñu“ö{¿Åó¦ùú?~×A_ßøŒÛá“ntY4Ç¿&O¤Yd¢~B¨Ü=Wgë'0Uþ|ýäŸT>Çê›®Ÿò¤3\`TTýŸJQÈmž«Â¬¤U˜Æ* <ÏWaJ¬÷nqˆŠD9àC—tt‚`AàaÁ/±¿Ëy—~ƒ}OšØÁdÞ’‰4Zg tUXkà ï9R`¦ƒ˜&ñb55QÏp%h¥žôP6™wqÈÁ´ ‚ºãt!þ\Wÿ?2RÛ Îæ)–%Om:N¹àk:ùš–eÍ/9;n>õbƒGÜÏ8›^:–jr5ùÏ´[¬-¢{™|÷xÖ1Ûñ“£²øúÏ#þ¢4ºhÚ@`R:JFÄòdYÿ9'ËÜL›oˆÓž2­ô zöë ¶”íÍŸm¡Îsh ˆuÕÖÎÏZÕPbôlÕõñüìg'MŒùlW~”íÌ ¿u°‹‡Ý³Ï_$l Û¡þSKâ'[ÿ5ø»·á⸠qg€/$~$,„qèë’VLËqå6û%#Üšì?øJ[âÜÁ}Nbãý>û>û6Hç€ôOVpÓð s4BçR¸Ÿ+aŠU*|H•ÊTéÚ䉶[`Ø]ÛǪ‰GVø Hù±yÄkÿÁ Ÿ!7Æ{O¶#Ûx–è=«úoHg7Ï&ÃÐÐ ©[ü¤Üð+ˆÍ7°Þ@¿º¹¯ýðÐùßé³Kp–˜¶ÂÈ䓞ÙÅÁt¾À$G Ù3 Ñ]…Ìoâ{æ&ãSI)zˆé4øóÄr1<Ò„³ÕÛÄjY臾£!}‹ï ]T…Gá°&\ÏÿëAßíïÑ7dËcƒZ(áÉŸPqê·ûŽjíœ endstream endobj 248 0 obj <> stream xÚÝ\YoG~ß_1û62³}YäÁœ`wýÄÎbhh‰’i”BÉÇþñ[ÕÇ\ì&‡"EÊ QS]]Ý]ÇWÕÝC¿´ ðšÁR\.‹ïßûÔ–ØâÍuA•©‰**Êk„«ßÊ“ÿ¾ù'²AÇÚjd’5³ÀR+î8häàÐbµq,û³Zîx^¾)~/jnMñ© †ÖDƒ[Ë‚1[ŸÅëâç–™qUÑa6¢6´ÏìÓ™C”È©›kæi Ý8òT¢Öªµt,¿: qVÐ:ôÙhNz™|”L ÚUƒ>†CI¼v@T)¢ã4‡uOrŽ’¹AìÛº¼¿NáWÈHÊÚ´6àÅžã{/›×‚]±Od£ˆ”°ZB0X^SÚgV˜¹5ùq9MŠS?ç“­ˆ…ª §1ñà™ÄM›SQ&kÂaHŽ5NÀ,‹ÀB×$-ûç 7̆¡üó&U[ˆJM°/Nä1˜è¤ýL_5*‡ÙSÓ§I› :F;‚1ß»K³¶f Ej"»¬¢&ªDDõœgȤºÈ9®{ß a¬At•Atž€tÔ6ót #K0Òãa½wÎgK†‘TlTSÈSœü¸ÝUª»þSu€³Ì“…€ŸjlmL2 ÏjK÷yžjk­[gy7à[Û݈…Ç!ÄâÐ:°F„ï°&^¢·B®qÛàVœ,³A†-T-€J @Ñ<–qƒ3ç U'Ræi#êÔ@ï>~ôó­hàâÂIìUµŽs@¨øˆ©\¢1jñ§èD›éÄ¢·rï*_:ÐP5Øð¥ƒ"U#C*ßCÂ8¹ûHÐ{ÌìyJp‰lsä—N2­2Ä9GQŸ—€ÁvVòüPÙˆY\åP (ÖÁö@È {Ãñ½Ç¾‰ð¹4C$pYF¦^òÂ3“…)ûhÎ$œšý8O1ÐËÜàܲ3qUÀ‘‰jH`3ìTa[,,âó8`nA7‹ñf¤(™¡0ÿs†§].djÈL8¿ãYǘ4‰aßßRõ3 Ž™Õø, öèñb3D•íÁûh âÜHR¨kq3ZaQíCQì‘qUk/hÃÅu…Ã.ªvTq€„±rýÙ/ýXYr nœÁŽUR¼2ÔÍftÄΗmç«a…"´R(}üµãõ¤b®ñK» a?Û"ÍCöÍ4ðÍ‘kàÛŽ8†Ø{ðìGuº1ž§Ï`(J –ž¨dKHí.•Ùì£Â…×Fƒ?ÌoêIÅ9/9| !Ë+ÿ<û<]Þ-fþáö?Eùð.¦÷÷ó›Õr¶š0]> •wëÛ·‹Ù²öJ¢Dâ pÅD¼dz=_ÎÓõâÃËo&•dÌ F”w“Š™r¶¾ž]>xJgU:Càƒ,/§+ÏùÖ÷õÔÕôáÃzº€Q\Ûõíz‰>,¦³+/ezïY›Á¯o‹[\ɧùêÆ“^ý–À.Ü·ô¤?º SøÖ5c4Q¡~9_Áÿ*º(o×þ·åô³£_LRÆ¥ !Ô“Š;ƒ?–3X^×ü]hfÝvêÞ¶„gîýþ?›R)Ü =¢ß–QR˃0Ìüïï7eX¼<óíÍb˜ìô$½/ʰ®‡*Z_&¿×ƒ÷"xjá}ürS‚pðÕøøü}ò}XLé ÏçM) ß”LHééÓ8i˜. ‡W\+|o¡â*¾ârÿ\PÊò½s^4ùÃmÒJ¤©!è63±Ýfjý8;ñ­fcÌdvêWlÑ/Á4<ßAkSÒ À!´f‹ä¥€Å}.é½^"»ß@ê/°r¤QÀ/©ÉI"ÑòªÕaM™îýRؼ†·#ÎfÏ#Æ]Ú¢|gÄ NgPý(ƒ¾OÔ 6î0h4Øë¤EUkN™i×­â,"8IŽ-¢r/KžÙRŠ9Žì 82«¾Î@"3NRµ!ñ$UìÞ0>•.“vä­)_“}|Õ#ƒëeR¾iÖ0ÑB«ÌçÙOïfëI?N[§ëùï}ò;¿Í}·RÞM±ø8ñe…ôXùÜO—á·ålºrõVFXS ±1,^L¾À‡€z,Tty‹õˆ—j%­ã'Òÿ,Â4)|õÓ¿üoÓ@ù°ºš¯!Í`-ƒÏoçwÓõÃüaæoÖÓ»wI«X(d‚Š~L­Ÿá[б€隌Q…Çp}ð”}%1Ø~K>∡Z±2øbÊWd Ùú"d\[ÎïýJ׳»õì>T‡NÐ8 }µJñ/ ®ŠO…ÚÅ¥T./ o ²†Ð}c°;ÿ¦Ÿæñ»°»ê=OX·˜L«X |ßóß®®*z‘TQ£ŸoP,NJ,ÇK˜(7=c1(2‡0gÅ6Ó“Ö´Óµ ¥i›v§««ä5ÅdåY^¤E(>XƒÌ,á:Ñ_¶ ™µMEUEY×s©*¿Å +Ó†Õ.Á;àYíª}ôŸûéNE·½Ù® àoó`¬’T”³Œ³5l½8xíìêQIæ– %¶•çZòÀñetªù*½GC€ÞŠž[^Þ®˜î<Ô¯®îCìƒçiÕ}Ø"ø¼½¾Ü–·¹lsÛŽZ÷¯É©óÖãß' JéŽtoF¦ûL@Ö×m„)áî0EZ÷×U–ÀÏܱA ä@8öSÄm$rvél›ë8¶ÖƒPfÐ&• ßp:²þü—ÿO‚ endstream endobj 251 0 obj <> stream xÚµXÝoÛ6ß_!ì¥rQ3¢H}-Ûú¶AlC›¼ÍC¦Êt¢Ö–\INš®ûßwÇ;Jr,/]€!Äãñ>~Ç»³÷Ñ“^ÒKBø¼bã=¿ðN^ÉØ“RdQä]¬`.‘ÅÞÅòw?J„³¹”aä_­·³?.~ö^^x=¡²Ô»õ¢L¤ÚHboãÅJ¤‰›®½sïÍÄ_Ò˜|yÀ9 „ Ι*zˆó@Äœó¶Ú6õ»Ù\%‘ÿ…>ö6;ÊÛ¶¼ª6¦š)éw¸¦}$_› ,ó.§QYÑ÷Åë_~œ©ÀÿéœÈWu³É;+üÉ«ÄÛƒ E™³,a$¢ÄÊr~WÕÛ¶l¦$~8:#!SoE" #eREdúK”û’ZØ•«&ß^ÁÓ³g4èÜ\¶¦»¿˜_uëV‹ºjy½¸Îf´ªòYÌN§tbe*"e|aÚ¢)·]YWL¯ÇúD"Ócò‹k3›‡Yà7õ®++ÃgöŒˆ‚A`éï«=q˜9•Lޤ-]雇 ú×zã„|Œ£USÛ5éóBg>u´°¤^3G„~-€)@Ś˘cA D#ÈCàv{ÚJ‚4yïL3eD ˜“zgSêÛíäJ|S”(­i‘»$Cà€Á‚C ˆ(òß›¡ dìw5íÜ^—êtM¢õ‡‡¨€ GŒ®s$¾™…©ÏÊ8Fpƒ[”~ÛÕYŠÙ\«ÄÿµîÈïó,#4õöê®!”æZ+w hh][VW4!´Ö$ .»¦é}¬uˆàž… .¦n±^Ý;ÆFÁ¡5JlB ©ÄºÞl×àŸõ6MÞš%íÝ–G–¨U@ iäq˜«DÄrsË•#úÐÍ) ‡‰£-Hða±€Ò ´Ô*†÷•YÙ'bâ6¥<«ÇP¥%¼#}kXTÈ„f+ú’ya`¬—÷vÑKwÌvJD ÚJ'#>]‡†R$²§ µû[oðÓ@ôÒÃvÞ­k ,‹ñÏBÖZT©M3rß8TÈÑ TïV˜hwK=EE÷,yj-„Äeµ,‹N|7ý(Dÿe&v ³Ó™¸o“³g;c;™ˆÜëðv UB97Ÿ2ªà…OÓ1ªäÿ&Ñù„D‰PòÎÁ+I2¶ÑëÕ$h`$'p½w?ð &ú~*aÉA¼àÙWùT >Ý7EUó¾{ýd)Ö/i ˆÚH舣>¶©Ðêx2€;òоCØÚÙŠ¾¤i¢†°ÝÛ}8l¥Ðšï_Ö;HIE•.Λ‚.s…Wx²*•CÈêLÄÙ8…<>dÍòŠ·GæÝGoªEâÞ¥‚)B(¦E–à>ìbÁ*bòlù~à!¬ŽDPF9‚èt¸mÏçûN‹g§°"…¿¼!˜[1òlɊȼ@ÃRGÌØ“±:ªjl½9„ÂìxÂLO—'¾å`G6ÇÀ7'©¨€ÃWÀÙs5}ûI©+Àå²·$ À³Ó˜M/÷\FŠúކ$‘Ê"ßTX’âˆj‘ `Ðî€aü‰&Nš ž¬Ô¹X\}žrr2dË'˜ÓúÂ-‹zq\² Pï6XÁXYjú[Ù’"Êæg#u°áÛðÊ R f¹§Ò¸äÃØÊŒRêÒô¼]Ê`¤-uE ì ÂGwߊÅl¢ Æ0|kº]SµÿÞ‚h—=àÙpoÖ„[Ò¼Émc×nñ ÉQ@€“Šä]íÖA®zD²áQÁ Ë`'ŸMScpÇ™ÿ7·ekø´ÕH¶¶^mI œï6McS ,màÚüª·%iÒ›2¯–ü¶õ7ÛÈ­ætûQ›Ññ—Ÿr¬kńѠM]š|nà1o}ú  WúMðµr™oˆ÷4M ¥ìÆuXÖ# ·ÞCgqØŸ!ÙÐmÀÄu ByØx‘¸#ËpSníAMŽrF—}^0ž>`éìÐ’µ 2X2ÔOÄ~ƒŸ@™•Å1ÛªP,ql·s·5K³Â¶SR³+º¾ƒèÀø ÀÃþÉSîê¹®Å1YG$‹Ü¿ŸX&a*B=f$„8äÞÿ.µÀéá¶;3?àö7I}s‰2ô'¡*ÏÂÇëf³ÿP,:®—ü3Gû(åòcʱմ¿ÉËjáßÔå’Ÿ¨Iõ~©9öPïŒfÒg´ùÃðƒPáÔqϸðÛò³©W öÉbÆ?ò¸åœ—Ý/;Ÿ{]È lëÔ^©SGú曀+h endstream endobj 256 0 obj <> stream xÚ•ZKsÛH¾ï¯ÐæDUEmöƒM2©=dâ$å}dfbßFSS´DIœ•H…¤ãø°ÿ}š™Š<W©ÙD£ðhföu&g!ü“³XÁ_8[f?ÝÍ®>Êx–ˆÔÚÙÝf¦¡Ìl!C˜˜Ý­ ê¼/"ÿ ŸíþøGgë?²¦<ÖÕý2øôšÞT›M“·Õf|ûcµOÃÜrþzþûÝ?gÒ©‡Ìû%Y¿Ä«ªqkÜúWMv8îsû½ZÎß:F‹gœŠ Q/{ÿ·Ë9‹^µ„ŽO8dá'ƒ3ˆÜ›ÿ¹ù«ñ ç —&"2Žàúæ?ïæZïoç ¨ kšb[ò'[šÃÃÚç|0Á¦ªYëØ~¸c«|ùăzËvK‰4vf ­P³…M…ŽÝŽ2êã:^bÊH¤ F*EB ÞírØ=V$®ŠI\x.ÊãCKÃe(͞ɊuÑãqŸ%ͼ»}3‡s nèU›­pÌV7-‘¯ª·ka}ÃG™Õ¡ }…ÜeڨH$ž¦ÚÐfMþ ùæu¶g9ðñé¢ÁlCsë¼YÕŽ7_“…µ1hõ…ÔÞ‚÷´f_Í• ¹É;à`¥‰FîDà·ÍëCQf-ðsÏE»£Q†'dà /׋j³è—®P´]Vg+XìøÛàc‘ï×ÌÒ-üæQ›~}Vó ÉÀ¥ÛúÞ©LÔìQ!)F¾»Ï³Í uP9^0¸ßgåqh‚昭Ð\ƘàC¿µV~k á³Û¢õÜzVW“kp^Œ$pôY[ÕDá‡äÅ:'‡(6ODÙîx/¿«Û’"“=ãN;å>W-RËd-ȹ-9·L¾>µóG´ß™àá×Å*㩯‹ÕŽV;‘aŸD–oóºéfXŒœèë¬Ü2õoìÍÑÐå“HÈ”Ýy†á„Ç'Â$L¡øõ"aìL{„ÒÒS„#èäÑÛÉM´ùá&ÑÄ&CM¤0è79£ Œ¬_ù;E¡‰R©¡³>îŠ=›ÿÓ¿ùûØ£2ÙûØWôs{u.¦ö‚¥¨ÊÚ¢Ü.Žn¾b ’ó•è.‡9¼`¨qòÉõÞW‡¾È9ધ¡ˆ¼ê¼Š÷V†á†6Ø„fôbGþ™• ̶ٽ;À¤¢¤ÜQT%Md¤jåžÙ£ÊwV®™ºö|¶eU{<$†èP%¶˜¸¶uvh´â¨SÁ’â¶S!Žƒ•ƒ?dGÜ C?N²ÔÓã.wÀ²‚II^ô©vqXdíjtl¼'­ƒL08¡hHž„¦ÎëÅ*krr1xq¨¡S¬ Ȉ« #G"ÖüZøÌLI|ÈEÆB&P`HýÄËeš»¦ùߌ~Hs®hœÖÏýrÁl{çü¥«5âÔ­šòË8‰b™ïØ.*¥§CŸ-ÂAᢻ„tIõa€Õ:3£¹ä8ÏäàBÏ%(`F^“°×èuÁã™>sŽ÷D^K ¬[VÎéÖœK|ÚÉê ¨8r>2>d]ò»á$¹ËzÙÁ̦òâ§0ß\6´…ªÅ‰vd«6% >ÿ|ýá–†®?Áð¹}ž›Õ¦IÓI7Æù‹n,ðd›§`Zâ–ôswÖÄèFî”ciäÜ4 ·àLF™”Îñ©÷ZYçÏj|áWRy¯¡O†¦”jEJ„–ÅÆ#ž(CÆLAåäöN;e9­€Á:ÜTÖYC¿ƒ Ö9.hØYWŽÍŠ!©Gô8ð&fÐ!"C>îBbE-Nwx†º+… ˜4#¯z®½–X8ùjtÞc:Õ¸2w3ÁC=¬qèÅ·yþ»Èé±×~óDqú2.Ä4ܺª †\h ³+½pU<,rQ› …»‰ÇŽ·‚ìsÜÑÜ2(„ì"É΋ȈP“nSQÀ.¡m¦ª#UŽÇ¿/S± „ñï1N°PRXO2uî±ÐþõrŽ™-JΙQcƒG¤çA+aÓgVŒC²¢í¬3”‡å‰abhE {nE i}Ÿ8m:   š•õÖ·YÞ2J„Œ‡æè€ÔÙñbaõ+8é@ÜDj€Ù“Å• M_]½sÅ}:p)|<ÁýTw NE—€`Ý8¥ú$¥šû ê?àƶJwÆ^°œç“Õdn¢sÛM;NJ¦_Í/\Ð`?—·“Ž Ûw(qÆÙî½.÷OóD¯9}ºÚQ{Ý1±‚õ´T_jpÐ]­Çߨ*¿$²‘xT/ .†Lc 6.c̬ývͨ 6?6€t¢o“|Ô 7ý“î¹½&Ú¾G>-$lWH¨&t±ïü†ª†›ë—— X€OV¾0ÿ‚’A é“ÇTjMñ~i¢d âÞµå±/pGúMéZ)ÅjœŒÍ€rS%áÙ¨¡øöL ”ÛQò8j¹là¥}&]%›äWõ÷ÃÌÏ­ä)b²?8DÖ§y–pL´lX’33ÙÇߤڪ¯ÕÎ%~•kFArÒ:(RÝyÌ6yzÃþÚΚ¡’PÉ •FŽkºFÞlüTÞ7~:,uhï)š`‚³ ½õ2w`ÜuB[ÀX3 .Ÿõ¡jž×ü!T“Hh*ú¹‡»ýòž×·w4xÿ3Œ^¾ØúU½tá‹Wå—ÃWʘÉðU“?Ý%dÝ­BÁ×þ7ãû6ÌŒ¬«¬]fù8Oõc¸¢‡ÑÁz¼»ŸÌ~‰ï­‹·ó…ƒÿ9åZÄ}µ…a‡'æür‚íÂ(Ð<…õÄõ$yz?Žïµ’ E¤¾\DF^¿?'D€¶—DÐ/Ë“x(6qn>…(VH¿úìœHìINÔÊîîÊß;·µŠ‘Òž"%L×–°ÄÅ¢Å~ÃM¶ù÷ÉCƒ¶§³L1U,÷9µ¦:ƪsêC?`}$\OÆçõÕ@}ªCTØ}^ÔÀ&ŒÎ¤|ÓÝiYw &´î@ð÷Ç"cÐXž¸Ñø†JöåÒ‚ n.Ë2¸%!dâ`|Ž‹˜²uŽ«3rf'éç\"‹býå<6]ìi;<¼àù]©ÙVëÓþxø¥?R޳#¼›F2iÒ>a^B2=è§ò¶„–^ŽòöwúN:eú´‡€ŸrŸJ ‰ŽJÛF®ã/âºÑ`HâG“Îá—üt߇#]‚kŠ’æ†qþÜéÞ­ªºÎ¹ï¬ÊµË¯ŽuÕoA}½“z`ßÁIww?¸WÔA³£òšë§ŠK®Å–Ì¢»«Ù¯3¡Ódöˆ­g ;Õ³ÃL&1~dåçýìvö+§y Ñ“Æ ¡1ü‚l KÊñ—X¢úéÜ*Eb »±‹ºcÕá<òºÀK|¢Ù4¸‡Ä¾¦¡‹E•ð‘ã…kÖ_¹âórI·j0õ±¨Ñq–Ž>¡£Ç/´tÕ•×¥‹o¿á»ý¶ª¡E90šÚŸ¬4àš¾¼Üæo¸œ"úæýM³Œƒë¡,p}CSº0¸¸-k^¹,­ð»OWH.1`Íñá~ŸçöOÌ Uù6`Tìù“_þ>ü© `Æɯvm{|suµ.ÙªõC‹˜&òõÃU§~s5ù¹}hlc#äñøKÀpÐÀ«Ö™Ô“þú·ÿYÞŠ endstream endobj 259 0 obj <> stream xÚ•”Koƒ0 Çïû9Ò,qÀqOi“v˜ÆmÚ!maE*ûøÖÂê† $'ñÏNü'˜|Fh÷0B÷R²)ÈmB®YH¢ VŠ$Yçöí&$Ù¾{›•/Ax.ê}è¦\}$ÏsäÌÒ•ìò¦Io´º46ýšI•Ûîì‚nšü³,Ò²5óúP­÷ia&[ÝjtÇÜæ¿z¹¹{3ã¬:º Nc$vðÚ¤éëbYh,À¢ºKÎP ŽzꑨGý­ÖzB4&ZT¢KìÖ$õb«¿DµJ2' –¤( Óœ œ$ØóFN’ÛÝÏH¨ÇOeH†ßyŒÀH1Ó.‘§*qå$­‰’rZ‘`NÒî.¨“t×.ç4¨ò#)_s$•UÉ]»ýÓ9®¼Z|çÃÙýŒQ2š’ÜM²_ þщӮÇö¾‡Äô{Az„Æ}¿ˆ)‰¯D4„H:¢¯W?kO_5 endstream endobj 262 0 obj <> stream xÚíXÝoÛ6ß_¡·ÉCÍJ%Jëö°­kÑÛÐ&oË)²â¨±%W’›¶è¿ûÒW¬Ø-†> (l€"y¼;Þýîx¤óÆñ~¾c5ü='Û:?Ÿ;Ÿù‘ãû* Cçüæ—¾§’È9_ýåj¨`±ô}ºëÍnñ÷ùoίçÎGIìÜ9a¢bC läl(P±íºçÌy9#` !wuÑæ¬£’d`$ÊÓ§XDÂ:mÊ]]]-–A˜¸¡‰<GŸiÓër›—‹Às[¦BúM¾åÎ*mS&-JnŸ¾øý'¤þå )b÷ºª·iKÚ?~fí%¨ËR”Ñ¡ -)sö¾¬vMÑt[eýõho•;Ë0T/)JÐ*dã_’â—²¥ Z×éî†)¾{þˆ?ú5o/›¼½?˜^fUÓfUÙÈxv“ÖÂèºL·ùÅâÉܦDC?Va@>Í›¬.vmQ•BoÆ UbÆäç7hz_»uµo‹2—5+¨ÀbÑì{Nˆ èqƒ2|·eaÁÈÏÚ’Ÿarð3h#~†¯¶’%ÒÍßµüuáùf#Ê %0KªÖ‰”Fó  ê0<MÏC'‘»Kk0y›×sæ°/¾ìîùÌöc;O¶ˆ_ËŒ­+ø u½-cH„‘û:Ï gÜ»›"íuè6;hc7Ï ÜwÞð²žï}ƒâ’Þ HP°Ò2ËyçËX£‡qœØºQA·uBóÌö­` ÓÖv¬u !ÊKUÁ`€Lh´ºæ¶í4¡%›ÕhÛ…ŽÜ÷È6rgÁŠ.{û—sjOE¶§¾$½E æ5àŒ':$&îÕ¦"[nÑMZÜDv:•ŒñM.IÁ°"Ð")Ü’Ù­¤Ë† ¨´*²´­êïçQê1ýGn„avVØ‚ÎÓ…½˜Ë›Ä*wç®W³h:k>‘ ‚œOrŽÿÅ4:›ÑÈ4ûÁ}8¿¸žÅ†7Dî¾ùˆß?Ìe7_…PÙœ0,[„Âq¿ÍWÜioR™N¹Ûº7)búmQ®R8MÌʬÚÊ(¬­³f*„ìíû€ "sܳÝ>ei¹:¥¨í%3èC°ûôp”¬+&?‹æèù ÌÈ|E€ž"Îvs˜Ï´ O¦ò N|Ï%4;ê0¡iQBCYCBÃQLYض*}BfÃOIhÖ-,Uí!§ŸP²uDp„àNf8wÌtI2‹údL½ðÁl6ã9qØ9. å­J,M+‹Õ ŠØGÅëYßj¨ ;’G÷RJ¾ZKºDg©ÅÒó@°ÇóæŒo§ÑŸu=uÄn;Åòê„ú,¢}¨¢ÿ›aà+ ó#ºÑræ5XÕˆ6›  ¡ €[{8‹øè‚É0@`Èw›¶ÆÈÍžþDªIçOƒeR³ Ì”ZO_t´Nîk¼`TãRB{ÅL¹ƒÕe›ËiGq˜Ÿ¶SV½îKß$Jë1ÄórŠ(HïŠö¿´Ûìauôއÿ™›Q}FZ˜óÕéLñ-@ÉR#ËN7”U4Üö¸BÜ;ö{ÇA8vuÞ4ùJøaÜ#Õ¨t$º´‘"p(ö©#)­ÆÒ¸³ ^'usºo+(œ±DËÆ[Û^Ztˆd~8¡Zu±˜¹µxc0þQµù§ßTB{ì¦yŸ{Sñ¸®8#NALYµ|£ä”˜C»·<'Gz(8RÝûŠG¥ÞÇO*ñC*ñ…oU×ÐÙ¼çnï–Ý­År9Ó[L-¥}ƒwBº áÕðª€ã­¥ës4Iƒ€mÅîù"†ØbòmzKe-“5ûZ¾xȉöCý­Gù¼©üÈ»+*iV«Ý}Ós’ù#ÞñxK¦wOV½=âžÄŧš½Ò„¹¾ÊÛ}ÝŸMGñDÂt—R¶Öi˰†±;4[Šˆ0Ø-Ëó×û žÆ Kûx¢Žè@y]aRŠ÷O ¯ïŠ&—Õt’Énç[T(Ùy]SZ‡¡-ˆM×]Î’ô¦ä² ‚oL׋rÉÒ'Ï÷ž–Œ‰•ï÷oKæôÛ’1pjùÃã’ôO¼.äd ÈUOÐÜ>3E*LFRð1μSb²^ÎðÖd ÝM ìÉ𩨗M3èLÌ4tA{ðeGÑso2¢ ¾4ÅŸ÷Òdਆóèà©i)ŸúÔôEŸŒ¬"ÇãD|*Ò1ÝH†”p¡4%§x]Ƶ݉3”ê2.ŒUfë™8RÑ‘wœDÙîħjÜx¾“ŒaÔr±lŠüÉ‘Éq8ÊÑØ•ýðûÓ×G˜¯0ÿÃG˜.«M|¬ctÁ22œC¿#}ùÍ¿æ¤UX endstream endobj 265 0 obj <> stream xÚíXQÛ6 ~߯ð£3$š%Ù–Ýn¶ÚîºÞÀÝpp_â.±SÛéõ†þø‘"å89¥9lëÓ†ªØ¢ÈOù‘rð>Aÿd`üEÁ|||ó4d$ò(.o`z†ip¹ø-|~3ùýò'j$¿2Ô„®»²wBÑHH+! }Ëc;RŠÄ)‰¦“™VIXõ8ÆaÕÑXtÝnS.è¡_<]ÐP7“™2ᢤÇU1Qiø¡ª—ø¬ì´UVÏ› ¿…µí¼;4RÕ4žØ‡Ê‘Æ ôÏF2¡Ý>yE½8Ô @5N£Ö™N2‘€÷µH«®ÙõˆĴvÈáWåFD®O"—Q&àA{ãAn„V<-xÚŒ¦gR&"–0.Mû/û][w¾ãLDE#Âø‰†~UÖEÑn?%ý˜7m[ÎûÇVk4Ö!ý:p¿ì€E5/ú¦¥Çæ†ç› «¶žÏÈó#ÇÙxÁUƒ'q;‘òƒý¿:[EïU±*XGS3g}Ó¸ "NSÄyö¦¾ÐÞä—ÝÛ8&OîM¡½AÀcŠO’4,Ö&™VáUX—ØhIIä4°ry5ñ Œ:Ç©ŠNtykñ4ýêþ kÎwt×½„¥¼úñ’xV¦H{9¦7mš‹,§pöH9àåzë–½„γà6H@2¦il‚T‹Ì ÏëàMðÚcc$ÅvŠ®Þ¶ÍÛ{ú%,’ÉÈ&¿ÌÏZ‹± @?Ó&¶Î5 ¤w=Ñœš–ƒ=ͳWËzSÚ)~‡¸Öå†Võ /.N1ZU‰H ñÛ]Ýl»ª;ô÷AÕ2Bf°ø5' U –rø5;æz½½²ÏÖKvöë‹)ýäošv3Ý/]¶ÅvŲώeëbSvÇ/mÕœZ¬ÈÒ™Ó>K“®çM×»ø=vJÇýCÙÍÛjÛWàí°ó%æ¤2:l!f+HwO™‡rd\}8ô¯ jqAÂowÕzÑ‘~8?;òáN1’ðvUÍ‘žV8©¨t[ʱÚ-íV–(çÕU$cì ðí>”€¨ÎdbŽœÊö)ýîÐ2·E çÕ™xbb¡\=½ðø Êu4–±@_ïÃþv뾨q×ï2³®±6‡¸‡tiø "khh$bmèá^Lf±ÎÃWM_:c/jjÙ)íY¬z†5ßËuXž‹8û ³§Q*³ˆj‰‡cH㢳m°ÜmåHqàùÏÄ”LcƒÊªº(é(¨"Ìòq‡2S*©¹v`ÿÜÙ¥îp0}=ÖT*×è-J ±ºdúÅ+>Ú“ƒÑ*‚×»uaÏ:©[5»5„ý¡ô|öȇ n&ßaSÏ^\\?yóêúåóW¤iºoI?‘UNö†loŠž0sAÂJ)“«É'²« 7PŪMõ§ÅÿØ ŽŒù°=ùõ c+>þml//†ÍÚÀ$ÙmèÅ-â*«åÊÆ½‹r/`I€ã« ç=8D³yz&6õþ>õÌ{ÃÈÓ¯ >âÄÜ„\{¬¶§ ½ñz3Š87OŽÉ´£eƒÞ«ZÂÂ%Q¡@Uw@gó’·ž)aº\ÙJéÙ>Ü$M6æUPŠwˆL†=)–@„I–âeÕ¾´·H©:ŸÅLbeˆ†hùÙ—`:>¼Ô¶ÞíDZ›µ9͈º;F˜ñiجÁ×V€6e%ÆÇš$ŸÑZ!óŽ/x€ÉP 0òfk›SèΉÖ-™s«$S>2¶hŒEcqh@­â e¸¥ãrdN¢ÈèélÊÈý¬Ðã÷}:0ðºXúX"Ý—ñqÿ޲‡øô©Gøt¸ÿN÷ Ûñ{üƒí?ûg|=%·– W€â#ª~pï }ßLŽ]ºÐìè¬Gé©„=×õ^jºN),í› »ÄÖ 7‹ÝÆÌÝÖÆ§¿6›TdƒûkBeï$Æ-ŽÂ·}ù‘&øªíÊšîs–þ˜Ò÷™=Ñ×™‹Ü×À4D¹ýÊ=ä{e¼¿W>ò·y'¾I]ú?¯èÓŸWr‘¨ÏrÞ|Ìm)ÜA²ì_8þD'>øÈÃvJêcÞþÿ“ßꓟíüçj˜œíYtšèžê#4³wÔ}BS&µ„†¶ö„†o‘²pì”Ðö³ÉCM‹ÈmwÑì ¬Y16œâ Ð"3œ»Gf z"³t 3P%'ÙÌsr1ä¡;¸9 ÀmÒˆÜØi¼ŠÏ$†¥ÅùÎ{¶* ‘饔‹åð½µ³wÇ8>‘ì™AÞôœía¶ggR]Sc·?Œå}ªkNuoDK¡ÿ¡cà—Þ;æ;> stream xÚV[oãD~çWDå‡mŒçâÛî‚´ì–jQ[ FÁq&·Žl§í.ìçÌÅñÄž¸%ÒÌøÜ¿9—ý5B#~häcø;£d3ú~6úæ„;tÂÑlä ?x£ÙòwëVïʼÿ1ûبƆ\;¤ÀØ.¬ïWã AŽU¯™Ü\MùЬmY,2¶‘×q%¿.Æì[ŒåòXí’„UÕj—e%çb—fõ9ß»Nd•Å®Ns¦üAXsûžíQpŸ;s—mçq•sÓólkp? ¶ë+æR)Ì~be¡¬`¶œá íÈ…xAÎRiÅ8#!V^ä.'O‘U1&·ÒoB‡üF4´±¯ù¬Yrßxop=ômÒðGc[qèW8ÁT`¡ÝÎÅS¼Ùf씋œ §}¸%#àÌ]oä_^`±¬Ã>òo /+I® qU¥wù.øjÉצ0¤yUÇyš_ëÝûë7\âí­Yå&®%Ϫ,6òJÇ÷79ˆ wi`ýiLÇöä*› 00qýöJ¾â—ìb+)DcyYóPi* õHÀ|]ÈUÔ¬‘…P4þ•Â8_JÑÇ2­Y¥×JCɪ]ÇØÈ­F™€ Ö·Ó«‹ß$~`;Xì!ãYØ$fƒ$¤/´)Vaƒt²Nó;ÛX>iБùw1“ù£z‡×4LlDã—ižd»%˜w1µ^WõrÉVöú;!~Ðs:œP÷Fvˆ_ýqË@‡d«êr—Ô|ïZË%ÍÕ¹bõ+¹û,—‡ù2®ãW}ÓÏ©\»EÆä>)ªŽÚøP-÷ µÊ  ¦yd=é2÷­ƒìoPkÛµTûõ¥T‰SŸó‰!Ù¦†€.%í[¹ˆîuZ3©:Uú‰«H!"RS ¦>Çês46èæÚxÑ7­*².•x±Zæ­Þóý=p \¢6"º²V$nE¨yïÕY[³gG“ž¦é±¥P\øˆ¬©²xy5¿¹½™__ï¿h”Ÿnž æAFÅß(Ö!’ñŽ;ºdkoðòè݈¶rÎͯWW –Z}ŸU¡LIä¦F69<¥RG¹ÝËÔϧ? |sk‚Îö?Z7Wý²’ŠÕ+"Ð8úr·ï°cæPªÚ-*–Ôi‘+AV%eº ³Æ x£rŒ¥bšê¨}½ðÆ)¥>ÇIëðF˜ˆíÿØÀålØÄ|¸ñ§ÁÌu>ß‹{IËÒ{>…˜$®ŠLÍýêåPï'~h“@Ø¸ŽŸÒ ´ÁNmËâÃKY/daG®O0-φN)Ž éT§CED£†]QoOÄçˆt¨NĦþüBº‰°ÎÙó õô`¬SQ—êî©ôœ¿¨ÄÓ©Ý#Ò ¤%ºçÈïR]êňn‡Hu"éœ]ˆ¨£S»×OdÑñë÷z£pOôå½u°!è!¡NmôLd^·Cÿv·øÀ5øg…1÷Ë9:Ì}cÞšS½S¯ÕÀC†=Ç=+ب÷ïË Ò3cHòNa *¤=…Ô„5º­—ÑŠ«¬¸=+®Ñm×hÆÂm ô¿ºÆ¯Þ@6v u0¯ŠVƒ’~OÒ×RdP4è‰ÆìÒkiPa8Å3¹€NŒ9'zí«g¸L‡­#“usΙ è4$6å6>µ„ÌýàÙ¶Ó"&ëd¸!œÒwš'‡þ¢Áðê„§ÑÄ£òÑá’†õç/þÖCŸT endstream endobj 272 0 obj <> stream xÚµWYoÜ6~ï¯ú$µ#ž’’öÁ9$M ÇñCn±P¼ò®`qZäÇw†Cía+ˆ! °aŠä|3g>ö>{Ü‹à‡{±€ßÈ»®¼çWÞ“3{ Kñ®n<Åbî…<‚¾wµúËo—\= B-”ÿ+6Úÿºðõ W‹€ºûQu0úÛïÔòàï«·óØ£žò¨‡5SXó8l<…§±!eBp–r‹Þ õª³s÷“‘ÛÑøå'\<‚Ó$0š LgáÄ —sb.pÞå¨êïù¬ˆ”ô$PÌÎ+ã÷…üc ™ Ôsj.p^ýõÜjè¹Â13ËÏÝÉ\¦Éw#œ€Â‚_Õ+;ñêÊÝÆã0©5^F1ÆL2„œƒ·u¹aŸ=&ÓÄ»ótÊEˆØx•g$Kâ]¿ô>z&bX¹8YWoÛæÓÿ@\à\3žþ0¡™ ÑÜFøY¹B+ÿ6ÚïšòK #?§Ñ¬ëŠu]åu ¹ßÓ+óŠìïŠ~C_ÍЇÍMx[”}ÞR¢cÅ"Êå(aˆÖ´€¨ìü“³ØÃ‚ P , Ê¢™Ž­ñÇêfÛÝqmĄnj'„RFTÊ¢î©ÔPœ¥Kâ²¹…¸‹ýÜMÓV'{³u›m7ÔýåµßÙ~Yvy0[^7Œ"1.Œ]¡V–Àª 9Î$ó!ôë"x6µ|®¤] OF_/óîº-¶}ÑÔ ¯YªÈ\Zó« ÄU*ò[(EQçs”1(¿ŒAÓhk¯Š—B)š  ÆGÀ"â Ÿ 6H¼ª¬ÄGÕ –¦íõ ™ôDˆ¨HĨ"œÜ© HE#Æj‡'SÉajŠ4Ùë‰"¡‡àåk÷Ñ®làqÈÒ˜–”2‰ªI8¤nöpD:ÐQ"„dQŒ( AÔyÓçH#ÒYO„ú èÕŽE Nþy(ÚÜMee9âÜü.ØYe}ææj?Aûζ€,¿Ï×y~ ´wC¾b.kl y("« )¥¿ÍÚ¬ÊǽyO°S weÆí1!aÐ%™¬r«\º¾Û×XÚ uß]PkÁðPf$)…ßmš¡\á·²ëJ|ÇoèòÕÓ)n°(:ôöRýîbyúñ|ùþÍùSc˜™~£¨[ŠÔÞä×=Å®²ž8õšlà­ ÿ7h’EpB¤`Uñ¯åÿl’›âvúçÿÌ-û:›Ûû‹Çq³1PoCEwÈ+/Ö›8÷ùj¤2A˜ax±÷ܪ:N™x…%1»þá &=8ãâ¹% ÚP'†‰øÞž%[½ÿ_ƒRáÚÑiÄ¢d\÷ôB(ª-l4w9Yâxsƒ­¡-‰õ½ÓƞݻÛËšâNÇáOY‡y° úž—›¦,LÕÍŒ5·å¶;î`øÏ-ÂÇhò’‘ƒ³ oíÊ]o[†_1¥î­ºEîŸ@/ªà–¾´­ CyXquM ”–þbqæ(u(jjÏó³bímwò3è^—§ç/ÉôEÓn™õ§üË|Kki{GŸáÅ%þé°ºžz<5 ‘/6ÙÈÆBúo¬‹Ý_t³X¼ÇÍW̃×Þ‹ýI‹Ä¥ gèqÿ‚ŽQË\*8òÐ=šq.C8¿Žst¶ Ø"pÂEzÑj4ýðÓª/í# endstream endobj 276 0 obj <> stream xÚµZmoÜÆþÞ_qýÆC|î¹lÚ¢jklű @ÔubÄ#’gÉE|gvvù"ïÝ). 8r_ggŸ™yf¨Åo ¾ˆá_¤þÇ‹õnñ÷‹Å·¯Ô‚Ç,‹³ÅÅÍ‚k–©Å ’ÅÅæçèâ¶X®D–D÷y›ïоh—¿\|³¸˜LK%3¸:ÎxíL—5¸u—­×ÓÂi´móû[·GÛÀÛŽÚ›ëåJ'ѯź±\ÉXE·åz)ÒÈŽÖQw¿&*ÖåeÌUÑÑ´aݼëÊm½+jœÒÓØàº*ÜeÝõy½.˜xeKS8ºaZŽG—<;qtŤ?ú§«®èÇ—‚Ác¥N§RKGyM[5Ð(qÛÚÜÐoï%±SªÍ¤û¥H¢Ï¸l!yš03è¿I(b–¤Ã·®Ý6ú„,Ú¾x¤ŽMÞçôt]5öìµÜá5 1¹&«WÇ2ЫdZÛõ× ]I3¤p;IÕ´ÜÆ½’"¤‘6å:ï›öOvMÒáªbÿúqË)Z.uË) =ì·tË;uÅSuÅÓþº>Ñ,½6¿£3rž2c¦ñÿ›D¥#š¹| ç77AlÄ£åNá;ÛñëÑñçÀöœ3í‰- tTZ »#Â/˜ã~Wl西Í]wN?S½ÀëmŽ˜þTÖ[‚vÛÅêu³s­0·]wóM¬á÷À9À°D¿YNwŒ¼Þœ4µ&ÐkÐûô;ß64 îÙIŽ7?C€:ŒÃàé(ÄYÆÔ—þLi~Ÿ¥Œûò«uÓZÆDvСáèД‡fßn¨·'QÄèа•z:´”ZzÀ¡™ÉEmš=øôB–õ“áèœö=uft‘IÌb3½ÉI‚ι7 ÜćÄÛÆÚ ƒY–b·bWaiåü5x·"] C˜‰q.%áQ±ÙÚ'áe1šp†‹[ ,hü´Ô€âjïFïPØ}דð×AidI)¶ Ûk1™ˆq«6¯ý^?‡îE@ I¥;ìêÍùÅÕ»³¤43b°³ÀB j‡ú¿yÞ2¿8Ô«„Slîë ßËxæsÇg~×C3îçŽ}ôz6 䌛3õ ˆÈÃ'Àú0æ/h;Æ¡›¦uÒT‰‡˜é|¤„›,@|ôIâ#ü]wMu€TÌhÏŒ¬á–F$‘7¼¼/›ú…c õ‘¹%ÖܸòT(‰Zð¨eí^: ´f2ްR[Y~ZZrd7Z¼^úhSÊî…è1Kg¬eà(}Óç="l.—¤Ò›f_oÀú”R‡ $AžÔØ€è²;„[oç?½}ZDŒÐ~1ãrJªK¢uÄÀ@'Êë^=|ëÆáÙ*x㣠F_ ÆœBŒf©lî1$:g2;Œ£‰(›dJ”ñí†~éœð0å¡W?ƒ(CèãDy"¡õ¸®ßÕ|p ž(¨¤‘ŰeÈ™!lÃÄÛŽ)§˜'„@7¢Y"¡=àILÊ”—ÿñKO’0¡Ny6ÉèHŽÚ <½Ï9ãšú3Šá†à§f–:áJ•r†Êo_¥“u£‚âö€ÑE¿o‡="^¬@Ná2 ìO½L?Ü÷åΛ;Øì=”÷ªÖàzY¡¿†%müúíû«—ç?¼äm~§ó†–½„$·$¿ÛyW"Á!;œ‰P<–]ß—AŒ2üóìâì˜?Õ¹ÝH@ìGˆ ù"·½k²™5¶t¤@/ÛÊÓˆu¾ïÜ76þ2 ‡¶1 ‡‘d*vhë&%Lo©Û‚»²‚ÇSã¸tHÀ⊶Ї¾inhÝcìZ‚ˆÈ)ñÙ §G« æÌ…³­î¯Ö·Åúî*ïj”> Å,³ÂË%*HšEªªF;·Üj¨N,ª7$ .1E ? ’Œ%³äáÆyä_Ͼîgç¯_»ï‹Û!ÏöJø€Âæ.9¿o‹]¦STŸ]0)ZÈÁòžh Ý~:Ü>¶xyçŒÃÍ–––\´nðñáÙFôêìÍÛc:C»PÆ£Aª ´ŽÚF 7dDŽ*]+ù[h*QØZ5Ûrž0ãº77~¬õG0x=É q1·ckŽß‚H4Få6ûöK@vAº£ê”‹à÷ø§Þ¶ Ü¨i]tî› „“„éÀ^ï·+ÀñÝß¶õž5íö¯A)Ç,“ 8V©8–ŠV<óbÿ£Ù¡}K0¬wk(ù6YXêx >öWÍÍꮬ;@²‘mÓ‚'ØÑÔ*þn t(¨U„n [1Þ×zΩ 0J®Û,Á·Íë²]ï+Ï4ulF!ޏƒ•?…ô§@Ÿà¼ÁUsÂõ)˜=%Šý=Gºr¥’.³Ü‚UUÔ슢Øa¿9ýÔ…Mp™¦½£áݾìÉwã 5;ÕBÔNž(S¦”K::Q:’tÆ›¦ª¬¹>¸ª…u )ˆ¦:ÜË WQþðÚ=´[ª)ó éH…@#$3)ÕÆÒq6NܬC+€°¤B4Ç€‹Ø 9 XA•¯m½Z‹Üg J —ã¨Ë(˜q ÍžýÝr àÄ¡ ”lp.~ÿkË"iª"ÜFeÌñÒõëYµi O J Jðl.$fœO#ŽJyä¼*$”Ï‚:óCyªÁî:ŒéoÁj¶·¤šIi_­ïŇmCzr¢‚2é3’)ýÌ“ÒÙÝŽá¹úò$Yì©“ptvÃÈ™¥Ž£ØªRíë²ww-Ó$Úß»„ýxšº°gå†wsif¬Íîƒ*×_'(ͽ®dÖ®¬è¶‰ÊûÍ!CˆÕÿVžñ¤Å»¤h ;®)bÁSÌ´d™·.Œïgϯ޽9l‘È)ÎíŠmÀ Ðª‡‘qS$¦ÌÑóž´ðJ1KÑYrL´'gÆ’€‹ÒòЙŸÿpæ`u \ßP«Îq<­·q&øÓÅÞ½?®@ÿÉrE9Kâ…O9 *ÔórV¾Ù¸Ü«ñIh¾,«2o?»òGQl®s*R´¿å„òÂÁsÝ…¤e±˜`Çb*­´Ò* @VñI<Å·£Âp1ùrÔ #êáSÉ‘Ï à3Zå(&Ÿ¤ôHHÁÐ<Õ+ttàv*÷LåŹ£™|¢Õé)²!ä…£…,Cåt–Îò©ä©h_Ž6©q"£ó*ìrèCÕ{eL0Õç‘ïoL¬#¬ŠÎ½…5˜Å,Ö§ái%>‡à°5×Yps÷M ¥ð‰®•ì#ÑZÑS#?&-W|Äe8ê¯7Œ~<Œ©'{%¿C5©8çÄKñ²¬EM„½¨ˆ˜>/rÆÍq/ºRìwVw;á™å”f™Íàñ—<8ÂOO Of¦„ÇÉý[¦°¯÷>žcžÏ¾‡Q!1–ܾ–Iä,S¡µÂú\h?3V›¿–ß·³˜Pô ë0êbb%Á|M¼ÆçÅDHH~[€71‹LÌ5¬™Ën¡R ïÕâãâG—åHààBÙ’yƒcRôjó,‡ÆjûW0 eæLƒÏJbŽäkü6+ e‰³Ä .¾³¥>l÷‰B{ êÙïJ¶ÏNÄÂÆ ›ðÕ®sÓÐ 7ßV¤ìFÖGÒ½ƒ‰h6MD‡šˆ…Rû!Þç]çò)ë˜^ÒÇ?+rÁÍT4ÿˆaðW‰"G¡µúãþ ýXù endstream endobj 279 0 obj <> stream xÚX{oÛ6ÿŸÂMÑU^#ޤ¨‡›6@¶uA‡¶èÖ P©lѶYò$Ùq;ô»ïÈ£d)bÒtH>îx÷»'þ±…?6 9üÓÑ|=úébôã¯bÄ(™ÐÉèb1b>™ˆ‘«6‚ÑEòÞÓñØõêTé:Íâ2û4ޏs¬öBgQ”jÂÏÇÔŸðΔðu˜Â¯…É#T_°° “2‡Û•áÝ#5þŸN•‚ L 0ܤ¸Äž@ H(º1oúúíÝ%†våª$EÄ÷4Ó‹}¼ÞdÒßjäêÛ—û´l/ê«#²·9ð¼á7·9(¿B#ÓÐI§'„]|Ô¬íµ€Åt`ÝSÕvVɹî<ð ¬æe:SÝ‘í£&Iuú nͳµAŒ¢Ó1ìZ0^ÐäõúCl\°‰YÇM³æqõÑ£?U®°ÝÉÒ+ÝÞ!qQd¦»­žÞÕóø%ß»?´nÿTʵ¯© m׫»€ö%EשÙÇC¤B†ÉsÖ“(úõ7šD8<ÁaÒ/.!Žª_0ìº{TÎÍF9¯†º½ufÐ!˜“ײ”M¹‹k®ã™çm¾J'óC@Ñái¬ŒŠ‰úeAƒçÖúÀ¬åßO$µŠ¤v‘lØ’öEêò;ù‘Ì»%o¸¾Åð —¬ÝKáÒÀ•p¿hø-ëïßý·Az endstream endobj 284 0 obj <> stream xÚµXëoÛ6ÿ¾¿BØ—ÉCÌŠ¤øP»}ÈÚõ1 ÀšäÛ2Š­ØjmÉ“ä<†þñ»ãQ–ä(NRthPRä½x÷»ãÑÁ?"øÇ#à/ fëà·³àÅ[nË­ƒ³+Øžò>‚³ù_a6_døŽ“PL¦J¨‹—4¹¥áW¢W4Ϋvò÷ÙJŒž!‘‹ƒ"¥§’ÏÉŸ$’Šä£"ÅÀJµ/2ö¼ñsDªƒVÆß©É#…É÷ òTæ9V>M¤~†/¥z’HõÝ®|\bü$‰ßèê G®æÎ"[©¢r<Þ\i¾¥%EÚo88WO=èdåïg¾Ìë€s“òu^HÎb š`’8®ÅjÓ²ý0™Øà&P ³1q¬-™5»ïUp|ÑÑ£òzÒºØTåå=ù˜¸ê)à\1ž<ª¡OæU,ÓÕj2•&¿â ÂóˆÇÅœæ—ù&­š¼Éès6³‰ŒÂe^,ˆ§¼jwnó5nm×´1K«y^¤«¼ÁÕ;w‚oM€ÁŠ´eº3F1e-§wE¹©ózÑcâ†q ,x(æyÑPô Þ_x¨s·²¨ÒÍ’~~wD“ËõE5û‹éÅíùäÕ¨Á¤œ[¦¤Óý&«gU¾iò²ðôqßVÅ’¸O~¶? !êÜ6y‘yžÁ•a:´!ýþ‰Ft$1‹¬'§ÀÕ¤"Å!¦ˆ ã#†1Úˆ¥+úèE ˆïˆ2/h³!³ã°ÞÀhÂl–£ªlN«Fм)×p £dŠæBÀ&Ó8ŽÃàd)e¸­³g1Р׍8«jt¥[pÈ‚ÑiÇÉÛ‰aY5Uê(Ä!/‚]ÌHï—¯?ñLO3ÏÈ€UéÏ8'¥—Þ8ÿÀh<õã›-¸A¶X¥NñäŸT ^èYbœ>­™…¤•s§–ÛŽ9=ÓÀJ€ºÈ¥4žÈuDúo–9Å–Ü‘¯7«l¸ÔP M[æ.ïG?Õ$ ]-Ê*o–köôC˜„ÈY)3”€¤²L¨.ÐÀNºÎ𬠣‰™æ>BïÆÐϤöÛy{&/¢hÃ2'o€tÂR¹‡)_‡eðµöໄZ ÂÏÙ¬!ßL­Dì'³äÉ£'í \µÇ!ðÍ^Šá¡D:ăª‡BܪË›ÖDzš÷va2Z‡w(V‡£¹Â ÀrçÆbÌB1mv^®Ó Š|æ6Ù-mÌÓ&¥Ùåªtap(ý‚¨¢‡ZB(OXÒ謤˜¥yQ°wÑ*HÜÜ’# ty1ÏgiSV/Ì{u7"ú¯ƒàÇ$ÎxqñAyщ÷îŠúÚpŒ8Ëv |åK"\vpqðÿÍ¢Ó‹L‡Af˜38¸ÅFÄì|ú¿-:~»9S­È¡n[‡aDÓºÞ®]ÑuNê·Sú~ÏeŠ˜¾¦& …ÛNX1+×~x«Y=Tâüˆ÷Øø9D¢º»÷ȶçôÇH‹ùc†š¡Àz(„ªz¸É%‘a #Ë1òÄ#À2˜D€" IX> stream xÚWm“›6þÞ_á^&h B€IRϤizMç.“6×O!ã`ÏšÃàö9íä¿wW+ Ääêfì±ÞžÝ}´Z­Ö“wâÀÇ„ ¾Î$]O~¾žüøk8q;r¢Éõ–-“ëìñ¢\¯Eaz®ÑÔæûëßË{X×·#ø©í{ ½¦åqnÔɺí•ù¶‘e#ßX'& O´´0-Z)M" ‘ÑÒlV4ß´*«ôBÓpYó;æHá&ßÌ“ºØTåb^Þ&ùÍoǵA ÄÆ²¬ÈÄåjab<·y¢¨˜´¼Ð³Ã6ïÙ¾¯]\¾™?ûz~uõfÄfÚS_›L Ø&‡Í%yN‘Ýê¥e ¾¦ÉÛD¯7%µnlÚ¦†‘ñ[‰ ïðGìL65Du˜‘Ç|ŸÇ‚Àv؈ËVHé˜}Ø<Òp©èq\Ûm¯”ˆÅ=Çö>Y&u#*[kü2ÎqórŸ¬7¹8=Ęk-£Àý¦JÖ4¨W%R»Ã˜cŽ 3pO®¦æ*‘d5¡)À3’º–7Æ;à¡Or±&€,ê&)RmRÔþòêê9J¼xKc ž¤!‡´ì;T%(ã7bÇåÈž¾ñaìˆxd³@»¼V[µáF\ä‡6k£ÿÆ@*íîM%de!7IÕÈF’)ò^Éâg<£\¶+{¹V‘ƒ4©2Y$¹lôÍEäý«ûÛZ+Ðw-Þy]<ËžSN‰?׸Þ#lÑó]"σ\QÁžð0=O&tziÇà ½%´§nR Î4ƒMÒ4ßl Ø—×”Ýp2…Œ´aëv)*d‘æÛ 4ùŒÏê&ËÄÒ^Í”ø “#ey"0—‹/þ¼xÛÃ1׎˜Â5Ÿ6h¬nªmÚ`ß7þ¡Fz\‹æ)õ>S³›gI“<=&y²Ê=(týð Q 5v$€:Œ¥±(3»Ø$¡>D…Æ?ĦšŠMk†³04GÙ׈ù56D_£8Ö(Æ4võ® óÁKöK™ Ó¹€X( kHJ›•¶qAÛfS›ñ>QÄíDÕˆ½îF<®îH•j„A|.ϩś;‚» ÕŸ¨A½)dÃFר¨åߢ\¶M­­óÖA_a‰©µ½Î±q¡ÅËå«Ó{~¹ƒË=W]n»^_ëY—þÎZ³Ö*Uwø‹­õÓÊ©dF9t"¢áƾsDŸ¦‚3‰³#j³8.Îzç4êMU—P¸Ê¸«¯©ž}¦§/¬Y±k—?»›®ã;Æn wïäû§ã[×48^ØÎšAºÔõÒ÷zíõ_——ý ¬Y3/ľÑôÐë›;xj"4üi÷Aç‰N,£þUˆ™[3© &V¤í„ßek¶?'g¶öõ|÷L䢻=£'Y‰f[dÌÑú{yÀïéÿjùÃè$]Ï™Ž— ð¤áÿ.H!VuØÒ»èD½ú f)Ub¯­[BÕÌ@ªÞ.j‘ê—EVr%Âh Uñ´W†ö“Ç e€Kï8‡•Ê r=åô¬wÿ; r€J+Âò– €\Þšú,.Ë\WŠõ“ûª ñPúH«ƒëPEêl|¨ qн8ä:ì}èNê‘mÛÇÁó| ‘5®’š:SjS óEH-¾«®ª'ì0¦'ª´>¶íMÉf/©–¼•¾ÑxXÇ"m²ã­õðCWÛuxd¸š"½ØîI²Î¨¬ó_²*Fß «]æzßÀ™Ý»_grýÐg/ ^¶>U*ýi ýã»õ1 endstream endobj 290 0 obj <> stream xÚ¥”½! €wŸ¢#7ÜÙr”ÜLØŒ“w:9¸ùørÂMzœ9Iiè×–”ž@€a6Âõ;ë°Óü-\ׄAßEßÝû*èÊ YÕ,YnâáÅ6 ¬.þ8ɶ‰m XúÉR–UÉHͳ<ÅÊ9«A2 ·€å×,xïÈꂸ\Àª¶-`eKóì×ßÐÙúækd²}”gíÿ9O²¹þÝû8 .Ð ó@JÛ0C­•ý¸d7šžVoò¥ñJ endstream endobj 294 0 obj <> stream xÚµšK“Û¸Çïùʪ²°Äƒ¯lå°özìõz+^ïT.™8gD$ŽIÊc§òáÓ'Á!HWm¥mÿ}ýnóúZÉÑtC))’D뉘¤…Ñ#T*&Ñ˲Úr=Üwíå¼—?\‰  ¬IRˆÍŽ%$ÉeíëC­‹£bŒŽý•lå6¡‘l©È£GùE¶¿uøÕµxb0††©›èÕ‡7[¨ÇXÔôøÉ£~(‡z¯®K}ï®=Û-Ë¢§žlwBÄÑûzP†CÝÕêòv»ƒ"úË}ó+Ôg¥^ª»0”Û]’FŸêjЭ£ñ¸£iNâT7ïÝLû3bÿEôt€ÁC¿¥¬»=f€›DÕzl8˳¨½SŸŸÚÛ^]ÝDCÙ?ô ÌŠ,*«¡ùC]«iT¹ÙbÿY}ëîÚîÔœïUýº4-ayŠºó=¤„gº.‘Œ ¤$+ôc6'WÖÞÍ&Œëç]ýùÒtµîßМê9ÅTÜ´ÈPa0H‘ác.]”’”/´YÐ-q³d®a”$L›‰å0æÑ˺oöµrébà69Œ¬ÄAOœ‡Dˆ)ȹáI±Àòð˜çÚwY^H¿aE)†S bÁu²tcK@GÐd>Z°!M€ ÿ“ËÁw¯—”ëõ2U­€8Öß}óG£®¼Ç=ünãžüVê- l_l…ÆÀe›S󬯹ÖËv›.¢ý¥3Rðà&:•2ðöåYnI8“K4–µõÇÛ"më Í1(˜ ”,ëö,ʸހ^©­Ö_KôEõå™±ÊmÑ´Ú`Aí€3ûÁÏ‹|ó‘©À¹£#ùæ´ïÆuQ?nþØü>S8— ÖiT›ë²r£é…>Ü'fX6™j¿øN{•×°›fciscA:è¿céŸë¾kí27¶ÀxAòtdÁÞ[`"Áy6¶pm6$žv–ú­·7´AsÒú8nU÷}ÛõÏlX2ƆCÅ—@A$:y•áF 8ƒ˜,Š1W(^ˆàøó˜Ä؃öRÊ“ ‚uÚ#Ò Ú†­Ó~ýµ*Õf f,tAÂÖÔyØK\òƦx°Ó!kó8#qîiÿ7HÖjiaZøž F´týZLŽl³”¿½ Ó²Ú>¾Z#í÷’Õ7ÄîðU²\œ–Öâ„â ´‘E†fµ}ŠAh0ü‰§ýSšÑžP Ac~ž¦ QY›ÅâUšÕö)®AsÚÛËýA¯ÇË ÞâJ„f,N(®AsfšÕö).@KsOûešÑžP Aƒ÷êÍ4U?¸äøCÍŽq9ù庆fµ}ŠkМöÕ6çQWž¢±1áÄÄpÇ<¶Aã0'+îƒ[ãäÄ8í ¸'or©ú “K0¬“”©5&ÌÉjûàÖ89í+Ø_ö³‹ê®Mw™17a¸6³œ¹Û•ÿHûm™Õž0 !c NS†Ad”pØ›p*c‚û©l™Õö®!sÚòh¨lθ¸ aTÆÎ„Ý*gg•ÕöÙ­¡rÚ ¨Œö„]Oð½ï4e·´¸Éj²Æ¦üFeµ}vk¨œ6l#íï{ßóŽf-N(®AsÃ;§íS A£jû6Òþ% ÍhO(† ‰ßûNSŠ \†óK$D(ÿy†fµ}ŠkМöÚêŽÄZ›\欱00«í βBždŒ´ß…í Á°”ã àiJpa–Q¥’ODZ)¿…YmŸà0§í­a71MÔ¶¤í§š1;A¹FΙ]˜jVÛG$GñWâ±ö¯zò>LÐØ˜ ] ȼâêFp”å±ÏsR¨´“ÜÊßs›öÒ¿ms!ÏuóXgÀ~ÖO½wÊc+Sàò©ÁÓ ¼Òå3ÿ̸³üV•úBŸî™2P«¯ÕY"&‘ žJsêc߀°~˜G÷]ùx˜;×Ú™“{¦ôfþ0Øf³üÓO²Àé5¨e.¯„&‘>Áž=a.졞Dá™rþ[ïg2sx†Îë“ÉmGí§z›°ÔökOm÷0w4Çp‹3:„/ì!|AÇÉ$`ÿ¬¦Ì~66Í:£d%cÂÈWm€Õ‘m{Þ÷ª­xnˆŸ¥úøÔÞêþà ¡zÒUê"@GˆççÊ.üuV€»t‡•“öÿGNÂN@hH¹wªSRjRRLMàøJ±”š`|œš %]"KYðÜžQ\=¾k|ˆ i*îã}ÑÝëÌ7w4.ÔÇ$+†Ë‰¼ØÕÆŠ÷3‘šq"R¬•’¸pg¶ª3££Ny†»• ÆÞŒÕ ;>LE{’‹wK“FÙDªZ£©?¨sá³>½Ö rìÌ©ôUsOÔ•œ6ÿfOfb“tçä‰&®®ô-?üâg]CžÍ_úA}suq•Õ·êØT?b\Q‹ÉKOM_Ës}5Zõ 5ÛËqïòH·¡9é™Û÷ÍíÑ´µUŸ&@ŽÉ³à+Kò½Ôü­Á¥p¡s àvy¶GW\z§V)õOº}¸õ&G@Òëw^ètMž-³ñf—dΠؘ@döûhŧ„~d¹JÏ]’§xp绪*›`–Lšš2ð뤈1eH{(fY_›^Áåuy–ðK¡xæ P<±„[aiÕ„÷1Û?åxbm—m€·U¶¼RÙ/0_.1 „Pù$º.(”µp«ŠAäÕÅžÍQgÕèº$X»¾È|>óê¦òÕ&Eì ½º§_wõ/NûK%SH᪄¿Òã@èÒzVL¼(v^$³L9 »šG|f¥ßÇÎe=èµN|1Î â8¥òèRáÿ2é…FGl„—\µRý‹”:7Ú&)É.Ó—Ì€‹ö,§ž` ÞTPðfiny-—£‚O{õÐw¡“PsVœSÉ A<ŸõÃj.7©©ÎH­{ÿþ—ÿ?ƒa endstream endobj 297 0 obj <> stream xÚÍZY“ܶ~ϯ`üÄI40q“¶ôàC«X±«âxß²)5ÃÕRž!G$WWòãÓ $ÈÁ»#—SVyÀF ôõuƒ½h”À4Ò þ%Ñj}{}yE–,É¢ëÛˆ%’H-)' ëÅß-þ}ýؤǕ™ÂR8ý¦ŸÞ4' ï§y?M³(#™âfZ-£%ˈb†éÏ=lj`JúÜMǹ%'))L–ï …ŒÉ‚Du6çœ¨ÎæÜ#Ît«5Q*’DSÃóC@±’(yžbeH±0ŸÂ&47,_Q«{~½ÏÒè}ÄiŠ;[¢4mÁJœpáž7Ñ/ÑÏáB>ñ—¿Ž£äÌs‰Ð¹$a©ï0_9ÙF£ÃŽçÎb2]c$ê1mûè×OrÎt»ä‰&ŒÁ¯D»"ß7Á`¤—##W³GøŒNÍþ$%]†&ŒPîž¹ …Cñ-A„=Õ·ÁS¥ìñ“JT/‡El(¨#ÇR!‡Da,Ôîpc&ˆ†*fTn¨2HPÅgZW>@Úç_÷\êÔ† [ókB/ z: [%Áh‰úNuS?JÐ,®6åÊô†2þé~Ó•}Ssͪo² æöµF=˜Ä¶b¶uîÛ.a ½\›·­1Ë»†×>fO–¦'ìÉñ”µDhh½~_ß( ¯ìo DÞ‚†á)3žŠÔÎíü²YÏfMÚÞÙ£‡6H5t˜îº«Ï<ë=Vve5l«›¦+>ØçuÞåvôjc*–ØøÔo¦¦QžY°eÔ~Í\ c\ª-4Iª Ê‹Çà’nCŸUײI]ËádUQ¬ã€®1Äæê›MpfU7}¬öëjm]è¬Á6žá…ÕôÖlúñ†Ê£Å0=Þ/Ž×¹™Iÿpò °ÛóÙéGR:^¡>=¥1Ì- ‹Ëξl­ºò¶½ß:¼Ë»ðß•(_=÷8ßÐâ`[ù M¢c:\ÜÌz?¬±lÜKs%: {.ʼn°—x{ãT8Tˆ“¸Wãç¾ÞE¼¸çÒTfFÒ÷æéÖþvn#CÜOfOÇ}†—«§â>õচ öãžKÞÇ=ÎìÅ=—™»AýJS$õPÇ+gõPG˜¶íêÆhSÃ]è~(þù…K¶…imšMY@‡¶Ë›ÎîÔË'þiSð'6¹ÚYc §c \ÄÀ;D;û>0#ï2é鎚yq„ŠèîJ§<†¡9JU÷E O¹ù;´QÉFëi >ñG–"ëRõ7DŠ:ÖŸÿô?]pÛx endstream endobj 300 0 obj <> stream xÚ­XmoÛ6þ¾_a _ä¢VEQ¯kW i§]l]°/uг•E’¤ÅþûŽäÉQl&UŠ"øv|žãswÝÑ¿#2 àŒÒþ£b5::=?F$ðó /F$öóh4ÑÉè¼üè/ùxBãÈ[3ÅV¼åjüéüì"ao[ûAØzÇö¢jЦ&~š¢I³OÂÔã…˜$âfˆ=V[& “´á-޶m;GÌ–ªÜ[Þ Âº<$iîgò—r3¯¸ÃIšùaˆF¢Þ#Þj®Z~­ÇÔ+YËìʼ’Àœy…¶øòLOæ^+ Á„ÒØÏRДúql¯–ÂX.Á0I É<%7­¨Í õšV*£ ,h ëlÞ?Í}Úy[±–7Z²,ƒ­Lénx­X¹Î™>íÄXHe ©€qmN"ëRÔ—–ý³œûãI%ÞÛ…SÚ0ô“ü0ú$¸þ¼óõ¥Ã#ú$Âõ@+˜ÆplÑ  aœìfjÙ¢¼ñ£¸/¯Q®ôÍr—Ï™Ó^>Sâ•:÷(W¼.pfnNÎM*]u—ë FLv*CŸÕ:ièq¦*±›îć®öº±]“§zU® Tµ&«*Ž¢m§9¹-3”$N<5Ž7\m]¡ŽS?ïêÎj2‰’HÏõ$;æ3dƒNRÙÆzI2ïJ@4jÛ×Þ™ú=eøMØ¥­Ž–:\¦ÃŒêެ°`¾V`gù¼[*7еBÖ:B-r/övúX­¬>oÐ?éW®¤†¤´‹*u'>Ìcˆ" *Ñ ˆ“:§=ƒ~–}àíFÕ®kÐa¯úg~B0†—Õú¢X¯Ðõƒ®Ä:`ÛŽb%j±b•Ü•\Ïô$3HBŸCÝGaØß—£àÚ¾æ¼Ôk8¤]Å+XÁ­²²ÙFHêÇw² }'0*kRë6&zï¾+÷É5[­º[înoŽ{``Ø.áófxÀn.cÝÈÊfwcÇíwv)8¬]î჈ÍÒbÕv³¬íô©¸ôm/² s¼7¶¿iLvdVJ<ÍNÉr†¦s&ír/4ê]Á™x³P`£“ÃN/䦳¶SÑm9Á X—LuË›v½ÁžœÛIG<0 d~fôDÔEµ))#ïeÓ–%_øËW»BÞ=L-…Ü3¼²ó! Ú—ž]HôÌ\½7kHü…5kZµÑ‡±÷Í6ø¼0ýö™myƒªya;ÿÙf{¡ß/Yž…y h–Z–|æmgc»iv£?ÍÔlDukÑVLÔ`-Eykv+Ã7]É`¥³ªb½DŽ©u2„7RÔacO¼8{P ¾Ø‰Òuº™V¶¬ràMíòo¶1‰­8|•­§3¯_¹\têÌÆÌÆ0½•åÅ^u¢àÍÌ›¢=¡Î 6 ÓÉ«íGòI‹ÝÞq‡BhI /—çOíÄë_m{r]°-x‰J>9t GûÈGˆüžÝØŽ©Hf+t âþ$ù 7—˜ëj³š››iIä !f àÉÒ±#Ë©þ17vàfûΟt°ðñjÐ{~ ?`„~ð`I†ÄáYÞÖpíéïšœýóú‹"Þ§HÉ>Åô0 ¼â…NÙAçȆ¨u†$/9GS%‹/ƒrA¼OðÖ%TÁ —¸~N !Á}<ýlz‡<²Ý½ô=\r_ û¸¿ß¦«~ ˆ«¬Ã}–÷‡,:Ö­kB‡œåW,•”êÁÓt×%SEï¦Ä6ÔæÞí‡2)^À÷ƒ|ôHü[zˆä ðÄâ?ÒÿÛøÿØ…òƒøÉ@üÓÄOâO‰O±Íñ߸ðωßò3ð“ûñO~z?þôûøÝ‹ûÎÿÄÁ ~?L’(3´IØ™þõËÿ+¬Q endstream endobj 303 0 obj <> stream xÚVmoœ8þ~¿EŠI!ؘ·k¯'Ý)Ûkºýpê~+UDoCËÂxÓ;úßk3î &oÉJ†™ç™±Ç3XÿXÄòå?±b*¾µÞZ¬¬‹‰­ÄK£ÈZm,šx”Y.ñ¥ÂZí/Õî:/Šë¼]gö›ŽÒÐNpM3ç¥ã’0í‹3PýË®åk^ðžÞÂrvá|Z]É‹O| ðCÿ~‚«'¤™¼5¼{"ñö J®LKAx„`BðÎDðþ©Ðy‚å D#ò ^ÿ‹¢\ïvGºf³é¸h6™}{]ä"GµÈœû x§,#a tV£³+é¡2R>îÄi×–µ.'ï˺ÜQïÚæ+_ x(öm.ʦ†§Ó?õè&Ëjù;bWYL¾‘äªùŒÕ·*·Òð匥½2¼üà¸4’X— –ƒf¹PTÇDÀÍDâº.äöxa‡ý…YÖyFilšì2».ÁzAí+T¿q_׷ëóóÌ™BþÛ!FxuSðL¹ß~,?eŽûZ¼¼{äpU Ù¬ï iðÍÈi¨çóû¹GÕ¼•‰·óVÏà=œñiPØi$ë+r¨LM5/Bá»Ju–oŽx1ŽÔoØ+X|Ï÷ ˆ¿Ãrrv¯øŒËá Âæ@0›C«ÉêQý07²‚W\ðë/m¾»‘ûg,Ü–‹}‹÷××ð™^K€±`–Òù©$ôRe”x!ëV7Üqƒ˜ÚÍ^ìöäMÛlAð:°ù¿ùvW¡­ì&2<4én‡Fö÷Z=[öšØ¼’ÊØþº²^Wû¾Ï*¨¯ªg(ÏZ™ì·Ž´W^±Í[¹mAr •‚ê*½WÍe§.PÛ`ÏÀl‚!›ÂÈ‹ÝG—Ø9,’³‡Nmž·UÉ;úNäm/ƪDvÜ9YEÚÖE±—Ðc_3l.ñXˆ}ÛW`:_lg>auÙÝÀ»)eOŒ£r1C)c»ÊÅsLe~ ±–K–×€"k0LžÂÉ@1j‰ÁŠ”Ì¡„}-c(ç P}7WÏת²z.Šå0Y…H~ƒÜ²ŒåŠl5=ÇeŒÙ¶¥(×jj*éÚiÞ¢Ï6o¿©rïKQ¢VLÿ¡Q'x[vß:¯ør5ý<•·8›Ñ>rmD³ÇŒhÉÖ4tJ¼`p³ô8„cß‹Èx3ã †ós­ÁàeϹ=lê±(A˜@eßZ¨ñ{öÒ¨´AŠoÙPC‰Ø±0ö[„îj¦ÿ(SªÉ¡ŒÝôðtÐxêQ=Á Ñ2Aê8Ç€æô“ïóh´”øw¼ÈŒlN;F´h-ÐbKDKfÖ“ sò¹nR ' :P˜ @}Î}±8H†À}Z˜Ì7†I±iœ£fÐOQ)¢R-Èän0y.˜ R Zל^o—z›§ò£F7b Tj0˜þýËOö𽤠endstream endobj 307 0 obj <> stream xÚXmoܸþÞ_¡~Ó^V|‰´ri.H€är9ãî€ó!wå]õ´ÒF’½NÛߥ•lÚ) ȇÇŸQò%áI<ÉügÉæ|w™üõ{žˆŒ#“Ëøyí°‘\nK_í‹ãPv«µ4&•«ß/ßµI„b¹Íƒµ††óÖoºâ¸'ÛŽCu¨þU UÛ`Ož¾üø–^>µ·CÕ”½÷öú’"° WL*|ŠÌ2!¼SÉøj͹Péûâ¾:¬d–ÞÀS®ÒM]}¹-ñ]§Ç®½®ËÃÂ)7 çÌi=z•9´F¯Á¯N¿+6+ÉÓ?v]{ÛlÃ"UÂ3æ2‡C¹fNÁpÍ´õ£/÷e0s33ÑŒãTÜNq*î ΕÎRŠ:òô*}ÿêãÕ*6­L«Öé\ZÐcS}_mÀE–¥›ö°yz]5ÅÐvUQ£MÛå87&‰­ÖFÉôMu‡ÃÊÆÏ 9ç̈dÍ%Ó”¤‡ ‘BVª®Ü åÛ2Ýù}¦€y6‹Ø9–óð›ØŠ`†ñ÷¿¯Ö"ÇåÇAÆs ^­µN_Àfx^G¼vGÛ«Õ†¨ÓÓ¾ìʘg%˜8{Ž„(˜äóœÃú zôå@ëooèIéë†jSö~^)ÛF×nµ n_ǧ±Yå8«˜f-·»0N‡ýh=Ç?tfÝ|+½‡-=¯2®ÜNnÀIIuÑë!mØXnC|Í‘UÊŒ©ÑêU0ÐOlÿU&D\+àåŒÆT Ì¥iK>Ÿ(¢Ï>„+ßE Î[üåͽLcî>ŸvCèܶ·×FoÙ·õc[Ð'W«Ñ¥PXx(ôe¿éª£¿UŸTÙgsTÙk•giGÃxðæK dãÉ‹ÁÏ?RÚIDF–!ésd,2:™¾)šÓSàSœef>…Rxu}sŠÉlš‚0ò83RB¹5ݧÇžSàƒ/IûgLèIû¦"T =‡}èè ÆmZn*ôb {gºŸÄOnñ¶šÉÊ€#Ͼux›ÈjÄ<ÏCXxﬧ~è¡bÝ­@|ä+/E·*àOoÂK· ›s¾¹% (ÜýœRÊÏ£q`¯rÏï„_T¨Ç¢+%ÖÑçê\pÄ„ÃBxVp,2$wØõ¶×p$MúOذ ª Hô/ú  }°É=ù "/[yànÆ*K_s?E·¡!ñ{\J •|ù>r™:ÑRv,/Ó™îøU¹Zʈr³(xšX²\Mþl²å¢ Ë¡`húj ’Ç×¾°øžžX…ÑÛlfÎúïÞW¯&º %–嫃¢¯¾Y×­?@þaê.ÌXíš ¶EB# ¨‡Šäƒ?Vc©É Y»²‡’%ÒÅ¿]y¬‹ÍtÚ•fJÎK+Ì*,»¦¨ë¯£»ÆÎ¯AZTgõâ§§s÷¹gö‡Ã<… r·Ìà÷§ 3Üu‡š:žæö³™ ܾ‹Ñ®à¨ýiòÇgcdz£28zÐ)}¡Ž½(Ú°w—è‡ÔÛ`{CƒOZ ¿(V­:ÏîáÈÝ`™¾W4Á5Mìæª×ÿ°-†‚Þ®=¸lê‹Â?.FQ 76ŸŸ¢YÙ¨€Åá0øý/ª3 µ¿àñèÂ>¿PxnÚ GùkdšõßyåŠÁËäÊr¶bŠVªz¾§Nyæ¸郆™À¹+»õÝ ¨°¨oýU&5¥Fê©Ïæ«ìŠf û[¥4‹œNI~•!gZyûáòPA ägr–£D0Æ+£Ð~ ¨3+G8}ÿò׃À®åÅïž±Uúö&& zËããÄñûÌ,J‡Äշœ›¹‡çi‘F‘©îoñσӷŸì"”,òt)úþö@rË¢"ü t4zfü&·,ƒ,QsѲ/2wˆÚòxyiìãìQÒð¸u Þ!a*ê©=Ï—„Kˆ 6}ØÊ¥¶ [ å¢3&Ü $¢=’\Y2ú&ôÉ?EúŽ¢’À•ôQøž0×G(e§&}dƒ>RõæÛqÿ ÌÊ´)Oä|.Ü yÓvd@y‚ž >-ˆÏõÉ'ÒçÌùœÙY1j§”~*‘~h»-~ÂFwïÂZüfÁóU{8¢èßy[‰ÜŒR‡•Û@Xšc‘´F‘öûТ,Há8%S‘eü‚ºŽGF}J¨C²Y_ð>åÀ k£è#“Q£éú/d8 endstream endobj 310 0 obj <> stream xÚí]sÛ¸ñ½¿‚o•g,ŸyÓ{pï’N:Išk|×δ––`›9‰t(*Núß»‹ER†b9¶c{zOH,»‹Å~‚J>$"áðO$VÂOfËäÇɳ`œå£­T?Í$K!Õ+Ñ™éõ©þª ͘£6Ì ´áT3 Æ;lX¦Šbš3#Çb§ÄÖQàÖS±7æ iª‡é±rÿÂ?…Ü¡>MÆ„Ä꜋êèCBå…&bÀÛÀÄ&S}ÝÚ[1Ž!>*aöð^ŽäA„Ùkñ(¨+‰A]X‰i`Ù ”é(¨ó‰L-ãOtÖùÇõùDE[G+˜BàCúÕ£ÀêªÔ^S»ð²¯£w#û²âû•²Ü ßì~y<ˆ½L…£Æ‡DnÃÞx˜Qưñ½É0Þ ^Œ¯ØïF|Ÿ¢Ìûò½g™ÍÞF+ä,ò7ù¡|9Ad;•©ÞAöKújnâ,ÖCq½íh8D­ÁVÛ°ì·óNi>,£û>¸í‡§Ø±B}¶o…cv^ŽÛ[]Žg·¸ðýãñäö6•†AP3œép((J¦±pjO°A¨¼ ?ÝÍòö¥–°—OerOMw]j!­\nµàºHdœ¥fOî6º kêëKìpxS¥Ôä{|è¾ i e•Yðóm—7\_'¸¾oÁÇ]tLp<{p«».‰à概›G"xzSÁå#Ü>USÉn*¸êÒ‘O0Ãe¹`\Á´ìÊÆå£ÅžZëÉQETܧby±p4YŸÒ³=w4»,>•Ëi'ë%$¨®<;ÇgK°Ù¢ü°.šúdá–l§l°J‰‰‹‚å12Ó¸¶hŠ¥k]ÓéJÖÙ”Ù<(sU/"Ê’þ3`\LQÐY‰€[ƒz²¨ýä¬h˺:˜É'mM(—çå ·vNö“­©×mY…Áª­¢©{Œf2ÔŒú‘ ª¢›èoS=´±Óz]ÍA\AÑpÕ«—_e¢¸œ”+šÛ,XùÃâá8Ç«àÐV´¬›, zù豚¶œ¹€RV³Åzî‚HeµÅ‡ch–¨‰—§±sÓøª¾|p+1€ÍDˆÀ[ÚyÒ›Ÿ_½Š‘ýé‡Ëk ÕXn‡ v­P5ž>¼aU݆i<à9q0X‘u÷qd¯òz{…z}èüÃÂ1ÏP)S…[OñâœS¼ €aá8ÖC–ÒÕÿʵq_Ⱦà |QáSOj*$â¡Þ`egÕðKó€{JÀö@¦“ÏH6¸èye¦?ô²Ú%á!í˜v–è>Ñx^´½xßÍ&ÞGEßÕ}—úr…Ÿ+†1»wfee8}«;gÆS·½7ãLA ¸Á ®-˜â컃©‘†ÇYº¢ «Úó¢íÞÍÎêˆ^xaëj^VgqÊe 1p5\-íñᮆáÖGŒCz/|ì€NÖ\Ãêæ²\¹ñãþ)ðëI¶ÓPEJiJiËŒ·Ô4äÔvZêÍn[êÖU Ëdàÿ‡ˆ¡ÿe”æyØêÐ@pLç³ zh‚r‚;ë‘;?{aGyž ¼Š¸÷_]»nªUDŽè¡[ä~Þv‚ÿå¢-—Å"\ü±˜ê§°)†6ÿO¯ÞþûùGÇGÖF?WÅ fki„ÏYø\µEÓâk0qsEC¶ˆnj''ÞݬX¯:”zéhÕPÒpÌiŸeVôjElW¢a ¯b|‹…5­;sÍôãI!­¬Áš¯o 5šu^NéÙÕ™·T¡!¢[ tFî>w4ìÀÅbU‡eþ´Ðoü| FjÐ!ÙŒ¨''7“>âK祔 Å}š97&'>ìá^¾9¾âCYÎ2HCÿ™Å[¼d›ñ.`åôË€×Gù‡e¢óߨ‰ áóëTäè°>…Ö­‹ø•T'à@LšSÊSÖlÊ Z›-Ôô)úlq¹Ž7ØOµ ×ñ‚g>;À@ ù(ãuXäw—ƒ j|£|FíÉkúò5ä7XDªáY4[eÀ§«õ!%Vó·i×Mçö¨3Ë'ï ¤­ø ñ˜†¯xK/±ò748뮆^…25;ªb6îÍÛ鬯ê½u‡£ÂMù¬nÀQ—]vÿ™êõÆ}X—ëê*êÊ‘ —Æ –”Ë@¬ ½‚wžºYuu±r«E’-XÎ'/+_sº¦çúŒîmCžù$äÇ®2Á*Cd“³¦¸8'ôwÍj/ÛGtZŒSó@¨&4_ËZ1_Ì\5ûLàeÑ6å'š‚-\µYe ‡…S»jå"'¯8³]wZ7@3ìÌ)ª3¹ÆÁN(h¸KH{1ä}3Šì}“ø>–öI4ÿKd}Ö·Eï¯ö˜~1xF:º¸ÚjR}žîp¾èÀ`MJ¾à|YAÅàƒΕ=|ùú‰üðް(Ð>›Õ $X¾"y@LAú¾}mê%•šèÎ(=Vçÿ‰v…þ';¡?ñ[e³Å‡˜éA|îò÷Xï[Õ`_üŸ>]YŒï¾Qç¢hΆ+ŒS¿§%)ûYˆ–n›f_Éá(´çžAÕc’2xÊF!U> stream xÚ••[o›0€ß÷+P¦M°&Ì%¤é"í–h“ö0-o¥Š(bÕ@ $i7õ¿ÏæB ˆN‰äÛw®>ÇH’.iì§KSÄþšäÇÒçµt¹Ô§’£Îl[Z‡ìx¢kl!­ƒù-I|º°2±)_çEàPÝ.”Ûõ!’¤¯)¹{ ÑÝ}ƒCº:ÓK®xÚaæ`y‘íý‚Ï-ù/ Aº¿£æÇ¨˜ÃŒ$‚Êqµõ Ãax…7oBà³BáÏg~t僫€˜Ë~ ë®Rn¹ÊdÁwÙRiën˜rì‘„Ñ) NØ),d3Š%aeÞn+l¬ÀMä¨Èlòœx˜·•Ö) c3žŠf•X3yJ;­àð# ܶŸa¯Ààª+çäNÃ*=®"Ìi®Ò¡Œ‹3é`ãû%-¯ž†!»«“žq}¥µÆQîÅ;ŠUŸ>Œ:•³[¾}Jöxƒ=¿ø/sïY:Æ¥ÝTu£i¨SÚäÅÆë<›´¤v»&3zéç»`^_ÀùAäºÉètãëŒ?L³ªZÉ™½j ®Åöj²HÕÑÅEOiꚥɇ3}LðpCnçÝÙ©ã<Õ¨Éb¼)Æ$Ú¾ˆ?…Ô‹^dPÙAÍÒ%ãV³Nì…²³íòjÄÅð~²š?w×i€)>•ùª¯äöY"*¾¡ßlë¿\šßÓfü%Ö-uÆ!GµŒZ*Ž!ó 4 C.¶&¬lyÍÃ"ߦ šÊÇ–©—$RafñÁCy0†|0†|0;2iuýNZMU7_+ÄÞ4‹½™¶é”r¶]¡¿ÞüG¤+ endstream endobj 316 0 obj <> stream xÚT]kƒ0}߯ÈÛ"ÌÔÄDÓŽ½ ÖÁÞ6|…‰Æ°ÆF»öç/&:Z¬}…ÜÜ{ι' 8 <ý`ýz ك׬¶8­ƒD™.»ØÓ¥ßP8.#²~a;»èã& °€p Hn¥ GÈÌÔV[ ú¢·îÛc†ÖT£9b¾AG…îáû>L¤R¢m—p(ë´¬s›—Ç®9v6ΔÜ÷…ÝHçxßTæQ2Wñ)[›ü‡f²ª¤CxÒâcî-º9¡#{_"¶Vú#ií¦°£°Núè§5PRBÓy¼, ‹¸Gm–_¡º2C2®SàaÞ"ÍuíBA­ZUÖ#õ$”°‘Ò†§”è,çÅ¢¼g»¶²²ÁÇlÊíMг¥ãÍØ¯Ì‹îŠê? “©âüªàÝ—$ó’tNß—ôç%ùBI:/‰œÍK²…’Á¼$YxðpÁÁñô›½”ä‹?¢ñw½¼QÑw n@¹é„#ôóá1¢?1 endstream endobj 9 0 obj <> stream xÚí\[o·~ﯘGí —<‡×" R Š I¶†dkí±¥@–‘öß÷ûÈÑÎH3ë‹D­ ´âåh†<‡Ï•·<ØÁù!»Á¥Á…0¸¦AÜ’D†˜Â :¤TAµŒOÂP2>‰ƒ³ß WðQœ|…¶¼uƒ‚N°aPPŠ­ (:TA´Õƒ&(ªZ4¢Tñ‘¢iÁ? ¾Ô㙄½¼eŸ’1è€W’žÁQçøDJÄ3HÚ„g4ážI:¢?¤cXóè[ é„g°Gð ñŒúý ¤ žH¢?$%ü- iã”wn@Ó>8< nd%œ–3:X@çHÚ‚y ˜«AПXÀ˜H,€Y h$ XÀGèJHø'y°€þ`wèM²…¯ È£MçО ¦ƒ¨$öÒ¡‡)@:ä%Eðç0v)cô"PplÙ Æ8 ÚpèwVÏ¿”!ûŒ1\9ZŠžrB¿"ŽÃCq6W©,‚qrìCì@.TK0–ìø ]-–âìØ7ùÞ:ö5±wR…&.ã "%Ÿ]ŽÖUÀ J‰0D–À’³€—è v…b4PâާG¢CŒ ‘K¨!–@àÑ.–Bm •ð û(‚®kAªè£UmJºâ*¦àT N-¤J„¨²÷B\TÑ–PÕ³.yÔH„j1`‰52 ªžG…æHXèµp=ûJÃè@ D©Â5 ¯ÎGð!7çFF<¨e|ç9h€ Š)Gª*êc •-".ÃMÝH£€»P‚ÅP(9¡5ðMSjKH5ø«c­–v&pø«Ú£½ ±Œ  Ç2fe‰5 ÍG5Yp)”éDŒ¥PR"h%bϱL¾Ð€ð»HP%*È©ERlPë!=Ê·”GëÄÌ´+êªU‹—X‚Ô©ÐØEô_929!%â9cô”èæBÛˆ–PGJ,¶'Ê–£%$j…#O:@Åòo”K-àOó–(¡ü±ç%B]•ý-%a #­ìeÉÀųo ëiâ(µŽÆ®Êoa‰òKÝð?HrµÂŽ%h‰'êV[¡ WV¥ÑL+4aî„F—%Ï·lÙ'b¶ì1ÒÊqBwñ ¹ Õ<³nHÄ…-ÃÌÑd³¤¬A^"´BëFô´Å&ú°@®@`{ Ú­µ8ÐåwzY%¶ oCÕHHÜJ/¾Ø~wq~ÅXwxÌŸ¶ßÁ·¬& _~¹ýñòâùÏ»«'Û¿ýnûËîßWÛïßœ¾Ü}Ó~¾n?ß?ýòË?ͤi ÑÜ¥¥_þóûnûÕùùÅÕöçwÏ®øôëóß¶__\ží.ŸX´iŸn¿yâZá+Tùyû—‹_.¶ßžØ ¨ý´{~õ$¨š¿ Kh0Œp>p@IŒ®7£ãMðô«Îxhi¥² N:Б%M¦@+ïM‰ÚŽ.éˆ7”ôJGÑ7ç;ÐñK:ÎøÐFÇ%sÒNXÐñ%ZÌJÇ¢o®¸¤“!wÐcÒñÅè¤%d ½y¥“Ð7—:ÐÉK:!š{VéD5ˆÙ:Ð))†q¶÷jïU:}s¥Ó%üø©JG£A4Ñγ%LɺÖÃ<_R±bè{*[ "ÿtÎt4g“K³nZÐ3éÑŸÝ’N †ÑB¥“ÅÀûw óbI':“J³nHL–tœ]òÙ0°¨„B0’z˜Qç–„ ¯±4û†È ¾¯‡}s²$$Î8ß œJ6({Ò!$háT#dA°Óƒ_ŠÑßt¹)©‡IpaI(¨i¢€LÁø."—T´˜ÑÑ!™19w xÒ’ŽDÃ<¢B´…賡¼$äÄ 9o„\1H°zšû d|+‚²–6BÈ4ŒJe]:!¤c&V‰–I©‹².½²LãF«€üÑ`ÌzZ:"$è†IU%óƒÿVb¯3 f·­t+3CpKç³iüèÜl›Ðʹ¥w‹êâ›×‰µÒÅ»¹¥{‹Á›<ÊW„ä.ò%K÷¡9it"º8Yº·è<¹ÉW„éá déÞ¢µ&ú‡F›LL=â]Yº·~¡W礇ב¥{ piato![º¸7Yº·m#ѳ’-KçTL±cš GW´Kš½ônÁÃ9•–— rÔ.=Zz7XÃiÅ–0$©=œŽ¬dX1ÆÌ4 ²Ç.ºº’bg¢ …Œô±‹®®äXš cìòÇ.„VÒ,A2lÇäTÈ.Fál%k´¦„1mtÉ”ÜEWW­‚ç:oôÈ!{Yɳ²š<æ Å"…ì"êJš•¬á\u%”rÈ.„VÒ,¯†í-Ÿ³ÈíºL¿­¥YÅÄ8&Ž‘Ûõ"]ú!uÑp¬åsŠÜ®G¬ K?¤ ­â˜¡ÚbBéBh%ÍÊøuMê¤D$‘= ÆE¾ f!ä1q„YÈ=Ì‚®¤Z°¨v´?‹jµ‡YЕTKÙ³1ö° ]蔕Üiöuê“ç®"\g ÇÌtòiñ†Ø÷b —>T‘nt7Åé-¶÷«)ûd's+Âdgû]²´’³CÖ±è†ìo.œà2äx;k‚õÉi,rËÂX C.÷Y¸™ÑšX18qu×!ù8JwmuBÜe·@mè éû’_fµ7hÎxº7©íßñ<æ˜Ý¾{Y„)ø.Npñ;#Ý uK"©º«ñͧº4;¸Á]ûûOßóÿ“_¯®~ÿóv{öêÍéó·æòÝÕËÝå[³;{·ýæ×Óׯwç/wo÷ü ª» àQ WûƒîÏq.Ãp…;ŠÎ!Ó4™®™êÌìѵB‘û¦BŸ•äUV×tÜ{b{±0µp í¢w_xÿXS6¥nÜwXnݹ= ý\@¯…¶+ëˆ< ï (f¨| ¶˜ nxº—ÉžëÚns—K-ì÷ ù¸Ô؉½¶dê7…ùëF¸µ+/¬Ñ{eå¨>cšGàšYä&´’ëŒ —P=Ò ï"G÷ƒ‘ºÙ‘åMú2îø3"ù ^·¾óA›A>×ßOw e»fâøØÞá&r÷5ÚÝèÌÊ8U §I6±b¸.p[C%HàìTÝРwtf?ˆmY¿ÓT ˆ5™û£5–»a”,wžsž8É£±yÇgîh-¿½aÎç>a®Y­Ãç$—Ód©×`¸á˜V˜Ûµ9×PW†¸ï\«sdíå<Ž9$~šWv©ÑztÄ„º/ZORgü¢×OWÇiuHŽ þŒ—kŠ÷4½.Ümèê^}S¸C[s H|‚Iò=⣇£ßß=Ûžï®^¼¾øcûrw¾»<½º¸|Ë?ýqqùÛöåå«3üyRÖ”MæY O…Ô °œŸ¾šö lÖ“0 î ×Ñ]úYÎõÝœÁšInçäÿ^ò$³i[[§i%f£Ò¶§Ô£^ zòÝõdu–öaTv5»ê:¥p‡´ñÓÀ8óLo5‘{´à÷‘vZcfÈýSõ!ãT`™²EÇÊ·³ôiiEÄð ð$˜(Ãåƒ ×L0Öke®ýð´ÒÅ|ÿÏÒî-²Óº®+ð+<™$ÉdáI&WÓ)áøaëÜU±\Ïf=TV½!»‰ dE„¸‚”ÇèôXøöq¶öÁ qO+ ”ïIkZû¤¡žç±GZܘMi»­¾±ÖîüòÍ‹ašE„é3âr–ê_xhs}ºïÞÉÌ ¿úÈÓ>/BB_‚±<€‹ƒ‡!ƒµ\áÿüBÂ{õ{ÚrÁmdõÐkݷƽlÁäj¦#t9}ZœøÁèp2‘óo.³YûÉô©a>'ÄÓáÞßËù®¯®¨Öf]][ø_ `§2+èJ"üO¤OÈU¼ðLJÂ÷1,Bêi3üšÉëÏ>ð¼å#‰Úç¢zýèµì£ªÍ´›„§”Fp‹ˆp ÃpGºÇÐí–žÏÜq1¼ŸFR4®™Rcy3A\Ùgùˆ³5œ6YÝÊ÷8âw6[z€=ämÈå¼®÷Èé¤+.]¿ùi½ÉWipãT½ƒ%"ðâb8D^ßk“{.ss±ùAÖQ*)Sþ@½äÁÎ&gÞUgò*å$óQf{:Ô5ºš{=¼WeÖ¡®ÛOÞkþVQìa[>ÃÕÒ0-ÍiRä/p¼ÏCy©Y=¾À}^zûÔG¤ëËã.Æö@®JÎÄâ2œý,BÔmýðêÍ««·ON솗<ÝþíôÍ®>òº$´wâ6¼Ü©–ðdž/VàrQ- Š’[-:Ýð8ü¾I<«øVÇ£Z1 [1¢˜Z1¡˜×Í«žÍÕ‘§²Qy:EQZñÙ†×QÕâó ï£ZiôlÃC»S£g^WUëì6¼¯ª_lxa‹è²6LPwW-Û´c“}uöö /Ã'õú¯ú«¡ý6ŸUU܆ÇF÷ìà™·bUr Ü’{•Õ¶xÄìÚÒÖÓ¦y·žAœØ~ìÀ Cœ¡a(€34 Q×h­4úlÃÓlS£;Œ<ì0ò8CÃPg1œ¡¬4 ±QÚD7cãHul) ‰ $±A¢ü6@´¶ÙF£™ zµZývükìø OMüìØº ;6 p¦†¡Î4r 8ÓšnhÙpÇÕÔ(ÀNc'vj*àL Cœ©aˆz0ækî6Ü+05 °óÈÀnVüì7[Æ}ÚÌ"«i^S /NlïÛij6óÈU9mš«Úæ¢8ã®ÍX³o¦[‡´6Ú†#Ê‘FåÈ£r”5åðiüpbh—±@»4=ð, D<ËÈ1ð,kÊ|ëd¦pxÔ2öálãmÃ!:¯½«ÅÞ{Çb@iM5à‰OÊÔ$y?kD”? ¥`F©áWPZÓŠÓÍÉLÑN7¾™û“gßÒÉs”àÙ5Àrs¨ì]<€ç‹ýP”¦¼°þ:;þÎQ•HF¥IãhÉøé^4 WçôþkÈÙðzY— ãüÝë×Oñ¾Õ™¿÷<üzý^bó÷Rp]¿wÍòÖ÷P3Ï]Ãezéo¼gòT³Yžë—QTO/£Ì_&ø¼ý›|èMºÙ`,ˆþ÷/Ç€b| M4aÿ®Üèïm 'M²÷/‘ î+нÑh½œcö²`TÚPîaIÞLã!öP-¹Á÷EC®_êjp’ÆíÛ̇š¼5x³7óa¿Å†—÷ô9hð¿c&hz endstream endobj 420 0 obj <> stream xÚ¥[[Û6}ß_Á·MâáýÒv[½l‹î&Á@±53Þ±­YÛÉ$ûë÷|"mS2é*Ù‡FQüîçð#­*ãgÊ&-SV2cpQÌk\4B1å Zâj™pô·c’cÜy&fyŽÉWÁ‡0wÞO2”Ç;ÿ‰À´Ä{ Wc™†lMs$g†;\-3 s­€ó`wLsŬ0¸Zf5æà]ë$®ž9.p Ì)y‚¹^®dΓžy²ß¸#{›¼ƒ>mY ;ájè½ÆÕ@žÐ,À' ]‚C‰p˜“‡Ð&8^S!á|ˆ„pI7˜­$Þ½;xG È—äpCÓ½ÇM€«>0¡$| 7pX…ü£ ÑÆËÂn\;¡=½ 9FÒ˘n i§'ä+â*,P„ˆQ¢ Yè/M†9جá´ðœ†0ÝC¥Eò>?(¡È‘ÙÓJ ËH»Fø¤t£oN7šIG™¹Òsše™ ††`7·H d)ÊѪ·C¡¡k O lÑ”kð2ìF5!¥Š¼¥:Ñ”wJ ’¦%Ù¬)&9š†Éfüaèa$m ÂYºÁ„@u› GœµÑÌòÙ7Jû¾KM2˜±$˜0ŽäèÀL@yixI¼@-rº‘ÌJx K¥®,k=1ÌZŒ“qÖ9šŽŠ ”¤ík 5éP.0“3')P¨(GIÓÈ™3ˆ¨FÐáLµMa]4 OB Í<§xâ%Eú¼‚+°ô”a }ÞÐ×÷†IBUóG±z n Pw@„ £l>¬Vïþ2AÎ`èqPçƒÆÚY8 "ÌÙ ÖÖJá0èbáè qJƒþ4ÑûY_{~'Ò0ad4®Ô,‡ËÙE¥9×pê¨Êt,^ÎÀ}ÇñpY> ôâxP2~._ͬ-D‡"‡¹'Ûƒ¯¤‘ø§2"xmDÚÊÈP Hž)/f¼bº”?¥*«ÓÌøÊ ð>”jIfƒº’añ†0ã¶2ˆedv)ƒ¬»/à hóÌŸ¤ê ¹#Ò©`PËÚHÓ>4r4ˆeëÁ zÝ) "¸Ãôú™•AeôÌ›ÊàÐ÷QÚ gÖT±Ìά.‘Á¸|#àú™:åPœƒ<Ìä)R]$ bêѸS3g.ŒC¿×Æ$@¬_à@W*‰lþ‘¤ˆïÇþé™q%r.úçôe’r輆ƒègá„s5@Ê™T¥e¡`Ö7ß\}ßîö;ìWzŽ|þœ½^îWí“·ÍÃ{Øv·Ûfͺ÷ÿnçû§W/0þûÕÝëîêû'âéóçW/›m»Ù÷­4iú­ý´ï»ú‘¸ÛÕÃõ|Û6ûöú¶—ü–6‚ñ 럌„«p“ w%á»v%_ošuÅ7»ÝòvÃÞ>™ß5›ÛöíÓ¨‰Ñ#uº îå¶ýØoy2ݾ¤»Y,®?¶ÛýrÞî’æÅ‚mÚGv|ºïŠ^šºZ—« 5—IAûé¢Ïñ•’Ó¶®ÝgÚ#¶JN7ÛùÐ_zPqÕÕ•…\™()[´«Q„ñ¤EéÞl»uQ¯¯êMœ‘ôÊšÞ£“I%ý]ÕêÚD®M•´µÛf7ÀGÿ í¼Ûì!u¤¯©ë“¹>]ñ®2¹Xòì}]“*“Gîåæ–5›[w‹åÍgúkÛ}ÀÓv7’/IþËínÄÜ/ÍîhûÕwÝh~ÆŒ“jHçÞ^¢Ÿ×ËÍxÈ (ƒëGG¶-rßUNFªHF7’ õЃƒ–÷ŸÙœ[Àc[P“Bœ“ò’9p/É%÷nêz]9µ»(¸»Íy–M5Ȧϳ©*Ù„¸H~HÜ"¯\ú;!¥çêYnØž$Ü,WãH‹ÁÚ¥rÒEzÜ.‡Hé$…`¼?Q' ꢫ:'!-«®Îç‹fß”}=ªEvÙ÷?ýúâ»ßÙ|µüχöjÞ­º-òtÓm×ÍÙ®êfål¥U=$¹]£˜|µYºn–,×#Eâ®È‚ U)xV–)ò±,£‹‡²Ôå² _)õ±mî¯çÝú!Ã}³Z1z¾úL$¾A#Õ.½Óm cǺ›"áŠÁò¬s‚Ó¶Øì·Ý涤=Ž|©~WПÒ0D‘÷ ê¶ûh þBÆo—óÆà)åj›ùgÄœ-–E|Ý[®ƒfÓ¬>ï–»j˜¼L^n/SÑ·ÍöGå/^þÄ^•õæu—–ª¤v°¸™“Ú|õÖþ\íüþ>nc˴Ή͈*¹¬—›y·Ûgì‚'Ëõ‡5ë߬ºGÚ ¼_µkÖÃýè2€ç#bMNwFÖye`R$–ÿϦEݦœëL‘ë’5׫„,àˆÕ &ÿ~y9¶¡­ÛçÛèK6t÷Íê6š±ëV/Ååq¹¿c¨ÈgÝͳûåj~ru âÝ߭ǦÝÔMËwvÆ\2mÛ®šOú lë' Iì6ëv×-ˆ¾E`wí}³ëûÆ×»\ñöÉ«¿ýòâg?ýãíÓqßÈë–çœiŠœ¹i÷·í&Züó ´´n6EsÖî»íýÑX¼ƒØí»íX¹¨+Ï9Ò¸ºòkRrfÁnï›íâ̔円æãCʺ%yóhŠÍãív¹8Æþx¶ZÞ·ÓàêÊÏ<ÿµVã’l2Ò4ùbm|yG ó]« “IS¶á&'M{4›O½õi6ŸzϾ”›¤-èá³9_ÚK|™[“øòkÍqusrª´eªŒ†œSeÉšKJ_WŸ³¤Õ—ÔßÜŒY²¤¿'¡ºíâÙV÷ív×mj )Cݬœ!m‘!·ë›#¾~ìV‹›fû(/UEYS·à,¿$åé `6Xôá0;XêÁ8±ÓÑ6èlNNÖWÑÖì6'žìÑOºÖ$¥\ܬ\Ý‹‚úÅüÌ͆:ØÆD°}­5mÝšœÍ\ñ n~×Îï‡Öôºí}>Ѿ½¯7¶å¦nKžkWäÄdÅî ºK¨W¼ªÜåèä%åg½QAûô¦H‰ºM9:uɦ;Úöcï— 6@=?ïã 2t ‚9–ü%8h¹ÿ<6FÖ9‹É‹3·Ç¹~ŸcßeØwƒ°+c°F:=ûj°µwyæŠýÙüá!Oçœö÷´‰|höw×”)èH:ãæï¦TY¬\¾iŒ6b%˱:§ÆßR[Õ=ì—ëåûþ·ß=Öv­!ßµ†Ü]9¶ùiZ¾<97=Yƒ…Øåtä‹tôOw®ÛOÍ|Ÿ•ü¡¸ÛåíÝ>EÆW«  R*CmÅKâ+¹ty.óP¦ïÎré*G '¯²õW6×èóä ÚXQN^¾÷? ¨\H~n¡â{¯Ú]÷aK¿ŠD ¯??´~ÛUøÈûßvoz!ïÆ³…ž8=þhLó߈^>^ú3ÉãEÄ‹Œ/:^L¼Øx‰RâÏP,þ@Äâï5,þÂâï,þøÀâ,žÐ±xâÌâé5‹GÎ,Þ°xìÇâ'‹Š,ÿ±xÃâÁлa0ÒÑŸ#žM½»z±ÙtôÛª?Ðã›]÷2,;°¸ógq—Íâ–•ÅÍ#‹;7÷P,n{Xä^6;r;c;QÛAÛ8 ˆE–g±­`qEgqmeq9cq!aq `‘\Xd<¹ŽÅzÅ&iBùQlrB>ÌÞ¥j>Ñ™ˆøy¹Ø½‰¶ÅoèsÃ>aþX¾”» jöÙ¡}ìËÀŸ‰ÓSÅ©"®‚›:ß–qÉùT!01À‘Yü†¾Êì/¾b‰ªYâGÁeE‚,ÁT$„É*^¤¯W&HâËš>¨bé#(–¾béCœH›" [¨_!ªDƺa^ª`!åTR”c–~£›"AW$LvJº¯ˆºHL‘Ö ôýK_ÓÔ„‰Ón7}<ÓKKLv@Ø¡2¶ž;§jÀHŸ˜ekgÊN–P† “%T€¡'{¡å´…,¨"-ìé¦þëêþªyÙSã½0nHt8A+­°".±ch3Uf\›3hé"´ŒŸ,°ÒvY1U‚å_õÔå¤{ûïÒãµRʶ¶Ü36GU$¸Éì)o±Eçˉ©²Üh1‡ØእàÌdÑãRp“ú˜ARË&R—–¾£fé{éó ºj])çNAŒ«ùØS/§ÊŠ$˜yŠEïÍd:3ΫЖá|,kØN.ŠÆ9U`¸¸¼Ë±W1‘iIá"M¹ R[¾‚ïÿ¸G¸(L¸ò*•š¶D‡Â=؃üӘŎ#øZÌÆÜ( ÇýŽä¥â“\N-¹‰6¥üJn& ,·"’ûɦµ"†ç­HJGú_úÿ3&^Ëý½¢fΨ¿—Y )SÃ#c+9Žº°“ešQÔ‹› )ÂdåîBJ9U‚_uÉS´E:oHGRf1“ÅXÉj¬üذq¬Šô(e˜,ð„T™N:¤:˜¤§vIªÒ^W*7U—žTÁÈU¥µWj1U´æ#ÑbÊ9Ìßá€èp”ΤÊB¤UÑÎZþ„Û9ÊŸPÅüé0Y`¥Öœ*Áˆ“{æp8VÌ´©eZè±Ìq¦ËDjùdaÒByð.&4qIsŒÑÿz“ endstream endobj 529 0 obj <> stream xÚW XgÖžœŒ–¦­e,´:/»Jk)hë¥^¶*t±´ŠàZYA‹ƒB!€ H¸'9! áb¹TñÊÕ[‹UñZ[/kÅíS·Ý¶´Öþ¥ÿ¿êvë™üŸÏî~1ºÏ²Ûÿù7Ï3“ÉÌ|ï9ç=ï9߉Œñ÷gd2Ùãñ¿ŽŒˆxnÉqq‹W‡‡yï½A,ÿû¥§u”ô #—Iü$A.úO`Ù²'¼çG£gæûǽçgéIyu,ã/“q[ôÖ°°™¡aa3–dfdoÔ¤êTÓ’CTásçΞ®š6WµH«ÎÞ˜œ”¡z#I—ªÖ&éètU\fòFµ®@5m~ªN—õò /äçç‡&isB3³5 C¦«ò7êRU±êuvž:Eõjf†Nµ,I«V=t;ôáÅ’LmV®N­z#3EA}}"Üo‘߯™¥L´l™_,ó&‰IfÔŒÆ/ÑʳåùL! b,ó$ÈLb&3S˜i̳Ìtæyæ&Œ gf2³˜ÅLó*E1^c^g–1Ë™fǬ¤h«˜ÕÌf¢#cüé?Ê eÿí—èwQ-ß"ÿ£ –ÿÉQãF•ŽºÊÆ°§¡Š¿qk¹Ý£ÇŽ~{´gÌ+cúÆüõ‘Æ.`}ÀÍGJ¥Ôƒ’ûÜû-2ÌÀ rDOÿ6ì^'äCµ±¤¤`«zÃ4#W°¹"CÓnqtÙv;¸{îŠm© ¹{YWtwo½ÉzïJµ·dxUò‹_ñ¥¥`„B®\¡q•ôøÛëtw‰õ h‚·óê*¬i¹cÊŽÌb1Ÿht÷îml>uòÔÜàP92UH…ت5)e‰š‚¨cÑAµå–j;ÔAÝRßr¥óÐà®ï‹X&B´:jy4GÝÈý[®aÚ J8Uþƒt‚w”Ø ìPcµÙ_» nà.Ômú­Ű&]“™mÔõ¦-&ƒ±Â•°•+Pl6›v GØ›®Ø…QKÃÄ4Xdú¨¬Îd®X™É¦’סŠÛ6ô2>…¯üî; àÛ5çÃÛ??ÒqÎpø"™ì~Lˆ ) ²¶Ül┞ÍЊㆤ¥-2)Ã#òE‡3( ÜL62 è-¢¹w;¨jå­ŠËÚ B7»öBÃ>”á¶ó¹úT{þQ>É6ì€hXUnî#ý’o<âîutsfÖ–F‡n˜t-ëµ8„僨’Ýĉ8€¢EÏk¼¦D¿A¼7ü 9ìïñu7.'±mCíw­'à:‡Qd#$ äyrŒG ŽVô!gxž°ä)È G.ðXŽc](᧨*ÖˆJO\é-©þ¶ì‹!'é×ñô§väÖVySj›Ílm¡‘š­&k¹%¦mYúÂ@ž 2bÄ' ‹ÕâW0Pí]‡Íhð2Zú'T cç-Ù‡83±Hx«¡®L Ily…±DŒPTÚªk…/I [VUYDQç¯ü †úܘM!æ[i1XLJ©ÍZS·ýNÙf®-³i›íWÑ÷·O"Ïlø‘c±øÜÚ¿«SâÐê™Ø"ûŽ* Ë=Oóû*šÖ «Ùô÷I_é±ú^¾‰ãäÒ\)„Ç&„zÔ‚5¸5Š…el!•C^>ù„œ ÂÝŠû`G‚uúÀp¾åAhÊk„·!ø¶µv‹JéS¸-}ì5B=*»ÍK‡?çÞòáÔ)ÚM;¥§ë¡oI2|Lާ=“ø¼Z¯å^¥&O‹D‰ ¬ôð æzA§` •òñÿQãp/àãÆ-¬HÅHÌ£0›P®À9ä@CŽ Ú øÛÒ {Ä{³ð'sqœ¹ÖÄ¥1Å¿!y…;$ݽŸ#<Žãåž*'ùm³!´`”„K?÷gAš32…/*ˆ_^O"‹‹;Q+(¥6ý Þ¾$Û‹ãp”Rð 3Èts¼ñÕQ™yeUÐCEí s¹¹ÒVe§B·ÐÏáwµ}ÜɦM1bª"•4ÉÔÈÓ‹¾;ágÿ._‘fßzPèñEIÆÿćNCRVw¯ÿƒ¢}—™¶Ü"ýuü⺬Çk9ñ®ê÷ŒnÎbt– Õ´™•–%¬Ÿ Üd¸}ásÛ—wċбµ[[¯¯¡U:³µÆá„©¼’U­8kÐ[óç)T,…Âø>þÝøSЦҖ}ì}Àd©«r4¹žbçÆhi`„Ã’ÙßåÜß~¸;f2f]2@2JÔA£¤.§™ö„í´9Ú›oß®ÂB†ÿÐ÷‘u»¹`'ׯh{ ‹KÙ.úøIÉÏ?T5—’ðíUYÏö'¹¤Â‰<œÖv4%w§Ö&9V:“ÐÇÜïè.CwöÎ\g鿵©¦U zk²+ͼ¸µäi “Eøm›¶#§+­¯âŒ~wÕñ2XÇ%¤T¤ë ÎpºÊf°TúÇJcqI,½,ø½Îl:Uxš;Žc­8ú6ú68ˆòÙ7tHÀ iƒ­ï¦S¶JÄ_ø"K÷E6G§Ðo Ãx7Ô‹-¤–ýe÷[W„:8'ššmg·Ó©Àb´W¶VµkËh'1™*+õåY¹IÀå5_òæQ^ úç. …ŽØ†H©bijlD\eÀ€ï)<òÕjBuVû£ÐW¡ÿ+nóˆmBé)ºßdïx¢åždi1oØåmu Pb(~3wá:V; ‚*Û*Ú¡tP¬++ZG¥’Ñó°;¨´SïZ\>»òÀùÓ½À wâNØÜ.¶®í_tSÎN˜ÍAµ±GÈ w‚KcÛr ¸ß±‡ÁYï줚ɂkxñšl¯*—Jcy§»†fŽ;”…yŸ¥ÿcÔöÑ)z|^³¸–Žš–n3VÁÖऽÐ,àeÖÝ=½é!ÆÃ*c> stream xÚeTkTSW>—$7WJV¯m“èX‹‚E‡¢(BxED‘Z…@Á4>ÀŠ/8 Vª‚ÊãÍÒú E쨭 4R´…(Œ2kt¬è¸fÔ™Ù7=au:3kÍš?û®{Îù¾óíý½$#†adÑIË5Q~êø¥Kg¬ÌYBvýê¬ð#¼ï&ÈE»â÷b>=%ž4¢‡^#Ñnô;HÌ0ܺX¥ P©f©–œ¬l“ÒW;U9388È_9K¥ V†t…9Úô|e|º)[gH7ÑŸ<åR£6Gg²(}C²M¦‚¹3f˜Íæ€tCQ€±0kÁT¥9Ç”­LÒé ×é2•QÆ|“2!Ý S¾ðæ£6 ŠMºBe¼1SW˜Ouz Ù(E£8&-FI(¥£L·l&廊ÌT¾'âÑxä‹üÑt4ÍD(…£HEQ±Hƒ¡DŠ\‚–¢d´ŒâW ñnˆAb K@}L “Élc:ÜX·d·r·¢8‘UôX¬‡‰ ÄÇÅÏ%j‰^ÒÃz²‘l£°Sµx€ùó€ ðóæ °2A`šMð­gà„C‡Pþ±M%„²d‹+D’˜„öKIlä;^€2°sɤ¸á:Øà¥9ß–¢­|SÑ“ sð6p0 ÐBF£ˆÁk kÓV'—­ÄI8ú@zSÚ¹ø/KÎãNÜy¢ùòV2!aj ÎÂùûós€á_¹—à\PZl¤|.:b±Ÿ¯8‡›ñyÜÒÔÒ`=ÖØŠÂÉ„Ê Næ”–uƒú:üåæú DÆ)HɈ®¯Y /x஄‡G¼€x(È8¸@¾¤—lPóš ½_$È¡Ÿ¯ªÕÕJ@ø·>Oý“ÉrbÖÜ;|ÈB$±KY—¿ ã¡ޕ˜Võ’eÚPâ­9ÅoÒÀ©áç³$ÌeÚ¾)oƶ\Ÿ ¶ì\î£õ—÷¼×À(I ÕÃÉC*!¥Ì¯€¼“i¾‰Ô28ÃÅtÏ”¯ÆieɹŸÇz­k9qsW¬™ñ ”ÌÞþá*Âeû@~ÿ¡ª£…[Û+ o[p‘Áò›õúòM˜KÍiúRí Úk­äd‚™Þs×›ë™S(î þTeédóŽ­8²s*µ/ñ"^=¾·ðųG¸T%ÏãMxc^y}Q™ sË"š©Åï œmSœÅ'- Ê<‡2Ïmû§9Ù¦"ay|ªü‡Üﲯ%Zƒ¹_N%cˆ×ã) U´â¶šËgðîòÆŠJ\µÓŠw§e&—hqŽººÄ\u_ÓváÛv|ÛËë&q2h¦½ê€,3Ô+‚ãÿÖ1Ʋ=WXåûp>SÂÝšöwc.@꫘µä–‹ë¥}i¦XáuÒ½½O‹;Zù®ˆD¾gäåçpÐ6¬qÀviבÛ?>ܵ8GNÎ:¤2(Ä ‚O=L¤HLwNჂÙíd2æ 量­zcvÝ­ƒ:f@ðH7¨I‚DH¡œw@)½ÙI–äì”0½ˆûq8]oÌᮇ»"ÿ_… /ë‚~s܇(*ô<Œõÿ+iÀd2šŒyæ"`‡žƒ—œhI ‘Ð p=-ßwßü˜“h–Å*èådy̵A_Óç€":ÚüZùS¹­ë~¹'Ïhs¸'¾š£Hʼn–O²¸‹aÇT8,®>pú\æìíêÙ¾Ñq1 3^·Ç|¸àõ¦–s‡–HÑøºS!‡ÇC·ºVQ+â*s³–s®Hê¸hß3V;̳‹ OPñ‹›VU0ñëÂ) <ÜŠOn»¸åÊg8•[¤Æ%r-NÞŸz¦4Æûš¾í³‹t„zZû®)ð%ã©Oê•î >¼©jå~ÜÊ]ëµònÜl>¾‘Êù‰ÞcïxYÏ ÝÁ<úL`\msÏâ²ä.ùœMª‰¼!¿Œ/Ö^øÝ†Nï¢uù¥y˜[]Þ~t¤Beàªÿ¯=B8JN°aË I±Û¿’ƒ=”ôIç×Ý’ŸÆw«¯^æRijα¯ 㔎œgSHÌf]Þ¤+i¿—Ÿ\Ûøt¨½£ØTZ8ûÓ°r-]ßÑ™òmŸÀtïù,Œs…Kì·°°|vݬÒŽØ—}ƒlò¦saÃ!!üè5bÉš}R¹»Øbôµ×ýÒã-›»ã­ö=Žj·áÆØ?¿Ýë endstream endobj 533 0 obj <> stream xÚES}LSW¿¯¯}Æ‹•>ŒF¾R*„1ÝB¡øÁ‡d›© ª`€ÖÚÌ9P£Ñ^§ƒ]ªŒl3èP‡NØ2ƒZ@evtqø¹-›ÛܹõÒmݲ~7çÜsòûýNÎaR‰†Ñ–feƦ™òò$Lf’LtÏ“µ~§ŠÌDdCf+HK¦+g#ÄD„ȈÏMâØ´IŒ•AŠ” #T¿ƒõúD^ŸfµÕÚËו9¤¨’hiÁÂ…ÉqR‚^¿P2TZìå%ÅU’©ØQf©,vÈA…”g-)·8j¥¨Ô2‡Ã–_SS£+®Ü¨³Ú×-‰Ž“jÊeÒJËF‹½ÚR*eX«Rnq¥Ez&Z÷ìI³VÚÞrXì’ÉZj±WÉjÕQLÒ³”Ž2ÐJ”ÊQ²!»,{ BÁ(…¢çQšƒæ¡ù(%!#2¡(…(ƒ”( mG‡˜P&‹iV¨‹uŠva£Ø,ÖÌv²ß‘]2îq=ÉoaF¼,òoi ·P3¦É˜¦wÒ"˜GEÁÍ•žÈ)•m|ë}|C×0w°Oø¿ªå~Žî!Â;ÀŒ!Cú(¢ó@–q'×õ.>NUm M:¬Ç´k›i4p”†¸~¿Å<¼ÅBzƒx3%¥•·ÓÕ)NC¶T»‰ÇÍœöÂû^–äèˆwÝØ0¼”‹b#ÎY¿6u}úŽœ„)Óh:öê'Y—K†ðÜ¢ýjûð¾ëøgšé)‘†a(~ Å¸·ùÂÑá3GOcÂ0Í×âlœUk²ÅæÕoÀ²-ø"Ùvé¬ì§b„…sþ—ÄMÜæÍ¯¿AÑna‹ÓY«-á{ñ]ÂÄAªYß^¤~²mˆtö10q“íîsÈÌ!šÁ×á:g$û÷.zúûð=Ø%茊p~ºMw¬ïn¬kýó³n|=™IZ¼ªzEf–ðÔ>t¸¡îùØqÒ(¶^îíÄÂW]UF-Î\_P·Ó™³s«SX6ÌÿÖš˜ŸòZnš6§[ýMýò c›»eŸSÆ>ÖâEC/~|­ãä ¾"øRb"át³EæñÏÄ.0öĦŒ³„õÅD޾0ª<Üu0«à8ç¡fÕ8G/ø"¨éß*ºÓøóqíaîÞ&á·Ù»rWÀM<,‚pˆ…•°Š¾ 4UK P‘ŒB á)O³h6eçRQ«!_ËÌ]nØ;ÀÜñ±¤®Šnú%ì‘ß÷;÷ËÚ ý©L\•ù‚äên7˜¤Ï(KbåæÓK^ì~‘~ ‘´>`¼ ×@ω^Sù¸‰—I° ’‡àKÙ™¦‚¥4T«ñÇcy4ÄÀ™6ØÏ‹cÜ„Óû'äÀŒÉ¸AŽÇ¼ÓÀÛrýüˆö1#ü‹Ä¤$·ƒF‹†‰åžgþÈ–§¿qò$ £œ%NZè‚d7<쓯 êåÑÛ+>ßx ?ú~‚Yœ öMœýî*³pNž”—'mÊ#í‡å õ¸_‰›Ÿ‘fÐZñ¦¦Úöûšñ‡òÉ|/«Yð/XEü«÷Êa×; m¥ÂXÆD‡×T»ÈòƒPäjvq´ø>"H™Ü¢ž²OÔ žêòN=¿W­ö6©ƒa4ì'2k endstream endobj 534 0 obj <> stream xÚ]P±jÃ0Ýõ7¦”"Û…NÆ818¶DÉÒM–ÎŽ –„,þûJ²ÉÐAÇÝé½Ç{GëöØjå~;#zè•–'3;Ðá 4É JømJUŒÜZ_¸ýä#=Ÿö?ìüZ_®yöv¿5ùHìWÄm±Å6·G¶LÇV÷Ê’Ðkœ¼[`·—¦Ã—¸ûrÒìî5K6[û‹#j©ª$—¯–„‘8Y.Ðq= )³¬‚²i*‚Zþû+VF׋wyˆÈC „þ´ö!¢BŒúL*f炇t”.QŸ'³ÆFVzøÊo™ endstream endobj 536 0 obj <> stream xÚ­ztÇÖÿ ÙÚ¥°Ø C²2½†PB „:„PL÷‚{î¶\dKº’Ü{‘eËÙØÆ…¦C ¼B í%$$2kÆ/ ä/ÿwÞ÷ùøì9Þ™{ïïÞùÝ{g,¢¬¬(‘HÔ{ñ¼ÙV-;wÙʉ„S\±á…ª-ÁšDño‹øwºñœ˜`õE‰LýÈ“zÑGx~×Wx'QU¶”•HÄ("5&L?a¤¹Á[=½BíG¹Ž¶Ÿ8mÚÔqö“&L˜f?ÛÏ=x««³¿ý2çP/w?çPò‡¯ýª×­î¡ö£¦{…†~ôÞ{aaaãýBÆ{~2zœ}ØÖP/û•î!îÁÛÜÝìçø‡Úæìçnß¡óøŽçÜ¿@E¨{°ý²7÷`¢k¯žâÔjd·±}gP³û¬¤7vsMÅ‘O=(?Ê_Ô“J¢Â(†êNõ zQ½)ªÕ—êGÙRRª?ÅRoQ(eG ¤QoSYk(5ŒN FR£¨ÑÔj,5Žz—O½GM &R“©÷©)ÔÔTêCjõ5ÚJ}BͦæPs©O©yÔ|jµZD-¦–PK©eÔgÔrêsjµ’ZE­¦¨5ÔZjµžÚ@m¤4T"µº%¢¬¨“¢­¢v{&~O¼ßª»•»Õë^ÖÖ^ÖÉÖÇ$3%É’ÐFúwÆÒ}zwS‰=N÷ø£çæžÆ^ö½L½÷ÖôþÃÆ§OÏ>¥}~컸ï/ýæõ»j»Ñ¶N:@z¡jÿ² öþ[¹\€dI²2Ù/vé LÔwPÔ »o_zgå;U\®”»&϶h;¸×`Ü6¤~Èó¡C >|ø®}F ±WÛð7ÀÂ[[PšIôüò8÷讘_ÍcmÁ=#¹·ßÎP— ÁLhaXeu±¼ÞkÇ*îsptONñoX•Ì8̬ŔK¦û^ÇWé-JXÈùÒµºÃz³ù€¦¡×0 ½P {äè*òxý½Q·O_Õ´šÈ÷môlMN½× ç,²¦ßlù’;Uá:`´t¤&,@¥ ®LPÇBÄ1˜¦møÖ |w!ú^½É–X±ôáâsÒƒè1coF¬‹—ý{]x1m¢´ä줷4Z ÄCL·–ü|§é n;ÔÇC]4ªˆb¼+bKÊÊ ·Ÿ\Ý2{<¸ÿÀØW*¢£²CAÏsÒǼ”¨÷Wù?hO•µôÛÐêRô>ù. f­úŸ L#O ‹½‰¾Ù{™Ë‚J¨JHH‰Š‡ ˆÈŒ.R16m—_÷°¶K¯Nì)ùßþCðÜÔRacŠô6õŸƒÇM†•®Ñ¡uÎÆõÀ¼‹»(ÿ£¸ñüÿX½¨Ëè'wOråP—\à¦I0PäF'£ø&4À$B5f4Ø,æ½Ûº³{]šVº99®ßí~èhsÓ~nÜ"Ö) dïÞJã®]Uá›7†9Émx5//݆Z?·­E½¦ËÂCúz—¿Ãž ÙãäTXÏ!?;=]§×éHÜê!&E>Is—.‹‹ ¨™¤´”´œ[ß ZóÖ7Ñm¥Ë5xäò_«aÃ˰¡ôÅ*£èçbt'±`}dî‡l}Ð @ïš³ÍA}P¿¼\ЃÉH1¨¸x˜¸às,]‡»Åa1L…9¸÷Ql} ÷¹³8˜ôTC†üõÚ(Š,Þ‚ ,\S¢Þ«‘õrÔgÊ—ñÀ¨RRTrPƒ¦$â§QÇñdÀî€gzàOq_lÛ©¬*5%ˆû_DÒC¨[.ÃmâÌâKÑž&´×(â­›Äü»(’E5’ü0Ã!Fà‘ZI>”„…Ax ‡kq-aa%/Gä/I „P’/Š:-%€vïÔQÇž iv}…g!ä¦ggêõ2N#‡%Ÿ9nR©o¤t`™{ý:¢ÉBËOˆrP±U£åì \¼‚&kÃsÑçb´ú0[Rîïâï_R]]^^MÀWwtŒ æ·mbÓòü™œ„,%)ñêxü÷?æÈ’ceVB—©Ù†l†LV˜Úd&Qã-”yKÌ;¡K,ÜH¾áuyóÓ a9Ì rï3?y| ³R'6ÏÜõÑ¥°p¾)ÝýCÍù´kpÁžøëŸ›#~Tž‚‡pιÌ#%¨ç•,3Ô¹ˆ’QÙ«`&,…Y°@¹$zÜJ¿- È&üÑ`ÙM\xYŒöµõgËAÊ-[2|€ñ¥d©Ö ¦½€öTÇMä||%u†»ÐÔtêÈžõ¡'ªs„mWѳg¿Xl>CŽ‚ÍzéUöùS4q§ŽÀ;$™xÛ`ëÙïMZu Eu¹Í^\¢Ú²/4œæÁ®¦ÉáãõÓW/ë±·L©$_Cé3ž–T¡9ÖÁ’d¿$Çøè¤ÄE èÐ^Qu1hXêñËfÛdõÁ¯èã‡3ŸJ1…v¡gìÍÊ<7';bæò™Þ¦ðj‹ÑT}pDs–çòêi>ª˜(‡8ÍŠ G¿[ÕÁÚDmˆ& µIZˆg¤íJeq»%7ŒÆoÏ÷w”;Á¬"¯“uÉìdêþ!>1Ž-B"dóàÁ¯7—^ZÚ‰/há Àû®€Ñ4ö}ÚS£œÍmó•4Z¡¥å04¿N›wŸXFò ìéQ\‰•Ä8|ª}«Ì—FfB‹j RóÝ­; GÝ~BK Þ²=øóF ¿'ýw@›YÔsÚLqÁ)ÊÓ‹Aki£ª6©Ô烼tuZ’\KPMV‡%l[®°9cSi¢ACÞ1ñ%ÇèHÌç2@oHMÏ)l8ò-´‚ysfD¡‡Þ Ö3ÒàËCœCÜ<‚6ÃXy8ò¤AkÐæS[d./4{Çx%mžr~ ²’KG̯?"©¼Cg~HÙ­MÄQ÷‘ÛÃÅ÷¥íH†¾eËi”ŽúÖ"dߢ2me¢]a‹oy´©p{Vã)Çýâþxfq\úóé#$þáïd¦tÒXÌIۀǺ° ꉯ°KÁ bÜ€bæZÍ“ûdËï˲bX`#¬ôô[¾99´3|Jù/¯ŠŽ™x(æùçl–ÀŒ¥ N‘`Ð䥔0Áoìbm– ³Îäåf¤_ƒ<¥«D5‹Þñ o,‡áº-{÷žlî G G3¤–åßÙýEgŒ¢¿GEÄꃡ»QÅîЃÒÇh*¿™Ý¼=e1§¿l¹xéìÚ¹¬t۸܋1E³_7h…sÌÃIÇ'Œühöx"ô[Z6åÄ5›#éÓþSVÁ(f㓟!ënýÎA½r{KxiTö’&f¤3‹ų́ ßçŸÙÍžµvÚ”¹_ÜâàDÍÙïöuêSÿðv?LpÃâ‡Èí> 1ºÈúÐ8vèæ\$8èw0»3«‹,!Š(¿·…G\¾C,²Ao#âdÂôW“¸Õ°!Âi‹Ë–Pg˜Åà~ßFVœô÷ÓÐÜRv‚Á}?a£`3øž‰h€ƒ ðվ҆ʃ;óêˆCj·mÉõI] ›™·Ž™Ìuð+ è¢XÞæ_9_³úWÞí`|4K˜i{çy¸IúË›'K…·‹YRxÎX2;)ñuêüúbª5—^å‡4â.C—£ÏÌr²kBã›DÇÚÞ·ÍE7Ø‚—i©ýGIW*ó?à5lWŠ–·ÿ]ý2A‘R…ìÿõ~‘QTÓ6[Ìi[Ê&çi2¢ ÔªäìÚþƒ,bk´ƒ–m™n—¾ÞÒª©Ê¡õÁæ 9tÙ:ý^4@†@r¿KªH¤Øù­‚@R>Õ.ÀÎ]{µ-d|½b2”µ 6ñÙ¤ðÆ×¬±BbÓ¶Ž(p΄-¶H~ x<ç áæ`¾‹´t­>c‡úJ×}°fɆ©X,À>.9.3wß»‰ßâÚ»ù–K®ê•žòörZúŒ×'\ˆ/ÿ¶ÙÝ¿÷w9Üv‹s™eø:‹ûI6i2jå¨}NÿÜ2~á§k§ #x(,mïZl=å}êHbxt ýÀbWôžˆ>CSBrÄdCF,§PiãñPûiXÌgxÝtHN<ÚŠÖî8Í!Ü›`Ä#ô1 Î¦ ¥rOA†’KB”ëgË<ê× Œô^ާàɘT|m©`iYDˆ»ÃKŸˆëÚf²¾åôK“^ÔM‚¦#BŸ£•xšˆgÊqÿسñ;;‘z"ùÎ+}ºëó¬)0°8|¹ç†°À•+F2i›N€>eAµ;Dèí{hƒ5Ìbôö5ö¥Ë’”C’X0:Ï"U¶]dÆûôãŸäfT,™¢ôÃMDI’N÷°R»U®.ÄrÆ, @ ëöS/}bÓfO„î³ ½BW›ÑPR_o›Î¶ï}å¸Ò—V’Ô} ›@=‰ozäÕÉ‘öýcöKÑSã½ÇrSPz—è^4Ì« 1GDÛ´™–# ¶ðÃ;ÜùÁ=¯:i4ÿ ›§hr%쟙r4‡nLMû’³ÐÚÕ?×À³×0ßú¾Aé!_BK÷a+,MXŒ7Ô¡CÄ·ëkOq¿Ãƒ‰F<ò/]ëSãpdì3üž„±3zOF+åÒèKp£bÇI¦s¯}aA;,`´Þómü¯l½>ç*Wn‘x©gƒ»û,ð"êtŽÅ­(–þ‹¯C„€wvî¼ÒQ÷„ПÉ V\ðW#lÐ?ºÂïí{b¤Ô1ä\ç*aÓÁÝmz‡° úº¡K˜Z9 –º;¯w,DOW KñÙ Ó dÅo³ˆš‘}GŒŽ¢Qì{ëW­áT°d”Èùt%ì{JÂÁK»Aãí½A/D?…Mòö™4 EEÛÔ ÙêŽOÅmîè!‹œðXÂÜ‹ñü.~»]8O@óÑb4MF[8üþž‹~òQ.ñÕ­»hè§8 ãw¦¾'ï$ÉèŒÀÇ÷о§b†Î³h†õBÔ·O~õ=~GŽŸÿ)éüEä¨Q‹Ê:¹ùžM†Á6¦ðd"(Ta"¢›P+I|ܤEÖ3ŸþXAj—Pá\*—†2È5²õÕ`æ>²JÁÃç‡|„GɟIJ˯†kÌXräðßÞ N½á"ñåÅ*}È鈦¥ÿ(„¨ÛºÓ|a!,×f÷fÏ£ªíÀ\+ºY•9±r’é´IªO½"‚IIšx(æQì YÄÙ µ«KH}ÖJòå„*ÛcAgÑWg×TH/¡_y‹û[–¸vŽœ¾Æ¡Á„?LߢSŠPo¤•ÈÑæNÎL­6)Îk¥Ì¯Ú¥y ñÔɃåðáá9×sRÅ] 5ä£Ê¤íIU¥AÙÞàÍ|º~îTÎf¦­9°âˆú¬¶^›Hš&’"äx I9¤!Ðé3r@g0Ô¶l=ëyÂÝoü„ºÉ¥—àÉ¢›Sd{z~rZ)šÝ ª7£Ì{(Ó,nß6mG’p¬ …t>šRP‹ÆB1T@¶¦4”Ê`·BÌÎUè‰~…½{ŸvôD®ôÈß!lâ¤üâÔ}%”™\à§t䤂րN.h³\Åâ!c>· ÷0£•ßï/‰©7#“é¢áþ£"$1! št‰®…=ÂæðÔnÔlõÚ¨÷|µ9©¥mƒ-¢’¶â6“Ío¨¬þJÇXh_«6Èo…>Hܪ- "’¨ViTxIû6^ÅëUù„‹õvÕÇÁ,,®žî:ÿ’—Û_È2ÂÓÔyPú´´|ÆæEn§¼â!⃉¼â㻲ÈóÓøjýü—tÊû›Öè á R'ycÚ]dø}>V›ªI‡4»í' ¢CÞ‚“ÞEJ!×Ó4O†åí³ñ^Iš¸ 0¼qìHMÎõ@›ÚÛd†C|32RóÐ4>M†>jOï|i×ù–yE_åm+Åüþ-½ƒ6›jvÔÜ’‰›v“&Øu#¸v&“‚ ¯Ñ$)±Ïa9h É™jG¶hÑ.W/õp÷]¦ó 3Jè£P’T€–b‹ ˆ“cÂü6;RëZôµ G;6%½YYI¢,Ëš‘ƒ† š„õ)†PÛAœ"ÒI¨¸ë —`gKgN¯…miÛ,¯µG·ïˆùßùÛlÃé“©5Ðåß@ß.ÿ6†‡ÉA©ŠMQái¸T†¡ýIÙĽiv¥æÔ=Î7çÍ:g2¼˜þ 2•…AÈÿ ÃkßÈ$¡ô'êìF9rœ°¡éŸ&êÑ$F™ØÀ6y1îq~çhZ8ÇäžF­aF[4Τ@½. éÈ̯b+"+=¹0ˆ‰W©´áPœÑ@~ªj2¾>óEn×á_rj²òÙ¸Çòò-»êŠ++„ƒÌÿnâŸTíITÜ–Àâw\ÿ1nŒ+zG"s¾Tõë%yÒ£ý·JÕ¦H ò1UÜŸøp¯É¶åêÆ‡hêùKf©ßatç6ÕµÒy0¥§ó¿• ^E¯V)½Sö¤qhMˆ¹Ñ³Á­q}áFR&Ìß´ÈÏYQUl$mVnríf]eÝâåÇÝ&É=hé®ÃëÔóÔKýfm ^ ŽÌGƒÏpDÊ9ØÛT²IB²#éqs·nÙàRwƒ£-·Ð´t¿•&e)?Ô„¢Ëh¿R4Çd[u %œë8Š´Bil:}Û¼˜§Ùx›'lN™M(ýÙá1)™÷†á~rbóÀgclö qIv¢>Y°Y¥Iô6âa=¸nmðÛç ž±A':o„Þ¿i!«sïŠÑ\~.‹úûýûw¿ùÆ­Á£vͼÖ æ0ýÿÜ”¼á ]A‹°Õ±KZyâv‚2ÛªÖ°+hΕºVÇÒß•(Íb߇'er¨ÔÕ˜3sËªš€¹ #Cå¨õ‰NŒ p% 3n,¤BY‘±1 Y]Ì£óç¯Ê¡!ª!¸¬~G}Z±ÀZ`Ð*S’•ÇDæÅf—d”ÅÕ¸‘Mê¨rvq®u6(€?þ'rp4¹›·ÅFGxƒ#m£À7Ïݶ<ÒÇ \™¹?¯F6¨Ço‡®qPsh]Õšªðƒ$é|R·Y€xw>ÏŽ˜è°öîlØm`NJî +˜âðéúÑòΫ¶Žp¡nç‘ûy1êö ÛTî¾²¢U³ãõ•ÑRú·‹ÇΞÉqXÉáúMãÖñÚí ZEðøÖÇyWÀTp\éΠ§Lá$Џµõ~n{åù¼sÒGhÿ‹í…_f©Hèš^ʨÑÑ—×ÕuÊX”’Ö(—þ’Êïdk‚K|A¦ K•¹´†Pä ìl*üžéX×õaë³ÅçH-ê!¬FÈ%Úl%ÄBXLicú/h¶‰ˆ#ÅçÄh^ÛböÏXôïï»n6[&ÛÎ ¿Ò¤M|ÌâRú ÿ1swvΘ›œ–1ÒoŸ‘2R°Jz Óèλâ׺K÷ü_(þf…^*qõ•{º”P+Íü“ˆÐàö[bÞy³¨ÿÈç¸7î7‹屿%ù ÷/?!)‡ƒð&Ö K÷ï†ÓPp¤|wåÞ}¥M°v)*œ*œ`¸ƒ'8([ý× 'è­x… ¼]K°¹+Û=&Ù®{®+ .f¨åÒoÛ½^š´Cת¯¨<ÔÙ¡vš>΢ӢZ¾yÇüŒ­äÒÇ3ÀÙ1LAR`‹BèêCªséôdl{Ï›:[î îÆÀf’ðt@š¾¼K›1fRltf¢où¾§Y¼àßKç+h÷ ÖÒDZU.g>˜rÈüî÷xbˆâ y—©š1 _¦Á'"@㸠˜9ŸÝ#™¢ç…[—o´¼¿†>è¥×ŸŸ{~Gz}Œ¾cQ7Ë_E¼tÏëxã§n¹÷põz­ZAL@i´©Øœ[Sã[íÄI¯ÎÏ…1NÄXNiâ?(±­5ïGæÐýÒ{È ­aM)7£`.³ÎËu7<‡§ÎӦƿìåd½\èt%%z"¦¸d·óm)žÞû·¯åpØo{\®w[¦s& ªU9 óàSWÑ|‡CÝ m¢ÞW—EÔëì8él8“IîS§Ä'¤¨Ý«\ šÀhã¾p•¼ *Œô^MP•ê뢵Œ¤ç‘F`AE¿GÍb4[ø_•¡<- –h§ùÙNaßáj÷yW±êâYîxðjz¶Ÿ»ÇBxPĽ¬8¬[^î¯p~Ðuv"†½®7ö D㑯ëùôûÌ™š²¯•Cßu}¹êIr<†žÐ8N~ vWU w6夂Hú;>FÌ¿î°YeE»Î ܪñ׆†lÖG Ü× Í %ýV‚&%E9gʰªQåu´wPLê?í*Mh «ÎO~RUy¾$õ!YzŒ>9ò 5+5[hš;Å 7ÿD÷Øâƒ–¼:Aœ‚ˆSøoч ó뵦ðh’c'à,Ù(T“’«ºÊF0iþÚuš?ÿNi P¨ÉŽMSåøe„OÁɲqȘ,TÕ©/Gwè–²F×Ñz„\u®²Å¿ËÒb ‰‚núô´ü_P½ìWܪ^Ùå¡Cß®L#ÊåubÔ„âØí;w(¯°Ô7ì´Òø‘&x>VX¹T“ Q›¬Z6C6ã—¡CJ·ƒ‚‚,cÇhí"MÔ¶Mº@aôÐi÷-ÿ³²wqÏ+>×lúº ½EWQÝ¢)v­Â”G*+Suí鯿)ËTæEL¢…†n»î˜ÞTÙ¨ÝÞyh¡­î gSñm^A\z[ÌO&Wœ9¤+„—ؤWâ-ÚÂH²ñZMrܬ•a12¥dkR j PÂujùÒ£û…†Ý iÉ’cc¼U±ŠÕ󗀾Ë-©™&(d* Cñ~[Z<rg ùxùq¡J3ßß$j1£/Ìb~ ?œÍÊœÃä%B‡/I”xеY’þkIÙv ’HpM{ïá><Ù.&ƒ¨‚nIŠÐrë`Iî±Í3B!-±yH1 /¢Ä/¢P&kú#JÑÑ,ž{"zúäÑ1räÿÉ–‡Uø(&EÕvcE9‡ÞªR˜ü‚BBŒAÛ«L¦*ÎFaâç!ÿœt“»äÒ–ç{š²zõ:oìÕ›ëa5ÕØ«;ºÓÿ.Ìñ' endstream endobj 537 0 obj <> stream xÚ]P±jÄ0 Ýý¯”b'C§(q¡wm©ï íæØJjhlã8Cþ¾±/ÜÐA=½'é‰6﬉@߃S# Æê€³[‚Bèq4–%h£â^å¬&é mNÒ¿Ê ~Ÿ/ß÷ÍI|ìárn‹GÐ8\)çÕ#”{Ýq±Î§ÎªŠÐmâà ‡'íz¼KØ[ÐŒápiDFÄâý/Nh#0R×y\q½I9³— ƒ´#’бª¶­ Zý¯·+úAýȰ1ùÆ,ç™»£I•üÝì©%„mo~Bv”–‹·?yç“*ÇÖAm‹ endstream endobj 539 0 obj <> stream xÚ­T{lS׿×vìH²RÕÓ‡mº––'°AºðˆØhÓ„*%0A^Ř›Øcû&®ÓߨIüølǯØI›È¡,%*©M[MT͘¦ŽiëZ¡iZW©R…ÎuŽa;Æ¥tšößtu¿sîý>ßïü¾MI$MÓ%ÑØÐòÌ®=Í«4¹?µ¦;ûV¾É¼U Œêf³ÎÀrvõúZ=Çõ>·q£Íf«ÔöX+Í–®íÔ6§Wïe­¬¥Ÿ=¢Þm6qê—´=¬:/Le~Ùeîéí#tÕ{ÌGX‹‰\5%*¦¤¢×RORUt+ÕI¿Ju’²Ps´›öÐ^ÚGí§t£Ú¨ªÚF­Q4%¡*¨zj™~šŽ‹ Dœè3±Sò„dDr½ G*–>#Õ ž’Ì4HÓŸ Hœ)Gò©iH&í0 Êž‘ØÁf›†)U z¼E߸%FûPP>g5™¬V“iÖ:77;;§$‡ÄRž$Ê›X(C§ä¸ µ:Þ€ ʆ†œ¼ †Þ8Úp»Ãó^/ —ñãÎqeDµ¢VÒa]À CY"‹« cž/€7¡ªƒWPjP„ÂoN„ÂþÀØD˜¸+æPºÀíæy¦deÓ™›iz)¹”¯üœPE“¸iñ(öTNàIÔµhyQÒ¡„2Û”Ý.Ç®G{œ¢ EªÇ{1¸7á£*rAüxU¦7Ñ*M¤nÞ— ÏHñNü(.ÅÕø'H‰åh› ÍHïû“Râ£B¤@!)y6ªpäv½ü{…éûÑ÷°RÂéd>/[„/åñP4‰ü…GÁév{³—ñ¤bÀå8ÃÓ#Âe<¡˜@˜x,§^̈f“ȧÂY[žp? ª² ÒÁþ{¹ý/¸Ÿ¢?É'ÃáÄ`Ü~=’½„&oDÜàÆáÊåÒ 3Ù$›Óç‚‘2>æŒ+ƒ$cF8ÛÿÜÊ`®Þ–VV‰3$õ¶OÛ{Øu¬c·«|Œ#QåäNÿú£/PÁÅÄX0ˆŒ½þW¦pñeÕz¾à0.8Tà5ž!Ù3§·›¹ýºÔžWtúªAÇåïŸ?y.:qáZô*ø™„\ÊðyÝv®¢i+.h㉘0 Ã!ï¸ûÛCËÛN`IÐá÷LM@‚Ô óªvÙöŽéô¡y&S%ý2&,ùy¡lž^šJ¯ ¥3b!„fåûçxÓx¢ùBóô`pá,Â…Xö))!™ Éàó/ÿòÞó‰ÁS–¥Ž%û`Páu$"å%«Cb,SalÕ´üŒyÛ ?÷‡O¿AÀÜzïÇU/<·Iõ2tœïOYNr§^ú3³ûüð®ºu˜¬Ýÿíß¿^þìoªá‚6Õ¢÷¸ñ·µLI¦R—&:ÞçÄÂ…ÿ˜µÒzɾBk Íê½ZŠwàÇðÃx3ތȊv¨Põü)^ Xö•=’ƒèK $I× ¦´X@ÂGr’@› ìv%¾#ÃOã-Ý;•Ðûåo¶/ÂÇp’A·e߇dE2¼=[Ö ‡Ñúߣre‰àÁÁ”Ð9+ÈD2.‹Ñ‚p[é·?Ft$ä'ƒ#Lúxe9høêüš Ž@·îU½‰õöùF}n7ŒÀPÆ}Ÿ¸/uÅ[‚<)ý.·È@ ݗس=ŸðgIEôØ8 õ7޵̻≑ê_`P§ .º¦ºçûS¦qsô¯Ç.‡Ìw¬ô)Áʳ2âB9èŽ6`z8Éðqˆ)ÿ 7ý×DX…ùô¯OÏ Ìøó¼óhõc­ ü¢'žG#¬ÎÃ|ëÝ©Ýã`œ<½Ëþª{±{â@ЙgOXµGæ»SýsC¿rÕp]íð2C&;aµÒL„Z£M™ŽûâßÙ,³ƒ=™„ééï4ÍÅ- ¥bá)Ü/½š¸7iMà¬ìTŒLy"Ç€á¹AáoÈÁ”Xg3;ÈŒ|4.S®’lIFŠVù‹V§W¥W§ß**"o1ºñпAQég endstream endobj 541 0 obj <> stream xÚ•XiXg¶®¶¡ª4ŠJ[Ó…FÁ]Ü’˜¸¢h¢â‚ (B@‰ì«² Ý}ºÙWQÙAhY…ã×$7Q'17™Ì$!‹‰NŒ‰9Õ~¹÷kˆfœ™ç.?¨~¨úêlï9ï9§Œ £P(ì<6m\»i锥nÞ3]­w^Ú@rÆØÌé¶òóŒt8Ä1ÙÌHÆžQ1£Í<ËŒc^dÆ3gÆ…™ÈLf¦33Wf&3›™Ã¼Ì¸1K™eŒ;³œYÁ¼Î¼Á¬dV3Ìf-³ŽYÏx2˜Ì&f3ãÅx3[˜­Œ3{£`l˜<æsOá©(4|P—’U·YdsÂvªm ˲þì).ˆ«ägòÏl2gÈÝg<žù|èæ¡=Ã^VkÇØ}:|ñðÜ#ÞÑ7rÝÈ&û©ööU³ê§Qž£Ú„•ŸGoÝ,kíÌö á #LЇÈà›È(åóJ!]¿1;öƒ2¡E‘<M^ œè²Xóy°\Ã5N»ºztÍCÇKËñ¾ù¯w9r[+Üã~¾{èZõ­NMêuº}©™É°Rsã*Rò²A{ygÎoº*>CW%îûDè iñó ñók éêjiéRÛÉ7INÕ£ •Šë²§R6š× y¥¾roI²:²’3“-Ãÿ>Ý!+2AÏÇW¤•«« ¯,ÿO_N3ÉߘÝ8 p”R®Ç›Â]=fL’©'é“&È^ÌÄýFÜó£šdI† Õ)·ÒÏÀÏpn»…gJû>,®…БpxûÁ7a,̃ àºß+yúêäÝ`U’œ)¬T`*>£Ä_ÍJ¡Š#ÕiÔÇôý =ÇCðñšJ¶Î.æ-åDÔp'sBoïC8ICFœ8«‰ql«¤¸ˆãq9Ò*Ç(AÃjãÓW%ïOË\LÃÇVj;ÓÕ}Ù¿\—à{¹ÿDÆ’aÓÇŽÕÕAßÚ¸Ý?$Â{æÝµ(àŠ[?~£¦ºá|ØdBã@ŒQ!Éî4È·p¤R^®Â]i²<=¢Ë §y ×§&‘Ÿ,o8h°ƒ(ˆ†kÍùºÚ¿„àÉaéX¼fÛïöƒãM_ãû‹øÜ+gqŽSýJ#î+ 7ÿ;2Q›µšP¸£Y%ºfàÑù[´­+Е¤ŠZšÓiÙž±›3ý`l>Y”ž£7hO†´½"éæ!¥Z]ÆÜ‚¶žsÅÀ÷Áì×DÕ#7p!CÕѰ:Ïÿ¢ÉØPK?ëw :É+}ÍKŸ¼„#Ôª_qν¯ÑNì·˜Náˆz+2j\ƒ#pŒÊ‚«ñ{á0ÈVu¨•Ι®À!hÖÖÄg%FÀn~gMx[[m}ëUÿkcÉ2o.ÉS«Áü¢×:–K‹>Žþ:#þðg|œo‘a¢ÊK“Úÿ ¹&xAD[FÅÞ&¸‡xyN:ÿ=,vq†%Îj;³™á,É++æ#J9Ì%sÕ–åd,}¬êÂhä@_ýËW÷Døaîûä™"~.¹.ÕØ›ÙJ Ùï¸?BŸ dO½‘&É$Åuœ&k{•æóLá0%ªÓA§ËØÿÆ:Ó¯ZAkÒH¦‘IÄŸøÓò™„F\‹¶8¹Êý†=b ¤ƒ~Ï~ò¶ÆÀ˵^W4S?‚¯áB2×Þ{÷½/KÎ2ðý¢j¢ÊI0èj€¯7ëE»G¶”[ú$u}Œü,º(ÑŬ,}Vo–r¸'S5»0‚LFl-nµ–>AîCgî=ø<¡×½Å»pL¢HݺÍgÅì½k(g™³iT[$,>k=çJJs0¡\KÔ᳈õi*¶œg(ö["Jجa—¤ûMVoÄbœÊâ\¨w« Ãx‰} 3mSXƒü9µÉlO ¦¢k$¬þ]ô _ ÒÌóËORÈïÃÉ^Jýô÷<Öœæ~(z¢*ƒªÚ‚ÕèdUU³ðLUÙ=“&Wa $‘ì­˜LÆq[{UIæ±g…ƈˑÀ—CÙ}?•¸í\?6 ¯ÁñΜJ¢í,,0&2)43æÂ܆­WýΧ܀om*ß9ÑÛ~úö‰à×C¹§Aw{gi± žÌ .dñÁ d–ˆª¤ãðÀxú*¥«×ŸÀ6N‰2d%6@; |}'A€Õ$–‚Èj¸Žœ{ÐÓs:¬a`9»GÿþæÄ³òoV¢ëBì—ëÓêÒ I”5„—YˆÕëõÑZ­;>ÊÏ‹ÐÖy¦_N%Ÿ=†Dce$¨æeÉÀaå^Q|iV 8VBáÜ"l’‰ƒ¡?‘XSÎwÐÑqLVš:ŒD"¹XHƒ´(Þî‘Ãc_ÎÊÙg•xÎ}J–&,v7¬…ôYº’ŒôyÉnlô« !°§<ø÷.ûëÝÛîâwv«nÉÎò,¶æEšáŠc×Ñ«?ª?…û;kȘÜhÐU_ y5"®¨ ÚŸÓömÛî°¾ge‘•\–N'ÂÊã¾U±½[›÷£"šW}÷UÂAmuܤºHðå}"—¿¨^djeNÒ‚¼Xà£!3F$+¹H?¤.£±° §Çá½­ßeRwpÞU´½/ªn*_ýÌõ0µÛœQef%E½ù¢Òœ ÿ&ä—åÝþ0Í0½.b‡Ò ãŠþREÈÖféµd›ÅÇ씣mïXÓp ø¾ !ôз6ü¦(LÌÍ8 ŽP%µ´Î/dšvK¸öN3Ù7áà…t‚›ƒ¬*Nr[x |VŸb+K¡¶&RÄ5úV Oé¤oÙ»d’'±Ëž½½%áHcSU§ŽQßGó› ¥ÀÔâ¿HÜI)k™–¤™ÀOÁ‰¨UqŸ‚ÔQÝÉïÁ™ÂTnÊŒ”(ï-'Õ´wà¬òÓ9V¤¨AUò &\Þþ!²˜‡£TI¸Kž `GÜ3l5ÜÕ-w%®÷‚­ª·0£wS Þ¤_Ólvœv‡L Dæ[¢ãù|BÓ<—;Òrªá<=cd˜»Øà› îxnŸuÐ.Ìl—‡·+Zi¦»QÚB‹=Y±„p„'Žw¦ât|éòå4Õ‰tCÈJ‰\í“àM³Cté¹8±jË´¿»&ÉÊ~׬zòh “ä—º„­®Ê·•8ýÐ&Ê¿ü£›Ä‹SõnióÊßE¥:›M§W‡o§âDêâ8UÛXÇã5’Ã¥$l¤ ±ö¡§à\}[C§TÜ¡=´:ŒzX›ÙŽ«ã«&EUžñ½RÀ0¡ºŽˆÐ˜ykËé7M›-§2æÌOF’ç~œŒsqV×Ç Kܺ¬Ì½q>ž¡+鑱zt|[®ÄÁò:á÷Œm1t{Z¯÷—ùº‚qvŸÃAÕ©ó  tIi Àûµ$Ôkªêè î^0‰0þĶŸò5áÔn˜0¦Ã¾éŽ;*q*á+÷/T¿¦a!z ³áýînxÿ«¯àõmÛàõÙ"±Û'ôD¿­«£90þü'4@RÔñ¤ŠcUƃ.K—N'ü¨ƒ‰õõ×ÖìiñU'F»=$±Ô¿j õvüÆ4k*šbx•™ ÉÜE7¢¤Ü­í¡)Z·8XÍ{Ÿ_ŒtÿäÒ‡´2®½Þ¼áèZ˜” ˰½ ­•N·Å¹ò ù«d“@9­mÁ#8p]O‡níé¹| ÊÅþµv ?4óYôCVIû®@CvÔpÙØÚvIw´k âPñEïµæª¸EjRC××§—r¿ljsQOïõ1;xüþʺ¯Jxÿ|ºÚ‚®d2ªï0FÞ,7ë¡KýYw•Êl4ô;½­³¢äÁ©îËï 'ƒ›ý¯·¦æ“ŽX{·®âJ:Ëídß§*õ4v M'Nõ [Ž*®¡¦0¿²ü>±w(J­ˆ-ŸN÷ µ†;füÒgjÖ[÷ð=œhsS*È vÀÑ÷ËKŠ ÞG‰‹ÐFAdÄJcŒ•ûj G[˜Á÷û%÷ÑÈñV3bÌ+…¶áéßî‘g ‚MöýÁöøSõÒ_YèÀ¿ýËÞ«ÍÕñ ÿ]Ðÿ—Ç¥ÜïŽñjWðÚéÿÝŒœ ˜žÛBWóªÏáÈb«­ªÞŒú¿oüaÍU÷ÿdÖÿ%6{FzóªÛèêÐ%ߤ̧ …ë'†6Ê øÜŒûäeòŠëâHF|傯áü/ïãp5)$«¢¢„ý¥ÝðöÁæÃ':«z¡:÷V‡Tí„àÃÏÂ]?ìÉf ÇšdÅùíOØü3ŒÀ? pØ`(/oï8“_ üûÖ{2ÖÝk¥˜LÙyÛ¹´20Àa~MWÈÉ}ÖÖ8ù§~vw½CÆ‹‹aó[1‰¼ênïi$Z ÿì;G“ówF´ÇW>áÜ»ò|'@"h“âv¬óNÛ ¼ÇÚwÐÇýIºüñ©ù[Äò¯…Þ ÇÖZ9wü,:޽?E±ºË{Ú)`ÄëŸuÉw¨ºÝ¶2|q£µu1ÑŽ¢¶¿Ж#¯þAéV Ÿ¦À¥œêö‡uh÷£Z¯OÜ a|@S|CCSUûÙM ^jU·;ìØ³šrø–L“ü|“}k§ÿ L¥Šg0J›+K@â¯~‡ÕAkXÞFC’!ëñ óéÀcýb˜Y’¿øÝ„nTÏŠ°£2¢rO{Hkæíd^ÕgÊü(Öñ‹g@¬z,DÞJíÊ*Ï‚äÇs‹b`n)#T ÃðcO訾§:‹Ðßr”fY`Chþ‚2jðÚtþKÂE•Šþ!’ò½žNcz+5ÿ‹µ–±1>±>¡+–c2è 9E¹5åЮݖè-\V߆w®¹h¡]¶¡L(»)åMtâ,,1¡ˆ¯J†DµEɦ’¥¶›ÿ Ñôø¿²¤É¤÷"uŒ-£…'`á6[ ›î¼w q~.k—V"¯+ÂmUÅ%,ñ-à¤!È>Ó^0t(²G‡S±y¹rè`ÃP;Y5ê¿ü)V endstream endobj 542 0 obj <> stream xÚ]PÁjÃ0 ½û+tìÃI;…À’’5ƒnci¡ôæØJjXl£8‡üýb7ô°ƒzzOÒ¯š}c´þMV¶è¡×FNv&‰Ðá  K3PZú­ŠYŽÂ1^…û#¿¾×‡Ësu,/iör>Õé+(ìï”Óâ²­nöí2yÓ[ÈsÀÖ‰“§voÊvø°/RHÚ °;WmDÚÙ¹_ÑxHXQÄqéý&iNNH$ady’×uÁШ½MÑõò&he–Y®‚ÀÝР þöäL´îOˆŽÂrmðñ'g]PÅø»èmn endstream endobj 544 0 obj <> stream xÚXXT×ò¿ËÂÞ+"õ*$ñ.vì5ÆØ°¢(ËÒ¤wéuwX^¥K]DDVEƒDšû{F>£Ïü£ÑD£sñðòýÏ]LLòêÇrù¸ç윙ùÍüfæÈccF&“™oZl»d™ã¸vó'¿'½™¶žd¼kÒo"¾ÃˆïÊÄ!F¢ aYä[Ò“éKŸÌý~Òs,}¼ÓÒŸ1–ɸ°Ý`c3e¢Í{ #‚½<3Þ*Ü+ÔÓj{ˆ{p˜»›•m€¨ÕJg?w«­'öüYà¸#Ô=ØÊ.ÀÍ=ØŸêÙ§·Ñh£ F“¹yŠ¥Ìr#{fÑzÆ‘q¶ØMM?ÆŸá˜^Œ)cÎôeú1ý™Ì@†g1ƒ Æ’y›Æ gF0#™QÌhƚˌg&0™ÉÌf*ó>3™ÉÌg0 ™EŒ-³˜YÂ,e–1Ë™Œ³’YÅØ3«™5Œ³–YǬg6Г72›5ó¡u¡1S/!«—=4²5ª1:jtC>Hî(¿`ìiÜf²Öäšb‘â »€=Ì \÷s/»^•¦³MwôfzÏêý¹Ù³c}¼ú473¯î;¢ïž¾ØÏ§ßµ·lÞ"ý]û7 è7 jÀ•¿àGóEƒ˜AŽƒ™Á F‹,K+Ë K½˜jÞ5ôøJ!:Ùóçèöü>rr±DÉ£BOz?S<ÿ²X'äV“©Þ¿ Â8ׯˆ}ÍE‡y´-|amÊ&?צհ 8bJFyÞÊQóT×È+[[©½ 55—¡Òl„Þ_¡Ûë·×¡¶îTÑ·SYr‰ö”Eæç¢Â~¨JÈNMß~‘YË–5ï2‘”…Œ ß4AÓÜVªc3Ô‡ûÆE‡@·½&¤IW[Ùrrëg£ˆ‚Œ÷"}„«Õ"¶:Sã©$×ÿ¼&Nüõè7þ¡ÎéZÆÇk6¤¤@*¨!.=0Ûb©ñýÈPwÒë¿ÿ»·¿ÿä۪˙G5Éh@“š›»! BËvsd kŽ_ XŽóp„ìN•£‡x‰WÏñ¶sØŸ Ñ@ Ÿ—YøÓ´üÒû¤Ã¶@o7jv¡öegsæâR’Qþjm™ ™‡rÑ”$ðÚ{‰1«p!HŸÇq£I~~Zdpù1,ÄSó‚ÂÈÂ.&+€,²â"YŒÃ·o‡rÛ“ùÊ߉}(Ç[¨åWØâb2 ¹  ê!à’c F ) .@cb¬' AúlÜD¦cbc°"&ö9 …}å8Ù¯pàÎ>”åc§œ:a!ÿtN’ü_ŒãÎ+ü!ï77o_ïÁƒº†C‚¹xš¤—¿r(“—ÊÅø®µ~½~weCsùQÚ|Ë}3Zvf”÷ððG ”0gýñ#áqFÜ.q†tjLëA°ÿþ;8°­YvЇʱïðh öÂPÂ(Ã`iºS“>§¨ê¹Cþu.ÎþþΓž®Ã¾8óë¿?àxð÷dRÍ·5ŸŸ…¯¹ë Î%1ži?kãÁÈ}uûK©F•qM›³Ú}™ÀÝ[?%ø¥lñq ò R»«c4ášuR*$RHweB™`ð(¥qué_Q&ádþ±~¬8OQ­É"¨1»ÉãîU*<@óU¦bë´O ¹é ÔPŸŽe‰L àÉe=f^Æ·p‚îG®RPÅ´ãD±˜oJ¨"¨‚OᡆÒG ’Ûù1‚FÊÔä-‘›b` 8åm.IÔ¦jS‹¸]Jr˜Ý ±eB.hÓ²só ›ߥ®† ,€á¤¯r;¬(ôú”ë,h­hªÙîç±yê×Ó±7N||û¡ùŒ{dˆÒœT>œA=$ºOд¶YÖŽw½Ç`ñ>µõ&ž¹)ûˆÆüÇûN€ܳI‡‰ŒX.œ;V€u5«®¹“;ma¥ô§hÖ÷n"'ÊÞow¬åÈ’g|x^@%UóæKmåÝc[— à¡ZãÍ‘^ïó(| Û©GËÙ³ƒX;t~-ÀÕ#GÕôhP…¦'uø‹äòè)åÛ`ÜÏ/¢”Elh‘òÈ+®Ë,/‡F®9°Ò'È{×¶E'ŸÑ½¿Á¼ €$’cf“!Dùè#4Úàã¢ÆËQ¬ç­áÖàÊ”ç¡rMFl®ŸÖ¼¹EþÖÓó®4´m ¡-níšÉ'îUï `P''F´î—‰‘ H NM‘˜#B¥Ø§=u5W üÏîwÈK§œ§ÍèÄAX®8GlL&¨ÚÇÐÒøTÓmãYrOŒä‘#‡LH”¼«•žù±+õ2I³öoø®ü`×|^õ¢ûñP•èÈâÌ[÷)áûIŸQS{Ú¹‡Óo’©YG¾ä±—²ÏÊçl\ä¶€V,2†|ÃãÇèÄb¯Âl]á5‹°Jó®Î=n(Ãeå袗šbZ›¼+®k*_ é;„8[R5,I™HF’íÄÇ1¨F[dÑMK’Òv+ã(ýkbãÉxÂo˜ Ë`Ê^‡sž->'ø¡èjû©óןæƒë€}œëÉBm|.®´UTg”ˆS#Gàñ]jdË#g²¸­©ñÞFÆc_b¯$öÿÌ‹q,{.yØPçRº ¤×î ž›=·,ñž œyWu^›‹Ir-p&µi=VRj#c¶Ï!ó)-Û`ÛiÅ£\—¹Ê6¬wV|ç4ƒg%—Žtþ{?£?ûŸU^€¯‹u6ù|’\>äÓ¢?í56Ã%ê­íL+Œ^á¡ ÎΣÁCÒɸû11V±ÍÚ§ÐÖöš%«YóWÆ¿¡j!½ÄY<ÆãÖ‚¼œìû`©gW©Õ°ÕoSlTiöÅq¶Û”\1Á;/ô¬?5ÛÃà üéº!h¥x ÍÍ/¡Ž0½Ùgߢ;iÔ¦f$CŠeì&Ø!¨ØFíwÐRÿ†¬ d×AÊž¸B Ó§Jgˆ‚DÛHòíu8+J–zÅ&õ{°~;Q¼9PüŒqâõ7G·‹Ï%’­ÇüŽÇwšuWàîé°;ÄNè6ùMìs*öç×H`ÇÞŠVhŒ©ª÷¢ü·„þ¸txð¼­©î§ü…% éÑÊ IÔD'oô  5.ñBÂCnÀî¤ÎÄk„¡%khOza3•„ÓÓgÚ¯ÕL%³)7˜Äè»ØVÙÙxõ³Ä¼uEê(ä:t§ áÞær28= 4¥À•Cz¥íÙRÈÚ-$Bª&>NµÉ"¸|ãÁ±4Û‡ÏLdJXÒ¼¹0êĆڤç¡Owä«+ ¢ëÀ‘S…}@Œ…)@”õ 8J³Òà ƒÔPJ8´mH,² --7'//§ ºú³-·£ÏÐjóå‹Jø?»DVMª¤áòí ÞÍÖ‰ŒV„“8ZysP–}Gw«û[2N¥¸©}MŸÿnJé2Nüö&K³§ç#‰ºÄ—wõÖ˺<»>³ #÷p%z…¯z$,„О¤9µ±ÉQĹۓøŠq&ßé>êqàîcmH«,Öý£wNxަ,‹i#ŸSÎ ™Ñ¢·hÅã Ë-ÈÐêÒ-÷¥g@pûôŠPõlðÚ“™ùpêcÈ(âhA)ÂÍä)ù'€‹—5ÒõÇ,“ód )IMõLµ V'k€ ”ràÔ6üÍPÙØXpÿ|Z1â-p I7™!U¾§´ò=3¬£íž>I‡.58U'kB9ºHí£ OðçŸ%CˆiòtçÆˆšúºòJ÷îÊÓåTÑöŠûêûL¥+KsyÊ6"·A.ü¢ò¯p¼­ì0·T? Šòl¨ Ù¥\‘F»žJŽÈNñ¦GølrÑÑ÷ïÈ4ü°‡úÅ$I'¾­ÃuÒü—‡frt£ ™—`¢bÏf›²ûÇ6¶¤´¤´¸¬cýÉØV ¾ðâ-ÌC&< }¡=lÞéâÃíqâ÷;±·®ö2`©¶Âší¾N›ã|`1l?UA™Ô¤fqp³¬Íp±Ä*žØ‹Ï…8!4šä˜ÄK&ш 8þÈé4Œƒ³N«“•tQ£¦scôn望vU—·´ß&læ:b»ˆ¶r,y÷ûI8'7 —%üÞ$é¤LêR|*•Ö{ÈVvGé¶:[zаQSˆþdZ*OB{éA·EÛL=k—•¢H;óî¼óJÇhið¥Úá㊖†S§3+áŽÐm£¦å&5£C~¨“5Ð3ãé êˆA|e&T+¡>ñú–vç6‡‚ÕRñ6’ô'VÏlpŽ;ò¢¤ˆÂJjjRtв¥aNtËH ¾sJYg¬=”v°¼¹´q…^B1KÛHÇÅG¿ ìhb¸Î@¿ÿõ:ÆÈÝ 'Œ|3Âÿþ¦B+·4â{¯7bt“¬á6†¼È¼-ÇA¸Œ?tŠú“½¤„ÿæ˜ÜºâªŒmj2mý¢¹°Âûö––WE4: *p ‹p©rËq¤Ök?\¤ß\—6¯];#<ÁT•ÛË#C’ìBa gÿÅ\³î|r]€oW×ç;U-‡)´ÃÜÉiª¬˜ìÙiEyöÎä§ÂÅ£Gáâ½{`»e ØNUž"NüÕKÑ<=WÓÁÒÂãTËùsP¤4\kˆ¦† Y%íR^Õâiþ{—ãÄH›FùqüAñûHÿÌà“+´†]}}­áÅ"s³óüò¹©ùó²aR×£Øñ#×)r é’æu_/w÷¯C†y,$Kiô6Dß%ƒ‹PS{Þàw;‘²>"›uâ9ƒœõhzŸJÊ£’Z}]]}|\]}Z[[²Ä ©* H]AOî¶f·Æ|¸’ŽýÑñÚ=éeÅtîmªôö ñ\}ÖïÊïN<ĊÐq’r]ŽwQÇcÿŸòsór.J­I:¶9ô°l~Uj‚R’RÔj²ŒŒ²Uì?{ŠZQsñµ§Þf‹ó‹ *öbbc‘•@k¿†‹ ‡(ÚTi¿„šŽBÃý ᛕž’K[ÉâãŽçùý‰x>û§û$óWs ¸ö€º­çWÞu—ûÐí­c£`óâHŸÈ»‹‹–Ã8Ø`æDA6R9¿I} ÀŸ@–Ý:qî@ÅŽ9ÿäÿ²Ìþkÿ2Ѐ§×Gÿ›ÿ1ÐÄÓ”;ßîa—|ÊÒb Ð>eÒ2™LŸ:œ "ƒNÀÉ8ýÞì/-YÍ“A€½n誴¹¢õÈ^=| Í%e°œ¸@¹“—ø’¬×ãHDÍÏ© ™RØOÆñ¶¸VQ½ãp°Tð‡¼üG¡0ñ>y‡r¾c¸«wâ‘ýGmÅCücÅûâ´=ÍÍ‘ —+U ªðm§tùàÍ‘¿r´X"®ç·+ÖÏðìØÔ¸”ö˜Âð÷É02üé4´P¶@Gö‰ãÙúOž.µµØG{·|Õi|Gý¥ýô#³¶Ð&~[0ÏŸ?“hÒ wðº,œ‚½„¨ØÄ]Á¹èvUWëJul¨u>/Û(g •\Afüª?òä*Z`¬êe-_aäWÒ•À\ÞÐz%Ѡߟ’›˜œP¼=“– ?2È % Ã~;’k’uIÐß Î܇6&8Šâ€ÇIeš´]¿v]ì¯]—ÊŠ÷•Zñüöwßʧe ŽéÂ÷º4ye®Ë]ž·*Žq_܇rå¹Hœ- >†ŽÐ\\Jc†ÕãÜ2ÙO×>mÒÕ*-´óÎ µ“µu*ç}‹4°Co‡^¹vøÔ5¡Óy»ÔÏßw\¨|]K¹ß‘(¾WþVIÙ¹[WÎù(¥ú¤€XbûÆkqìè þ/…*¸ú[\Ú,Î{SU%*J.yÚŽ%ˆæ|VQFö9àô¬Ž\Õ°Fb šŠäD¥taœGz‘\ Âc“ÉI©O[þ«!ˆn:ÇâÂîþ9;µÉ•R«—­Í)£-Mgì.7±ŸU’žõ™$Û_ .цÙÍ9ÑÙ)qÃHa±ÅäSiæ´‡@G5l¤{N³é {(£¦'å†@2¨S5©sÉj Â`©´7T½}œÀϰ't¿•‘‘X–y€ì²¸×â)ÎÙ!ýkYé™Y{¹_X†xäÐ2¯ 'û‰|¨é^þ*Ô+-—LW''ªÕSÇXXc“¶×ú­3ì¸Ì¢ YC“~tLTbâ °T±g´Zh¨kƒZ‰dw†íÉRB¤ee?E ”“wLœUŠ*í¨­ï4ìY$ U/ô² )ýľ|faFöyÉ[^ê”7H¤µKÞJMMÒ¤R$öXX/!B5 ð·7 qžE»î‘É1QþÉ1–a[}lA Ä@l¦6­>Z8]H¹ŸoH˜×æÃÎg„ÛðÉ5Ú¨š¿êÂ< ^‰òW"æñº_DoÖ<&_´ÏÁme¹ù ²%‹Õ›¢¬wSŽ™Ê*Íú¦ÆÓËÌz¥™™‹½þ?£z¶( endstream endobj 546 0 obj <> stream xÚ­X TSgÚNÄÂ¥Zªb:aÚÞ‹ÖÓbk­vq©:](µj]pÇZe— !@„@BHòfß aI"a ¨ì‚b-ˆË¸t³Sk¥­íþùÿéßö»p™3ÿ¨Ó:sêiç\Nrrï÷¼Ëó¼Ï{Ù¬éÓYl6;lö¯GÇ>½qûº¥K&¾YÆÇèÑâûè‡Yô#lúÑi4Dÿf:ùùúéÿœ9íQ‹½j6¾²Æœ¸~=kâ:_8­sXÓÙlB\K–<·xÉ’g£3„y"Þ´ìȨ¤…‘KW®\¾(òÙ%KVF¾’ž"â%%"7&d§¥¤'dã‡"·e$ñR²ó"£V§eg _|æ™ÜÜÜÅ éY‹3D~·pQd./;-rkJVŠHœ’ùz† ;rSBzJäöÅSÿ¢3Ò…9Ù)¢ÈÉ)"Fò+ŠÍÚÈÚÂÚÅJà²XV(ë~ÖÖbÖRÖ Ö«¬hÖk¬Ö묵¬7XëXëYXoâ_obmÆwIJ¶²¶±¶³v°vâ»w³âX{X󦱨8R{7»uÚ A!AeÓ³î{ô¾ö`nðB^ ¹A(C£C?½Ÿ7cÃŒ¡™Ã(¸fpùƒ=³^šÕ=›?ûË9á¹s—К0ú&“૾þŽ §?ñøØ¢›ô´³A£a£Ïq ½ Œ„C R² X :ZRœÆÕƒCçO®9ùF!0«@òŸy•Xœ/I‘*¨sÁ1Ì?‹ß–¿-ß¡å”wæî¨ê?åêtƒ_’©*Ì ‘S¥¨ =PYnvúàxæµûÂèEŒÑ;¶ÍÃF‹ú‚P £â€ *ǎʸ è‘!:©P¼Ë¥×ã4XKjRLÈ‹Ï3ó™i̺CÌvˆ„-ö7«âüotꀰ˜LêÏé ¢çÐq*>Ÿ×'º?(B]Zª¦@ Z«âôJÛ2ˆæ‘-ã!ŒŠ‰—Ét:Ð*“ÆB:…|úš¦¡u´¾'ÂF÷çFŸ°Ñ“_ö®áèMz ˜ƒÎ¦ µ8ÇÅò7_áÆ_‰­ˆ‚IdøLSĬø~"Ñ.ÄF{ (¡Ô r7³†™½aËŸ;ƒæSpΖ^GÓ.ÿõ¯=ñݱ§ž§ ³„á(`ÆpŒzS%66£ìû÷c«ƒÆfÓ4ÇÖd³Âk‡ªr%äSÌÜàЀ<ùrüw=¨õi! "˜ˆ`éDØ :P‡‡£-•1sÇ˸²m)Eû´„R®Ë+¶h¬Tãc éh`æ|KT•©ôEÔVƒ¶Ü`‹©EÐõ\}ððø7†|P¹!¢ÌV‹“e㯙yãç•<µr-DL‡qS-mÆÖÖŽ–™ó­øyå*È›=XMnœÕ!€ZkÑù{ô¡?¡Kè =Œæ ‡ÿŽBo®½À°)fà'Á?<ÞÎ:Œ¸sXk‡±­½£íîÃL`0¹Œ½›c?f…f >¾ÚŸ¹‚Ü‚…)ûÓ’ã$›qÑæ‡åçxGçá*'EÉéKœ#çj*zM½É¸yÁQDfgj²øiü™óÕ… ‘ÛuVªRwD ‡ ¨¤X-g,ã©ÜZ®Óã†6E@¥¥ú¢ž°•Ç®4¨©ÔdM*?íÐÌù¥²I̪LjC¾Ô¸t ­ZÁÈÆ_Æé¼:ÿ%}„Ë ÕerÐÜu¯\T7€RŸU?þ®^l(uOTÉls£z¸¾ñ½Ô•aÃdtTa´Mî£öh}së2zi8ücô÷!ŽsO‹ø(ü|ª_F~®É…c3Þ|³‚䃊§+!»%]ü >Îbs?³ˆy|YOÌGTøÇÇืý$qY9{™X%ã‹Û!b¯r¨‘‚¾ ­êô÷ôuqÜ¿+SW¢Uc¤ñéÓ>”ÚÉF!ï"ᥠtft)Go4Ø0<»Ú¨$5 ÐitQJn‘N®Ã#Çéè5¨$h4… ‹§¸:"Rˆåk?@ÓQ(z=ñýæ“›Éà‰y|B3Æô~DÁqûÑl­ƒÛÓÐÞz¤ˆnÇV> Bf†`C‘(>f7L¡B­ŸtûØhÚU”0D¯¥àÄ©!´„Ô)=\Wãk=ß²™Åp°J=5´îhîgÿã6+J²'T©xåégKóØ!ê¤` îÛÚÞcûŽvƒºµîÄ[Eºúd•‚èÓ÷z,SÈ-ëîªÅT%î©ÜnK ±¥†£<´iÕv þ½j68¬«ÊpH€FWz»vHèC«pš‚¯ ’Ö ¤DRN#\2öVÒÁJô¤¶m˜Ï<ö8³´wÙ×ÿ!EëåïµQÐêè¶Ö§ ­øÆè¢ý°7Y ©0449?i žžðNLOtîfj¤pnW:niâš`ׇÆ*÷U[‹sà†ìÕ–KÓKdY;9—ü~ÏÑ®ÄÉäB1©xbfwÝ„àä⼺ñ4}u<´h£"Q-ŽPò&¦©$F¹û®iº¯KÜBþt T뱉``eå£Ã|˜n7…—ÿEàˆ—Å©Å¼ˆ¤½IP…X4„N­Ì •DyqufÞ!YrRKÞMò[¸öûêkˆM¯çšÜB2E¶"ÈV– ˆð¯e Âúx\àéLÅÌ[vb-&Û·ýÐÕQVF\D.Î>f½’¿i &Ûí5'½(Ô{ÂúxwgíË•ÔZmäLÕð=“Œ‰ÿ‚«ÓêŠqÿËíÕ¤Ê+N“» =d­7û,^³Ï~Lo¨jò4u¿ŠInØ'¦`ã~f†,©§)1±¿þ@ï—GÐBód–ö¥P¸0±Î»Ð卑Õx:Ðt$nl÷í!߀´´Cé.ÿþˆOç ¹gN¼“p#œF7Ñcœ>J | ?J)Ó×QP[Þ\Þr½Äu4ૉwRü©Oó˜…%“C¶ôxJØ›k¿Âé,ɦ K.PIÒWp á?YJ)î "¹&ñÔWÍèIþ§:›ãϵÉÄÂÜ ‘GéòÔW7S}i¿N;'±¥ÝDig÷~>Ž® ÷qzMà"N¤wm‹ÚÉ<¡ºu4è-þóíçNá7ääQ ÕHJ¥‹Ægs w&¯Ùy ³iõGÆ&¬»·;%µE|œ¼×/zGˆðoÐoGWrês,E¢¬¬¬BGnMßç'§ø(¨»úiùT¥O\ùå•nk½ÁÞös[J.ˆ!»šR ÓV "ú„¨…<¾fgµ¯Õ5<åboKLánÉÚý@µ‡=¶ÖëÍf/våp9¦îMûa—×[85ÔÖÓÕ`•ëu ª’4P…vI­¯¾ªµ6ïÈ>r'Ä'ð’¶®“JÓòqà>åt²¿:{ïqÍ×pu¥%¹P@LZÞVðÔ•û+º.ÜF]jД¨DÜüIBƵ1ltp²ÙèÀ0Ú4Œvbå£hÎTë—ŸC™·¡¯kð =°»€¡J -^Ï”sµj] vwr[‡,ƒJ«µº=Ïý÷ýÊÜŒõì%c nú~å•]Õû`3ì9È{[u’× 7[š.I*Ü‚ {›z³¯êjõɵ ßjÅ—™Ÿ¥nè_ØøãðûA_ÙàªéþèÚ¯Åü•ðÖæBɯÝv :žæeWƒh p¾ÞråùÛã{ÁùŸ¡Yˆƒ×€'HÆÂx8É©÷ñ¬EAM§[†{±”ž¬ß¿…‚øœüÍ‚í»÷í™ð 6fg-š|6½ùRП™¹x„*5É:¢¸$*s‰•ªk0Ö7™pÙåØÜ)@¶, ,ÖZSÅ1ô8ךïOÄZ€÷†( -œð-Ôˆ? à î+ý¼èÕ UeCÙÛ‘sŸ¼ó“¦&V1b£ðv)39¶îÇæ#ˆ.¦_¸Ã&¥Aƒ°iÒŒ¢†Ì£oÝe.: ¥¶¾.™YÊ•ÇëJ7èˆBlÉ'÷‰¦£ÆææcMwGj5˜õB‹L÷è.VʽèÊ'nœÙ…xÔ;QØ8ŸƒêÁ#K“køP2©UWÛ©õ΃äëp Nš#H®>ø º+^Ãd’É}ï^G‹/÷ùæ\QAsÞÝûAøÇ9®èVÀ‚/\µ€ÌX³´¿ß 8{Õ…åâìŒü}›¼‡žlEa=$|±¦*ÑN„—a9`ƒ.¢Æ{ù:Y- g2¿T)Ä2*·ä×TÖ–uõ$¶­cBŸÚE†Áï.ÊêqЈ|ò­A4^tg`Ý+Çžg$¸rbS()µ*¸EM¹ôˆIã …¸´ ™yŽ»ì_o ®ÿ`ákN:õ¿ý·ÙX Sæå½•ôòV,Õ௸½ç‡ÑÍ·HóÌ0ZŠÍ©ƒ~xâU…Ë¥SéÎ%ÓKœòU¦›[’ÚâBI† Ëý¾âãÍ 7ÿÙÙæ5»ððí;ˆ_œÆD©0|mº¯'‡¯&_…P–œ“ù ì"žœ&àHcMcÕŽ.uõ=ì+w¶ 6Z2ì:ƒ–ž ¢ôLÎÑ¢€ [”MB¡UeQÕdùX”2ö2&&d‡¼¯™„Á¦/êÞ7WXÜ?í¡e¹›a/±ä‚`­îAÿ¨%ÃFÝ:|é0Z<ŒøøôYh5G•¡ƒŒZ±3>,'átí‡ÖjóÏ?,Žy2A<¯6«)£[S Mp´¼±ßÚ.‚³ÐÙÑø^ãå6´ˆŸŒ’øóósvñß"NÚÑI]_ã<Þ‰Vs->G;v“5€J¨UâD&É}®ë(óºËǸ‰únÑúIN’RAw‡sý±er;Ü£äœÝcñÄæ7Ù±PFÇ\Q÷ù©¶v ª³“p,E{ŠS剺RùÛÒõâU›ñvŸù®F›Ýn¢Vl)‰Ä“;³{È^hn­lôl=)¯â›~ô[ÏD婉ʗH…/Ä%ã•'WXvŠ‚g—툳Ó}ÎÖì:U÷Î 0‚*d8„<&Á=p½ÇG/ðÈ}sþ6"vŸ ÿÖrR˜•¯ìâ-Y«™Â¢ ·êæ²:¨ ¼Rg^Q²zÛ®Þ;Øäÿåÿßþ›&¹z‹áßÚþ7ü¿T‚¤Í[~–ÿ®5ååDXŽŽv¢,C…/˜Ip†î¿<ÃgŸ9“¼úrÏÌP4:÷ÿf¨¿ê endstream endobj 548 0 obj <> stream xÚ¥Xy|Seº>!X 3MuÌ) *(È\¹(ŠP«Z)méBš¶iº¤M›=9É{²ïmÚ4mº¥+-KÙ¤B±²‹ãrq@¼Ž£ŽÎ—zêû¥·‹ós~÷žþšåûž÷}Ÿ÷yÞ·bâD‚ÃáÄ®IZñÒÊ—HHL|fá‚è+KóXó·#ªI‘»‰ˆ¡&D⹑;& /=;ñŸ1î&Nòo¢Ï©Óñ“øzFôù{ü¸óøo ‡3yÊŒjc{ZþÖŒ´Âœ =¸`Áà …RqζlIüÜôûâ.Y²x^üà ,‰_žŸ)ÎIOÅ'¦I²3óÓ$øíñë Òs2%Òø¹K³%’ÂGz¨¬¬ìÁ´üâ ÄÛž¸o^|YŽ$;~]fq¦¸43#~eHÿ|Z~füxŽÿJ(È/,‘dŠã 22Å¢(b>G<:qyÌ:N‘6!“È™T<™àè941˜FÜMÌ (b1›¸‡˜CÜKüž˜KÜGÜO<@Ì#拈?‹‰Dñ±’x–XCãöËwÔ ^ãGèØÈÕ #8ƒ þÎYûÙùµ’Ú´ä¹Æf0L´EéÖÖhlj䤠ôèËÞÍ@êªA¡vªSk׆V}ƆlÛ"—kµPWá“× kÁév¸ÈØÈ)EúçQúøÕE¦ðÑ$^.;W• «A…ŽW >È@C]€˜´>Ñyx ZaÐþºû‰xB§Öä[‰¾àÕ˜pâI·Óé¦À­±Êm£AÄb#4knøv}€s$r7²fd3ßê 0ã'j@CÓZöoÿ“(ÀÅу‘T8Un¡Ìv›ŸüTÎw[Vð€GmUXG_C>Aµ¤B¥RP ²j}šHe£øQ¥ÑiA7v LàµãUFÉáÈÓZ…&óÓWgT¥Ðr£  œÔZuaKØÜÚÙÝ3Ëæ…z·ŠÑPS±Bà±¹¾?¢ÛÈÂ3•úØß’Ìß@—U)¡Lá“pçnóÎÐñþ¦n%TS‰vºíù‘IC,P zVI²å£ÏðÑ+èb{qRìˆC:D}aNäëO¸èïñ•õR +¢';¡ŽB#<ô0šŠ¦þ•‚ó/½ßý÷ú¯/À§ä…gN°1Böc^ùø'ë)ÔƒßPgp§ÓHÓrÒÏšøo"ÆÙm2ï†8Äç]nX›²è?æ±±»ž½Ì¯ÂEÕ2J†fÀ+h²ÖAô"ï¿ë—§Î}ø~v*;²¥$<2?Ìyí w„YÃ7ì*Ì£Q¡xú Ê—üË’-fKØ"VÆ.ASYšO}ìÜûÉŸüWÀLº”`jAg0¨U"ÉS+_\¹þ¹Š @.œy- `¨=ò74娹k?òË7ž`I Òi#Î²Ò L‰(4\ÁÓá„9#©qÑ¢r¥€ry4èCÊÀÉ݆ ÐÌGÐDö~*š ñ·”êŒc­ÁFƒâz‚þdä'‡üﯓX›ÊØÿ|„ ÊZºŒŽ›Äû¿YÂPJqå†Ã¨³‹3²UñMV³L$.¹P­Aû,;7k5» ŸpïMN8šŸóþ ¥b 4 ×ätF·£Î¢ub}0[-5C¨Z`ÓY5cçÑòÒeRÉC@Îç #­³›±ìÁÉC±í¢%ƒA_Z£KŒÎ¬q ÝÀØLõ´\`nÑÈQ¯ì:Sz[AJá†3褬`´Yðó4FjyÀ0öZæ8Ì}a´·‹ƒŽ ÷øŸñÞqTŠ~€Œ!Õ6½M茹î0ʘݸß̤ÉàT •`Ôé+K—Hrï²ß@.à¡é¹OP =]h¨Ó¢_@^ý«{ÀLµ]0·u^쌙åôà8À¡5ι_Rø,“ÈL[À‹ñÙ,58¸–’0ª Gæüjr/B\v2z„ÚΞšƒzìNqs– H«ÉÌP&“k‡µ¡þ]Åoõ[üîÆ4ÄV7So×YÔ”d--Ùþøö˜Y*9ŽÇAŠ6h44ÓV÷¬J±E™UÀN`oWdùÀ¬!ÜFv¡%_£Û_?ýÙ±ÏÿeoœÇ•z3Œºp{X"_ñ=&×Û@6;°)€¦ èÑS¢˜YjÅÍõÂ@W¿ÀÒö(ï $wö˜]ç!î×7{çh׊HUãÂHµÂ9s+4@Ј hhÒ•H”g`y›ÉÊØN£:ÊKc•ÌÓË”yåÆD eÿÞط׌ËCdêXüf×û@69 Þƒ»-§Eù+òcfiªÇ#ØÕ‚í³Â`P±wöTY´#—Œßйô¶¹­ýB{Ì,|W½G %”ºÌTjÒ[À “ÄM%òZIðš©sÞF¸‘‘ð&ça kÝPïÔšÕ”øyZœûhî÷eo¦Á!Cm§¡ ´AÍNMß¿*iA’«òÙˆõȾæ®öŽBW…t“|Uâàæ÷©«ð÷“¡Ïq½ÿr=X[d.ßhÖGu…©ó¹(Ý%¸v¦ÏÒnv0.êH mW KÄtñ¶Œm8~ 7°•¶ƒ§æK´ºÑ;ÙAÁèÂ8oâBX0j“ö‡Êã¼ý’Œþ¸òß÷âMªf÷þ¸jv[Ð\ã;äôB÷!R€H6è)Œ*e\~ªQ¥P\÷Öþ]æþàëÁ˜YVïUÔV¦Ú)ëÆ9Xú}Á¿ŒÜ} Èöñ‚ë¨Ü%tîxÁ忊²ß;n$× Øüï£íKT͘h UX‡:MeÎC),]Uâ›÷[Æ1}ûðõ&|ÈFçØPPA±^A^>Ê=%xxwu¸0:üàqgA+Ï"ÙYîHÜ WÐaWW½ºNP´oCèYÚ­l ;™FÁ£ƒÉ¯ÉþQ èU–Árá’ù÷­a¹A4CMÖ&ÆÆXðèm"]F‡O1à õúõl96<­[§{­Çw`H°ûÅÓUGD¿Ãã^šAÁ™œ.™OÒ(³<ÜXbÛæR™ 9m0Hþ×þôâ±Tv¢òôRÐŽo.`Ì<8G>(i™‰m€Œœäxo—¹×äa?f±›°HDææäÅÌÒâ†V8vªÅP¯„RÉJÀÈÊ«"Í“üÞ½>÷¸Ó!•Þ R(g¤Ñ§©HÜUQ¾ÖRG€Q™Åï~'0—Yh/Ô‚Åêðb!E02?Èé?ÇL‰Äò¥½¢–-8mSØìïÙ{ç~æ=*-Ãçiݹû¡k;ü=ÞcÑ\©€ŽNzºªâYéÚ­@ÒÍxÙ šî=î]&—sGŠØ[qwZH¿ÜU!,Y ]B>Ëzø:)d)/m­,ò•ªÃ¸Ò;ð¼±7üÆ@o?où–h)¬»Z£ã\>†eíâìFŠó\¤YÆÇƒ\µP+ÔEµQa)‰ƒ­ÙoÒ(… QåèJ—°ï ä¯è+!›œ7˜x—l:V±{®$yL˜ [EùÛɲ'ø¶ ˜œîo Ô4ÙÓ’¿†‚µ¹ìdifîêäm@æä¶\ p Ô×ÇHžRQ×åþ gç$™Á¯Ä]UU)3TàÕ°¸NQßÖÒÔ`sïSì]l;›¹ðèÒ¿£Ù~ã±áÅ6Ê/ƒV½t.ËÁù\áa v>ëz3—ûüF,ïW#!›¯ñÿ!6-èú(bCU}‰Žs#31¬ú*±$_’_æ«lliin²Éß-æ—/{uÝzÐâå_êl·ãðd­¢¾P,*Ý–Þ_²_x> }~52A` `%1“CiݯÌYw»7¸£>tlï1<øêôixê¥ú ŒÃË0üÏûÐîSGñØÿ¯ÙG—±sFßÖYOœ$ sâ °ÆióX(Ñê¢ÿT Ïàù\O+ rƒäÚþôCÂvh© ö†ö¸ÿ´»ÊVH6¦Y^íî¡Àoi´ÔZüXô]ðÖsm¸ÃuMû÷î>6ì‰&£ÇÀDÇj#MòUZ•r²Ò]ÞÒÜìk—tn@²:ᱜ̌ôL‹^SGø»8{s‘û&•“ ŒQ©£ýv”¦ TÆ­Û“½OØ ¡€¿§n‡çèÏ¡|m:ùÐᣠ‰±Zë±íNW›‘éÃ5'¸—ßàÓ2­/CRŸªFè:‡=À˜<ûl¡à_¶ -hm´ømŒ¥&à®Îý|¶"8xÍ}{ nÝ7ÄÜ™Ê/0–•@ Y唃Mþ¾ÔËXAÖœ!<~AÖ¦=¤<¤€—È"Éb6FXO€dp‡.Ô­dc¥§´(¿t˺¡ôKè‘>4m@=å!¹§°UdMqns¤Ûa€lk:vY‚ƒšš ÌÕïpãÂ(!À9éº5rÿ/àݤÔ"^š…ÛÛ6î64UÙì"ÁüèvZ.Ç›u™—Àöê+p»¾¼#óõ/‡¢©Sƒ>:8Ò:Eêì¤â K•ÞNL[“}Ì«Ï\/q•ñ«#|÷Öî¢Ý¿h†UëËW¥Ý8#èÙçènE„À\ãÚa©±6ºv`xu8YX£‹Œêœò)l‚<ɨOl”½i}¿ùŒ§ý{‰—õS‰ }´£wÎZ#–Øb…H+Ëš[š›Èygį OBÏ€?ˆq—_ÇÍ9áFw\ãF²#$ÿõ¢Z©¸¸¨DÕV­[ÑPæ-‚mdÚ󬔲QÒ}HGZÞ_´ûQàÛ¾ØÝØvCàÅÊB4…%«“!s—+÷¢¥CèÃCÂØ‘”׿åþòZ‹lEWùÖ «÷F ä UkÊhÍfv½¦H“oˆN. 00:IRþvl½Á?Ö¾}hº»ÝæÃ¢>Û»éçùhù¤/Ü}#bE¦"…*O†LrÁ©ìw„~Øýg›×œÑ¶Ã;°çxóp×{èNØO.¬©‹Ç’aÓ:ÕnE¨^…Ñ}E‹’²³qm.l¢ Õ¶øpFO+‚ÞQÚÇÞ §í*:u•‹>B‡ù¶æÆ«gÁ MÐP] +Cñ˜Ü;êú­õå_„ì$¹D|òe—ÈÙëX¾8ŠÂëˆÉäìúædÛe}·êE ¶W¬Îbã+³ÓR°•I Ô²p«´”8dù⢼äƒe{¢>k¶y²z2†üjñCQöQxvÖ4¹ñ«Šó€Ì¨ìèÂì³Ý{0îjl¥».ïú#‘ßð-><šÙÇK¡„J­JfЩ·ë¥¸…ÚÂ-ìj^–úô3@nTìÁ´Üë³ëríN¼nnJËŸ8¿XY¤)OŸ)]›É‡ç¿!ìƒ.kkõù¦ô¤¢œLQ2š¶˜+újÁ >Ëéòb¾… -JInå¦Wöd½)ü ¾ºÒŠ&MB§Aä :Naå¹Èýh[¨' Ì›ƒ==Ÿ~ÜÇKœƒP´A§Êµ´²ŠA^#ó—7Vr|2ùÁRY뤜xU2Ùê÷exí­×4ªûenh†m©‹Ê+.¬Z½qcQ9Àd²¹»Û[:ðÎæR…DþÒºJLýÏ¢[[¬z«šû·ŸFòìšò\(©­Ôžã•YJ±ñW‚Š&cK‚‘·Û‹òƒ<6Í=Y8uââ@Ì{ÌT&æ–ðÔó·„l11èÒmÿ †Q endstream endobj 550 0 obj <> stream xÚM”{TT×Åï00s¢bsEïŒ iIƒ0åòQЉDÀFl F…:<„„„+‘7™ù`@‘7fD†ÇDQ@yˆ J•ÆJ‚Uc‹X‹Õªç’c×êÅüÓuÖÚköÙûw¾s”µ5%ìC|wl üÈ7ðËuóû51ÄðóŹ\nÅ9 ¸•V#ä­WR”€rà•úû¢yZ<¯ð"]BY ˆM-”É>v—ɼ|5 i‰ª%+uüPê¹~ýZ7©—L¶^úi¼"Q¡–F°JE|Ëoâ¤AšH•‚M“ºz+Y6aƒ‡GJJŠ{D|’»&1ÆçC7iŠŠUJ¿T$)“QR?š•n‹ˆWHç#»Ï‹¯&>á«H”j¢‰j>©Ð…rÈP” µ€²¥¨%Ô¯¨w)šZJ9RË('j9µÐŠ/dM hA¢`ÖjU‹ÐKøµõjëW›³"N»3™Ì­ØffòùØÌlk³Q0:„-xÅŸœó¢Çtј6k‹ @hrš:®1½Þp%ð8`‚,<Œzb÷ˆ‰]îgà ŠŠî°³ágr³é»•ȇ3‡Jô%`dþÆØdI¨NцÁ. ¸^[‡å#¹¥WŒÅå·žÀ3¸¥è;T'?U¶»Å–Ñû«ø7\™<‚,ä E¬iDÂÖ=þg£…œ'1˜~2 ^Œ ñb Ë*¡R%ú¢Ì*²Ó*¼ °àNl‡W ôTWA)*-<’äCðî¼\²œH5$ˆ=v†`çþÏkyÛËØ@Ót, Ķ!Ó²Óåhó $PºÊ,,%Nmäs î@:ˆqÞ-ÏÌÔë¡òË™Zè(;Š—c©¶çÍÍÉæ9[³ ónx$ä2ð ^gÅ^ ûiCý K@¾:C³Iç »`‹á×}¿ëùôVêèƒ5ý³í7 ` –ŒÑ*ð«M~™=30ãð׊‹¦çwËá[?h”Uî€OÀ¾Ï¬ ä÷ü2baþl°pm–s|³¬I!¾6ç@7銘½‘;“ÜÅŠ›`.5¡7åâhm–£Œu@w÷Cè´w±(ÅnÚÊvɼÍ~öò_Á…—˜}ÂO §kkº,µÕ—GF/Â?¶ûÍâ@ì½e^!gò«M­5§ƒ!‹i¾y­ñ< Ç}Þk%ðþ¦Ä–¼C–¥Ë²²ùáJDœDÔŒýmâDÚ”¼à¬Ô¯ó6B: â'šÇÖr ñé—Nn=Ç{ÿ#ćñCz²û{Äá³è¾¯Qyjl°´± û4#Ýžbvz<ýL÷¶L|P?i½? O™(ã(Ô1obG ÊC¼q[È1s+h#”%3™ ×çdo"—Åâ“ëx‚Ù> +ºo(†‘‘b¸ÏdÅ>ÚŠvɽW–UâO8ú 9"~Ûíå,ö3cú~¥QðÚ‚uÓB,åFéªÂŽœ.@Øaâ§šŠ|CDÇcÊ-ˆ:$ÏúŠ¿Úš¸ÊœRèeBvš„ôˆÓ «–)CIiYeÍéû0 Mò£©u1Årˆ‚hýWš°ÔøÈ¸ðø¼“3èCÿ0ëµ¶««RÒöå„{Þ•a1vxõ/Æhí b+ †=é ÕÛÑmáœÌ?Nwœœ{ŠKf„˜Á£áÞ‘›§¾kéè¼FèÑ6(Cu…*ÈFñ k®8ýçÐóžDBV‘e$ŽÇKž2}0XÕ}¶ãÌ·]ðaG×i"d|!\Ά L“ÛôNˆm?df»u×á4šºu‡é‡–ýß(MÑ »ù–³_®L {;ÕÉ&ntŠ'‡·Ï9÷Š>ZÅPÈQ"Ä%ï*ÑÕÖ¢8‘ŠÄØ´ŠŠk*Æ«Ë*JoC W)r! ·$âÞN9 ïí…îJ¦O Øå8¶=?öKõ9[¾ö¾Ô/Ä÷ñéá¦ëýp=ùíûª5›V3]¥jT×%—è.G‘Å;6A"VX¸ ð¢Ù{¯¸¢êJ¯;X«/Z3„ˆÇ ­®Kj†“èÊxÇ÷w¯îÜÌÀöÐ/Ôhc ]¢Ã¢ÍuÙµ¹ƒûàÈgßÖ{münŠÛããm¿¤i}:eæœùD3¸ôŸBÎ÷ÑDKPÄv&vZÏ•,PŽZغ¤4u¶Âxï4^‰—bg‹«ˆxÂ…Ø®ò Ž„~ºÛ0ßÃÙîãˆ,÷§å 6hgÛùgF¡«©³ñT›±®AóC)¤è÷‚¼Ãݼ˜…> stream xÚYXçÖž¥ÌŽŠ lF!13Dc‰ClQcT,PŒ51Š¢"dY:Ka©»t%»ÁŠe-IÖzc¢)ŠÑ$&jbîYïGþçÿ–¶››Üÿ¿<<³3s¾SÞóž÷›•0ŒD"±ž·p‘‹ó»ãç»{x¼édødêv¢Ôïy¾ÄRÿ£.Ñ¿l¦ÌõÃ,^fIž-=2ØŽ÷†Ž¯Ðƒã;ÆB"á"âÀÉiòD'§IóC¶EËý||Žc7¿æøæŒoMpœää4ÃÑ9È[î·Ù+ØÑÝKáë䥠'Ž+C6ûy+¢ÇÎòU(¶Í|ãÈÈȉ^AaCä>³_›àé§ðu\áæ-ðÞâè¬p\êäíØãôÄž?óC‚¶…+¼åŽî![¼åÁÔ[«±¶oKf3s.±XÁ~Ȭg60^Ãb˜8êöf 3ˆ±b3ÖŒ 3„±eìóÃ3C™aŒ=ãÀ¼È g^fDæf3’y•ÅŒfÆ0c™×˜qÌxæuf"óãļÉLf¦0S™iÌ[Ìtf3‹¡ë1ó˜ùÌf!ãÂ,bÞe\7f1³„qg–2ï1˘åÌ f%ãÁ¬bV3k˜÷™ƒonfŒ„1£·”Kœ%*É%É/fƒÍ™˜Ý3ÏüžÅb‹K–,÷±ãØÒÒ÷¥Ü8®jÀЩn\>ðÄ —A­l­¼¬Ú/|ÂÚÑ:Öf„Í•!ã‡dùÁìlì\í’íjeSdÙ³|^8Á*9ôÊ0çagí-í÷8Œvðq¸ý¢Ë‹-/¹¾T7ÜnxÈËæ/g¾ü@°²ž¡y¦– ³Î\ﺊ‡²ÔÜè2ä›õèh÷¢ˆ/~_^\ e\aº:4˜l$ö¤H2èÈ›­œœwse-põyêB±ÏÖG:s|†çxÀAëïû[}}nGpò´ÈâŠSó2p:‘”‘©àc¶‘¼ä—”’q\J~d]nD{,¬ïk"ôóÉËhsñªÚîs½=‰üTö?xóy­ßVõ¯†Øl(N½³²L„Š„¢Ì,yŢݡ¥Èœ³/)ØYU\.4mÈùÙõYŸB“Cìö÷ÿd‚³\³C sÑ^Y” ©ÀEÆGljUœ¶3%Ëì ³,!5> "¶Cð>‡\Ë U¹B°C2øïÞ »iøMªO3ë9ëÛ|ç ΦQG^1ÇcXË㶤Z[}!A$#p$[­¾¾à› ‘d„4þëÛ %"Ž #Ùðm¥7—ÖDÔD`±ÕØá:½ø’L­9|œûºØ„íIÑéÉÅ•ÅT´<=…fÚ-oج ðn’ïò¡ « ›³ÆÚ+’½“¹~uÂèÁU¶Ek@[ µnkŽ·.ðmAõÞòÀÀ­Í¡-{ëví¬§kž+Ô’³ú æzÏç6|Ay@!WW)„Cj\Z<ùúûÔX@ ]£ª¡ ,'g¨Õj%Çtø1…Q0žåqé(F̈Åò"q#KŸ’ah†ñEtˆ/)äßqÃ8Gë~¹qýÊkd ëF¾C}Ôê­µOi>Ó)Š.éoñåP$DAZBz‚÷´5‰Q™±ªˆLáä•éeBìÏ?´—ëšé$ ƒÀ :(1—-«ƒæ]a+:±ƒZɉ›Ø¤3ÿì,Ÿœ’–J.°Ê|Àî.(jë¥UPíç Q!IfÏÿéæÁ};Ž\‚¯8´}“X“³fLÛÚ˜X¡©©h $}grAÙ‘£»Nwç‹õ“EX¸v¹«‡!˜}=µv‡:ßëÄmºÍ:Ù#½9Þå;>j<§¸ó>#RbµðCÿ:¥ºÇXiÚŽŒœ]»®BpŸóñ!(Îw[x@¨<Ó'sÅö8€`Nök`-õ÷ûËñw—/]¹ÄIÜ ³‹Cæå䃚«RËáq“-Gö탇‚ì\]w噣ñ#£ÕPKš® ¼Ã|/fðÉñIñä_”ºKÀ<¸³Æä½kLž;2·Œgïà3vwj¡Ÿ†Aº*>’#owq<Êñ©%y*¥±w|ƒ‚§jíNt®Ö¡J'û'6ëx_غ)œÃ˜*í·FªYÿÔä‘TI£AÑ"TBn^ᎆ–ý•g“ýëÎáyno/xï-1†œÎË+, q6)Ê#â‚’·Lÿf!Z í/÷Ñ\ýóÉìŸÉ@Áû¶ 8CkwòKTv®ÑÑ‚ßó¥øÊwîÁ(OÌK§?iÍ…UFÖש+šÛ}N£ø|‘ &ž‚ìIB‹y¿ äçoÐ ÙÉÄLé×ÀšÏM:’ý¼liÔfæ«ò3ó9U.П¬"€cV#U™PÀ]8ì·O¾ë<ÕuÅ|ê“Fߦ•Ò¡m1X”'Îd‰ÙÄŒS‚kEEq“‡mø:ÎÓžSWfgC)gH@¾fÓÊ£!8?½¤Q¾§ª»ãÌÖâzŠ1‡kèAö˰‹Ÿç~¸ãDÇ'_Þ:óášîæ‰_ò_5n‡3Üi·È bõÖ¬™¬8òÁ—¡Qs#/ƒ¹Ü¸‡“ÑíÜ{$ÀM·sÎniá§»vè´g/~ÿàÌ’¥.®+§‹†eg\À6š^ÝšNŒ¿Eý*ÖóIdÈ;cÇC2ødE”çæååCW­•GÆT.À(™ÛÐÖÒüb1×M 棧ӄ³÷&!Íï£p¢âð~޼šËÏ\ýÙ»W;®‰¡QQYï_ò>¤A¦*Ò!=7’9U+¦wS%å[tE[YÚ.;'{‚·ô¥4ÙÃe]|ü*器”´ e*Äv“hõO§ÐâÓ oŸÐ¿ ßvÁºC£ß îáÏeúX¾¸`g!5Q%±B2d¨”ÉäÙlŸœŸQ_˜¸#¿#Þö¥É9*Ú·åU%5"TÑÏ È>tµ75·‚f©(ß`v¦'ïÐ›ŽŒ¬dàb£tìÐÏSqqµ'ô˜jXÃAQ•P.ANVig¦=®Åfzêø¾v˜ë_ÕGóÙ!•þÀ½í6•X’AWfÞhÿé:_Œ% Èp2„ #ï’EhMÐñþ7gšC IŒ HJò ðNôŽ0ãÁøÚ“§¿Šp8©f)·˜\å×y¿õÍ‘ÓZ>s¦çŠ^þM‹ºÛ’½¿9êô·ùä½Ê¬@Zo2¸Kc¯¤e&¦¥%A<TÂS¶²–ö{$øˆ5¿Yâ4¶f¤¥O$ešZ¨Ÿ²õÐ,ÂÎô yi9áGÝ™¯ç³ØËDgIì ÔZ~¯Ã8݇†–žB»mÙo«Ýý7¸Ž_eqU©úÐ ¸À]_z‡˜ $‚U†Báņ.%+{¶•ÓUë¡TD‹–ç;o‰ ûðòÌ*Ε”ðD†(°ß6Ïó\»eÙ±wœíÓáççÍõQ}3(Ò“ÒS3·Cf¼Ü¿q½ú}ê/O,ºÜb¤q(rßuÞ߉b2MFfpêk3Ã6ç4õw‡¯Ýý½S<§×—Î̉Ɏm®4êÔJîè°Rg~^|¯¯ebu—2œí?ÃM,»‡Ž8§LÅqÄA$Ò®£¼^ù“-;ˆáÈ€åĆ˜,b¸7híép˜î°nNö¯GZ>ÈhL/öL¾ÎÞÉ)¸µTÖ…á8Lº b[÷@u•ð°÷rì&𠘹ší!"Z¸.Ý•¶ÃOèÀƲm°ÚÜ]2ï䩇ӥÍq6ò8œý[›ÃÑsþƦ­ÑÓÝ]J“$L4¤5¬”&kñV²W‡õ”cW¡7_[»šC!N$ƒØ89õŒNNñ›@,Ö®[ ÜÌ9ðcðõ¯~½%¶ÂEEa²còê{«¢´»ØžççÛ¼¹Ì‹–ÙêUòq%K~£4H<šÕ5\8DöDÔSÉ]ú„4iÑQSGêˆ'ñEÏ?_퟾u]J¹É,d¼KN!êK"äFKºÊö¢£hÆz„aËh{íêNÄ^c‰éRÆä|¯É}Œ!£µtµ]hã©¡f¶¼®/¡®ÆçîtMd§ÍHRàC®ÏÍË̓ò~!²äÓu;oŸú^èsK¢Ã4ê™ 5ØÁ–6ô-8Íl[—r«ñLoÕ‡O5h(X"#(>Ó¤†LÔQ&”\éÀºs<¨·ä|’ƒÓ‚9›tt2–dæ'ÕÊA ÜÊžTi EìRJ"z-ßéÉZˆúÐ,iñúKÄ#7¾P±Ó;/5?¥$µvBiaaiNþ·˜_r’Ëê eÿöa¥´EC#§q¬¤èÞ®LåzÃ}ØÔ¹úk|ÂmÀ-2A€¡Æýg¿›Q’Åâ’®Œ¾åªzph.ÉÙ+êó댢éS¤„¨Ø^¢êÐa­–¯Awˆh$îÄ=b9Hh¶¡;.©nÀÙD5÷dkŽ%‡»p.ÀçÅGvžÛUrnBkr™GÉ:˜ KÁ$®J\1 ºÅã-RDP&ɤœ‰™úEîúý‡ï©H&ýߥ4áäÐ bõJ‹ßÙŸº¬^½Ñe<„úþA/WØÑ¶qÕyéÔ:Y,:Qˆ\cZöáZÏåNâ|=øOÛª´°ŸûnΪôÈÂÿ®aüYÙ±[l4CKHu„ƒÝpUT5Æîîbí§{[ TD©ZÄ¥dn #'¸…É5 M ²¸wkcwâ2–_ö¾,{ˆíØÀ7¦} S¸5—ÍB`mîæ¯†íT•ª Uep:‰½4äÍt‹”_ZÔ²/H{ 8ä®Ýëá’Ï„›öm+x§’“=™YéUâÝ GŽ·rUÀPöz~`Nxqšº“ì{8‰Ê M­«J<)'™Ï5M„w¸~ÆÉæª)J3úX¯CÚ÷qýßPìK¬JŠ¿8OÚå$:t)×Hãüo\k`†›:L4í¿1oòëèºfÍj·ÿð‡f)ÁßÝõ Klî¾ñøñÝh#X§hô{´’J}\í4½ÏŒêyD­âlr.~uÔœÔ*6½u{ErÛ8½ƒ}ë_îüˆ&¬«b‡w94C•]EmµtF,ÖJŠõ*s}]¢¸…f™À‰Ý@¾KYšºFBI»´תò“kTß&A$$…g¤®#ëÒÝ)Ù@žª*õÔ½£½ —Ï2øÔEb{­Kç[ %àPjØ¡Î)8…ñ¹û¸,6×ó‰ÎÊ,×C½^ y­}•Û«÷4ÇCø%–¨°¬6vÐÈΨq=G[ªkzég¤1­5,Z‘p**,ÃaýÖc& â\ý Ym©ÿó%à ÖzºöùHÊÖrZá÷žæ3ʵg·öÇbi`~Ò]Mæ×„ç#ûŸTRÈ~þ ß1üèÓ„?F’ &ç®=o=¡ï­Å„ÿðÒ"Më¡Å7µµv§u;Ñ]'‹Ð›µðÕŸ¨ö×XÝ›/HÊKÉá0PzuÕ7äÕ£`^&¶V(ƒÆ¢¬6(ÌÊRg—fí4ì²ÿq"p(;Jf›`<çrÑí© ‹hƒ Gwq‰¸”KJ9!bK´OŒ§aæ¾iÏÇ"´׆£r bÜCƒ¨EËn}•¯“ÅáL½=n=5Ï(6w峑AU‚ºNµï÷:˜ÜBI@òèG”¡Í¤Ÿ_eq‚g´_ G>°¸.=wöäÅgçM¿Ðmá;¾÷>èZø…Vr]‡aæú­(áƒ!Mˆ…¤ÌÔÈ´ø¨uÎÀM›åûOQŠ/i>†d1Ë·JY \­¦¢éúHð$sß#Ã'«F¡Š{~®èMèçÝþÔëÿ¿Žñ> Ü'\ïki¥è©Ïgÿ™ÄÊÚý›6•o¤$?ÈÈûã~§atÀ†Æ&,HWzNŸ½à½«?]¹|åRûJî0†ŸÇ´’Ó:¬¥àš…+yM´!»øg2” ?† Wë'£‘rÕÑûu† EºûÍH UrKsÅ~ÇeçK¯Ÿ;}¨Ø—½Ú=ž.hÑ–o‰îÑ]sÌ׳sú<®?o×t6J‡ºÏ.¿&ûg"*q¿ÊëèÉ3‡8u`Ýê6¬ßôås2÷*Ú{pýåúæä¦˜FMImîάüm5©;€«¨)iª‰ÚµJL„µªõ~±Å¾Uë{}Á\Jç+üË¢8ac“Ã!|KåE Ξ°¹©Ï–Òíô Ï.|+@[ô±÷â ¼ªßn!›ñ’G7Ë ¥‰¥*5dCnviî‘‹ü˜¹‰PYÔÒ¢®+/‚ëÀu¢%LÝ0wã˜î­B7 ÞƒVf៼p–ð.xúEEq¸ôoP­Ü`²¡šÌ–Ò%§éÞ€ ÙÇ7ö?Yòž@"·ô¤¸Áp×ë&w±=u»ýؽ»èèP½ ±—2F˜Â’\ ƒMôÄ'ÆÂŒ`eOô™áÕ!!áá!!ÕáÕÕ‚5‰ÒÒABM҉à Ɵé-úObûkŽC»^g!¼C}·yÒn†„ì¸ì¬š»®QQ¡ žó3ìÇQ¡Õ%AöPÿë߬׃ÀAfTñíÃBmPjÙj¢ª'šˆ\–L#,ñYORÝŒ|ØÞ¥\kÂŽ&Ûœµ·Ù¯nÐB¾Ñ³uîv~ Ñ|à¿IÿÏþkw‰†RÍÏ›œß1顽ÕðÐÚìÀA†_Ùm”èGñ™Í‘ \€q®’ RŸˆÞŠÞëq!‚îíq‘TÖÞ¹ÿèþšÒ7(¥Q}e¿ù§›þß[Ò©ÚGv’›âC¶Äíé~»!»Aʰp®ßÏn¨Ê¾ ¬ûße›ÿLQþpÊÿðÄ8¶»d_ôö@/ ŸÑaí ¤xâ/tço1q,±%²' šýøÚ Ä‹LåÝo>üþòå«×.¹9MtŸë,Z¹ß0tšGß̸M¥tÿÂ'£-þfJôÎÙ£¦ÌRï?·b㊖í[ôF÷›Œ깇ޑïÙ{Çx Ûš6Õ¯ ,n1ª›Å‡fâçp¤MSÑ€µ&*ðm(².ˆüе3f8»]¹ÿàŠî«›‡g» ý…Á×uèrWvåt†þpî',d…UDÖW­.oP'˜.¾‹£=–p²/öô´13¢þ6¹0Ó¤JMzÈœí)‚Ý5-&hµ²'xœöš"72Gžœ»¨>æê[vý(| ¥A9¡Y1Ù1»zÕ³®O"¼ñ,æ’Šçö”¯âa5·u«¿“°VËo¥Wn/íUòãz„|”g•´µûœÌl¤Õ™Ôòõ'¢ì üFxM@^7D>×þª–R0‰6¢Ü0‰¦›ôÙô;lÿ«–SŒÃçÉ`ÇîsýÆíƒ• ñõWEÄ*÷I àfɺÞy}¡öQø¯>+@•À™ŽkÚÔ×~ñoÎL˜»[¬ù+•“"v¼.ìº ‹Úûw´5rÖÛOàM­¤V¿Í\?ÆÐlÂcqY"!7‰oZ6þéŽ~ªkfQJ–øÑý;8TA ï¦Æ5è¬Cs­¤\Ÿh®_o°oïa-)Ö-p«ÄvörÜRÅn¯?’°?úbF±/ÕßQHõ÷f"l¤ú{ ·lïy¿¨€¨þÇ5Ð,ž'¹Šœ¸}à°rŠ*µu÷²Jsª©îÎ[ÓF䦔ÄTRÕÝ9å¹Õ½¬"iÐûè[Î#‹c-÷™¼£èºDçÑsžXÖ÷)N2 Gíd‹ÉX2„LµÜlüô½/¿C›NbcÒ'¼éµþ56÷r°¤]‡û»_c=ç5j:‹*¸=á%‡=›µõÆÍZ=fKÉeÒ©Ê€¿j¨ô6lu>Ýj”qg¯õ¼Iµ´÷›½ž¯(Ÿ¿Ä÷#ùÇ©ñÈÄbýü"œSÌ’è©v nÖÊJg5Xhb5@_ýÂÿ0ËÅ? endstream endobj 554 0 obj <> stream xÚ-’}PSW‡ïMBrP¶,Ö»b­7i‹T-ÔD[¥Ðê"E]¨ –¢Dù á[>k’7ÀðíR0A Ù˜€z—–ŠPPÖÕ©v+:¥hµ]ÔŽv{.sÚÙMìþó›yÏç<¿ç=4%Q4M{Å'ì|7"þµÈ˜Ø÷’Oj^Ù*=øÿ"ͯð¬_&ZIQñqç}owNÿÑ«\!6/¡D4´úàà ÁÁë#ÕÙ…šôÔ4­luÊÙº°°ÐÙúàà0Ù;*¥&=Ež%‹‘kÓ”*¹Ö5dÊâÔ)éJm¡lõ[iZmö¦  üüü@¹*'P­Iݲ&@–Ÿ®M“Å*s”š<¥B¶M¥•픫”27s ;"Õªì\­R#‹Q+”š,Š¢~T°'EyP>Ôêyj)ÅP¢–Q¾ÔrêÊK@Ñ”ˆ¦_¡3èïÁ„P-‰2D U|Õs<޳töþ2ÿ^œÿwïI3}{¿Êaÿq!žZ`¦ª®dšw£ýgI³•˜ë?«”ÂXÖöi¹Éh‚6dS|$!èhpøCÔ™}yç“¿¨)GäŒdsíûÝù×Ñ@íÙ¦3™-EºdC‚â;ÈbYØh4¡©¹~ öj¼; Oa$w@Á%}‘Ôß‚ LfA0#Ãã³ ˆ#„Á‹ lá°vľ¿¾¹Øó =>‡‡ç„|?¾ÁÜl%bbˆbÁll¹Áº'9l7çL_„‡pþ ·þúåÉßësp5·ckk¼)¶@4øũ߈,Í÷Àñf®ÏLcë]!& ÞŒ]*6*z¤RH¬pÆmè×jI”ú±É ñH팎NÁˆ——,ñƒcN©ûšøGLÝçè˜ÂM? ù¼‹9(6”TD)?ªÛ%€È.1^ú´»ëþä)ûr»½w¾B؇xÜ$/f]Èë ŸëšOþ­ýtG©c?{bpâìu@?¾½I ï~ñ^4© *ߊ £2¿]ìÖsú –`©Ó?;é¹ÿà2,â~<Ã̌Ů"‚¨Äi6øÕí»ÈÕ~j….Ôs"#[U$_qøy¼úÑÜ#nÆÝ"‹í·­““ð-ºóú8ñ"žë÷„%;ËÌÖ®öNå¶g×öý€'s6JáƒÌ×^Õ³ •Pa,7ÂTÜ mì3؇ãÌ4OM ù ¼‘áˆ'¿Srê5l!ª*ËÈã_“|xr³KiY(›¥›M³5}}³Uf—Ò,I(´8¥w$y†ü—Ø$ÏŠòȽhqíi‡-…x ?Ä8+{ôÝУp¥§­ér/XбŠ=[F(×§–$”ì€aOã¾¶ŠZ}µP ”Kɰ¤ÊÚÙF¨©­o8éèëž„½¬=$EU\ÆLeRq2lƒmgs.˜ê8hA]y™•òOöÝÛ€—à•Íc,zJvìÍ;”~ÇôvLÍ9ô•'¸ÛŠ¿cLª§{.÷}sÕ>'àœ¾S}P§; Åèp{®Ý~üø©‰¤ «H +H:ÑcìËrp­nâ’ÃÁý¾‡nýäα4ÇþžxRÓw#ìG®3ä%ÀáÜݱoH‡Àž×yȦ€}Û éé)9ªCʼnÏ>xž…|à—;/ä¯ñ?1MP 6DšÅ Ǥ¨ù°¦ÌôI':(N%j3âKÓ¥Öæ†º»ÐêÒ’'./Ù“µ–xn'/ @•x~ÎcmÀô>¼0þÿ꿹jOâ™Q!Ïàߘ¯£p=|yèâ±f»? 1½‰Ÿišt¥Mº(M`ø#â‰}þ‚^Žw°…ëòÞ#­í{m©fD¢1S‚ ΡÜv|=u+9œ…-¨KЛfšu¿ìê*±”ލ ½t $ðÍ/gX˜¹3:bþÇ6ÛÁû¸ãî'B>_c`ëÑðÔ]EâÞ·A {jÔVG}cGÖ•ª  sÓ¿T÷p –bVb=Î’¥„!(ˆø²n“ŸNíK>ø&܃þ1 ‡ÈÚh&²O[ÔgŸÃ\ÎÙkëv¶¹Ä­²5eÝîͤϹ6ÙŠÕM 1‘7K¸EÓ‹õ^^Óm^`‰BÍ^žüKÿ«ÕCQ endstream endobj 556 0 obj <> stream xÚÎ]HSqðÿ™ÓŽ:íWA¹ºI)t}€,#’¥ °ÄÒÊÒ¡'·r;:ÏÜ?æœzÜëæv²£NÜš›+WV^D”}ÐE—^$!ˆåMÝõ?¶ 6o~ð>ð¼<’JAYšêkmÍ1V[®NgMqÏŸOÛŽTñb®DT¤ˆ¤Š é?™$!ô{oÒ_»“~ß“ôhÉÃ}HJ¤¥gL¥:U RÔ0íÝfC«ž¥òšó©juÑqê¤J¥¦JŒ´ÙЬ3QZ«§:6q´Q—™fÍvSygõ,Û~¦°ÐjµèŒŒ¹õ\þqÊj`õÔ%º“6wÑ-Tcb©‹:#MíL/ØQÃÛ-,m¦´L m6!D¤£dKLÌBGP-’J¤‰h‹X¹l¼¯¹‡ÏcDàŠH ®˜•Ã-P—\Œ’N~Ä'|ûŠÓ?[ž7¬ ìXRøÁï½+ÙÛÄðõ˜XL´qº¼®¸‘k朮‘!pÃλŠÀKO ô6$;⛆¹©qNé§Ý°3BÀã]Ãòƒx&ÍÃz óD‹¯8²·¯§j°ºíwÆxEÂî !<> À a׬kÞ5 dòÝ´”•àâ¹¥Û’ƒc!—·ú`Ø9ÔOÆ{ÿ–Éñ ¼þ4¾žš-®Ù#þM\»é‹?ðêVŠhóä7öÛÐKÚfz"÷£áÇ/jç• ¿2Ðe{Õ©’ªŠçt8xŽWN‚ÇëöÅ~~‰-ù`ÁÖ „Ö¦øéþú¡6£¶¬ÐÅú¢Þà<,›`3u˜ uo­Ï`iÅ”tDÄè=Þörü Ò®Ñ‘^‹¦ªö*¦ö¹%„fÞM.OÌE1róSOß¼†9pþA2Û5‚ `&”× »Ò¢ ,—eŒË2c«™ŸL†7rþA/¸ endstream endobj 557 0 obj <> stream xÚ]PÁjÃ0 ½û+tlÃIƒB¬)9tíšvÐÞ[É ‹mç¿_ì†v@OïIzâEµ¯ŒöÀOdeZmá`G’ vÚ°tJK¿T1Ë^8Æ‹ƒpŸ¢Gà§ïÛýë¥8œ·¯×K™¾ÂöA¸La³ÔÕ¾ž}eZ YÆøyž7xš`õ®lƒë€I!iÓÁêZÔ©Gç~±Gã!ayÇ¥‹¤U88!‘„éeI’CV–9C£þõEÓÊA3s˜»Y¸ TÁÝÓœ‰æ½ñÑQX® >¿ä¬ ª3Òm endstream endobj 559 0 obj <> stream xÚy\W×÷¬+;EŒ®£`Ì,ö®¨±ÅTlX°ƒ ˆeé‹4¥ïîÙ¥w¤/,,RT@Š]ì‰I4>±E£Ñ{HñÎzyò}wÁ˜¼Ïcò½_˜°sÏ=çÏ9ÿsΨž=)@`j³vÓVûuã­mífÿž¾ '¾.2D›ðPüÿažòƒz~HQ‚ä~äN¡¾Æû7ïï#Ém„®?ÕS `dÁ VVÓ&YYMµöñ ñßíî!³ã2ÖrÊìÙ3'XNµ²šm¹ÈËÕ·‹³·¥­³ÌÃÕËYFþZ®÷qÙí* ±3×C&óýxòä   IÎ^“|üÝç`´[æaiçàê¿×u—åRo™åjg/WK£Ê“Œ7k/ß@™«¿¥­Ï.Wo¢©iaÔèzXõZÔ×Îd«`åüA$ù¨åEyS±TÅPïQ½¨>”Õ—êGõ§ÄÔŠ¥Rƒ(sÊ‚L}@$ §FP#©QÔhj 5–G§&P©IÔdÊŠšBM£>¢¦S3¨™Ô,êcjµ›ú„²¦SK¨¥” µŒZN­ VR«([j5µ†ZK­£ì¨õÔj#µ‰ÚLm¡¶Rö”åC)©ʶ% zR§‚g=F÷¨î„vÂa»÷ü gvÏoLÖ˜<-=¤CéŒ;ÓùÞô÷ŽôšÕ«º7Û;®÷KÓ˜>}võ9kæiv¬ïú¾ßò~\¿Åý ý=ú%^<€;à.»‹ýmྷ9:m>Úœ·±øbð´Á§¿þ ~ÈŒ!9ù0ùCž+çžHl%G-ý‡Nzr˜Å°I쇅ð 3þ)èy=Òh¯®¢=W?ò7ø¬›"úQks—Y• þŒ_Aˆ¶<¿ ¬Î½z'Ç8÷½Z—ýëŽéõÃ$Ød®ôþšv”ÃrNJ·h ÔÍ-ûUGMGèéårh– ¯Ñž?>?©ÉV?\ªºD>¢?QdÖIÐu×£¡ì÷~ÊeAµª2,ZRˆJ *‰RDB4D2˜Æ^´¥[û~+ßè/D÷ù¥l˜Š|R¥„p`°ê!úùqMWã´»â¤D‚WihIyQ®mCÓœÑØt£%÷¿Ñ}:Ý’±S‚‹ÿú)¾ÇŠý«ŸoXÌ*@¥ŽI”f¹ªÃˆZ"L­õÿ Ø;¶û7Á OdŸß­ÿ’+‚"eq\xlt„AxjX^4ƒg‘2dòµ¨ŸV€êÐ10ìQ§CÖ9ït´oÚuúlC}37Ú– ÜšxîL}ª¾ø˜bíú±R‰ŸÁX„"J€i‘µVˆ¬øoÙË~ ÎÁ¾¾¾¾5\6d'e¦k4jµ ÄEK`¹×j'¥R¡€x&>%65ãÛ!SmøÏš¡ƒoµ°%*¸ýcÌøáXSôÚ®Pðã%!zŒ£YHV$Æ¥bõÚ…–²4¹­ECÑà¤$M"$3©ñI±\$L±ÞˆãFî ÖéXt÷:‡û¶’LjrRªäÑ(’È>Ž’Xø&õØŒ„kQßI_E¥ŒQH ^£H=»õÀC<Ü;à‘ø¥"!(«ÐÄd×tí´>-ý )CÀß°‚°"…=0{uB<$€ªËÀÌ;7P¯/üêvýŽŠ67WM ³½(ÈDåBtÙ²q¹-M„ô¢„hË)¶"@ëåàïíUPYYZZI0ÊÔúk‡ï£œûBÞ }ÅÂÅ}m¼ t¬ÛÇ{.ÿÀ ͸ƹ-3n†5çp]×ðCå•”ÁmKñ—¬Xç#“¨spÚàs¸•uºðáåüj8—‚ &en€y° lafÔÚ½X´(ʲ9 ž:½Ý¢6ƒ˜Õª4þœíÊÉ$0Rº.À©2¦3‡vSDNâ<¥¢ÚćP_ÿjIPxÒ“YuF¯…Û¨ãç½àøÏÈó!¿-a}Dʈ˜µaqÑK!ˆ„àRÑ‹Çhvá$tX zÂmÜÓ󬬶6ƧWæÕVî-–rñ €UéÕËU§€é¨™°T#çÏrØŒWb{s¹” cx±Èˆ™î¢Ð°2ÔëåEmÿF$@[ÛuˆCgÑ/l{Í‘¯à æÆŒóÇÏ[»`OqpEEQQEM@în®¬áBáQ`îæ-ß&¯8W©“‡Ò[é¯TB 0âG«bT g"Ò`?×"zppÉ<ÀÆ}‹$Æ%;]¯×i¡š9à_äíïµÏyjûRÄ ~í:8ñoð`éõñEÝ ¢ÁzÞ™8ç…ë ´…•¢²éCùB.P*º”ø%¤&_c&¤3ñýýHÞž.„Ô`âý*Ut8ƒtº±x‘I§ˆî² žDƒî Ž×äëQÔ#áÏè9ò. “RÒ+ZKOó ð$w 9A['_gçà]°–Õ\WCŠ2˜ÂŠìZ}`¾ï^ŸH«¯'#!êóÓsô>ê3ýHÀ>ÌÃA[éÊh}¼Ô÷ÚÃìô¸¤x‰’à¿-Ø1Æv€SšcAT²TÀDBT¨¤KE^¢½ûÃar ß#¯öß‹;Ñ`t…ŽÌ¶ò…õGÏ^‡BhN(qgÜ‚}ýòƒtº‚üÊ3.'­0‹‡b1ˆ_ãRd¶ì1¾lGæH<ù)6áÄk`‡‡Ï½o²v°§%²"¸Iuò˜+zD=åòà(TÙ¸‚=8Ë>ØMj·=Ö·ËËø‹·múÇíB>‚Ŧg‚Ьáþ ÈV0>¢=ØÕD'J*I;“•šr rˆÝn¢ñxˆm"ñL°³ƒSs ÉæŽÒ€F#æäµ.é:C_bï)¿V¤kõ;%¾òö¬W¬ê˜O¿<ôÙ‹—p°d£‹ŒÑ†±ÇJ¿:w˜ÇOO6{ád\sÜK½÷§$œucħ9¯] ³™¡¿,#îÍ<ÿQ<[ÔêŸ'OóÎLeFî`Qÿy%ûŽyÂj‹¹sæ~ôÉÅ»\;vþËÚnuê~¸§å‡`E;òú^üŠï‹>gi¬ÀÂv¤Ø’äw€I¥)¥Áa¦,¤ÐÇ'8ÄkùÉK.säÉ_£RlúÙLœD0ÿ0‘Cxõ>™ßÈ`v1Fö¼|àÞJ®cE+Ê®%i§|iRTŽ[ÒjØÁ|²gøD®;"Ï·IïÃV”’,àå]êO² ¶‚Ã_÷üïÌhÈ$qä çm Õ;!?Ѱ’ÏV¤ W†=;¿7Ü#ó˜¯"¹ê`"A¼¦XuÆH×vêP=@º&Y“Ü‚Xs”%:…Ç'E© AYx­?ÂïM‰' ¹)î’¡´-ÈÓ£t„ÂÑFËE¨ºmbfð$|ªEuúþhø=tõé’bñˆ­Ö¤¶ph èyý¼5ó—-(ÁSDH)g_~y ®3ß¿ƒÍ¹NFZ"º¡‘»I:‹i7¥|>'“ŠÄ¿ð#DèƒÇÛ%ð裯°0‹Á[ð-v›2µZ‚JÑ:1‡Æ®ž¿fÁ‰™!4Po˜¨´uðñåB¾ƒÿõÔÛEê&< OÇNx'úOEÐÇ?¡Ñ{.‰ˆUEÇà ØtÑ`fàå'ÑT…Vœ¼+y¿,,Å34êøl`ò ¹H‚"èýÉÅ‚B͘Ê@oRö€þBxÉ`Éþ‡<#B‹Ð04†p·– )x±„+BÑÿtÂ×Ò]½=ƒó[Êݬ˵†1°†mX²ÙÆzï*š†5Ýózt Z€,¡í¤T2æ²×Þ¢VðvÃoE(ÓÄGä'ûYãÄ~KQ7bíôó,ét‰åûˆ¦GJÇr“PŒ¨û|‹è6æaKF'23L%ûµèQs÷~öd¿§ÆýÎþ÷~¢¦Ä‹Ð|ø{¨éâ9«ÂsHùˆ~–é9£{§rÏqÜ”üf§þ"4´ëó0×µSK Eèù]'góHhXh˜Ãþ ä- Íÿów ™ø#´Eò®ÕêŽî÷­õÈ&Òó$h!}8)ù §§W(ä°i×tð0!­¢Û#Ý$«hl†'@Äl¼ö(ªë>dî‡ÜMõ¨Zßeý¥GB¾Ž§Y| …‹ê4™7¸½ÈI±׃‘_Bÿ§ç6%žææ3ÐD0‘Ñó•Æ"]Â9÷_Lÿt3^ôÆ×, Q(ÿ#[«ÉºÍiõ¢ رÃv’‡µômM¤»QweäÎ_*ªOü?‡z²‘?=G™UKDiµmˆâƒõ‚VRL~ 䇓H­Ï… ºå¤›Ùè2­ ºjú‰ºNzòæM›9p(ð?x(¡¤ôLe`©§4`¯Ç'_®þûžÈyªNƒ#PFüõðºòOùïØKç.ª÷«=í­Ø QÎnj£e´N•Á£ˆ‰Å÷ñsôýÏ^@#3d‚Öà‚4yú>[xï‚’½Ž$ƒ¦²ÃpܘîVAxºg3Ž@ßš›¾Õ=Ò ù'(“còQá¸?¶æ£î°áut]RÖ÷\•^ä¡°GÛwëÄWˆÌ^/z#q¤ž¯½#488V­2é¼òVñó‰W 7åzWEó_çŽçŠöB,Ć`Yçes,ãÏǪ4¾`ç¾ ¼xÚF³NkrÔG[sU§Œf„Ör _E«ÕHõo*9"): ,2!9=)éòçn;õüB½É ÓØ˜,Až!‚u¢VÐÆ’þ¤³öoDgÓü¼ÎWi‘É yV á[èrhí ³Q¹Oå`¡^o<Ópð•t. ÍÝáÀ Ô cXË:„†ô‹vàÉh^C®É¤ÜŽ·#+’‘W“Ë MEÛ9üßcGaÉw()Ðð[Ïž¡ás gbÉ´Q’î4X«C—Œ÷:ßAü]a‘eǃ§/F<À Æïà‘w9K$­@Ǻ¹é©ÍÜÃɉÜðÇ<‚d%E V¡Gǵè8á³aPæKÛŽçzq( A¯X”AC™&½ )]SEÀÜGbÀc§o_…‡H`û¤üæ9¸É¼À}îàѾö•ZˆO¶¶’Ÿ?©”H‹«‘©èT¹&%TºÁ>X Ë`{«k‹ÛyÈæ^îƒÒÈê"-Rzǯ’HÁä…1û£‹£?kй} kHqs…p¡•NÐvݹ,$,<ƒSèwŽ0WN]¾Ç!NŒÏ•¬Ž'Mb¤bÛH*ê4cÎU©b##B2²÷l-Ü|l"q‘÷fZ”À¼‡äø¦íùñ¨·ÏàtåÝjUµ¬elìZqóKªbÐlU.¤D1A¼‘‚˜,.ÔêÔ¬ìü¨ˆ'.®¹Ez dvçå+ ´í=P¹ã´SæŠ\⥡¤ÁÂu‚:=Ê|„2ôF&˜Íþ›á@Rqæ Ù…h)U* C™Ÿ Ž† ºö ãvÛ-Ôƒ$:r36\»èa[m -(S§&ehÊ!ÈòBï<»‹x2 Fƒº‚Ÿ7ÑwgÔ¿Ë=½h< õŠ84úúð%‡:éJhy·ûã—42vÆèuؤ-3–gE†¡zA¡Á[ˆ<ù—,Á=ÔLåq¨ œ[ÀÑyŸz±QÀW™ãâ; æ)ûcó S’sÐ>þžyÑÉúœ YÔCá »w©í+ŽªŠeà1*eB^ßbnöº¾{¿‚ס!êšÅGª’©d¡oƒò®=·‚Ó†X°5J8ÊÌÐôˆÂe¤GQ)¢TJ<´s®9žÉï#¬¨Äw®j#J¶+rîì4OOŽË‚4HÓ¤ y|Š9šß™˜ª‰Í‹,H6꿉¿mžÛT®=gd©Â¤ž>êuF9—T%^ ƒxe‚2öOÉê a¥™¤ÇkQS\†‚$‹Ò:µžh±SAJfGÌ"«÷Óç!'&ßùâ§æxÓ_ØEf­m¦‘=ºTX¥¯½¥¶x¢G`÷¹Õ„É$©ˆ‰$:0PÍÿ¦\Õók/œ3 fÓ²)Ìþæ:Eò.ŸLEâ#WÐ$âÏ3D#; 1‘¤ï‹µI…BŽ÷íG…¤‹Á\ð¼–Òc;Î!%þ"ÒïNé[Uñvlyp¹ òh¥Ò8$d”’.Ï*/´6i4‰ÆqOr\jlÔŒ…Øte™sCMAy¹qlõÏ-äÚ ä®­x\CÚŸ›íhÎõk:±ƒ=¹Æ&;W¸7£½”{[rÆg-‡­îîКÇ!kÚ Ú©Þí€CîV`f.q^)- -+/(,kÜž¬’”—µ¦Ws¼Íušd-.£6*Æ/ó´öÜ .Ììg¾W8²Ç]8x:GÇDÁŽ[èµ}Ûöêc|Öö%š˜bÌ\rmxo©En ý_]EÚûâh9ºÆ’¸WgæU7Í;p8 Ì¹l‡f-IÛâ6ù¹zî”n'p- ¨ /50ÑXýöc>§ÈáôF=ž¢A¨ß˜±©Ä¶yø2âmè ÇÈM¤ôçé±ö’ÎvmÆo“ëPí÷:Aõ}´4Áÿ!»7!(¼¿Â ²²¢ýú‹KNÃÆ[â~˜ýy,i~$U¨Oz–œH³*[ºÞo 0+gŸ E¿Õí–ó’l8¥¬ócœžØeÙA{U|€·@¦,„€bß^©“c° ì—R¿¿Få9¨‚–”“e‡‹«êõ'¡ï-wÍ #Ì$^`ãSœNÎ#NÕ×r,fq¿—£PoÉWÐÔ˜_Dl[I£ñ™&zÚ&:õ¨„ÿùφšñŽÄHR4_+¨¸Ÿ ù(„-N†¢ŸÖ?Á°éÄáø}<è—Ѥš2;úª$5>%ZŠXUÂî‘S•ûÀv–˪÷U‡F]ʦ£IòtpÎ;«ñÆ ý1fF&WÛ ÑÉ®Ù}odB´©‘Ë <#á?f÷]l˜7{-áKúÌžß=Œ'.Œw–£U—n—£ØrAÅ´ïFõ!ê‡lXm˜~_30O®}~KG}ª#r×¶@Ä“2ByjpIN^FQA¸Þ…ó'¹‡»oñ®g`&XÛÌ•À–J÷¼}J¥8Âî<÷ò-a.n°Yü @}9yƒƒúà#n¥ëkÖÁ">£ñN .'ç•—œ›žÍt$°Sáy±Ê5ÕûKs ËsuÀ<‚q2Œ›"iÆóÙ*ÔWõ±Ý|§‰cµœÎËøì¾¤{8ßåÔó:r».D+ +Ø?»hÞŸçí­­Ùª“ÌãWпþëÄ¥sÙök8öÎç¶€?¨ô Ú@Ã]¨ð©‘é\³·’ÃÞCºžQ‰ŒÃrl ÈQýo!jÑUq;Zůfñ£—Óãì%¸èwÉMš"õ‘¼èšø¯HH>$ÿ˜ÈìWHeþÞÞ%þúîѺ‚µün¹»ÚÏ jñUñ/ÈÛ(ÙÊ(ùë.Û$´wÂhNAˆ, «*t$Ù–úz‡ùn>ëÓvëÒ§?pâvÄž¿ODþ4>D4U"¿Á««B´y±¼ýNäŽh´ê†z­ªé-r?Ò—O=ÃòÓ"!Ü"J)í2¯T}¨¢ *Œíµ{+†6š?ÿ¶ùÐç‰]¬7/?õF#w䪲b! ‚Ã"¢c˜. ‚£ï Ѫ¿;ÂÿùÊÄÌð¬+nµýànü%¥q‹¨›ÇΟÎßµä¯Îöwø>ø''xº=u{K]²Áì}6Ežs© sÀ~ó^GF|Gõ\„G¾ÕþõÆ¿¿Xz£¹ÛuqS—ÚÿÌ#'ÁŽ¥á>Ä#Å7žÑÿk 2ä:~\WF«½/äƒÑn þ3î‹Å£,IRë÷óÔ‰üõåpÞÂng­ì_ƒê$4C´ië+Ë­%üVïY¸»ÄY½œÁ Öùo÷qt r6ŽG¯àMz4AËÔ‡êú¿ºŽŠïY޲ÕgO6sóüLa‘Í´%„‰Êj" IÍPÀØô,ó«ÞóÙDÔìKÜK²¶ºîdÄ.½qÕ«)q;$gå¡7*Œèb¨âëÆÜýŠÝvË.݃PA/,0ÎaÅcÐ{’8žÛxšÁ‹ÿZÆŸvÄmFúIØçë¿ÃÙs0‹V}GšhæêÝ7›gm {Žúýl_]}õ9Ù¥„-ê3Ñh$âT´RE’xã[ZRT’[YåUéÄ­gg™m׿öŽ|GN7ãÇʵ¼U± ú8Š8.DÏø»§@ñ¤¤ŠˆT*££ãâ¥ÅÒ”ÝÄPó=Ÿl‘€gŽ_I`µô`ìñèãQûÅ¡1Ú`pe¦‚pn$ø}yJ‘¡J‰ìjGB$x ÑY)¼ÕùI)™ÙÉÉ ;›Zãà¾ñÚ 4•–ì>àžº(Ç/ù“lhcªJ¾ç©³4þêHˆËîj— ŒïÔˆ¿‰õhV¡à×ëh°NˆnvqÜH´Ê‡VÍô1NÁø?À4îyGvòJÍå«\›ÏFz‘ÔÝ}|—Ï¡Jú÷rÀ¤ámÔð–h;uëJëYñ§8tÆãèÝÅT Gà pnö¨ª= 'àhIÅyF¬ž%BcÞr=BoÖ¼áúCò"~0iIKÓWW—^è\ù‚·kH·¹ÊìbAX´<>nå\óy/bÓ•Hµ€¬Ì¬ãÓ®J?•“ÒvŸþ4Êæµ?aÖ<ÐoÓò@ÿ­kì”{/ +Ë¡¢ªJUe IÿDÅ~È 0ääæ—êË*µ•·F™÷yTD€qrß@x©QÓ‡Œ \À uFý ÃæÝãeøo…hú•ËdÐ0eÕPD ±W©œo”i"½^–/šÚI›û¯ Üäm³,ü!4[¡ISëÒ š°nžÌ?$ÌשÁí÷)4ž-=–ósÌ3Ëòë/kˆmž )DüîÍJp‡“r.fŽ6'54èx3­ Q.Þi$?¼û5R“¡þ†ôN³Hï”Ò‘_‡LHìõášN&ÚøÊ2Þ",Hp´“ÖÉŽ´NQX±÷3Î Œ­JÕ €Ïcµþ´Ù묮¾Îcµ¿eùkCþÓÁ¯Ï:„hÿX¬ÄÇG&óñ)‘ét%%:9 ü¯ÿ™óÖû‘wfJ±ïÌ¢õ½®÷Ö¦˜š^Ï3íÃõê9³Ðô=ôdÀÿ”ÇúÈ endstream endobj 561 0 obj <> stream xÚ¥yt×ÖîY£ŒC̹„Jl0ݽJ.r¯r•¶äÞ«Ü+¶Á`LÇ!`¢# $¤ @r +9ÜõÞ‘ms“ÜõÞú±ÐZãsf·óíoï},¢,,(‘H4d¥£ãÊ•¶S—ÙmÜ8ßô‹¹‰8JØÿb­DG ¯‹„7œXmñE‰J†‘oêék¦ïo‡š¾Ç“¯Is†S"£ WÏœ9gÆÌ™³—ÉažîAÖ“ß¶ž5þ¼iÖ³gΜo½Ä×5ÀÓy·ŸµÝî WßÝAäÁÇú¹³§kP˜õä…AAŠï¼2c·oà y€û¢·§Y‡xyXop t vu±^)÷ ²^»Û×ÕºÇæ=ßËä¾ ek€µÜÅ5ÀØ*?`ÒØ%¯m°p¤œ¬£ˆ©(1eAÑ””b¨Ô j0eI ¡¬¨×¨¡Ô0j85‚I±Ô(j4%£ÆPc©qÔëÔGñ”55z“šHM¢Þ¢þEM¦Þ¦¦PS©iÔtjõ5“šE͡ޥæRïQó¨ùÔBêCjµ˜úˆZB-¥–QË©ÔJjµšZCÙPS¶”µ–²§ÖQë© Ô'ÔFjµ™r ©-ÔVʉÚFí P"b°Õ Ú-z1àS±Dì(Þkag‘kqÍâ7ÉHÉZIä í@ÿ(]+½À,fòJf ƒ¿·´·<Þ&ÓdÇT@äåi+´¹ý× V GüM4þ&"¶ œ`ÉvÐù­°¯Õbywº Hßc¼ Ù[‰ʦþío—ѱ®àæÚ ùü9:—줣ÝÀÕmäòÍtjP3ÁEáå\#¤U§µ¤7§Ö¤µ0?þ—µtî>hÝçѼßAãÙ{DO¥­Þ¿ˆÆ^D)Ѹ‹¢æ®Î®ßȱ°â…›–­Ë€L¦"´0Œó‡øäX\óÇ2™:1%TLpq¸ž«‚̲ô\Ý}ÆÞpïrtð°_º´ÅþÄÉæ®Ü»«ÙøÐŠC‡J+²²Jƒvî Šçñ&ÁÈÞt?KvÚ-ÿ¨eÙyþši§*¬²½ƒìÌ. ܵôÓ*Ö€ 4Ü zÚu· %6½' `ëé‚ZhlR@$?ŽT€7 ÅêÀ5¾ïÉ·DU¸u…¹q«þœc.úßXµ~ËæélÌ·-Üáæ¡ðŠsfáÑå7¹ÓÐÖRÓ¸×u¿o0—k®u앃Z®V$òjï¨PðÏýÑÅMgÊ:S3¼½ÎF| ‡!›9UYWÑ K4øEønYÏ(ñ@6_qt^™_ˆ¿ŸÜרO›xhË*ï8ÄX¡Sz´î™ÕÄè‰À=ìtðSr¨Û},E ¹Z­F§Dò£ˆ·Y¾;.).˜°âÈ¢Êß/£‘œÕûúA$ÅšÍ,Åe¨2±ìÞÄÁ¯pKo(ïh»uìÀ‘†ÌôŒlÈerË\Ì[ÿÉ»›ßŸ ËauÁ´‹ÓŽ-»c_LMFYo¹öŒ5Åè7t†…KQOÖ<ÙzýÃ.`äIÊx"r²‘ìݘƒ7aq°r‡óâ­{¶ùÄ'&Ũ2‚k¸ øæÌé{§¾.¾×«za,±3äªA°º*­j˜,höðxZ]ÀÄs²èLµNLHdD(1é1%q¿}"¿!(Â!iLhaD— é©é©ˆº Shl@ÁăGs34gqP£1¨«Jc+jÂ+#u LYaQ)eQY‰©ÊüEâÒûLV‘EÁ”F…p*HJIJa¬¾Ô£n¢…ÄDåM1:…ô,â^fF 9ÄÓ¹°Ï¤_ ‡yÌKû21G䉎×V²9³Â¼ B#DÈ M£F›¤ su W¥„%‚’‰, +m|~ YœqkßæàëåV£hå2!S«Ó<èoŠN 3ÅÂ<¢ß¬üýJ™ôŠ!Fw>g[}j¼Ý>Þn ŠÆÖš†Æ—p8#L ;^X²YE }™§  MŠÃ_ü±TH`‚J#K¸JÈ.!yJ’Jƒè¨5()ȹ£µ“Ðhl%oá±Ø¯}†G# $yŠÆ"{á4öC;âéD4éòׯ_ž‚'âIvxà‡ÄFƒ@ž‘P&]n³…PãÍ…C¼*1Úg…³Â9%R£Tƒ/’SɵÁ~}EÓýÎli„?xy×@!ÒéÂ’ÌþÁϦMc ¢“P†Q|é<Ÿ‘ŒW qè{º);k/_'-… 77VpXIŸ:Œ,îWU´¶\¿?3hðä/ðP<ðƒÞsnŒ+,«.®ç@Ÿ™”^|èPõ `¾4nŸËÊMöÎ^¦@ dr0ˆn<êq gŸZáh»aÝ\Þ§yrZ % ¥Óåhµ ƒ4¦*Dïé9çñ4 º÷ð wíNoÓß8™y‘ ýöâ‹X‚_[³u•oyXU•¾¬šƒì”ܤ̦dsµÃmòè=.þáašm).êSˆˆ“… ÀsƒÀˆ^ïïCÀª¢ ›3~iQû8¤hOGÉÁÛ«'r«Í4hÿÜh~X‚žÑ{ã³=8?:5ÑÁ žÓM³È=–àÇR“Û4Ë úÖˆâ x¡}õ2.£=Uñ®<Η†€3WééY9õ-Ç€¹shÅÇ‹V®›Ï;ƒC‘²]«•eæhuº¼¾ÈT‡”ù‡Êc\Ü]Ž$hØ/øÙŸð@Î ö$íR2ȶGyÝE4× :þ *%1޳…hÌý¯®‚¢ˆÄ„”XB,AÅAu5e¥õ‡½ÏNÂãÈÏkØ Ç"ñG¿"Ñ/_£!H2û¶à6‚cèw&¿ÍBvr*”0Ÿ}vâö—'m–Íÿxò J4RËYÅê…&ƒèñqVBœ]·Æé#Ø*žÔÊíL4¸·¶h÷qiH‰Dhå¯OKKRuPȘÂáÛtBQ8¦rƒ P~‡4‚Z[A_Ùñsƈò‰/Ñ×ì™âKp…¹;ï¶Ä–óÎç`å¥íg"lB—l„ÌÛ?Ì!.ÿáþO|½¸Ó¶„YØÈ®°oÿôxç‘[·:·mÙh¿kÏY,°=}ñÜg]÷¾?m¿ví' zjáÜ‹¨ŽDΈJ¿ PG,œ=¢ÁOR˜–ž–ÅLEx…Ÿ"$Ôw{ã:D£qè549 XLÝ| K&Í#fIîÏB\œÊ?v‰ESXm‚.‚°Äú Ž‹>p0\ÿæÊ§×¹K°wcñf]¢6Q›Äh“€üÓ$·|ÓÄMh…™Ÿñ_ fñWÒê£Ì—ïÊþá]Ûn1«ò ”ûF&¤D&@h™–ÿÔ‰$çûv»+䩸®ÇÕŒÕI½àVÖK¥ë„06'³ ôL•2?’SC,DÄâ[ØE›!R ÊJB÷±·,3%K£¦¤¬°‚ÔŒèì¸LÜŒVÉ¬ÐÆ›·oŠZ…ÍbÁýÄæ¶fv(ÿDG¹þ«…ô_è9žÆì'];éê°@ǺÎÞ|kÖ£J6/+7“´†eQÙñéø>ò–%¤Æk5À„…Dñ’¯ÊI@Íx• Æë’Sâ!tL@yt!—éº ÓÓõ¢Dç¸û Ø”ÂBGÞ©Ÿ;;ªJZ¡‰Édݰõ›õf²)NNOΨm8­Õó°Ãß“'¸ ŠÆÖ á]ØÃx@Ø /çrð ö¯M1„ae¢ZÁCŒ® _³ õqÙžÀÄÑžŸàƒu—ÈÂzÚ.¯j(⑨—À•àÁëKÐ Z?]â¡|Iï"3½‡ÑØÍañ0ºI›ÐŒ´ýŒ–Öå8iˆ«¤0 Gƒè¾ÅŸ ˆìeº"¾º[éO¿zBÑgÞæá¬Û•YU·ªëÏÂ1Ƹö.sx8.`‘#²’Þ-[ëã®X5…ÿÞÇ"'½[»|§“Û†y|_l3¢#·ÄBè˪¥„ĘÏ Ò5ë€Á£°¿ŽWãÕh~Éäþ·Oö* ŽO_PûÇã!Ô±ÀÌšÿ;©‹oûü;¾¾Q•â¡iUL+T”öÔG¥Aô¥åÅgû»¤ïV÷sÉ™F£¿GãÑ»èݹh Ãc‹îvVP>”"ú$)Êb̬ǖÖ&Hn@[ ¢ÇF4ÜØE0±µ²h8í ¡­&Ü“¾òêJ¢¶ Õ&º—±ÈÚmiS|¶'×=Ьº®[ég~øÞû¨OHP(·‚T“ZÓGô‹2î#j—¢jú{µ£ JúµCéÁE-ÁEc·ÒÛü„fÑu%rR€iÓM3 ýQ«ÎÞ„ö°újhj4­cK3öÚèø…KW³xñ¯è_èíÛÏoñpØ)w‘.RÖÔw ˆ—öp$FF˃JÝ*7’¶œHŠÊl÷+–¡Áühk(.füsbkzL6ãñ#r!6Ø’ºQiÆ2¶¢_µ0•Ø» Ç?¯¾²±²[Ø/[¬Ì» ,]°"Ð,éO«tz’„û$Q(s”p;åGdöDêVbªßs{¿}”)œ¦žêÒ#´„ø1•ª£ {Ë=±Ôάýn÷Tzᇉ!\ìÔÊõi©é¤V†•Ëå¡!ò5—v<ýî»O¸>³îu‰Q=zÁ¢)h½¤UONÇÔ>Ì2aÉË»rx¼gKP¶^úJÙ$úðÿÌlP0I? ÝÃë8Që×·~»7,Aàû2¥~3¢h–ÕÄ›Oûy3ßé–n¥»ùI°ìö¦•¦¡ÜJ-í“v¹ é‰;G…7Øhçè=‰>Œ†N¬‹kˆm²AN²¸:U6™çÖ÷Ú[ õ|·Rê؇ݻ½ê‰m‚»Vš˜í—íw™Ôœ´˜,ÿz¨‡¬ê´¼ÏÑ&h+®§W2Únwúo_VJë+û0¾žö \çËôÙ÷° û„«lÔ¾`P³üFõƒà©¥ v;oC,d®z¨$³_‰ö/h+¥f¼RýÅyj討ð£áG^Ž §{ÓÐÃ4* ®ÅvØ.XÛñA½Ù!ÛòtÃ{Ș0‚ÊcÇœ„/¡ >‡ëyù'êò¾€ÛГ¿)w;Bía¬ŒÙ稜 =´¿Ü€zøLÕÃf‰,É4øÚ£~XþæIÿd…dæ“÷£¥Å3úÉU{VM#P#¶oêc­á$‡—GD£_ÑiödSý ø”ùnÑפ5Å«þßRÕ…qâ&] •š:ÿrÂl°Ö‚W‰w©w]D30çk>oß+þ ñbÕî‘pä CUÉŒˆŽnò«HNeðÐfv%r¹BÿжnÇNû/ËÑÉ«¨é*iÌåH໩m]ja+Ñâ…dnÙTç–s`g}ÂÍðœ”+©p!¤Ô<‡]Ÿ,áö€s¶¢h{mòM©¦HSæÑÓ±†ð˜•F‚¢‘+‡ìüLÒObÉ„˜ëß?à¡QÕæ³ßåȶ\÷¬àô¥ÅÑi;rÝ[àsìȑ˒Bጴ€4ßbMÑŸ Zµ 3}úxiØßpýhÓáÁ/–¾ZéDú•ŽR3M-ÿÒ7±Ôu#Š$Psü–’™kE~@O´uؼÙöäs=¨“þîÇ4væÓ§÷¢aœ•J/4D%B¤XØHdï5ešéë&ô©öò+pk´ƒrfÒž1Z]žÐ”X=]-Û[Ñ—“z ¶’ìD#»ós\Ê ÆT kËË-^›‚¾üc¥,'8OULúåRS¿œ•œ¥Ie^ê$ç…ξ°f{Îè3¨Sþ‡§ô{¶éå`+ÁCÿ¬Lôoô•µOÙ˜ÌdH‚HVÇ&bËeÑ ª$‡˜ì¨Ôäì˜ M®åÙokóãu cj²›²y(V¥Gg2VS^^£Lù‡[~†Ö“qÚÆ`º7žÏB†úàÖT Äj4Zµ–ÌãP“e¸v0'='ƒL%á…Ö«ðÈ%Í{µÕ•sVI¦Yùƒè”ÑT‰…E¨…ýÂþ l½ý-øÈ¯<¬²¨!ã(W›ZbºƒºsØk-?PcÙ6x›Y|Åî'.nAçþJÏN ýHmeOŒà#!B3™%WXB%ÁÎ!îá; ˜u{šÚx8öt/ªeLš/ЀrÔšÈQ¸ØåÅæ ê:¤7Åʸßýa‡Hr‹zB¦ÌÁsŸb ~ì÷ðcð‹³g»rvÕ»³mV/]îòÕÉ×.D׌Èç‘XpC"V™­ä¢! TÊ„ÈðÝ+€yoå•{'~G#ùb(ФA™Z«ÑªR=kâ'Ô”•ÕÜœÛð’µxÜlõïÉdÚ|³áçBÞlûÞÛ…¥g;žF+K+6‚OЇá×LAßíÅ--Œ„än™i'½b7íXðÑÊu—ïÝ7\ºÑuÜaSì4„œÐ(‡tô Ðz¶¬ö!ÆæGÌb«i“ð`<ô×Éh$Ûñ Òä#Eff•2pÃÇdF\óö†D.Z°ë~ËTi™¼ü w¾Õ¯9«3³Þ[´½€œ;qm¾ 2Ñ:cãy1rÿœ'öŧFLÄæ©²SòI¤A^zvMdƒª˜ÇÆߛػ6¼º<¯PW Íð×ÇSQZRY£lØÌÁÎD7?y‰g.)Ó—,Ã[¾wI *"ΟT¨Ýz¹N½jwŠ D2s~³'ùðß»¾Gob[ðã¶")븫½³³½ýĉö]›6íÚåÈkñröÁûÎ+v½õöÒí<´68‘Ö¦³/QºÎtÒ¨ƒýykÇ|nlwõbÐÇÒ¿‚V¹³/¼×ïŒÑúß·š+\Çá@ï~åbJ$ôÎg¢ž®Á œùë$‹íñ(óÀ…$¸“´åf¥æs˜€nÓ=&ZáƒPe{ôšI|‘þ­à]&Á¯Ú„QÝ“iˆWwO?’ÍQ‘ÚF Yšý^Ù1À("¼ýmhÒ>4è2/,íH¤aiï¢L F’æ~“ÄLs‰h¢ñ4ü¦ýÜûö3¨Žv+úAl¦Ù5§›ôíÄ÷ÉïÀ¾Â,Íâ}þcÈèËQüÝß?%Õïù^?ëFõ„èD¢M±°}Ê–²˜MÆ'سEzx ‹W¼Ÿr]„ãÕ+­šyÜ)}uWðÀ|‘€–K¿9p¸­,?ÊŽÃáR•_ß©]ûÿÚÒ ÍÂe­¦xÏŸÙ¨ó Ê^>ýÔhºÙ<‘‹†NÿK°dúd<}2Y ‹'?¡¡vÆ3Ù¥ö7Ü¿pþÊÕÏífϲ_º”·Â=£ïÙW”ïØ~vl£ÿ Å·D§ûý9ËÊú;4HcÿZú4^0ˆöQ 1ÛAàØÞQ>ćó®wÑ;v¦'MÃÃñ&#š¿G0ØÅ©_õƒ¡éçìÆ­~°ìãË÷^3ܼվȾì"4…x„lÙ§—¾C—êV›OxK_\[Óñ>¿l61 ½Çfô‰;?è×û—ô›qÅ/#Ý€r ba‰0ží›ø“bR\K·’v‚ÁË"gÊyØÜ˜¿7¸6éyDuòhØÂøøyLåÖ‚³>älBYr®¼¯ožÙÛ6BAfVíq3PF¾ ò‡ý¤@û4:W¤O/ܱ&Z™êÆÚ‡ÜCHõÔ*uòóP’é0Ÿ“þcª±Çs¥©ŠÌéWEæ|E÷]µ„p¼o®ßàHúÍë×¾»Òelö‡X.BÔoµ“³Ò˜%ÐYÙ'ü¼…1S`Ýèy‹b<A]‡ÊÿÊÃ8ž~Éÿ6× méíõi¾ePÌ­?cZžD•‚B,|DŒïß•2sN5=&"ƒ¤ºß¹ ê7¹Ñh¾—çVzS UGšæ^ÑEB¬XØFD÷5GäÅ!fÁÇéíø DC'×DœŽ¯<•\äî±>Ö-z[r™Ô· ƒ’ãýÔ饗J¨åÏàï2]ËÉÉi‡Ôœâ®Š¯´eÚFK§Ê‹í2”Åö©ÑˆËå¹y Ѓ(€E"4QÒÖè¿”Yůž±ò‘¤ò•­ƒû_G¦HšYç~—:ƒ_Þ^øñws3ÿÀÿX3ép¦ûÊ¨ÝØëb2a¤ë²t™PΖ=œÃ4.7ý½;:#ª09]MB [ñ™|n¬gR‰EB]ÈIÿ«›/+$AÎÐå§gæB!CL 3½ágz9ÔÔR¤«ëˆçè ü«L«N‹ h‚Fú)ýbÔ™¥2us@ájyX¨Â¹a×Iþ*tž¯ûîe”ŽQ±r;úƒ-ÈÓß›[ƒ „Ã÷{Ç>'óØWb¥Ø€E‘† bÇ”qèEï$pÎ|Í芳¥d¢@‡LŸ¾r„œY(…cŸÔŸn„£PÊ w¥Ä©}h´ŽÉëZ«Õ[ü×ûÂVe0Ù;ñ5§Ðøx×h²y46vC@Ïš¿nûç¾Ê‹êJ2ÊTCSƒ\Ïã±:hæ/Úw²P ‡Ð“S£mhThUdo*„ªKªÕ‡mëw”¯Ñ™Æ%rØ>µš,¢MMà©èÑ [Oû~âMª`¯eàŠG«™˜^¸”ðUpIw¼úL=#¾YÅæ ˲ÐG¹4Í,-–C¸AarËBùÈÿ â¥>c endstream endobj 563 0 obj <> stream xÚmÕhgð{rIе-«¶Î †bW¥IÓ´Ý”Íè4L­q®Q϶£YmZ5ó"(u®i~ìšä’­ÙÔÎý´s§”ÁPæûkŒaÿC„Jþ(„ç…÷E÷^bgòf„;îrßÏó¼ï‘÷ Hf³u›6û;ßÞùR·óFŸw펾ÞÀ{ƒÆƒV•%üc!%â²ÉD6Éd¹ù9I‚ŸkŒóðRã¼½šŸ¥Åü´àP­´@¶.°-­­«öù^\ݸ¶¹ÅݱþUÏëÞí]»º÷ìïí?8 ?ýåWÅ¡8š‡Sq´(—âp+ŽvÅåT\-ŠË¥¸:”Öf¥µMiíPÜÅíRÜ­ŠÛ­¸Ûw»âîPÚÜJ[›ÒÞÊ‹G?ÚùÑ¡8Œª^ܨkvòk'oãä÷NãžçîæfǺ–ö–-CÁ½g(x´ïp¨¯×²ï:6Ügwس¾ã9šìêá@(Ô4¾òõ …Bö.e \W|güÔ€´P²™ª¥Z©Ñä€éiƒôše;¼%¤ó!8f‘ 1ˆC> Æ! )HƒÈÂGð1L@>Oá4œ³0 ŸÁ9ø¾€/á+ø¾ó0ßÂø.Â÷Òj“’IrIýÒiéwé¸à]În˜$“ÛtÐtÖô›‰È«än9&ÿ$çÍ+Í;ͧÌ?šïY,Û,',?Xf­Ë­;¬'¬­VY«\U–Ì“ººH"‹FižAŒ_j#™Ñ\¢A×ôd*ÅŸC’_&r£™­a ÞQñ†ŒçÉ\ÅÆ¢ô[/š)â/5×U¼&c–ìž7Ì+š â-—T¼"cœì™›Æ:E¡‘ÎqNÅ)GȺQ£Ç}ŸùDqŠø´L<ÑGƹQ1-c?,öàˆö3¿`’:Oø5«bŸý*†eì"ê“‘Å"´‹õTª.ÒS2ºaÜ+ã66X—ÐéËäH4Ir’MŒ4hì`GÒÑt,“Ègt-ÇEWdìfý†ØJ‚¢ØÂ‚‚ØFUÆ^Öc ˆÂÇ©¨ãƒÒ2™‚¸ÆË2N2/1ƉW0ÉÆ™WP×ÃxUÆ)æ)ª,ñTª,ó£{ªHÞeõEq“¬ó3¬^ÈoÃÌfäÓt–ÔˆùYV]:&þ;~Ä X}ŽXÄô³”¥d)ý§˜~ŒÅôcúPH×Ñ|!M1À¼OE м Vp‘«Šéc)fÅ¿+…ÞÓšžNf y;½3ßÁ†w*óµô¯²ú«è­Â»‰¦Y-Þú¿üz¼L4Ñ™yQ3•¢žÎ”ÏNá5 »ivžyqBD^:QF&ñ =4>?—NÔDÒIµ2²ß¡kžH’©ØXFôQiãSÆ. ‡p_€L¥MÆ,Y~DÅ&c>]|†Ò݆Ò­¢â–T:™.l ÿ Hö"@}¢ ¯²Ç@öâ°!zé>Qôâ¾B2‘âÇã†ØGD±Òó= –!ÎñaÌ~ªŠÂG+çqˆ' ›óÒ¸`ô$¯œËU œ**ÍV*fÅùz¼[+éM1ÏsùZÌù8[Fo‹ùex[HÛðAáïƒÕÐY1]³å3 +xíX6’>©Eõ-¢÷E´ï'u‹|T¸…Ή) Ε—FJÌ…4å…F¾”¦§NÛlÓ‹¦m‹Iì™5\Ÿ; endstream endobj 565 0 obj <> stream xÚeTmlSU¾§íb™¬æÅ{ °Ê‡‘m·]»ñ1åkˆ2¡ˆl ã–1æ6\:öÁ–Nèí×½íí­ƒn³8™Á,8Xˆ‰,F'¿ø§QÃÔhü Æ·ñmˆ÷®q´“œäÜó>ÏûœçÜçÊ` !tÝÎÚº=µëÕn;ð–cÃ;N¾©£EÛ°§©DR9I •´’d™.Y¦O¾hXNQäÀbm^“¯Í9‹Ô™Z®NÏ—P/bx.7oQÁRvYáÊ5k×seå›*·îxso@æ9oáxk)oµðV+o-ã­|Y9oãx›…·•ñ6o³óöRÞÎñv o/ãËKùrŽ/ßÈo´òm<Çq¥¥\±µÂº«­Õe>ÖÖzÚÙîròfW›ù@÷)§™37t›[Ž[N¹¸×ÌíM.—³Uû´ÿX›Ëevmnj-NVÕžŸOÑÔ Ê¬{…*¡¬Ä®Û¢ÛJí"û¨#ÔT›Zà#~ A"‰„H˜È$B%Ÿrž\ 12H†È0ù”ÄÉEŠÑQ„ÒQ•Ô9ê•$ÒA>'³ºµº.Ý-Ý¿úMúNýMý#ë†:CÌp?gqNUN¿ 'ôP’ŒÓBPðû|5«ìX߃NVrG=± "1JX–ÃÊЬyPS¬¤cž¨[bM{‘I}K2A{‚^¿×ð γ•â묈Ë/£i´",0²Oñ«õR4*ÅXᚈP-ÎDf¾ ÄÅ2š0£z %›é1ä€Ã«w*~fä»txr37ürâw×~…ñÉBXÜA'èfM8>¡;étmPaüJÕOŽßêþbÛûgØ'3åñÕpO¬6½=¡ÇÛÉ:Òöa;nÏìTEc-4¾ î+ìSgTäLr7-yOŸŒ7³#M3¸*±òŠFhÜ çYoÄ;G!x*E¶à(´C4»Ó=\Ýèšuµ;"©8”Ð’º/ûÕ@½œ=l‹µ až€SPÄ>‘Û”'Ijä+ÚðA·$0a!â‹øîS,ÙÄn(J˜Ñnyþn«ÏV{«EÜ+"è MG&Ý“K úS‰ ª!4Ç8 9=#²[ ߉=ÍRÐ_wnK.«Ä*e×…Ú&-ËhªHÔõwUÃ^Ù{åÜŸâ ÈB­ޝ¿–e&ƒã´Köa§È‹¼ÄËi ¦—Uü5ûœš– Qñ’ÊÐ+Âñû“Ÿe3túÑQCâmHiŒ¦3ª¥¸”†ºœ‚«ßGò!êºÙ¢Þ7¤¾€àg|>¿š‘t.Ôÿ Yõµ›i Gáà·°ŒOS´ôâ6|'Þcµdeû®“T;öÑP3qX—H„æÉ‘}­'°`b°ÒŽ…õû¼^&à zæájdHªC4pcp¸»w³ñüa,Þ\Ñ`9QêzVøøYš.‚ŒàßTeul¨c1×áèíõø|LFõÃ8<†£ç§¦,Hw7R¸£hg³ÈaÅ=pA÷YÍ_=>N­¤UCÂÐvX‡ÇØ {4SЊ!Ü Ün6Kã]’ŠÏ¡eyúѨƒ“Í õí³)˜‡E8Å>¡ëzèKµÓÍPƒë ~,!„™ù<ȧ¿lý  ó+ǰPîx™H úlMÐ¥>(#tº|.-°{oaC¬ÍzÌ:a!ÖÀ?ŒšZ’Œc ­…Þ'¯šÆú茳$t¶ò˜Â"vžÄ”È—¥ùÒß7.L> stream xÚuÔmLG཭UD t§¡z¶U«èyÇ}€F‰H¤¶õêÚ*½9+ x€zQr•e½e±çrˆ¡­_¤Ò´Ö¤±iÓš6¦±M“ª?ZÓÆÄÕ´éKòò£»=@ŽÚL2ÉÎÎ3ïì;ûáŒFŽ’Y²¾ø svîZ·í•’å›Ü¬º±FáÑZÊH.7b##v~ÄnyÆøÇ‘msô~ál½OI×z.[ëRïdpÏbœ6cVúÜ,š=ÿù…/嘭ö¼UkÖ½¼¹]aV˵2›…Ùr™ÍÆlvfËgö<æ°2G.sØ™ÃÁNæ´0§•9s™ÓÎò,,ÏÊòV²•6¶ÒÁ¬V«Åb5ÛòmÅuµ“«®¶ÉÝàq3“§Î´íð·Éjzç°©fOîu™©¹¡Úãq×êC[]u©¤òÝêZsâcµ½ÏžÍeró8¿ˆ[ÁÙˆ“_ͯåŠÉ®œ{›«Ó&HÄOÚ‰L$HB$LÒATÒIN÷I„œ$QÒEºÉ)#=¤—xŽpYWœAö;(Sõ`ÔG §ÑÇߨŸ ôe¢Ò„!Ìðzý¢ k¹ílÊT v©Pø¤ËôVħ¢a5¨éÖΖ ~4:Ý'bò˜ùím‚Ü:a;ÂP oBÙW—z©¢ü׉òXÐŒfzè_œV Ÿ>Ý&A©Ö6þôYÿÿp,YŽÛq_Ý[t‚*¾8ðÀµIÂÝßüü×õ'îX åÇ㸠çáîã^š¸»R °O‰:š>šž™˜¨5¬(à„°þÏxœNšçt£=¯á¼éiøý9ÃX´U«Ìh\‹Kè±Æ¦ò£{åV!Ô¢&Vê÷ö^‡J¨šÉë¤áUøaœ—•­ÀÔ"\@Ô–#ï÷&m#:pª`T%óópmœ74XÐXŒÙô¨gΫ’ù™¯5®ýýÉ<ýã¼´T;£ó ¸”&Á°:pÿÒ½OïÒ;seH‰'èt½`Ç $y*ìÈ$˜*;}PÓ ‡>¹`X+ôă( ºöî/DW@»Ûe_¿V^jg(*Çzƒî_¡$ܧÛCs 3Ž d`(æUýÂÄï-«b×"(d Qß­°¯-")‚v]Œ_=ÿæ˜hX¿C®•Aê XPD?<|yÌŸXBV½¤F±êjY¦I¼gh\Ç›­§Jé…f°løâxn<‰{®¢6'áf½ðš3A‰C2b±°*LäB”‰X¸%F |mã’$L*´áç:0Ÿû öÑ©™3‡Ÿžô4ëÿ3&• endstream endobj 569 0 obj <> stream xÚ–{pSeÆÏ!% VE3¦¢'¡ƒ ŠXA×E.3€ºX¶\ЍÔ*½ÚmšKÛ¤M“æ~’7÷Ksiz-é )­åâX\¹¬è¸+ƒÃºŽ;;úpâº_*î:™w&É99Ïïùž÷}CI’·mX_°i㳯ËÏî·éV*8×ÍIÃtv.ÁÞG²÷Oci{OýE^Æ™Óî'’¾W‚»=]¯ß‘® q™7‡È Iª¶Á–›»lInîÒuÒµ¼²¼B)~°l‘ø±åËŸ\,^š›»\¼¦J"¯,+©ç—(+$U%Jüfx«´¬R¢T‹\Y¡TÖ<õè£õõõKJªK¤òòÕ‹‹ë+•â‰B"¯“¼&~VZ­o,©’ˆ§¤/™ªë¤U5µJ‰\œ/}M"¯ÆZg® VkˆuÄ3d>QJVò<‚¸9Ä|b±X‚¿{šÈ#6¿'ò‰ç‰mÄ Ä‹ÄœiIdà[Ýää¡i½<[ÆÎŒ§K¦³üæ¥3.RÅÔ¥™ÖY,“…s/t 5ˆG¢MqÚ@^SA~¾•±ÙÀBýf_è³+hæûŠñõÒiL:Ò8è¬äG:ØÏ÷’_&çò’ŨVò¼†°Á«ó¦>GCB­Ï PZ½^+mÀ2³G¸˜0…‹Îl0ƒ6[Ô‡i8!죲’Ã@… ví^å£Ù‚WÖ–ê˽]g‡Šq6‡è€×uþl—'3Ç…XXë°ˆêu~脨?ÛwM¢>~·jz“ZS¤Ñ‚ÊîжÒAuÔþ5hcü@¹[!ÑB£èy°˜ž•ì?…L§Ý×j0ëÍzŠÓ¥Ö Pº:Æ]ž•´Õ%’ ä±¼äHr¹ÀávzÁCùÌm†1žY-4„_¸ÈÍŠÓpZn7×À­EÂyh™Ýˆ÷§·/'Ž„ƒ— ˜ÝZ6 Ó\ÂÑÜÜǹL ŸDˆ` ZxèÎO>ÿûè Ðœ·,A“U:J7§ÛÝŽmŠa›N$Pÿ0™Ô#À™䦜öPÝ vF_»[P´•{ËÉ㜠€üN¿Ó{õ ¿çÕíMR›Ån†Â.Eè8½î¶cH"t¸\QpRA#&Ô‚Ýdi¨_U£y¨…ü“Èv8B6Êå£ÌQÅ2ÔYä ¢t>‹ŸŽ€#àlkG«…~¨‡Šè@M§ºù*¨šÂÐ&rA;´Ù:lX•,6³ÝÂÝ›J ›q Pÿ¾Œå÷€üiÜÇ1îx&Ñ9tIðþUwcµL 7ÉìV»1 Ú(p]ách—Ðát…ÁA¹™ 6í¶ÑÕ¯Rª—õÿ òü °fÊŸHÈþ@¯Ö‚ZÂÊ|™pÙ@»•iæ²Sû~ `uéâèvuâS¤ù1û°-”/‚C§ƒ:QAé¬q1.aD¯;JeÝô@‚ý!AÞÜÁ~#pÎÕšJ©ZÄ ø5¸´õ©ÛRg…KÙSÖ»³ ²¹¹iUi¿ZûpšÁj·3Zî®”W¨Û.«]o£Ì:»Úì1Eî.×…+Ñ@fŽ÷M¨Ùi•;ª¼0&F÷±¯ ü¯SÈÕèhŽ@v|-Þûh’/tعy©3?Ñeÿ›. ýΈƒzŸÿt3> ¼‘)­ "÷Pƒ³ÎisAÎ}+4V‚Oùg6_B·£»Qzà› ¬ ·Bqy­ŠŠ¤2ååñEÐçî öíóÅýû<íà EÇ&Æ€:+|U;kÅU›eÛ^ÞQXX±>Žz®ÄÉñOQà û{— Ô¢ÝõTu¯1ì™tŸ:õ\Ï&.÷*͉° 7èÒϾ ô>3;‡±˜W.á204µ­8qQã{¿{óôø;GÛàÃ}ÃÞ[Me¡~Â\'ÿr.qž‡&“‚ÎÆV¥¬ZQUÛÚØÕ»¯»Ÿæ¤x‚mmÑXtÐ]8Z~ìëƒH]¦t†MŒ^¹¢´´ (ÎÓ'‚n_{x ØìkéøTè @u´l襇J8±Öà³úñ¼px]Áø7úúŠ-RèíMú* ¾†+޳_LiÒÜ@Ê <ö1,*¦‰)ªdR™*ªêîï÷Òœä‡ß4 ó6B#hÜ6Ç@Ôݪ[®«®‘ï’ŒÈOЧMíG™×ÐM¡+äôC”:¾ãÀ–yù?ëh‡Ëí?79y¨ŽPÓ.<ÕüÂ:Žâ8t-:• tââ;塉ÿ; ž£j.'õ¡Ðª3Ø©†HSŒÿ~w$8Öû]ËØqóG*( 4zFkkÂûlóxñ»ôô„cÝ#­'ñLþÙa³U­-’­ÇÁ™;±ÃaGÈÓåpãeÑWç·¿äé …¿=1ro¹ã×o3A~nm›¦³¯¿óà bx;½^ÜQP°¥@ÞÜh‡^OfNx(ú+²ÆŒ#eÿ鎔IhņãŸÎŸÜ}”>]ƒ-í‰è{x yŸÖÀXì´±¨™fÍUI9P SW·b®WÛªÓÇǯ£ù—Fã$ºïZvšÇ.d3Jkä”:¤íŒ´LœÎëÉçî-Yü'Yùˆ´KÝÆ¼¥2ÐË Sí’ªv* í €ß¹å¯O:}!Dõ×øt¥ºç7Ÿ–|…ÖŽ ÛÇh¸¶(¶Ó÷rà5ŒQím~MÂæ¨ ¹ GÿŽ ýØ›#ø?º5+rùÃ(=<àÈîh 6Е`ªi~u—%|˜¯ÒÞÚ×ø›8“Yn¨€¦ìMG*} Í µœæô®³š4õ/oz#PuºHâ?pS-G¢Y8Ù³)°¨ŠÖ­ª°axBï ]ë|'Øã @;Njÿ+–rót¿è˜Þ/ÇC@Ez¥”¥¶¢dž¡Ê©E”½Goœt{Z‹&ÔÃð&t½î‹î޼‹÷¯×êÓMív³L»]]P ”Ò‹‹ -0èíñöDOºÛ÷^zûBoâÐõÔ{utÔL ,7rKîì ¨ä[kf ÁåWÁªÊd44úMcW}D »©WžÃ.fWt¡áxÿ•î“¡ý.?Æx{ÇÀcüùÐÐpà˜ÂÐË ¹9Ö]°‡âÈ/ëO §>D“鬺v]°¥Õtð¹âà zVÆ“{3gú2g92gïŸuyvÜ™‰¾¸û_‹€C endstream endobj 571 0 obj <> stream xÚcd`aa`ddõŒŠuÕŽˆt ôÑõMMÉ,ÍI˜ýáüÃùYÈ3üP`ü¡ÈôC‘ù‡8‹,ÃAy˜Dî‘ &ã.!vFFv.>Ñ€°CÓósËCCCC=c c·ü¼…äü¼²Ô¢’Ô…’|…Ê‚TC…¤J…Ü4£‚C…ò¢Ì’’Ô> stream xÚ-ÏoLqÇñßÁY—žZM&›zÜ“–.‡h[Îþ-Fµ¥¡ÙÃz"É%Lð8þù'…ÈMäO` LÊÍ­Ù“¶Z¥Ï\ëi™Oò[\³íÎn­Àõäµ}¿Þ (@¤üêEuû­Î­öÊ©âã\\ ×¢{¾¡µˆP'©P[íè_\Røu¤èÊ¢ß=^@b> PÁÃA•ê¤R¥jÑXmÆ4`dÉúþ²¹­­µ‘lQ©ÚH5M1¦~½…ÔêY#EëÙÂa&oXûMë!ëÏYÖvº©Éår)õ´]ieÎ74’.k$¯SvŠqRò²ÕÂ’zš"÷Û•ûj¬´ÍÁR ©µ(Æ"9Lå tT€5øŠ ¡RìÉðjGø‘¼”NÊ`cïMÆ11B?æ‹úf“Û›|åúЛ»§ÙBgÌ+D &¹x «º'òBuž¯Ê|H#¼üËóÏR~w•-xæX›eÈÂ<ÏgsY¢Kü)ãbÑ.Žr1ø[ë]ê=vG”;&9_’HÂðL8º¸óþé"ÄÒ/«€.ÿhðám±J>nA¯ÉKOzá0¦{=°ºû–—ÏOO%<Äœšô»Gt÷ºtóø ˜žI=Z*„ÍŠ}yaãYb‡÷mJC¡,g 2f»sÎ}–ËæÑô§Yæ¾pM× ±€5Ä)`(< C©Dd¦°üPdÌF;î÷¬¿">A™ãñmþ·|:ŽÂdaÆJ‡XrI¬qû¹Å!.’|ñqíÝ*Är†Q@opl*€U83‚&ó¶Ì±/v(E[Óø¡^ÂË–K¿•-s8ÎoUýíâ Õ endstream endobj 574 0 obj <> stream xÚ]PÁJÄ0½ç+æ¸"’¦ xÉZ­²*vöš&Ó°IHÓCÿÞ&[öàaæÍ{3ó†ŠfßX~§ZŒÐ«Nn ¡ÃÁXÂJÐFÅ­ÊYÒ*ÒȾœß^ßÅ­8<ŸYqw:Öì4öÊqñåV7ûv™"ŽípNè÷:qŠaÝ“vÞ$ì3h ư;‰6#íìý/Žh#¤ªò8v¹I9“— ƒ´^ðº®Zý¯·)º^ýÈ@øýãÊ,KÆ2wC“*ù»ÚSsëÞü„ì(-7¯òÎ'UŽ?žm6 endstream endobj 576 0 obj <> stream xÚUoHqÇïôv;m³Ç´ÎíL*%™s¾0§9RË Ìˆ Ý¶Ó ·Ý¼®K"³Òy¿SÊ4$™lÒ}QoB+ˆ^ö¢^I‘/ŠÞýßÍß’nHV/žïóåçóüÁ1‚Àp/hsŸhïpvus×Ú³•ú(ý3BëVÒs:ÕŠ© ®–ç¨ûsU3Q†a¸­0«vgußM1‹&9Ï‹0 Ç æŠ:çý•'õrA®W#;Ö#îØPÀ …X1À‡}h$ÈJv{Ínw¸øˆ$úü"Sé­bj꫇ÝÞÀ qBÀˆ™NVôsÙV/dºyo€%¦²É¯rÖÔÄb1ŠÚx¡¯¹ªš‰D?sš‹rÂçcZù°ÈœbC³}¬m;¹øPdP䦓÷qBX»‹8‚9±&Ì­Ùq<ŽOà2¦ËÁpŒÀŽcÓÚ‡ÆÕxÁ¦a«d!ý%«ÅЫ*™xwvÃVX47«(`žZ”Á2L¢~D5£.€Q™ý€"/Y^KŠ’²f!æ¿tû–Ù”T”E+˜—•ñ©à¢ëé¹O¾7±u°A©-ú”¬D,dD–¬  ÊuÔû‘žÒ@´ª.Ðäû?ûÓé<Ó¿³T§@£^@"¤á,{ =æSZý?n£ÔKȇN"fdT–$E¾3šŠ½:»vðAcÂT­KÒ›ñ 𸶆ÓÄwÍ› ¾Ö ¤¯¢¼ éCCcUè  2_Iõ–úyúöä¸Y &ÁÔõÙLoº°D}D½àã噉g×6.½íI¿<¿ì¤’$2Âe<¤d9~CŽƒ‹`DMýò—dîf~\½Æ€\:2æ-±I#)¡_Í_ÝõpÚ`ÐÂhÉ'$Þ?ÿ!$U endstream endobj 578 0 obj <> stream xÚcd`aa`ddäu öt Õvö Ž´ Øæþó—aYøs>놲Œ?ä˜~È3ÿg‘{èÅòŸ‡I–á» ˆüÂ"?€Hu Á˜,ÄÀÊÈÈÁ_Ó8!5'575¯ÄÀÀXÏÀÀÈ9¿ ²(3=£DA#YSÁÐÒÒ\GÁÈÀÀRÁ17µ(391OÁ7±$#57±ÈÉQÎOÎL-©TаÉ())°Ò×///×KÌ-ÖË/J·ÓÔQ(Ï,ÉPJ-N-*KMQpËÏ+QðKÌMUûAL:çç”–¤)øæ§¤åÇh$Ú˜YÒtðýŒðÞù½„Ÿìbþqó{¹èì…Ý‹•vWËÿ b›ñ]þ;Ç×ï:Ýß-Ùà¿mØ~{üVý­ðÛé·ówµßòßÝå¿Û É[²ýÖéþÍñµî»<_ñâŸö Ø~ËMg—ãbž¦úŸ‡sW÷N®Ü;çòð1ï÷‡"xý‰û endstream endobj 580 0 obj <> stream xÚMmHSaÇŸ;ï¶'/ERn—>„+ÙÖBIJ–қ"—sÞ¶‰{iÞZÓÐÝ™:ï™kê6 3M4,¡`–Adô©o~ê“Їè¹ríe“9çüàœçÿ?¢iDQT®ùÜÙêËS­¹¾"38êþ]WD·­?‹EH,¦DµLÔd‰»hõêúJVŒúµ=ßù~/Èp_²û;œ¢pþ>ƶ°.ÖÍ ‡tƒÑäñ|N»ƒcJlZæ`EEy)c4*˜*ësÚ¬n¦ÖÊ9X—•K7-ŒÙcs²\€)©tpœ÷°^ï÷ûuVW«Îã³Ó–2~'ç`êØVÖw‹mbj> stream xÚÝ[ÛrÜ6}ÏWðmíJy÷ËV*UºxìØò%–äHrô0+MlÕÚ’Kïfÿ~O7À!‰!Ç´"¥vSª!A°Ñ88èn40#+U%*+Tå}¥œ¬¤µ¸›J)‰;ꂯ¬Œ•¶ºR^TÚi<‡ÊSYÈÐGy”5ÝCå Ð*U9”U•‹wõУD ô„XE”­2UÄ;UI)HŒ•”´JWR t„’ôXmj, Ž 6ÖèZZ–xe½…°¯¤3„5:¬D÷±2À&ƒE_•Œ—J KClé€M‹Jtfµ""¨fB(„JaC|hEïF@£5¶2D…5]8@0‘ø@ÁJÒ…1IË @µõ$l¡48¢c§I#ISᥠ8T$ºPy¡³á] Ù ˜1d#|€‘€® z‘U`˜ˆˆ¦œD¯UðPc!hŒRVQXh‚þ(ÍBµ! ¶Š“+]¡&(xŒªcá#…€-A¹J“È mÐ 4 +IfM8Œ=H¤€\Š(s C¾ˆY’/H)æDÀX`à…a:¢lHé1¤Ò ƒƒá J’1(EF*iÇ| M*™œ²ª4Õyšz° [#¨€‡zCr$!™ÕiX…%+Õ3- Û"zr‡Ôˆ(Eôëð‘FP¿,Kt:²gÃX ÉOuš4a¤ ÎYðï•È~øazðŸÏ‹éëùûÅÍtçêËå²²xº^PA¿™>¿8¿y³¥hñé=t·ÒÐýôÇ¿ëS&}­|c¥Í·.ßCÖ¦ZÚÞ,n®¾\Ÿ-nà+,ßè_a”ܽ].ñ œnHƒ­Áhˆ£5„ZÃ;åyا….?z<>gºuyyµ¼á°‰çºM£Ç·æÎÉ4gÎä{žC/Z8m/N?€S‰§ëâT²ÁÙRÄh…±²ñÝ2ر:ƒ)@ª~a´B¿Éú¦Ãçið!*OOpý†å]À‰­ ½\E;ZWÉ•éå*†Ñ }ïð´;<-Ä-Ø1±³ E—ïqŽ‚cK8zŶNì´ÔFëòÛ®m-åX…RôOÏ—ô€?ZƒÛ4_ªÏó¥ÓÀùֆƶw²µÈ…Í÷4ùÚ·®R2¯J*¯u*¯Zj#4çSs“£–Iþ[¯§5âÓé‹ÅùÅ|ûê÷w¤žr\UVºs½˜/¯®ìÍGÕ¿/–ªèçúzñ[õy~öOt÷púúúêüËÙâúÁù¿.>Ÿÿöé÷ê×ÈI„Ð*üúðaRrqu¹;_.ìþ¯`ÜÒ!Y@&õ½ÐâoS¯>/.·ÎHø]rºÙÅò”Gõâê|1=¼Y¼ú²üxq‰A¾œ‚˜ß§u5*R¶ÀL¬xdrvæËùÇ«÷ä'–Ò¿üþóZOt}j:õȵ˜iy§'HpC~ŠfbêknÕ´N²ýý¥ 5!°„•rBè§£²²–{°¹ßàÜÄçwpy5QD Þ"—G¹~ã ¡¢¾ NÌéw´(OT ƒñ¢õÜ}ZÿsÊ­Fã,¡B Å#u'£‘±:árÏÔÊLl¯>IŸ Ä“‘W,oÌwªSJ±FcýÄ·ek*ƒ%ÐF;ž´& õg€#ט/lvøJZRŠ“ô%ùòº“x°­yξWV'Nó+‹úú¶¬¹]âÍm¶DØÆ„=΄vad'é²­–=`÷V´zôžù!kÔÙ&=×å7¬9•©ÝØjé¨56¨<ìަȂ“¯8ö+gɃ|0˜s’ÓÉê%I$´[ŠÒå÷¹®öIíØGˆ‘¬Û¦þ°‰#ÁúQ´¤VÐZƒd†Ý¨]F¤gã¯%2E©V5NÓ‘'h%$t$‡Õ8áí· v*§«ÉÎŒ0ºš=Ø@{ŽÚìvÿVDküWµšuÚ÷J9ŽNâŽÿ†µÖöÕLX›§Ã`Üÿ§e¤‰çÓ‡áO_Ëà¨eaB§d•!H²Ýl“×ȱñG7у 0à(H{H/ƒSmͰR½ÄؘåÒ’’˰!Yi+ó€Rm` ×õS´ä’¹ÕJ2I`oO>`ùj<à·ß¦¦rº2šHÍ.딽ÕDÐèö«k®¾ôÎ2?"ß¿õZLž‰>~"fíÄ>¥yw)ôÞ^Vœ·> òy>½ ¬<`E’¢(‰[¶þzmóV¬õ'ª»Ïf¤|¥u!ozz—þ´zÝæJxZ;°zØîݧ'›þ,B=ûz¤ ÛäOO„D–ÒÝ•óˆ4´ù|mÕÚ$ÕcNínw-y«ñù1 ¯ƒËF¤\ÁyZ÷"¥ÍršÆ©(í¡õ“¢ µ ¯¥²žÔ.¦¼Ã[—¹Éš“ _¥°Ž]5=:VZ’’¡CtÈ%Z éÈ©y›i¢:C+pz«îÉôÞ„ ¤ó&SݼI@S9˦žYCÞ_¬ âþýën{}øÏÍFŒà9­ k™c6[7Ån•×¥ÓŽJ =…÷<žÒy(…ê¶Ï}DWä F¸”1æüµÁ;´uÚîôoà¿ÄPO›û+>àYTÿç‘1¨h³ÕU¶yÔñÎÞ¦#4ܡӫb¯ˆ0%¶ýçtœ ¹îé ¥ažÓ:O¿à˜ë G2‘œA#5 $iü³>‰ü+Lö›Ï ÿèŸ1| „”†‰OåÊûmþ$Ÿ&ÑñÀQ&ìÆ£ß;ÍŒš|ãtõ]Æìêr9Ýÿò%=Pœþrq¾üpÃ?dI_\ß,w>̯aUÓ½y.K¥¦Ûó›·?~òæñîî÷;/ö÷·¤`¥»‹›³ë‹ÏË«kþÍH÷kì®Àtgþùéââý‡%23ݺ9£og¨H2T~$ñðÓrþñâlëòýÇE%¦ûËŧ·ô›‰éìãü=}c¯¤M]oÓ×,:[ wŠ:ŽæBŸ£!Œf[R=¶T¤þ‘äø‚%íùÛíƒÙ”¿è%'Þ+9^õ’£êhmÂ:9¡ §$9± G·2 ÛZÂNvöŽ_ÐJÖ˜I¿c»¬w¡×uð^¬qbEáM îqŒX¹)ûišíÇOf[”Dô˜KŸ2#”Õ¤ ¸"EÁ6Ç/ëך_]—Õ¥¤ƒ{$)z¤™¼=z¹»ý–èv댨û2ˆ¯3¢êDGF½n&EÐmáÉHrmgoÕJkvŽv^²WÆuNôý3”Úd²ëÌ· ôâm»)  c3å'¯ßŸP|ÓÃÕ½%Ê+š:afÅÎKEØÂ=Î~\™þéÎ’mJfGG³Ù»k'ö¾¢L/'.G$g.v·X®ÈúÚ°GRRî;;FâZµ{üò—Wßïní?}D¿Ëüòi™Ñy±øÚnA”…2ÌXþO&þt9)¶}ÀGrcJnl{ÕÊðNvOž£­ƒŸ^’ãÿr(mçKþtÙ±ÅR݃|$;n,;¯ÏNžî¡íMì„ÿv|—>ä#Ù ›–*Z ðÓ7¯^Î8Ö÷dy÷œÿön”©q¹žë¹"·á£Æ‹±†óêøäèð1Ñ¿ÿóÞ€á8!îÜpBè[š< ‡.ùÓaŸùHvÔ&툼·»õìð%3ïÖY‘·2;Òp‚í1YŸ+#×ìÆa¹~tŠã»‡~-leÈ¡åcOŽž=}N§!{NsœPwz|ߪE~ÅÇ[©°÷ªKP‘v0´r×m[Û(ÛJ·_ïÿ4;䣳°N‡¾·C?×»ÝÆb‘Ú#*Ò3b—•b»ÝF>’”¸ä™ +û{ÏïYw\gÅÜ+zð(ÔþŸ[úq\‡•Pl¸ÛÈñ¿ €g- endstream endobj 605 0 obj <<249974da5a8977cfd68ceb0076d41963>]/Size 606/W[1 3 2]/Filter/FlateDecode/Length 1443>> stream xÚ5×WpTuÇñÿïnB½„¡’¡Cè½÷^CAPPš ½÷^鈂¥Wàƒ>0£>9Ž#㈌ø`™ ßsöå3g¾÷îfîÞs !„ׯ£%„*X9 :æ07ÇØJ! ! !Ò‹ïß̹gÎåhl§ N~Ž8:ŸÞa 0ó`^̇ù±ÄB˜„…±ÅbXK`I,…¥± &cY,‡å±VÄJ ‰yü·°¿Ææ*XS°VÇXS±ÖÆ4LÇ ¬ƒu±fb}l€ ±6Æ&Ø›asÌÂØR!©®þV|þEü+tÂ.Ø {pNkæ^Øûá…R•ü}Úð>‹*d{iKY¢P½Ÿ—v”¥ ©û½´§,¿ ¥e…B“>^:RV*dÍòÒ‰²J¡Íj/)k™íóbîªÐñ¥ŸÓsÖqtˆBßÞ»Ó×+ MôÒƒ²Aati/=)›yí0¡0!Ùöâè…Y1/½)[æ—ñÒ‡²×ŽRXºÔ{_úz6ŽÅñ8QamüwìÇ™»˜ûcîßÇc?:£»ôò2ˆ²Gáø^Sö)œ9áee¿Â¥_½ ¥`¦p­¿÷áô™s÷œ¿¼¤Vøn„—Q”£Ì£ž\õžM?¦ðÓ /c('˜Ç*<_“ãè'ž?ô2žršyNÄI ñs&sÎçÌS^½ðþý¬”g——©”sRÁÃ^¦Q.Hežzy›ò%ótœ!UŽ_¥ïpô¢”VÈË»”KRæ4/3)W™gIÍâŸó=ú5©u–—÷)7˜g㜋óp¾Ôù?ÿοż@ê½ÞûBúWÌrýL–—ô£‹8zWÊ^ée1åž4µ±—%”楸Lš™îG—sô´p¼—ü”HZTÌËJJLZÿ¶®¢$HîzYM±»úi[Wïkévo_'íŽGÖÓ HGâÿ¦(vÏ߈›¤S?úQûž&IçzÙB)"]Îïe+ÅöÂ6éJ)ïÛéÅ¥{ßz±ïf éQ‚—”RÒ“â^vQlƒì–~Èñ¾‡ž,ýü¯—½”²Ò³ø=p¥œôgQ/ûñíÂX k¡í‹˜Ó0‹c´ûÿfÛ÷™+1ÛU}â%¼ŒW8Ó¶§]½ö­?„×ð:ÞàÌÊÌ7ñ0Ú•yï ]“wñ¯²]ù¿¦ØÓ‚(G™K`„1L@Û°Çð8¥ÚvÎaNEÛ¹'˜kb"æÁ¼hO'™óc,‰Ñ®´O˜“0ë`]´} ?¥db}l€ ÑöõgÌÑvôy¼@±'»ã}A)e0í)å s9,E1«¡=ؽñ,žS¤‰þ7ÏÂÙ8[ íÙ–hÏ ­Ñv½íwÛé¶ÇmwÛ¾¶mk{¹ vEÛŒ¶smÏÚnµÚmWÚf´­gwWÛ,¶él»ÙF³-f›kÚ¶¶¡&àh´MdÛg,ÚÆ±-cwþ‰8 m³LAÛ&¶AlkØ.˜Ž3ÐîçvŸ·-0‹ïx%æMh÷êyh÷óeø!®Æ¸íŠÚŽ{q'B»ÄShß2»bóÓíyû<ÚµgWÎe´kì6Úà:ÞäµvÜAû¶ÞW,“'üÜ£1/&bȧ±$Å XËcUEÅýÝRUœês5E5:çþo"J[祺¢ô[oJ÷W^j(ê™ásMEÚ½9:ù¡—TESâgÖR´ø¬Ïµm¾ésš¢cÏ|NWt:Ûç E÷Ÿø\GÑ7{ß¼ó£ë^ê*zü»ÏõýqÒçLÅò-ö¹¾bIÏ}n X‰m>7T,9ÇçFŠ¥¼ô¹±b5r·€b©ÿxi¢XíTŸ›*–‘âs3Åêüæs¶D{Vo‹í±#vÆ®Ø{boì‹ýq Æ¡8GâhƒãpNÂ)еéÂÿ)£Œ endstream endobj startxref 212810 %%EOF glpk-4.52.1/doc/graphs.tex0000644000062000006210000037563512175147600014517 0ustar maomkpasswd%* graphs.tex *% %*********************************************************************** % This code is part of GLPK (GNU Linear Programming Kit). % % Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, % 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied % Informatics, Moscow Aviation Institute, Moscow, Russia. All rights % reserved. E-mail: . % % GLPK is free software: you can redistribute it and/or modify it % under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % GLPK 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 General Public % License for more details. % % You should have received a copy of the GNU General Public License % along with GLPK. If not, see . %*********************************************************************** \documentclass[11pt]{report} \usepackage{amssymb} \usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue, urlcolor=blue]{hyperref} \usepackage{indentfirst} \usepackage[all]{xy} \setlength{\textwidth}{6.5in} \setlength{\textheight}{8.5in} \setlength{\oddsidemargin}{0in} \setlength{\topmargin}{0in} \setlength{\headheight}{0in} \setlength{\headsep}{0in} \setlength{\footskip}{0.5in} \setlength{\parindent}{16pt} \setlength{\parskip}{5pt} \setlength{\topsep}{0pt} \setlength{\partopsep}{0pt} \setlength{\itemsep}{\parskip} \setlength{\parsep}{0pt} \setlength{\leftmargini}{\parindent} \renewcommand{\labelitemi}{---} \def\para#1{\noindent{\bf#1}} \def\synopsis{\para{Synopsis}} \def\description{\para{Description}} \def\returns{\para{Returns}} \renewcommand\contentsname{\sf\bfseries Contents} \renewcommand\chaptername{\sf\bfseries Chapter} \renewcommand\appendixname{\sf\bfseries Appendix} \newenvironment{retlist} { \def\arraystretch{1.5} \noindent \begin{tabular}{@{}p{1in}@{}p{5.5in}@{}} } {\end{tabular}} \begin{document} \thispagestyle{empty} \begin{center} \vspace*{1.5in} \begin{huge} \sf\bfseries GNU Linear Programming Kit \end{huge} \vspace{0.5in} \begin{LARGE} \sf Graph and Network Routines \end{LARGE} \vspace{0.5in} \begin{LARGE} \sf for GLPK Version 4.49 \end{LARGE} \vspace{0.5in} \begin{Large} \sf (DRAFT, April 2013) \end{Large} \end{center} \newpage \vspace*{1in} \vfill \noindent The GLPK package is part of the GNU Project released under the aegis of GNU. \noindent Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All rights reserved. \noindent Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. \noindent Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. \noindent Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. \noindent Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage {\setlength{\parskip}{0pt} \tableofcontents } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Basic Graph API Routines} \section{Graph program object} In GLPK the base program object used to represent graphs and networks is a directed graph (digraph). Formally, {\it digraph} (or simply, {\it graph}) is a pair $G=(V,A)$, where $V$ is a set of {\it vertices}, and $A$ is a set {\it arcs}.\footnote{$A$ may be a multiset.} Each arc $a\in A$ is an ordered pair of vertices $a=(x,y)$, where $x\in V$ is called {\it tail vertex} of arc $a$, and $y\in V$ is called its {\it head vertex}. Representation of a graph in the program includes three structs defined by typedef in the header \verb|glpk.h|: \vspace*{-8pt} \begin{itemize} \item \verb|glp_graph|, which represents the graph in a whole, \item \verb|glp_vertex|, which represents a vertex of the graph, and \item \verb|glp_arc|, which represents an arc of the graph. \end{itemize} \vspace*{-8pt} All these three structs are ``semi-opaque'', i.e. the application program can directly access their fields through pointers, however, changing the fields directly is not allowed --- all changes should be performed only with appropriate GLPK API routines. \newenvironment{comment} {\addtolength{\leftskip}{16pt}\noindent} {\par\addtolength{\leftskip}{-16pt}} \para{\bf glp\_graph.} The struct \verb|glp_graph| has the following fields available to the application program: \noindent \verb|char *name;| \begin{comment}Symbolic name assigned to the graph. It is a pointer to a null terminated character string of length from 1 to 255 characters. If no name is assigned to the graph, this field contains \verb|NULL|. \end{comment} \noindent \verb|int nv;| \begin{comment}The number of vertices in the graph, $nv\geq 0$. \end{comment} \noindent \verb|int na;| \begin{comment}The number of arcs in the graph, $na\geq 0$. \end{comment} \newpage \noindent \verb|glp_vertex **v;| \begin{comment}Pointer to an array containing the list of vertices. Element $v[0]$ is not used. Element $v[i]$, $1\leq i\leq nv$, is a pointer to $i$-th vertex of the graph. Note that on adding new vertices to the graph the field $v$ may be altered due to reallocation. However, pointers $v[i]$ are not changed while corresponding vertices exist in the graph. \end{comment} \noindent \verb|int v_size;| \begin{comment}Size of vertex data blocks, in bytes, $0\leq v\_size\leq 256$. (See also the field \verb|data| in the struct \verb|glp_vertex|.) \end{comment} \noindent \verb|int a_size;| \begin{comment}Size of arc data blocks, in bytes, $0\leq v\_size\leq 256$. (See also the field \verb|data| in the struct \verb|glp_arc|.) \end{comment} \para{\bf glp\_vertex.} The struct \verb|glp_vertex| has the following fields available to the application program: \noindent \verb|int i;| \begin{comment}Ordinal number of the vertex, $1\leq i\leq nv$. Note that element $v[i]$ in the struct \verb|glp_graph| points to the vertex, whose ordinal number is $i$. \end{comment} \noindent \verb|char *name;| \begin{comment}Symbolic name assigned to the vertex. It is a pointer to a null terminated character string of length from 1 to 255 characters. If no name is assigned to the vertex, this field contains \verb|NULL|. \end{comment} \noindent \verb|void *data;| \begin{comment}Pointer to a data block associated with the vertex. This data block is automatically allocated on creating a new vertex and freed on deleting the vertex. If $v\_size=0$, the block is not allocated, and this field contains \verb|NULL|. \end{comment} \noindent \verb|void *temp;| \begin{comment}Working pointer, which may be used freely for any purposes. The application program can change this field directly. \end{comment} \noindent \verb|glp_arc *in;| \begin{comment}Pointer to the (unordered) list of incoming arcs. If the vertex has no incoming arcs, this field contains \verb|NULL|. \end{comment} \noindent \verb|glp_arc *out;| \begin{comment}Pointer to the (unordered) list of outgoing arcs. If the vertex has no outgoing arcs, this field contains \verb|NULL|. \end{comment} \para{\bf glp\_arc.} The struct \verb|glp_arc| has the following fields available to the application program: \noindent \verb|glp_vertex *tail;| \begin{comment}Pointer to a vertex, which is tail endpoint of the arc. \end{comment} \noindent \verb|glp_vertex *head;| \begin{comment}Pointer to a vertex, which is head endpoint of the arc. \end{comment} \newpage \noindent \verb|void *data;| \begin{comment}Pointer to a data block associated with the arc. This data block is automatically allocated on creating a new arc and freed on deleting the arc. If $v\_size=0$, the block is not allocated, and this field contains \verb|NULL|. \end{comment} \noindent \verb|void *temp;| \begin{comment}Working pointer, which may be used freely for any purposes. The application program can change this field directly. \end{comment} \noindent \verb|glp_arc *t_next;| \begin{comment}Pointer to another arc, which has the same tail endpoint as this one. \verb|NULL| in this field indicates the end of the list of outgoing arcs. \end{comment} \noindent \verb|glp_arc *h_next;| \begin{comment}Pointer to another arc, which has the same head endpoint as this one. \verb|NULL| in this field indicates the end of the list of incoming arcs. \end{comment} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Graph creating and modifying routines} \subsection{glp\_create\_graph --- create graph} \synopsis \begin{verbatim} glp_graph *glp_create_graph(int v_size, int a_size); \end{verbatim} \description The routine \verb|glp_create_graph| creates a new graph, which initially is empty, i.e. has no vertices and arcs. The parameter \verb|v_size| specifies the size of vertex data blocks, in bytes, $0\leq v\_size\leq 256$. The parameter \verb|a_size| specifies the size of arc data blocks, in bytes, $0\leq a\_size\leq 256$. \returns The routine returns a pointer to the graph object created. \subsection{glp\_set\_graph\_name --- assign (change) graph name} \synopsis \begin{verbatim} void glp_set_graph_name(glp_graph *G, const char *name); \end{verbatim} \description The routine \verb|glp_set_graph_name| assigns a symbolic name specified by the character string \verb|name| (1 to 255 chars) to the graph. If the parameter \verb|name| is \verb|NULL| or an empty string, the routine erases the existing symbolic name of the graph. \subsection{glp\_add\_vertices --- add new vertices to graph} \synopsis \begin{verbatim} int glp_add_vertices(glp_graph *G, int nadd); \end{verbatim} \description The routine \verb|glp_add_vertices| adds \verb|nadd| vertices to the specified graph. New vertices are always added to the end of the vertex list, so ordinal numbers of existing vertices remain unchanged. Note that this operation may change the field \verb|v| in the struct \verb|glp_graph| (pointer to the vertex array) due to reallocation. Being added each new vertex is isolated, i.e. has no incident arcs. If the size of vertex data blocks specified on creating the graph is non-zero, the routine also allocates a memory block of that size for each new vertex added, fills it by binary zeros, and stores a pointer to it in the field \verb|data| of the struct \verb|glp_vertex|. Otherwise, if the block size is zero, the field \verb|data| is set to \verb|NULL|. \returns The routine \verb|glp_add_vertices| returns the ordinal number of the first new vertex added to the graph. \subsection{glp\_set\_vertex\_name --- assign (change) vertex name} \synopsis \begin{verbatim} void glp_set_vertex_name(glp_graph *G, int i, const char *name); \end{verbatim} \description The routine \verb|glp_set_vertex_name| assigns a given symbolic name (1 up to 255 characters) to \verb|i|-th vertex of the specified graph. If the parameter \verb|name| is \verb|NULL| or empty string, the routine erases an existing name of \verb|i|-th vertex. \subsection{glp\_add\_arc --- add new arc to graph} \synopsis \begin{verbatim} glp_arc *glp_add_arc(glp_graph *G, int i, int j); \end{verbatim} \description The routine \verb|glp_add_arc| adds one new arc to the specified graph. The parameters \verb|i| and \verb|j| specify the ordinal numbers of, resp., tail and head endpoints (vertices) of the arc. Note that self-loops and multiple arcs are allowed. If the size of arc data blocks specified on creating the graph is non-zero, the routine also allocates a memory block of that size, fills it by binary zeros, and stores a pointer to it in the field \verb|data| of the struct \verb|glp_arc|. Otherwise, if the block size is zero, the field \verb|data| is set to \verb|NULL|. \subsection{glp\_del\_vertices --- delete vertices from graph} \synopsis \begin{verbatim} void glp_del_vertices(glp_graph *G, int ndel, const int num[]); \end{verbatim} \description The routine \verb|glp_del_vertices| deletes vertices along with all incident arcs from the specified graph. Ordinal numbers of vertices to be deleted should be placed in locations \verb|num[1]|, \dots, \verb|num[ndel]|, \verb|ndel| $>0$. Note that deleting vertices involves changing ordinal numbers of other vertices remaining in the graph. New ordinal numbers of the remaining vertices are assigned under the assumption that the original order of vertices is not changed. \newpage \subsection{glp\_del\_arc --- delete arc from graph} \synopsis \begin{verbatim} void glp_del_arc(glp_graph *G, glp_arc *a); \end{verbatim} \description The routine \verb|glp_del_arc| deletes an arc from the specified graph. The arc to be deleted must exist. \subsection{glp\_erase\_graph --- erase graph content} \synopsis \begin{verbatim} void glp_erase_graph(glp_graph *G, int v_size, int a_size); \end{verbatim} \description The routine \verb|glp_erase_graph| erases the content of the specified graph. The effect of this operation is the same as if the graph would be deleted with the routine \verb|glp_delete_graph| and then created anew with the routine \verb|glp_create_graph|, with exception that the pointer to the graph remains valid. The parameters \verb|v_size| and \verb|a_size| have the same meaning as for \verb|glp_create_graph|. \subsection{glp\_delete\_graph --- delete graph} \synopsis \begin{verbatim} void glp_delete_graph(glp_graph *G); \end{verbatim} \description The routine \verb|glp_delete_graph| deletes the specified graph and frees all the memory allocated to this program object. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Graph searching routines} \subsection{glp\_create\_v\_index --- create vertex name index} \synopsis \begin{verbatim} void glp_create_v_index(glp_graph *G); \end{verbatim} \description The routine \verb|glp_create_v_index| creates the name index for the specified graph. The name index is an auxiliary data structure, which is intended to quickly (i.e. for logarithmic time) find vertices by their names. This routine can be called at any time. If the name index already exists, the routine does nothing. \subsection{glp\_find\_vertex --- find vertex by its name} \synopsis \begin{verbatim} int glp_find_vertex(glp_graph *G, const char *name); \end{verbatim} \returns The routine \verb|glp_find_vertex| returns the ordinal number of a vertex, which is assigned (by the routine \verb|glp_set_vertex_name|) the specified symbolic \verb|name|. If no such vertex exists, the routine returns 0. \subsection{glp\_delete\_v\_index --- delete vertex name index} \synopsis \begin{verbatim} void glp_delete_v_index(glp_graph *G); \end{verbatim} \description The routine \verb|glp_delete_v_index| deletes the name index previously created by the routine \verb|glp_create_v_index| and frees the memory allocated to this auxiliary data structure. This routine can be called at any time. If the name index does not exist, the routine does nothing. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Graph reading/writing routines} \subsection{glp\_read\_graph --- read graph from plain text file} \synopsis \begin{verbatim} int glp_read_graph(glp_graph *G, const char *fname); \end{verbatim} \description The routine \verb|glp_read_graph| reads a graph from a plain text file, whose name is specified by the parameter \verb|fname|. Note that before reading data the current content of the graph object is completely erased with the routine \verb|glp_erase_graph|. For the file format see description of the routine \verb|glp_write_graph|. \returns If the operation was successful, the routine returns zero. Otherwise it prints an error message and returns non-zero. \subsection{glp\_write\_graph --- write graph to plain text file} \synopsis \begin{verbatim} int glp_write_graph(glp_graph *G, const char *fname); \end{verbatim} \description The routine \verb|glp_write_graph| writes the graph to a plain text file, whose name is specified by the parameter \verb|fname|. \returns If the operation was successful, the routine returns zero. Otherwise it prints an error message and returns non-zero. \para{File format} The file created by the routine \verb|glp_write_graph| is a plain text file, which contains the following information: \begin{verbatim} nv na i[1] j[1] i[2] j[2] . . . i[na] j[na] \end{verbatim} \noindent where: \verb|nv| is the number of vertices (nodes); \verb|na| is the number of arcs; \verb|i[k]|, $k=1,\dots,na$, is the index of tail vertex of arc $k$; \verb|j[k]|, $k=1,\dots,na$, is the index of head vertex of arc $k$. \newpage \subsection{glp\_read\_ccdata --- read graph from text file in DIMACS clique/coloring\\format} \synopsis \begin{verbatim} int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); \end{verbatim} \description The routine {\tt glp\_read\_ccdata} reads a graph from a text file in DIMACS clique/coloring format. (Though this format is originally designed to represent data for the minimal vertex coloring and maximal clique problems, it may be used to represent general undirected and directed graphs, because the routine allows reading self-loops and multiple edges/arcs keeping the order of vertices specified for each edge/arc of the graph.) The parameter {\tt G} specifies the graph object to be read in. Note that before reading data the current content of the graph object is completely erased with the routine {\tt glp\_erase\_graph}. The parameter {\tt v\_wgt} specifies an offset of the field of type {\tt double} in the vertex data block, to which the routine stores the vertex weight. If {\tt v\_wgt} $<0$, the vertex weights are not stored. The character string {\tt fname} specifies the name of a text file to be read in. (If the file name ends with the suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine decompresses it ``on the fly''.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \para{DIMACS clique/coloring format\footnote{This material is based on the paper ``Clique and Coloring Problems Graph Format'', which is publically available at \url{http://dimacs.rutgers.edu/Challenges}.}} The DIMACS input file is a plain ASCII text file. It contains {\it lines} of several types described below. A line is terminated with an end-of-line character. Fields in each line are separated by at least one blank space. Each line begins with a one-character designator to identify the line type. Note that DIMACS requires all numerical quantities to be integers in the range $[-2^{31},2^{31}-1]$ while GLPK allows the quantities to be floating-point numbers. \para{Comment lines.} Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character \verb|c|. \begin{verbatim} c This is a comment line \end{verbatim} \para{Problem line.} There is one problem line per data file. The problem line must appear before any node or edge descriptor lines. It has the following format: \begin{verbatim} p edge NODES EDGES \end{verbatim} \noindent The lower-case letter \verb|p| signifies that this is a problem line. The four-character problem designator \verb|edge| identifies the file as containing data for the minimal vertex coloring or maximal clique problem. The \verb|NODES| field contains an integer value specifying the number of vertices in the graph. The \verb|EDGES| field contains an integer value specifying the number of edges (arcs) in the graph. \para{Vertex descriptors.} These lines give the weight assigned to a vertex of the graph. There is one vertex descriptor line for each vertex, with the following format. Vertices without a descriptor take on a default value of 1. \begin{verbatim} n ID VALUE \end{verbatim} \noindent The lower-case character \verb|n| signifies that this is a vertex descriptor line. The \verb|ID| field gives a vertex identification number, an integer between 1 and $n$, where $n$ is the number of vertices in the graph. The \verb|VALUE| field gives a vertex weight, which can either positive or negative (or zero). \para{Edge descriptors.} There is one edge descriptor line for each edge (arc) of the graph, each with the following format: \begin{verbatim} e I J \end{verbatim} \noindent The lower-case character \verb|e| signifies that this is an edge descriptor line. For an edge (arc) $(i,j)$ the fields \verb|I| and \verb|J| specify its endpoints. \para{Example.} The following example of an undirected graph: \bigskip \noindent\hfil \xymatrix %@C=32pt {&{v_1}\ar@{-}[ldd]\ar@{-}[dd]\ar@{-}[rd]\ar@{-}[rr]&&{v_2}\ar@{-}[ld] \ar@{-}[dd]\ar@{-}[rdd]&\\ &&{v_7}\ar@{-}[ld]\ar@{-}[rd]&&\\ {v_6}\ar@{-}[r]\ar@{-}[rdd]&{v_{10}}\ar@{-}[rr]\ar@{-}[rd]\ar@{-}[dd]&& {v_8}\ar@{-}[ld]\ar@{-}[dd]\ar@{-}[r]&{v_3}\ar@{-}[ldd]\\ &&{v_9}\ar@{-}[ld]\ar@{-}[rd]&&\\ &{v_5}\ar@{-}[rr]&&{v_4}&\\ } \bigskip \noindent might be coded in DIMACS clique/coloring format as follows: \begin{footnotesize} \begin{verbatim} c sample.col c c This is an example of the vertex coloring problem data c in DIMACS format. c p edge 10 21 c e 1 2 e 1 6 e 1 7 e 1 10 e 2 3 e 2 7 e 2 8 e 3 4 e 3 8 e 4 5 e 4 8 e 4 9 e 5 6 e 5 9 e 5 10 e 6 10 e 7 8 e 7 10 e 8 9 e 8 10 e 9 10 c c eof \end{verbatim} \end{footnotesize} \subsection{glp\_write\_ccdata --- write graph to text file in DIMACS clique/coloring\\format} \synopsis \begin{verbatim} int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); \end{verbatim} \description The routine {\tt glp\_write\_ccdata} writes the graph object specified by the parameter {\tt G} to a text file in DIMACS clique/coloring format. (Though this format is originally designed to represent data for the minimal vertex coloring and maximal clique problems, it may be used to represent general undirected and directed graphs, because the routine allows writing self-loops and multiple edges/arcs keeping the order of vertices specified for each edge/arc of the graph.) The parameter {\tt v\_wgt} specifies an offset of the field of type {\tt double} in the vertex data block, which contains the vertex weight. If {\tt v\_wgt} $<0$, it is assumed that the weight of each vertex is 1. The character string {\tt fname} specifies a name of the text file to be written out. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine performs automatic compression on writing it.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Graph analysis routines} \subsection{glp\_weak\_comp --- find all weakly connected components of graph} \synopsis \begin{verbatim} int glp_weak_comp(glp_graph *G, int v_num); \end{verbatim} \description The routine \verb|glp_weak_comp| finds all weakly connected components of the specified graph. The parameter \verb|v_num| specifies an offset of the field of type \verb|int| in the vertex data block, to which the routine stores the number of a weakly connected component containing that vertex. If \verb|v_num| $<0$, no component numbers are stored. The components are numbered in arbitrary order from 1 to \verb|nc|, where \verb|nc| is the total number of components found, $0\leq$ \verb|nc| $\leq|V|$. \returns The routine returns \verb|nc|, the total number of components found. \subsection{glp\_strong\_comp --- find all strongly connected components of graph} \synopsis \begin{verbatim} int glp_strong_comp(glp_graph *G, int v_num); \end{verbatim} \description The routine \verb|glp_strong_comp| finds all strongly connected components of the specified graph. The parameter \verb|v_num| specifies an offset of the field of type \verb|int| in the vertex data block, to which the routine stores the number of a strongly connected component containing that vertex. If \verb|v_num| $<0$, no component numbers are stored. The components are numbered in arbitrary order from 1 to \verb|nc|, where \verb|nc| is the total number of components found, $0\leq$ \verb|nc| $\leq|V|$. However, the component numbering has the property that for every arc $(i\rightarrow j)$ in the graph the condition $num(i)\geq num(j)$ holds. \returns The routine returns \verb|nc|, the total number of components found. \para{References} I.~S.~Duff, J.~K.~Reid, Algorithm 529: Permutations to block triangular form, ACM Trans. on Math. Softw. 4 (1978), 189-92. \newpage \para{Example} The following program reads a graph from a plain text file `\verb|graph.txt|' and finds all its strongly connected components. \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { int num; } v_data; #define vertex(v) ((v_data *)((v)->data)) int main(void) { glp_graph *G; int i, nc; G = glp_create_graph(sizeof(v_data), 0); glp_read_graph(G, "graph.txt"); nc = glp_strong_comp(G, offsetof(v_data, num)); printf("nc = %d\n", nc); for (i = 1; i <= G->nv; i++) printf("num[%d] = %d\n", i, vertex(G->v[i])->num); glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} \noindent If the file `\verb|graph.txt|' contains the following graph: \medskip \noindent\hfil \xymatrix {1\ar[r]&2\ar[r]&3\ar[r]\ar[dd]&4\ar[dd]\\ 5\ar[u]&6\ar[l]\\ 7\ar[u]&&8\ar[lu]\ar[ll]\ar[r]&9\ar[r]&10\ar[r]\ar[d]&11\ar[d]\\ 12\ar[u]\ar[rru]\ar@/_/[rr]&&13\ar[ll]\ar[u]\ar[rr]&&14\ar[lu]&15\ar[l] \\ } \medskip\medskip \noindent the program output may look like follows: \begin{footnotesize} \begin{verbatim} Reading graph from `graph.txt'... Graph has 15 vertices and 30 arcs 31 lines were read nc = 4 num[1] = 3 num[2] = 3 num[3] = 3 num[4] = 2 num[5] = 3 num[6] = 3 num[7] = 3 num[8] = 3 num[9] = 1 num[10] = 1 num[11] = 1 num[12] = 4 num[13] = 4 num[14] = 1 num[15] = 1 \end{verbatim} \end{footnotesize} \subsection{glp\_top\_sort --- topological sorting of acyclic digraph} \synopsis \begin{verbatim} int glp_top_sort(glp_graph *G, int v_num); \end{verbatim} \description The routine \verb|glp_top_sort| performs topological sorting of vertices of the specified acyclic digraph. The parameter \verb|v_num| specifies an offset of the field of type \verb|int| in the vertex data block, to which the routine stores the vertex number assigned. If \verb|v_num| $<0$, vertex numbers are not stored. The vertices are numbered from 1 to $n$, where $n$ is the total number of vertices in the graph. The vertex numbering has the property that for every arc $(i\rightarrow j)$ in the graph the condition $num(i) #include #include #include typedef struct { int num; } v_data; #define vertex(v) ((v_data *)((v)->data)) int main(void) { glp_graph *G; int i, cnt; G = glp_create_graph(sizeof(v_data), 0); glp_read_graph(G, "graph.txt"); cnt = glp_top_sort(G, offsetof(v_data, num)); printf("cnt = %d\n", cnt); for (i = 1; i <= G->nv; i++) printf("num[%d] = %d\n", i, vertex(G->v[i])->num); glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} \noindent If the file `\verb|graph.txt|' contains the following graph: \medskip \noindent\hfil \xymatrix @=20pt { 1\ar[rrr]&&&2\ar[r]\ar[rddd]&3\ar[rd]&&&&\\ &&&4\ar[ru]&&5\ar[r]&6\ar[rd]\ar[dd]&&\\ 7\ar[r]&8\ar[r]&9\ar[ruu]\ar[ru]\ar[r]\ar[rd]&10\ar[rr]\ar[rru]&& 11\ar[ru]&&12\ar[r]&13\\ &&&14\ar[r]&15\ar[rrru]\ar[rr]&&16\ar[rru]\ar[rr]&&17\\ } \medskip\medskip \noindent the program output may look like follows: \begin{footnotesize} \begin{verbatim} Reading graph from `graph.txt'... Graph has 17 vertices and 23 arcs 24 lines were read cnt = 0 num[1] = 8 num[2] = 9 num[3] = 10 num[4] = 4 num[5] = 11 num[6] = 12 num[7] = 1 num[8] = 2 num[9] = 3 num[10] = 5 num[11] = 6 num[12] = 14 num[13] = 16 num[14] = 7 num[15] = 13 num[16] = 15 num[17] = 17 \end{verbatim} \end{footnotesize} \noindent The output corresponds to the following vertex numbering: \medskip \noindent\hfil \xymatrix @=20pt { 8\ar[rrr]&&&9\ar[r]\ar[rddd]&10\ar[rd]&&&&\\ &&&4\ar[ru]&&11\ar[r]&12\ar[rd]\ar[dd]&&\\ 1\ar[r]&2\ar[r]&3\ar[ruu]\ar[ru]\ar[r]\ar[rd]&5\ar[rr]\ar[rru]&& 6\ar[ru]&&14\ar[r]&16\\ &&&7\ar[r]&13\ar[rrru]\ar[rr]&&15\ar[rru]\ar[rr]&&17\\ } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Network optimization API routines} \section{Minimum cost flow problem} \subsection{Background} The {\it minimum cost flow problem} (MCFP) is stated as follows. Let there be given a directed graph (flow network) $G=(V,A)$, where $V$ is a set of vertices (nodes), and $A\subseteq V\times V$ is a set of arcs. Let for each node $i\in V$ there be given a quantity $b_i$ having the following meaning: if $b_i>0$, then $|b_i|$ is a {\it supply} at node $i$, which shows how many flow units are {\it generated} at node $i$ (or, equivalently, entering the network through node $i$ from outside); if $b_i<0$, then $|b_i|$ is a {\it demand} at node $i$, which shows how many flow units are {\it lost} at node $i$ (or, equivalently, leaving the network through node $i$ to outside); if $b_i=0$, then $i$ is a {\it transshipment} node, at which the flow is conserved, i.e. neither generated nor lost. Let also for each arc $a=(i,j)\in A$ there be given the following three quantities: $l_{ij}$, a (non-negative) lower bound to the flow through arc $(i,j)$; $u_{ij}$, an upper bound to the flow through arc $(i,j)$, which is the {\it arc capacity}; $c_{ij}$, a per-unit cost of the flow through arc $(i,j)$. The problem is to find flows $x_{ij}$ through every arc of the network, which satisfy the specified bounds and the conservation constraints at all nodes, and minimize the total flow cost. Here the conservation constraint at a node means that the total flow entering this node through its incoming arcs plus the supply at this node must be equal to the total flow leaving this node through its outgoing arcs plus the demand at this node. An example of the minimum cost flow problem is shown on Fig.~1. \newpage \noindent\hfil \xymatrix @C=48pt {_{20}\ar@{~>}[d]& v_2\ar[r]|{_{0,10,\$2}}\ar[dd]|{_{0,9,\$3}}& v_3\ar[dd]|{_{2,12,\$1}}\ar[r]|{_{0,18,\$0}}& v_8\ar[rd]|{_{0,20,\$9}}&\\ v_1\ar[ru]|{_{0,14,\$0}}\ar[rd]|{_{0,23,\$0}}&&& v_6\ar[d]|{_{0,7,\$0}}\ar[u]|{_{4,8,\$0}}& v_9\ar@{~>}[d]\\ &v_4\ar[r]|{_{0,26,\$0}}& v_5\ar[luu]|{_{0,11,\$1}}\ar[ru]|{_{0,25,\$5}}\ar[r]|{_{0,4,\$7}}& v_7\ar[ru]|{_{0,15,\$3}}&_{20}\\ } \noindent\hfil \begin{tabular}{ccc} \xymatrix @C=48pt{v_i\ar[r]|{\ l,u,\$c\ }&v_j\\}& \xymatrix{\hbox{\footnotesize supply}\ar@{~>}[r]&v_i\\}& \xymatrix{v_i\ar@{~>}[r]&\hbox{\footnotesize demand}\\}\\ \end{tabular} \noindent\hfil Fig.~1. An example of the minimum cost flow problem. \medskip The minimum cost flow problem can be naturally formulated as the following LP problem: \noindent \hspace{1in}minimize $$z=\sum_{(i,j)\in A}c_{ij}x_{ij}\eqno(1)$$ \hspace{1in}subject to $$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}=b_i\ \ \ \hbox {for all}\ i\in V\eqno(2)$$ $$l_{ij}\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A \eqno(3)$$ \subsection{glp\_read\_mincost --- read minimum cost flow problem data in DIMACS\\format} \synopsis \begin{verbatim} int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, const char *fname); \end{verbatim} \description The routine \verb|glp_read_mincost| reads the minimum cost flow problem data from a text file in DIMACS format. The parameter \verb|G| specifies the graph object, to which the problem data have to be stored. Note that before reading data the current content of the graph object is completely erased with the routine \verb|glp_erase_graph|. The parameter \verb|v_rhs| specifies an offset of the field of type \verb|double| in the vertex data block, to which the routine stores $b_i$, the supply/demand value. If \verb|v_rhs| $<0$, the value is not stored. The parameter \verb|a_low| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores $l_{ij}$, the lower bound to the arc flow. If \verb|a_low| $<0$, the lower bound is not stored. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores $u_{ij}$, the upper bound to the arc flow (the arc capacity). If \verb|a_cap| $<0$, the upper bound is not stored. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores $c_{ij}$, the per-unit cost of the arc flow. If \verb|a_cost| $<0$, the cost is not stored. The character string \verb|fname| specifies the name of a text file to be read in. (If the file name name ends with the suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine decompresses it ``on the fly''.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \para{Example} \begin{footnotesize} \begin{verbatim} typedef struct { /* vertex data block */ ... double rhs; ... } v_data; typedef struct { /* arc data block */ ... double low, cap, cost; ... } a_data; int main(void) { glp_graph *G; int ret; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_mincost(G, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), "sample.min"); if (ret != 0) goto ... ... } \end{verbatim} \end{footnotesize} \para{DIMACS minimum cost flow problem format\footnote{This material is based on the paper ``The First DIMACS International Algorithm Implementation Challenge: Problem Definitions and Specifications'', which is publically available at \url{http://dimacs.rutgers.edu/Challenges}.}} \label{subsecmincost} The DIMACS input file is a plain ASCII text file. It contains {\it lines} of several types described below. A line is terminated with an end-of-line character. Fields in each line are separated by at least one blank space. Each line begins with a one-character designator to identify the line type. Note that DIMACS requires all numerical quantities to be integers in the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be floating-point numbers. \para{Comment lines.} Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character \verb|c|. \begin{verbatim} c This is a comment line \end{verbatim} \newpage \para{Problem line.} There is one problem line per data file. The problem line must appear before any node or arc descriptor lines. It has the following format: \begin{verbatim} p min NODES ARCS \end{verbatim} \noindent The lower-case character \verb|p| signifies that this is a problem line. The three-character problem designator \verb|min| identifies the file as containing specification information for the minimum cost flow problem. The \verb|NODES| field contains an integer value specifying the number of nodes in the network. The \verb|ARCS| field contains an integer value specifying the number of arcs in the network. \para{Node descriptors.} All node descriptor lines must appear before all arc descriptor lines. The node descriptor lines describe supply and demand nodes, but not transshipment nodes. That is, only nodes with non-zero node supply/demand values appear. There is one node descriptor line for each such node, with the following format: \begin{verbatim} n ID FLOW \end{verbatim} \noindent The lower-case character \verb|n| signifies that this is a node descriptor line. The \verb|ID| field gives a node identification number, an integer between 1 and \verb|NODES|. The \verb|FLOW| field gives the amount of supply (if positive) or demand (if negative) at node \verb|ID|. \para{Arc descriptors.} There is one arc descriptor line for each arc in the network. Arc descriptor lines are of the following format: \begin{verbatim} a SRC DST LOW CAP COST \end{verbatim} \noindent The lower-case character \verb|a| signifies that this is an arc descriptor line. For a directed arc $(i,j)$ the \verb|SRC| field gives the identification number $i$ for the tail endpoint, and the \verb|DST| field gives the identification number $j$ for the head endpoint. Identification numbers are integers between 1 and \verb|NODES|. The \verb|LOW| field specifies the minimum amount of flow that can be sent along arc $(i,j)$, and the \verb|CAP| field gives the maximum amount of flow that can be sent along arc $(i,j)$ in a feasible flow. The \verb|COST| field contains the per-unit cost of flow sent along arc $(i,j)$. \para{Example.} Below here is an example of the data file in DIMACS format corresponding to the minimum cost flow problem shown on Fig~1. \begin{footnotesize} \begin{verbatim} c sample.min c c This is an example of the minimum cost flow problem data c in DIMACS format. c p min 9 14 c n 1 20 n 9 -20 c a 1 2 0 14 0 a 1 4 0 23 0 a 2 3 0 10 2 a 2 4 0 9 3 a 3 5 2 12 1 a 3 8 0 18 0 a 4 5 0 26 0 a 5 2 0 11 1 a 5 6 0 25 5 a 5 7 0 4 7 a 6 7 0 7 0 a 6 8 4 8 0 a 7 9 0 15 3 a 8 9 0 20 9 c c eof \end{verbatim} \end{footnotesize} \subsection{glp\_write\_mincost --- write minimum cost flow problem data in DIMACS\\format} \synopsis \begin{verbatim} int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, const char *fname); \end{verbatim} \description The routine \verb|glp_write_mincost| writes the minimum cost flow problem data to a text file in DIMACS format. The parameter \verb|G| is the graph (network) program object, which specifies the minimum cost flow problem instance. The parameter \verb|v_rhs| specifies an offset of the field of type \verb|double| in the vertex data block, which contains $b_i$, the supply/demand value. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ for all nodes. The parameter \verb|a_low| specifies an offset of the field of type \verb|double| in the arc data block, which contains $l_{ij}$, the lower bound to the arc flow. If \verb|a_low| $<0$, it is assumed that $l_{ij}=0$ for all arcs. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, which contains $u_{ij}$, the upper bound to the arc flow (the arc capacity). If the upper bound is specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that $u_{ij}=1$ for all arcs. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, which contains $c_{ij}$, the per-unit cost of the arc flow. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=0$ for all arcs. The character string \verb|fname| specifies a name of the text file to be written out. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine performs automatic compression on writing it.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \newpage \subsection{glp\_mincost\_lp --- convert minimum cost flow problem to LP} \synopsis \begin{verbatim} void glp_mincost_lp(glp_prob *P, glp_graph *G, int names, int v_rhs, int a_low, int a_cap, int a_cost); \end{verbatim} \description The routine \verb|glp_mincost_lp| builds LP problem (1)---(3), which corresponds to the specified minimum cost flow problem. The parameter \verb|P| is the resultant LP problem object to be built. Note that on entry its current content is erased with the routine \verb|glp_erase_prob|. The parameter \verb|G| is the graph (network) program object, which specifies the minimum cost flow problem instance. The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the routine uses symbolic names of the graph object components to assign symbolic names to the LP problem object components. If the flag is \verb|GLP_OFF|, no symbolic names are assigned. The parameter \verb|v_rhs| specifies an offset of the field of type \verb|double| in the vertex data block, which contains $b_i$, the supply/demand value. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ for all nodes. The parameter \verb|a_low| specifies an offset of the field of type \verb|double| in the arc data block, which contains $l_{ij}$, the lower bound to the arc flow. If \verb|a_low| $<0$, it is assumed that $l_{ij}=0$ for all arcs. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, which contains $u_{ij}$, the upper bound to the arc flow (the arc capacity). If the upper bound is specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that $u_{ij}=1$ for all arcs. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, which contains $c_{ij}$, the per-unit cost of the arc flow. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=0$ for all arcs. \para{Example} The example program below reads the minimum cost problem instance in DIMACS format from file `\verb|sample.min|', converts the instance to LP, and then writes the resultant LP in CPLEX format to file `\verb|mincost.lp|'. \begin{footnotesize} \begin{verbatim} #include #include typedef struct { double rhs; } v_data; typedef struct { double low, cap, cost; } a_data; int main(void) { glp_graph *G; glp_prob *P; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); glp_read_mincost(G, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), "sample.min"); P = glp_create_prob(); glp_mincost_lp(P, G, GLP_ON, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost)); glp_delete_graph(G); glp_write_lp(P, NULL, "mincost.lp"); glp_delete_prob(P); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.min|' is the example data file from the subsection describing \verb|glp_read_mincost|, file `\verb|mincost.lp|' may look like follows: \begin{footnotesize} \begin{verbatim} Minimize obj: + 3 x(2,4) + 2 x(2,3) + x(3,5) + 7 x(5,7) + 5 x(5,6) + x(5,2) + 3 x(7,9) + 9 x(8,9) Subject To r_1: + x(1,2) + x(1,4) = 20 r_2: - x(5,2) + x(2,3) + x(2,4) - x(1,2) = 0 r_3: + x(3,5) + x(3,8) - x(2,3) = 0 r_4: + x(4,5) - x(2,4) - x(1,4) = 0 r_5: + x(5,2) + x(5,6) + x(5,7) - x(4,5) - x(3,5) = 0 r_6: + x(6,7) + x(6,8) - x(5,6) = 0 r_7: + x(7,9) - x(6,7) - x(5,7) = 0 r_8: + x(8,9) - x(6,8) - x(3,8) = 0 r_9: - x(8,9) - x(7,9) = -20 Bounds 0 <= x(1,4) <= 23 0 <= x(1,2) <= 14 0 <= x(2,4) <= 9 0 <= x(2,3) <= 10 0 <= x(3,8) <= 18 2 <= x(3,5) <= 12 0 <= x(4,5) <= 26 0 <= x(5,7) <= 4 0 <= x(5,6) <= 25 0 <= x(5,2) <= 11 4 <= x(6,8) <= 8 0 <= x(6,7) <= 7 0 <= x(7,9) <= 15 0 <= x(8,9) <= 20 End \end{verbatim} \end{footnotesize} \newpage \subsection{glp\_mincost\_okalg --- solve minimum cost flow problem with out-of-kilter\\algorithm} \synopsis \begin{verbatim} int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, double *sol, int a_x, int v_pi); \end{verbatim} \description The routine \verb|glp_mincost_okalg| finds optimal solution to the minimum cost flow problem with the out-of-kilter algorithm.\footnote{GLPK implementation of the out-of-kilter algorithm is based on the following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, ``Flows in Networks,'' The RAND Corp., Report R-375-PR (August 1962), Chap. III ``Minimal Cost Flow Problems,'' pp.~113-26.} Note that this routine requires all the problem data to be integer-valued. The parameter \verb|G| is a graph (network) program object which specifies the minimum cost flow problem instance to be solved. The parameter \verb|v_rhs| specifies an offset of the field of type \verb|double| in the vertex data block, which contains $b_i$, the supply/demand value. This value must be integer in the range [$-$\verb|INT_MAX|, $+$\verb|INT_MAX|]. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ for all nodes. The parameter \verb|a_low| specifies an offset of the field of type \verb|double| in the arc data block, which contains $l_{ij}$, the lower bound to the arc flow. This bound must be integer in the range [$0$, \verb|INT_MAX|]. If \verb|a_low| $<0$, it is assumed that $l_{ij}=0$ for all arcs. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, which contains $u_{ij}$, the upper bound to the arc flow (the arc capacity). This bound must be integer in the range [$l_{ij}$, \verb|INT_MAX|]. If \verb|a_cap| $<0$, it is assumed that $u_{ij}=1$ for all arcs. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, which contains $c_{ij}$, the per-unit cost of the arc flow. This value must be integer in the range [$-$\verb|INT_MAX|, $+$\verb|INT_MAX|]. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=0$ for all arcs. The parameter \verb|sol| specifies a location, to which the routine stores the objective value (that is, the total cost) found. If \verb|sol| is NULL, the objective value is not stored. The parameter \verb|a_x| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores $x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow value is not stored. The parameter \verb|v_pi| specifies an offset of the field of type \verb|double| in the vertex data block, to which the routine stores $\pi_i$, the node potential, which is the Lagrange multiplier for the corresponding flow conservation equality constraint (see (2) in Subsection ``Background''). If necessary, the application program may use the node potentials to compute $\lambda_{ij}$, reduced costs of the arc flows $x_{ij}$, which are the Lagrange multipliers for the arc flow bound constraints (see (3) ibid.), using the following formula: $$\lambda_{ij}=c_{ij}-(\pi_i-\pi_j),$$ where $c_{ij}$ is the per-unit cost for arc $(i,j)$. \newpage Note that all solution components (the objective value, arc flows, and node potentials) computed by the routine are always integer-valued. \returns \begin{retlist} 0 & Optimal solution found.\\ \verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ \verb|GLP_EDATA| & Unable to start the search, because some problem data are either not integer-valued or out of range. This code is also returned if the total supply, which is the sum of $b_i$ over all source nodes (nodes with $b_i>0$), exceeds \verb|INT_MAX|.\\ \verb|GLP_ERANGE| & The search was prematurely terminated because of integer overflow.\\ \verb|GLP_EFAIL| & An error has been detected in the program logic. (If this code is returned for your problem instance, please report to \verb||.)\\ \end{retlist} \para{Comments} By design the out-of-kilter algorithm is applicable only to networks, where $b_i=0$ for {\it all} nodes, i.e. actually this algorithm finds a minimal cost {\it circulation}. Due to this requirement the routine \verb|glp_mincost_okalg| converts the original network to a network suitable for the out-of-kilter algorithm in the following way:\footnote{The conversion is performed internally and does not change the original network program object passed to the routine.} 1) it adds two auxiliary nodes $s$ and $t$; 2) for each original node $i$ with $b_i>0$ the routine adds auxiliary supply arc $(s\rightarrow i)$, flow $x_{si}$ through which is costless ($c_{si}=0$) and fixed to $+b_i$ ($l_{si}=u_{si}=+b_i$); 3) for each original node $i$ with $b_i<0$ the routine adds auxiliary demand arc $(i\rightarrow t)$, flow $x_{it}$ through which is costless ($c_{it}=0$) and fixed to $-b_i$ ($l_{it}=u_{it}=-b_i$); 4) finally, the routine adds auxiliary feedback arc $(t\rightarrow s)$, flow $x_{ts}$ through which is also costless ($c_{ts}=0$) and fixed to $F$ ($l_{ts}=u_{ts}=F$), where $\displaystyle F=\sum_{b_i>0}b_i$ is the total supply. \para{Example} The example program below reads the minimum cost problem instance in DIMACS format from file `\verb|sample.min|', solves it by using the routine \verb|glp_mincost_okalg|, and writes the solution found on the standard output. \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { double rhs, pi; } v_data; typedef struct { double low, cap, cost, x; } a_data; #define node(v) ((v_data *)((v)->data)) #define arc(a) ((a_data *)((a)->data)) int main(void) { glp_graph *G; glp_vertex *v, *w; glp_arc *a; int i, ret; double sol; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); glp_read_mincost(G, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), "sample.min"); ret = glp_mincost_okalg(G, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), &sol, offsetof(a_data, x), offsetof(v_data, pi)); printf("ret = %d; sol = %5g\n", ret, sol); for (i = 1; i <= G->nv; i++) { v = G->v[i]; printf("node %d: pi = %5g\n", i, node(v)->pi); for (a = v->out; a != NULL; a = a->t_next) { w = a->head; printf("arc %d->%d: x = %5g; lambda = %5g\n", v->i, w->i, arc(a)->x, arc(a)->cost - (node(v)->pi - node(w)->pi)); } } glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.min|' is the example data file from the subsection describing \verb|glp_read_mincost|, the output may look like follows: \begin{footnotesize} \begin{verbatim} Reading min-cost flow problem data from `sample.min'... Flow network has 9 nodes and 14 arcs 24 lines were read ret = 0; sol = 213 node 1: pi = -12 arc 1->4: x = 13; lambda = 0 arc 1->2: x = 7; lambda = 0 node 2: pi = -12 arc 2->4: x = 0; lambda = 3 arc 2->3: x = 7; lambda = 0 node 3: pi = -14 arc 3->8: x = 5; lambda = 0 arc 3->5: x = 2; lambda = 3 node 4: pi = -12 arc 4->5: x = 13; lambda = 0 node 5: pi = -12 arc 5->7: x = 4; lambda = -1 arc 5->6: x = 11; lambda = 0 arc 5->2: x = 0; lambda = 1 node 6: pi = -17 arc 6->8: x = 4; lambda = 3 arc 6->7: x = 7; lambda = -3 node 7: pi = -20 arc 7->9: x = 11; lambda = 0 node 8: pi = -14 arc 8->9: x = 9; lambda = 0 node 9: pi = -23 \end{verbatim} \end{footnotesize} \subsection{glp\_mincost\_relax4 --- solve minimum cost flow problem with relaxation\\method of Bertsekas and Tseng (RELAX-IV)} \synopsis \begin{verbatim} int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, int crash, double *sol, int a_x, int a_rc); \end{verbatim} \description The routine \verb|glp_mincost_relax4| finds optimal solution to the minimum cost flow problem with the relaxation method RELAX-IV developed by Bertsekas and Tseng.\footnote{GLPK implementation of this method is based on a C translation of the original Fortran code {\tt RELAX4} written by Dimitri P. Bertsekas and Paul Tseng, with a contribution by Jonathan Eckstein in the phase II initialization.} This method is one of most efficient methods for network optimization. Note that this routine requires all the problem data to be integer-valued. The parameter \verb|G| is a graph (network) program object which specifies the minimum cost flow problem instance to be solved. The parameter \verb|v_rhs| specifies an offset of the field of type \verb|double| in the vertex data block, which contains $b_i$, the supply/demand value. This value must be integer in the range [$-$\verb|INT_MAX|/4, $+$\verb|INT_MAX|/4]. If \verb|v_rhs| $<0$, it is assumed that $b_i=0$ for all nodes. The parameter \verb|a_low| specifies an offset of the field of type \verb|double| in the arc data block, which contains $l_{ij}$, the lower bound to the arc flow. This bound must be integer in the range {\linebreak} [$0$, \verb|INT_MAX|/4]. If \verb|a_low| $<0$, it is assumed that $l_{ij}=0$ for all arcs. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, which contains $u_{ij}$, the upper bound to the arc flow (the arc capacity). This bound must be integer in the range [$l_{ij}$, \verb|INT_MAX|/4]. If \verb|a_cap| $<0$, it is assumed that $u_{ij}=1$ for all arcs. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, which contains $c_{ij}$, the per-unit cost of the arc flow. This value must be integer in the range [$-$\verb|INT_MAX|/4, $+$\verb|INT_MAX|/4]. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=0$ for all arcs. The parameter \verb|crash| is option specifying initialization method: 0 --- default initialization is used; 1 --- auction initialization is used. \noindent If \verb|crash| = 1, initialization is performed with a special crash procedure based on an auction/shorest path method. This option is recommended for difficult problems where the default initialization results in long running times. The parameter \verb|sol| specifies a location, to which the routine stores the objective value (that is, the total cost) found. If \verb|sol| is NULL, the objective value is not stored. \newpage The parameter \verb|a_x| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores $x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow value is not stored. The parameter \verb|a_rc| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores the reduced cost for corresponding arc flow (see (3) in Subsection ``Background''). If \verb|a_rc| $<0$, the reduced cost is not stored. Note that all solution components (the objective value, arc flows, and node potentials) computed by the routine are always integer-valued. \returns \begin{retlist} 0 & Optimal solution found.\\ \verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ \verb|GLP_EDATA| & Unable to start the search, because some problem data are either not integer-valued or out of range.\\ \verb|GLP_ERANGE| & Unable to start the search because of integer overflow.\\ \end{retlist} \para{Example} The example program below reads the minimum cost problem instance in DIMACS format from file `\verb|sample.min|', solves it by using the routine \verb|glp_mincost_relax4|, and writes the solution found on the standard output. \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { double rhs; } v_data; typedef struct { double low, cap, cost, x, rc; } a_data; #define node(v) ((v_data *)((v)->data)) #define arc(a) ((a_data *)((a)->data)) int main(void) { glp_graph *G; glp_vertex *v, *w; glp_arc *a; int i, ret; double sol; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); glp_read_mincost(G, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), "sample.min"); ret = glp_mincost_relax4(G, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), 0, &sol, offsetof(a_data, x), offsetof(a_data, rc)); printf("ret = %d; sol = %5g\n", ret, sol); for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { w = a->head; printf("arc %d->%d: x = %5g; rc = %5g\n", v->i, w->i, arc(a)->x, arc(a)->rc); } } glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.min|' is the example data file from the subsection describing \verb|glp_read_mincost|, the output may look like follows: \begin{footnotesize} \begin{verbatim} Reading min-cost flow problem data from `sample.min'... Flow network has 9 nodes and 14 arcs 24 lines were read ret = 0; sol = 213 arc 1->4: x = 13; rc = 0 arc 1->2: x = 7; rc = 0 arc 2->4: x = 0; rc = 3 arc 2->3: x = 7; rc = 0 arc 3->8: x = 5; rc = 0 arc 3->5: x = 2; rc = 3 arc 4->5: x = 13; rc = 0 arc 5->7: x = 4; rc = -1 arc 5->6: x = 11; rc = 0 arc 5->2: x = 0; rc = 1 arc 6->8: x = 4; rc = 3 arc 6->7: x = 7; rc = -3 arc 7->9: x = 11; rc = 0 arc 8->9: x = 9; rc = 0 \end{verbatim} \end{footnotesize} \subsection{glp\_netgen --- Klingman's network problem generator} \synopsis \begin{verbatim} int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, const int parm[1+15]); \end{verbatim} \description The routine \verb|glp_netgen| is a GLPK version of the network problem generator developed by Dr.~Darwin~Klingman.\footnote{D.~Klingman, A.~Napier, and J.~Stutz. NETGEN: A program for generating large scale capacitated assignment, transportation, and minimum cost flow networks. Management Science 20 (1974), 814-20.} It can create capacitated and uncapacitated minimum cost flow (or transshipment), transportation, and assignment problems. The parameter \verb|G| specifies the graph object, to which the generated problem data have to be stored. Note that on entry the graph object is erased with the routine \verb|glp_erase_graph|. The parameter \verb|v_rhs| specifies an offset of the field of type \verb|double| in the vertex data block, to which the routine stores the supply or demand value. If \verb|v_rhs| $<0$, the value is not stored. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores the arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. \newpage The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores the per-unit cost if the arc flow. If \verb|a_cost| $<0$, the cost is not stored. The array \verb|parm| contains description of the network to be generated: \begin{tabular}{@{}lll@{}} \verb|parm[0] |& ¬ used\\ \verb|parm[1] |&\verb|iseed |&8-digit positive random number seed\\ \verb|parm[2] |&\verb|nprob |&8-digit problem id number\\ \verb|parm[3] |&\verb|nodes |&total number of nodes\\ \verb|parm[4] |&\verb|nsorc |&total number of source nodes (including transshipment nodes)\\ \verb|parm[5] |&\verb|nsink |&total number of sink nodes (including transshipment nodes)\\ \verb|parm[6] |&\verb|iarcs |&number of arc\\ \verb|parm[7] |&\verb|mincst|&minimum cost for arcs\\ \verb|parm[8] |&\verb|maxcst|&maximum cost for arcs\\ \verb|parm[9] |&\verb|itsup |&total supply\\ \verb|parm[10]|&\verb|ntsorc|&number of transshipment source nodes\\ \verb|parm[11]|&\verb|ntsink|&number of transshipment sink nodes\\ \verb|parm[12]|&\verb|iphic |&percentage of skeleton arcs to be given the maximum cost\\ \verb|parm[13]|&\verb|ipcap |&percentage of arcs to be capacitated\\ \verb|parm[14]|&\verb|mincap|&minimum upper bound for capacitated arcs\\ \verb|parm[15]|&\verb|maxcap|&maximum upper bound for capacitated arcs\\ \end{tabular} \returns If the instance was successfully generated, the routine \verb|glp_netgen| returns zero; otherwise, if specified parameters are inconsistent, the routine returns a non-zero error code. \para{Notes} 1. The routine generates a transportation problem if: $${\tt nsorc}+{\tt nsink}={\tt nodes}, \ {\tt ntsorc}=0,\ \mbox{and}\ {\tt ntsink}=0.$$ 2. The routine generates an assignment problem if the requirements for a transportation problem are met and: $${\tt nsorc}={\tt nsink}\ \mbox{and}\ {\tt itsup}={\tt nsorc}.$$ 3. The routine always generates connected graphs. So, if the number of requested arcs has been reached and the generated instance is not fully connected, the routine generates a few remaining arcs to ensure connectedness. Thus, the actual number of arcs generated by the routine may be greater than the requested number of arcs. \subsection{glp\_netgen\_prob --- Klingman's standard network problem instance} \synopsis \begin{verbatim} void glp_netgen_prob(int nprob, int parm[1+15]); \end{verbatim} \description The routine \verb|glp_netgen_prob| provides the set of parameters for Klingman's network problem generator (see the routine \verb|glp_netgen|), which describe a standard network problem instance. The parameter \verb|nprob| ($101\leq$ \verb|nprob| $\leq 150$) specifies the problem instance number. The array \verb|parm| contains description of the network, provided by the routine. (For detailed description of these parameters see comments to the routine \verb|glp_netgen|.) \para{Problem characteristics} The table below shows characteristics of Klingman's standard network problem instances. $$ \begin{array}{crrr} {\rm Problem} & {\rm Nodes} & {\rm Arcs} & {\rm Optimum} \\ \hline 101 & 5000 & 25336 & 6191726 \\ 102 & 5000 & 25387 & 72337144 \\ 103 & 5000 & 25355 & 218947553 \\ 104 & 5000 & 25344 & -19100371 \\ 105 & 5000 & 25332 & 31192578 \\ 106 & 5000 & 12870 & 4314276 \\ 107 & 5000 & 37832 & 7393769 \\ 108 & 5000 & 50309 & 8405738 \\ 109 & 5000 & 75299 & 9190300 \\ 110 & 5000 & 12825 & 8975048 \\ 111 & 5000 & 37828 & 4747532 \\ 112 & 5000 & 50325 & 4012671 \\ 113 & 5000 & 75318 & 2979725 \\ 114 & 5000 & 26514 & 5821181 \\ 115 & 5000 & 25962 & 6353310 \\ 116 & 5000 & 25304 & 5915426 \\ 117 & 5000 & 12816 & 4420560 \\ 118 & 5000 & 37797 & 7045842 \\ 119 & 5000 & 50301 & 7724179 \\ 120 & 5000 & 75330 & 8455200 \\ 121 & 5000 & 25000 & 66366360 \\ 122 & 5000 & 25000 & 30997529 \\ 123 & 5000 & 25000 & 23388777 \\ 124 & 5000 & 25000 & 17803443 \\ 125 & 5000 & 25000 & 14119622 \\ \end{array} \hspace{.5in} \begin{array}{crrr} {\rm Problem} & {\rm Nodes} & {\rm Arcs} & {\rm Optimum} \\ \hline 126 & 5000 & 12500 & 18802218 \\ 127 & 5000 & 37500 & 27674647 \\ 128 & 5000 & 50000 & 30906194 \\ 129 & 5000 & 75000 & 40905209 \\ 130 & 5000 & 12500 & 38939608 \\ 131 & 5000 & 37500 & 16752978 \\ 132 & 5000 & 50000 & 13302951 \\ 133 & 5000 & 75000 & 9830268 \\ 134 & 1000 & 25000 & 3804874 \\ 135 & 2500 & 25000 & 11729616 \\ 136 & 7500 & 25000 & 33318101 \\ 137 & 10000 & 25000 & 46426030 \\ 138 & 5000 & 25000 & 60710879 \\ 139 & 5000 & 25000 & 32729682 \\ 140 & 5000 & 25000 & 27183831 \\ 141 & 5000 & 25000 & 19963286 \\ 142 & 5000 & 25000 & 20243457 \\ 143 & 5000 & 25000 & 18586777 \\ 144 & 5000 & 25000 & 2504591 \\ 145 & 5000 & 25000 & 215956138 \\ 146 & 5000 & 25000 & 2253113811 \\ 147 & 5000 & 25000 & -427908373 \\ 148 & 5000 & 25000 & -92965318 \\ 149 & 5000 & 25000 & 86051224 \\ 150 & 5000 & 25000 & 619314919 \\ \end{array} $$ \subsection{glp\_gridgen --- grid-like network problem generator} \synopsis \begin{verbatim} int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, const int parm[1+14]); \end{verbatim} \description The routine \verb|glp_gridgen| is a GLPK version of the grid-like network problem generator developed by Yusin Lee and Jim Orlin.\footnote{Y.~Lee and J.~Orlin. GRIDGEN generator., 1991. The original code is publically available from \url{ftp://dimacs.rutgers.edu/pub/netflow/generators/network/gridgen}.} \newpage The parameter \verb|G| specifies the graph object, to which the generated problem data have to be stored. Note that on entry the graph object is erased with the routine \verb|glp_erase_graph|. The parameter \verb|v_rhs| specifies an offset of the field of type \verb|double| in the vertex data block, to which the routine stores the supply or demand value. If \verb|v_rhs| $<0$, the value is not stored. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores the arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores the per-unit cost if the arc flow. If \verb|a_cost| $<0$, the cost is not stored. The array \verb|parm| contains parameters of the network to be generated: \begin{tabular}{@{}ll@{}} \verb|parm[0] |¬ used\\ \verb|parm[1] |&two-ways arcs indicator:\\ &1 --- if links in both direction should be generated\\ &0 --- otherwise\\ \verb|parm[2] |&random number seed (a positive integer)\\ \verb|parm[3] |&number of nodes (the number of nodes generated might be slightly different to\\&make the network a grid)\\ \verb|parm[4] |&grid width\\ \verb|parm[5] |&number of sources\\ \verb|parm[6] |&number of sinks\\ \verb|parm[7] |&average degree\\ \verb|parm[8] |&total flow\\ \verb|parm[9] |&distribution of arc costs: 1 --- uniform, 2 --- exponential\\ \verb|parm[10]|&lower bound for arc cost (uniform), $100\lambda$ (exponential)\\ \verb|parm[11]|&upper bound for arc cost (uniform), not used (exponential)\\ \verb|parm[12]|&distribution of arc capacities: 1 --- uniform, 2 --- exponential\\ \verb|parm[13]|&lower bound for arc capacity (uniform), $100\lambda$ (exponential)\\ \verb|parm[14]|&upper bound for arc capacity (uniform), not used (exponential)\\ \end{tabular} \returns If the instance was successfully generated, the routine \verb|glp_gridgen| returns zero; otherwise, if specified parameters are inconsistent, the routine returns a non-zero error code. \para{Comments\footnote{This material is based on comments to the original version of GRIDGEN.}} This network generator generates a grid-like network plus a super node. In additional to the arcs connecting the nodes in the grid, there is an arc from each supply node to the super node and from the super node to each demand node to guarantee feasiblity. These arcs have very high costs and very big capacities. The idea of this network generator is as follows: First, a grid of $n_1\times n_2$ is generated. For example, $5\times 3$. The nodes are numbered as 1 to 15, and the supernode is numbered as $n_1\times n_2+1$. Then arcs between adjacent nodes are generated. For these arcs, the user is allowed to specify either to generate two-way arcs or one-way arcs. If two-way arcs are to be generated, two arcs, one in each direction, will be generated between each adjacent node pairs. Otherwise, only one arc will be generated. If this is the case, the arcs will be generated in alterntive directions as shown below. \medskip \noindent\hfil \xymatrix {1\ar[r]\ar[d]&2\ar[r]&3\ar[r]\ar[d]&4\ar[r]&5\ar[d]\\ 6\ar[d]&7\ar[l]\ar[u]&8\ar[l]\ar[d]&9\ar[l]\ar[u]&10\ar[l]\ar[d]\\ 11\ar[r]&12\ar[r]\ar[u]&13\ar[r]&14\ar[r]\ar[u]&15\\ } \medskip Then the arcs between the super node and the source/sink nodes are added as mentioned before. If the number of arcs still doesn't reach the requirement, additional arcs will be added by uniformly picking random node pairs. There is no checking to prevent multiple arcs between any pair of nodes. However, there will be no self-arcs (arcs that poins back to its tail node) in the network. The source and sink nodes are selected uniformly in the network, and the imbalances of each source/sink node are also assigned by uniform distribution. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Maximum flow problem} \subsection{Background} The {\it maximum flow problem} (MAXFLOW) is stated as follows. Let there be given a directed graph (flow network) $G=(V,A)$, where $V$ is a set of vertices (nodes), and $A\subseteq V\times V$ is a set of arcs. Let also for each arc $a=(i,j)\in A$ there be given its capacity $u_{ij}$. The problem is, for given {\it source} node $s\in V$ and {\it sink} node $t\in V$, to find flows $x_{ij}$ through every arc of the network, which satisfy the specified arc capacities and the conservation constraints at all nodes, and maximize the total flow $F$ through the network from $s$ to $t$. Here the conservation constraint at a node means that the total flow entering this node through its incoming arcs (plus $F$, if it is the source node) must be equal to the total flow leaving this node through its outgoing arcs (plus $F$, if it is the sink node). An example of the maximum flow problem, where $s=v_1$ and $t=v_9$, is shown on Fig.~2. \medskip \noindent\hfil \xymatrix @C=48pt {_{F}\ar@{~>}[d]& v_2\ar[r]|{_{10}}\ar[dd]|{_{9}}& v_3\ar[dd]|{_{12}}\ar[r]|{_{18}}& v_8\ar[rd]|{_{20}}&\\ v_1\ar[ru]|{_{14}}\ar[rd]|{_{23}}&&& v_6\ar[d]|{_{7}}\ar[u]|{_{8}}& v_9\ar@{~>}[d]\\ &v_4\ar[r]|{_{26}}& v_5\ar[luu]|{_{11}}\ar[ru]|{_{25}}\ar[r]|{_{4}}& v_7\ar[ru]|{_{15}}&_{F}\\ } \medskip \noindent\hfil Fig.~2. An example of the maximum flow problem. \medskip The maximum flow problem can be naturally formulated as the following LP problem: \noindent \hspace{1in}maximize $$F\eqno(4)$$ \hspace{1in}subject to $$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}=\left\{ \begin{array}{@{\ }rl} +F,&\hbox{for}\ i=s\\ 0,&\hbox{for all}\ i\in V\backslash\{s,t\}\\ -F,&\hbox{for}\ i=t\\ \end{array} \right.\eqno(5) $$ $$0\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A \eqno(6)$$ \noindent where $F\geq 0$ is an additional variable playing the role of the objective. Another LP formulation of the maximum flow problem, which does not include the variable $F$, is the following: \noindent \hspace{1in}maximize $$z=\sum_{(s,j)\in A}x_{sj}-\sum_{(j,s)\in A}x_{js}\ (=F)\eqno(7)$$ \hspace{1in}subject to $$\sum_{(i,j)\in A}x_{ij}-\sum_{(j,i)\in A}x_{ji}\left\{ \begin{array}{@{\ }rl} \geq 0,&\hbox{for}\ i=s\\ =0,&\hbox{for all}\ i\in V\backslash\{s,t\}\\ \leq 0,&\hbox{for}\ i=t\\ \end{array} \right.\eqno(8) $$ $$0\leq x_{ij}\leq u_{ij}\ \ \ \hbox{for all}\ (i,j)\in A \eqno(9)$$ \subsection{glp\_read\_maxflow --- read maximum flow problem data in DIMACS\\format} \synopsis \begin{verbatim} int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, const char *fname); \end{verbatim} \description The routine \verb|glp_read_maxflow| reads the maximum flow problem data from a text file in DIMACS format. The parameter \verb|G| specifies the graph object, to which the problem data have to be stored. Note that before reading data the current content of the graph object is completely erased with the routine \verb|glp_erase_graph|. The pointer \verb|s| specifies a location, to which the routine stores the ordinal number of the source node. If \verb|s| is \verb|NULL|, the source node number is not stored. The pointer \verb|t| specifies a location, to which the routine stores the ordinal number of the sink node. If \verb|t| is \verb|NULL|, the sink node number is not stored. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores $u_{ij}$, the arc capacity. If \verb|a_cap| $<0$, the arc capacity is not stored. The character string \verb|fname| specifies the name of a text file to be read in. (If the file name name ends with the suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine decompresses it ``on the fly''.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \para{Example} \begin{footnotesize} \begin{verbatim} typedef struct { /* arc data block */ ... double cap; ... } a_data; int main(void) { glp_graph *G; int s, t, ret; G = glp_create_graph(..., sizeof(a_data)); ret = glp_read_maxflow(G, &s, &t, offsetof(a_data, cap), "sample.max"); if (ret != 0) goto ... ... } \end{verbatim} \end{footnotesize} \newpage \para{DIMACS maximum flow problem format\footnote{This material is based on the paper ``The First DIMACS International Algorithm Implementation Challenge: Problem Definitions and Specifications'', which is publically available at \url{http://dimacs.rutgers.edu/Challenges/}.}} \label{subsecmaxflow} The DIMACS input file is a plain ASCII text file. It contains {\it lines} of several types described below. A line is terminated with an end-of-line character. Fields in each line are separated by at least one blank space. Each line begins with a one-character designator to identify the line type. Note that DIMACS requires all numerical quantities to be integers in the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be floating-point numbers. \para{Comment lines.} Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character \verb|c|. \begin{verbatim} c This is a comment line \end{verbatim} \para{Problem line.} There is one problem line per data file. The problem line must appear before any node or arc descriptor lines. It has the following format: \begin{verbatim} p max NODES ARCS \end{verbatim} \noindent The lower-case character \verb|p| signifies that this is a problem line. The three-character problem designator \verb|max| identifies the file as containing specification information for the maximum flow problem. The \verb|NODES| field contains an integer value specifying the number of nodes in the network. The \verb|ARCS| field contains an integer value specifying the number of arcs in the network. \para{Node descriptors.} Two node descriptor lines for the source and sink nodes must appear before all arc descriptor lines. They may appear in either order, each with the following format: \begin{verbatim} n ID WHICH \end{verbatim} \noindent The lower-case character \verb|n| signifies that this a node descriptor line. The \verb|ID| field gives a node identification number, an integer between 1 and \verb|NODES|. The \verb|WHICH| field gives either a lower-case \verb|s| or \verb|t|, designating the source and sink, respectively. \para{Arc descriptors.} There is one arc descriptor line for each arc in the network. Arc descriptor lines are of the following format: \begin{verbatim} a SRC DST CAP \end{verbatim} \noindent The lower-case character \verb|a| signifies that this is an arc descriptor line. For a directed arc $(i,j)$ the \verb|SRC| field gives the identification number $i$ for the tail endpoint, and the \verb|DST| field gives the identification number $j$ for the head endpoint. Identification numbers are integers between 1 and \verb|NODES|. The \verb|CAP| field gives the arc capacity, i.e. maximum amount of flow that can be sent along arc $(i,j)$ in a feasible flow. \para{Example.} Below here is an example of the data file in DIMACS format corresponding to the maximum flow problem shown on Fig~2. \begin{footnotesize} \begin{verbatim} c sample.max c c This is an example of the maximum flow problem data c in DIMACS format. c p max 9 14 c n 1 s n 9 t c a 1 2 14 a 1 4 23 a 2 3 10 a 2 4 9 a 3 5 12 a 3 8 18 a 4 5 26 a 5 2 11 a 5 6 25 a 5 7 4 a 6 7 7 a 6 8 8 a 7 9 15 a 8 9 20 c c eof \end{verbatim} \end{footnotesize} \subsection{glp\_write\_maxflow --- write maximum flow problem data in DIMACS\\format} \synopsis \begin{verbatim} int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, const char *fname); \end{verbatim} \description The routine \verb|glp_write_maxflow| writes the maximum flow problem data to a text file in DIMACS format. The parameter \verb|G| is the graph (network) program object, which specifies the maximum flow problem instance. The parameter \verb|s| specifies the ordinal number of the source node. The parameter \verb|t| specifies the ordinal number of the sink node. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, which contains $u_{ij}$, the upper bound to the arc flow (the arc capacity). If the upper bound is specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that $u_{ij}=1$ for all arcs. The character string \verb|fname| specifies a name of the text file to be written out. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine performs automatic compression on writing it.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \newpage \subsection{glp\_maxflow\_lp --- convert maximum flow problem to LP} \synopsis \begin{verbatim} void glp_maxflow_lp(glp_prob *P, glp_graph *G, int names, int s, int t, int a_cap); \end{verbatim} \description The routine \verb|glp_maxflow_lp| builds LP problem (7)---(9), which corresponds to the specified maximum flow problem. The parameter \verb|P| is the resultant LP problem object to be built. Note that on entry its current content is erased with the routine \verb|glp_erase_prob|. The parameter \verb|G| is the graph (network) program object, which specifies the maximum flow problem instance. The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the routine uses symbolic names of the graph object components to assign symbolic names to the LP problem object components. If the flag is \verb|GLP_OFF|, no symbolic names are assigned. The parameter \verb|s| specifies the ordinal number of the source node. The parameter \verb|t| specifies the ordinal number of the sink node. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, which contains $u_{ij}$, the upper bound to the arc flow (the arc capacity). If the upper bound is specified as \verb|DBL_MAX|, it is assumed that $u_{ij}=\infty$, i.e. the arc is uncapacitated. If \verb|a_cap| $<0$, it is assumed that $u_{ij}=1$ for all arcs. \para{Example} The example program below reads the maximum flow problem in DIMACS format from file `\verb|sample.max|', converts the instance to LP, and then writes the resultant LP in CPLEX format to file `\verb|maxflow.lp|'. \begin{footnotesize} \begin{verbatim} #include #include int main(void) { glp_graph *G; glp_prob *P; int s, t; G = glp_create_graph(0, sizeof(double)); glp_read_maxflow(G, &s, &t, 0, "sample.max"); P = glp_create_prob(); glp_maxflow_lp(P, G, GLP_ON, s, t, 0); glp_delete_graph(G); glp_write_lp(P, NULL, "maxflow.lp"); glp_delete_prob(P); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.max|' is the example data file from the previous subsection, the output `\verb|maxflow.lp|' may look like follows: \newpage \begin{footnotesize} \begin{verbatim} Maximize obj: + x(1,4) + x(1,2) Subject To r_1: + x(1,2) + x(1,4) >= 0 r_2: - x(5,2) + x(2,3) + x(2,4) - x(1,2) = 0 r_3: + x(3,5) + x(3,8) - x(2,3) = 0 r_4: + x(4,5) - x(2,4) - x(1,4) = 0 r_5: + x(5,2) + x(5,6) + x(5,7) - x(4,5) - x(3,5) = 0 r_6: + x(6,7) + x(6,8) - x(5,6) = 0 r_7: + x(7,9) - x(6,7) - x(5,7) = 0 r_8: + x(8,9) - x(6,8) - x(3,8) = 0 r_9: - x(8,9) - x(7,9) <= 0 Bounds 0 <= x(1,4) <= 23 0 <= x(1,2) <= 14 0 <= x(2,4) <= 9 0 <= x(2,3) <= 10 0 <= x(3,8) <= 18 0 <= x(3,5) <= 12 0 <= x(4,5) <= 26 0 <= x(5,7) <= 4 0 <= x(5,6) <= 25 0 <= x(5,2) <= 11 0 <= x(6,8) <= 8 0 <= x(6,7) <= 7 0 <= x(7,9) <= 15 0 <= x(8,9) <= 20 End \end{verbatim} \end{footnotesize} \subsection{glp\_maxflow\_ffalg --- solve maximum flow problem with Ford-Fulkerson\\algorithm} \synopsis \begin{verbatim} int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, double *sol, int a_x, int v_cut); \end{verbatim} \description The routine \verb|glp_mincost_ffalg| finds optimal solution to the maximum flow problem with the Ford-Fulkerson algorithm.\footnote{GLPK implementation of the Ford-Fulkerson algorithm is based on the following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, ``Flows in Networks,'' The RAND Corp., Report R-375-PR (August 1962), Chap. I ``Static Maximal Flow,'' pp.~30-33.} Note that this routine requires all the problem data to be integer-valued. The parameter \verb|G| is a graph (network) program object which specifies the maximum flow problem instance to be solved. The parameter $s$ specifies the ordinal number of the source node. \newpage The parameter $t$ specifies the ordinal number of the sink node. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, which contains $u_{ij}$, the upper bound to the arc flow (the arc capacity). This bound must be integer in the range [0, \verb|INT_MAX|]. If \verb|a_cap| $<0$, it is assumed that $u_{ij}=1$ for all arcs. The parameter \verb|sol| specifies a location, to which the routine stores the objective value (that is, the total flow from $s$ to $t$) found. If \verb|sol| is NULL, the objective value is not stored. The parameter \verb|a_x| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores $x_{ij}$, the arc flow found. If \verb|a_x| $<0$, the arc flow values are not stored. The parameter \verb|v_cut| specifies an offset of the field of type \verb|int| in the vertex data block, to which the routine stores node flags corresponding to the optimal solution found: if the node flag is 1, the node is labelled, and if the node flag is 0, the node is unlabelled. The calling program may use these node flags to determine the {\it minimal cut}, which is a subset of arcs whose one endpoint is labelled and other is not. If \verb|v_cut| $<0$, the node flags are not stored. Note that all solution components (the objective value and arc flows) computed by the routine are always integer-valued. \returns \begin{retlist} 0 & Optimal solution found.\\ \verb|GLP_EDATA| & Unable to start the search, because some problem data are either not integer-valued or out of range.\\ \end{retlist} \para{Example} The example program shown below reads the maximum flow problem instance in DIMACS format from file `\verb|sample.max|', solves it using the routine \verb|glp_maxflow_ffalg|, and write the solution found to the standard output. \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { int cut; } v_data; typedef struct { double cap, x; } a_data; #define node(v) ((v_data *)((v)->data)) #define arc(a) ((a_data *)((a)->data)) int main(void) { glp_graph *G; glp_vertex *v, *w; glp_arc *a; int i, s, t, ret; double sol; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); glp_read_maxflow(G, &s, &t, offsetof(a_data, cap), "sample.max"); ret = glp_maxflow_ffalg(G, s, t, offsetof(a_data, cap), &sol, offsetof(a_data, x), offsetof(v_data, cut)); printf("ret = %d; sol = %5g\n", ret, sol); for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { w = a->head; printf("x[%d->%d] = %5g (%d)\n", v->i, w->i, arc(a)->x, node(v)->cut ^ node(w)->cut); } } glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.max|' is the example data file from the subsection describing \verb|glp_read_maxflow|, the output may look like follows: \begin{footnotesize} \begin{verbatim} Reading maximum flow problem data from `sample.max'... Flow network has 9 nodes and 14 arcs 24 lines were read ret = 0; sol = 29 x[1->4] = 19 (0) x[1->2] = 10 (0) x[2->4] = 0 (0) x[2->3] = 10 (1) x[3->8] = 10 (0) x[3->5] = 0 (1) x[4->5] = 19 (0) x[5->7] = 4 (1) x[5->6] = 15 (0) x[5->2] = 0 (0) x[6->8] = 8 (1) x[6->7] = 7 (1) x[7->9] = 11 (0) x[8->9] = 18 (0) \end{verbatim} \end{footnotesize} \subsection{glp\_rmfgen --- Goldfarb's maximum flow problem generator} \synopsis \begin{verbatim} int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, const int parm[1+5]); \end{verbatim} \description The routine \verb|glp_rmfgen| is a GLPK version of the maximum flow problem generator developed by D.~Goldfarb and M.~Grigoriadis.\footnote{D.~Goldfarb and M.~D.~Grigoriadis, ``A computational comparison of the Dinic and network simplex methods for maximum flow.'' Annals of Op. Res. 13 (1988), pp.~83-123.}$^{,}$\footnote{U.~Derigs and W.~Meier, ``Implementing Goldberg's max-flow algorithm: A computational investigation.'' Zeitschrift f\"ur Operations Research 33 (1989), pp.~383-403.}$^{,}$\footnote{The original code of RMFGEN implemented by Tamas Badics is publically available from \url{ftp://dimacs.rutgers.edu/pub/netflow/generators/network/genrmf}.} The parameter \verb|G| specifies the graph object, to which the generated problem data have to be stored. Note that on entry the graph object is erased with the routine \verb|glp_erase_graph|. \newpage The pointers \verb|s| and \verb|t| specify locations, to which the routine stores the source and sink node numbers, respectively. If \verb|s| or \verb|t| is \verb|NULL|, corresponding node number is not stored. The parameter \verb|a_cap| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores the arc capacity. If \verb|a_cap| $<0$, the capacity is not stored. The array \verb|parm| contains description of the network to be generated: \begin{tabular}{@{}lll@{}} \verb|parm[0]|& ¬ used\\ \verb|parm[1]|&\verb|seed|&random number seed (a positive integer)\\ \verb|parm[2]|&\verb|a |&frame size\\ \verb|parm[3]|&\verb|b |&depth\\ \verb|parm[4]|&\verb|c1 |&minimal arc capacity\\ \verb|parm[5]|&\verb|c2 |&maximal arc capacity\\ \end{tabular} \returns If the instance was successfully generated, the routine \verb|glp_netgen| returns zero; otherwise, if specified parameters are inconsistent, the routine returns a non-zero error code. \para{Comments\footnote{This material is based on comments to the original version of RMFGEN.}} The generated network is as follows. It has $b$ pieces of frames of size $a\times a$. (So alltogether the number of vertices is $a\times a\times b$.) In each frame all the vertices are connected with their neighbours (forth and back). In addition the vertices of a frame are connected one to one with the vertices of next frame using a random permutation of those vertices. The source is the lower left vertex of the first frame, the sink is the upper right vertex of the $b$-th frame. \begin{verbatim} t +-------+ | .| | . | / | / | +-------+/ -+ b | | |/. a | -v- |/ | | |/ +-------+ 1 s a \end{verbatim} The capacities are randomly chosen integers from the range of $[c_1,c_2]$ in the case of interconnecting edges, and $c_2\cdot a^2$ for the in-frame edges. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Assignment problem} \subsection{Background} Let there be given an undirected bipartite graph $G=(R\cup S,E)$, where $R$ and $S$ are disjoint sets of vertices (nodes), and $E\subseteq R\times S$ is a set of edges. Let also for each edge $e=(i,j)\in E$ there be given its cost $c_{ij}$. A {\it matching} (which in case of bipartite graph is also called {\it assignment}) $M\subseteq E$ in $G$ is a set of pairwise non-adjacent edges, that is, no two edges in $M$ share a common vertex. A matching, which matches all vertices of the graph, is called a {\it perfect matching}. Obviously, a perfect matching in bipartite graph $G=(R\cup S,E)$ defines some bijection $R\leftrightarrow S$. The {\it assignment problem} has two different variants. In the first variant the problem is to find matching (assignment) $M$, which maximizes the sum: $$\sum_{(i,j)\in M}c_{ij}\eqno(10)$$ (so this variant is also called the {\it maximum weighted bipartite matching problem} or, if all $c_{ij}=1$, the {\it maximum cardinality bipartite matching problem}). In the second, classic variant the problem is to find {\it perfect} matching (assignment) $M$, which minimizes or maximizes the sum (10). An example of the assignment problem, which is the maximum weighted bipartite matching problem, is shown on Fig. 3. The maximum weighted bipartite matching problem can be naturally formulated as the following LP problem: \noindent \hspace{1in}maximize $$z=\sum_{(i,j)\in E}c_{ij}x_{ij}\eqno(11)$$ \hspace{1in}subject to $$\sum_{(i,j)\in E}x_{ij}\leq 1\ \ \ \hbox{for all}\ i\in R\eqno(12)$$ $$\sum_{(i,j)\in E}x_{ij}\leq 1\ \ \ \hbox{for all}\ j\in S\eqno(13)$$ $$\ \ \ \ \ \ \ \ 0\leq x_{ij}\leq 1\ \ \ \hbox{for all}\ (i,j)\in E \eqno(14)$$ \noindent where $x_{ij}=1$ means that $(i,j)\in M$, and $x_{ij}=0$ means that $(i,j)\notin M$.\footnote{The constraint matrix of LP formulation (11)---(14) is totally unimodular, due to which $x_{ij}\in\{0,1\}$ for any basic solution.} \newpage \noindent\hfil \xymatrix @C=48pt {v_1\ar@{-}[rr]|{_{13}}\ar@{-}[rrd]|{_{21}}\ar@{-}[rrddd]|(.2){_{20}}&& v_9\\ v_2\ar@{-}[rr]|{_{12}}\ar@{-}[rrdd]|(.3){_{8}} \ar@{-}[rrddd]|(.4){_{26}}&&v_{10}\\ v_3\ar@{-}[rr]|(.2){_{22}}\ar@{-}[rrdd]|(.3){_{11}}&&v_{11}\\ v_4\ar@{-}[rruuu]|(.6){_{12}}\ar@{-}[rr]|(.2){_{36}} \ar@{-}[rrdd]|(.7){_{25}}&&v_{12}\\ v_5\ar@{-}[rruu]|(.42){_{41}}\ar@{-}[rru]|(.4){_{40}} \ar@{-}[rr]|(.75){_{11}}\ar@{-}[rrd]|(.6){_{4}}\ar@{-}[rrdd]|{_{8}} \ar@{-}[rrddd]|{_{35}}\ar@{-}[rrdddd]|{_{32}}&&v_{13}\\ v_6\ar@{-}[rruuuuu]|(.7){_{13}}&&v_{14}\\ v_7\ar@{-}[rruuuuu]|(.15){_{19}}&&v_{15}\\ v_8\ar@{-}[rruuuuuu]|(.25){_{39}}\ar@{-}[rruuuuu]|(.65){_{15}}&& v_{16}\\ &&v_{17}\\ } \medskip \noindent\hfil Fig.~3. An example of the assignment problem. \medskip Similarly, the perfect assignment problem can be naturally formulated as the following LP problem: \noindent \hspace{1in}minimize (or maximize) $$z=\sum_{(i,j)\in E}c_{ij}x_{ij}\eqno(15)$$ \hspace{1in}subject to $$\sum_{(i,j)\in E}x_{ij}=1\ \ \ \hbox{for all}\ i\in R\eqno(16)$$ $$\sum_{(i,j)\in E}x_{ij}=1\ \ \ \hbox{for all}\ j\in S\eqno(17)$$ $$\ \ \ \ \ \ \ \ 0\leq x_{ij}\leq 1\ \ \ \hbox{for all}\ (i,j)\in E \eqno(18)$$ \noindent where variables $x_{ij}$ have the same meaning as for (11)---(14) above. In GLPK an undirected bipartite graph $G=(R\cup S,E)$ is represented as directed graph $\overline{G}=(V,A)$, where $V=R\cup S$ and $A=\{(i,j):(i,j)\in E\}$, i.e. every edge $(i,j)\in E$ in $G$ corresponds to arc $(i\rightarrow j)\in A$ in $\overline{G}$. \subsection{glp\_read\_asnprob --- read assignment problem data in DIMACS format} \synopsis \begin{verbatim} int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); \end{verbatim} \description The routine \verb|glp_read_asnprob| reads the assignment problem data from a text file in DIMACS format. The parameter \verb|G| specifies the graph object, to which the problem data have to be stored. Note that before reading data the current content of the graph object is completely erased with the routine \verb|glp_erase_graph|. The parameter \verb|v_set| specifies an offset of the field of type \verb|int| in the vertex data block, to which the routine stores the node set indicator: 0 --- the node is in set $R$; 1 --- the node is in set $S$. \noindent If \verb|v_set| $<0$, the node set indicator is not stored. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, to which the routine stores the edge cost $c_{ij}$. If \verb|a_cost| $<0$, the edge cost is not stored. The character string \verb|fname| specifies the name of a text file to be read in. (If the file name name ends with the suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine decompresses it ``on the fly''.) \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \para{Example.} Below here is an example program that read the assignment problem data in DIMACS format from a text file `\verb|sample.asn|'. \begin{footnotesize} \begin{verbatim} typedef struct { /* vertex data block */ ... int set; ... } v_data; typedef struct { /* arc data block */ ... double cost; ... } a_data; int main(void) { glp_graph *G; int ret; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_asnprob(G, offsetof(v_data, set), offsetof(a_data, cost), "sample.asn"); if (ret != 0) goto ... ... } \end{verbatim} \end{footnotesize} \para{DIMACS assignment problem format\footnote{This material is based on the paper ``The First DIMACS International Algorithm Implementation Challenge: Problem Definitions and Specifications'', which is publically available at \url{http://dimacs.rutgers.edu/Challenges/}.}} \label{subsecasnprob} The DIMACS input file is a plain ASCII text file. It contains {\it lines} of several types described below. A line is terminated with an end-of-line character. Fields in each line are separated by at least one blank space. Each line begins with a one-character designator to identify the line type. Note that DIMACS requires all numerical quantities to be integers in the range $[-2^{31},\ 2^{31}-1]$ while GLPK allows the quantities to be floating-point numbers. \para{Comment lines.} Comment lines give human-readable information about the file and are ignored by programs. Comment lines can appear anywhere in the file. Each comment line begins with a lower-case character \verb|c|. \begin{verbatim} c This is a comment line \end{verbatim} \para{Problem line.} There is one problem line per data file. The problem line must appear before any node or arc descriptor lines. It has the following format: \begin{verbatim} p asn NODES EDGES \end{verbatim} \noindent The lower-case character \verb|p| signifies that this is a problem line. The three-character problem designator \verb|asn| identifies the file as containing specification information for the assignment problem. The \verb|NODES| field contains an integer value specifying the total number of nodes in the graph (i.e. in both sets $R$ and $S$). The \verb|EDGES| field contains an integer value specifying the number of edges in the graph. \para{Node descriptors.} All node descriptor lines must appear before all edge descriptor lines. The node descriptor lines lists the nodes in set $R$ only, and all other nodes are assumed to be in set $S$. There is one node descriptor line for each such node, with the following format: \begin{verbatim} n ID \end{verbatim} \noindent The lower-case character \verb|n| signifies that this is a node descriptor line. The \verb|ID| field gives a node identification number, an integer between 1 and \verb|NODES|. \para{Edge descriptors.} There is one edge descriptor line for each edge in the graph. Edge descriptor lines are of the following format: \begin{verbatim} a SRC DST COST \end{verbatim} \noindent The lower-case character \verb|a| signifies that this is an edge descriptor line. For each edge $(i,j)$, where $i\in R$ and $j\in S$, the \verb|SRC| field gives the identification number of vertex $i$, and the \verb|DST| field gives the identification number of vertex $j$. Identification numbers are integers between 1 and \verb|NODES|. The \verb|COST| field contains the cost of edge $(i,j)$. \para{Example.} Below here is an example of the data file in DIMACS format corresponding to the assignment problem shown on Fig~3. \begin{footnotesize} \begin{verbatim} c sample.asn c c This is an example of the assignment problem data c in DIMACS format. c p asn 17 22 c n 1 n 2 n 3 n 4 n 5 n 6 n 7 n 8 c a 1 9 13 a 1 10 21 a 1 12 20 a 2 10 12 a 2 12 8 a 2 13 26 a 3 11 22 a 3 13 11 a 4 9 12 a 4 12 36 a 4 14 25 a 5 11 41 a 5 12 40 a 5 13 11 a 5 14 4 a 5 15 8 a 5 16 35 a 5 17 32 a 6 9 13 a 7 10 19 a 8 10 39 a 8 11 15 c c eof \end{verbatim} \end{footnotesize} \newpage \subsection{glp\_write\_asnprob --- write assignment problem data in DIMACS format} \synopsis \begin{verbatim} int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); \end{verbatim} \description The routine \verb|glp_write_asnprob| writes the assignment problem data to a text file in DIMACS format. The parameter \verb|G| is the graph program object, which specifies the assignment problem instance. The parameter \verb|v_set| specifies an offset of the field of type \verb|int| in the vertex data block, which contains the node set indicator: 0 --- the node is in set $R$; 1 --- the node is in set $S$. \noindent If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs is in set $R$, and a node having no outgoing arcs is in set $S$. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, which contains $c_{ij}$, the edge cost. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ for all edges. The character string \verb|fname| specifies a name of the text file to be written out. (If the file name ends with suffix `\verb|.gz|', the file is assumed to be compressed, in which case the routine performs automatic compression on writing it.) \para{Note} The routine \verb|glp_write_asnprob| does not check that the specified graph object correctly represents a bipartite graph. To make sure that the problem data are correct, use the routine \verb|glp_check_asnprob|. \returns If the operation was successful, the routine returns zero. Otherwise, it prints an error message and returns non-zero. \vspace*{-4pt} \subsection{glp\_check\_asnprob --- check correctness of assignment problem data} \synopsis \begin{verbatim} int glp_check_asnprob(glp_graph *G, int v_set); \end{verbatim} \description The routine \verb|glp_check_asnprob| checks that the specified graph object \verb|G| correctly represents a bipartite graph. The parameter \verb|v_set| specifies an offset of the field of type \verb|int| in the vertex data block, which contains the node set indicator: 0 --- the node is in set $R$; 1 --- the node is in set $S$. \noindent If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs is in set $R$, and a node having no outgoing arcs is in set $S$. \returns 0 --- the data are correct; 1 --- the set indicator of some node is 0, however, that node has one or more incoming arcs; 2 --- the set indicator of some node is 1, however, that node has one or more outgoing arcs; 3 --- the set indicator of some node is invalid (neither 0 nor 1); 4 --- some node has both incoming and outgoing arcs. \subsection{glp\_asnprob\_lp --- convert assignment problem to LP} \synopsis \begin{verbatim} int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, int v_set, int a_cost); \end{verbatim} \description The routine \verb|glp_asnprob_lp| builds LP problem, which corresponds to the specified assignment problem. The parameter \verb|P| is the resultant LP problem object to be built. Note that on entry its current content is erased with the routine \verb|glp_erase_prob|. The parameter \verb|form| defines which LP formulation should be used: \verb|GLP_ASN_MIN| --- perfect matching (15)---(18), minimization; \verb|GLP_ASN_MAX| --- perfect matching (15)---(18), maximization; \verb|GLP_ASN_MMP| --- maximum weighted matching (11)---(14). The parameter \verb|G| is the graph program object, which specifies the assignment problem instance. The parameter \verb|names| is a flag. If it is \verb|GLP_ON|, the routine uses symbolic names of the graph object components to assign symbolic names to the LP problem object components. If the \verb|flag| is \verb|GLP_OFF|, no symbolic names are assigned. The parameter \verb|v_set| specifies an offset of the field of type \verb|int| in the vertex data block, which contains the node set indicator: 0 --- the node is in set $R$; 1 --- the node is in set $S$. \noindent If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs is in set $R$, and a node having no outgoing arcs is in set $S$. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, which contains $c_{ij}$, the edge cost. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ for all edges. \newpage \returns If the LP problem has been successfully built, the routine \verb|glp_asnprob_lp| returns zero, otherwise, non-zero (see the routine \verb|glp_check_asnprob|). \para{Example} The example program below reads the assignment problem instance in DIMACS format from file `\verb|sample.asn|', converts the instance to LP (11)---(14), and writes the resultant LP in CPLEX format to file `\verb|matching.lp|'. \begin{footnotesize} \begin{verbatim} #include #include typedef struct { int set; } v_data; typedef struct { double cost; } a_data; int main(void) { glp_graph *G; glp_prob *P; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); glp_read_asnprob(G, offsetof(v_data, set), offsetof(a_data, cost), "sample.asn"); P = glp_create_prob(); glp_asnprob_lp(P, GLP_ASN_MMP, G, GLP_ON, offsetof(v_data, set), offsetof(a_data, cost)); glp_delete_graph(G); glp_write_lp(P, NULL, "matching.lp"); glp_delete_prob(P); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.asn|' is the example data file from the subsection describing \verb|glp_read_asnprob|, file `\verb|matching.lp|' may look like follows: \begin{footnotesize} \begin{verbatim} Maximize obj: + 20 x(1,12) + 21 x(1,10) + 13 x(1,9) + 26 x(2,13) + 8 x(2,12) + 12 x(2,10) + 11 x(3,13) + 22 x(3,11) + 25 x(4,14) + 36 x(4,12) + 12 x(4,9) + 32 x(5,17) + 35 x(5,16) + 8 x(5,15) + 4 x(5,14) + 11 x(5,13) + 40 x(5,12) + 41 x(5,11) + 13 x(6,9) + 19 x(7,10) + 15 x(8,11) + 39 x(8,10) Subject To r_1: + x(1,9) + x(1,10) + x(1,12) <= 1 r_2: + x(2,10) + x(2,12) + x(2,13) <= 1 r_3: + x(3,11) + x(3,13) <= 1 r_4: + x(4,9) + x(4,12) + x(4,14) <= 1 r_5: + x(5,11) + x(5,12) + x(5,13) + x(5,14) + x(5,15) + x(5,16) + x(5,17) <= 1 r_6: + x(6,9) <= 1 r_7: + x(7,10) <= 1 r_8: + x(8,10) + x(8,11) <= 1 r_9: + x(6,9) + x(4,9) + x(1,9) <= 1 r_10: + x(8,10) + x(7,10) + x(2,10) + x(1,10) <= 1 r_11: + x(8,11) + x(5,11) + x(3,11) <= 1 r_12: + x(5,12) + x(4,12) + x(2,12) + x(1,12) <= 1 r_13: + x(5,13) + x(3,13) + x(2,13) <= 1 r_14: + x(5,14) + x(4,14) <= 1 r_15: + x(5,15) <= 1 r_16: + x(5,16) <= 1 r_17: + x(5,17) <= 1 Bounds 0 <= x(1,12) <= 1 0 <= x(1,10) <= 1 0 <= x(1,9) <= 1 0 <= x(2,13) <= 1 0 <= x(2,12) <= 1 0 <= x(2,10) <= 1 0 <= x(3,13) <= 1 0 <= x(3,11) <= 1 0 <= x(4,14) <= 1 0 <= x(4,12) <= 1 0 <= x(4,9) <= 1 0 <= x(5,17) <= 1 0 <= x(5,16) <= 1 0 <= x(5,15) <= 1 0 <= x(5,14) <= 1 0 <= x(5,13) <= 1 0 <= x(5,12) <= 1 0 <= x(5,11) <= 1 0 <= x(6,9) <= 1 0 <= x(7,10) <= 1 0 <= x(8,11) <= 1 0 <= x(8,10) <= 1 End \end{verbatim} \end{footnotesize} \subsection{glp\_asnprob\_okalg --- solve assignment problem with out-of-kilter\\algorithm} \synopsis \begin{verbatim} int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, double *sol, int a_x); \end{verbatim} \description The routine \verb|glp_mincost_okalg| finds optimal solution to the assignment problem with the out-of-kilter algorithm.\footnote{GLPK implementation of the out-of-kilter algorithm is based on the following book: L.~R.~Ford,~Jr., and D.~R.~Fulkerson, ``Flows in Networks,'' The RAND Corp., Report R-375-PR (August 1962), Chap. III ``Minimal Cost Flow Problems,'' pp.~113-26.} Note that this routine requires all the problem data to be integer-valued. The parameter \verb|form| defines which LP formulation should be used: \verb|GLP_ASN_MIN| --- perfect matching (15)---(18), minimization; \verb|GLP_ASN_MAX| --- perfect matching (15)---(18), maximization; \verb|GLP_ASN_MMP| --- maximum weighted matching (11)---(14). \newpage The parameter \verb|G| is the graph program object, which specifies the assignment problem instance. The parameter \verb|v_set| specifies an offset of the field of type \verb|int| in the vertex data block, which contains the node set indicator: 0 --- the node is in set $R$; 1 --- the node is in set $S$. \noindent If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs is in set $R$, and a node having no outgoing arcs is in set $S$. The parameter \verb|a_cost| specifies an offset of the field of type \verb|double| in the arc data block, which contains $c_{ij}$, the edge cost. This value must be integer in the range [\verb|-INT_MAX|, \verb|+INT_MAX|]. If \verb|a_cost| $<0$, it is assumed that $c_{ij}=1$ for all edges. The parameter \verb|sol| specifies a location, to which the routine stores the objective value (that is, the total cost) found. If \verb|sol| is \verb|NULL|, the objective value is not stored. The parameter \verb|a_x| specifies an offset of the field of type \verb|int| in the arc data block, to which the routine stores $x_{ij}$. If \verb|a_x| $<0$, this value is not stored. \returns \begin{retlist} 0 & Optimal solution found.\\ \verb|GLP_ENOPFS| & No (primal) feasible solution exists.\\ \verb|GLP_EDATA| & Unable to start the search, because the assignment problem data are either incorrect (this error is detected by the routine \verb|glp_check_asnprob|), not integer-valued or out of range.\\ \verb|GLP_ERANGE| & The search was prematurely terminated because of integer overflow.\\ \verb|GLP_EFAIL| & An error has been detected in the program logic. (If this code is returned for your problem instance, please report to \verb||.)\\ \end{retlist} \para{Comments} Since the out-of-kilter algorithm is designed to find a minimal cost circulation, the routine \verb|glp_asnprob_okalg| converts the original graph to a network suitable for this algorithm in the following way:\footnote{The conversion is performed internally and does not change the original graph program object passed to the routine.} 1) it replaces each edge $(i,j)$ by arc $(i\rightarrow j)$, flow $x_{ij}$ through which has zero lower bound ($l_{ij}=0$), unity upper bound ($u_{ij}=1$), and per-unit cost $+c_{ij}$ (in case of \verb|GLP_ASN_MIN|), or $-c_{ij}$ (in case of \verb|GLP_ASN_MAX| and \verb|GLP_ASN_MMP|); 2) then it adds one auxiliary feedback node $k$; 3) for each original node $i\in R$ the routine adds auxiliary supply arc $(k\rightarrow i)$, flow $x_{ki}$ through which is costless ($c_{ki}=0$) and either fixed at 1 ($l_{ki}=u_{ki}=1$, in case of \verb|GLP_ASN_MIN| and \verb|GLP_ASN_MAX|) or has zero lower bound and unity upper bound ($l_{ij}=0$, $u_{ij}=1$, in case of \verb|GLP_ASN_MMP|); \newpage 4) similarly, for each original node $j\in S$ the routine adds auxiliary demand arc $(j\rightarrow k)$, flow $x_{jk}$ through which is costless ($c_{jk}=0$) and either fixed at 1 ($l_{jk}=u_{jk}=1$, in case of \verb|GLP_ASN_MIN| and \verb|GLP_ASN_MAX|) or has zero lower bound and unity upper bound ($l_{jk}=0$, $u_{jk}=1$, in case of \verb|GLP_ASN_MMP|). \para{Example} The example program shown below reads the assignment problem instance in DIMACS format from file `\verb|sample.asn|', solves it by using the routine \verb|glp_asnprob_okalg|, and writes the solution found to the standard output. \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { int set; } v_data; typedef struct { double cost; int x; } e_data; #define node(v) ((v_data *)((v)->data)) #define edge(e) ((e_data *)((e)->data)) int main(void) { glp_graph *G; glp_vertex *v; glp_arc *e; int i, ret; double sol; G = glp_create_graph(sizeof(v_data), sizeof(e_data)); glp_read_asnprob(G, offsetof(v_data, set), offsetof(e_data, cost), "sample.asn"); ret = glp_asnprob_okalg(GLP_ASN_MMP, G, offsetof(v_data, set), offsetof(e_data, cost), &sol, offsetof(e_data, x)); printf("ret = %d; sol = %5g\n", ret, sol); for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (e = v->out; e != NULL; e = e->t_next) printf("edge %2d %2d: x = %d; c = %g\n", e->tail->i, e->head->i, edge(e)->x, edge(e)->cost); } glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.asn|' is the example data file from the subsection describing \verb|glp_read_asnprob|, the output may look like follows: \begin{footnotesize} \begin{verbatim} Reading assignment problem data from `sample.asn'... Assignment problem has 8 + 9 = 17 nodes and 22 arcs 38 lines were read ret = 0; sol = 180 edge 1 12: x = 1; c = 20 edge 1 10: x = 0; c = 21 edge 1 9: x = 0; c = 13 edge 2 13: x = 1; c = 26 edge 2 12: x = 0; c = 8 edge 2 10: x = 0; c = 12 edge 3 13: x = 0; c = 11 edge 3 11: x = 1; c = 22 edge 4 14: x = 1; c = 25 edge 4 12: x = 0; c = 36 edge 4 9: x = 0; c = 12 edge 5 17: x = 0; c = 32 edge 5 16: x = 1; c = 35 edge 5 15: x = 0; c = 8 edge 5 14: x = 0; c = 4 edge 5 13: x = 0; c = 11 edge 5 12: x = 0; c = 40 edge 5 11: x = 0; c = 41 edge 6 9: x = 1; c = 13 edge 7 10: x = 0; c = 19 edge 8 11: x = 0; c = 15 edge 8 10: x = 1; c = 39 \end{verbatim} \end{footnotesize} \subsection{glp\_asnprob\_hall --- find bipartite matching of maximum cardinality} \synopsis \begin{verbatim} int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); \end{verbatim} \description The routine \verb|glp_asnprob_hall| finds a matching of maximal cardinality in the specified bipartite graph. It uses a version of the Fortran routine \verb|MC21A| developed by I.~S.~Duff\footnote{I.~S.~Duff, Algorithm 575: Permutations for zero-free diagonal, ACM Trans. on Math. Softw. 7 (1981),\linebreak pp.~387-390.}, which implements Hall's algorithm.\footnote{M.~Hall, ``An Algorithm for Distinct Representatives,'' Am. Math. Monthly 63 (1956), pp.~716-717.} The parameter \verb|G| is a pointer to the graph program object. The parameter \verb|v_set| specifies an offset of the field of type \verb|int| in the vertex data block, which contains the node set indicator: 0 --- the node is in set $R$; 1 --- the node is in set $S$. \noindent If \verb|v_set| $<0$, it is assumed that a node having no incoming arcs is in set $R$, and a node having no outgoing arcs is in set $S$. The parameter \verb|a_x| specifies an offset of the field of type \verb|int| in the arc data block, to which the routine stores $x_{ij}$. If \verb|a_x| $<0$, this value is not stored. \returns The routine \verb|glp_asnprob_hall| returns the cardinality of the matching found. However, if the specified graph is incorrect (as detected by the routine \verb|glp_check_asnprob|), this routine returns a negative value. \newpage \para{Comments} The same solution may be obtained with the routine \verb|glp_asnprob_okalg| (for LP formulation \verb|GLP_ASN_MMP| and all edge costs equal to 1). However, the routine \verb|glp_asnprob_hall| is much faster. \para{Example} The example program shown below reads the assignment problem instance in DIMACS format from file `\verb|sample.asn|', finds a bipartite matching of maximal cardinality by using the routine \verb|glp_asnprob_hall|, and writes the solution found to the standard output. \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { int set; } v_data; typedef struct { int x; } e_data; #define node(v) ((v_data *)((v)->data)) #define edge(e) ((e_data *)((e)->data)) int main(void) { glp_graph *G; glp_vertex *v; glp_arc *e; int i, card; G = glp_create_graph(sizeof(v_data), sizeof(e_data)); glp_read_asnprob(G, offsetof(v_data, set), -1, "sample.asn"); card = glp_asnprob_hall(G, offsetof(v_data, set), offsetof(e_data, x)); printf("card = %d\n", card); for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (e = v->out; e != NULL; e = e->t_next) printf("edge %2d %2d: x = %d\n", e->tail->i, e->head->i, edge(e)->x); } glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} If `\verb|sample.asn|' is the example data file from the subsection describing \verb|glp_read_asnprob|, the output may look like follows: \begin{footnotesize} \begin{verbatim} Reading assignment problem data from `sample.asn'... Assignment problem has 8 + 9 = 17 nodes and 22 arcs 38 lines were read card = 7 edge 1 12: x = 1 edge 1 10: x = 0 edge 1 9: x = 0 edge 2 13: x = 1 edge 2 12: x = 0 edge 2 10: x = 0 edge 3 13: x = 0 edge 3 11: x = 1 edge 4 14: x = 1 edge 4 12: x = 0 edge 4 9: x = 0 edge 5 17: x = 1 edge 5 16: x = 0 edge 5 15: x = 0 edge 5 14: x = 0 edge 5 13: x = 0 edge 5 12: x = 0 edge 5 11: x = 0 edge 6 9: x = 1 edge 7 10: x = 1 edge 8 11: x = 0 edge 8 10: x = 0 \end{verbatim} \end{footnotesize} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \newpage \section{Critical path problem} \subsection{Background} The {\it critical path problem} (CPP) is stated as follows. Let there be given a project $J$, which is a set of jobs (tasks, activities, etc.). Performing each job $i\in J$ requires time $t_i\geq 0$. Besides, over the set $J$ there is given a precedence relation $R\subseteq J\times J$, where $(i,j)\in R$ means that job $i$ immediately precedes job $j$, i.e. performing job $j$ cannot start until job $i$ has been completely performed. The problem is to find starting times $x_i$ for each job $i\in J$, which satisfy to the precedence relation and minimize the total duration (makespan) of the project. The following is an example of the critical path problem: \bigskip \begin{center} \begin{tabular}{|c|l|c|c|} \hline Job&Desription&Time&Predecessors\\ \hline A&Excavate&3&---\\ B&Lay foundation&4&A\\ C&Rough plumbing&3&B\\ D&Frame&10&B\\ E&Finish exterior&8&D\\ F&Install HVAC&4&D\\ G&Rough electric&6&D\\ H&Sheet rock&8&C, E, F, G\\ I&Install cabinets&5&H\\ J&Paint&5&H\\ K&Final plumbing&4&I\\ L&Final electric&2&J\\ M&Install flooring&4&K, L\\ \hline \end{tabular} \end{center} \bigskip Obviously, the project along with the precedence relation can be represented as a directed graph $G=(J,R)$ called {\it project network}, where each node $i\in J$ corresponds to a job, and arc $(i\rightarrow j)\in R$ means that job $i$ immediately precedes job $j$.\footnote{There exists another network representation of the critical path problem, where jobs correspond to arcs while nodes correspond to events introduced to express the precedence relation. That representation, however, is much less convenient than the one, where jobs are represented as nodes of the network.} The project network for the example above is shown on Fig.~4. May note that the project network must be acyclic; otherwise, it would be impossible to satisfy to the precedence relation for any job that belongs to a cycle. \newpage \hspace*{.5in} \xymatrix {&&&C|3\ar[rd]&&I|5\ar[r]&K|4\ar[rd]&\\ A|3\ar[r]&B|4\ar[rru]\ar[rd]&&E|8\ar[r]&H|8\ar[ru]\ar[rd]&&&M|4\\ &&D|10\ar[ru]\ar[r]\ar[rd]&F|4\ar[ru]&&J|5\ar[r]&L|2\ar[ru]&\\ &&&G|6\ar[ruu]&&&&\\ } \medskip \noindent\hfil Fig.~4. An example of the project network. \medskip The critical path problem can be naturally formulated as the following LP problem: \medskip \noindent \hspace{.5in}minimize $$z\eqno(19)$$ \hspace{.5in}subject to $$x_i+t_i\leq z\ \ \ \hbox{for all}\ i\in J\ \ \ \ \eqno(20)$$ $$x_i+t_i\leq x_j\ \ \ \hbox{for all}\ (i,j)\in R\eqno(21)$$ $$x_i\geq 0\ \ \ \ \ \ \ \hbox{for all}\ i\in J\ \ \eqno(22)$$ The inequality constraints (21), which are active in the optimal solution, define so called {\it critical path} having the following property: the minimal project duration $z$ can be decreased only by decreasing the times $t_j$ for jobs on the critical path, and delaying any critical job delays the entire project. \subsection{glp\_cpp --- solve critical path problem} \synopsis \begin{verbatim} double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); \end{verbatim} \description The routine \verb|glp_cpp| solves the critical path problem represented in the form of the project network. The parameter \verb|G| is a pointer to the graph object, which specifies the project network. This graph must be acyclic. Multiple arcs are allowed being considered as single arcs. The parameter \verb|v_t| specifies an offset of the field of type \verb|double| in the vertex data block, which contains time $t_i\geq 0$ needed to perform corresponding job $j\in J$. If \verb|v_t| $<0$, it is assumed that $t_i=1$ for all jobs. The parameter \verb|v_es| specifies an offset of the field of type \verb|double| in the vertex data block, to which the routine stores the {\it earliest start time} for corresponding job. If \verb|v_es| $<0$, this time is not stored. \newpage The parameter \verb|v_ls| specifies an offset of the field of type \verb|double| in the vertex data block, to which the routine stores the {\it latest start time} for corresponding job. If \verb|v_ls| $<0$, this time is not stored. The difference between the latest and earliest start times of some job is called its {\it time reserve}. Delaying a job within its time reserve does not affect the project duration, so if the time reserve is zero, the corresponding job is critical. \para{Returns} The routine \verb|glp_cpp| returns the minimal project duration, i.e. minimal time needed to perform all jobs in the project. \para{Example} The example program below solves the critical path problem shown on Fig.~4 by using the routine \verb|glp_cpp| and writes the solution found on the standard output. \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { double t, es, ls; } v_data; #define node(v) ((v_data *)((v)->data)) int main(void) { glp_graph *G; int i; double t, es, ef, ls, lf, total; G = glp_create_graph(sizeof(v_data), 0); glp_add_vertices(G, 13); node(G->v[1])->t = 3; /* A: Excavate */ node(G->v[2])->t = 4; /* B: Lay foundation */ node(G->v[3])->t = 3; /* C: Rough plumbing */ node(G->v[4])->t = 10; /* D: Frame */ node(G->v[5])->t = 8; /* E: Finish exterior */ node(G->v[6])->t = 4; /* F: Install HVAC */ node(G->v[7])->t = 6; /* G: Rough elecrtic */ node(G->v[8])->t = 8; /* H: Sheet rock */ node(G->v[9])->t = 5; /* I: Install cabinets */ node(G->v[10])->t = 5; /* J: Paint */ node(G->v[11])->t = 4; /* K: Final plumbing */ node(G->v[12])->t = 2; /* L: Final electric */ node(G->v[13])->t = 4; /* M: Install flooring */ glp_add_arc(G, 1, 2); /* A precedes B */ glp_add_arc(G, 2, 3); /* B precedes C */ glp_add_arc(G, 2, 4); /* B precedes D */ glp_add_arc(G, 4, 5); /* D precedes E */ glp_add_arc(G, 4, 6); /* D precedes F */ glp_add_arc(G, 4, 7); /* D precedes G */ glp_add_arc(G, 3, 8); /* C precedes H */ glp_add_arc(G, 5, 8); /* E precedes H */ glp_add_arc(G, 6, 8); /* F precedes H */ glp_add_arc(G, 7, 8); /* G precedes H */ glp_add_arc(G, 8, 9); /* H precedes I */ glp_add_arc(G, 8, 10); /* H precedes J */ glp_add_arc(G, 9, 11); /* I precedes K */ glp_add_arc(G, 10, 12); /* J precedes L */ glp_add_arc(G, 11, 13); /* K precedes M */ glp_add_arc(G, 12, 13); /* L precedes M */ total = glp_cpp(G, offsetof(v_data, t), offsetof(v_data, es), offsetof(v_data, ls)); printf("Minimal project duration is %.2f\n\n", total); printf("Job Time ES EF LS LF\n"); printf("--- ------ ------ ------ ------ ------\n"); for (i = 1; i <= G->nv; i++) { t = node(G->v[i])->t; es = node(G->v[i])->es; ef = es + node(G->v[i])->t; ls = node(G->v[i])->ls; lf = ls + node(G->v[i])->t; printf("%3d %6.2f %s %6.2f %6.2f %6.2f %6.2f\n", i, t, ls - es < 0.001 ? "*" : " ", es, ef, ls, lf); } glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} The output from the example program shown below includes job number, the time needed to perform a job, earliest start time (\verb|ES|), earliest finish time (\verb|EF|), latest start time (\verb|LS|), and latest finish time (\verb|LF|) for each job in the project. Critical jobs are marked by asterisks. \begin{footnotesize} \begin{verbatim} Minimal project duration is 46.00 Job Time ES EF LS LF --- ------ ------ ------ ------ ------ 1 3.00 * 0.00 3.00 0.00 3.00 2 4.00 * 3.00 7.00 3.00 7.00 3 3.00 7.00 10.00 22.00 25.00 4 10.00 * 7.00 17.00 7.00 17.00 5 8.00 * 17.00 25.00 17.00 25.00 6 4.00 17.00 21.00 21.00 25.00 7 6.00 17.00 23.00 19.00 25.00 8 8.00 * 25.00 33.00 25.00 33.00 9 5.00 * 33.00 38.00 33.00 38.00 10 5.00 33.00 38.00 35.00 40.00 11 4.00 * 38.00 42.00 38.00 42.00 12 2.00 38.00 40.00 40.00 42.00 13 4.00 * 42.00 46.00 42.00 46.00 \end{verbatim} \end{footnotesize} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \chapter{Graph Optimization API Routines} \section{Maximum clique problem} \subsection{Background} The {\it maximum clique problem (MCP)} is a classic combinatorial optimization problem. Given an undirected graph $G=(V,E)$, where $V$ is a set of vertices, and $E$ is a set of edges, this problem is to find the largest {\it clique} $C\subseteq G$, i.e. the largest induced complete subgraph. A generalization of this problem is the {\it maximum weight clique problem (MWCP)}, which is to find a clique $C\subseteq G$ of the largest weight $\displaystyle\sum_{v\in C}w(v)\rightarrow\max$, where $w(v)$ is a weight of vertex $v\in V$. An example of the maximum weight clique problem is shown on Fig.~5. \begin{figure} \noindent\hfil \begin{tabular}{c} {\xymatrix %@C=16pt {&&&{v_1}\ar@{-}[lllddd]\ar@{-}[llddddd]\ar@{-}[dddddd] \ar@{-}[rrrddd]&&&\\ &{v_2}\ar@{-}[rrrr]\ar@{-}[rrrrdddd]\ar@{-}[rrddddd]\ar@{-}[dddd]&&&& {v_3}\ar@{-}[llllldd]\ar@{-}[lllldddd]\ar@{-}[dddd]&\\ &&&&&&\\ {v_4}\ar@{-}[rrrrrr]\ar@{-}[rrrddd]&&&&&&{v_5}\ar@{-}[lllddd] \ar@{-}[ldd]\\ &&&&&&\\ &{v_6}\ar@{-}[rrrr]&&&&{v_7}&\\ &&&{v_8}&&&\\ }} \end{tabular} \begin{tabular}{r@{\ }c@{\ }l} $w(v_1)$&=&3\\$w(v_2)$&=&4\\$w(v_3)$&=&8\\$w(v_4)$&=&1\\ $w(v_5)$&=&5\\$w(v_6)$&=&2\\$w(v_7)$&=&1\\$w(v_8)$&=&3\\ \end{tabular} \bigskip \begin{center} Fig.~5. An example of the maximum weight clique problem. \end{center} \end{figure} \subsection{glp\_wclique\_exact --- find maximum weight clique with exact algorithm} \synopsis \begin{verbatim} int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set); \end{verbatim} \description The routine {\tt glp\_wclique\_exact} finds a maximum weight clique in the specified undirected graph with the exact algorithm developed by Patric \"Osterg{\aa}rd.\footnote{P.~R.~J.~\"Osterg{\aa}rd, A new algorithm for the maximum-weight clique problem, Nordic J. of Computing, Vol.~8, No.~4, 2001, pp.~424--36.} The parameter {\tt G} is the program object, which specifies an undirected graph. Each arc $(x\rightarrow y)$ in {\tt G} is considered as edge $(x,y)$, self-loops are ignored, and multiple edges, if present, are replaced (internally) by simple edges. The parameter {\tt v\_wgt} specifies an offset of the field of type {\tt double} in the vertex data block, which contains a weight of corresponding vertex. Vertex weights must be integer-valued in the range $[0,$ {\tt INT\_MAX}$]$. If {\tt v\_wgt} $<0$, it is assumed that all vertices of the graph have the weight 1. \newpage The parameter {\tt sol} specifies a location, to which the routine stores the weight of the clique found (the clique weight is the sum of weights of all vertices included in the clique.) If {\tt sol} is {\tt NULL}, the solution is not stored. The parameter {\tt v\_set} specifies an offset of the field of type {\tt int} in the vertex data block, to which the routines stores a vertex flag: 1 means that the corresponding vertex is included in the clique found, and 0 otherwise. If {\tt v\_set} $<0$, vertex flags are not stored. \returns \begin{retlist} 0 & Optimal solution found.\\ \verb|GLP_EDATA| & Unable to start the search, because some vertex weights are either not integer-valued or out of range. This code is also returned if the sum of weights of all vertices exceeds {\tt INT\_MAX}. \\ \end{retlist} \para{Notes} 1. The routine {\it glp\_wclique\_exact} finds exact solution. Since both MCP and MWCP problems are NP-complete, the algorithm may require exponential time in worst cases. 2. Internally the specified graph is converted to an adjacency matrix in {\it dense} format. This requires about $|V|^2/16$ bytes of memory, where $|V|$ is the number of vertices in the graph. \para{Example} The example program shown below reads a MWCP instance in DIMACS clique/coloring format from file `\verb|sample.clq|', finds the clique of largest weight, and writes the solution found on the standard output. \newpage \begin{footnotesize} \begin{verbatim} #include #include #include #include typedef struct { double wgt; int set; } v_data; #define vertex(v) ((v_data *)((v)->data)) int main(void) { glp_graph *G; glp_vertex *v; int i, ret; double sol; G = glp_create_graph(sizeof(v_data), 0); glp_read_ccdata(G, offsetof(v_data, wgt), "sample.clq"); ret = glp_wclique_exact(G, offsetof(v_data, wgt), &sol, offsetof(v_data, set)); printf("ret = %d; sol = %g\n", ret, sol); for (i = 1; i <= G->nv; i++) { v = G->v[i]; printf("vertex %d: weight = %g, flag = %d\n", i, vertex(v)->wgt, vertex(v)->set); } glp_delete_graph(G); return 0; } \end{verbatim} \end{footnotesize} For the example shown on Fig.~5 the data file may look like follows: \begin{footnotesize} \begin{verbatim} c sample.clq c c This is an example of the maximum weight clique c problem in DIMACS clique/coloring format. c p edge 8 16 n 1 3 n 2 4 n 3 8 n 5 5 n 6 2 n 8 3 e 1 4 e 1 5 e 1 6 e 1 8 e 2 3 e 2 6 e 2 7 e 2 8 e 3 4 e 3 6 e 3 7 e 4 5 e 4 8 e 5 7 e 5 8 e 6 7 c c eof \end{verbatim} \end{footnotesize} The corresponding output from the example program is the following: \begin{footnotesize} \begin{verbatim} Reading graph from `sample.clq'... Graph has 8 vertices and 16 edges 28 lines were read ret = 0; sol = 15 vertex 1: weight = 3, flag = 0 vertex 2: weight = 4, flag = 1 vertex 3: weight = 8, flag = 1 vertex 4: weight = 1, flag = 0 vertex 5: weight = 5, flag = 0 vertex 6: weight = 2, flag = 1 vertex 7: weight = 1, flag = 1 vertex 8: weight = 3, flag = 0 \end{verbatim} \end{footnotesize} \end{document} glpk-4.52.1/doc/miplib2.txt0000644000062000006210000002057212175147600014573 0ustar maomkpasswdSolver: GLPSOL 4.40 (options used: --pcost) Computer: Intel Pentium 4, 3.0 GHz Platform: Cygwin 1.5.25 Compiler: GCC 3.4.4 (options used: -O3) Test set: MIPLIB 2.0 Problem Optimal Solution Cuts Used Nodes Iters Time,s Mem,MB -------- ---------------- --------- -------- ------ ------ ------ air01 +6.796000000e+03 3 41 < 1 1.2 air02 +7.810000000e+03 43 201 6 13.8 air03 +3.401600000e+05 33 414 12 21.0 air04 +5.613700000e+04 1901 109800 396 32.4 air05 +2.637400000e+04 6445 201649 452 45.0 air06 +4.964900000e+04 11 6868 31 18.1 bell3a +8.784303160e+05 --gomory 7965 42363 17 6.1 bell3b +1.178616062e+07 --gomory 6031 30467 19 3.2 bell4 +1.854148420e+07 --gomory 7203 25019 16 2.9 bell5 +8.966406492e+06 --gomory 5605 18555 8 1.5 bm23 +3.400000000e+01 373 878 < 1 0.2 cracpb1 +2.219900000e+04 47 5258 2 1.3 dcmulti +1.881820000e+05 743 3366 2 1.1 diamond infeasible 3 4 < 1 0.1 dsbmip -3.051981750e+02 --mir 217 46088 24 4.5 egout +5.681007000e+02 91 137 < 1 0.3 enigma +0.000000000e+00 16419 55071 6 3.2 fixnet3 +5.197300000e+04 81 380 < 1 1.4 fixnet4 +8.936000000e+03 211 1095 1 1.4 fixnet6 +3.983000000e+03 1031 3136 2 1.7 flugpl +1.201500000e+06 397 231 < 1 0.1 gen +1.123133627e+05 195 3991 1 1.7 khb05250 +1.069402260e+08 2163 14498 5 2.8 l152lav +4.722000000e+03 7419 95299 68 12.0 lp4l +2.967000000e+03 173 1331 2 1.7 lseu +1.120000000e+03 10821 31954 5 2.5 misc01 +5.635000000e+02 769 4593 1 0.5 misc02 +1.690000000e+03 29 282 < 1 0.2 misc03 +3.360000000e+03 957 6742 2 1.1 misc04 +2.666699247e+03 17 2052 1 7.0 misc05 +2.984500000e+03 293 2520 1 1.1 misc06 +1.285086074e+04 57 941 < 1 2.7 misc07 +2.810000000e+03 --mir 66075 579129 424 33.4 mod008 +3.070000000e+02 8185 24245 8 2.3 mod010 +6.548000000e+03 315 6283 7 5.3 mod011 mod013 +2.809500000e+02 545 1155 < 1 0.3 modglob +2.074050809e+07 --mir 5197 31985 20 2.8 noswot p0033 +3.089000000e+03 305 955 < 1 0.2 p0040 +6.202700000e+04 17 66 < 1 0.1 p0201 +7.615000000e+03 521 3660 1 0.9 p0282 +2.584110000e+05 623 1204 1 0.8 p0291 +5.223749000e+03 71 154 < 1 0.7 p0548 +8.691000000e+03 7617 23556 9 2.9 p2756 +3.124000000e+03 --mir 3911 15157 57 10.9 p6000 -2.451377000e+06 19209 40906 570 15.8 pipex +7.882630000e+02 1569 2469 < 1 0.4 qiu -1.328731369e+02 80473 1918742 1174 69.2 rentacar +3.035676098e+07 43 1649 3 12.1 rgn +8.219999924e+01 3325 18700 2 1.2 sample2 +3.750000000e+02 163 347 < 1 0.2 sentoy -7.772000000e+03 335 723 < 1 0.4 set1al +1.586975000e+04 --mir 17 532 < 1 1.5 set1ch set1cl +6.484250000e+03 --mir 1 502 < 1 1.1 stein15 +9.000000000e+00 87 375 < 1 0.2 stein27 +1.800000000e+01 3255 15327 2 1.0 stein45 +3.000000000e+01 52301 389140 139 19.2 stein9 +5.000000000e+00 17 45 < 1 0.1 vpm1 +2.000000000e+01 --mir 9 836 < 1 0.9 PROBLEM CHARACTERISTICS Problem Rows Cols ( Int 0/1) Nonz Best Solution -------- ------ ---------------------- ------ -------------------------- air01 24 771 ( all all) 4986 6796 (opt) air02 51 6774 ( all all) 68329 7810 (opt) air03 125 10757 ( all all) 101785 340160 (opt) air04 824 8904 ( all all) 81869 56138 (opt) air05 427 7195 ( all all) 59316 26402 (not opt) air06 826 8627 ( all all) 79433 49649 (opt) bell3a 124 133 ( 71 39) 441 878430.32 (opt) bell3b 124 133 ( 71 39) 441 11786160.62 (opt) bell4 106 117 ( 64 34) 385 18541484.20 (opt) bell5 92 104 ( 58 30) 340 8966406.49 (opt) bm23 21 27 ( all all) 505 34 (opt) cracpb1 144 572 ( all all) 4730 22199 (opt) dcmulti 291 548 ( 75 all) 1833 188182.0000 (opt) diamond 5 2 ( all all) 9 integer infeasible dsbmip 1855 1886 ( 192 160) 9768 -305.198 (opt) egout 99 141 ( 55 all) 392 568.101 (opt) enigma 22 100 ( all all) 298 0.0 (opt) fixnet3 479 878 ( 378 all) 2631 51973 (opt) fixnet4 479 878 ( 378 all) 2621 8936 (opt) fixnet6 479 878 ( 378 all) 2550 3983 (opt) flugpl 19 18 ( 11 none) 64 1201500 (opt) gen 781 870 ( 150 144) 3174 112313 (opt) khb05250 102 1350 ( 24 all) 3973 106940226 (opt) l152lav 98 1989 ( all all) 11911 4750 (not opt) lp4l 86 1086 ( all all) 5763 2967 (opt) lseu 29 89 ( all all) 394 1120 (opt) misc01 55 83 ( 82 all) 746 563.5 (opt) misc02 40 59 ( 58 all) 414 1690 (opt) misc03 97 160 ( 159 all) 2054 3360 (opt) misc04 1726 4897 ( 30 all) 17253 2666.699 (opt) misc05 301 136 ( 74 all) 2946 2984.5 (opt) misc06 821 1808 ( 112 all) 5860 12850.8607 (opt) misc07 213 260 ( 259 all) 8620 2810 (not opt) mod008 7 319 ( all all) 1562 307 (opt) mod010 147 2655 ( all all) 13858 6548 (opt) mod011 4482 10958 ( 96 all) 37425 -54558535 (opt) mod013 63 96 ( 48 all) 288 280.95 (opt) modglob 292 422 ( 98 all) 1390 20740508 (opt) noswot 183 128 ( 100 75) 760 -43 (opt) p0033 17 33 ( all all) 131 3089 (opt) p0040 24 40 ( all all) 150 62027 (opt) p0201 134 201 ( all all) 2124 7615 (opt) p0282 242 282 ( all all) 2248 258411 (opt) p0291 253 291 ( all all) 349 5223.7490 (opt) p0548 177 548 ( all all) 2127 8691 (opt) p2756 756 2756 ( all all) 11103 3124 (opt) p6000 2177 6000 ( all all) 54238 -2451377 (opt) pipex 26 48 ( all all) 240 788.263 (opt) qiu 1193 840 ( 48 all) 3432 -132.873137 (opt) rentacar 6804 9557 ( 55 all) 42019 30356761 (opt) rgn 25 180 ( 100 all) 540 82.1999 (opt) sample2 46 67 ( 21 all) 179 375 (opt) sentoy 31 60 ( all all) 1860 -7772 (opt) set1al 493 712 ( 240 all) 1884 15869.7 (opt) set1ch 493 712 ( 240 all) 1884 54537.7 (opt) set1cl 493 712 ( 240 all) 1884 6484.25 (opt) stein15 37 15 ( all all) 135 9 (opt) stein27 119 27 ( all all) 405 18 (opt) stein45 332 45 ( all all) 1079 30 (opt) stein9 14 9 ( all all) 54 5 (opt) vpm1 235 378 ( 168 all) 917 20 (opt) glpk-4.52.1/doc/miplib3.txt0000644000062000006210000002041612175147600014571 0ustar maomkpasswdSolver: GLPSOL 4.40 Computer: Intel Pentium 4, 3.0 GHz Platform: Cygwin 1.5.25 Compiler: GCC 3.4.4 (options used: -O3) Test set: MIPLIB 3.0 Problem Optimal Solution Options Used Nodes Iters Time,s Mem,MB -------- ---------------- ---------------- -------- ------ ------ ------ 10teams +9.240000000e+02 --pcost --gomory 6013 349276 207 12.7 air03 +3.401600000e+05 --pcost 33 414 12 21.0 air04 +5.613700000e+04 --pcost 1901 109800 396 32.4 air05 +2.637400000e+04 --pcost 6445 201649 452 45.0 arki001 bell3a +8.784303160e+05 --pcost --gomory 7965 42363 17 6.1 bell5 +8.966406492e+06 --pcost --gomory 5605 18555 8 1.5 blend2 +7.598985000e+00 --pcost 7185 24256 7 2.1 cap6000 -2.451377000e+06 --pcost 19209 40906 569 15.8 dano3mip danoint dcmulti +1.881820000e+05 --pcost 743 3366 2 1.1 dsbmip -3.051981750e+02 --pcost --mir 217 46088 24 4.5 egout +5.681007000e+02 --pcost 91 137 < 1 0.3 enigma +0.000000000e+00 --pcost 16419 55071 6 3.2 fast0507 fiber +4.059351800e+05 --pcost --mir 407 3108 4 2.4 fixnet6 +3.983000000e+03 --pcost 1031 3136 2 1.7 flugpl +1.201500000e+06 --pcost 397 231 < 1 0.1 gen +1.123133627e+05 --pcost 195 3991 1 1.7 gesa2 +2.577985637e+07 --pcost --mir 59 2723 4 4.1 gesa2_o +2.577985637e+07 --pcost --mir 69 2588 5 3.7 gesa3 +2.799104265e+07 --pcost --mir 93 2774 5 3.7 gesa3_o +2.799104265e+07 --pcost --mir 117 3271 6 3.6 gt2 +2.116600000e+04 --pcost 5613 26115 2 1.2 harp2 khb05250 +1.069402260e+08 --pcost 2163 14498 5 2.8 l152lav +4.722000000e+03 --pcost 7419 95299 68 12.0 lseu +1.120000000e+03 --pcost 10821 31954 5 2.5 marksh1 marksh2 mas74 mas76 misc03 +3.360000000e+03 --pcost 957 6742 2 1.1 misc06 +1.285086074e+04 --pcost 57 941 < 1 2.7 misc07 +2.810000000e+03 --pcost --mir 66075 579129 424 33.4 mitre mkc mod008 +3.070000000e+02 --pcost 8185 24245 8 2.3 mod010 +6.548000000e+03 --pcost 315 6283 7 5.3 mod011 modglob +2.074050809e+07 --pcost --mir 5197 31985 20 2.8 noswot nw04 +1.686200000e+04 (none) 361 5544 345 138.3 p0033 +3.089000000e+03 --pcost 305 955 < 1 0.2 p0201 +7.615000000e+03 --pcost 521 3660 1 0.9 p0282 +2.584110000e+05 --pcost 623 1204 1 0.8 p0548 +8.691000000e+03 --pcost 7617 23556 9 2.9 p2756 +3.124000000e+03 --pcost --mir 3911 15157 57 10.9 pk1 pp08a +7.350000000e+03 --pcost --mir 663 9196 4 1.3 pp08acut +7.350000000e+03 --pcost --mir 17233 260160 154 21.1 qiu -1.328731369e+02 --pcost 80473 1918742 1174 69.2 qnet1 +1.602969268e+04 --pcost --mir 183 20352 16 3.6 qnet1_o +1.602969268e+04 --pcost --mir 75 7645 9 3.3 rentacar +3.035676098e+07 --pcost 43 1649 3 12.1 rgn +8.219999924e+01 --pcost 3325 18700 2 1.2 rout set1ch seymour stein27 +1.800000000e+01 --pcost 3255 15327 2 1.0 stein45 +3.000000000e+01 --pcost 52301 389140 139 19.2 swath vpm1 +2.000000000e+01 --pcost --mir 9 836 < 1 0.9 vpm2 +1.375000000e+01 --pcost --mir 11729 164856 91 9.2 PROBLEM CHARACTERISTICS Problem Rows Cols ( Int 0/1) Nonz Best Solution -------- ------ ---------------------- ------ -------------------------- 10teams 230 2025 ( 1800 all) 12150 924 (opt) air03 125 10757 ( all all) 101785 340160 (opt) air04 824 8904 ( all all) 81869 56138 (opt) air05 427 7195 ( all all) 59316 26402 (not opt) arki001 1048 1388 ( 538 415) 20439 7580813.0459 (not opt) bell3a 124 133 ( 71 39) 441 878430.32 (opt) bell5 92 104 ( 58 30) 340 8966406.49 (opt) blend2 274 353 ( 264 231) 1409 7.598985 (opt) cap6000 2176 6000 ( all all) 48249 -2451377 (opt) dano3mip 3202 13873 ( 552 all) 79655 728.1111 (not opt) danoint 664 521 ( 56 all) 3232 65.67 (opt) dcmulti 291 548 ( 75 all) 1833 188182.0000 (opt) dsbmip 1855 1886 ( 192 160) 9768 -305.198 (opt) egout 99 141 ( 55 all) 392 568.101 (opt) enigma 22 100 ( all all) 298 0.0 (opt) fast0507 507 63009 ( all all) 409439 174 (opt) fiber 363 1298 ( 1254 all) 2944 405935.18000 (opt) fixnet6 479 878 ( 378 all) 2550 3983 (opt) flugpl 19 18 ( 11 none) 64 1201500 (opt) gen 781 870 ( 150 144) 3174 112313 (opt) gesa2 1392 1224 ( 408 240) 5064 25779856.372 (opt) gesa2_o 1248 1224 ( 720 384) 3672 25779856.372 (opt) gesa3 1368 1152 ( 384 216) 4944 27991042.648 (opt) gesa3_o 1224 1152 ( 672 336) 3624 27991042.648 (opt) gt2 29 188 ( all 24) 376 21166.000 (opt) harp2 112 2993 ( all all) 5840 -73899798.00 (opt) khb05250 102 1350 ( 24 all) 3973 106940226 (opt) l152lav 98 1989 ( all all) 11911 4750 (not opt) lseu 29 89 ( all all) 394 1120 (opt) marksh1 7 62 ( 50 all) 324 marksh2 8 74 ( 60 all) 448 mas74 13 151 ( 150 all) 1705 11801.1857 (opt) mas76 12 151 ( 150 all) 1639 40005.0541 (opt) misc03 97 160 ( 159 all) 2054 3360 (opt) misc06 821 1808 ( 112 all) 5860 12850.8607 (opt) misc07 213 260 ( 259 all) 8620 2810 (not opt) mitre 2054 10724 ( all all) 39704 115155 (opt) mkc 3412 5325 ( 5323 all) 20621 mod008 7 319 ( all all) 1562 307 (opt) mod010 147 2655 ( all all) 13858 6548 (opt) mod011 4482 10958 ( 96 all) 37425 -54558535 (opt) modglob 292 422 ( 98 all) 1390 20740508 (opt) noswot 183 128 ( 100 75) 760 -43 (opt) nw04 36 87482 ( all all) 636666 16862 (opt) p0033 17 33 ( all all) 131 3089 (opt) p0201 134 201 ( all all) 2124 7615 (opt) p0282 242 282 ( all all) 2248 258411 (opt) p0548 177 548 ( all all) 2127 8691 (opt) p2756 756 2756 ( all all) 11103 3124 (opt) pk1 45 86 ( 55 all) 915 11 (opt) pp08a 136 240 ( 64 all) 480 7350 (opt) pp08acut 246 240 ( 64 all) 839 7350 (opt) qiu 1193 840 ( 48 all) 3432 -132.873137 (opt) qnet1 503 1541 ( 1417 1288) 4622 16029.692681 (opt) qnet1_o 456 1541 ( 1417 1288) 4214 16029.692681 (opt) rentacar 6804 9557 ( 55 all) 42019 30356761 (opt) rgn 25 180 ( 100 all) 540 82.1999 (opt) rout 291 556 ( 315 300) 2431 1077.56 (opt) set1ch 493 712 ( 240 all) 1884 54537.7 (opt) seymour 4944 1372 ( all all) 33549 423 (not opt) stein27 119 27 ( all all) 405 18 (opt) stein45 332 45 ( all all) 1079 30 (opt) swath 885 6805 ( 6724 all) 34966 vpm1 235 378 ( 168 all) 917 20 (opt) vpm2 234 378 ( 168 all) 917 13.75 (opt) glpk-4.52.1/doc/netlib.txt0000644000062000006210000001617412175147600014515 0ustar maomkpasswdSolver: GLPSOL 4.40 (default options used) Computer: Intel Pentium 4, 3.0 GHz Platform: Cygwin 1.5.25 Compiler: GCC 3.4.4 (options used: -O3) Test set: Netlib LP collection Problem Rows Cols Nonz Optimum Iters Time,s Mem,MB -------- ----- ----- ------ ---------------- ------ ------ ------ 25fv47 822 1571 11127 +5.501845888e+03 1651 < 1 2.1 80bau3b 2263 9799 29063 +9.872241924e+05 5358 3 6.4 adlittle 57 97 465 +2.254949632e+05 71 < 1 0.1 afiro 28 32 88 -4.647531429e+02 10 < 1 0.1 agg 489 163 2541 -3.599176729e+07 100 < 1 0.5 agg2 517 302 4515 -2.023925236e+07 178 < 1 0.8 agg3 517 302 4531 +1.031211594e+07 182 < 1 0.8 bandm 306 472 2659 -1.586280185e+02 252 < 1 0.6 beaconfd 174 262 3476 +3.359248581e+04 61 < 1 0.4 blend 75 83 521 -3.081214985e+01 41 < 1 0.1 bnl1 644 1175 6129 +1.977629562e+03 581 < 1 1.4 bnl2 2325 3489 16124 +1.811236540e+03 1730 1 3.7 boeing1 351 384 3865 -3.352135675e+02 419 < 1 0.7 boeing2 167 143 1339 -3.150187280e+02 161 < 1 0.3 bore3d 234 315 1525 +1.373080394e+03 38 < 1 0.3 brandy 221 249 2150 +1.518509896e+03 191 < 1 0.5 capri 272 353 1786 +2.690012914e+03 203 < 1 0.4 cycle 1904 2857 21322 -5.226393025e+00 953 < 1 3.5 czprob 930 3523 14173 +2.185196699e+06 754 < 1 2.6 d2q06c 2172 5167 35674 +1.227842108e+05 5368 7 6.2 d6cube 416 6184 43888 +3.154916667e+02 6596 6 6.0 degen2 445 534 4449 -1.435178000e+03 506 < 1 1.0 degen3 1504 1818 26230 -9.872940000e+02 2205 2 4.1 dfl001 6072 12230 41873 +1.126639605e+07 39863 117 11.0 e226 224 282 2767 -2.586492907e+01 206 < 1 0.5 etamacro 401 688 2489 -7.557152333e+02 444 < 1 0.7 fffff800 525 854 6235 +5.556795648e+05 167 < 1 1.0 finnis 498 614 2714 +1.727910656e+05 338 < 1 0.6 fit1d 25 1026 14430 -9.146378092e+03 488 < 1 1.7 fit1p 628 1677 10894 +9.146378092e+03 1379 < 1 1.9 fit2d 26 10500 138018 -6.846429329e+04 5751 16 15.8 fit2p 3001 13525 60784 +6.846429329e+04 11960 17 11.3 forplan 162 421 4916 -6.642189613e+02 170 < 1 0.7 ganges 1310 1681 7021 -1.095857361e+05 724 < 1 1.9 gfrd-pnc 617 1092 3467 +6.902236000e+06 416 < 1 1.0 greenbea 2393 5405 31499 -7.255524813e+07 3012 3 5.8 greenbeb 2393 5405 31499 -4.302260261e+06 2153 2 5.8 grow15 301 645 5665 -1.068709413e+08 358 < 1 1.1 grow22 441 946 8318 -1.608343365e+08 606 < 1 1.6 grow7 141 301 2633 -4.778781181e+07 159 < 1 0.5 israel 175 142 2358 -8.966448219e+05 123 < 1 0.4 kb2 44 41 291 -1.749900130e+03 38 < 1 0.1 lotfi 154 308 1086 -2.526470606e+01 104 < 1 0.3 maros 847 1443 10006 -5.806374370e+04 703 < 1 1.8 maros-r7 3137 9408 151120 +1.497185166e+06 2340 5 16.7 modszk1 688 1620 4158 +3.206197291e+02 705 < 1 1.4 nesm 663 2923 13988 +1.407603649e+07 2240 1 2.4 perold 626 1376 6026 -9.380755278e+03 1103 < 1 1.5 pilot 1442 3652 43220 -5.574831533e+02 5726 11 7.8 pilot-ja 941 1988 14706 -6.113136466e+03 1697 1 2.5 pilot-we 723 2789 9218 -2.720107533e+06 1382 1 2.3 pilot4 411 1000 5145 -2.581139259e+03 532 < 1 1.3 pilot87 2031 4883 73804 +3.017103744e+02 7573 28 12.2 pilotnov 976 2172 13129 -4.497276188e+03 988 1 2.5 recipe 92 180 752 -2.666160000e+02 17 < 1 0.2 sc105 106 103 281 -5.220206121e+01 51 < 1 0.2 sc205 206 203 552 -5.220206121e+01 124 < 1 0.3 sc50a 51 48 131 -6.457507706e+01 25 < 1 0.1 sc50b 51 48 119 -7.000000000e+01 30 < 1 0.1 scagr25 472 500 2029 -1.475343306e+07 352 < 1 0.7 scagr7 130 140 553 -2.331389824e+06 94 < 1 0.2 scfxm1 331 457 2612 +1.841675903e+04 281 < 1 0.6 scfxm2 661 914 5229 +3.666026156e+04 587 < 1 1.1 scfxm3 991 1371 7846 +5.490125455e+04 881 < 1 1.7 scorpion 389 358 1708 +1.878124823e+03 146 < 1 0.4 scrs8 491 1169 4029 +9.042969538e+02 545 < 1 1.1 scsd1 78 760 3148 +8.666666674e+00 91 < 1 0.6 scsd6 148 1350 5666 +5.050000008e+01 182 < 1 1.0 scsd8 398 2750 11334 +9.049999999e+02 397 < 1 2.1 sctap1 301 480 2052 +1.412250000e+03 196 < 1 0.5 sctap2 1091 1880 8124 +1.724807143e+03 425 < 1 1.7 sctap3 1481 2480 10734 +1.424000000e+03 729 < 1 2.4 seba 516 1028 4874 +1.571160000e+04 883 < 1 1.0 share1b 118 225 1182 -7.658931858e+04 167 < 1 0.3 share2b 97 79 730 -4.157322407e+02 87 < 1 0.2 shell 537 1775 4900 +1.208825346e+09 467 < 1 1.2 ship04l 403 2118 8450 +1.793324538e+06 373 < 1 1.5 ship04s 403 1458 5810 +1.798714700e+06 262 < 1 1.0 ship08l 779 4283 17085 +1.909055211e+06 516 < 1 2.9 ship08s 779 2387 9501 +1.920098211e+06 274 < 1 1.7 ship12l 1152 5427 21597 +1.470187919e+06 686 < 1 3.7 ship12s 1152 2763 10941 +1.489236134e+06 383 < 1 2.0 sierra 1228 2036 9252 +1.539436218e+07 857 < 1 2.1 stair 357 467 3857 -2.512669512e+02 399 < 1 1.0 standata 360 1075 3038 +1.257699500e+03 140 < 1 0.7 standgub 362 1184 3147 +1.257699500e+03 140 < 1 0.8 standmps 468 1075 3686 +1.406017500e+03 299 < 1 0.9 stocfor1 118 111 474 -4.113197622e+04 24 < 1 0.2 stocfor2 2158 2031 9492 -3.902440854e+04 499 < 1 2.6 stocfor3 16676 15695 74004 -3.997678394e+04 4456 11 19.7 truss 1001 8806 36642 +4.588158472e+05 4744 4 6.5 tuff 334 587 4523 +2.921477651e-01 61 < 1 0.8 vtp-base 199 203 914 +1.298314625e+05 69 < 1 0.2 wood1p 245 2594 70216 +1.442902412e+00 326 < 1 7.1 woodw 1099 8405 37478 +1.304476333e+00 1093 < 1 6.0 glpk-4.52.1/doc/notes/0000755000062000006210000000000012175147600013616 5ustar maomkpasswdglpk-4.52.1/doc/notes/dfeas.pdf0000666000062000006210000017457212175147600015417 0ustar maomkpasswd%PDF-1.5 %äðíø 17 0 obj <> stream xÚµYK7¾çW8§ô(ÛÆå·DI$8pCÙC¤L@DÄ‚@AAùõ©²Ën÷ŒgzˆV£mµír=¾*åï… ‚!(ñâNüt+î=AjpâöO”LVÌ ’4AÜþþë´7öÆyü©½ñ€ÿõn6`pÄZüi…2êuyg¾«??—Éy"Šóf§ý´, ÑŽÇ­¡ÿ´…¦ªˆ ª‰Ï!ì~»}"Œ–Ö‹YƒLÀêÚOPv¯«²‰U2Ýðl]užË ½ÌÊû2·sY­{µÔÉe§F!ˆÙ(©5+©”Äýò2ðË#I /»"‘#duªd#‚L!+у•Æ©J™ÁîsÒ'ôQ”Á¶íÙ ¦Ä"´X*nÒJEz¢÷Öì"L’%[´¡Ï’Á‚ôZÌ^K—²hØvÙ¢‹èT]J¶„ä×bûø¹DwF/ÐRÏ£…¬u›‘õ¶´ ÖeE‡{DµJ¤²B? þŽý U±Ý2´³¢ŒC ms>¡Ã(2ËPBœCY–£®Ú<5Ñèŵm«lfµbõ@4À†5ÔÙº÷Ù2ßYF±°€æ9Ê2ï_žºYQºˆN áïFB@:àñ<Þ¬ÄÊad*âoë½ô¨B›ò‘§¤nJ’Úó_C¨Œß½z3Ò1JH<ãAŸƒ–÷ÅLÒeã?ŽDií†ñšÇŸ³dL´¥“¼aÒ^i7Úº­[cÌßj¤Â^†’fû ö»¼g„• è ˜ rξ êZþ2À»’HIpN€.Å2/-¤ëU›©‚Ïœ*µÞZWU«©cùt°v z%Á÷ Ç¨!î=\úî}ÜÄ}û½20„‰·—"ÿÙÇÁ.ZIÈwÒ¬€¤|ΖOS>¬”W†·þvä@EðÙHÒ^ZyØ8çÈcuä4”|&ýà|úù•_ÓWé§7Ó/V:ÂÇëŠÔ³àšþ'œïßÍ: ¼i$ÉÉà%-XðD@f i4çÕ`+# ZZg ­ tæ7g¦¦¦®èJ‹è誣ùTuYª„R¯Ïw‡ ¨Äå#W Ã,°œ¾¤mg[ÖçÒSvóÇëònaÍ"q¹:©¯fK…øyö@ìxÆŒuîÌyƒ¨9‡xM¥k]sz7çªS†oËñDШWR¹6Æœ‚'âp$ª‡ñlþìe·a¥vkØdúv6y´‡MØ‚÷°ñ6Þ¦PÉŽ gzê—hÙ¡ÖIœKÍŠ!³°Latva|K4*ÎVÚ ƒ/Ç=ܘ{H>TŒ qmÃUDÙeVk9åhFXF¡£ôvÍ=Ê3ÍŒÓ1y=Ïv¥!«sIjÛSu™ cÏç˜f}œ^7¥'º2fL2kv1M|¡òƒ.æ`Ɖ.¦Èrís[y5á…¨IÞ,àH²ôú¿¥¾£¤¥ö:†Uîžý>—³2ç›#)È(s®€$Ñf 딕ÚdÂêh»r‹Ý ›‚Ôá³›“¸¦h ´T˜N.8ßœ¸ ùÑó!I‰ØªDRÑ1õ˜Ìy’bœ„KIJŠÒš „àNÙ^wJœ²ÛòQ¦KCèG¢sC¾Rg>H{gä_á$õKÞ+0¥S(íO*=´Û^%âÁ ©öÍ\’ë17:x°¬´fãbÖ¹„á‰ÏnŒ ö˜S"»W-‚R›A²{ ÊÇÈÃfË%—ŠÉÈøÅctZ¡£2ãá—¿¹HH%¨ùæàLö|IÒ‰ºU¾£ì\¾ S|õ|ö¼ú))*êÿ.\öÚt¹’AýŽ…½€Q³Ÿ_”R_Q0Éü8y# ¶«¾¨Àªšè¬:ÀÕÏÝÅj%‹ÎUœ”k©†U?cÈrÁ…ò>ºïÚÅ?Â: Ýi#½2âÏ äØ©½x-~Oùà üReÊ<)h’É ôÁužo½ÞE7P§Þùß4îíºª]Xåæ$N]3õ EÙÂôh¾{öêu­OÈE[4<&B-oïž½ý'jùþÅ›?þ–ï?|?ˆ¢Áꃾ¼—訚v_¾ù ß¾9…(ldQŽÊ¢õ”Æôá€?¯0ZŸ~õKœMc endstream endobj 24 0 obj <> stream xÚÍ[Io%·¾çW´O~Âèu¸/V|H€äÛ ºE9dA€™>Åȯk#Ùýªß2’ÃI]üš,‹U‹íåÇÅ.¦ýg—ì–œÍò÷/ËËêkYþ»8W›–³a5vùÒí9×åßËŸ–ÏËï^—_ÿÁ†¥®5ùåõŸ”(-¯ÿøó)=ýåõ •kÖj* Âêbûáð-ʒך¡9¯Ö·×ð~ÿ:t\m_×âA·šVãºàH¹ÒP©£ ï³¢]Cµ·B~ºÐ/­îR¿6TCsYcëÔÂO}FôšÚûüæ×ó!2βº´Ä5ÔI˜ÊjÂröeÍ(}3Æ`ö€?Þ'ÎôãXXzü±Ï‹ïÚJå2/~³²-»ÅWáiO:œ]+tø\»=Ü©pº­¡]ÖÀØZÖÒѶ 4¸§Öæ  ©µù;ÃChðL­. ÊÎpzàF+è< œX‹“‘™µ8ucd0.e×Êð8 Üp+úTœvR€°“¨5ˆ2~xáTïD7 <3‘è–±C ÀÆB;,c†@Sî´t‚ÂÊ ÖjdwIZ­ê.‰c¸eN ª §iµãŽc8E3(pʃƒÙ\À#Ð0he,¹Õ€dnÃ…®—Ñ* +±1ñû“ Üi!#g=(pï¨Õg†ç!Pà”Õ äB‚Ç!PàÆS«I Cpd>W!|Ü Á_u!îɪWÈj-J©0Nýœmð8»¶¶\3}óμùØþ%»>½·'úíZ“ñMÜš4‚EG(’¤†ˆ¤íïÄ£U:]†ÄlŽë°•÷åó¦’Û6MG¼ôboà!ÔRêƒC<)&Ìàj†MÀ&Í9+Ê8 ÉÑܱ`[…Ò¡B/Og›’~T‚Sz«ÝÛÆÓ3.*6 Ú©mD8_QóJõ_—#YÏ!@f§ÊÍšOÄæÁ6 ùæ5|*fö©8ZÅÇBf™cŸk¿s7¡Q~?¹>½aßÍ#O¾-™ n<@`÷äò‰^w¥.h`T“•‰aêŽ\>*†¡!Zß'ûöô¼W‘‘ªým½˜8B…ŒLƒc!îéP+Ð0LÆŠ‰µ „Îz4Œ×øwÔÐÁÁ_¥ý•ãX’h{ûQ©|š‡íD6…Åiÿ’Œ€–„c» b;l÷ô¦h›ÈÍÎNwÌ3Åï”]“2F|‡µ¤9Ì~^!s‘ÿÔ|8ë!ÅFˆ”æ±ë-¦‰)m¬Ò†T†*À¡¶Cµ€¿‰_X>)û›ŽïÒ¯4vô¿v£øƒA¦ò¶;ô=Íénû)“ª›I 7ŸÈp0< i8å–ÓÞ=áºïáºyVM:<]B‰áÅUÍ0 œ¶#ÕÉîœ.'É ¨ËXwËè6þr˜ì.!¤mBþN㮨X8¬<ÒÖ6”(LC(èaƒ"†mô°c(äŒ0-( ÙLÁ8HC%Àep„p’5¨»;c«’ì[ÌiÄꦟ—ürùasä>9º$ë¼c®ÀìÙEç ®3Ÿ¹@&â0êãå£+-¬‚‚ @¬I®³á.Oå*†>ƒúµBgÔÑ3Í­@yàQ9ްýªÝkÁ'S`÷V½I²Enfæ¿þ¤þÌ8ü©™9ÓW9Í %\b¶™˜‡Uq‡õˆͪioÕíѤø>i\óÁ\4í3Æ&˵¹ÞÊrhýžå¦ŽüA?%º»8Àž‰?<û¯cân£iÚ¬PžõT©|ï‹_ÞEpλ ¿„…z€–—Ÿ“‘üFÏ9¸½’ÎHl*ð½xrðq3 |=ÿùWÿ…=¶Š endstream endobj 27 0 obj <> stream xÚåZ½o,5ïù+–Š;½·ÆŸc;@ñ  CJG(x ¤WÐåÏÇ3öxí=ïÞ^rQ rÉŽ=ã™ß|z§'5Éô£&¯'ïåôç—éÇÇé۟ݤ¤ˆ2NOÖ‰`¦œðnzüë·Ó“±æ¬=þ¶éãο?þ’Ö@³Fmژȥf“Ñ#ã'#"͇BàÛ=¤Pjš+ÍçYûÄõ4â—„ƒkü`²Â…Ž_¨Ïå4{‘žþ3Æ‹ôÛ DÄã\H\G4Ë`œˆÅ@H³¡“')åÛ¨Ålh¥áøfŠ‘γ!ô¸„çÒÎM€j{2 Ué»!5j•þ²±—(dþŽ«-,VJD%®õÿÒÀd Ê®‰“Õ™›SCüFá}‘ùy„&m/ÑwÌÔ¨¿³¦Žu#ª›“¼BO³2¹+ÐZËÛšY›!°ÖÃ1‰aGb',?þ˜ôo ëò‡¬[,ŒßñYû?ǸܦåÒsáj{  ÑWSÙP» ¹†BA0XÁ‰Vøf_‚ȼµLAH³5B†ÞXÖ—e– JÅý ØF&¿…ä3é«f`Œ$Ißîž/lw{’ ‘púnà ³—˜Àf•<çÂiÚ ƒ°,÷{ªN] òGÒŠ> ½…“Jsºª¯‹Z:}—¨? ý%lçwš|йSõŠ]Ïè^6{jv ç`rDQÅ…h3âÚ€¾sÄmPY<Ô¨">œ/Hn×Ýb?­W²CèÉkceß‚˜u‚=²j&Š?PÌ¥³‰(4cøµÕÀ´§Tæ_T½AfMyʵyŠPµ¨(L*‚µáUxz'3_j1¢eå^h{9®ãe\iÈ´½ZîmszBÛhŒJ1Բğ£Õ ìs.%uþmk¡ZïÁ*WRiš“ôF}PÝëö<Ð5ÅŠ³eƒ$˶—¡K£ôQµê­õW ã !W…X!ÔH:Š_Akÿ¦?_$J+ॉ²Ç40B¾ùžYšÒ/<¸$D>EŽŠ³w´uÀ0ËÇûdys{–_9È ¨Ò§ÝevÕØyäÖMÝsÈ£«Àq(𫢂»O“JX ñJÄ[Æá~F9^÷öÝ5ö•D°cKnìÒlå€QcO 5P¸ƒõUHç'Ãþè&®Î7ÓÜVuö«ë”WöÜ.§Ú»¹]ï5+øP:l“ ×Iž•Ü€>Œæ(Fضb=âuyò3Ö–¯ÒÜÅÙ[7, ¤»Gxe)¤LõÑ„aS¥°œy³¬òþú‘ôýM³Êƒ·êuÞª•Rþ[5¦Â9á/BtªetÓ ø¥,É”×F…êÆyŽ~§’ÂyŽŽ+©B\E"&mã¸ë'‘¾N+s-¢˜±,ü+¨õ`eUO]Ÿ«l{Z8ògÔM*{³õÚ xÓ’pPžüpœŽcn<|‚ Ð\«(ô?µŒ)»l/ë8pÕ4ðß9óKÓe~^Xúùe‚e„IÞ0ó ¾t7.ûl×éH*)`q&ª6tKAMKiThcW¸Jax¸™…¢èQ„r¹'ÃÑ)õfvÎÅ{‚Y4«á9»°ª×[˜+'CXŽM–CÔR"滋J©Ûû»Ò!×´4So6™†ÔhóªÀJÊÇ88wÏ4+Möú†1ÛôÖ>·j¹^³–¡Õ2ÍÁØEA»MQS åþÉá3ÎÓÉ”Œñîåµ %Žà›Ç=?msg!L‘Ç\À³I¢È9„žVN’‡õÙ@ä,´Šç^®M4ðät6mkcm´ä«¬ÂI-\Èd²õiÛøt?9`C*W½Æ–D×ã|mCÞ½7p!‹ŽòÎ;9·p,²{Ó [8gÿ¶þÎxÝÑÿzˆ2BÎ2‡ÜyS/jß KH_#µšåJýÓó(ø¥·½Ö<~.ã 0]Q~uÝe`Ÿ²4ìw­£á)Œ‡§ÃLæ<æï€uhÎda#“Y+¼¢LÆYÖhÓ£¤ÖŒó3u~†ù’Mj©¦û®×q=ëxU¸–LÉ +µfn(9´·mWLµ› 3Åv. ¾õÐ:$ÿãRýÏ´OˆƒmÐ}Ö-RQ ïk™œ)NÙ¿8&Q¼²õZ“¥„õE|æY&*ñ+þë¸GZÛ)Ë—H1€l§±ç‹r®Èg%Àto:ÄnÐbõT)v> stream xÚÅZͳ$7 ¿óW4§Ì;?ä¯P$)öÀÊï´ŠÅr">–%ÙîMÏÌ’**õ6¯¥_Û²¾,©ßòÓbSÿ³KrKJfùû§å§eõ%/ÿYœ «ËÅX]>uB}Neù÷ò—åÃòíÛòÛ÷–²–è—·vP¬ ¸¼ýã‡S<ÿõíOkÖb ¢`u¡þãà ä%­%!;­Ö×× ð¯øãÛ er¥B|Y³GÙJ\ë„{Â劊…k_éì Tßr òó|qu·òÕ­ÂØê’òê¢ÿEЇÂUc}Ÿßübº‹ 31¯..a…2I…©.1™·«0Û5‡ ‡7Tõ¤<ÃëÑl~÷ð¨ÃÙžÐáƒpw{¸Sá¼µF»þ¬7¯¹£m'hpOÜj†‚Ä­NÆpè žˆë’Àc'hðB\“> ¼´“%|à~48WdñýY'b'èA¸ó¶^TýùŠfk\+*ß ¼í×":APà$K\ú³ÄŒrÈ0 ÜÄUbÖÀ¼”Iâ (pOLkú³nK´(£Aƒ%nËçþ¬¡#qÅ<¹?+ààˆ "I ^ˆÛã¡äNPà‘ÅZq«žÚÞ°–Àp;¼7‚'=æo‚»APàm°Bf¸„¸ã °^«žá0 ÜÓÊâ¡?kàL\#k‡APà®ùž_³,AûHÜ$«§APàˆDëyxâ‚h½ ‚Ì%Y<'|VÀ‰™œ‰ê/ƒ À3sc¸N‚:Q£gpª=»¶ÃP&8 ÂTmjâ9OŠŒµÂÕXPJžæû’'LK]jªöVJ¿«wæêCý‰v=_¼·'Çÿ¿z®ðÇ]}Jõÿõ'¸³‹•F)Ëêòõ€æQÍè7¦MÕéËÒד^˜oqPö=½ÅYQSBo5¬€zh µDO*ˆ–8!’ŠP‹u+rl!{ 3(2—@5¹™ ÊÁ(OÓ.F9U@_#öJ¨Ë®å;h•9·.ñ±!h¥wÆÛÖìýp–¤`aIˆ¯Ï—’nIÐ Í¡G'Å£wÖÌKGtkÆòjª£]~ÿj«5b÷…€¾YAÕê!´çªH¤DƒaA~Ñ|øÙýýDh ðÍr¢ jkšö{¥æcqGxô³häá¶ØSõÆä} Uä&Dý´h,®.ÜÔû¬]ŽX!щe_@©e ZRˆ,7ä]Äð;(¹$à]´^—š¼‰O&òÉaF¯²M“Q€Õ?)´…¦'aÕðtÑnÑk^bFfk>Ug±¯Ñž:Di§T=“Å ¢/<þ$²DÊb±xØZmLzœlïä¸DÃõZÛÊï’³šÖÙ–Ánßšu»{+± ›'sÖKˆúR‹g0­_­m+È=匢ÌR¶ëRYgŠÈo’B­ÄòⱟFþ›–n±dñVI©síñkÍÞovâúÛÏš×lÄñ;eƒK ­ÜXA’ F½3qp“‹žN«BáŽÆD–on4–ñöy¤1û’Ê&9Ò9´³6ÇØªlóºKØYT÷`9NÖ¨tuÏÒ sï%3GЬè$š8›NY¦å±šeª £o[öí$õ†’”Ì'FyÊÝ›”¥%Òd9Aõ]gSC¼˜ÆRô|*Þ}“;%Kº.Iûb/åw³K*f–ï#•0 &Á¸Zt"ªß¾q¤DNùm7^+ˆøg—w*C…:’Í”Èø¢H~¾tÀkYvi+­Y¥8eÊÒrÑ­ªn:ö¾ æ¦O#©Ò±A½=yÖ%UNµת–iNjÌ>ɆM´ºÍEÄÛ<'Ís©ÚŸž‹ÿÐh¦K6ÈÜIn“s@cµÕãÊRB•¿¶I±E² 5gÔ*{àÔÄ­´¦”~³O¾èzðn}DÑ|ÐÏátÏ[ißàFÀR<àUJ¾ÕW±ÛËÌT)ϨNã§8Òhšd.%L¥DÄ\S[÷ë© jEcˆÊåœúå,ïËÊ­`²»2s:;¡÷qè”e<Ð)ËiGÁÓ<<çFÇV ¶ƒHNý\¤©^Z¦Í³ `eñLßyçŠÅN…fùﵘ58èê‡k|gøÂÖk…X^X㣢2´v@¿¡­WÚWœøÙ©@Ã&@ é[!…¶ïŽ’_§DI PN]Ðz8ÅÍ&÷-xáN0a=èåïÛ°®Òæ¸Ç«øV¼„6—~^”Š‘åkó“ÉHöÖHßÝ黼DéFúF/«jp¾g›)1Tënë N¡}/¼­VÁ{üjJK}UsIíénÕh3.CÛâ ¢C¾RKÛU¶ú"tFÇ4“nâ¾ØƒÂù’ Ý{³aÔúÝ<ê#ÜèÌ>˹ÿ/šØX?}­Ø´]ÏX¿Þ$ªõ=…bÞ„bÑj>lƱïtFas,,ˆÚ(ºäÀ ùn¦¶m"Û!_ÓA5 0èÃQsNIðß"Ý™=îÎp¼øÊX1>ëzïÕ¡­ñÃóÞ©]®{Ù¹w;Àÿ¶ƒ–Õ·³F“~¹3|T»‚2]þÕW±+þî´ˬwyv 5”Bܼ.3(* ·=qŸ–Ú?ÌýìÃòŽç—ø«Ö(çu}q}þ†Oþ4÷à|r=¿æ,À\¡ãðT†¸ú(óv‰iê·™ ?^fn¦à4ÕÑN;š>8UÛYjh—›†ÐŒüƒ–Æô w‘;—hî÷Hô¾ðaÝ/(3”ªr=5½MoèÞs¦ÍDäÜ7÷ÛVG%qIèíI>˜q‚Úù'Žéöež/F Ò »f²»{FœÈííz7MðµÙá›;†­cÀ¦µ‹¬Ë ñç&  È=*Ct™:ñîvŽè}S7>°I­‹>ð;$`Ù8’{'«ö S¦÷{ÒIãNœ>á¤.LL#£%I9AÖépâAǃ(ùÛc=™Ž>‘Âk_¼>ÿ)<üD GŸHKžÇKT²ÏX5¦»¾›æ8Ó4aL°wãcQ}Mç©YT»¢p}@šÜt?ÓoŸô¢ê¶78ÄÙ:ӥѾ¯×ÖP_ER;ÆŒ|Þ¶ù”p÷o^¾ú ´»ÿz'?'üð«ÿæ÷h endstream endobj 33 0 obj <> stream xÚÍ[ɲd7ÝóÅŠîÀu-¥f"0½`á°ƒ^™fÁ,¼ðÊþ|”ƒ†ªÊ¬ª×ƒ!:ÞëwOžÒ•RºRæÉ[§Nþäú?*p*Åþñýé‡ÓZ=ýxòÑNgŸâáüéû ôëÒNÿ9ýùôíé÷oOŸ¿ññÔŽ–Ãéí¿&)wR>½ýç_^å×}û§ÎÊ'ïŽæ²â©ÿ Dø•ê©­ ¹½É³?r$¿‰ðÇ·«o¹agÚQCï`ÓuFßÀùÃÁdaÓg¥sþˆùtütÓ½|@0ºW:ãÇS G„­{Ó•{÷&ûÊÚé-Õk£Ù»YÛÑÿè¤xxöô;ç£ÒY_n:ûù›²µT°·“ñÛ×g(å•S<“ʵ¯¹YPnF³ðàfÞ¸Ù>á·mõ àî꤇«/ß_}áîêƒ>/!lj_XùÑò Åþ­¾~§´ît.õH½Q¿‘ô-‘°ÕÜ?/Ÿ|–§™¦¬èátĶû2gwz0÷%ßnŸqxKGÝŸèOÀ3ô|MÏ:]¦3NúîÐáš:=²ÕÅA_€F§­­âÇ„¾^ØÚ§@è Ðè­}™ ½N@¡ »·Éì0¯5²X]l˜€F§qì’РÑ+[gWæõ 9ã¦AÆÂŽ Ðè‘­aø<.@£¶úáĸ…îéÞ´;2=-@£'¶Nö¼ÖÈy 4-@¡óÒë«%/@£Kc0ú’ëzƼz ÐèÔzŸÙáõ²…Îs’Ž2V@]€BOlSÔÆ¥FÍlŒ£#m =¶ÊSQ$¬HêcÑérkñJ‘ƒ;^)™õ–„î Ðy3¢c‘é°….1CŽÂóZ#W¶Æ:Ø ¸¡9#žŽL Pèåaü2ZO Pè¼…÷x`´ž Ð=cᨣõ²…ÙXFãu^käÆÖ4|^ Ð“4‡ÓÛz+w…vO¹VÈEŒ²UtÞz«¡Ã:w†«,PXeaÃQ’ÐãŒ8J“Íú½Ù‹À.5¯àò„¨Ÿ¿iñ 1ÐÖÁßÓ9¯t ƒlƒ-V%´óý„ æG°¤©ÛîcØçåV¿VzM“Âf¯}Ü5|l™àôϯ$¢Ãz0¹…’e¿äV€É­°>yr;»7ÝrÛ½¤8oujRúõ¸ÜÀåå\ÁS?úu_ºðìûâÃH7%ôÕ'ʼ/Ö+&Ám÷yb»ò¹J‡k:Ü¥»I¯ÐèdMœ¡,zR2¢¶æI_€FÏl]C]€Fl]C]€F¶º4è ¸¥£)bF&Üy}C òöP* ;,@£g¶ÆIOÐè­s}”‰! °+õ%p&Fôht`ëè Ìk…\“¶¯Ðè‘­}> ö¼VÈ™< œoÐbX€Fgc‘ šW 5IC‰](·@¡óÓ˜1½.@£¶‚ô(ôPØê@èe|æÇÓ(P@¡Cd«,ó@¤ ݶÆ*ô´ÎÆ0ÈãR¡ºÀF?Èq7tqœVѸ Ðkak3 Pè¼ÊÝ1œâçµFf[óãçµBÎb…Ño·…ž€­òäõPèä³r4/ôº…ÄZ¢ÐË:­•n•Ç(s@¡{±ŽÆÓ¼VÈNŒ„pC÷ì†nu£+a xÈõh†y­ ÛÊè‰Ÿ× “A´ŠO<Ÿ (ô(G/ôº…N‹º[eµxÞOPè´sç:V‹§œZ…N+èKfÓ>ÆÀ ÛaDVÙ@=oL (ôÙ:ØƵB––â¦Ÿ× s4´Ϧ㳗…寲±8>ïPè@ó'êy γœ¥Öƒ½[À5=öç°±5¡‡(ô*%:,ÀÈÀ}jŒÐæö²ÔY+Ú̼jêü÷òªù©‡yU~W=W¶™Qô(ÛÜO¬¤lóIòªŸµl“~\Ê6;w‚ÞïP1(ø ×Ϙµ]̽”„VR-%!=ƒÚépM‡h•„f5JBzµèi«ñ+ƒ¤™A _Ï F‰¦´U0*H”0å­‚$€QA¢„i¯  W(gÚ*HrmT(eÚ+H$´¦­€Ä×FýÁo$Œ Z}Ø*H$Ì<Ú^AÀ¨ QÊ´W0*H”3í$Œ Z£ßJH5$´ÎzfZ€QCBë\yF ³º×0jH”hí5$Œ%Z{ I£†D‰VÝjHè5¤™xIõDÏ»F‰Ò¬½Š$€QE¢4«nU$Œ*Z lU$Œ*ZSÞªHU$Êʶ"_ë5$´AZ5$¹6jHhum«! `Ô(+‹[ I£†DË^CÀ¨!QZ¶×0jH”™µ­†$€^CBcˆ«†$×F ­~¯! `Ô(K[ I£†4óºQDÒóºQE¢4®lU$Œ*ZsتHU$ÊãÚVEÀ¨"¡5ìU$T‘.cØ'EÙ‹¢H#Jì@*V¤°Óáš:=o‘ѳ),ºD DOV¤@ô´E ;=ëô°i­D–ÖJtØ´V¢ƒ¥µ}“Z‰m)­htu[ˆÕR[‰ž7µ•èÙR[‰6µ•èÁR[ÄMj%®¥´œå©Ù¡XR+Ñã&µ=ZR+Ñ—ÒJdChEêqIhE2dKh%:lB+ÑÁZ‘^ꦴÒäVKj%zؤֵÒ4©é#$(cz\µäV¢‡Mn%:Xr+ÒSÙäÖ5gšÜJt¿úD÷Ö±Ö˜6¹•<›,¹­¡mr+¹ªYr+Ña“[‰–ÜŠVH›ÜJ®J–ÜŠV_—ÞJC¯†àJd¿ ®Ä¶ôV4ò'z+ù)Xzk€%Ï–"ô,½éCž^lè­H.u\×°5Åé¹mŠ+ ¥YŠ+Ñ7Á5@°ÔV¤Òʧ2Ú[§2Z£ßÔVµ·ÔV´¿©­4no©­h¿ÔV‡7ÔV4z¿©­ûP@™ü]j¥qXJkÏa(­Ô­f(­H.u“Z©_ÕÒZ‘žó¦µ"ÝeKkEzŠ›ÖŠ@‹–ÖŠÖ›ÖJCKkEkؤV‹¥´¢Ñ—Mj¥¾KjE+²†ÔJ}‹–ÔÀɲ+Ç`oH­HfŸ‹ÖJ}«–ØŠô7±•ú-±éiÓZ©k–ÔŠÆ7©•ú–-©­¼Ej¥¾yKjE+åäCjE Kj ¾IEA¤Vê<’ZCp"¼‡Ôzýò4š‰@1ÌG|ùȾçåû ÛÛ?ÖûGÚû nöîeB郴ê¼Uºô‘lþ$çP§ûD½ ©ÿd¼>‡à_ùÿ]ðé]ˆøïB)ýÿþ“éÊ8ª_Ãxò5ŸËaÐ Ë›¯tÑ;ÞóÔ oñZñQÁ¸Q^ç 1öÁüpIN\ÄsøwwSé×9M&°5¡5£ÑØjXíàç¨ Mã÷±b½ã…Næ€Öµû¼RÔ3%<Òì¹Ç8ÕGÜ{\<÷qý Oò—ŸÂ…’äçêSE|†Ÿv¯!¿bŸõ¿;Ãõ©.}*†s°Éð:Åq»„·"ÝÝN«2^uoî¿ÐüšÔRñÀ“gÕ)ë£âŽèä1ºÿ"Ÿ‘N÷H$ Eþ­ÒD¦=7,Ñ>xeci8c|Ÿ_j[ ¥Mlÿþo?i[\ß}…ðå(­¸­´‚ïæã™P©X;“ë–‚9/B¿IÅK„fD~§‰¤G|ñ¾š¯Zž+¿–˜1¼½óJÚÅ+™÷T.ž}£t§wSOê…ÝŸß™ï”éÊx¶f*¯78/æê7óðR¤\"s®¾RÆÝŸƒ~6z@µðÁÉ7—ÛùW7~‘7·‡_ÞhÏ£ÃtnR¶ñÑF~A_ëûB·>߯wгðë,“0O¦ÕùŠÞ£z¸µ¤'·–mÚöÕÆ ~{ãÿdg¸Œ®w·?zê{©ñ¸z<ï–öäžåk3+9þ8óaue¾PËÒƒü’ž„:¯<¨Éü™d`ünJÁ:_NŽ£4³K9Òâg3w/çy®É™Fyle€²àqvažOÍ99åâeN,lm¿¤—w? Ë/¨,YCäœ×P^‘ •c¾Žñ¢;{^í¶„^PÂ~°«ÂEÙ†éæÏà‚|K®2Kžò|êÝ1óÏ.!àß—b„8~è2šçzQŽöébú…?u%]Yú`Ohå}¶¯ì†(c8‡Ð¥ Í p¹ÉÒ‡ÎÐʇ¬3~éზY†‹e¦,©X†´9+ñ“mF…eõˆ<¬³­‰†VM_ðÂd<¿v©ˆ_Zåï®Å[÷¯ÿ%ëæò“Ï®ÑRX—óE28‡Õ<ìK¯c|û‹ÿ¡­£ endstream endobj 38 0 obj <> stream xÚÍZI7¾çWTnï!]²j'À8q||1Ò>Í›K 0@<@Áùõ¡VIõX[»F£ÛU*’â"ñû¤á×A ÿ©ÁëÁ{9|ø8|û8¼xƒaÀ ÿÀŠ`†ÑYáíðøó¿.p•Œñr3Êߌuø#oÆ)ü­¯#@À7ø£ë[UÞ:]žÅgôãÆ28DqÎ\uM$Ѷ¾“~'>E”—HüÛûÖkò“?þ0h#œFåE„<œ€I“H& jÕny52)H³“×Ñ8w© Q^udLy ÕÔú}R÷â”QÆäűj×èW[µkyÕi&PÝ—]XçšæžfXæj²IköjWíE÷Õ¡«ö}gï?ªÁ®1Ø«…ʶþQøf@6`î¤×ß0ß+%¬®ï?Ô÷a@ßûœT3ΈèòûGN¿@oM#~g ˆBûÔ–fi€F/dÉ7ŒD|™¾‘¡3i–鄯BQÂÅNDo3Õ4â+ÎlüKò[kö[Þ“ê„ÙoÙX»ð9Í~Ï{;œ0û=ëmû9­~ÍZíö¬†Æj{£¼šíþ’™˜2i +vüïÿ¸™¡¨<_æ÷XÍhœFŠy¯¸²ÂõìTW£ö¸D]8 yC(ã^ÝÍÕG¦ÎwM|XIL×E8ø"Þófœñšq™ïÊãv­C”Dû¢3%îÒ Æ ‡HÊ%t¶5ùÑ·ôÈŠ<ñ{cœ0åÉ?Y¿aG‰°›§\üPg°8„õ{5V#ˆv¦­&IÙµ%¬¥X8hKÇ6H9ŽN‰¢GÝé»;wo?ñ{c¦ ½â*Q¥ S:Uí‘mö§—Ìj2*ë„ÇZE³¸I)# [I«áש³QŒqaÉ]ÔNeǦ ¾ææ–Z Ù-̱Ûp€V/µ³n×ÕÍ¡qqSæ²^ÿˆť;ÖÏnR'Y‹@’w«â-ošíÜ ´ž8oWâ ÌÚíXÍvµîWRõ[楎\ÄfåFh»·[*aÎhÚ–|RÉoG•¸Õ]ä%—8Ñ¥äB(ËŠp» "¸rpؘÜ:Oëj‚o¤¦ßòMÖ¶<·%Øe‡X÷Ö“‰Upz5@~^ë ÐU!âV…í²¥+RÄ£d/ãü!s7uÉ10ÕÄå¨4*\Ƨay²·c”·-„_ÚÌ‚T””©ZsýZ§XÏédõUg>ˆ|"ɲ0$P,w4RSPËP2uRs´©•;]4%ÐD@yWšJ\¯O°gýWÙÙŒ¦ÐKq(1k0Kz l[0O¾eÊÒˆ²%‘F9§_ujkmçú‘«rÐdV©Š‰¾â¨+ˆ;’¦v{ÔàŸnÒ(–`°èäÖZ5LPËJ0ñ Øv[`;ü5`;|:Øvñó í–·Á®ñY‚kÁmÁb n‚ôêÓÃy¼~ä vþ(¦o®íNŒß‡õ1´Púˆ dïO Z÷ÎäŽâ{uðá%åïš™¶'˜}“˜Ï ð^É¥ý?-¹£—%HPdpÛ I<ÇAaÁ‰_ý:vû¦t$’³Cçz+°½Æb<`…cHÓÈ‘La«·h Î@›Î¢–öE}ÜKa¿zûàì[䟗˜b­=Ås¥’›˜ Iã6IÓ3AOc÷âIv¯•®¥M]XGÁä¨öP@^=µ¬†C€1$²¡.´¶«Ô½µ¢«‹® ÐW d|¨¡žug ±,àèÔ|ÒÜ€”ªí0ÐçA-ºš—OÑN!>p„¶CÚ3†T8r•ÑÄBÊÎ@é@G´BØÁ6Ùåïñ˪†§vg4¬váù4°„J è’°sv“°£mæûÌ/_Éüª½…çå —õ“µëÌP¥(|^žÖÈ;viÕGéܧåöþæsÆÛžƒ0>®á5«ÁuÞ°€ç™`Q# ‹×DZÚ†³K«k¸[]ìܼ*ߪ’C¶üNù¢¹[$sõfSË/å¡•_jŸ<“‡•ò-å2¹¤ü¿˜iñl÷Ìݲ,rÙ†–Ëï›ÂÖD‡ŽsÅU*±nÆ)¤!‡´2Œ&ܱoùI¥<'¯aš—„ /'æ;yó¢QF´ŒþV¦«wÓ—²Ÿ€‡ÉÒÊaf&_6ô»›úŒ±÷I7ýÚ A{Ašû†ä4Î4± ÿ‚ÿÜž }@…¹Z¸Ìöç ›Ù0÷IÙíÞw$èKl«þ(Oy°d)DµÅOrϰÄYfî@)MÒÎsº˜9%Ý¥žG‡XÂ2¿­Ì}sû“I¥µ¢hOæër/ÀÝEÉ­µ®¬ÂµDæ®Ö¶š¶(ÊM9ž_cÂ[Ù´ |Înúþqøu›ÿÿO·x5®dvøˆX'æÓ÷úà—áÇá]¹û«Â(†!XÈÂ#ú!¥ÈDW.çÄwq3š½)åd?çö<*§Ÿ¶O¯Êh×x?,¼_dQ ··kÉÛt»vj…žïæækÍ'l{˜†=3ÅýÅ&ªTN”t7U´‘As‡‚`V¦Ï l«ªïYImÙ?Õ«Þ׬/o%IkDC=½Ï÷¥µO†ö\;/i]Pr?-×p\{îó×QGJ‹ä(ÿß}ñ'R·™¹ endstream endobj 41 0 obj <> stream xÚÝ[KÜ6 ¾÷W¸·Yd­èEQJ I¶ZäR`sêôP¤Ð)Ð[óï«§%Ûôkv²IŠ †&)òERÚîŸNtÜÿÊ‘wï?v¯î»§o œ9îºû‘ M×`Ýý¿žÎŠãYi~V ý'œ•‘þ9~¿½é5žÄ`6ÈHDá3ü^Œ x¡ã¿)ÿ+Ïì!¿™:Þà§óIèó͈à¤fµÎŸQÉJ¹¥Sà‚Ö«¿ùíþ箆9å?ƒb–5}×A_q¾¹ _à”” ¬±XÐ$áF ]TÁ8*ñTU^UÕ$=?äc¬L‹ÔlÔ¬c”$k“ù™"-|‹Žt4—ÑJ|l ¢Nó(Áuž›¼‘ö”x&Ý4üYTñéÁ;ÇœQ!`:΄ëz)™ÔQi>̤¡We˜³³ÜA31L¥‘²F¦ áŽqÝ)Ãt"y™Il‡QÖ‡Î2a;å'¿/L1¼FÞLýd”ô/ñÄô§%0ébt”æBao aÊoBsaZ0¡“0Xæ‚0Xöަ- Â\+ ü;æÒ™%ñw„0£™vSac@3Ð*IÄN¯gÀx=ƒÓ:Ídd€Sš¤W×KÅìÐê8X/ƒ8 z\½L«ÎG_Ho¹J–ëS#ˆž¹„™/=ïàmfìâ Hóè…®"¶QèöÁÌw0r‹ÈõŒÌ.FØ0º# ‡A]ôósÈ©ãpº „$,q´ö°u¸ªð‹7Íë1/O¢S>H‰¯24¿Ÿ9K‡ÀWEâP3¥Z¯¯pY!0±—Ë qyˆË"üŒ`V|©ˆ7‰%1þùˆbR~NèÜ ˆÚ LìB×Ubà>3ºfn6¸#„I—#ç‚X]&lkMЬs› ¹÷Ó÷*NO¬ Á5“j®eöð™ÁÅ­D"…õb0 IŒûºá2ÝVõ/u[Õ{vUÜŠfQ¡ƒ›áƒvU¼Ö®jöîªò‰eù-`Ç¡O4P~BFGŸóÆ]c}œö,†¨‡íð—g=r‰Ý7T§{°j€øŒ°™S!ç÷°Éí‚“€óM&l›š¾¨wÁ€½óÈÉsí_z&‚î²ÄN@î=i¹ÖS‹½˜Ð3Ij¤g²Êy€‡hxðú”ßÅÚ¿A=ôØ"MÕ”îb ¼F]²ýB5R ®ð¡MÆàùD`T‡¢›?áq²âDñ‰ ua– }Êï?-Ojf̦@7Xã;0[—/ô=B ÅsrÒöø¤u v½Q‡w´ìcêpG #îµlà’•H=@¯ÏÔ.íüqç±PÓ+*kdŠ}åf)õÂù'KoGOÓ óØÁT¥Cίô•¨U²*^šß«‡ "¾ÛAƒ|š`¦§ ±]"Xaã­ÉRï{¡|´ïŸž½\)ø§¾%×úþXN¿Tp2Ù J è2§ªoÅKö•äR6íôø‰¥_ÅTÏ‘ñ:4êÍÐÄ^õ—ÃF•šáZ¤cÝF˜Ø*ŽTíñÏVžQ™‰ It/Mh¦î Å „ƒíꛇòîðîF½Ý„ÖÅSnu©ætD7K¦ƒ£Xø9_ÜökþŽ49|fÅïHÅÍÅ免‰‡Úb ùžêWz­Jóñ÷ =$g*P›h/¬ »ä¤²¾šN-Ž$6³x6ÝÎ~HEõöbq×Utamà‹^cml깸öëIeb“¥àst‰öDjkÛ5Àc(×áýÌ…&z57ð*bÙØWj¿ó±$R6–¾h„'œ$Ûo¢ÎL3söÁUJo‘Ùv¶ìü–D±µ33;³hf1„Ä‹V·ˆÝÊÊH[™RB,ÃtÔ¹1ŠY³Õw!ðvÖàVÀeÝÑŠl .wmp]Vúõ &WTÚ帠2P¼H.§o2ÀÔŸ£f‘0©,qQª1žÒ_à·Ã¨Yq¼ •rn• ˜?Í•ž”Q·÷aòu”\Š–«aC“šªL6ù{)æÖœ×àºÔÑóšÚŠdEíX‘ðŒê£ ñ¤²fÿËù\ÛLOp1=yrqš Ç{w,±ÇÅÄþúZ¯eõ3\Ê\®¯õZJÍ<†Ð;žè­è­¦zÏÑŸèÓÚ²Ä6kŠ?ÿ¦TŒI_ìzÉÕ¤ŒxÌ"áòUø¹*„뮺KË{ Žyð"[¸8÷àÚ@ïXSrÿšzI„ª¡ôqT\8ïX}¸ºØƒoUôY»|œšB\P.mÓ¬8^0ÚÊŠm›“ÚZqô„dZØ«e!ÖÀF2Œ.œX­´v§æÓ–Ô.È}žBŒ»P`ÁxR>;mÍtÙ+¶q¤$qr> stream xÚµXK“ä4 ¾ó+rLª&^[¶åäÀªXŠÇ-úÆpZŠÅöü{,Yò#“ô ;KmÍvw,ë­OR¦“›lþç¦SJvzÿaúú6½y'gÍn÷éöû„`N+F“âtûí—ùÑ,äÏ`}„üGŸaYm~1Ÿ¸G¶P„TžÅð@$n.Çõ(bþ£\JÅ—2V"Ò?úÎn°Èü4É'SØžÂå».­E4«ÀL@ºÎꈳÃÇ¥WýÃ,7"©µüzû~ZšÝço¢:ˆI@,pÅ>²‚žU½XûµWSýinÔìäÅÃqöì„T}ÎN”»qÝW~‡ÎUÑ)KG¤ÞD:gÒ¥ JÅËÕMƒÊ¤GDU·*5È^³£ÃØ^_l-a^Vï9 bq±L©Ë¦âý7o±ËÕ„Æn™71}/ç۔̞è4˜œæÞìÈç·“ûhr¦WŠ„¢¯†Ýx¤SÕò…©Jþ÷žj%=ØÕ ‘ŠÊ¯Öˆh&2w4% Ón¶CB–8Fi%|8—R+-Ê«rª'jK´-a5ÈUŠh’òQ2›¤2´p9]TV¬u5æn¨ü£Æ^!JÝŠtYxëu¡~jAê'¼ƒ=ìÌ”º$ON ½@…¤…`õ&'>hÑSÐÅ©Rò£ ¢â ‘‡E¦"a¡TWeçdq7$I’³¾’܃¶¤ã_;“38£Ü«’`ÕÖaUÇe9/Á*."¬*‚¢ÕoÄ3µi%ÍìS«^§öjhn_ça (…F‘Õt»­¤ÄÞW4è“ ·ZˆÕ$èè+­zš(Cù‹]mkZêíPuDlîR|V„ I¿¨ôxQ4hßB Bi/ëi›@®È58÷\S|-­WdW¿lU·|+Ž/Ò}wÏŽµ¹im}…’"…Ê+p?T?S(çRg­…êªz_dÛ: ¯îª%-=Ð¥ÚFÝ ¦ÖHá¤Mn&†®“j-rRžé…ò;(å.žaœÔ8†§8™ÇR"'G»Ô¥´B§„)QÀ€­vcU k̽չ̀;4 «ù”¯ºí?Íz­cx°ŠÕjuj¥¤ãRtŽ]±Š¤ÑÊ»½Ï 8(JñQWU[t°,¼ïu5‘Ι9”kÐr½@÷:‰†0?3‰ƒ: ’ŒÂ»·Q*³:(Ò šëØX ¥ Ï 9¤*ZgÐãÚMAî(6¤1E "ŒmÚœ}u÷Ï“à§6µ6‡ºùþøÏÜË.š:äâïóÛ¯$><ÃhÖˇÿucâiû8@iEHã¬jà FðêXT¼¿´^µöë”RzóÝ\«3mšÇäåîé•ZãΚÕûÏe£¦Y4 ¥«çõX8À0Ñ´É¥p´—ÀtÔæÎ xÚéûÍ=ûA;HYÀAÍåâýUŸIÞ(£»ƒ)î½P(GŠŠw0M̹€19Ç{ ÖºN·èº%³Xaþ¤æ/WÃYÎëˆÿÍmú8™°oÓ_6hwŽÖx˜>L°9³ÅúàÏéçé‘{&‘wU´ÑX—©Ý¶ØëƒBÍo¢Ü6Åç¥ v…%¯˜D˜¾Q AMޛɣ©o%f!ÛrŽìrþ»vœ z9þcY‘¶kí Ÿ<ʯNÉèçT徟\ßÛõ/—5Ìö$ÀcƒZû ž«M/T0Eç„Þ æ£!WôÌ7“Ôh¹š)mkqî—ÄP¶½'›ŒŽ·Ê uüıÇ!Œ}¯ßÝ›ôLëßî´~mŠ¢ê Ú½´=‰£‹Æó ‘íA܈‡Y1$˜=”€ÄnbÔ x?y»}Îǰ»Wú¸qP¼ÆÊRò½?Ë—ùÓ(ù½îÓWCî EÁa-VAÛ-^Ÿ¥ò'/'“×}9‰µéɰYèÞ0UˆZj8@øe‚Þ«ox n•~RÇEÔ%4˜w8ÈØì’M›×»/þV³ endstream endobj 55 0 obj <> stream xÚÅVyp××Zö¾ŒK숪 ÕRf:tšC ±ÉI¡C1à˜œ&>ˆmaò!tY–|[’õí®îÃ:,°-Û|4à$pØ@ I4iš¶2%CsÐ'ºÌЕÚL 3í_i¿ùÍÎû¾÷{¿÷Kˆ’“EAÌÙ°jMN^ÎÃÏ­Þ˜»$ëÑìø»e±E¢XfRl±8öÝd~%q^ʪ¿ç¤ü@$"ÔÄíúïÄíÓs+ú‰`f9ÓEs bfƼ-ÊZ‘³ñ¥R…¦Áâtì?qi‹¼¢bÉâÅK—Þe%@v,¿ ²'À²øY<– ÷¬„{VÂ=;áž½$M€ÄîÙ‰ÈÙ‰ÈË^˳/ZºªJQ­V•)ççV•–)+ço¬Rl©ü·—ÂÙÉGDçEŸŠ¯ÍЉî"¤fÂB´V†` ްvÂA8 á&<„—ð~¢C$I¢$ÑQ”XFè’¤IœX*¾š\›üeŠ)å:ù2y=‡NR ©Ó3ŠgÜHÃ/$<¸YR„¹ƒ(íNÒ•–›LôÖ¬(çMâË“âã·VHjºÑž¨¹Œ†k+´R·9mL‹€ä Ë™¶k¢5demˆãó"pXà¤z}ν2ø¬^ p%ÙÙî1Auû(Úª°l—ÕÆ]•ä¥m? NÆ*&wZãAFú¹½²H”L»C¼ìônMl¥6ý›#øÅw¶œÉ¸6[%1QOÔRF󗼯òЬûÑ)ÛÕ¸ ïÍ-cÝ6/ëᨌ¿ŽúvÃ!*u{`k°Œ)êI¾@ò™qíìáâu9¹%èRÝâÞGãÜd<íâ"}²Cd/D­Ý!@—!T-ÐÎ}RõŠL ³Ûlž¢C|}D"öP¯ì‰E¾œ•t˜l¤¤Å:ùùšØŸ´DLtDŒÓã1ü¨/j)¢!Ûœ¹ý)cÅö‚RƒÑdáǯ–†Iî {¶··¯w†%7“¯Ã‘fïZG%§`+©0iÄ«Sô¤¢š;Hã 4q¾!ë@üìÛR‰Úh®“ñùdc²Ü~¯Ã}æ3KàK*b ÷ÉþLv£ÕRüeá^¡Íj¢¦ÎøZ‡&ö‚–˜Äõãâ/p£nëùbóu>…Ÿ¹B0 .ò3pjå"/À¹±ÈE†c8°Qv g–Õƒ¹º­A]\Xñ"TÂv¯:²ñMÓ‡pb‚öòÈ_~ïCÿÓŽ<¶ÁZÏ6P‚* Yñ+Gï£l^°m¯aGiÖív;œ#G¥NŽE&ãÃÿ#üý$U;åm[¡Ê]ÊÝTO$ÐCgŒEê:Õ*}íε—•o¿}¥ë\·>¬RÕit5]õ]²‰ùÖ}”Ì ²š(¥ ð\W8 „;OíSa[xK]'{F Í_Ae «üžšÇœRU0-Ì;~H<ßÛ‹úúÚKh~å+k¶®‹‚hõØë4t3=ƒ·I½[CååÙû3‡3¹®Þc @çYßžák¿¹6ø¹Ýçðr>†ÿFZ®o}Q°6X‡”5ÜP|ï}»cÂ}‹X}k}Oæóâ-<âŽ%KëÙ”oç}É‘ûæ½)U6¡£dã>mk¯[{¿¼ ¢hOÜy._"4³ÁóðÔÑãmônMŸÅ½b\Ë“ð©†_þæS Þêø!<ë NÁI[‰Sù¹2þ!$಺À—¼Ÿ] 8‚¶|cϸV0z¦ja“y½¼p§b«NO@ñ‡-¨v?øÛýÔyª)ú‚L G Oææ†ú¡Ÿéƒ„ÚCÐafØzŠ¿Šv47üê>×*ôÓ磱¯´„0 üâá˜0´üèÕns!}»A«0­Z(yu{¥¬¡çEõdµŠ üüî‚qÕøNýNÆÉ4üqË– ëœ:N›a}¥ºÈúžwðmÓªR~ÆÚôìñ7iœ…ÀkÆ5~áíñÏGùô'dßnæi™‡cøk‰™11f 4F½V2D"¡@ÏO¾¹†O_ÅÏžÏÏøhžCOÂÉÃá3,ÇØ…îÉ!›™±ý –fõæ¢Òç@ {­oípíÇð.u9ŠÄI²Cp¸2\H}k@¸ôˆx@º‰ÏL “ì0óÖ®®Î®[?PûÈ(£«¥ù j“FaÑZ´BTª›ƒUH®ˆ§Ö 3QÙ>rõv>Š«ÌaƒŸlâ×hn¥j‰`ü"=è¸(]øÚÂÑ…l«³ šA_WÕR«Ë¯Z¹^ˆ«wülÀªÓÐéŒFmјrDvÞë?„3ŽâôÃøÐÈä):Æ<#êh44L†6ãÎ ;7¨6hò¥¦FS£¥²’­}†Þ¦^Չ㪆!©Ùmvƒ‡ x;†¦Ëú&eùgº½ÿß;ãn=uï‚™^õ>Òµk+emB˜ ÊÛ+€Rëì{ãéÙïê8ù?.Ž×ÜíÅÓ¼&&°ò-1Þ«%›žþ9?û&AúåÁFÔ¨gü4xC]_÷ޮz¥7çìê<ÿ9õ©ÕB•iL/O5íÿ ¿eótËOiXñYå)3…çù%jP[Õ@å>Â];?Þù1}œìb5Z:ÍŒ­ôaÛ!ù’Í{ŸIáLɤκ1óð,Ù’ÇI¹\¾õ΃ÿpp endstream endobj 57 0 obj <> stream xÚuU}PSWÏÈ{(´–4Ó¸cójwÛ­¶µø µîV-”ª-ˆUDåCP0 „|‘“/’@„„A± BÄZÊÔJ©nm¥»£kw]Wwu×íÇÜÐëN÷EáŸN;oæÎoÞœ{ïïœóûÝC°ÂÃYA,LKÝ´99ãÅ´-©[W¬Œ ý[\Ê .›|1,øT8ÞŠ¯,Ž0üñ4‹El}"´¾ðxhZȬ¬e̲àùÖ1Ÿ³ø¹åq’S÷–+j]Ùù+bcWÄÍ‚U±s`å,X»fÌŬŸq«çÀ«³ ~n{üÜöøUs`.8~îÀø¸Øå«6 ‹ËÄy%Ïl-:W"z&µH˜-úÉO&“èå¬XÖJV<ëk’5źÁú+q›u¸ö=“àã¬'XÖ"BKèˆzBOa Œ„‰0¢°6ÂÎâÌc¬y¬5¬Qb˼óÚÃö‡Ý 7Gð#ò#¾e²ï’Uä]j+u/òÄc?ß5yËÿ%i—ÄpΡ'ïr˵’ (¡ŽxÅ~¿ÏÓÍç´ûË|Gøœs:¨×ë€b¶Ü)–xf~å1Hb®"ûUÎ4ªœYÎÅ©z¬„)üt7Î@‰|¥¶‘îQœ!´X„öã>gZZ½(Ì~°”«·lp.Z.˜,g|½íÇú¼ý@¡Åµ8÷ez# µë‹ß­8˜/ÌJÍÆQ6´ºöÖ,à ^»ôp=FÆ.uóý¸õ4<—ðê[›6­ã•‹ËKËKÅGxêº:-TƒÆÀ ‚,¶­(c×ešödAˆê‹NëØcc£g?¹üÉ?¯ÂwŠYö9f-]õÚó|(j,?¡¦Ž»|4øªÜE¨AU?W®™Ç:c‡*QÇ€t˜smG·¸z2ñðæ·5q”’„%ÿ~ë¶Ž²³ï{EÒ0Rö‡C½òfY£ÌQe¯j’[)#É™÷M|Ø0IÙÉé¤+KÖ¾¼¹wÃÀ¾?eR¿Å»¸œ›`Ö[À —ÇΟï3Ìp@ ´M1Rp#©5ë3^ç¿ #ʯ)δ7ø÷ÊÔ{Ÿ^ü"kR÷ff‰´õZ-Sz=[ ¥yãîã¼Âv_3È$1ïÚWk ”î’G{¸"” ‹s›{ip48Ìη•ùìæþ6¦;r¶ 5¦Úöí<›ØVj›TæZ¨£D{ôÅ|jˆI1ˆ ÕN…SãѸQú›hgJ×´é|å µª¾¦®Œ·oKÂÛ’ñ6ù^IÎï™sw *.¢Ð DáýÀ5f"˜þÒÁÖ/ÃÎÌlàŠŽ“Ç{´ù4¨ôjPSjÉ”ªlæÊ¹7Ã>E‚§,2›¬A¶è#¼ô<~a/‘IƒÕÐ TÐE¾×ÓÐÃw€CßT¯&e:IÎyp2¢žs‚'%§e¦¦¦3¹›$¾™õ>½$æƒÛÁü06øq&‹_«ÄÏâ_Ρp Ç»‘íD\”Œ’ 70mÃ{øœ!5hZEð Šë"Í÷3Q‘SLs»š{ìGá&\Þ>°®+Íž Ûsá¼â@µ®ª¾ 0 ÑR9ZPïÖ{êݳ2U¶ËÁç<1§?GÙ“W½œ‘ï‚áÜŽ“g‹ðÓ´’´¿qýÈŒÁä±–óLá8rSfoÁœ‚ã'̃ԕ² R¤É*<¬:Ýɇ&C4Qˆ&ä`ÐÕç^MY—÷;‘»²£ÃåöuJ[Kù(s¸/‘œ‘Ä})‰y»zÎòáoºîh66ë›MsŽö—Kb¾D;®¤ɹÝÜÄ•zÉn¿6‹Ægɼʺí| ²ŸÀ%gße‹Ó䄘Zvr¯µÑÜhl4Qœû§œ£]0Cé}‡ì¢F¡AÔj¼Ÿû_6çögƒ{SSRs·Ño²KMZôP(9qIp™Z½&êc6çþȸø-kä»h†ÎÀ“Ï>¤C|3Öõ³DjÁ˜Àes›Ûà$ôË:…}9æ4xÒô)y™%‚üŠ<ˆ‡¬/뾨o„&}#õ(qœ@¯x‚/y F`-ÓaÝÁ®¨ìéÖeÓ²Bé©@Eå ë ùU"$ ”±‹Ž˜OÐôFgöù²aX„¢o!ÍGáq( GÓ;`_ñÁ\jŠD­XÍÕ$•nH:(WUje@en>K£×Hpêà¤>ültâ~æmá3SC­WSäÅ”ä/Ñ7†þ¤¸Ìˆ50#V\!—¸e^Ÿ§µëÚŠc)8z ŽÀ&¿fJ´ž‚‰KÌëÏLNÊLêÍZ£ärRºsW^PK¡ׯù…Óð~EGÁœ¹|Á§<:4ÖÇ´½¯Šð²ýÆÑv¿Ç{ÌÜ ÔQ¶ÏZ]FãqJÔ’BXÇ<ã@IP¯§€Ì)´ ÓhœôZ>þQö§Ð+µà¨‡2_’yx÷¼ßüAB´…De#{Á­mË:‹‰9Œ s]C5S^-©-‘VJ¤ûDo§B9ÔØ+ì”l7¶6ƒ—j—»ÊÊdrñî÷‹ùß@úMçDÿ­þ¿÷ßjâµöŽM寱R²ÇUZJC¹Bª’N(Þ(HPø•]Jñ'ÅK/êì;Ø) ié8fp3;ÈGü)¿%D¯‰—À_Ð!ðî4U5Êœ JOÖ(k«”ŠìtÞÝY™Iz&õ²Ü\Û .èp¹š]n¿·ÓígÄöB¿ CШh“B ¥!A&QV†â3> stream xÚcd`aa`ddäuöttöóÖvö Ž´ Øæþó—aYøs>놲Œ?ä˜~È3ÿg‘{èÅòŸ‡I–‘AH2üæ‘_@¤:Hø®+ÐD‘ƶ©‰Å%©E™ÅÙ¹‰%ÆzFÎù•E™é% Éš †––æ: F– ޹@¥É‰y ¾@Å©@@NŽBp~rfjI¥‚†MFII•¾~yy¹^bn±^~Qº¦ŽByfI†BPjqjQYjŠ‚[~^‰‚_bnªØ#z`Ò9?· èßü”Ô¢<  ™˜®]ÆØÎÀÌÈÈ¢yýGßÏsßËw2>ù)ÍüÓÿ{¹èì…Ý‹•vWËÿ¹ÈV]Ú]R²°{¶<ßåküšÏø½á(óÃï¢SZûº'tsÌž9c®|÷¼ÆþšI«Š§EÍÿÎy@brß¼)“û¦Nì›Ú=…czë¼\¹ß*š3¿kôÎé\’×-YÙ][ÓWËQÏ>ó·æoÉçM;ºÛº%«kë*å»+¦¶Ïj9—³¸aOùoÎ0‰æŽŠ¦æŽÆÖŽÆî&ŽÊ™u³å&w÷v/™ûý¶DÍoSÖò9M3fÌ™2_®{jûê®éík;6v¬ãà+^üÓ~Ûo¹éìr\ÌÓTÿópNâáêááÞɵ“{ç\ æýþPÏ3Ã+ endstream endobj 61 0 obj <> stream xÚÕWyxSeº?§iÏù½!N¹Ê9XÔQAYZ\X,ˆ,•Ò¢€Ý×Ц+]’6I³¼YÛ¤IwJhÓKE–ŽƒÌp‘ªƒŒ £Ã ÎÕ{,óÆ{ðñžÑÑ™û ÌøÏ<'ùž÷9É÷~ïû{ïòÑTh(EÓô˜…ËםމŸ¼ö™§ãfÌš5=ðn–?ŠòG‡øçJüãB…á̽Lþÿþ2lE…ÈÆŠ+ýÎèÀztŒ¸RŠËÝ[Â)>„¢©»()u/õ5•Š¢P˨5T•DeS…”’ÒSvªÚAuS{©#Ô ê õ{êÔÔõ-MÑè)[RÒÓgLŸþXtP˜{K˜9ó–0gvP˜¢‚BpלநéA!¸=jVPê‰ ê‰ ê‰ ê‰ ê‰ꉞ AÍÑAÍÑAÍÑAÍÑA…ÑA…sƒ çΚ>ufŒ<{kA~rÞÄ•ò¤ä¼œ‰O˳’&..ÎOÎIJNúÉ"úäQj†ä7ôÛÔ'a—FþEòŠQT¸ˆÿ8JFëh=m 4Ð&ÚL[h+m£ít ]K;h']G»h7]O7ÐtÝL·Ð­ôvºöP‘ †Pc¨uÔiZM¢¹,¹_2º%ôZØf2ÓÁ¾D6sØ—wµ /ñàˆö‘ Fž3êÐè”1óÆ\[¾Yºp\è(\rva«l&¸ÀŽú.äó¦~ÿõ"K–|ê¿(Kdàõ@¹¾K˜èÛ/Üãÿ VS ØI}umW Eù…•±y«´Ï¹¥ÃüÐODZ¸GIõ¿.óîðòÉá§çñJVûè‚§V._·fõÚ¸Ujµ¡T¤Ð?õbJX2£}ÙôB(ô PždŽ8zðøÞwŽ_<C#„qoLš&°±·t*ºûvtv÷Éw¤p7OV½â_„ é=á0â~â¨ûq¼ôU¼ÏNÖÑq ~c¯d­âÕ,¬ÌrQ¹B·ÁyDËšUuàŸZS-VfôV¶eé;mYæMBžSO{€[I®x/1±=Ö;¡º ;SmDͼœ›“"„âÄì»à.Ï<9ÍI¤§Ît|´¾$_ Ã{g=.H’&§íÌÙ½»ÝÛؙۣÁ!Çaýþ—‹Âñ$†EI/ûð1ú„añLÿdöEÿdÿ*Æ­³—qFêŠÒ_ …aüƒÂÄjNUäµZ™ôsÔáÙ0á¬JÉÆc#ÄP^í§q"Ž•ô~#Kº~52/ôGb;t©>·-·E1¾7~·øì‰°èjÕ !V_•aÌ¢JÄãýŒ”F%äA¡µ¼µt{DI{ñÎ’va ΋È÷)|…]¨À؈ö_Í)KX¿P‘ȶ è«xЖ«ÔÕ/~bñã‹Ò²Ò3Sr^ê¿e—ª/× KÖ…wbJ÷líCŽ•6âÚ€ÂJ›a’!²r’öYÍÒâeñy+–C×lk {Û»zyé‹»s:R“äò-KÆžã>…Þ÷ZN·ž©}×þ‘>á¸b¾W:‚û¯õ3?Ïÿ 0þ«xþ¯÷Üʉj&íØ‡S²|á½×žÁPœ5ôFŸôCœâŸ*ë¨ñÚ;DRÍäÓYa¸°&W7 é‚SüqxÏÛü11ë_Í8ðºïuîdòv›&¯°@ëmà0‰ý|ñiá?8é¥å­šæ-êðµ{ºxØQÑP\ODŒɦ°Ë7Ä/ç¤_lÙØq˜‡+(m}¿æVšU÷øùNÔѾ}ø!ÉY?%ƒËÿùþ…¶K;ðÉTÀѤ†58t¶JÈ„ä²LMd¡a[sßKs÷ÁT²‚­Av%"¢1ü]œÆÃàÖwV¿¶©gmý:XS)ËÈ #;ÊÂÓ¯÷ôy<Ýu]ð $ÔÎ7™Š ˜(Xˆ7¬ÉNVd§”§@2$5äûr»a¯nO°tâ‹^œé ¿2„1×fcˆt¨Ë¿Z&gà2Õ‰¹Ö¬ßÆ —ÙÒ}1'ÒÍT$ ÷±oãÈzdE‹f÷m¬!Rÿž¦A7ü–|.Œu/æf é²+Œtè¤oÓ:2U¹……y…YÆl k™J4ð˜ŠÛXkuq¿e¤þ× b—-+]Ëòç˜:ý¿ðÒ_ I:ÿ± >¶ EGI5£R™ëy±òYÁBðÛä29¹L't½e{󬱿M¤Qáa¢ß/c‘0c³|þ»½á˜¶g I÷cäâN Û›ôE<<ªÆ=—±5ïE EL©ÖÇXöÛNty‰´xW{Ÿm·,æW0hØC¤ûrK–9G<©cK`”˜ÆW3••–[¦Y žcÁb´‰RS«e;WuF±¢íb¯/¿þ¨Ì̶¸Û]­‡Î×a|F\lk­…Cš©¯5”òÂU¶¬ÊPÎ ™JPUP!¡²Š‘¤‡†­ªîÁ8/Îï¢;‘ÁŠÏ$x?Èð-Æm­q!õÂUa  ëÊ6g¬Û²õx†“~ 9î,œ÷ù>2YÍÑ(G•M%öŒê\uyîËq °âvä ÷÷Á^â …}¶ïîíÞžÆn Ÿy&/àÅÃ?óñðM^Œö…ã§×ItÑ(ÛÓrÞ §ÉUa²c—©†¬ A[­1S ÅžR Uº*5Õ&èÈViÖ´r­`Üé¬ßùÚQ§Ø‘޾«\ó¤2–Ï`ª´ú*¥Mïâ»éçÇÿ ÌkYõÏ•­çਗ਼Š÷‰[c©ä´ŒR¯­z%Egù?Jjº?±ÕY\&œÜÜ×\a+·U˜ÈM¹† ×n‡nŸœ-*2Õòàô½Úèé9Òýz÷W³«©®ÙVk¯±:L¡ˆŸna+¡B )Úfiü$ r/Û-F‹Z,ô ÖhuÚu3WΉ}¬Z­Õ誌x8¢¹ÕÒúkþÊWpaøWC‹1']“þ׿¥?H_”m­‹až·†I϶¹Ý-Ð]ùé²ekNJJòßâáÒNûYbgûsv¦%å§gqPàÊ÷TþÔ»wÑ_]¾ˆj}¬êF&Ü©ç¿fÁf´ƒ 6§½Þév7ÔZ56­MÛ–Ñ•ØÔ•hÑÙµ %ùPÁea¯˜Í†ŠºmÛÅz¡­©®ÕØÅ ä÷‡Or!€ÀÑ€f]%e·–Æ%Å%Ç%|œmý;aTã=BxÀøpL훘X’¸.¸ @_ÒÚ¤/áX˜eœ¦˜_•)&¨VâP`np8š ™t(Úä9™q{³s8jñ!Û׿ýæ°¬¢[vÒXkk䆘F—¡„®°Òâò"}'"`RßqpFüÐ5S †Ò×öúÇýY²ûûZwÃÚb^¸ÀnM7är•Yø¬¯Š‘g˜;y~âÌhɨÏQØìÌw8óÇÛT6e½‘˜™vh|«¡«óíÎ3o„½¾¶ÞZo¾(+¹aiÅMKËÓX9Ë4e›¦¥<²iª^­Së«Ä ¤wèÄGq,"ãýÌ÷Ó~§i06Èá{Ýl‹â°qèöŠƒh’ò{*á Ü(¬`ÿ€Åì±tšQ[sË ÂFœÀ¶ü”9ÁQƒö‰uß)èðÇË„‘Ë@˜KÛ—ßr íDù›b§‰£Nã,Žo{3eoü¯´Æˆ#üh¡ùŸ!~H¸;J%U ¤p›¥é{.°à¶YëÌ£™:ÇM‚þ‹ô ´ùØ~|Èç¿§'¼ c"‡ÐŠl`ÀY%Klg¥_¶y üõfñÕâD4ô/Æ LoNÑ!8 ´øMÇ«îÃp˜`Øbd„)ÜZˆ/ÞœNŽ a¬?T0É´1y‘“`lnÏÛ£ÓKL0T³¶®Á¾Ã@þÒ*Œ[*NÚ 1jI°GŠvл‘• àŸ.+UV–C!‘·ætsv¦·¹Ãû'aœ)…70«áùòSÖoÞº–»2ïåá½NßiKÝ µÄ¡6kÄ»F1˜Ë4Ê‚„— @zñ# ûЉÃp,ßí:.²æ¢© «qž8wu£x}9×'†H%Ìéþöþ‡kgœæêªÞ¥JƒRl ùP¸bdá1+Ê&Q»ªÒÜÈãÅ Ø«ÍÁíç«^MK.‘žk•›7€üƈ5/0b-ÊøLHðù?ÞEo¿*i °ÂÃÖƒÛX«­W5Æ»å' <°’Yg?(KsÕ¥²Ÿ_QMtŒ *-*K£»Ñ^â+ØžÊeiË !—¬yC~ûìûØwæ$Þsïך{«ÛÙèö˜Z93[Î6A‡Î²-ÐpÊ Ò*ós–É—f.ÏÌ~/cPq$Â` „Џ<¦ν+pëXÿ=KP_.§ãü/cé·x"pñ°R¡½MŸÍ lªGîNóæ¡“„±ÂýÈF£ŒïƒŽúNV²ÒoE2iE2­d:ó;ÊûÄ´#Ïá#8væ×Â#|È+Ró v‹<2®+e.N»ÏÜÓR×VÓD*ôÀ¡\[ÙÍ/ÈÓ¸yðÒ êŒÞ nƒ›øeÚ'Óž $%®óUÙÚžOk¨…Æio0îû'âœú¶³óÏb”M p NV¶<ûÏŽ³Úõ£c®° Ôë•"<Á(µböâÿm%»Ywg{1áÇÿ0’ó³XȇBwqǦӕ¢•ÝÛˆ°äg*´Û[Ä+ü‚Í~xÛ†MêÃ=Ülcà¯Î¬”hºO™‚˜® |nÖo>¼Sƒþôfþ}ôî|Ç-O~ÄÛöf Û ¯@WÉ!¹e™uÃÏJŸÓÁE_Ä›|¸¶ zéSbwŒ¿,A*dò”œÔœÔŒ-¹™ uj€0¥¾r60]èíÄÌ‚Ëãq5µuz:<Í;"lv‹]ÔØ%Ìg*Šo°Ly“eÚ; j » Ãs9™eyÙJžú:ý‡SÛdË˜Õ ­à¡ËæÛ_·Óî5íòSgÖVò£T.ÿó|Éêu1B‚åî’ÔÍ1¬fÄ]¦ÿºëðpnNFÜwãþŠ@”G endstream endobj 63 0 obj <> stream xÚÍz xSeÚv¥ç͆Œ…ÑsDGÅdQ‘EöEö­-K·tK›toš=yÒ¬M÷6i“¦M÷Ò…²Ê*( "(È(¢#ê¨8o˜—ï›ÿMÛà8Ž3þ×õý×ÿ]í•ë%=çYïç~žç(ÁÀŠ¢F,›µzùìåO¯œ¿bñ„ñÓ^|7É¿Xà_2À¿4ÄÿÀ@¼ ¿ÿ`híßf‡>$„Ì¿Ÿ|8><ðÙ8‚| ž"O¼0@@ îŒ<$x\0N0U0Kðº`¥`£`» A ÈzMP.ðšÝ‚7'ç >|#ø«à¿)†A¢¡ž¦&QÓ©ùÔRj-AÅR*›RS&ª˜rQ>jµ:F ®R_oo‹D?•‘±#&fÂøñ¦õžz÷¾Ç&û{È®º¨RäI˜a§GÌ8Cú·l™KöÝ1á9tîŽB”£Éååááxøz<ðK€ŸÀ¯£Çð³Îª±k5YÌ<%¹ä%£!1h q€^lDKÐ4Âb)¶C!+l³hÌNxÎzƒØ~mémÊ8r’¨Òê :ÐÜ“îÈû+kįžø™X<é)C!Rñl^¥È¨‚ÀÏ’”å‘[t:¥Ô¬Ò¢3seàn)ªòt”ì.Å™5œð“¸Œ”ä·¬–/‡›ÃÁCËŽQEH/Z*1}ª¥ß'<„øN”¨ÍI…46µ<©±¡Êãá„®š,o'tèð›Gž{û“³–X;ƒ†ýᘧÆOÿCRib‹×åòº3Ý œ4MЙ÷Î0OXç÷³o¢y×_ûJøå_ýE¾Î5á(ìŽ1ÍcU ,J}eQZRþâ"±ŠB½+¢‹¡ØX¬ðÆ×Ð4Å8›U2³Ÿ}Ž{ –5Æa éZoYîLO²‰UÓÛs’’0…B×Þ@¿û…ððŤO¦™Š,Åæ" +¼ü–oß xýbì¾iÓÇFNH¨JóºÝ•uMÉ¥ñÜOÙ@/úü’ƒç…=uè%ªz–ŽŠÑoá2haº `„=5$£¼´ò r`ãÄ–vþæw¾'ü+0-`e‹t69's%;æcz:8È•Éå j£4¬×'BZÿ Ð»ƒ˜þÕúr!î²OFݪC9×B® á"‹Áj°[[åô¸Ó«S’¥éâqÇßFC¾º…†~÷:„Gð z“>*=.ŽEL½¢^SïÂÛîƒG,«llc°hL$zzCæÖܵ°¢ £Ê4j“ÆH¾Ô€Nkаø£,P:¸"°WØõM]•»5Ó]††¥;KwDÂ6˜£~iZd–*K— `á¡ÌÓýÉ•Öù©F±$¿Ÿ „O_ú‘}$2ÐpÓrûÂùúºÖò]Ð-òªDV’,O-—Öò5à,7ºYóÞÒÖ×ñËOãExxp ~‰VU+Ü7¼G»Û²ÂkÛ wC‹Ì@ñ}ÜRxc[úbÖˆ";sÙwëGî,4δ¼Qä‡}U‡`†SÓíÒo4—Àƒ#XRÿgïµ¾™÷iÈõ;ÓDqxK¨›¶ïÑïï&q¦kÀ]P,ZNozm툹Kÿ°!V±rÆ”V•] l}IM=_ÆR€ø³?v9p²ûŒÝaµA)[ÌL†ÅºGa9,³êê‚þÐÚ°Î}²nTÛ%Ý/¼–£/DffÌì¥0ž}ô‡Wo}‡¨sè>Ž‹ol–T$•¤V´žðœ:ïÁõ—N²²yô„ ¯?ÁÃÜ7—œgÇâu"á 0p˜á›‡Ž¶š ,f XÀ¦¶èº’ÂF² ^e_xeÝtnÌÜ—ÿ)Xí@TÈœý°åÈ©ËQS9X±aÍV‰VG~ ¯ ­*³h}ãbò$ä2ÿ¬™Ýø3áÊü³Égm}|v®ŸÏðµÿtIïßï±Ý€Cì·ÆzR_ß:Q§ÏH*ìáÑ™Ï_ÿRØÝ}g&á½@±Û\§‰âïV0¤RT„wÆjâ¸<󣓌0­ œ'|?úÚo›KL¥P Ÿ.:6Çn“Yd„œ+Œ¥¤Ú[ÎÔ;DâwqááE5ÛK£LQ„GºÒ!Ýìø šE{Á«wçIjXËØq³_ŠË„Lc&°ÓiY†Ùˣ㑅©/³Vs(ŒvŸƒ‹qÖ'WM|iÉ œœ%ïõLü’Ø\«”Þã CÜ5a[WÀŸ&¦©A»“µ!àq(*Žx"ïó$@é4¡ta’¼kèèsïïfê+ÌNÑôYxGÓð¼#Ök‰aÝtJ % {àçñL)ZÝtG@˜½ÉàZZا¬Ù§ÝÁ~-oŃðØ„ñòÍÀæÒIX@øá‚‹Í-¾}=Þ£ÏÀeõ4GŒ)ÚÝ+_F:!øQ1bK+ïobv5X8’ɈÁ þk°H›žf ±Á¤•rpðF¦ ¼²´°Qhb!Š Ý—­*(éâÐ ´ËÑüÝRÄW¨ *ƒ:'Oâb£ò¡Vb>w mt‡üçP‰ýo3ÈA’|‰zæ–-›7Í3,#fÜOK2LM<òÞ`š¡CïJ*K3ŠIù+ܨB¢` É ÎN“&Eéc€}Ð U¦š@ÂYCû¦æ(ó Ûº{¡°ÅºHæC7\è¤/Ì¿êó…~ïgБÍl7Ú Ü…á'jO€ ,ºso=Æ-‡5Ù£õz^g` tÄÉVaPªx¼ŽP©º˜«]ƒ¹ÜyëO{?öÒ‹'ð°pó«s2¤©! ØU´"ß àõŒQi×ÛIéZŒ&`÷ÑåPåVøåUfÁdvì”yÏpà±fé-­Ëâ%àUh´ ^ÃÀjÏê]Ѷ¾—Gú: A㣇y;£ù‡¾ûŠíƒK/,©5ÉÀDÿQØÔygº(é7Ôš0^ŒFØä&å¼ ´bMZ!l(.)µ9."ö2b?@ì±ëáöG±­ÔxW¾#^OäþR@o³$sD\<ÁX6Ò%ý?ƒ™°Â‡7Ht¡˜Kª§}Ф3§°:òrsTù³0û fgbvŤpen~ž*Çà×…·5XJ ŽŸ øïƒEù›Oêµ»­ßî\Èíµ;‰L[è%*ë]%E^§®®ÆœoSZæî»NQ†G)¬$Q›Â$ "\¦Ð¿xé(H4Çwd;s]9®EŸ/»¹è3½Ig"Äm+±[,»;wïÞÝùæþ=çH¡ábÆU•“ÁCJtrzæ3Ÿy~Ü8]bºL»¹jâ}Ï9™[‚fá'½wB|aÞïÑÓ.d¾&<ˆæ÷si‰±˜¸éÓìä3ÀCTx¸ Î}QŒŸžÑ «ÉöZ –ÀtásV×óÂÍuiÕ ‰i²ØE»V¼è§W+O´¢Áf4¼ c] ´›;a[e*&>®Ò—ê!ž½ÛÉFFë"9) ý›Síc~JúÒ‡Ú‚½vMØý›%íMTw¿Ö¼~­ Ö]<ªB×p«‹àÒèºð7 ±¥HÝ}H¤ûMiª×lã± _C*¦£ÉÔÅUÓÿp!q(ô™-2Ï©ƒ,ìÈWþø¯„=þÐ;oˆžÎ'ž‹í\’>æ±x&‚—£8´D‹ÑEX©žÄj¾w ½}»™dÔÍ€Õ`%ii¬)hæši² ©ª§ÚcL;MÁ ½¯;Þ\ü{Ym2ZâÏ&Ù ûžP[ F«˜j¨1”æ—ÉíY…ÙŸã'¾ÀO~†Ÿ´ÊË2A®ËHgf‹“¶J# bªÓÚlCø¦®ÚIø&É+õ$&¥¤ÅÏ8½â áb{ÐðND“ß.D»ŽUµž 0âj1S¿+;†×2úle–&g+f"1YÒv3[ReM+¾^þõò¯Ô9AÙw ªwAMàN–I»×{Ý¡ZtÅûÏ(˹r€&S‰çúGWnÃ5¸²qïüÎ%e3avÿ.¤pI[Q¬Mu…u€"Ï^t“†EùYQmc›« Ø í‹çó± ¦ñKÛ±pægâó| ½ß|¤µdk¤M‘uQ{ š›ÍÝìû’uŒ07I¯êðpPD‚\Ä"Žé=³_N<¨¾zòÀ[û>*8_Ùaï¬(ÞÏZ›Ö¤$˃47S“ LPˆUKs^ÍÞñêâJ†¸T†l2Hg£û˜Ç¢Á–ÐÆ}ß~‹îGƒ& ÿŽŸ ãצÌeáp‘ðƒ ÁÎ~TIzİ¿´Œ}šƒó±W³júEØpNõ¡þgk­ E°:Ã~<‹Þø`Õeáõþ9"Y5SW«%à>ÀD¦iÞà¤ÈÈ\@tbyåÛ“š68X¡wéåJ8 {×y£Ëâ‹âŒqÀNÄ[E?ÐÂOï‰X²xiÔJ~>-1i‹ÁÇ¢×¢‘ T˜Ê«Mì Zè?x,uùì±ùQ<1cÏí'Œ.ÿ('õ—³!uÿR»Ê•ÈD$[»xtŒ©²Tz¸Óô»pHcÅ£ ÓÈÑÄØÇnÒ㇥hr¯$´¡M8û*š‚†$–3 õº(^Íàð,¼ Oá²ðB‚¦Ó Ÿ¯ÖÝnj&ÉM¢Á½kŽ-Á$.H ’³ÐB²<Ä'˜»y´Ÿé¬¶æœ ~ìn˜H’©ËäðzZmT›ÀŽŠR{ñþ ¥?ÀRÊ<ÕYÜ Ü ºÆ!OåñÒ'µØ^gUdÏHp¢™.ªþ*Rœ !kPŽuÑ‹Åñíêoñ04š ÈèÇZÕ —êµ<%bSÂzX ëw¥Ìì0ô@7ktŠ>ì¾yíÓÚ'æp„¿^Þ*è ¬Ä™ö@˜pjÕÈò¼¦TÂô4J•V³mmxÔÚmK·l‘JÓUb`¥è “‘e+硤°ÌVèm­k©k-./-sT”ç•å–ç9T%*Ècab59sI‚Ä®t&>ÙÔÍÇ@õ^¯ÇéÈ,Í.ΪÛYíÝiSfC.›«”r½¢×BšoçîÄÖĶÄÖmõ¥ ,¬‘4”¦šòâ§ŽœÖÉ,Ö…>–Ik­ȇ\y¶J©T†oݾ.zó¹B®ÈS²ht  Ùà»ê öqN,–¹˜z¯vOVG%ñf¶5D5lkÈ,M/É*SÚÃUvy”€Ãj)6}ð#‰v¢ù®0tñÒk ¿GåH!ꩼQï±·ðxë&.b´âlµN­VÖ¶|H¯'d®Ôå«ùÞ§Ÿ:–LøJ£¢Ð@ø¦ŒE&‡ëôq×[À¾y)sÞÒ…ñ«ùÕ´J¥SòF¥XÌ6ÑÂ/OÀ¥¬Â—Y3yfên%Ì)ËzG[d­É «šN¥ä!¾"¶ZÚ·_µ®^Z„ðîšÆUyæ\s®‘íƒ}°xPÔ¯ÕO’+ƒIŠ7¶óÆB»ÝjÛu ¼¡£aWC‡ÓSåu¹Y\ÉD¥èÖö^˜Æ$&›I¡èÇ;N’9!ÝÁ ¥Fµm]øÚ…ë_[½ˆE•Ls¹ãâ=3:âј°^[„ßü1 º.20‰yñ:1ăؔPì²U•€—^wzM²‘ÉNI™ý猞ã×=gÝ™îh>YŸ™ © -•ÖjÓ3¿Ðÿ%xï|Ž[07¬õ„=è¾€ÑULc½.’‡yš9ò¹ŠÕ™ã—Cd[ä…U$5lMVERJ¾$ss›¸›{ym\ð›KG0NÚDìYa[+ ­O"cDA«ñÍjwUu£¥ØºÖœ)ãñ!RÔ²X+LJÕè…´ÕÁýO‡!;Ue kÙãCŒÓ\QË5ÐÝÐ)/^i‘HŒ’Þ¹fR`®r´oqùïȨ*ÿLQ¦9ÖŒ¶Iu¯Õ.¨{­iz¸Ii“ƒ²2SÔYÒ5âÙ¯C&dÙrŠªLå*weW¦¥de¥nØ#îá.BÛÅÚ·ÑÃèOáÕoº®`¹ºÐI™t]¥4……>_§,M^&Y–±9\«Ð*t Ò픵yn¹'ùtâé”3Z»6ðN¶¡\œs“|~qÈ&£Z>BÊwòjjlâEÌ®ZýrÞ€7g4nªØ£ðýãÈ„Ãâ¡~…ñ]PçôÔ³?•AÏz‚1AXbnÿ©þOBŒŒûhØ·Ðp4p<)!¿6efÄÐÑp|ü®Bä`®‘}ð· öÆÚ¢X¬gÖ¯Þ¾›k>È>«-3”ëËX§A¤ž¶aÌsÀnÙÐÕÃ#=cïÚÛ@ à»}xÈ4ÒÓûçµ@øûê©úÎÎ…¼‚Q/Y· Øy´Ôà*çûKücÿÝyåꯡ²–9oþSYª.Oê˜g!Ó<J÷wÓ½*Ž&*”ŒfCÄŽMª}™pØ7ú¡ýþÐÀÔP«ÛÊãƒD¤6 2™4õÈlËÛ<ªcZŠŠß¹×˜nÒÿƒúšV¾-Ø¥kDÏ»ÃЕ+ÂËè JÁ‹Òç'Äæëóõr`UôRóöfÉQ}¡®˜üS­Ñ’cËÕ»Ó/·/™‡}‰hðíh8~ˆƒÊÄ N£QX=ÙLd¾\²™è*¾ÿÿeÌd@xWÄZèb£¹ÚRèÙ}À{Øëûž˜Ÿ™dÈà…=› ©~=°iËÔYkæ`³Þ‹\{¡ KŠtxÓ¶@áÎé•ÚE&ý¯qÈÐL¢¾açäÏ€9JqɘDqpœ²±ˆû‘¶bæ"ŠA!hà'dúa&¡Áx÷0L˜’1F¯Òé•ÀÞxCÔÉÀù’Ë—›Ëmå¦rØíqK”y¬…¹ºéó7IsSÕ©0ÖÉ¿f¸7 ¶¼Kh ÜE»‚É¢-A‰¢‰L–™±zÃŒz½k\Lz ”ñPTæt×w´tx;ív£µØS¤vú©(*Q·ŽxøKºˆb&á'TOμ·—G•‹ú_Ïo¼yþTÑÇ|7í,ÒDóÃd.ÿì2”XPê¡ñà )š1dmÈ`ãû¾|à>nâè7$²¶¿ü?w E™ endstream endobj 64 0 obj <> stream xÚ]PÁjÃ0 ½û+tìÃI ÝņKÀ‡´£iìæØJfXlã8‡üý7ô°ƒzzOÒåâ,¬‰@?ƒS FèÕ'7…Ðá`,É ÐFŽJYÒÊké/rD õ×åûÖ¾òºyöÖÞ«üûå¾x„b¯Å¹Y¦ˆ£°½Æ½­§8|h×áˆ]ƒÆ`쇖7 ifïqD!#e™Æå›”Ó8y©0H; aYV«ª’ Õÿz»¢ëÕ „ï+3;òSâîè¦Úü=í©9„uozBr´-7ŸòÎoªÒOmu endstream endobj 66 0 obj <> stream xÚmVitמA¶Œ1$Ah0áâhP³8)&Áì˜@p@Øò†%Ë–,Ë–—ÑjIW’%k÷"Y¶ð¾à°pÀ\b”Ä…œCK $iszRzèwè¡Ïð§íÉ]™ysß÷}sïýIÄÄ$I&fìÞ¼wû®WÓ226.M™º³úçøWߤ.–O°I$»`û}>Fxç˜Ç Ó^$rÓ3Sqáì©8cŽÄË8ÌŒçýóFŒ%æV¬4öNÜ¡¸/¦¯™Ž¨ÁÅñ‹YsâäsL„}-B»‰N_ã±%ˆá£¥É#ë¸9·€›Ÿ|iÍß…—a¢íËO™}EÃ@ö\hj0:Œ´Ìf³¡boX€*‚¯Ûih»×ÿŠoEØ(»Õ͵fSEŦÂ5û¶RékùËSS™l ¶H‡¯Ð0r½gOß8êoÀ=ÿ[ra›½’JdǹÌVô›z F3B>ž6ûöðe;Á^å±s|•pkòKvfï|E½†[þïÙkÓè78ì6Çg¨KÚr2÷Ü€/†Ož9Õ{nÂDî¹¼èXßÅq˜ ¸tn¿ÆÄXP åV­Óî´ø0Lšƒ¶ñámIÚî"¹·Ü.JµÃVH[‹Ï9Zà4ÚºýCyÎ"[–}›bmqNήô¼í@­‘Œ}Nƒ¡+È%ˆÜ™@ËQPcE[èDv#'ŽLVaBcaòôô^Ô3ÊC_±_ò[*Ú Tô ôD³íÙ4r(Ñšü'Ætb])·Éi¨€,³*Ln· ¸Làæß—N(º;ti[ Ǫa%Wçä K@îWµ\V[P&SA{B2:~úÊE†Ô­zweHíÚ~³CãT´Š‡à"„½ŽQÚOç©6¿±¡ÐõÖ“Þ¬5í€iÀŸæ›šÖÉä09Êêxh ó%á^kR6•y¡¨Hœ×fs»¹^ë36ÂÜöª@5¶+°C©Fï¶Øè>cƒ1ºáG.*ຸŽÚZ£jæUk›„Màñ¹½x§kL+z† èlCÓ.]w{ÀŽ¿s½Å¥-Nå¾*„×®®ÿg)õ§¾ÃÑÛ¨Z«ÍAƒ½ù¾£±Íýú¯÷€ºÞ±ë}.–ãs‰\2ˆºá!yç!íåw)Úe2…B&kWtuµ·w ñSnW+ZûD#<´ßÆ¿ZúaNayi±<\Ò'ôC ÞëÁ½c³e³Y«iX—¿¥°aðæfÊà¬sú¾ù Í&N¶ä´²ýaò6‹x“+Xßïjp‚òé<ŒÐŒW×å‚Ƥ7A-ÔºM>;u#`°ã² |ŸÁYëzA6Áÿ%Dj¾Ïév‚üz'ã|t5 PŒNÇРsƒ6ÂÙp¨6˜Œ ›Çxt>¡+À:©ƒ”Õþ&Ñ4ŸžS½ß\kÕ¨)£Óävô8:ûz’\ùt6­´+Ü¿Ëç~‰æ P}œ]ä~ZJºÛ\^­…rÆvᱎcÑËQü¦Â>-ÔÐ æ®Í“±Kê+Au£–âÔ6òÑt»—»›È¾ =“dÉÆ³øžA‡÷Pínù¨£eëÌ2éziB’¡ïâÐñ\±`‹EǽðhP Ë5kW¥Ô=á »n8ººov'$¹ý8…Êè ¼ºÜ®²×ÕƒÜv·}ªQ×=î(÷8yúb&xH?¹†ooP ëõ%½•±BUëÆ3vƒV]Iµ’»%¨ÝS§|jÉhÆMf£Åè¥û™×ßfÁA™´ˆ*Oå»"`÷øF>n< Ô`‡ô]¶rÓ+$…éYy9@vܤñL 5]ÆHÞb"¨ÿîÑ'F#ûžÇŠØ9| ž»ÕÕš*K%î5E êêh?:²ïÈ[Ü Ü¼)óY:¶úhÁú]xR§Ô0êW/âH\TÔ&ùÈ%Ž…ìï¹xáÄ臡š œJDg™È$ÿ8yê2ù~†®šbð|>cÓé…ærîÙGf3c1€fÞö“ù§…} 7¶ ùÇp'zu`Æþe­3WW¾£ÞŠ]K ½AÚmNgsºþÔ:qÅw‰‡|Ì÷(9ÐÖÖÔÛ<øäsTïPocÑúhˆøO»:!p4z‡êmÞ!pQ-Õž*̳Ī/P¯ßÏ¥ÕfZë²ß\Ôníð>î¼uøº¿Û„5|èÈž%¹ÜBÖ‹‹Ò 6»³)úíБ! uG¤·åè¹­Ál·ù™µÊÒ«»¼2 lçø¥S;ÓSvk÷ô?¼í*4 ÛFCQez.'Òdä‹÷ƒ”  D‘Vè¤:ÊÜUÒÒ’CY•Ÿœ‚ó™ÃåÏ̹Ôƒ‹ˆÒŠÖ¥Îb(mP*GÓÛµrE|'1îìžÇïÿ/ÑÙJö~}w}ÃSí´ 1êª,&}Q]…¡Ä 7Ê?àÒuUÞÞÔ{ÌI,â©æñþ»MÇê}þY;~8Ú©¸›‹Xª-1¨³çWlǦºì²ô÷¡¿¹³³fwíÞìÌ’‰, ×ðŽÊ›°Wý^ªG^¯Ujöî9™;.|îw¢XŒ_Â\sG?â¾F¢y·ùçǺ¢ƒ=`üË÷‘3P?U-!>WYL:éû*PÛXÕ¬n« µ6+Yer=46 §Ý:5fsããAÈЦ?ZåƒÃw`EšZ³t…`CzþvÜSOXa‹³»|mݽÐ^]TÖ¬jÑtáóÖz®Ouý”æF³AùλêB(‡ —ª¡ PU¯Â“\:3•XaÓ|¾’Fâ8±oº0>fE8aFCB¼-afOüĄ̈+!Ý™û¬p³_ endstream endobj 68 0 obj <> stream xÚ­UkTSW¾!{UDåz§ÐÇM:µ£¶JÇ*¶V‘Ö'H­ Dˆ¼!‘·DÞɆ ‚¼%‰•@…2 â»>¦jm«£Òjiµõ5è¹zø17XgÖ¬5ÿfÖºk¯uÎÝ÷;ßþö¾ßöö„@ ˜¸~U÷êµïûø­ñp·mÌÀúùÏs¸7îM÷–Ç ¹×ìß"ë>O&Ùâ“mñ]>ŒÏp&ìJ®uwŸãæîî铘¦Œ‰ŠVIfDÌ”xxyÍ›%ñtw÷’x+dʘˆðx‰_¸*Z¦Wñ ¹$0!"F¦J“Ìø8Z¥J\ðÁ)))náŠd·eÔ'3gIRbTÑ’5²d™r«,R²4!^%Y®IÆ8»EŸE¢Z%SJü"eÊxž+5Cð>á>n!NÄ A*Ov1žp$¦ÎML%âÄk„ áJ¼N°Äb%±šð'6SíaOl"ú¤ WpÎÎÛî'áá{ýƒZä(Z-zH~JTþ¸¹"'Îë/ ‚§„èœÇ€JÒëñä‡Í´äZ‚&¡)ÕUPzjg¡>ŸÝË>Çôl—…0Vâ‰Ç±Ã<éöÊ]@••êwŠÿ2xp+Ò3p]ƒ&®EþhÒÜ ÛÊ/,ÌChÒ~›qÏ,¼h þOÆÎÛ²A ET~ia» †¾>è#È® áÊéùîùFÔÓ‰œC§›ÒÔ"ªiƒ!²Ä¸µŠj !%R³XÜŠ[ɬTHIi€1âW¢,H5 ¡†uâŠÔ¦ç.&ÁÁAT>(ä6¡« Ü(¸ý­ô¾W]8øÃ’¤ÍnqK ÂG°¸Ô£kÑ¡WSú`¾7vßk¹´ã:üÂQø* Ÿ›ÓîkÎÀ0œ†óp±| Mø®Â ­p1­aÆ®@X¾°–iVeÎZ£Š?,\‡¥›×(ñ[!ê}>•i„ë·jÄ%' <ÔÑ&j´–Œ*Êö`ãä¢6ýèì¼mŽÓ,q¤GQe‡Øs Œ<²8÷ °»J3Í!úóô rGì™xèŠD7°vðþÀ3°ôõmU]MiMÑl®McÝž §€º{h—>ÚøñZ?¼Ǻh4üÛdŠáHÑ>´ÄA)*Pä…mÏÌË]ê1öê}W…¦íAã}ev¶"û£†=¡1¡æÖÞS—yynÍ9ñþŸù/Š5¥î·LûûC “µô]¬nªë¸ÚC ÙÚ€¤0EpL‘R—«KÖæA®.OÛ)zT£Ù õl·èVDz™øÍ¥ñaâM°¸>út[ŨöDC|r\V˜ûÏ+9ݽû˜å‡[¾×ß1¾Ô½náÂy{¯ñ#/æÏd”VãÍn•‹ºôGÁj=]¼”[Iome»øÎCËt.˜—½,ƒÍá'37Ÿq‘“Èlap‘qãÆ Gv¿!_zmйÿA°¥þ~Æ­CRMðzˆ 66eDESh=iÈoÍk Mº|·º¬hGžXÇ«ZP”’”²"@º3Ę«×ò{ÔvÈÍã>2 rkØP¢/-«¬ë¸ GÁ,-O«ÛR )úDƒrxrä–$),5ÇÒOëuz]%P­õæÆÆtslVtžtî¥÷½˜~†¨Ç÷-ãÌýqÏàÝN¾QC(rxå=Š\ÐM¦‘Dehrû¶¬ù¦*3B噦ºæŠƒgÂþ2OÅo`'‰éØ€¨OFÂ{¿ð_Òž÷±¥G—Á– )Áš€¿c|Aq&¿6­nÀnêzËÃ!¶ƒÅo÷ØA Ó£þÒÕËñ1r® N˜ï ¹Dî)Sa³#… EØ ´Õ… ”R‹7;˜EúºŠsÕU;Ë®C5/e„H“ñ1¨c=ð±X ïòÒ…> =»Ø#$×/(ÝSs»û«—3ŠþzÕóU÷«ºQS·ªŸþÍ㤌´¹ðK¨§Î^°^¹z~½ k"ƒý£)S&óMGßQ¸H {žtŸ¾ÀÛ…´’PkHev‡ÒœNÑOâç êíÇËGýÁg,´kzdÖTcÆ®UÔôpMZ¸/µW«]½¯÷šëóÕ §ZÎÿØû’Oûð{¸i¶6¬F‘CüàÑ&ŽÄÛÞ‘°é°®$ñKª»|½%¹V¡È‰\>°ùGÄ 'ô&Šã»€L˜üÚ“] Ai›B7‡ªÂa1…§ü4Ù³ô³³ÐeÝsŠÂ“?a2@ òsiÐ6¿ê5vìí?PÝÆ7¤5¦>´*®Ô¤Ôü˜÷æ°¼Ÿ"×NäÖ)8ñ|¶ð¹ºÁÔ¾²ÒÑû¢ß­³VÌÝÃ_0¿›l¦xôQæ+Så Ó˜Ò-(ÎÔ4ä1|Øäl½<Œæ]ºj¦ÇÐíï™Òˆ½á½@ÏÖÜŸP’Ê|MlaÏ…`…ƒQ‘7Öåµ4d…ÂÞ´o·¡I U­Òâ½m}•ü/Ôw2ÒS¼…¤ÛPôY‘¯bqŒr=„Q ~UžcùS.ÂáΆ^*Íg¦“³|bBƒ6·õ³pÜ:ˆ¼Ê('ÔÌ{­ƒM|êüÝÓÏ.Ò?£Ï¸Õ –hää…Šü 16‘¡XÎÊÉ–â’Æ¶6í—¼1+ wÓJ¹L‹Ò˜ W'&%š’,ûÌÆ^·oÇ@Õ&gdw Él݇ìЯ 6¾Bk+>R²·éèK´åè#_òWNœ?W¹n ‹³þ§¼õ ]3…I¸ y{V}¬!€¿‘ÃüÓeYw¼+Cy‡Ù”àGÑ7GHü¶­Xºïry^ß±£ÿÉîùÿï„^‘¸ö/=¿“h´‘°ª¸b!êDÙLó}M–ö®ÚÞbÊB&iº$Å%Û§ÉI£¶|d@Æömù~ ]>ÊÙÅF™+ÔÖVƲu+´[CŠmÙ—¡X×ëÿ3.³ñ„à€Ïµ[ÁUN6•XŠ›ö[µ6²j}^5Ô‚iëÙo¾ŸîR®©Î€|ÈÉÉLÔñ—osñ‰ÓÞƒºf[ê:ÞTû)'µ‰ó©Gñ•e&Þ\EZÆ_š`ªpt¼dpœÈŽ·Ÿgp‡nOý'd … endstream endobj 70 0 obj <> stream xÚm”}lçÇω97kY½:-½óZ:¥!P(ea•¢´Œ…&‚A»–I-!5yéœÛqœØ±¿ÞÝïîü;‰1!YlL³vh/Ú@ÕÔ?P7 (•¶¢U-«P$ŠVuöœ9³íIh'ÔõNúI÷Ü=§ïïóý>? ¥ÕRæžö~ñŽ7·¶þèéå…ÝVU¾u£ä[¥Kç3u›Cݶ.ãMV“Ånz͸§¯×flk7›Œ+ÒëWjsŸ¹Ðf²[û^3Yz‰Vô,µ‡zžj£öS‡4‡©n E=Fm ž ¶P[©ÔST#ÕBí£ª+( ¥¥|šcšÏ+¦*+ÿ®Í­Ú´êýœÂÕ”T(*·‹šw½7^ÕûL¼¿ ÃŽÑ dY|“Æø~[ñýS­cÕÐÃnò6 Ùâ)p²ÎþÆé“gDù, |×\ݫְÐ3ªîÜ®j_=¸cŸZH­£}‡„”b¨¦´Šø×Eü«E ¾„ÿ¢ÿ‚þ0âìe!c!,øC¸'™4È)9ó6î1ˆ’œE¸”›ñïã:',ò9@ñ È‘ŸÙY;øÁ&õËœ i!™$=»CX1(ŸDÒø B rŸv‘ fÞ. fúQ°Ê@aç ÷©»Èª–Ͼn‹2DÿD1‘KÞÇû!…’þh€ñ¸:ë¨Zõ‡÷·¿Žû£/Í.*ïéÓ¿?9{EF©D, %ÆØ€ƒkjtût89¯ß’ìúaB ;ÕŠr‹A *9ÿq¬P«~ç«L³ ˜‡™àŠNÏ˃{yôÃÁ¨?ÅFfä+W'“ºG"“K{¥Û)šcðDeb~@ÉD/”?;E~jÉb$’%Jw`œžÇˆØ–›•ø"þ“·Ðx=Þô®ú¸ñ¢ªgÕëw$|®c¼ïY@6ï—Žå`Vʉèô§0ÇÅÅ– sÃËÁ0ŒHv‰—! Q)&F~PùÍÿ¢\Aø®µ‰whÛÁC.×OMuëfºFù7!ù¯_j”—–M] ú3ýEºçe,Á#Bˆ÷ >à‘;ÉŘqˆÄä\ï7ÜIÜ5Ú<ìmj“q~"<˜ ßIÑXö¼ýToô=/ ~¸ðV å“$œ÷Q@¯ƒœŠ,›‡KrÐÇt.s@ y ý¬•äp@z]G 1"§Ò£öbimQså£ÊÒ–ÿgfß»ËÿÐ ×üþ…äO«Ÿ„Ýêzuíî€ö´ž]b!+ç#SŸ)ë ÉE)ù> iȉBÆÉ:ÀÊ;ô<ý8 ü®ƒ¾ÎàÐà“†Ÿ¨]£‡Â.è¯U×,íÆÕ ^ø~¼ú4Ö½°¨Ü"þ”jõ‰D,i4îS>@€ Õ=!Ì!„xÑ3±Ì/;ñ;¼îƒ3¸†˜×D—/–¿/O­7 Çå(=GŽM,w÷"È$!zG™ pœ ðä"%¼ðõ¡T2WÔ}t ¾=VPØÖ/i>¹T¼\‰Ï—´ú“Î)Û@¯Õ<8圙;5;Ϩß+Wê_P™+ä‘ÚÃov¾}ó,6fR~9°<«ܘ­ñèÑ@O4ÏÂlüxf!•OåÇó 5$gÒ Eç:ÞxiS»jtûâáCF]LNnü6?h"êcaL3£¥I=RP®­hrÝÀ¶+•ÊV"*çÊYÍ}ŽIÇìü\aŽQM·ŸÒ»Ú·´\^\˜Œä!‰f‡3öÞ~Ké–w˜ €+ÞœÇºëø–ANK ˜Dxõ­ßmýJÇ8ˆr|rþÒùóçM§G{XåÈjìÓJsj|÷OÓê‘Ôj¦J»ó„nM\W%êªOW}P]ˆètøÚýÿã\‰Ä endstream endobj 72 0 obj <> stream xÚuPkL[e>§-íW`xÉ*³ölKæˆÊX†lD$8G™™& -i]/xzÆI;fI ”öm ½ØÂFs` YGÜbÊÌ…d2?¦3q¨ñ2]ŒÛ¯%KŒùN9uz€ßûñ=ßû¾y’çB A’dÉ+Ç_­¹íÅ–Û5úÍKƒýqׯ£Üù"„ݤ°G&ì• ¥ í½vÅŲ]A6>³‰ú§6qÏÓû$P´?K¨I²ð9ªòà‘Ì•U+ítÒïŸ6ZûÚÈÒÌÖldÇXúÍìÖÔg²š¬Ùb×b·°.½¾¶J¯?Ðâpmq¨ý½TM}}]%u@¯¯§šl4cé5Ú©#k¦mFVZ¬”ÁÑk¡Yµ¿Á̲‡««9Ž«2ÚœU¦ÿåŠJг°fª“vÒÌ ÝGµ:ì,uÌh£©íÌUÛ_‹Ã6pZrIu8úhÆ.%SÄNr7QIÔïII?9NÈ D7dI(ˆ bŠT‘Yµì¶ ã%¹4vgÉ»–ç^ÀnÍLxÞn]þ¥Û—†DweqÕ¬p™ß¦Ö ÷5ÉÉø$¤PÒ—ðhÇÀë÷ò+ât™Û7>>ðFG¦G…qªlj$ @ÉD"©ƒ„?êŽçy,¢yn[n†tù+Ê¡Á'ÊÂ?i¦£Ñ$àCôL,ÿž*;óCÇçÖ'>–æD(Ëó"pÞ FˇÞ¤6a˜Š!á²Øý¹¡Í Ö6 幤 ºŒ&ß=­¾£Džĵ3 O¤/<üêw\p=5 C b£‘@èíqÇ ÆSÁˆÏG¯¶ñ¶‹æOO¡Ï(]Û-¦·tÊ¥XYÇ¹ææ­Ìˆ£Ô0xµCA/gªnªK gGǃ0"E „á@(È{±¬û·C«"šðNS€IHé n»Óy eg»­|È“„„ö@(Á/?X€Kצ£‘ä4 á`8†¸„(»^ÿÇIŒü ÈÈ;¼é×—i¾ÙŽò‹âÛE˼iþ‹¥ÌÏ#áeÆþ±sÙÙuÊÆp’ü/ åKäÚœPúP:'&ñ¼æÄmÏ9ë‚áš!}¨ne¢ZT­‹r¬Òaܽÿù/7^M ]bÖzÖ\«€°úG,Ãj¬jÂrQ¥Uð’þ­#è#‹fùûõG¸Ð?7öÖT´®Õ‡ž«ƒ³Ì"{éØÏ¨õ©¥iŸ(vŸøû¯‡ßþú§îK¸fœ\¸`ýº•àŒ™Ý0ð$.ÊÊqm®G#ÕÎqàriT¹ÀÅóNkKœó¹Æ9¥ø|R¥-TÔñÅêXqa¨¸([˜-Êž/.–Þ|oçÿÖ"÷* endstream endobj 73 0 obj <> stream xÚ]Mk„0†ïùsÜRЉôcDhuÛ/WØkLF¨Iˆñ࿯‰ËzHxf2ïËäMŠº¬µò|:#ôÐ+-Nfv¡ÃAiÂRJøko1rK’âÄí;’cÙ^ê¯ûât¼0úО+ö ûmä¼X„ôZ×e³LÇZ÷²Œ$ß«ãäÝ»Wi:¼ ½'Ñ)=À®-šØifkqDí’> stream xÚ}’{LSwÇ·-íµ*›b.—¶Æ‰%¬¨Að >f6tN … $@K)`yÉÃÒöž{Ë£è!Â&þáâ²Çs8u›Q3ÿ1Ù–-¾–©‹ÙqNÍÎ-¿K¶{‘ýgÜsçÜó;÷s¾ç0D§# ÃÄoÜ¿kËöE¹yw-±«‘Ì*‹û(v$NZ@¤FZ¨‘lZ)Q—LÓ?KµÁT[ÿ¢b‰Y1q×f“x aH<áH*YFÖ‘×Hq’ ÒDä1‰1¬ÇáuU”¹öùrJ‹‹'oiqÉ„çô: ]Ï}RŸg*kò¬†¾©ðäY »öO…]û«ªË˾RwEQi•§Ìá·Û—¦Ûí¹n"Ãj+Lµ.ÉÊÊL³fØíYÖõå.oi¡£Âšçð•¸Ô«…Ž2ëwa©Ëç·ÚV©Ù‹×ÖÖ¦;Ê«ÒÝÞâ5©iÖÚR_‰õMW•Ë[ã*²nrWø¬[å.ëS1ÓŸ¾rÝåžjŸËkÍs¹¼ŠnqVÆFìÌ:í.UJ&Ä„žF`D&Ât0dº*¥Žt2ÉÌÍBM›æ–v½Ö­ÐÍ—Bñ±¹'•ƒÜôÈ1›Gµ±0÷¤ÞÝ‹]‰sÞ@ MÄK8RHk¾”ŒhÛ1á'4þŠDŒˆ"t°‡Bƒ¹Âó|Þ¶ÕTCs(¿”Žì¡çªèò6ºh&ÈÆy6.£÷¿£i÷iòƒù=mßl_7²<Ë"íÕJç¹±×M ß•fÓex¦¥a²íqk”ê€mlƒ ;ÚÅД½Aç\¢L¤—ÎÓ1s@^ó¶l¤6zs;MXK”ðáPBlKzÍ} ‚( ·—¯¡s¿‹#§ñܸ<Š+3ÙøØSÂü­ÀpÒ- f-®¦9w‘\DN{· ]I±-¸ÑOnœy€ ?F;Ø!^¨6ûI<õÔGšèV(aÇß1@.d,Þ•ïÜ[ÑØÊóP~¶ÿ²ã^ÆÍŒT+W°ã=È>KWaþ‚÷›D8 ì Y`€‚âÞ4ñºs‚ÃJGظØKƒœþ7ösÔj%£â›†º ×"ƶߔ®ã#©±»GmZT½¹~bRÁM ))t7M¢ý+è…}2 •ÕÐ" -l‘Ahî‚Ax®¸T¦¿ÁÅ^Uæ‚”Á±²‡›ÑKµØDW¢³a ØÃ/ÔÛ01å7GüøP®»& ãYlc ™¿ÑB‡ŸÖž÷ 8~ÖTà›:v2å*õ¢–6áJêìów´w„E^àEŽªk£6è¡·%çBé+>ÖÎö ÚülåIêOMüáÔ»S_€F ¼ÂÓÖJ*æË½t.£nzù`« ¬®HŸùèÄŠtD0SânLÂþŸñÂljœÄ"À•^”.ü'zJi˜<æzÏWZä+†J?¡t{B†-SÙ“<ÿŸÍÅçÆBw8Ý_gN÷H9›p&þçÕÍŸ·™ÊkÚS+éN`å?õR—ô{wTŒ@ç\:rð¼/6+I:­Ç—á^cOøë¶;u×ß:^uÏ©lö¸žÎÄSquê}Àó¡‚ýÐ, —$É}òã–ÐüÜæ0Ç×ÓsÔÌ0b™þY÷ŒÊ3ÓlÔùÝ3¦áí9ÿp&ø endstream endobj 77 0 obj <> stream xÚcd`aa`ddä ˆ Ôvö Ž4 ضÿóa5ü¹Œõ‡ ÃYÆrL?䙈³È=ôbùÏÃ$ËÀÀðGDþä‘_@¤:`Þ=‡cN͌ʪêº*¹îÎ)†=í= ý©=u¿•žJ4Ohíoîæ¨ª®)—ï.ŸÕ:¹}_Ù¾²ýª‰ù•Í5-µmÝåå³kæÈMîž3mú䙓×.œ1eÍ‚é“LïªmÏèªoÔ’¨š]7gî¬säº{šžvMèšÖ¾±k_ñâŸöKØ~+Ng—ãbž¦úŸ‡sW÷~®ýÜûðð1ï÷‡"^{»¤ endstream endobj 79 0 obj <> stream xÚÝYytS×™ÏÆï^–b!â$ä=š”„š@HÁ@„} ;66ÞdË–mÉ»-ÉZ¬O¶$oònË’-Yà ƒ1«4@BˤYdkC³œ\eg:W6JiʤÓùgæÌ‘üÎ=>÷~÷[ßï{b™aÖeǬܼiÝüùO¬]´fùÔYS§úÿ÷ŒïyÆ7?È· Øwÿ0ññ÷ãC>ø÷¹!3LСûüÏ¥£ýÏñcè“™L¬ c&1,3’Ë<Ì<Æ<ÅD0ó™¥ÌZf+Ã$3*¦)fʘ:ÆÅt0}Ìs†¹Ä¼ËÜ`n2ß1ÿÁ"v ûûûû ;—]Ä®d×°±¬2&):2-îÉ]YŠÈÝññÓ¦N6ëÎâéˆ;‹éS‹éÅ3E`ÏŒß3‹™Å{’gÎ|:°Hž<3 pf@àÌ€À™3##¦ÉÉÉÉÉÉÉɳgäÌ È™3+ gÖÌ©ONAž”’‘£˜°\£Hž°Fž™ü“2 ;n3‰4™ÎÌ`f3 ™—˜—ÙUL$ÏÈØSÌ›Ìyæ-öæÚý?0"Í"3œÁü‚ eF3a4îg¢90‰™Âü†™Æ, y°œYÁÙbÖÄkfKØRÖÂZY[Æ–³l%[ÅÚÙj¶†­eëØz¶md›ØfÖÁ¶°NÖŶ²m¬›õ°í¬—ÝÃDø-ˆ‘2yÌg4]° öx,xDðÎà[ÃzB²C~Ï-ãn¢çQ6ŽÀ ÷ŽÈqsdÔ¨E£>ý…3tzhñè§F·Ž9qŸ2lLØ×’º±Œ½$Ý.ýø5ã®Ý¿åþÃáëxþÁ°MèÖxO>ħ Cÿ<çð¤ÌÅÖ=RŽ.úWÖbÿ“˜¥ü÷<ûõ›Áäêiž>+³ @¼O ]/Îñy—W“Éâ(«Áf°¶Y­6ì)Íê*‘!£É, ÓÌé! Éh2Úf­,‡rlÓ[‹øb0A± ÿÝ=¤àÍàóô}q± Pè̬Р1´ÃÕ3 FĈ‹ÄP1T§+,-ÖÙte¼™³—45×T“1dø«dg¼¼’l§áúRUGï Üô°¬Nœ§$'Ua7ÈH…Kr,­—ÂâÌ—7m2Št ÃEez+_Î.{cëþš£p÷©Ï­JR%+’ZÒÚyÉÅ:¨±VUáP²ü,[E@ºœ´EC¢J¨Ø„ &Fª0*3@ŽS›ä{\Þ†®6e[o„b0úU b_M1{MmV] þÜ÷•T†ŽBgűz|»m‹)^ËÇËÈG^.rL9€7$Yúßd7Øòù(È.ÐlK^§Ùwd)ݾ$²*µ5¬°³¿& ?Ÿÿd?á|W¥ž}-€_=?G€e©óVdî.X_iPd5”™ð'¹üé¥ÉŸ|JXK[ãO”B©Éxos›Û›Þ"‹ÎI’ÿ’Œxå“[„{›ŒàbäÙ%{³ËUª{¥ÃZW…%ç::OÁ\Ô×&îŸxΤmÓZ2Ým-·;£E.PËMÆ»´Zß'Ó®°¾Ïˆá3É{d<¹&5qpÃöÅ™KžŽýŽ~耽ùÍ)XÏ¥fä$ ’›iõéwcãž·w,>!®§‰á1–¬áoÂû¿w|dm.q€“ gIˆ8š_kvg­Âf‘“–#8ÓöÕÕêÊ’ ¨„¿+Å‘°ëÐóšMÃy1Š _ôÄÑ7_ÕìÏFr‘<è[eJsÊ^ËIÓ »UåN¤Ù`ƒß*ñ÷Ã~>ÚGf,7{É{‰×Ë’ ŸîàžæJeûЯ1J¸Ý†¢t |ä› Ë|×P© ‘s…Ë5/Fnß¶åÓ zK—‘]q~: ×Ø\£4'C*Ö¸Iƒ\ƒ`mÞöúÌbd^HйŽf³ƒ'÷sá]c×ܺXK´5»99É¡ÿØ’_)½$ßí{ÜËžþÆ·øã`9'µ§vÇÖ®0—— d.›© Êpw»¹‹·y¹Œ!b’œ«‡zs=à]ºhM(‚Bªx!^½k¡8†ŸOlÿ0áŒúmx .Ùßéz£ÿʵã …&8Ä%ù¦¬:Àµ%åQ (7—C®4UðÙ²*-y×ë3< ©ÁëÄgĹâzq9ù•¸˜$ WáBó±sÔ¡Á6Òòa½I]ù<-;T›«w´ë¢…Ûíhg¬)†—ËÈa å›ò'$Y{2½ÜVnëÜÓÙÛÝjU—«Ë4{·„woìÞн±!5¼¼Ðž¹X¾Û”ÉËH…©@ YeÑ òôŽÕï­~oÝûÚJ]SÍèÔÁ'9rèÄ‹€½b¼ 9ó•ääåjÔµZ­Wˆó•ªŒL¥ª °° _ÉEtpoißêåhfh&h¨!AíÿÔŸ‡sæ„ú)õdqt¢\'‡dÀ󸌼 —àëAÐÙds”¸K=à¦Ê ³®ËMÎQñ|BÞø&¸÷ç]ÏíH³ˆš,A±’q§Œ‰#/ˆl—‰’j­´·ñW9Zzñ â Qé)±;Vj×ê[íRô’òZßû? 1WÞvK¶“P_¸´Íµ¿² ºÀ›Ù”Ô(7Ë g¡YšY°hc‚"5¢ðì¿È/ðgá×3PåÜ}ðmÇO ýòMH®‹‘%¤)½Ýš6ðôò'SŸå%)uÊ.Þe®khSÖ¤[1‰—NB/m^µˆ×r[­±ÐÿL¸Cæ‡*œz—ÜÛ÷ßÞK2éno&JN.¥£DÐnjÏmK=¼±j3¬„—w)×a§¹¸´u%,…e±iËL_†ÓXÿáäoi†w’oyôCrù‹…_Jníÿ¹4Í€#¶#®Óžƒ¯Áyø~ÂÉ©Õ ÖK½ K|¯»NËp~ÃÀ:׿–%´¿‰SÄÏ¥döš8±_ä­ù%…t3Wo¶8¬Õ—ÈËWȲ+diys•Ãæ0ß¾•¨Käó!o°CÑ€G£DYé~Á׎öíµíå©;MU~«æ#•Q#¦ß~³¨NW_Tÿ@ä­Md,ýn$cP·jëô–,xà'1!ŸþÓ°DsC÷9üMÉ6ìm*íäI ×T\k€d|»E%bù„»7ÿD¹ÿ5Tô×¹¹ýc—o¶ël;{úK’ý!Éú:˜Øo®£¹Mân]”‡R)æT㚢•¹[ÖDËÁ"XêZ2°ëÜækW @›¥ Ç ѺhÚ/³Ìyþx|êE9CTqg¬í ÐƒZKÛL­¥o”«?Ú=ÐÛzÖÚÅä‹kö½|pNÕ|‹´ 1ã´¿×¶ÞzSß=b¬8\z{6Z ‹ìÛöGv矓˜0=„%ëøoÏ–úf#$(Ê&>fVý`‘Y?Y|‘ÿ¿üƒú¹}¿vP…y=É×HÇuÉ­3~âY”ôÂé–+ÝûÏ]ú >hè«ì­­€³J°]mÖðùÅÙEyúiIóÖ>·VýHÑoMZêÄ"œLþ’WÑ”‰!ŸýšH“‚¯ž„N¦Ttœ°^JعJW¤Ó5Xró”øKiz×E‚æÿG—U<[¢ÿgƒqul¤‚RîX¯œÊÿ£©ìÅÕÁE¶:ÉTWØ÷WȆ÷V|(¹ÕN»„ÂÚ]†(AìC‘iÆ ¼‚T¢ $¬† Êöͧ:wYq ’øœ%Ÿµ›_…¾Ý®¸†]õ;Í‘€çŠ‘Òï9É­×D­´H·j}Â:À/pÊR]%´c²dù‚KMs)>C‘õè뙫<ªKhË;ÓÑgq”Ôaß]‘t{$E$Ýþô¢CÆÅ%Y ä(j.«máÇyÀkrfw¥Y—C%¥…$‚’Ò Ùÿ6Cœ $3\¾1.–ìðéW‚‰Ä/»y<ÆXt 7é±éÅáiâbñIÈW†»9ë!x}¯·Í¹¯¤ƒº_łӯÆeò’äÒd*>›¬ Iãäþ2>€8KOð.$N¹=Zš‘mÈæÅœ^[R&@y}myÕÙë6ò ¼‡•UNþ3®¥²0]O#ЃŽ^Mm?;æ¬ÚMâœd®‹uß †‹Á‘l)9ÊÙ­¶*rßsø¥:…þ‰£oN  —áícMÍ¥f Xp™Þ¦å³À”¤ÎK‹Üœ¼p·±d[gÆáÌÞâ~èÃf§Ô|Á}õí–ò?3ÆíyzŽp‡*Üñ¸ï¡Ë’î^ßóÒ tίØUWP—Û ÎIÏTfeDnÚ½vÛ¶Œ ¥VFûå` NÐ<æàòUÖ:ª«jm=‡u P¼÷$÷€OF E ï„ìRiÈûœ$åcˆ¤Û¥DÉ)–^á&×™öJ;=Òµñð¶ž6MU.äã•>ߌl¡]h¬ùfɳ™Í9-ç»þí Ê6\â³ T©·h¹äååètMøÚ«£ÖîÀD˜0tÀA’…ÆYÜ‚ÒE r·v âD”àHvÉZ) iÍÚòp-ÎàPn±TZ± -6† %# H´“Ìw™Taäý÷^øPò9é ZiÓ‡Õt0ý‹8Ѿ”O„xcR^Q±–ÎúXrU™. ž…&­F˜@kÖTã:Ý@³ÍŽ%Ÿ»Ž¬¡£ó±ò°qµl«/áŠ4FMaUq…`«ÙJÅ|üú×úIó^’?'¬…Åõ¹g ÕVG•j(ÒT“èPöÄ hÁu aµ•$Þè\]‡’=Ð[WHÜI¿û^U”ICÒ?È䙜<©´S0WT”Ûl}'8x¢ÙÕÔêpbÑŠd…Kþnw—¤°ìHß„3i¹Ûq‚I£Ñêt;7lÛ°cƒR¡JÍHÃÄŠ¼Uö ¼ÿÕÏ]šîŒ#ÂõúR šÿõîÚý?T0KM(UŸjJH5§Zë*jj K:ÛÒ]r™*EñÂW¹¯ÒVòÇ&Ëy\Š< GŠ<#-…UUfcÑO<ÿÝ埯ÿåJR5·Më x6„‡’~2Ú¯o ò¸ ±B‚†eÚÚå¹/…<ȧ·Ô¶4:òšä骜”û’ ß‚Lµ]±+(9M¥uÎR|“sU*qI2‡:ºw`üÑ1,Ïì2*}“¨A^_ðIÿÞ;Z¸ 1‚˜Ž rí¼2.s'íAË]hg|ãk‚™¬ŒoŠ®‹{`ßôž§{¦cI¦EcQS2VÂ5”4©öö|²ï“Þ­ÕeÕ–j³øI¸¤?FnÜL•¹H•™üYŽRr´¹‰scŸK˜[˜œŸ+ßöýæïwF[oªM»L2ûåPú½gúæÒ0²;“§Xö PFQ׆Éx'ŽG 3û»üÎxØñw›ï™½ín#õãBt?=ä»;¼£•BSûG~ÒÑOô¾uR<ñÇâ_]A&“á$ès2Ž—\%#Ÿ$ÃŇxI¿ &½ÿÍXIƒäê¿Èþu€¡.Hõ[u 9ËjÛxš&+ô@OI`g³>Ñß“ÿÎÜAq lÉË.ߣn?ciº!9êç+²A7ín+PTl¥N•œêé:uÄö¦Sì%#IÐM"%Üt2LKvsÚîhü&"-¢NjxvÛ„Ço\zœ‹D9>¥ðøÕ·½ö§~qøs<å tÂ?ö‡.ò¸ÜFý‘üÕÇK3´Y‚Óê3<­Íí<\žáZQ‚ÕœˆÅ ßˆãÅÐ/~IÆ —à\·ûr‰ÍZA‹³¼ÈRDI·)U›—¶}G2eK"Oî»*Hºßw“$„oÁUXf´éËŒ?ò¶A6#¿ÜMí/#BÜœ¹«t ÙÙèØkunà\õÆA<Œ¶F·òJéwÅqQ Ö~F®²ªN¾;Ôö 6EIªYñ7ÂįX!ît)È}¾,W˜¤¹ÙßÔuêÚØ– áîÅžÅîÅ{Ÿ /Õ–‚òòUºüyxævÙêµÅYcÍ«rZíµÐŒ%;9I)iªÍGûùo¡<ê~ëà·}ßôS åè~üš©@ÞÚô RÒc ’«SW§¯Ž¾óqüuc¹ÞÿnßÓ Mƒ,LeîÊbSQÏÃe¢¿! ƒWêq¯ÄÍHæ•ÕFS_ŽÙI4ÙC¿}„H…>ð4ºÜ8PƒZ¼+É´…—Ðt ¸Lžrgp»…Áˆþ‚E.¹'³fÍ}„ù†>FM¼%J„håÊd˜ ñw·ÕÒjôÁ‚¿á»àdli¬¹üŸ<EN,.B[6Dïâ'ÃŽï4ïaß “T±íWSG¯ï¥±0 ò¾7%˜_ñ³~.ªÌ/†‚Üè÷ª‡SmQ“ºZUݜڜڔڵ=Ü¢//¢G4I²œ¬ík·.œ XŽSC¤.KÝP#€«±¾¶¡¡¥ÙQï¤Í¥)Ù™âW8”T5=‚ìLm® +È.W!Ê‚lsNyfE~S~ÝîCqý»­Z­`+³•Zöî ?tòÀ™«d]ÜFcˆ(Íàš*Tù(só s³”™ªÜt\ÌeyÒ\Ê6]]¡¯¡+êÌøÇú½CÄ¥ª;ðqÓí§œ?7|,: o˜šžÿ9¶-yÏ…$7_¤ºLËhá(·£Ž¡´¢Üžú߬‡ˆ)Žœ¦´îÈiäñ7ûÝ…è«d…³wHüßÝÓjØ-,E 3íYm‘§Ô‡à8³ö7aÊ£Òëÿr7#·›Š9ª4Sž~·z—‰*³¥` K»ÙUéä÷»,CçÿÁìn}w…¼âÿJ¾ôø}4H_ïòÑÃÐ 8­o|ñg}ô5÷Ë¿÷ÑJÓ¤ò9\<ÄÇNW ù§£¡ìõ{8†Eù)|.=û_ ýôÁù’¥á¿þÁ•`÷=çI: GÌ}Îî¦Î.8}‰]±Û[J6~š îN£#Yãþñh¦+ý¤9ÜöÒ©óîÔ[‰K 9W&®ü"§457 wðÒM6 ªEw=ØsO¥Šþk¥¦ÿM©çè]ÿä®…»†Ú‚oŠ%7®“ëÄ(MÓÑé€âÁ2PÕ¤–g[³K³§nÐRÈ3”,þù ʬt,³pÁ3ø;Uí;ž+Lj˜_›{”¯WWæÓÁ®È @]žm+l_ýZü[þ~öí—DBFL%œø€ÉšÄ<½Q¯×™h9@f+=¥)Vk…Åh°õ°Ú¢­âk¡¬­¬ÒÓs´ñ0àrwªyžÿµRPë¯5myŽ¡0jýmþûë~†¡"H©T úÑ4ÉêBtoÖó=‚œK_Û‚%]âç ¾[A±5í[QR‰5Ü# ²s ÄøÃUÿúÛŒ)å¬fY¡Ã.DR/KŽ’L’$•ÅÈ¢wçæ†§&ÅË"Mx¨rORU'9t\ŽÒ\-@U}S¥ÝÙÞâu¶7¹ÂË*J­vÀgÅG¹»j}ˆ¹çú™ûÑHB1Mñ1öI˜óyÒ9=&“›¤ó¹¥³J¯ °¯Ù}Àæ¶¹ý¿£æFk>(q¨Òá[Ð@’ÍÕ­œ¸?"¸jÞ¨áe£F˜Güjı‘ü3“WUL¯zô¯cÿ\Ê endstream endobj 81 0 obj <> stream xÚUiPTW~MÃ{W4¨<[{&úžZŽ“2QQ1£ѸÄÄeuÜ F\z¥é…nöÓ Ý ôØ,¢–QƒqTˆ1¦Ñ¸Œ³”­25Ѻ=u̼6Sóc~NÕ«óãÞsß9ç»ß÷]N‰D¢Ië·|¸þííëc–ÇÄ„ÖbƒoRÁéaÁâà´pr˜éÿóo3(ŠêŸŠÞ‰¡X<)߸°hJ,…sóc,Y›•‘-—ʹ9+åPnæÌDuö!enª°ò?;%zcµ˜Š£VQ«©ÔAêu„J¥2Âr)™ˆ¢&R,5ƒâ©YÔê}j=µ‘ÚDm¡¶RÛ¨íÔj'59ŒQaÔ|Ê'š*ª{;ì’x¡ØÞ1#â{:•¾Á¬cN¢ßFyxŠR„÷à)b\ƒ%’ô¢\9¤¢Ô¶ôO¹jº³¦Õ ݨ;§ó e FDÁÙqpö¨„Èé›}_\¸réâPõ=äd0KÂoÑ""Jœ™Ö¬ô·¹ÝmÔP‹NÝê:7v?i s µzÛž´œô촜ݤ:U!ÈQ†·¬™Ã?ÒnOU7ßÍøLMYJuQõ@4 ýÍÃ×$=í=Ç{üO®HÝu§ÛÙ`wÛÁƒµ.5WBëË M…Å G¤±;—&ÆîÔu&ÈGåŒ%³WáWß:ðåÇ· ‘:Цº d¥›œ®F¼Šš‚ÚÎHNþédÂ黦NSƒþS3‰¯K’2“²“²bwH•z…N©+0* @ùõš&ÎJ×Y6Gõà)链oûŸô9íN4" S޾˓մáÜúóÎ%œ’VÚôfTB«uš|䞢ÃÍéàÑ«G7]zWŠ*¾0‚=£FDç‡_Ãñ×ÅA.¨•¨kÕr@s“ÉÄ•‹.êïü¸8ÜxÓÖeî„G(ðCÌ"‹É;dî3² Çq×`ÀÛsÆf³ÚÁÚò*5\|²ó#@FšD7lÄ‘€#¦¾Â3ðî t¨¼ÉˆÌ%»$PUQVÔßñÍà–¥ûvæ.ßÌmùÃÒ³(ªtÛqÔ¦‘è¾–âñjö,^d$n³ÛâtñŽz5Oh²9LZôã¾ûüyu´·ûÓN—Ÿä¦]¾Ê¿¢JÃkiö^ž Ü<^Ì€Óì'<Ú0¸²^Y©% ‹ËÖfyU­]õm~o$ó%«˜-U‰)6]áàòwÍgkº¬]•]êhžƒu£Ñw¾f³±?ø¡„„é,òšù€Ðx7_¶ùoTÙ+`GušcOïwÜ[€ÞÝxÄCokï…ŽöæÎª€šiWc…/e¬¹M 6§5ðûÊ}¼ž.‚b(ª*ã©Ãx‚ é]1žŠ$øsÚ_çl}¹ý™EÆ¿3› ò&ŽŒÅãø!øÂ×}¥ÆQSÎ'ÜZ›2 BeÐ(ÓiB<¼7` ó°¤~¤¿ÿ+¸ ýªV¢(¢Æ+†zoâ?¼X7Ý~#'€·ºn°¯ /ÎK>Qgl‡½ˆPxÎÁ'Üw€§w×þÙCÚûMS,·Š.RK  "šýŧmóð`·Ø+mþ‚.S' »? ¼âíLÙqc‹¶Åim´ Í%U˜ÞënjááÔ1wªE8œ²¹1O/--/-)2(·”YôÕRö™!¯6§:PìŠ yȮɪ—U–X‹€Œu™¾ÜXQFȶËëåÈD$¡íŠJ°@%l½ÈÝ¥‡^˜Ö,#ï—Wò‰ð»fÃU$üósüJbgz?ûì÷8s°z/22»’“ws{ åÓâ‹H°Ü7~Vz”ÑØ`_bc0LBúÈd&[¯Wò q4•#’öÚ=FGDý_cw@ŒÍ!©†ëV-,‰ "~DÂp4WGãǽgU¿ ƒÅq˜&S92¨B®d…*460vŸ3Ócpqmƒp.~_Ì.’Ý ™¤2×­Êèãxw|€mÇ2L$]L[a}G¢he~¡\Ñ oáÙÖǤ/–fÊtZ•º¾À˳íÕ`5W zé&³Ã.$ÌÍ…$@»#úqÿK<Ëöäû|žF?Ç:¯lvå>€éû÷ÿêC+ñþ> stream xÚ%Ž1OÂ@…ïl…F“ªÄtÀÞàKAÀ`Œ‰1`l°¡M,%¥±Á0¹€‰›#¬ÌÌ$üþ‚N8ߥ·Ø†å{y/oø `Y!ä+¥F½Z;¯Uꥌ.*SÙŸø“]äi‡ †œ°qÀßQÈ߃?‡!£`UÙ(?|i¹¼–ϩꥢªÙ{»7pÌŽá¢D;‰2ÅâU eUµˆî,Ý1ÛZ=h®¡[š”ôh·MÝ ÄẽëtÚó> stream xÚcd`aa`ddäŽrÔöñôs 74 ™ý.ø]ðkɯ%¬?d~È1þgú¡ÀüC„E–á½ ˆ|Å"Ÿ€H. ÁX ÄÀÆÈÈÌÆ[ÓÜ‘hhah``¬g``äœ_PY”™žQ¢ ‘¬©`hii®£`d``©à˜›Z”™œ˜§à›X’‘š›Xää(ç'g¦–T*hØd””Xéë———ë%æëå¥Ûiê(”g–d(¥§•¥¦(¸åç•(ø%æ¦*@]¯¥}CR#€®bb`RíŒ ÌŒŒ,Õ?:ø~Õ$/øµx>cò¯3Ì¿füŠ4yÂÔîi +ç–Ê5t7¶5·ü«þW#ÑÒÜÖØÝÈQ:·r¡ÜÔî©&Oâëý Ñ»ð§¿hË„æÞ–nŽÒÊÊRùîºIuÓZ~UÿÕ“˜Ô>¹cr7ǹsÊwÏh™Þ0™ƒï6×mî¾ïE~·ƒâ endstream endobj 87 0 obj <> stream xÚcd`aa`ddä ótóÓvö ²ñMÓ÷ý:ô³‰õ‡4ÃÆ²L?䘈³È200<‘ùAä]© $-„X9J*Ú Œõ Œœó *‹2Ó3J4’5 --ÍuŒ ,sS‹2“ó|K2RsK€œ…àüäÌÔ’J ›Œ’’+}ýòòr½ÄÜb½ü¢t;M…òÌ’ … ÔâÔ¢²Ô·ü¼¿ÄÜT“õ@„s~nAiIj‘‚o~JjQÐIŒÚ@Çñ0012²øÿèàûyNyÁ÷S;¿ŸžÏøCj'óïå¢ßw±Í\ؽhQiw­üï]ßw³Íì^XRÒ]Z+÷{÷ïÝìµ¥Ý%% »gÊòØj»K-ê^8SޝlÁçYßó§N^Àö;qû®ëÜË'ðð\ŸÍÃ+ÇÅb>Ÿ‡óû7‡(zÀ endstream endobj 89 0 obj <> stream xÚcd`aa`ddpsuuq÷Òv ò5°00‰™üfø!ÃôC–ù‡8ËïøßWdØ„~Ù±Ê200t ‚È~Ù "Õ€c²3##‹¤†ž±s~nAiIj‘‚o~JjQžBP~nbš P £!#ƒƒ0H#“ß¾ÿLÂr;zÖüä)gü^›ùÍw¢Yì»»wNÚ>ŸãÏ4öè¤î ¹Œ¬ïïÖ°ÕvWwUus„göí”ÿq’}JûÔz¹òîÆšÚÆ˜Üà¦n¨Y÷ìXÃxàó÷ÒW̯¬üÔ¦“ÝÏöZÚÈ×±7«9:x¸9;Häääfåä45µ´uWsÔýg_ñ݃5‡­-¯=¦º¶¥ lU6[fWfwV7‡:ÛÉÃ'ž9pþÈå3Ýï8¾‹þæ:£(§Ö­ãÒ®ÌÑž³ tÕª‹–¯/˜)ÇW¾à‡Ó¬ïù½3³ýíf—ãbžfÏÃ9‰‡«‡‡û=×^n9S/Žÿ"Xýw endstream endobj 91 0 obj <> stream xÚcd`aa`ddð÷÷Õv ò5030‰™üfø!ÃôC–ù‡8Ëï´ßWdضÿra•e``è‘-ü ²ADj Æ*!fFFI =cçü܂ҒÔ"ßü”Ô¢<… üÜÄ<4A FCF!aF¦Œ×|ÿ™’¾Ù÷o*+û©[.ô}éCá ßy¼Mf?нwÒž&²w§çu—tætfwçts$?aÞ°»õ{0›pÁÞÖÍìåÝÅ]eÝñiÖËÿ8Î>«eR­\ew]uMSD¶_K@7Ä–žg?Vmf¼üáûÔÌß~¬]sôðÊSÝ—žF)Êwÿf4°uôŽ ¨©©hî.íníiénãøáζê»?k[k^G\eu[[eWE7G›K—k·K÷ù£—^>x~ÿÕãÝo9¾+ÿ–9ü›Eý7—÷oöŒÅ¥+W-Z¼jMáü\9¾²…?œf}Ïï±”íwh7»ó4{ÎI<\=<Üï¹örË9f…‰[ ÿŠl¡b endstream endobj 93 0 obj <> stream xÚEÎQHSQÇñs¶¹æ\3­¤n7LД9 ³‰f6¨f¦†¶ôâFn³ínÓ²ÆÔæäÏœŽtiå aЃHB Ab>X‘ ƒ¤,ˆè¡sç‘h{êåß—?ŒD"„1–«ªi¨×çëôuÚD—´ÒÁÉXOŸøLÌg x¥?(ÊBýLK¸•šps_œ8g:a,á:û5šcj¦Xgíè²™ÚŒ“Û’Çiµ¥L±F£eªÌ¬ÍÔb°0zgdÍ.íL½µÅÄr]Ln¹‘ã:Ê ].—Ú`¶«­¶¶“yŒËÄ™:ÖÎÚœl+SmµpLÁÌ2‰Ëê:«¹ÃÁ±6Fomem„°0kPEü`2’¢4¤DI„‘5£|ßà}r>›ú'wêÂø×ŠlÓ ùï©‚H[É : …3¤–&‡ÿ I‚Þ@ŸÒ EºK7åÛMÝ]*^¤Òešúít$Á¡@Põš¸ãÛ/H@›n"h$ÂZ’ª^sƒÄ3ÐëS×ï ö½j$š thöuÚDshÆ€¯¿¼Ÿ¿wD‚­÷/ ^ø1õˆL"çGÓ±ôi<%cQ!o&k XõEÍÛ•SáTÚ›ó¯U{Ë ÎúΗ??þáæ3xëž~YÞ€OÚNß)Ì ë$IžeˆÂ¼…¡Åð—ןÀ,¬¸&Ô£ PçA¥žZ'Wyl ‘ÇæÈþyR2—b§„±Ëä³bl&#èVíþw;Àá Ã=¿C¯(Æ#™ì„[ªÝ¿âÛ.p:"0®’;"¼î±ŒGÄôjhÏcézÊô°L¶~_¶W)•†eÉäûj– endstream endobj 95 0 obj <> stream xÚŽILq…ÿSªþÅ—X%Q;.‚¬KbPbbª&hªâܰ‘6ÚË”i K7èt~ÒŽP)¤»P¥qãàÁ%FËÉ£cLŒõ¢ñâ –¨­ïð%ï^>iµˆ ˆ¥ÇŽžj9´o“Ñdjiª ÍöRô÷›9ÿu-R×êzª¯R×hõŸjÿ’šõ¡_+*ü±¬Â/Ë+ÜP†æÏJ¤%ìê  Û †mFG·Çií²°t}G½µ©içfz›ÁÐDïµ1Nk‡ÙN›Ì¬…±™Ùr¹BwtXÖC×7[X¶{×–-Ç5šm=gמ†Í4ge-ô1¦‡qö2ô‡¥›m ý_½ñ?[·‹eœ´ÉÑÉ8íU{Q r—ëÐFÔ†´D -ºM4ó*_3—€¢r¾¨î— å ²Xwfw;ßÁ…‘øñðhp\Ÿ~MgžgȺø¤®ExÊaD˜d"½WtµJra”Z£ÎÑÎx;𸠯Õ7ïµ°¤OCN”A†\d nƒ9aJÈ S€+w^¢Ž€ ñ·öÏijÃ!Ö0 âRÿürAùx¿ôqAzŠsD‘PW¨?uã³âØÀéqH%|â0Å泌dY–¬ë…±Ü‡À382•,ÈHB @Hð ¡Òºùûµ~KØ·°Ë ž10AÉoÎf#ÙrȺ Ë€¥Š¨8Æ) $G“¸F}ïÍO~VÚ>O扙¯Ê»oUªW­×] z/C?v'ûò7 ¹»Û²çôGÀrj¨×ý¤=0ÝZZuÕ/ñ5ј/~[œ|kÚ}Ž‚®‹¥ƒgWl¦ÀA¯ä‹br¦qÞpÛ¯:­gžsô¯àÎãÉB¾åµ¿XA/•Õ¹/ù(/¡‘~—±µí4`{wê1™ä‹±ÙÑTAA¢týÞ̳§‚4?éÃ5®ŒjL$Š#³°dN,ÒWkwÊäb‰¬ŽKŠÕï–äã$©|Zõ¢ÒX° endstream endobj 97 0 obj <> stream xÚcd`aa`ddäuu‹rròÔvö Ž´ Øæý ’a©ú9—õ‡4ÃÆ²L?䘈³È=ôbùÏÃ$ËÀÀðYD¾ã‘/@¤`ôb`adä(­ê400Ö300rÎ/¨,ÊLÏ(QÐHÖT0´´4×Q020°TpÌM-ÊLNÌSðM,ÉHÍM,rr‚ó“3SK*4l2JJ ¬ôõËËËõs‹õò‹Òí4uÊ3K2‚R‹S‹ÊRSÜòóJüsSÀnדÎù¹¥%©E ¾ù)©Ey@G110d¸Œ!–™‘‘E3ðGßÏÍß+·1>üÉÆüÓü{¥èÜyÝ ”wWÉÿÙÃVUÞ]V:¯{®<ß÷¿ûü žÏøwów‹Ÿ±¢sºç—•vWTÊý3b¯ê._°°{Þ\9¾âÅ?í²ý–™Æ.ÇÅb>Ÿ‡sW÷6®mÜÛæðð1ï÷‡"±ˆy¤ endstream endobj 99 0 obj <> stream xÚ]QËnƒ0¼û+ö˜*ŒCI á qèC…|±—©ËÀ¿¯4‡lÍŽwfW㨬y­†¢/3‰è% ÎÓj ïƒ"19ˆe¯ü-ÆN“¨|ïôG7"D-+.JLrP÷×k[Å)HìCC»i¶×5o¶yÁ±VýYF¢oë7/fƒC!§¾8îÓH4Ö ײñL³jýƒ#ª(Éso‡ìXœu'ÐtêŽ$£4‡¬ªr‚Jþ{KƒâÖ‹GgH§¶“Ñ8ÉIV:Mbêð)à“Ãç€ÏóÀ3Çs0÷svÇãŸÿ¾JÉlSù˜s+,æI K\öeq¤»WP»õ]ÌÏ”ÅjŒ Àÿ…Ö¥0(|~—ž´Sùó $œu endstream endobj 19 0 obj <> stream xÚí[moÛ8þ¾¿‚ß¶E›ï/‹EÄI®¾l²ykÒM·|‰Ûh“"v»ÿþž!%š’åTi“âîP¦(‰œyøÌp8”mágÒ0á%“ž)å˜L»À”fV*¦sÆ3-YŠiÏ—–)&„ÓLr&$ºœ‡ ‹³qL&4³‡Ʉт)(²\3ƒkkÓèç ]Cžóžœ=:iô<04 u&Ì@¡€(c¡H 5ðòÀ™åÀÌ=à2e!Ò’@m)°np£‘#ÁÎ3GÆe¡ÐjæH±“Ì“((Vâ¾'îC”¦k¨ÐhG*!á‘Õg´3ƒªµè„ËÀ‰(¨ä¸o˜“`’†à”SÌ‚Q‰ ÕS\1¬`žyALr‚H4=7ÌG‚˜wñ†&N0 êáÈJd€ Ž+A“lÅ‚Á¸H ³°à¡K@XŽìC–$KX-JÔdrȃöàÁ?)±ÔŠpx[Ko‚>°7“ñ9É!©ðx€¥ JR…ƒá7BxB)ð‘Ó eìèɳÐQC‚Ô±#Aš@FEÌQ'| aÜðÕ_îÞ\/èk÷‡»ð˜T!êc6O0š*Är¬i©FãN5Rœj‚½ª’oWÕH_ªFÚP}þ|xx{sy2]¼nïO§-†ã“wÓQ:m¥ÓøÍóç?•¨ÉÉ[˜–H FÊô%â§%#4±-´U² 5]¼eÕK`™ùoFó0D}/ ò“·n~Vȧ4¯>_NoŸ\ý{öéêíǿ؟OЈs%ýŸOŸ&!³›ëíÉbúdûêÏ‘áQgežqõ3ç??Mú"ôz”q0£Ébòáæ¿VÐKøq|Ûá˜^-µ l:„C{ƒå2Õ¢›àªü S¯ÛÄ>õýÔ£’Ì ,Q×Ðe¸„7?!p‰ØJûuÕ猩uýã ‹ª_óŒR{´°b ûX¼ÁºV¦˜qF—ZÒUݾºŠíÓ=ÌïiŽgØÕÃC£Ä@Ꮂv`³´«¯–?lÛ÷ÀÖHeyçKýV9ר¡Z$h†'ðB×å‡á×YÙ˜1r¨æ¥¯jéÞji­$oL=¢„ò)õ¬îJv mª—í<3+–Õ˜…/ÑXè–Xx°Užm¬É±M+W¬XÆ«ÔvÆI½ä|•:ñ}©CìßPôU*}e´lPçšÔµ°÷£Î·¨ãKæÔ’–Ñxst°÷l´òG‡;Éþœ¨šžá :6„p]q;&N/HQœm„øÕ:Øq®éN¡ÉI ¼!–?Ø4ÜÜ;?‘=¶^!ìð%ÕŸ7÷í¾$11 -ÖÐ/FLÉ›MÞZØûQ'[ÔIùÕlóìhë(¹2LjW¨ÓßyúzjÓž†Vµ"XûÝÔ-)°)þ×\š—B,¹ 6Sµ~pqü¾?>f¾bnÚ K¢ôú êdç•lCÒöô¢¡Á–m²Õ€ßÏÍ\{†ò’¾¤æ|ïbó಻˜±ÍLíB6t¸æ5'<¬p⛜”¸ûQZ”X_PÂí’’—{gg/"ÝÜ=®³ø.g‘º"†~îÔ"Æñ&1%ú^Ä8±~ykð²}t¸·õ"®]¾âm…㜬p6rBïR‘ÚÉ&' ä}ƒSe°qíÔSÛû%K;Û/_ kçUK¡/KüKÕSI»®…Œ<&Ò£‘4;׈Ʈ•O6 ÷ó™v6©:S¢£Ã‹Óó£È»]¡BðÇrÓqÁH *xŽó¶AH+K,q÷ãÃ?زþûŧ››qiä¡#»ß9»––uú]rØ \ƒ·V&ÙÂÞ‹:ÏïØ˜áîAÝîéÁøtêOO»©ëŸ„‹eìrI”â>É$Ö3…l[(̯uIo%“-ìý¨“wäáF/‰ïìýöì·ñÁNGLêácR§+a‹vC©hÒJ˜ûÑ¡×/d^‰óËW'›QòyúÁéð5ÒJa«˜¤œ'Ò¡SÑऽño ïGÊʾ¿ÕºˆÕçgãÑÙ%T«I0•:Ûá(ÊÖy [Iw|+T°ûñÑŽÔ:s†ß'ÚììlÿãŸ)Øù®hc¿k –Ø*§ý—ÁŠ”o°Ö Ô-콘 ü¡˜Û;ÿýü|?i·]̹ïË\ŒÓÄœ;×Fœ­8ÝÂÞ9yÇnÌ‘i[š“}ræ°JŠ´9¨»æ`¨ç ²í9Z¡º€Ýv ¶fÍîôøðl¼·73Œ„ÇÝŠéuÛŽ*6™^ZáºDßÛs+¶³{±µ5Ž ê*/òÑk¬ëvb†~š®i'ÖÈC+\—ÀBS:ÀÃõæõ|–¯·goßNo§×—Óùk¤ÔÓW“ùûÁåßeÃÉÛÙLpN¿!ë«P×àHuMäý%kÙÂäše’g‰ÒçZn«²4•¥©ÜC©\ËHT–®l®¹\£#åZ0¹D©éoIYŽÍ­l–c³›±ÚŒÕe¬.#t¡Ë’]–ì²d—%»,ÙeÉ>Kö­Ï:|Ö᳟uø¬Ãg>ëðYGÈ:BÖ±´vÈ:–6YGÈ:‚£ŸbÿûŸÚ€ endstream endobj 121 0 obj <<1a7ef186f4b453843db13215f9fbabb2>]/Size 122/W[1 2 2]/Filter/FlateDecode/Length 313>> stream xÚ-Ϲ/ÃqÆñïSuÔÕR”ºZ÷}•V©»Ô}רˆÁ`’ø$#3›°I05ý3$ ‰DØ $–ê“ÇòÊûÉç›_ò3Æ$“ã4%¤˜d‘6ÒAºHé%~ÒOHˆ “Q2NÂ0vcXŸ‡*™"Ód_:€äÀéд\¸ï4ÓH>êN4­ÄNæÉ"|.ÒIB~Í RH–É*YGø^×LRD²Iq'qa.ªw¥X?P•!v¦rcó[UŽÝ`êö5+p|¥ªÄ鹪 U5. S¯÷4=¸‰«¼ˆÛT5HDTµ¸ýÿTbªz<þªð”P5ây[Õ„Ÿª¯^U Þ¬ªV¼o©6ðáQµ“NÒM|¤H ’!2BÆÈ™$2CæÈY"+dDñ³cÌšó9ê endstream endobj startxref 63338 %%EOF glpk-4.52.1/doc/notes/gomory.pdf0000666000062000006210000022326512175147600015643 0ustar maomkpasswd%PDF-1.5 %äðíø 19 0 obj <> stream xÚÍZ[¯· ~ﯘÇ]䌢+%9mQHú` éy(’Ó‡ØM 9Nc4¨~)‰”4³œ=ë6) ãx/#‘I}üHíòóbÿÌí£^^?./î—O¿0‹‰Êš°Ü¿$¯Ü²•‹Ëýß¿9=8«ÏðÕüÓ.8üÃWÛg€ö9ÆóêŒÃ‘`ðßfDM³ýÁÚ¦”‡U¾‡ØDÔ‰ŽžÑ_ÄÏλÿó½òqY­QÙÐâêlÛf–YERŸ]Ô^”vç˜hFY\YFè*ûÓ/ìbPp¨f° ü²:­¬%EZ+”T a`¼õdƒÐl4„–%`·D•csyƒ&öMªÆE]*_“Q!ã>“ŠžÕ“9ƒ=ÛxjJ½iÊ¢/Ë '«uqA{îÎÉœI÷‹)J¡J7.*Œ€ŒJ¡ŠG¡Çó¼Kê¦ÏÕAdÞê(\J¦=û€Š!ð'C–0ìsüÎNq ëŒ¶¶°­²Îem7=¬S#7[dq\u§³¥‹œþµ#ðs„"ÚžF¸ûj’¶°2Ü3Ú L;1.à‘Âí8•ÚAz|ûŽÆÅy\R&á¾Ëˆïéyšžå=~Ms'¯¢ÃÿB; ÷ÂtP°¬}Äa¡YÙH ž‰4ÐãÂòq6?¶Âl|çèñ_ÅÙ™ž¾¹¾õÏ$ —H¡ç'ópD`4YÉ °YÇV”Ê–DýAr’)¼ê¤4’Ñ;+±ø¯/œjpÍ…ÿ`¦ÀCƒoÛî>Õãâ­‚À˜s´ˆÌ‹øêbYy3ñîØ‚2ž}¡µ¾˜ÐôÑV40Fòå66NÂ}ر'‚õ¹ë˜æ¼ßù9íüÌqðJ°¤W®,\ Øl”N=`mØW„—°¸[ο˜ V¯+ö… ;-ãT\´Œƒwe(02•¯¡|Só^¤É®!Û&SöQº=%÷Ž‹a€<ÉâEtŃD/Í=rؤap®‰ëZáX”WS¼^«ÕtIc*PHw RLEhí÷àO\à*–}ÇCÀž“=•DïL%?õ­c/8â;ul lì’x›9IÊÁ¶ÛÜÊ•Ü.©ÇiáÀêAOO ›nkÆ&/p†ÖS¯#EËM kuÉÐ7¾Ø1¹+ñ)M–B”Þ"Š×ç g/ä!âáÕÊä~x‘m º“$Æ)ý ‘-üVA®^ ãGñr#A’©Çyˆz)¬9)‡(ñÄ{e9Ëݱ |7'FaãÞõà+œm=¦Ý]@\‹9‘'æÆ¤˜¿kdÿˆ(“VkkòÛ§§£M@?§2û繜dÓH²«GÂ*û/–ÒCoÜ·q'?ó}aµúÐ%È9øñ þð&72mŽۨ‚Û­9lØ éÑËí‡ÅÒ!ÔõÌ7ë æ 9¼© Å)[Õ‘vd®ÈðfYfäœÇêüÙ¤›-ØV/Ѩ'Эih*'ž ”Ý hY`‡É¾ø°¡õmpɣ㨫º,¿=çÍ?ùzä¬:†»:PÖò=Ÿ–§§Úm*ÀNn³¥ô'Á(Yû^…Ê°åÆšŠª%(=‡öý>±w4Ô“EÈ7Ñu™´^Ð[­—ƒuZª6Þ-QP§•ws½ñ›Q¬æ³ï(%à‘Uå ôj–òWP:©p –ÈEûˆOä ¯— /K!Iª ,çzªÄ-Oª~k£ÜL à¢N»XcY3è«ñ€¾¢:6qB¨ä†…­ËùöAY,ׇ µª>“Šù:œ8îªüxÒe¼”ØíÔ>kôÖF³)‹ù›m9ÓÝyKÅÑvJñµ'RÒÛkS”¦69ßY0?&ÆTv;Ê˙ގ’$w0ÊûböŒ1^ˆçˆT9åÒÿgÀ¼&• ÍñâZµò±d‘r¥UÂ÷öòõT”BÚ&é{êØ%oiãJdª½.*2ŸTÅ)…”›‰Æ;.Žz÷¬–ë<Ú×sâŸèÍ•äÖFµœJ†äôû2þæÖ2„F¶˜ÄÑá¸m'pú¹wÑžµj@Ï)Ç0ÐëMŽtÜÀBó…ªÜí*ì>J¬€oóîzAa7í¼©Ò 1ýúk4êúœMFï—†QÉÒ’¸Ü’iˆõ¥h˜h·‹ã[iÈD¸œ˜[•:¥z ˜ÂŽ0otyIWÞ^LØë}6K©~×fs»6Û­z›p¬g@#¾$yßhaín¢5f@¡/  “¹r…UøÃò×iѸJœ»ÓF÷î´1ÔÚ¦“ÒÛÚç6éÊa¯ç¤Ê»å°·Ñö´…×ö”åü'}ÊÎÚÛJ,£Å”üa€×A‡{sf‹08Î…ÜÜ+ùò;€‹ v]Éq¹3rMíŒWó%AðrUÇK-ñà¦3gÛ¬ýL nU ÈÙõ•6VÞ%$2ÝWDMæU ìZç.Ö|A5R,r´˜›Gý¾(Ðs54žšG7ÜQUöà;Øì"¢Ö><'wvrñâBŽulf¸yWï½ ß{Í—\çöÃŽÏï—Ÿå°žø×‚€Åö Jƒûy^V6÷/~\þ²|I?÷q9¦ ©Ôe+8§`°Æ#tf€Fê°êDR—øw7†xø© ÙÎÏj}Øœ*ÁÝÔŠœwÖgÅÐäõÑì~|Ò ù;V`¼µLozÝoxFG&½³(\JÚ„Þ6ý¸…\/P1Âé`9ÌT¹Ô¨}޵C˜~ÜÂü¡ÿ¸¥tÁroNŸ¯ß¾ý‘©€ ãàúýã·?ý Zõþõ»ïþ©ÞÿòGÁ Þîzc³Ä ÀÍß¼ûEýôþ$ ¦6š’ò•‡rTW›UÊS•€Áúåïþ |*½Q endstream endobj 23 0 obj <> stream xÚíZÉŽ¹½û+òX wq¸3S^`|x€>žòa¬Œìƒ/†>ߌ ƒ fE.¥e ¡ÕÕ•\‚±¼xÌé¿“™tþg¦d§”ôôæ?Ó·/Ó7 “ÑjÑËôòvŠV¥8]cP)L/?ýp¹9n.š› .ÿè§¼ü5ϙٻ(»ä…aøûúÜMI- WTÖON-±,§µ«Cø¶‹JiºöQ.¥›ó¶lŠŸA ‚<Ù„ÏŸ®>êü)ÆòÅËŸc1»ÈøŒ~"̲y–÷etÈ££{²ñRfÀ0;äç Vôm]ÖJš­IŸý3-íÓl/ þ4°OPô¤m‡[\Q ׬o릫q*¾ak¯ëÑ}Ù(áAÚ¢©|ëu<"åàH[Ž…ê MÆT;÷™LѾ7zmÄ%#š•DEíÍ×ô¨;Y5Î&pK1ZúÞQ£ÿX/ÕfðÒ¼ Ä{ò¯ªò õ€ÿ¹Åøw¬ª)#G·ÙvðT·¸CO%-Á:ÞGJM¹Å3SŽê0èþbnO7mãíboOàðz©.2¦@š/2樺z£ë ]­cÍÐ[£ƒà$m°U㺌"w]z-á„¢M´å"7l_€LˆAÛ’—EW£ ·ü²ÄcþmªJÀr3*9”oÊîë§Þ€9á¯Yp°l(Zåöšv˜OÄpýÜE8ö?ôû@38<¥O×-­×Ì“ ÀÀñÂl»­‚©£H#®ž ÑÆä¿Lº²ƒ¹ÑguQžDßžhÛSñX ÕwÀX=þT“¤†>"Õ¡šžiHL §è›zp¯eMÙî5 ‹¡~dË>:ÔÌÒ<Š~ãAi½â}E´äi^ k2y³Ÿ‡±Á½y^Ýÿ¬çõáh~³:~£ Œ]|óSQwGÐ Þgö뎀TG®2kùç†m}P~¬£OfSH2¤”è»fETœ ü¬Š©÷ކ¢!ay–ôv&;¿lçïkþo7g+btóϴ6Q´Ä(øfݹ…Mq’™ÅHŸ&FŠ gˆ'?³¬€rL§C£r’È8‰±IÅPyÍí"°Ôfä= ç=@?UœqÀ·ÂIÙ¼ȹ^7€5ŽøY`NN¹ej#žù©£®:J¡ÜËೞñ·ëGÈöKJû=¤¼„ÞÓAt0®¡ç®ƒ?§0V™™Ž©¬e’° _c†Zìn—ÄFäùÖÔ]l}n4CÃveÀßcf‡£ÇhÉ™—=ŰXöГîÕ˜/cgk,ý#ç´);ʼï‡ê;^Åe œcÔ ¤"7°Ì¨h˜5]XÄ„G0Â$ìJl{KäµÒ\É·²¹œ‰,uqÈ ó´l씵Ó`§Ý6žP6 PU~˜ÛLÏwˆWFnäª>ÊžFÑç6\÷!D1º`hsÿJ‚3ƒÑzµÍ…?Ó -‡˜¶bšßŒç¨¼™Ú1ž æT<»ðh jf»d𢌱¹]@I6B½¾Û'oá2~–0Ìê±í5´ÝJÉWJîKè)ºAO#…6LÊ»»^Öf«w½a¸ë-zgZ¸ìŸùe¿_V·o”ɽ'Âî+–ÀÞàœ|v´iØØx¸Ê,žTˆçßNñ¼#PÄ;ºÞoäq캰¹–í7ðºäá1´ƒc僫¹½,äÞE)VÌpªç±Sêë9:þ —'œŒk¬—Ñ;•Z”+5¹ÞÚ-q¡‡Øê±m^ªñª<õàÉ2UêþÆðÞFYÇ“Öw+¼fïm¬o¹è þÚg|1PïÓgÊ|GyzÑ«ðˆ›á!ÈY,,äLR™¸ #êxОÁ :é”Ñ×6Fl˜NÅß ‚„~˰Ñ&Nµ‰×NB›¿2‚†Ð¯£CúÑyÿêºÍ»DTvñGñF¼Ç¬»ÞÍWþ%»RÜ!çsdEßei‡àKdŒÄÌ Ü<ÚÍàc[ŽŒ¯ñõêàà’£Œøýg é Ö*õ¢Õè4ãðÊîjp퇮ð‰b÷€/«3¯Ûz×*$¥TƬòÜz^Ã"q±ã‹éWrëT»0ó‘šœ?I',w¾ÞVþ‚cŽ!gtn£#¼JÖpÂÈ8a¢…nÇ5Ã…3Ì~™¾ÿÍÿCý› endstream endobj 27 0 obj <> stream xÚí[I5¾ó+úøF™6ÞHr@‚DÄ"er€DHDLP.ÀϧÊ[Ûýì^òz’B¥_wy«rÕ÷UÙ3|Ø@á?6>C‡7Ã7w×ߩQâ¨î~¤"V £VĨáîí«Ó½0æ^H~/”ˆÏê^hø­Ù 7þûÍȵ†'_5 [ÐØJ¿ÐÊÀ³’(í¤L}Þ¼¾ûæa‹y0ÁˆÓ0[œÃË(À`êÄüîˆJà÷'ñ{¹C¨Æ,BÒ¨ æ¡tú…ëPæ"ÂZpN’æõà:L”=1v“Û±ü+Ð…V°·¼Æ“)›„å¢ £Ó¾á§Û4.öúò ™´ÄIøW•¬‚úôM }ão|Ca{oýUC½JêáÒ÷ök”Ð…„&ŠGõߟ=HãwÊd”pÙ@š03&Zx™ßC" Ç$š "¦š…6yJÓ>àhl…®á§©vÊ4˜‚P°RNhPÝ»("²ˆ ÖÆAøY{E´Šh¨ÁápB%Uˆ†*œ-Uñ®¡ ƒ«˜t±¢ñ¿cpéÇpÕTË!,¡fÈYÝS2õ!*E™jš’Ó¤\6blÚ;´Ñ ƒà’¾ß6L ¶RüêMj6˜ÔüMªZá¸0i'Z°Çî,Z‡/ÒÀŒg”P0 ÷…"!!~BÈ á1 c¥¾áÖ‡cˆÂήàžN¸ç%7ãžs«¸§5Úc÷ì:ð¹ðùa) '`/LGy`¼Mâµ~òJyX{|ÛÚ(œ0»ÉÔ²2µª£¾²DÔ|Ä4SéµîÂÆ•‚ZD•s¨¤Á`B°S–åú³~n“XÁõ*­A–D<å*xÊÚõm€’%žwÂ4›…éÒ ŠÈDÀHÒ3Aߦb;žÌD‰ËxɈÛǬ“KC=„˜èubbÅØŒécºcn ÆäÕ0µcÂaWaÌî„1Û…±ç›h £zr€±>¶$E’íIŠ$Ûé‰×¼<Û-56Ûr!/ºM£'{æÞ›•,²¡°Ìy‚l/çñ_Cηä<±÷)çI‹ÜLO³ ‘×PGfDГ=Æ'~tš#WiŽ<$ö¬‡õ¹C\=òÒÐsƒ–« ZÎt/ú°IQ¹PÁˆÑ0”°WÇ:¾½> `r;ü5p•¶–b„òáaàà©Fç¿? /BÙ©ì77Ó mÖS’™Â_±ó+7†§OAÌv“‡Ò=-Ѱa aîÓe¸µ_)Súç©¡êJMU["ݤ«C<ü¦i”b ëóñƒ³du´ƒ£VÉìÎyrÃ7äÆåo¡?1ØHbb¶œƒÿóú³›ýÈ&°cØDÊ9©œReO_T•áÐ4kטø“_+J°9Ý™k‡6 |ÅüŠå”gHk¦Ã!Ã$‹(q ¼)¼Ó´þêg(“œ¤$½Äd.M±L¯c“Ítªi*HÃSåöçF|2mt×è8Ž·“ªÜÞT$COÎÒsÇÌa~ilKT®mÛÑj׎6¨w4Ätã‰fÅ\e*¿Äý’ý­Vµl…aeÐqÃ2~l¯râ#ÌòH=ì³K­lédä7¨jÄäKFÖ]#ÃÕ+VK |ÛX¿Ã½–{ÐI›­htmEx£:63[mÆÀhÙ*/šFËeÍ£`0Œêó8`ùiÊ’l‘³…ø²?'ªÒð L|™$¢ÃTBÖbM…zÆÉô*;(óðóßMøãÃïbÌX®ÈŠz} اucc:¤?ç=énOÍêÚ¶Ìã#êáá·÷mµq¤Î1ÌÅE¿mõ¶Êô#¬Èi¬häú‡Z©€Väžp¶àfÀçŽà¶p4Ý Ž-'³ŠˆY`œÅ—¶Û«fk<SìLaQ …»)K~óÇ{ÔËŸ`Ñæ~¶ ?t¶5Ö¼6ýìØZLŒ7ÜPÌRªxöƒEˆ›áD&FÌ-ç)ÇÇf½O¹Ëxs›f@WEåtrÁ¼3V _R0·™ÖÜÑnþiÇ)0¶¿H°ã­R’4±¥ó‡¸žž<·Ö3OÊ {®P&Íþ;rª¥°îYç2ªØûo£‰‚ÊàVž Éø6e^¹YŠ_ŒÒF£FGæ>Y½O÷ë}€ï­Å!7S0°Cu!Þ—ñ‘rµ4öY ·eiŒYØÏÃ(!5‚é> ˜ `Ý!¾èTÆR+c1ß¹¬0Æ®°2m'Ý…¥({@)Ê”ö{ÝTCyhúÈW6>1êQ\BSÜ™sêÎÉÝÅ9­ÙC ¬›ÿÆß ˆ½j°/'zr ôþþ’kàD80qô FÐŵ=];(«@%ŽÔÝ÷Ayl‰ÖqZ&V‘GNð¬}b&Ý^¢4£´¢ùWí¨%í±¿Q WäÎé~‹é~‹™ßo)•¢øDÃ;aV¦´ð)ôªlÓù8=¤¼û¢Î²ƒ?m™_LªgË×Cn“úºfû¥¼Ês™Î(ÏZ¶ŸVüªy„çÃú2 ³œ¦=êÁv5¼n—Ô¸Yº9TlÕ›CÝêUŸËÕŽF Ó*—j ,Snâb‘eê²tË|¿®X&•HòG¥¾PœAN/z435ƒl"žux¦¹ž¹ó:ñLûIŽ<·ß§¹19àT¡žwÁŽŽÌß&œ· Ξ§7K®åÈ "Õ\(,¿sÆJ&,³î<3L'ÎŽ’‹ á2f›¨Lâ{fuF6¶”[ÙºCü2x qn¯î6t}ƒü9ÞÃPþÜ)¾èÞí¬¾üÆ9 Ø¢€ÙÎFZNÄ4Ög߉l׉žnò î·H¤»“'fVr>—"W}-p*Âùä(eƒzžæË&ù"ÍÂßùœ{gñ-¶9k¾IžúY<ÊWÕ%‡˜‘†Òa«¤§^ñ!ÓÞÁÛ(ÑQ9O•„Ëo1 o±ù†g½ä :Â_†wOãNþ#Š2¦[”y×tói”ù›#.©F½¦ŽvE$zÒ,™uýwû˜µ„ £Š(‹"†Óô¢[À ­¤ÂSë¿Ù·ûO.êsY¼ÚgüÖ츢縅*ÍÙžþßy·[ù¦b+»ú?j0Šª›= @ζAšiŽ;ЃtÈJD /¾øBå… endstream endobj 31 0 obj <> stream xÚÕ\K#·¾çWè¨G ‹oîÚb 9äÀðX{‰6²|Š~X$‹n²[ÒH³³XÌŽFM²Éz|õì>üv€ÿà`ÅÁZ~øñÓáÛ‡?þU€3ÏýáÃÏ¥™“‡“ÑÌêÇŸ~8ž¥’OÂâo~ôÓÇ s\3ó.,ŒÃÿž¯C¸ ó/{æÍAâ8à«<À´ pƟʘoòÛŽ¦E¾ÉσMh¦t¾üë`ºc@—ÅèœÉÅ º æ}¾þn0Ý0nòå3™GøBƒ:3*Žùe´ÃðIøCsæBvÒViÈðï|Y÷—i£ÏÃs˜%dËG]ùxæœOX).`%l³Òl³Rí°vxéÀË•8•!_OøÛ|4Û|$6³xù$¤E?dš4—‹§“t<|Ò&üس4"üæáu˳´á³Öy „ÖóÈð ³´xæ8Óþ@PNGù}%5† ÙIÇ1ç¡9ãýwÉòvŽêüt~¢½ánUø1kJĸnܧLÊûí=I—‚œf£“%_­ž¯õ—LJ‘•™§L6`xo¢/Ñii®4œö˜0ô4#ìýóï#;l™¥eÞ–â´TL1ã;ŽÕÿ²ÈHPC$H•…™£hþ¤‹üÇù=hevž©…a®–}PÁ™ò/õ¹¥n}î|0Ä6(þw³ÕN¡‘»¦ÂHñ^É‘kÅ ‘•RLàÙŽáytzŴ߀RÏœ_†G‚™…ë× ‘ՔՔݗÓä«­!Ó¥3øFi©Dn`:†#a-K³T¹Û‰£"Ç)ỪÚÕ´ÈsÙ…€&‹]pãeO”¢LÑêJÀZ_håÓÚ+´ëµø×E¢šfY5™ÖDD·ç§gšAxKJÛ:<¨’qF>a™3ˆ‰ux“cÃ@ÉÑ#éMÜ~:)ˆËg®F<È&B>öqA$¼J?ñv¦!A$àð¤dÊî¤+ì(]¡W°9pX5i´¹ !ªö< }aAý~d´;±¦ñ¾/µ·7ª«5‹Uô>}ŸH2? ”ãöPFìÇ"¿¸£yòš²=Ê€,™Gj-”,$}_”Zh~{]ÇL=£@ÔÑʽiÜ7±ˆÛ«Eè†L©MÝ(óÚý_—µ)Õ†Ñy0ëÇðÍãáZÑyAJÄ>C ¨ÖäîÅAVçµE:¾ïD9HAl5d þ LøÌÈA8ÅVêôq9C¯Ëˆ±ð»zVeÃ1fKŸl£¨Es>ÈÏÀTÃEF—‹uõ%.¥Ãí%\C€‡é‹iÆ5F0ÆÀ–oV9¬^è Íf G<¾†ãvj8OÿÍ`…F[€¡W + ‘£qc%Kß™ ‡Òxc²é™bO±Mìq¤t?ÁG¿œ-­Nþk¸I;›TÛ©ƒ=´Ð¾ Ì”ê8ªT‰¦Í˜pÔoáh{µ}†q‡íX4PêŽm•—SòJvu—g ‘”_vG¶Jºé·Ð¼ñA{­:º&Ï®:Tß…¥cþÿ(ìáN |)é5oàK[±º%‚[-ŠŸß´p¿ÙËcœh\J‚iW½³¸AG^ÕZÆjÍF‚ª¾¬ýS©¶Æ£êúÙZ §ÓÊ}ËtMM]3¬AâëR‡D“ðrá ¯Ž×÷±¤.Jõ’ò´²>OrSªòõi½›ªÔn™ªÌ¿<¿‘˜î9æ›»ºµÒÀ$̴Ǧ¸"úôlʉôm4ªÉuP7šÎýJF¾ÐÇDï`©ñ™ÜЧ_þ;²Gs?=tôò¼è]Axr›÷ñ2h,R[L&>¼-_î&3»ÿåÃá·CÀ_wø_0±€•À“ ú|ÆO¡vÉå¿ÿsøþð]z‚­S.š% ÊøÌÄZ|ä„ï«ð¶ò½qHfžró\v»õÓ½1Ñý8óÖúç & 8RsKbt ðC%¦eB$€h5"˜a[‹_©—À¦ZÊ–­ºúTÓh¦jù%A\•vC6È‚–>B½l .~–Ó$?6írM«_ÆæˆÇ@™Âìšð¶½&N–†wãbPÂM÷xÙQû²³¨MDçÌ…7ŠÀ. ~–ÊV ƒŒ>µ£¬b" r¦|1ÁÁ2-=5öYqpFîStkßÊ¿á5€p[˜Í¨¬ç–O?õHטP>68#ˆyjp¾ì´¬ÜÌ[/ø6 þõΣҰ߾!aÙ¾ÑyP²IoV‹îCRwŸç ‘ôúG‘Ff'„ã»:O³ýC3ÏWkëyº\Ä+ ÏÃú 𖣉½šá3;ÊäÉ«Ë×):˜¿Èá}›f)Å›:Íà0ÁØØ×Ï»zœ“Û¼-«y[üõy,5æ‹ØG ÍÂ)PLoáÁœI€#8rpä¡WÆÞ4Û¨èÞ|:€qX  /fé@š¦êûÒ~T‘÷)‹À篋˜Q]d’¨y?~?—WE›×(dvoé –È7 ®ig}œ–úuBZã[ÿâ»,Ó½œÀ|Té„y§©ùwø?¤ï½ endstream endobj 39 0 obj <> stream xÚíko·ñ{Å~¼C´,ß·.à´i€´ U‚Da;²-C²Áh܇ÃÇŠ{w’å¤i A¸} ‡Ãy9;ý8‰‰Ç?1999ǧg—Ó§'Óÿn&ÁYàa:y>iüšfk˜3ÓÉßmN7§Š»S¥ù©2:þšSee¼N÷GÛYšA´¤+›­È€q€±Í=‡A–gÐôÈ4@‚3 ÝV:cð7Ž‘FhœÂÁAxŒ$¨øpjüO˜,þÂ\&­fûýÉ‘¾áƒôœi¹•xÀ…Ê0ar,8€°,øiÌêsþ*C´ÜŒWb* ‘àÄå¥ëÌLZœs°X©ÍœpÎ28fdœL1“¥‚²ÈCÃ+×hU…'UF…ÕÈT“… ¬ˆŒhS ²ÚeVØ+q"«Ä]E@ Z¢¶Fgܺ{k9Ò <ıíjh\â®e§ÛÄ=¥zÞq@h!„»Åp˳yI¡e˘úH oyϳ(+£ÍˆøjéYÒw-NøH{¦P;z#òlÖ5lA‰²&1âLÛ‚7oÀ»} `£Ô·V„KnG;\GòÒ“8\ó‘“q ˜êÇÆÐHƒ!ÙÚ<›¬’C“­Ï Ò ,ã nEsÐÖ“Vžeó·Ú–æ Èä }Íí!‚;Óñ¤—'údš1òŸÆÙ^‰ã®ÕjÒúê®3„ë@Ž#¼Ø5$”IIÄiI”#†‘²‚Ú'•–ùþ¦§Dw+\ãoM`RÓN°fSÅí2ñ$vcgÒª­´CŸš ýêvV(A[5B›jŸä {‚+#¸Ú:“eGR.¬áƒ8"g^æ…= •Ë)°`ÌR žY—À¾¹±fÍt„Ä`DáJ•׊yŸ§7ÆfM~ùÍoãÓà<¼ŽñÉE§þ„ |…˜™71¯"äÛAÌõsÇ$*Ãó b4>Ëw3@¡™¼SÐn爸&ho‡y¦‰Yï³D*`–Ð1Ìvã¹ DU- l¨”¾2ÃW:?%1‚™ˆPù{⧬4Ú_ÃÏÁ æoØ™@>;™~œ˜ŠÂøiA0"–h½ÂL—è²TåÁÅôïékÌT[¼e˜ LÙ„\äé]'Í¢Õ§œóÁáŠœÆ Ä½ðHíå‘굡µp!˜Ó`"ì0o¿Û¾Ã.ûÖKûVköÝ0òïmKˆÆÄ¿I ®Þ[b¿„—°­Z?œ)J­2ôj¿Ÿpïë'Ó⦣èÃG¬ûb Ž¿  _-|øýáMäx 7‹ðñj Ÿº‹àÝjxx5´æ:Ëõû;Þ3vxɬ5¤ß;dd`(ÖbG&¹bâ7;vò(ÜàÑÍØ¡Rìð¿bìðÅŽ]öäGûÞaßnÕçŸriV¢ÓýÅÑû³ð³PìøÓƒÖŒÇÄH¾%R*EÁÓQ³R‚ö¬-Ó6׈ZÕòYxä S wBz‰Å8Ië àL43¡_y HÛæx»šEY(ìÀðûp” ÄÕ’j`Y|U%<zaà W¦ÄÂŒ;%• ³tn¬€ç=µoÆ£o¥ý´ZÁW–;*F³¶hݬƒZˆÐ•)k&böx$wÛ‚tÍiÑ4RïÉD?P¤òw³u7žåÅXÃ{W#x”€…_0ÓV§ÔŠy¶h`¡þý]X¨ßk¡~¯…ª½ª~;ªö[¨Zb…þe3¤Öž[ì6Ã[o6Ü›Ê÷“Ù÷Fø?&ËL÷68´!‘4fOâ¯dæ¬v%Žñ–F7_ì~V]á$³b¤ºwŒ èîÇïÿAyýºòþùƒjîƒö @}•€s¢\ÉÝe‰ÂÖ¥ÇC6§¨Z×óm:iVx¨Oy‹NøuÐi n4vä'tÄfñPÝçn‡ŒöÀãÅ‚k¼x-ìªP¥»`yüékŽñîÛ'FçºtÆgzÞÝv ÞçSþ£|SÁUfh>‚ÄóP‚¢ÓQ˜Äª|¢¹h:@H× Çtã÷Yi¢«rvëðL×nVªe¥XuïT¿á­ SÈ~T Ô(Øê‰ž|a>n¹‰' ›ƒàJvÍð$5FÐ(COLy×ò c™µgÎý[$·Î×Ì8‡¥¶—Y ûõ­ÖJ¾õrâc÷¡½ÜÔãþæ:ºþPšB™sjHMÍ„H^ã$g:T‹!©NEÈÓõ‚y±¡I`‹¦%üOÇ›Ãýeÿ§ž™Zk,É­™ÃÎ';wÒ~Ï-B.ë]j+¦66º04ÿÒ¡‘¦3ÔÓÓIÝm »BÈJWHßxðÏz—a)#Dc‹ž&\„= ç!³há5©W&3gVrÉ•Ÿ{VTöüQß Ž%^Yéô)Ø-j“mµ€¨Ÿ÷úÈÁ‰‰MÛ×h†Þ«;KéÕÑ·‘pÆ‹ïŸm§ ?j×D}A$ù"i—û¸—à?:a8Û7mi.©Å4þÖ6i@ÆùT4bÀ7úC=E8*fíÕÄí2¤jûØJ#iÁA<(}©Õ{´Ú® áZó „ªíKÛ9žj‡Ä^}€#ÐF6}Ú¨Mu±ÔŸEVÕÑžÆ-ÝxLÄAÞ<&ðôfÑO‡ÐáÙM‹§íf;j§³k—ÖÁî;ÊôÙ wÂêÜÉe6EÓe ‹ŠH/Ïžú,_V³ûvÔ„›ê;j K¾Ca|@>èÖ’šYÁ&RhÍgDhʪ«½öÇé–e ûW N+à>@ 0+ 9NU/yK®«ï6ðý©µ.%¿nÓûŠÅý¹ADâM^»ž:Té³myâuª®†XNÐÔ[›¢ §4„¬¾ë¼ÕyÝ„G’^ϵÖÐÔüªj*6VÚœé"RCf^²ÜÚø °Ÿÿó_ÿha[·ÛµS>%çaýÐø µ4[›]Æ-M>ŽR0Ñ)¯qâÅÅ›Çgÿyrñøí“§¯¯~)^,]›¨‚”¬4nj*2ùkòÝB´M›}»^k•Eƒ>6’éý²»vY³Ö°Vª3LöÝ·5'zp3‹<}ýPrT9å2Ç4NÙ[ÞÑýƒû蟎÷•ýmvÚχJ»ÓþpÔ ™wñÖ­vþ°éYJ8˜¾ŸîŸ~:dñ\ñQ$¹í.ü]ŽæÕ:úèiÀ† µº—……®e¥T»7r”bÎ6.wT8ÈàVÍ€ÞÒÞŒÛôû+ý×qT³£C3ÄAÕ¢¡””v-š/‚tN^Ï m¥¢OP“¾Œ´)V~Tfo‹Èô$¹&]óW§W»ÎMSü´á© —Ò©?'@hÝ4w'®2¯Ïâ“*§ËÓÔ«L4ÊvúÀ#%¯¶Od×°àIÑï¨L·ø6sÏyS%y¶Ù¹²<‡ÝE:¡vQ¡„ÛÔí·TeÖ' áúޤÆúŒ’ëgÊ 31®DÞ’—÷UË ñ¥8L7–iô!0:^ÆÚ/¤Æ´ü iL“²¶AŸ,ÚFW›w’iEhh€²=l;D—‹û˜á÷Ÿåßϯ.¯®ÿ»õ«,µyô_<¹xqu}þöå%Þ>¿ºÆ‹·/ÏðòüÝÙøìü5ðæíÙ‹³k|÷æúêéÅÙeþ¶ãП=ƒÈýòõù³'X‹Ÿ½ËÛ\]¿E¸ã/ë§DÂ7/QÕ—ò8êÑWë¿^]¿aé©Úˆ`9åÁ-À9*8h¦/ Ö9¥èú탢(¢±~ƒDPǺ[·Ø2´7ë3 ºnΚœz–ºª~¹#¬›o°2ž6õM* _å]вQ½Ù–r“@ç¨E;¿þÃÏ~'= endstream endobj 43 0 obj <> stream xÚå[K‹-·ÞçWœåùc3 /¯ŒþŒ‹¢ŸÐ Mž&Àqªð.>­[/.wN“vÄ)üøôûÈË›PÌ£´ÃþqéVÑ,œŸ…­sÎ$yÆÂ¼]fR^®Q8bzk Vö:GÝf¦Á_þºfŽæD-íµíñwîÉMÝS$ufͨ!ͳ“e" ½ÃJC>&pä»ËÜHóÀµ[qËË¡%è²øÞfvHg)ý*À›4l†;†¥d :}AfÁD´Ðù?`xÓʦÑÔ<­Àby¤Ä‡Ä¿8¨ƒ!Då.M¼åÖmÄ&S4íá¦/k„¿’žqœˆÃÉÀ`:‹iä€,—&UÅ*÷• TôúÓª®¹ˆIÓæ!®uÙIsÍB©Ò2ÙóCZ’°,¨~Yb!…k‹ÃØPõá¦LØ¢Y±(9š·ÆÛ\¥Š#c SÛŠ…á2™©Ž‚9±ç0) ï«©9kIFÆõHØŒ0è6àY³l¥(ëMPø‚rTšÖ H`¹BÓÒг¿õªh“sÝÁ°Æxs  VzM¯_*¬ zС­Î-fJ+(X(7<(M&„¬÷QŒõ¯ €“Æ\›ø‰chz êP"*]ÐgÍ€é ™÷K òLFšä6€’æ PÒØ3@!9¯$Žd_(ËLèhÒ-NåZƒÞ{#Fñä4iäô.µæÝŽ( ì2L³LÊ% ™œ5‰_lle`ò»Z´ –ƒ`Ã1ô°h ]6Ë}í­s ýÄ0çÕs“'_nðõMú³Y©åØÍÌN(îâ}(Nh ÑI‘ük¥>V Å žq×hÀêM}¨Dñó@‹ÓÉ]«Žç·-™µ{±qÙa¶¶0õbCJ,jí!Hôëì›{ãqù*rA¼‚? ‚íA û„Œ¡R€—ö)ɬL4žTÁ§Qâ›ßÒ›@†Õ?A“ßüº(™ƒ­Ïl³™7#"´^]”·½‡‘AŒþ¶â¯‚¯¥(z#Ë|Â(S|5riñ—Àiþ{5„aÊ †è—©|âÛQtbêî`•¯Zw(ã 4£Ÿ‡{A|•ã©YýÀe7盨|10ðþr_;¨7YÑÃûÌ9'„“¶|D„?!¬§þç€oBÜÉÓx¯6yVècòþÓˆ'ñ×E*:Üæšýmn|x}fŸŽE]í­¾‰+¸4ãd‡$òÁÔÓÅÚáN9`ìP±Û22¦è{8ÔS™ùÇ’gĺ%K[¥E „§a1à1šŒw©6뛘6‡V1œR~bA êƒeêÇaP«ëû(žzS_m:cBkÌeǧœƒXlaÓ×í-,P„³» µÎÌ–À–ÃjÖõ«Á6D =½ BÆ%Äøs ýï[@æÁ³. Ë+?Ê> ÕtZ˜“Ð!Ï'7Š-Be{õd‘Û:1ÅE¼³[Ýš~‰œQa‘½°'²¹u›½pÃìQ.‘™K [L"k4_"w•I!¦… tªº(Ó–éíþFx½ßõƒÖèsd³e/5- ô'f9 Âvéû(«ÌÍGäT€¡za.¨J*ô‹ì™z¡âGõBê…Ãmj g¢½ŽáÖ R ªQÇï†iéϨã_G}TUæ ìsÖ;þ´ᦘ‹VCJÆM§òªñá%«%FÇ.“ºqÙq×ê|f‚KLPºÛ4úŽ ÊAV äuð£cäÃ8§"^Ü+ÿfð2Çi…uV¡CL³ ÷ÓŒß1Ù öyˆX˜AÌO fïØA ÈÌ’ÙCÄübf±OCÄâÎôÿ1J¯¶f1šrIÛ› b>´—âãL?a0Õ±ÁÌ$_†h&šÍ=N–Û£d¹9H–£ÅT/ÍÃnÐgŠ~Œ;9)‡Š.9ð~O:ô›éù®e~[Ñøå^u”£œS'/Ëᾂtøu`; ü9a;vŸpêØ¨)G0Ü«Êwª³Ý¤×MŽ@nŸ»’L”T¤Ð —Òi6¤³“ œÜ DÐ×´)ýÑ,8ü"KN™ 5Xiʃߔ‡i5;—®¿ iR…7>Ü|b›{¦ n¨rº¿Êð'eð÷·["A(ÛŠUÙÖ¾jmõ ʶnQ¶ÕmÙvll=Ó¥ rÆùlËÒ°f¦>LÑÆ•D½M"[+¢_½„mú˜múmŸ§Ø6š¤aÚâ(£õÊ}~Ä%ÚHÛGoÞølq{íH7éBJ.iŸÚuQnà¢úØZ˃ƒ(NÖ¾gIï‡üti:è}çZ—:LG¨;gÞdŸò¦ý·µ®ÉœßÉì«'^KÇ6ö öí»[ë\,:ªDÓk]½pàöObHWsfÏŠ/Î ÐAìt£Ms…µ/‹'–5×'îL¥ O¢ô3¾¥•ûÌw¥°û½{¤©«¶ž¤u`4uTSà¡J_^­·x¨\»Q- ¦Ò«§K¬{½Lõ‚C½|² û¦ îSwƌђwï¿V®WÛ;…ëT)K0ÂÝÒÜn)UýO¢ÏpS}ܘæêbÝø¾âÃMZ z%@B¥u•íâ ²¿6=Õ[£ei¥lŒ©Ë›{Ïͱ <‹zÛ !~!q¥K¦¸28¤GpÇóël]{Ïu| þŒ@wf8óÿ4ôUFNžÙ:·K–½À-g3Êc¹îwöo2‹sâêEçô_C«ÍV/Ž45—Es’Î4l+]ý…¤‰ÈåŸç•/ÕÿîéòÇ_ý]¾§E endstream endobj 46 0 obj <> stream xÚåM¯#·íÞ_1·ÚX[‘H}Œ6Ý 4ÚE4oëŠRd9Mÿ}EIÔ‡Gã¿çn¶ ‚‡ÏERü3ý8©I†ÿÔä`rNNû0ýîiúì 3))¼ôÓÓw“áìt¶F83=ýýýá‚J^Ъ þløÃ :}AkƘðþÕæxÖf˜V'K_óţчL Ê.P—#ch¿:~càîè8“hFºÄ•åÓ꘣BÛVÚF槸~EiX8~ûôÇ鬬ðþAaXqA]]6±p ¥=$y8L»Ž”mÚA7™KS1è‰`h‰H>KÌd¹[àI–÷M”T³ÚH+&sdxHÓ$Ì‚Åz^B»Ê•6ç($y%Ýo0xA?ûBÁä…·H¦ô,¼ŸÎ(æ„ü— ä''¼#³z:™`þ‘a°Àô90AaAÀkòÇ/óGÀðÖ»9¹'à¬êòvAÜc§òýýˆ¾¾Múï"È'~žþ5èð]Jjú0*¡°¼øaúfú:̹9™ÇŠDô× ¦\$ÂB'²–†8Oâ߃}¡!Æ­îH¸†„¦q‘`–»3^8ßn0¸½½Á‚Æ{¼H„Ï3¶TÍò§y§9µžìŒè_^Лh¦óYŒæºàÜFóóƒ“SÂÿ\ášQ0lѯkF4c:±‹+A¬ö‡g8@r¬àÕŸåÜid™Âº*À¨²Û2(HU¤ºæf‚KŠ{3°Ož¾7@·õóå0´oàsy‘J/a…r}?XIÕ¾C]éb}YQªõʲz_ŠcIQøÙÃF5é¢àM5‰–‚cq½ßU®±Œþr¨ @5ŽÂjtù¦|ɪ ìÑw³»LBmQ:½%ÚiCGˆÁT6á ªíjy*èWñ*2mª´³Ñ'&`.Ç×UÏNÈp¨Èâ6½vÇÎöªTSx3 WÑ$)¢ÌÌÑ/D1ßü–ßÅ5zó›!+zèõȱ…¨†“š…´7œƒÛO ‡z¬ï¢S¥› D±ðJ#ž¢eèâ¬ê)yL`Ì­2B1»?,–Â衷ص[쎂Ö"îˆÏg:°é9ŸÈÖ¯ò‰‚€TEɹnFB‘%~}¹ØÏœ9ïøí@&ÁÉ‘[ž‹§Ú0•ŽLE?ÌTpUl*˜¦”#ÃOj§gÿé™;ÙiE¸iE¸nEñtŠVôn$“ðD.GyΤüíL µpÙÚb”*õ–ÊiÇlFõ×õ"Tt,^E½¦B‚Ùî*¿êꌳUKe>d rám cÞJ5ÚTCc_í4*’º:ꞢÉZä× ëóÿ²h‚›E“Ò* LÜá‡XIjW^¬$§m¦4ü® ýñµ“Ú¨”Ëe\Ùä ñ$ol² •M6¸» t졎K;{™ŠQωÕÀÔP8õ‘-­RXy 0+JèƒBuâMy±&¤‚æÈÝUEÛUKx?ŒWa…ùçHÒÜj’ö€È;ÌßÌvb6ÒÍ>û6¥›¯Ö !$ºðÓ­Y®rÛrý-Ë}‘ D¡Z.èÀì¼e¹í¶åêÇX®»•3šÿEËýÙ ¥ qßZîh¯!3•ë!d4B›Æd0„½€ºa2­˜ E„×£ü¼%›8£"””«gà’rö¤×ªxî:}*%üŽ”-õ!¸qbšKÓ·å3MÑzÜY–d»çP²Ïþ—ÔZ¾>ÀRH;­¿âîp¸ŸTbG3zÙT,~b­£¬¬0¥þ? Üh)ײ{ÔR¾.Ó|¼ðKé߆Jn¶ª`»U¥VZUnÑ…š_ÞªÒM«êÕ2ÖÉ Á ³Pfj¤P§¢Ùò‹µPÇX±×û lýAµ:Ü®ÕõF­®nëvÐòiéŸg“.#æEX]KI$«Ðó‹ÛB×Òò¥Ü/Oèï†)F¼¥l{$¨Šk˜»¢2¨Å}7 ]acl Ú´P¤>e!Æúüb­°a4”ä”o®.yõWÃ*¬º•>‡Âïe±óŽØ6¨û¼§•«x ¬Ú£Uñ< {~V±d?Nò<̯íáS®“ÐÉo4í|{2Öü£mh¢éÔZß{­1ŠÒ.è±Ik`%­ zŽ-²æ¦TíSÆ>(MÏ8yÏ숓»{ž 'aºUºU¾æÎw¨é]ÆHIcçÉ#ÍÝåB7õªk7:×‹Êø¼6Ä SD– £ø;·»yCqéjÔVÊù-IQç’¦›®*œWޏ“Í“Wu™Bo‡”3S:‹9=¥~ÇLC"]Èê, Á6\ySFœòU×úþÃÛ¯þt¤SÉMu›«>Ìw•hð2W} £•zÄ„lŽñ‚¸Q´ìÑ–é—ã)£¥%m›ºüÛVVœj¦Ú;ÐÏÁ±hHŒK†—f2žŸjTª5ìV©`pÜÇhWå5Ÿ"æ0Š1-·ó¼Å]Ÿ·´0ë™?¶_›ù!S8$ÐŽþ?~esÚ6–£ Ć+ªÐø‚£ÖSÙÒK†^úb°VHü/_r¾¸aÕßQ¼¡]»Õ›}g÷vþ<"þõv¿Ä®~\çÔ©ÚðàT:qÔCZÌÏhæ]\îR‘žy:†ŸêlMémí>,§¶uµgØÆ•aÕ Û¸»†mÆõº¤¦ê”0þ1=ÓGê´§Ñ›àÚPÎzújb›:lužW“'z²Tªóו\ fVÇÇÜv£l÷©þf(é›)Ž;`šì’*âÆ(€âvÑž˜£±&y§˜Ûu=•†m£¦îÀÃZÌUæùÇ¥‰µ;/5%ð$R|ŠÎôTˆ^œ‡¥¢˜³¥ò˜°³Ë” ±«+{<Ñ[,¿Œ†ÛÕÙ# %´Zi“c3&gþ”j™”óq•a/l¡û‰Äž}–é22­k8óo ¤¿i젯ƴ‹/5v ¹Ü–¾Q;mMf“2CuOÛB¦¡nå,µ\©õ’ï,7þþÕ— endstream endobj 49 0 obj <> stream xÚ}S»NÅ0 Ýù ­DƒãWÚ 6D7Êbâwâ÷ÉÃ)å‚PU9uìcŸcÎó!¤„ðz‚Ûnî"†XßÁ($ƒÉ4$…õíyØ8¦Õ6¶˜-o,:N¤’o´ÞŒ”òY¤Eù7æ;m™BÙ–K& ÍSñ[Å#y$ól£R«ÕLÒÐR>[­Ï^¿Dz¤¸Õ?£­a–º5+¢ñÀk`ÜÆ#Ç‚¯8/ëLÑÂÂÙpЮPG¨õ½—¬ÃD)z]uUê¹×þ‡£Æž]µ+˜r]\M¼šš\ZµØ%ýÑ@Åî‘6¸*u¶ópÙ´D—Jc»·):Qê+q¬@­3?™ô¾š€x¡]ÙU‡U¸v mo|Ÿòt˜qðˆØ¼yº®«“ï­+2×¶]m©óñ̲yjKw+œ!È2Ã'D›ƒX3c8Í1̺;>à ÿ7DDò“æ@V¹Íûñê ýºÈ¢ endstream endobj 57 0 obj <> stream xÚÅVyTSgÏ#𾤌#ÍT›g=gÎtƶ¨u$Ö.VgÔb‘VQk«lBlšÂ*d¿/KB;¨mE*ê µBÝÚºŒÚe:zjž.ó¥ózŽó¦ËŒ3óלä}çž—{¿{wùÝP‚à`EQ3Ÿ[ýüÊ­ñ 6®Þ»(z±Ôÿn‰/Jà[ä[$ôÝÌ­äÎÏ YõgC(ø¥ÿLú…ÿ\;“?¿ãpÃ,Á}9÷×F¯xvÃË©rU™ÑQßÞóÆÐÄÕdYFÆ¢… /¼#<¶äްô÷w„èÀOÑ„€Nô÷:ÑA–ݤsé‸G¸G0—Ì¥óeóe«eÑ }lU–<[™Ÿ–;/6+5-W1oC–‘ôªÛÞ&ùš£¥=;ÚŽTáùë¶pHq›zïØ[Ú.ßãêYO‘¤ÑÍäáÈ[7ÈMQý¡C=ÀÏõýñYf'Z¥~iyy¡.T¸9b.æ‡Q8ÕÕ0†YšMéNÙ¸ŠŽœ°wôÚúñ»…[Ñ+úD™$ò–Ì4ÒÁt›»Š;²†7vÅÃØ”­Ü¨/ÓA1έ/jmñ¸[[ŠÀ£M§7tHlOëWïÑôúà*acÍ—peéë±6ákjUùVª©¯FIÊQa¿o•¨Äƒ:¼Æ4†»€d9ÆI‰óT ]9–×KMM£jð¨xÿ‰¡ûO:jªkìµ,×+ÎÔ–ÆM)–¡¬lËC. ÞæªC7WâB]&²´ÂœÌ„ÌDþIë**+ô»ÍdŸx¯Ãý–Ħ#Y2‘Oij¦‚‰¼ôŒ†ÜM”•'Óí„ H¯ÎmÅÍõLäPsQ“2_S˜s9÷È‘+mï´kóó‹T9m¥mB­Ê·^Mù£Bá¾y;é <®‹Ö,¯H(Xö"ƒÆQîÄM ®OyƒJ]R¬NÈdŽBûE×á–ácûu\‹ ÑÖØbÁ7èG‰Šá® 4¹YvWT~JÊÍß>]ÇošÉÃÂA¿o'êê2í`¸^ôbnN2oú¨­5;È@;ÛÁ?$SìÜÙîNˆÚ5e­´–Öšë¡é´kÏÀä듽ŸÙ]§ÕÅr_‹Ó5Ú­ü1ž"”›cí÷ûîku ñ %X4ÚÒDŽ~‘&sˆ[à —ZB~ÜY;F¶³ Pn¾mˆ!R²ƒ“¢LSQÌÏU΃¼~ãÙÜ2õ6TLA÷óÒ!?M:Ç…$Ç'â‹×<óðüsü`Ï!3®ô÷•$œ›-áæp ‚js5TÃç§î­wxlõp †ž®^ÁjØB(„xÃs²„<ùÎ,‡¤K•g±©êLuþyá6y}_ª©¯GIݸpÀÇsqzµÝÀ|—€@Ë“p%–e›’²çÕÐÙùÖ†%›Z·åï‡_‘ð«$˜3ð—ä TX x’{N¡L4¿+&nN'Ò¯JåB¿þø0C¢8Í.pá±³GÆ>{›µ\:Йõ?0 }€Çí#_‰ ¬Ÿ=°ªD£V5777Ôw¼ÿÄðZnÖ*îžy\èµùd&3'Fß¶XY;OqVd3°Fžä ØX¡Ü’˜ºÔ ²ºb ¯Ã9|ÙKî%A’Ã0¢hLÀÓÙž.+IöðEÝÍE…4Ò–öÍ–¶¦¶[7à>ÚË2Ü8¥^%7ªjþV\D ž,$“ûË=ŽÙ&¯¤_|½;Áï¼Ý$ŠßyÔÍ㧸üƒŽGÙ‘Ù&oS´É{Å6}µ–G¯«ÔõÉâ”­/IŸ0ó7/ð MË3%:wdÏ›üªéÙ6ܳÍj°ðúP\¼»Ø¯ö ¯Æ—·¨Jå,m)iL?”v0}Ø`¯¨~W9l¶WÅû‡ß¸r™ÅnnA jÒ;ÊùMŒ}Y‘ j/èT{ó÷ˆ+j+à„z·ÓcÁSÄÅÍSù>ùÏ~À¨®nµCaUX<ܲ:DC˳­üÙøQ—O¾‡”BÂÏê všÒçØ÷2ä}Ô]í>ñ=cþt¦f>•YŒÖ¼•wZâ¢_‡!¶¿ s÷Oÿ?¨Ä©9ÆäŸ›°:ÔÙiLf81Ê^jJ‘(é-Ú£=ÌÇȶ§›åËjwÓ<Ó|ƒß{ÝìÿÞð·OÞ}†è Lj…DÇÏ‹Ò!Ý”Xùtÿ“²Ÿ;÷훊˿<^!Û6FÞº{%,è”íZ_õE\ƒà@fŸ¬9µ%™M¼„̦ï°ÊZn»h’>q:5fÝ Ië™´Z›rØG‹JÜ(r²£‹çtîßËS”ü¼G²•öc ¸Y7¸1Æ5õÝͤé|“Ü7…|lÙ¢ø§žáîùƒžoÈežrT®aëp6´ÕºÚ÷¶õ´ïmé;j¬UnÀg¸9ôÂ¥©ôÛx_±ÿžÖuHÊ1•3°âSÅI&sëDJPš•€c±NžkºÎ§Û,*5Qìñ­t¹¥©™æ¶W#I˜ÐùtxhUx>ãfØÈ É¢Çi™L¶óö½ÿ‡¬Üâ endstream endobj 59 0 obj <> stream xÚU PSW¾WàÞ â‹˜mܱ¹mwÛ©Z|¢Ö¶ŠV±V]QÔ*U‚yðLx„GBHþ7 „@$(âƒ*Øú®ÚâRû»»µî¶µµµ³Ý®Î =ì¸7.tºufçÌœûÍÿžûýÿÿýß!‰ÈH‚$Éɯ&&oLÙ2kóêäõsçÅLJß-Í$B³Æ…fG„‰ÄëñÇÓ£ ?%F=Jdú”ð¾tRxÿÍdn'frÛøoãˆ8’ŒáMrNÂòµÉ;÷ˆeÕõà;œž“37>~nÂ(˜7wÌóFÁ¢…c`ÑX< Æ‚Œ±˜„%£`ñXÌâ±ýtÉ‚ø9óWJÅù%ÅY…­—îÉ*”<–,§K~õ’ËiÊ"ž˜G$çˆ‹Ä q•¸I~A|E|C|K|Oþ@Ü#F¸”'S! ëÈzRGêI di$M¤™´VÒFÚÉFbê8‚$Æ ‰ÓäjòÝqOG|YõHÔ*ŽRÑ“è^f&Óý|ôý˜×&Þ''Ý1¶É¾“ûäq¼sh꾬N^…LA[q à÷v y¾@‰¿@È;W:}=0Ü'·e'åÞáßz ò¸Þ!dâ]GÃsø8¹L•0‹Ávâh•ÐI¡äÖ¤€ï^?š.A»q¢w] uz-0˜™Á×ÛÀ6€?šŒ½æ>ÿ!ßÁž¶#À é*œù »‚†uËò·•íͧ£¡pl£ -PÝåaø04$QèFÄg!/ß;pêìûÀ|ùFÂ2žL\òÊÊ•K²bY‘¬¨¸@ ©­­ƒ*Ð8Lˆ hYT U›jÜ™R褧¥ÔÙ³§Ïœ?õÁ•o‡à.ƒâf~„‰óŸ{JÒFÙa ÓÝâï`Á_鑚ՠµnŒˆ,tëÃr­ü<âæð¾§FµQæ.ó)·ÃbvÜÀôR.îáârÛDɤ¥¹¤8·(W¶ïeLdàÉ€yL m”µVø€i YºüìIÐ8šòöw.³¯¹í¯hŠÀæ°ZÀÍ8ñãtdÔgÂFH¶è‚qŸ}ºÈDiÁÐv9y ‹/A;‚t~¦ë N‹ÓÔdñX¹eï0iå8(¨&0ÔU¾[±­ÈVlT›TPËHvêó…d ÓÅPl¨jªnÒzµ-«PÊËhkJѶÖûeP µ®¦¶D°oHÂÖâ Š×ä/pçnA•|Ä ›ˆÁ7£8RÃ1…x¹ m=0Á5ªË‡t‰@k‡—ó%ÝtwW]6 x‘ËðD<#?G\“LU€K¸âÙÞ2~rì`O×› }ܹ÷¨ø@íޱϘmÎfÚ¨TR Uú*˜¶/Ï|˜‹Á &ÔBë²t àÔ;€ Òø¥ç×—–éʹöÞ¤TJp²àò¶4ºD³œh; L#°ÙÑÊëÕç°#nT%¨@­ç3ñ'¾!8ÅÑgÛCÍ×"ú~É^­×€†QÑ붪ӹÂåé×vد²†Ðqs¹­ÜR>ížq?}ÏèÇÑS•Iî®g ”L~“½Ê4õ4õ¸zœÝ£Õhm°F.  ÖnF–H+VC5G†‘ –`+2eÁj°ü\ñº¼^ž†3FŽFé(œ:*?Qn|Є̕rÿð2¿^wþ›Pö×Ü8ÞNáãç*ðøw€3œ€"ñ«H„¶">Z‹’¸9Ek0mÀ;…¼~ hŒ¬h$–߉2&ÀEE_ex×÷»ºìàKø`cïÒý›íka`þ>¼ÏÝSU_©«Ì 4CÆë8ÔÆ;u7Éo?ÚçåZ}ñä¦-l ý^%ŲJÚ¾æFÁe8 ƒÝ¸ÂñÆÔC9½pº›^g>.ÙAK´i¹yêBpà`KsÈÉ¡Û Î-Y·4ëy‰§¢½½Åãï(m.¢LÌãϦy§VíZ·*k{×!|ñçþNWƒKï2Ž2Tµ…â}¨A×å/¾†º®óîžG×øú0rëOϯœúú#´"3p±Ð­Q#¬yB› ~B³fÓÊ•81%´¾Âë™îgïínW´œ”éî š4xûÌßR´š9‹ù|ÞÎÃë}ë­ë‡[lS+…#åâž ÓfØ›õë²R EÙeY°Ò®Õ~ÂèÁ¡o Sîú„Áš#'ŒØZÉ/m£;ui,>CgUÔnÊQWJg‹Mý,ºLƒ×ÔÔad©«p^cÆÓ¸yªAó¢œãâRŸë%ƒŸ"啈{áq>F5šM?nùÇàØE˜Ä óߘ÷·½~e‡šËÈH} öù>1L`b̳–S­6_]U¸+5/² ÇWÔ™ùfÝx›1xøCÇ¿¿ñEûïW 9i²Ÿîã2Þ}u±WNK¥¦#lƒÝn3[{Ï ú.ö¿uâ’Åfµší숔UkG%ù¦ã,:C÷¶Z/ =X\ꡃõ{XJU«UgnìNÞµ9m“¦V­ÖªôÈ'8`s½'ôÐÿEæÊC˜äye´¸Ðt‚½Kƒ³ÉÚhmnjvµ8ËÜΊýû:÷öZUvT1• •œû ÙK§€ü@~Oú…Œ i46Uko¶»].ç™ãƒ—ßƃ–Òöz+'"ÐLƒìmRiñQ¦(+»i°„EÁt»¿æ8ˆ2Z0Y¸½,Ø 6Î*Ðãœè§Ac¨ål%M¬O}x±ºö×g°xÎDèƒvçÕ¿‰6ÎB‚CáyèGå¡dþcÊg愯.L}Ž#ÅÞ¾‡¢Ãæ¹MÀÓ8ï¨ã¼£ŽóŽÉØÂÿ¥¾9óø$þ³ÂÉ㔠zÖšÝFþs¹¯Gt†ù’Vº«³>I §§5“%Öå +%H,¡¤¦Ã¬­éH¿Pr¦¡ ·‰bPdŠà†o ìÊß›É\¥Q3ÖðµIEË“ö*ÔuÜ]‘úÒÉ3,zކ&½š˜·Þ;}ù‡,X-än}^&Ùyû?p‡{à /B‹(Ó.ò絋•åMÕŒž®Qª*•Õé)‚=¯¦¥&é9Zá¥e&• Z ½¥ÅÕâ ´uxœ±ùr¢vQcuk)Ô0ZÊåÊŠpü¯’Þò¶½§Å½â×EÇ´6Mme ô;ïô!ênX@‰¥´×QZÁB‰BQ]^­¨VÔ(è»–ÑSe%y@é,õry4p£ï±·˜±¦þ¬¥ìëÑ’Ž~Qþ°0´°wµ™Á4ÕÅ‹x7ÿ+êÒ@Ö+¬š®MNÍü0IT‘Öq(÷…›‘¤ÁÝNá …1Žc£­±1†Øñ9=^8/7Þl6[îOý7Š o endstream endobj 61 0 obj <> stream xÚUßKSaÇÏÙ™ÛQç,ÑÚÊÎ9A–£1§!6ñ:(3œ¨YÝ,=¸•g³íÌ9¦¦ÓµcoÎü1Ýš:§RPtq"¨›¼èBè*¢+Aè/÷ŒW²3/úïûçý¾ßçù>8¦Tb8Žt·Ú:¬¶‹Ö¶®îËÙ‡zîW{©2IåH&ѸÄ(¤³„tRIí¶*5Š3†Ÿ8žeAa–Ä1™ØŠwE˜ZîX¬g¦çÒv/ÏzœÞûœw°ý,ǺxŸËév™Í—Lfs•Õ=ð8ûÀ”×9x~ ¶¢Âï÷›ìœ×äöô5ŒŒßÉ;˜NÖËzÙ^æŠÛÅ36;Ç2Gk™Žhus>9Óæîe=.9ºÃ¬ »-çŽGpŸÂrŽ)1ö ¯Åg%A›Ù~ßËœ&2íÐ_’LƒõuÒ_UAàù4HÒZéÅÖšt*…ñτT u% á(x Èd"¾BƒÕñ™á¹–—ÞÅ[)˜ûI7]]˜Æf£1°@.…W9 3$`ùôòÔ¦ è`d8:B>T'é†fðèƒ#£ Å"Ï&wú7Æ>øQî Ý„0šÆÃÂ8‘Äh’šÓ`sªè†QuŽ9//¤(‹¼z¼ÙÞ¯ImææuNe¾÷ž¾ÿ·V§*iHîC# ¡EõG@u*Ԃʃš‘žG4¼Jút‹ "÷G!1(JSø¶(…E"S*m—$Ašç/H¡5x:¬wl½M“wÁ=Ð> stream xÚ­V tSeÎ#í{?e“†`xëè  -P ŒÊb)PÙK«¥EKíÝ—tß’6ym’›4{÷t'¶i‹–Z¶Rh«Œ::(.€¢ˆÃ Ì8‹eþ8ó Žž9G=9ùÏ=ïýÿ»÷~ÿ÷Ý{ ‡‡€ ˆûV­[½e놹ÛÖ<¾ÀßßÏõÌßé'p.ç\(tNóàR¹÷g’Yÿþ½ç,€hšêZÓ§¸ÖˆûøUð(¿LòHÂK4ó‘ùKW‡DƦäÈTƺ¶îþ£Ã美OHXàç·pÁ˜±ÈoÌX²Øm,qKÇŒ¥î=K¹ ·áÞ¼ôÎæ·±lÌpp; Xè6Ü p0À}j™ûÕ2÷«eKýæ/ LKIÏΊ˜½1-6.3uö3iɱ³ƒò²âRcãbö’ÇÅkñ†à]Áùq_GXÀ7y ¼"¢‚PjBC¡%tD%¡' „‘0fÂBX‰*¢š¨!j‰:¢^ ' ãkCÄrâ‹q9™ÂW=žð¸àé c( uÙÆÏÀ+Ðëð„E>™Ø5éñIßN¾9î‘sõÚ>ç\çcBø¥ó¢8†€#úCuèÆËܬçÔ>n†óc ôZQm¹¹ˆÎƒÜ¬œÒ°ÌÍì@cßÀžNè#FðTŠ' 1å<&¶ïh= èüà3ËÅ>±òéëCC¶n ߬P¨ËAŽrœ~”Ç{Æ‘ìKÚçbAª’‚÷9thèðHÿ#ß„Q„%Ü´×ö娰ÙÑÒîÞ¶ÎîÞ´¶xzòMáŽá‰ÜÊüÜ~çå>÷b ž*ÄáߊcF)ࢠ¸rîIîQe9ËÊ¡ʵå€ÂÈt®Ô³—4¿¡ïè«}ú#€œÓÉÃpDÕ›v4Þ°Ö¼õ’é¸Ô“CÎË£}äs¸_ŒàM˜°åÆeròM‘W%Ý5Þó#ýÎK˜öÝr|ã•£N “c°¡/ŽLLÐÙ­óc}^uŽ%ïϹug¸àO¹gME•¹­Ð ú&Sý9¼ñ3¼ñ,Þd¶Ym›öÆ5‰O >Ýçã¼6ÚÇ¥EÀ*Ùb¹T²Žó[Ãù®å|•…ŠB¶©I¶±Ô¦°ãùkð<~•·IØZÖT侘rŽm;€ç%;¼÷^_ƒ=°ÿèë½¢³xžs¾¸Ãd7vÊða(n’ÁMóÇDö»Ì|d·½…´äó¯%:æ8F¿B(3s²Y{c©KA'¸iÑ×ë9B¾x·=·ÃÑÞÚÅ@[I]^-¡Üjñ‹‘ð”S †+>}¡åë6üÔ.ÀS‰R[* ¥qEIJŸNbyèÅeš‡`>Ú@Uqcj#ˆ§Ü„±/'Ó?غ?ªg[m(¬†yÒø`t’ QpTûÇ}½­­ÝU]ð DšWèrµ¹‡¤D¨CRâ¤)ñÅñ±uYŽŒnè¯Øçfu'~ÁŽÙ½¯ŽâÀë‹ñ8Ñh—s«8²@µ¶ P“MUÀpW¨Â|U-™¶ P2>@½‡'ÕbŠhqï9÷5œ¬wÐ%njM½˜K_%E£o;¢BH’gäädæ$kRm#KåPÇàݘ¦êÍújúRäØŸ\¸™|“¿¹¼‡ÛñŠ.¢“¸ä+!þÎã·È½© ž»ÆÍc ´hgbhtúXƒ¸‡1±Óô)8çp|¦Õë*A,e9/ãò EqÆKáÙ‘ð<„·eäõj@?²{ÀÀý•f{O}7 ¯Zç®t9¿tü{Þy”8¼ñ—×ãḂObx_ã9+œ@׸¹–ÕtìR'—(Õl¹RÃÓ³òZ •U”)^PVR2²‰nÍkížýCV¾H }([ø”,ŒI$ËXU™Ì ªfºIÑ¥‘/ع K)žÜT›àiSÉiT£¬,¥YR¦bËÃÂÜSÌ_ MÝç U•ÕÚjx{gw¸­ÄPl(Ѻ®ñ%œ«ítÞo'.âÈëÂÎ_¾?µ#ÊÍÕš°:^«oí9Ú}¬ûhµ­º¡Êf0Mz‹–;"ùùªJ4r@¹•õ _,õ<Êø •o54U6ÓUP¥1z™S§Ù©FhÔT*š…’­`Cm\¶°\Á*+Ê4xPbkªlºs€º“Æô—‰ËWî&ÖAÉA>P-ó Pg1XµÖšš:³^i` lK†¤+¦;¶+¦²ÂÈ‹J² „NÆÙŽ<*Jª š¹Å8\šÊÍJ#ÒRŸ ž8Á•ÃJ>[E)E;Òs ÃcÃãÂcþÕô?Wàœ·+xo¼«‡/@¢ƒ˜¾•B5¸. 55¨ò™H ü5¾ÒeI<%Y%(@©«³XÀ†:¤-i©ÙÙIáý)ƒ4žf<Çðî î=Ÿ–Õ› õô(Y_­Îg¸«”(¯8W•Kóh÷|=® ?Ÿs]ëpN·×ûÓþ&|åV´Ö1ÀTy wJOPgÐ¥ÉøYG™–¨ëd´ø¼5±1±6ñ‹ÜNk–5Ûšõ€AnÕjŽl‡ú·êº:ßë|ßõ—k͵úZ-÷ƒ¤(ÿV¤%·#-¾'"ùRi )REùÆ?5_¥¨P¨ÊxÍ©,üO:,IâL 1çôÊJ‹!¥5¥vÓFr¯­ÃþWnš6žQ“[aKñ ñÏïL_ kG_õÃ3é“ðQ§ãD¥Éh3²(tJZIæ®H)ËŽ|Q hÎ ŸaϳV<OeÚ¡½¢µÂu=(䢶 —ãåü`ÓÕ}FEgzù+’sËùÑNtðMã§ÿ¤ÛI«®¼Ì…w¡L-ã[Fdk²\ˆ;(ÞÖò6ßGdºz_tƒmÑ,tÙ {•Ht¦)M·ÒøPŽ—{ÞÑÐb;Žü©†\Õgt³«:øS95yQ'J`×nAÜÚßH4Í|¹äî§R+إ졿¡ê][­?2DøàªöÿVz&O߇ë©!Ò ìém¶÷Á~4ÊMn^HÏųȟªWL¿›ªqל¾1ÂEçÈãÇÖ3 UH ó3SbUñ®‘¨LUia~:Žeôæô‹îW¡uàm-x•x—¯GW„XŠ¥â´øÔ]©»£%IRÅ.—ËBG1åªç*#ÒQPÝÚZÝÐÒÙÚÑÚik“Œ•FÞa·‚,É»ÅÙm.°÷Ä…|*‚`SjRQf ìBO—0Lãù-â`rë*ý t«öíÚ=€^'«tl)3Y^íÜbÁ/êíÕ$i¤h/aÕŠ‰ãM½´'\öœ@/I ¿9í?EÐv« endstream endobj 65 0 obj <> stream xÚÕz xSUúw.¥÷\A¢Ç{Å dQdÙÙ·¶,ÝÒ½I÷%{ò¦Iš4ÝÛ$M›6ÝKK)û. ( "(Ê(â‚:*Žã søþó´Ž3ãŒßóü¿çûOûä¹”{ßóžwùý~ï¹aDІ¹gîºEóW-»rÞŠÅÆO{Îÿ·I¾%"ßÒ¾eA¾û’eäÝ?×ýuVðC"Qü^ú9àÚ0ÿg÷=ôS4†~Œû,D4y€ˆÝ%.zHô„hœhªèeÑ«¢•¢¢í¢8‘\”'Ò‹¬¢ Q­¨EÔ-:,zCtAôèSÑ7¢¿ˆþ‹AÌ=ÌÌ#ÌXf3™Ç,eÖ2aL4“Ìd1jÆÄ”0NÆËìbö3'˜·˜óÌgÌÛ¥ÛÂ’#Ÿ‰HO Û5aüø SÓú/ž¸˜¸x6pñ\àbrà"ðÔÄÀSOM <5qbàbRà"`gbÀÎÄ€“O üeràæÉ›'ÿü_S7¦ܘX}J`õ)Õ§ N œ08%`pJÀàÔ€Á©Ǧ,O Xž°<5`yjÀòÔ€å©ËS–§,O Xž°<-`yZÀò´€åiËÓ¦ŒfâìxiBjÊö¤‡ÇoÛž÷ðŠxiXÜ?üQ$bÄ÷‰F3O ?x¾h!³L&Ú&ŠÅŠd¢#¢cA§˜3ÜeÑG¢£  Ý-*&ºW"ÓÊ”ˆîÝ/ = !zP4Zô”èiÑÑ,Ñ\Z©‹Ek£g 0F¦€Öœ™±0…Œ•±1EŒ)¦5XÊ”1åLSÉT1ÕŒƒÖ¤‹©aÜL-SÇx˜z¦Öh#ÓÄ43-L+ÓÆ´3´f;™.f7ÓÍìaz˜½¢Åþ6@]Qоef1Ë們2ƒPPÛÀ'Þ¶°Ø}h+ÚÍEš?hÏàWã»Ôw}2døÕÝ÷ÝýýеÃB‡uÞ£½W²@ü ø›áÙ’'${ï›sßë÷+Cg?0ø=#"F|õàø/ÿaöCQü(¾UÈ|xôÃ-#×|÷‘)T<*qbÔ‹£ŽŒÞ0úƒ'¥O¾;¦xìì±ç‡þ-h$߃‹œLöJd·KhèßÅ13I—ý5K|wB|Ÿ¿­dkÒå¹¹d¶žÌòŧȫøqrYW¨)®Ðd1 PœàÌ+}‰ÂÓü|^‚ïÁ÷X,%6(âÄíYËÏ@o0׿Zš5§Ÿzƒ.¥Õt ƒ¼Ú4{î_HHy È$ OE“IcÈÐä„P•*W NcÖYx[Ràp–”à{ñ½ðLÀÓ/\†“'ð0­ImQƒü‹ù—¾ALfÈð^yȧ8Hæ¤;›[%1ªÀÿ³$iyøN©5§´èÌ|9¸[‹«k;ËöÃ>n—âì^üqLzRbœ[^'T@©Õnç†âe'˜b¬—¬ÀU'Pß .Ù·þÀ‰àû¿“Äk³S •K©Hhj¬®­åÅΚLO />B7hÐ÷îÿÖ“7d®Û¡N£<¤ólÿ@|çÜ~FB–e¨IŒ„gŠÈÀ7ç6o?œrðX8ŽÇ`ªŒUP78hÉNܽkMíàÄW4 1h€#ì18ý9 §-§MæÝÎfWs«{x¡!Û™²g£y:Ìæ–!H4ÆC}§•¢áÜO‚®ßž&‰![‚ݬm¯þ@73[î‚àðrvÓ+k†ÍYúØ2„zÅå!Sju– ¸†Òš¡BâÜ»Ï|£û¬Í^h…2®M†ÅºGa9,+Ô5üRúw×…tí—wãºÝ²âx9þ\b@3£f-…ñÜ£?Ì¿õfÎã»x8)=º±%¹2¡4¥šVë©ÚÓ'á¸þâñI…\.;a«£˜sxɹXn4Y'ß3-3\<|äx›¹Àb¶€¬j‹nwBè¡È·Á|î¹—ÖMçgÀÌýùŸPƒ.ßý’"tîýÖc§¯DLåaņ5[“µ:ú¹©ÕÅë›×*ßøÙoíð=VËtýë?òã÷$F&F/›½#e3DB¸-¥«u—6¸²\ñB*¤eêS85šs.ê'Çxž ?ÁUÑh¡ü üzJq¢%fÃ’mË·+¶ÀfîáK$â‹Ø“p|OÙ NOëòŒ¹§ûÄ8àÍÅÃ>ºêÀèǯ]$d™ZJ`Z.À¾—ý„pãO”oî÷ÍúgNhïã„óýœ@® ü‡[zÿ?À·r/ÎòúFy™c_ùf}äûü-IIR˶2à¬Fk¡€§#(4XigµÕôð^Ò E”0*€ëlU‡  0(A ¹t9ÜÌÙ&òcaÒ± ×cN¨.ÂøÚõ—«oïé8Qsð@xo|`N×E:€+)° ¸Y v¯u®V•œ‘’“´þðêæ¹.%KÉ2‘l!‹ñcd.ÁÇá·h$‚~~Á\§”Ýé Áü5q{×íé’äGÏbàZê5ÂJD¡GEùwg´&†§á5æS`¥Ì‚(³¸) ñ6rüX“@™¿€ ªÁYZì©­­¯¯1ç[•…ŠƒsöÍ90»8½6’¸äxmï·0ˆZpš‚ÿìa# ÞÛ™åÈqf;}¶ìæ¢Oõ&‰©µÔf±ìéÚ³gO×á{;Ïç%¥ÈY.@RdbZÆSŸzvÜ8_Fݦ=¼ËK›¬ ú·Ò¤Æ†Û=&yïæÎïöo®57jw  6ø÷DwC·•×·-©ÏŠ<ØN9,œ‚ªš˜x5%aàf±òLK½àëF-–F vE†"à<¬¸ÝKþ€ÄçûÖ«_ì&¾P‹ÏÐx ×ðñ¯ÄºoÏ”Hÿíªâ,)f‘ø€?˜yØ\è%Θx0ux ºiŃßð§ýÖ“çÇ”¦¤C­Ç1ä¦7£ÚŠB'ïb/_ÚA °S»-%nçÖåŠ5 U8em´#ñTgH÷{8üÜ%·øf|œ¤®©Ý¹¸‹‹ç ш°ä…íD<óSé¡”=`>ÖVº—3²¦ðúˆ½Ð --ænîÝäuHœ“  ‹ŽUuÖòPl,bó¨÷ª„ûrâÑ©‹ž‹z1¡2­Î]]U[“îHâõ}‚cÈý’QH|æn\µ@ËiÙaíû *üæ/»nš¨³FoÒ+œ¾±.l•3-W±ãl>é^1ê¬Õ/HŠîw¯¦{2ê r/ ú˜"À½ÂQèªÙÕÍ-@ø1{°7ÅHMûß_ùøH(â^²_º°ÏQâ²P>taÛ"+-XŽ< [£Tæ%mÛ¿ fÀæwòßÖ—A™¾¬$Œ^ßhÚ+ñ€³â/;(NH+P“[³Y ^‘¤_ËKño&JH45 ¾»Ð*œúÏHr¥I¾üE]öÚ¾ý¥“gƒZü{¬BMuÚ´#AÇË¥XêMaã“LmÂí`Jõ†/-‘ùžñ2Õ¾Ùi5:æØºEc;Ç´±äš³Ë¡ª/–·×_ð¾SÁuÜÝr”ö š« ž˜ÀÖj²)Å¥å§+ÓS—'­HY®ÊP§+3¢¾ØþÙöÏtVmØ83*t5€Ãÿ]ïæâ^¼Ùë[+gš%Rz‰âÃË[„åö*KyisE‡µ‰Ãz¶ìk‹íR×qÒ ÏûÁÁe ~‡=  ö&"¤d—ä”jšŠÕxý]‹G¯À“C5źÂƒ>U•>Ÿ,]H–¾B–g†gF¼@ f Î’àAøU+×üíu„ûÖØ@eÖ·Ü奺?ü>>ûÙ«_Š»{[ìw –¿Ä©Õà08àSøÑÛñ“¹ÔDŸ,:1Ûf•[ät‚¨4–QÑ×z¶æÄJ£—]T³½,ÂAuw¤hó"ŸKðˬ´'3exuómøÍn ׂð¾ÅZ¼ÚWrÈV2ˆŒŽÛ›·¸6ÈýBçhÁ¥®–Vïþ‚š™¿²gá¢Ò5ÍeŠ´DöÚ—ÓA‚êü¢¤–6Á׌v56ò4#†b=‘ÿk°D›–j ±!d•y`Œ¨ ¢ª¬¨ 3xb£#"W]Pº›ÇϱN'D wÊ(è^ 2¨ j®`iMžöâ6ê> otýçPI}o¢Î^LÏ[¢ž¹eËæMs ˨÷²Éé¦f{n èÔ;ÊSRªn\™¬@`f¥Ê"ôQÀ=‹ ØÆjS?ÇᜡcSK„y…uÝÏ¡°¥p7œø oˆoÕg ¿ïCø¶Äj¶mî¢ÐSu§ÂEßKø×ç—Ú¬‘z½N¯3p ùQDz€£@%uTQ«KøjÐ5š+·¾Ø÷p—ß[ðnÁ¨¦8Fã’FR(—[Ž\hjmj9n¢\ÞÎÖÔécü‘ê…7 ߦ‰ìͧ¸ØÞÄ1Tg4ÐXÍó,a·o7ÓŒºý£l!MKSMA ßž‚wT®©¶(ÓN“_ ¤õQ"UòºD¼Ä—E³ò=õü=Z\Pc(Ë/ϳee}FF}Nžü”!)5vÆ™ïñX '0׃‡ua–þîÆ¬óDuÛ9?v¬–¢†]YQ‚é³”™šì­….Œp”k3ZSšäÍ+¾^þõò¯Ôö<ÿÜR€ \»¨~¦Or(5€þ½gzGêðUÏ?âLê¬×‡ ä9ô fV}È_wMïz8bGÿ}àAº©AMÁC‹¢I¨êU~»ÕÙšÛ©¥­ ežŒÀ]Xé59 œ~Õþ+Xé­D/þ° ð2¾3´Ïà$9ºUŽN®‘éätªM´$o©+_ܶ9R4šBWÀV£´.é—á /ßãV,È_¹|ËœYk'k8û(Œ>Žp6d7çæëj^ƒŠÈ,žŽ‡Q1±?‹'ãõxg“uÂ+ðrÒ¦5²Zéál ÐúŽcP>(+ø €fSiíõ®þ×àêÆ}󺖔τYÿ¿Í¯½Îº}O»p<Ä[—ø>nº*þñ8¾"±"xÏõá_ßÿAÁ…ªN[WeÉ®Yµ&%d9š8eœBªZš=?ksØüÅÙ$˜*·DG 9¤qÈ6ò£Ñx°†£°q×·ßâ{ñ  ˜%÷ 3aüÚ¤9Ü*ÓûbÁÆ}PE9bèŸ[Gåáù|"&ÃÔœš}6œW½¯ÿÕ‘¦‡Ñ°:B~<‡_{oÕñ t´”»P}–÷Ažªy—a#ºˆÙrÌ Ê7'5o°sbßž²+Uðì[ç‰,-Ž1Æ7‘l•üÀŠ<³7lÉâ¥+…yl²I[^¿2GPiªp™¸S¬ØwèDÊòY£ó#êÆÞŸF¾ÌŸÏÕÿËÕUÎx–X¸[À'Pµ¥ª–?þ G4…dEš<<1¸ïà€<,Ó{-á 5x¹ùxRæ·Xt‚‘ÐL²Lá3ÉBŠ‚¦Ó)¯·ÎÝaj¡ÉM`À1½s¶5Î$-ˆ£–3ñB:1ÄÆ™»|u¹,Gy"ß ‘$gè2x²žUÕ&°‚½²ÌVràbÙp•¶²¿žê-îFþ[cÏKÈYÊ“þ\ïfUt¸ˆsà™N¦áC¬8DgŸl ÞÍÚ-û·«¿%CÉÝ Ca> Cñá2œé¬ßh.0™+T[4|&¨£ÔyIa›âÖÃJX¿+õPF§¡º9£Cò~÷ÍkŸÔšÍSüzq«¨/°¾{Îuøã€NÁéUÃ+r›S(Òh”*­fÛÚЈµÛ–nÙ"“¥©¤ÀÉðkN”ži­ ´¨ÜZäi«o­o+©(+·WVä–çTäÚU¥*ÈåAÑšì94ARgŠM4u ß!píóÔ:ìeY%™õ;ë#=;­Š¢,Èá²r”2¾×ôZHõîÜßßß¶íP¨Ö¢´‚…3RBi®©(9ØuúØ)àh±.øñ ¶D[¨|ÈÉËR)•ÊЭÛ×EnÞ‘§ÈSä*9<¢ï<ÕÆín(ØÏ;ˆTîD í6¿¤UÒ’h[cDã¶ÆŒ²´ÒÌr¥-TeË+‡R°ZJÌt¾ò£‰tàyÎ|éò+ï‹¿ÇX!驺Q ïp·ÈøÂM| Di¥YjZ­òÏjùÖ@Á\©ËW ½o¾tÜ È/w‹ oJÀXl²;Ïœt¾ÜáËs—.Œ]-¬fU*R0*­Ôc®™y .g½È)Ðä™)Kø•0»<ó-mqaM:Ït*¥±•Ñ.Y[ÌÕ>øð°²b,‚·×4­ªÌ5ç˜sŒýçeæÁ¿Õ? Ît”kìŒE6[¡u×ÁÐÆÎÆ]ŽÚjÓÍ‘*‘¤[Û{c*ŠO4ÓF;Ø_ï$Aîð‡t‡`P(”Õ¶u¡k®eõ"W¡– û)ÞÄŸÝèlŒÅ#Cz}óÿÄ<èºÄ€âscuRˆ©)®Äi­.'þÜi5‰F.*+)iÖŸÒ{N^¯=çÎpG ‰úŒHY™¬Nû똞ý€þ©÷þÈg»~wCúPO܃ïò;]štáÌÕÌΛ£X1~9dC–%¯¨º€Æ£†«É¬LHÊOÎØÜ.íæß„Ús%‡ªÞ-üÞãÊéj¬ôX¹›¬Ç–“,“Hœž®^þ/“âw¢øÄ7F§Qæ{š:!ò࿾!îiôûà@õ ÚíÉD½oer¹E;Óè•N±£üMÁˆÛ¢œ‘eQtŒß5¾c<LJK.Ãl1˜KÍEÞ‹¡7Ú?ëø´°ÌZn)7’¯CÅ=a‘à·í÷%¡Ï—ÝnóZ ÃQ è²4Y ³•­'¢õ˜ÙŠlÄŒ¦\Wž?§·öþC×ÈP\‚¹S›ÑFåpü3’Nµ[¥†¿U¤„ê(‘»I¾µUXûºÄO¸ùµT0 P]„s|+$dxÖK æF~Dã‡ð½7ƒñàgq0Á“‰UòÂé¿NŸ@[I=_Á¶C[A;pµM”@N£©~ÓofÛOµ¯yñ3Nß“n† ‡Šƒü§â½Û¦sa" 7là¥8Á›‚â’Ím4Ïs\á¯ËöÀøîo~ÂwáS©v*¬„M²ˆÍÜ[WD;#üÑq*ª-7Ìë9Ôû©”’i)wôíƒoÜj%’YªÇÜ÷VÎFã²?¯.&ð} §ŽÖ8¥‰èsâö6Ú<2‰Êˆ‚6ãa—»ÚÕd©®‘­3gÈrA’Z­ãÄ ):?¼PZÜÿ¶ì:SUE¡ðhË^AseßÈvCW^ÉJKrA²1¹W×L î;ó'[œ¾Ûr¦Ú7S’aCG 0½}Rý+u ê_ižjRZó@™IêLÙé¬W!2­ÙÅÕ¦ —;³ªR“23S6ì•öð— ýRÝ›øaüE¨ë°óú{~Ô™£ ž”ÁÖWÉ’PèóuŠä¥‰Ë’—¥oÕ*´ ‚²².×W›x&þLÒY­Mëÿ¶Pc+8yÇ8”8¿ø¹ ü/nZ?ÀÊ·°òÃ ÜØ÷îfW~¹` ›Ó›6Uî€Ƚã¨ÂáÈÝz‡»¡ÞQÛÀýÒZ´zÖó½/?4ÙÜñKÿ¡Ú¸z9•ûxè·ð0]£ÓhÔNO'¹7‡N&z…JèÿNÞL*ÿ "ΖÍ.KQ힃ž#À]ß?j^F‚!]÷l‚„†õÀ¥.S'ëÌZ³`«Åÿ2äJ7ÔïÜÍÐTÖXâ‡Ã›Ö wv¨ÔNªô¼ê?âã™$}bç_b Èq’SŽâ¥9eå0ÿ#·t‰ÜÁAxàÇTý Ix0y€&LI©WéôJàn¼&éBp¡ôÊ•– k…©vAGz­´5¼ÖÂÝôy›d9)ê˜ëÎæ_3ü¬…FXÞ¦0êdÎ_ÅñtÐNÆñ’ìd¹<#5lõ† ô{×8QZ” P\î°—4t¶vzºl6ca)p§iïôCQD¼nÝAü?ÃEšDF©žœùSÌ>?^!é7> stream xÚ­VyTSW!÷DD!¾)j}¡S;îXG±nHëV­ »€¬a ‰ì@’‘UD’@PHD„÷uªÖ¶Z•V;J«Ö¥ïÓëé™—YÎÌ3ç¼óóîýÞïûÝß÷å—Ë#¬­ 7bçªM|¦zy¯qsµ,Ì ÃÚ—Š96ì8‚}ŸÇŽ·b>ûžõx‚àMwà"ñr¤%þ0Ê?â‚Ý2Gšǣdé*W×™.®®î^ ‰i’èÈ(©ó¤°ÉÎn³§9»»ºz8{Š#$Ña¡ñÎÞ¡Ò¨q¨”{‰söK‹Ž¦9Oš%•&Î1#%%Å%Tœì’ ‰\0yšsJ´4ÊyMDr„dkD¸ó’„x©óªPq„ókÎ.¯£W‚8Q&8{'„GHâ9®v“xS WÛù„?H„aD4!¶ÚJ¤r¤‡¶„á@8Bb4A Þ#œˆ1ÄXbÁóˆÄbâSb±Šð!Vë‰ÄX+‚GX!DäåòÎ[yZýÈŸËl-·¾g#Ø  òµ‚cd(yŽb¨ï†;aënû#«´g°VÿÒOÇ{|оÇy4hA“^c,ò4Ðâh1‰*+@ZjgVÁl·¥«±p¶ÊÆ|˜ óËñˆãØæ ygEPÅEÚ¢b£ ¼ii¸!G#Ö"4rÖÅí@) "P‚ª&í—I'ñLÀ€nÁŸâQØq[6¨@I)Š Š™2¸÷åi$<‚¬*¾§ì_왣G‡Í¨KÇcmÌ|v:J§Q“`W èt©%ÂM¨Y° jRR 5‹Á͸™ÌJ…””Ø%BÜ› Ru:¨ÙÅØ³J™á…“×ÞJúùlºFÃÍü›Q_>ôØ >°8i³Kì’üùð ,*r;¸ðÐÜk)=Ðßê;4]Þq¾£p$¾F‡ÃjcÚCù€Óp.•ôÕ áß”¡.¥ÕL*óƒ…°ÁRùç™ÓÖˆƒ€âjƒ‰m3ur%~ÍGÝ/FÓu ‘2ÞŸÏ„X âHu´žzUEF*³Ý˜Ø8A‹ö.˜Íw¡Ån‚)–tS–·‰,0×ÑààS“cï ¾/1 Y$¼NýŠ\s¦žŒA·›ØÛxÎp÷ëmuKÅÁú´ú(&×¢±ºöb_Û) îšë!‚O6Î[ë×â'¹œÛM¦„ƒ,)؇ÛHùâ¼àí™y¹ËAöš½lßUD¡ µÈöé9£c²þó3ôÉÀÂ_…˜@‡Ð }{ï©+œ<·gž˜ú§…> c © &¡¡72SÏ¥ÊV —¹‰ [å›,öVJÔ¹êdUäªóÔ°¾’ËwB5Ó)¸Ý¶t2~I|°(UGnÉ7àÕš¨‹OŽÍ výi9â!ûû÷Ÿ1\q¸½òƇú7ú¢±&6”¸û:'0ò ?&#UrOfkœà ö(ttƒƒœ”[IOUy«èîÓDÖŸ“½8ƒÉá&37ŸyíG"£‰ÆJR²Ãl^Yý‚VÐ{ý޽ýM(õoÂçì:H£áO0ÁøCHFd…Ö“:Es^Phä•û•ÅÊy"5§j¾2%gSÊ2ƒÀú\­Š[£¶Cn†÷i»‹Ù mQqùî¶¾[pŒ%i»·hÂa#%| Qà“š¾%)Úcé§µj­º¨æjc]]º1&+*/pÖå)ÈZ$|ލg‘Pôš3ûÇÚþûf®Q÷PøÀŠ{ÂWÈ Ý¢ëHTŒFµaê Caˆ¦2à (®.Ó°»±´ýLð_æàÑx¦q’HøëõéOˆÿàgîK¡ûCÌg„¯–– )þŽ¿¡W‚øŒ¢*­nÂêFÓ“{Ìnè“÷ž-°6?lLûæKߌž½xwÂø`€Ï&²Ct©Åbô.`{PUÔPA Þlchw—ž¯¬ØY|*9)ÃòŒy˜'‹qÃãb°>⤠êê‚ÃeÌŽk—ôÕîºÓyîÍŒ¢¿žDÕÜ©{¥¨¾SÚ+|„f³t`cÁ~¨¦Î^ì¸zíÂz/Ö„ûûDQ†Lú«¶ž£p‰p?é:q®§ iš Ž€òì6‰1þê?Ë&Q<[6ˆlô?g U~8¢#UŸQö¹™šJ£‘ó÷¥v‹aÕÏEë=fyëgàTÓ…ºßðiø¾–`iÊ~>ºJÇ’xÛ‡¾L:¬Ó$î§:KªMÉU² qNø²¾Í? Ù£÷Q,×dÀä—îÌZØ”´9H ‹(ìðãddÍŸŸ…ƒµ§(­ zÁâWÝú¶½½*[¸†4GWUÄ­„@jNô”™Œ=j„!”0Ä»3ÄGkY{º!¹.>>99>¾.¹¡¡®®Á7¬ÿcsa4ÆŒ\̼/¦ó_x¡›tÕ;~õPðÖp«DìüýÖš3E¯~d¾³b®.Öš_N3ó­™J°–6Oy9í‘ÿ=“ü—ÝáÜîÌ94öè÷iSÂÐx'¥ÜnB±†ú{n]ÇŽëþhöåkF¡øºó-]¶7´(ýÙ]·D'$~¤¯D!)8¼ƒA$t@{d[xûÆÝþ@y, X.Ö¥×ïÛ£«AE~s`áÞ–žrîGÛs2Ü]´…:¶Aù™r¥xQ´d=SsIÎ3\•KÐe®é¦òÐz"9Í+:hÓæ–^Žwô#b®×«åFÔ<ÐftÜßÖdYlyЧÑìÛǘR8¯n‰Ü¬Tˆa•´'e_½®ºñË…í °Ã LàQŒp~<‰ó×±MÈ®¬l;(9KR¨ñ.+²·%d¿˜yͲˆÈý‹Øt CŽß }vIøúŒ]Ecg¹My±T±I„ d–1qdSaŸ¦®¥EµŸ³£¾‰ëíׯAeGduEXa²Bh¬‡ÖRxD³·þè´er8,B+Éß®ž¸p¾|ÝgýOyëAêF ù‘pLq­YÕ1:_î®ì“‘u׳<ˆó¾€oJxkÄX+ì¹R’·‰óº£ÿÎ]xøÿAü¿zGâú?H~KB)7²®Þ¾~ÔÈÝ+bQ FOÂ#°ÃÌØþm*7#žþ‚„ NÂtë»$pZ¡úê:÷vuëÍÐ ‡dõ!õ!à  ëdÁ² àø ­“ëÙ±&^ ›Åg?FwèÒÚêC— ))UÅ«¥Éšt» qd›º\ ©£*(„Kœ°5jRTr^«Sß{)Vû©¤‰a…bKúy(RTÆ¡ 9giò+9Ï-*-*³”³èjâU°…|dFÙtã=uõ¦ÖƒUÝ–¢I*±:Iü…f›E¯*Ù±}[¾Â{¾Óü§9e\Åâ1PUUª{­^®ÊØP˜hɾ…ênŸÇ˜všŽ‡ûû®Vm…1qd½ÆTXßСª³è/ÓæUBšÏ~õíD§ye( ''3QÍÝ” Oh {ÛÕ–ÔuœcK({™õªFñåÅÞ\Ašl/7”ÚÙ]ÖÙ`l­gë송;£ÿ¬ô endstream endobj 68 0 obj <> stream xÚ]Ënƒ0E÷þŠY¦ª*I£FBH)‰Eú",²4ö@-Û2fÁßÛ(‹.lϽߨ¨ËZ ѧQ¬A ½Üà¤fÃ:„$I \0»Uþf#Õ$*.T¿Ó!zkÛÛWùX\š[?µ×*9Ç>Œ\nu]6Ëdq¬e¯ Ë@ô½:NÖ,°;sÕáƒë}ŽFÈvmÑøN3ký‹#J 1Éso—„˜â8iÊÐP9 Éâ8‡¬ªr‚’ÿ{;E׳jHvL×ÉtŸó•÷_¿8~|ò~›Ò9» î°Ù˜u7”ÿµ[PH¼g©•v*þSt{ endstream endobj 70 0 obj <> stream xÚuTlç¾³û²Pªœvµ]M#вÄÊÆJøU (U!´% ArÌáÿÛ‰qða'9ÛïÿˆRR›¦¥I©4DšM+ªP'uÚÔŠª¨R[©•ºÚï’ϰ}¶¥š¦Ó}÷}ß½ï÷<ïsÏ{4¥PP4M×îxñŶ½ÛŸÞ¶§µm­¡´³Éqwÿ¿ç_­’~KI+i©^&­’K+ÚÛ»ÿ©‘=AQ4,+G—–Æ“‘ZI•殺¦«—ÿ¦qö?߯Ú>ûòëv³Ç{Œ6³‹5zXWynt¹œÞÃ]6—ÅÜí¹·èrzºYkgž‡Åé8bs:]6öˆ§<)‡šX‹Íâ0—6§åmƒa]ƒÁдÍyÌW^ëW™Vë×67o\£o2šõ[ì¬Ëb2:ô{ŒÂnô…Mßê4YXO¿jS·Çsì÷^¯·Áhw78]ægV¯Ñ{-žný>ÖͺzÙÃúgþy£ÕW”j¨<¶9íÇzHYú=ÎìËAô`(Ù£ôjj ÕDuP]UG‰8ç)5IótˆÓhé(£‡©ƒÔ!ª“Z&£hJA­¦vR7é?ÒÓ² ²Ÿämò¼ü–b©b«ÂSU]•«úP ÕΣ¾ý…„äóõ¨O}v²Yô銕}>ðzÇᬮM¡¶éÛ?ÊÑ~UOº'·Ûá˜pONNLLjÉ!©œ´'K£zÉ+—êÐÛj|uø3a1u§O8 ˆá4‡âN &Ç…Ã0PÇF´IÅLu  2a“I Å¡.“L¥u B,4ñ:´¶míF»5Ãñ±ÑḠÆb`ÒÁ”_žç8†ÀOPCNº­Ô³QúZNC¦8žßÃg4}ÁÐ!83(½‡G5£"DI§J¨)>Þ—,fQD#ŋފ&½Ð¯+Î(û{ïiò?pпÔgâñ¤`„¿’(^E£š“ ÂÀøƒ% üÉ¡ôtƒ¦˜Åà D‚0XÇ¥im”T:š`¤ ¸óÿÀ-ô£:W ç¢ÏÕïšçŽO÷›_i?ÞÕÍÜYªì;±'}¥ìè|yœb¸QˆmKæ.¾õ—ë|òáÍó;Q(A’+"†DMXˆ'âøñBý×­?qÙˆp˜ÁS@(Ÿš[?{)~U1Ãk¿`‚’\}íúÔ§d2´ý‘€·«qK#^Ñzr0R|X‹ @²Î[æ0 Ä"`RiÈè iÿtßuFò+÷í²o… ãOCJ; ¤²—¿ùÇ7hÅûgâQ”Qæ#‚7…eWš¿<€>Å ~`øuœÚzmS<_RÛ'-]ÍO½‘Í2Ò å”ã÷e÷~«ÝåõŸ4˜ ÄóeÛ_–Kú…ë7)3è1¤ú= 2(ï¿ÀMJ¼ÿ/ÇëñzDžh³5=ðÞ ÄOV}çG• z Òµ,ý~Arä’þ¦‡q¯|>-¾«ÂOáÖí!x.õÒ;ÏÌÂÇpžAwT÷CŠ2^ƒ~·-CËѪ¿£zm­ôŽZH‹m%.ÇQõXnÑ&¸eÁ ¬äöökï®WYc|þÁ _AŽÎÍRÿcÀ-ª²µr0¦C;”ùhtZWÎÈ-l.,bÌ·?€±]iåy«ŽœÞ½Ù,Œk ªRîL‡¢V-Þ¡üùø–»åý¤Z)D2¤#’…0³Ý”£éŽ o~Œèİ@º:Nš8m=D¶0ø„ ƒÕt´ÛÁ†{"Cž‡A8‡‘È þª9ÝåˆÅÌ nW¬WÙKöÜ%ÒÈI > stream xÚ]PÁnƒ0 ½ç+|l5M&u„T¥câÀVò!1,RI"üý E=ì`K~~Ïös"ªKeM€äJN5 7VNn&…Ðá`,K3ÐF…½ŠYÒ³DÔÒÉ!iëúóúñ"êºJùk{+Óhì”Ûâ²½®.Í2+Û;Èsü¬§@ ÎÚuxܰoÒHÆphE‘föþŽ#ÚœE—>nRNãä¥B’v@–s^@^–C«ÿõvE׫_I,ÏÞW&§ÈÝÑMµù{ÚS3Ѻ7>!:Ú–‹Ï?yç7UŒ?©4mM endstream endobj 73 0 obj <> stream xÚ¥WitW–.!cÆ’N%2™¨ „f {&Ã@X„€C̾‚1Æ»±lÙ–-yÓ¾_I–¬Õ‹$Ë–÷c0[B³Ä,MÂ’Ð9‡ É$Ý™,ä•»Èdžñ$gºOÏ9óCOGR©ê»ßýîwïåQNjٙ°~˺—Ö&$Ä/Z8òÍòCœí¯Ãê±ìTŠÆc§a_ä³ÏEï½ñsô˜(Š—þÔÈùÒ¤‘sÜdrR3ÉñtÙÓT5é©gŒÕÙœ#ÎL>˜&INMË‘$˲ 2óÄ™Y‹.|yþÂ…‹×æ‰K ²22%q³RfÇ-ZºtÉܸŠ.[-J+ÈJIÎKH–d¦‰’%äCNÜö¼”¬4IIܬ噉xÙ‚R©t~²¨p~^AÆÊÙsã¤Y’̸mi…iÅi©qoäåJâ6%‹ÒâF›?ú¶6O$.’¤Ä%䥦äøOMàÅPj 5“Z±š·‰ÚÂ{›Jæ§SY¼ª*¢d<Šgày&ž™< 5‰šH½@M¦j5Z@-¢SK©5ÔZêujµžz“ÚH%P;¨]Ôj/%Cñ¨ÊÏËçýÈÿ ¿2b^ÄÆgă±SÇDŽl·cÜèøøÃQ{£LØ<á§hÿÄ…c¦Æ4MJœLO¾Åc†£ ±óB¼#·ð‰?ðÙ|¬¤ñ¢ù§Vs/pn:7uþЪo…—áFÃG}»:si?[[¥³é-FmÉÞ 0Ê; ÔƒÕíýGÕcd5;•B€Q_RòVöª}[І×è—W®T¦Ú,¼ÂÀ©&Lu¼{âæïÝ€þÜs+H‡­ÖRÃ^âvÕãWBøçPuÛC¼ŸÇLº;x™ÏÞ`¯Ò·w\Z&Ü ye™ù;RvÌ‘­â^þi’Àl°ëœà›Õb»Ž[ÍÇÒoÂM¸Ý=xìäñŽ+p n¤¿—¾ÐyþÜ@Ün-×+M…PR³Ênu÷˜<$øôOÆ[iX—¶vwŽØ-µŠo·d3æ¼÷l~è…K›·/ÞcI´n-|-/5u熌m€V¥]ø7ÔØW°Cºw¿Œ£]èÎÙÌİ[¡áE¼Kß4sëØxš{J4‡{¸‰è¥+k¿ÄãïâEX(„ÏSNg f n¹ ÇP(ØØ-lƒ ¼¾"¨Êk…kk•Ù2œ»=PhEÆÍ ìlÝÞ¾ y‹èpbÛNX‹âÓ¸Wçï88ð‘.÷â-øùBl<—bsFXÍ&Ç… ¯ñÝ–O>mk<ËÇóñû4Ç[[42àæ<«±#Ûe¸‡'îÔhƒZÈE’QŽ0 ²•N]¥Ùb¤1i Š3ç. \8ÅÀÉt¿Ò^aÏòÉíR§ÔY\µ¹Q°ß/j…8røÓ? ôÊÛèí2´‡XS™È…tE~“¡p®çãÛ½þ¢h !^ö¦$K*#‡BÈ×#£ËTuPm';=Ý©·kK Ñ(©£Übˆ­VBº?ù„áÙ¸•®%z  *Í~½Æ¨Ò'  t¡\Ýà·›üý¢Æ 2$‚ÔPâ$äTs9õø­'%Á®¹ÁïäVÓF¸ •{uÂzðú­6»«OiÆT0¥C|i<Ï~~ 3¦Íq1D?\½®ì•ö Íׂ#Ü=¡þ£7O‡Úõvä¾ÁÀŽ\.B¼7û­w¥ŠžÆåÖãMðgx§›Xo ¯äVÒ¹ÙzTй…vÙÜ 6§½³Os™«ÌuäéËHÚáÅwR‡^c¸°™Ûµ™ÛÍQÁíçà´4à1Cל.°‚Ušª¼•ÜŒ—„0ïêš п¢5$8)ÌÖºÏm5íø™;_=t­yç;ÜXŽæb¸ùL nƒG¼{øxǺµ°17·°07·±°µµ±±UH~åvÖã×ñp|ˆ“,ôՂéÙÒ‚­l€<.—‡Ö®p<a‹ †5r¶ú¿nòαÏñÙÃûh»*‰9=¹£´F£Žûæ?z9ÀŒ”.µGè[•£ý,£=v§¼àÕØ•öÇïâj¼ŠH©V+PÛuÕZ6ÄYÉQ¡Õë@ûä†6B¿¯ŠÜP í8±]äáõx²!µ"ɨ0«dHg×;…Íí¶–ÎîŽèiŽ¿Å=ÇpGÊ” S¸ ÈøÀoöškM#(GA$ø%#—yÁÆ´À‡¶bœ!3yAÈD,´Š€ó¨A–žGR«Ýâ@x ;HR¾Š¼{FLL&UúJjÆžý›5I€¸©‘1ÃíÜ®¯o‡ñ¤Ûæ¾ÿCˆ}ö>Ÿ}ÓAãïã™ø À;~e*¦¸Ù\'æ¤\· Gü¿( CWåa!a¤Ñ!XqO8‰7zª´6ƒ‰Þ¤+|}kA&$By³ê#ÄmuÒ+Ú³îÀgp­ OûS7¿ýòøM@ßÜ\ÁMa`æÛœœ[>Oß­º¹Ю½{v3ÄΕ¤ /)éŠCp´¿¯` P¸‰r³YeÈWŠ´y#NymTl »€^‚ß1:M¤¤cÁQ¨t[ܨC^…“  ~Õ†‡ÊU„£¸—ÁIåʽ»ö•½mŒ•Ö T>a[§­½÷pÏh%¹U£¶äX¡jkj½¾o1%øìÏÿÁi*•3˜bA#+M5(Íj3”"…*…-×m-ዤ«¼ðª@Ãl°˜l¥ý©_lÀ %C\ÿOèhimìk²ù,.€Q²P”mÌIOË hå e@k7V™]æväA…R®Q“öÖú?ä³ãÙº¤7·y?Iëxn27“ûí¼³ñw˜ œ®úЙÜ}º¡¡¡¶£®Çw‘¸¿[MQÙ`¬(}³dËA@bcSŒV§ç˜gÀêvõõà8AU 1«JT§p— ¡¼ÈX„Þä¼´¾Lå¥I;–‘ ì©8{˜ÓxRÃñö÷{ûý¾z©ŽIgÖœ«ŸàÄé¼CXyƒ5ëè'AJ`&ߤ1+ÍP‚H Ôœ´jUBЪ³ôÅK¹? { e‰æžI¸E,géå/~¾ëÚ«ÂD8˜+ÊAÒ•4éÝV—çÔïkšõ4‹62°%›W’–½!1#PVvó-†Q ö2Aòº2„»î÷?™ps¿à³qìdºŒ |eå¦RТB¿2ÐÚÜØj_ïëÜó\ìÈÔ»èÂòïñô?=ò:tU:¡L&fù,ŽGZzK|jˆ#Á¯».µŸ?{ô,™1úäÕbò¨º_ƒÉï—ˆËa®º”D¬Ó“¢ù5b£t3§Í_ìÿ/ÖªÊ:´±úÿ˜¢ 2î³âv<ã?Ä;óðÏòÙé{‘A÷“RÊükd=ެ¬¯þÐáuêjêIïl‚@I’A• åHâWšZC}Ç ³à­Ñ,]±QUÈ=ÞøÅãÌÕÈ×3%sJî†X€ÌÜæêÔPâ•åç¥í?VxDxúß÷÷u\nÀ-¤Uâ¯GÙ|öï“¡£C|Ü;<–VÔJÄâ|±¬º´±¡­¡M¸êq4ím%[G³3h¯&…4x¨wϼ4n†Zå&=Ñ «½¶ùËþ¶.@Î:8Ä@±¶Ø ÒäïçPÙU¾<ŠÑ¾®Ì“_öâ®ÿf˜,,ådaÙô61`­»°£ºá"¡l¡Ìý)k{‚Jþç’ud*¨¨+”ˆ$"iuYCssS³Küi -[õÎ¶í ƒr(qµU±Q­2 .È-ÎHé/:)¼_œ ÿå!;F`B5ØÐùäî=3¶ý‚Ý‹3¾xüâY@Õ~C2£Ò@V#ü®24LðŽ_æcÏ?¨+"VWsÒ¢Ö•qO?6•&-”Ån;–yBØ á`]¿Ï{áï%%ÛBö2tTIYìö 8S:sϺy"Äñçñìó|öy6ŠÎ3K‹ U¸ÊC¡ÆºÃƒެâé3’„°âVy«î=Õ{JØò%KÈxPAÆrÉ™>}¸ ZPC™·8_T¼Ûù”{ø_㉃Bè‘…^qK®=É•áL©‚AÔÚxñ>i5§µ5©õQËÃÔQÁwçhÏÁîü£ÿkiTl—­O&ËšÊ×I¬Í{ÂÙÝB ÛVã±7¸ûÀü8)ê|³&K¶&‰[«Øe6¤¼J:ÐnÕ`/çZþØtÍÛö«œæ¦ÿ­œÂŸöõörÕš‰œ •¹ºòôYÅ °ͽVð;áUè¬ Ü(C¾8ù/Äk}ˆÿð?ÅgiGSÃÃë`‡F¨—çé¥PˆÊ<²æP‡¿ÿ½-ÕYd©ÍÜ¥\ÝéÎ4}GŒ<™Yj­®®GWÃDÈnõVrJ7¤sqe ™ÉIDd(ö…í¡zBrs‘³\T(ñ´ôØœë6‡7½'uÐwç1áŠQƒÉ`ÒfÇ­/<(µ¬£‹påyŽÜr"òûÿƒt¶”}Š®¬&m¡j”;”éÔå&½&ÇP¢Í׊uâýÜ¡üÀºx@o+×]êº_{¤ÒCTÿHü›š,Påke)SK¶Á>´ø²è}áaèªki‘ïVìMÙ•Ÿ•–›H {¿­ôp-ø Úëv¹ÉpŒÚÅ•*IvÙÞ=ÇÒ/ ¿ƒï>oÁcQLQˆ]ëñø°(É%{Æ £"–£ÇWEGY¢'´GݘvDGã{ÏüY#; endstream endobj 75 0 obj <> stream xÚ}” lSçǯc×ù nÒ.N×úz@[^ i¡@€U¢´ $åÑòÌ y˜<¨Çvœ;¶?¯}ý~ÄILâ@CFGËÊkk‹:ª±  £êD)CTÖ¡Mû®{öKX%´NÓ•Žt?}Ò÷;ÿÿù!<ïñ›·¬Y³eAiyùÏ–?8X¥aéoog»c~H0Oó˜gr)Ÿ™)^/üK”ó AðòÀU<¨·žxPŸç :1ðx¨eU\¼¸¨¸øÅÒ&U»º¡®^+›[3OöBIɲ…²‹‹Kd«ruCM•RV^¥­—+ª´ÜÏÛ²ÍM5 rm»lîªz­VµbÑ¢ÖÖÖ¢*…¦¨I]÷ò¼…²Öm½l“\#Wëäµ²µMJ­¬¢J!—M¢MÖÒ&…ªE+WËÊ›jåj%Çšû ±ž¨ 6ñxJBÅ¡Î&~L,"Kˆ—ˆ¥D±ŽxØHˆr! zxÏñ.äœæû?üý1‡°@x9×Ç8ó³ïBŸKáÃ^¶ðÿä3q—œ²¬Ôf‚¶Žô’L®—à<å —Öü|£o>…èÊ+çÙiRöž°ÝÈ]Bofô$8\.§ ° >‡¡Ãnúâ9»몗³3HVÇþYÜåq è züqZ‚w ¿Y¿yÞ‚bVDæg÷@†¹Ÿá1æž8tع(†„‡ŠH(( • gƒ†¶rè'I{yž}jâ°ä{´ €ÛL„S—ð£Åg•š²Z uE»Yû* vºðQ4”Ÿ½ö%›aÆÄÑSƒã4 ý1¿=ØIZÛœ«W»D³ôN³Ås…Ès¨ ì`wèÙœ‰2 kc–> 4PÈ>ùTýdÒ´Mrš¶7·¼F!›ÉÕnóY¤7I‰fy㈚=V²Î­ðÃðÑÝàÆ3™„Ä-Ä#_ôn*…Ü¡×Ûˑӥ¬|2…Od¦1ç®ßnàÌŠš€>þéº$ìÒ®ùyãΆMæ\»BlÔ‹qÁÈ×Wà ôå¼ó,)eO>äüÿš:èΙ€¤g¿}"ü †~@þnHtaé„vØçÑy(BàóøÝ¾ó¸G2ý~Rx3µ³š„k“]gQvÖ@;zù÷—¿ypx0-eŸ›à‹ßd¥vƒÝû w­ûÍcX [h«ÔÄ- g§veuu “É7DÂ` /6 E†F>—„’ÑèE§kŽl›_ÅÊŒ]GP·Ÿ§n¿?”Ô¶7‘ÐéêèTp®¯fw§˜ë“L†ÛX;Îg^à †„FÑÜÔÜoLL”²òûKņŠe ƒ—rĽCBƒí1R¥n”ÿB}VzpÎÑ4ÝÄßJè¨'qôá®w6þ¨ü;ޏé@<}á̙Ӏú£\ÜÇY)™”†ÇL¿àçãJ¼\LÇÃGéx÷àNf2§Nÿ Ñ~]% oT±Â¶ÆF°m:ÑôÞÝÿ’GSRU+¤·„“$$ƒáñ£Çq.|„®l-•®€­;”r뇻mƒ:Pkõok*;·s£ýVÞÀÁ詾ßtЯn!¡ÝÞfi¤,† ŽŽ=ì|.…65—m“öA<ˆÒþàa·˜vK/xØIÅUþ¯ÙÇÅ–½”…óªƒ[Z]!» {éËãý‡ ¶»L;Á"!Ð7–ÆSbÚ‘º¸,p33 ?û—uçW’¯ÃÎj¥B7ötþWû–y·Áé;Ëåõ@@«á¬uh( ׋}½à‰÷ýÕ{ÉQ@§;Þ"aO‹L±¡ùÍ»*½ª¿ Á㉸i”¯ëgJÑVõ ÙÝá\éTÁ²ý¢)ÑT·(ïÐÔ«y)¯H„¯Ïø7ù0^ endstream endobj 77 0 obj <> stream xÚ%ÎoHqÇñßm·Û¹Ö¥ÎÒœ¿BþkžJÙú9 z É&²¢1wÔþtÞ¶¤–s#³}—„æ*$J¤ù`A á@TdO{`¬=èwãµá“×—ïçÑ›B4(ŠâÎŒ\ðt¸û/vóÕåˆG›³ÑÙRÊ @ªR›tª]¯6ÐM¡ŸuU쫺][µ½õ¯ÑÅÆnÏ÷:x¾ÇŽLJâx@Æ­þ6ÜítöuâžwâÓAAý¾ôÉ!è“+Ï5ì ûEAžÄ­'²9ÖÕǾà„#,ŸjëÄqQ`·0!H1a Ÿ ‡d<ä x·Ú±{\á`$*  R¨’¥s£ÑJb/:Žô:D!­RŒ:Ë•~' ’Bò’WêÉAb#)ÒŽÉ¡ïë–›¤@þZIž˜Œäðý“C8ª9›IGÌJØ—ïáûKÓmiÃör­— ò¶†¼LanŠÅ(˜[ ‘¼Ñ²Nj˜'°yq57 ÎÁ覸}w÷ °[ZNÀts 2Ó™Û3ÞP4ç!õy¦x/—þ”yØÉ_Yb¹’6Ô¯ õEQ¯*ú’©Tg]xYȱ/’³—sÌ”vÇ 0 ¤ñã[‚%û™rKy+=³l¼¾Ëvu…yJ^¼LZÓ'4Nó«a†KæÔá‡äòóÅ£]š7*&Âìy=o6fż×n¢ûž™k²fNµ4üyÛÞ endstream endobj 79 0 obj <> stream xÚcd`aa`ddäq tq sÒvö ²ñMÓ÷ý:ô³‰õ‡4ÃÆ²L?䘈³È200¼‘ùAä]© $[„X9J*Ú Œõ Œœó *‹2Ó3J4’5 --ÍuŒ ,sS‹2“ó|K2RsK€œ…àüäÌÔ’J ›Œ’’+}ýòòr½ÄÜb½ü¢t;M…òÌ’ … ÔâÔ¢²Ô·ü¼¿ÄÜT“õ@„s~nAiIj‘‚o~JjQÐILÚ †@çñ01032²øOûÑÁ÷óœò‚ï§v~?=Ÿñ‡ÔNæßËE¿ïb›¹°{Ñ¢ÒîZùß»¾ïf›Ù½°¤¤»´Vî÷îß»ÙkK»KJvÏ”ÿä±Õv—.ZÔ½p¦ßåÝk~¬^³}>ã÷ú[ÌßÏý]ÖÙS —”V¬Ó͑ž¬û`÷Ñe¦²§uÔëÈed±mé{ؽcÇ£î-<*k2Øu:¦oç+[ðÃyÖ÷ü©“°ýNœÆ¾†ë:÷ò <<×góðÊq±˜ÏçáüþM‹–žH endstream endobj 80 0 obj <> stream xÚ]PÁj„0½ç+渥M ¥Š[ÁÃvËf·”½Åd´š„þ}M=d˜™¼÷xo²ª96FÈ>½•tÚ(£¼Dh±×†PJ˰M©ÊA8’U'á>Ä€}Õü|¿> stream xÚ]oLeÇïözc¥º…†bŽö”é@è0ŠÀ$nD6ƒìlȈQÛÞ±^ÖkËõàhq cƒrÏÁ”Á6 XFÚ¹-Ù’Y3Ͷ쉯öBILœKŒ1߸¨Kž§<ñ*§/žïó}~/>ßß÷”ÉDlíMm»:[Ÿklyµc³;7©‰°¬ùbæ”?Eá2€7äá§óq±©”¢@纜6?–ÓúÇ ¥œ†äÿ´žZ €µ¸ìÙší»ßøêö]¯ìñ ¡KQ«֫¬ZIäÿöB_¤G’<Š *BŸ²úàÅH8à‰*b€T‘Üîç+ÝîêÆP8*‹ü Wî«à6×ÖÖlâªÝîZn«$È¢ÏäZ<Š_È1|ž×ò‰‚åÊ·ø=ꪪTU­ôH‘Ê| ¡b§ŠŠŸk"‚Ü+ð\“±·Ó# ÜÊgT®\!)Ü£2×â9hô¶¼DÕQ[¨j7ÕA Æ`ÄÁ(Ð:£˜< P&ê5jÂøÍ*0çÊëÅqÛ’uÙ1—ù-p²æc=»ß8ÚPZjJ×á,3¯é²³Ÿ& Ó@ö@²‘Én³tëÚçmúŒ®§\9Hñ¿ÌŽåb{R×ç]pVÓGÆó×ßü…ÿN½¼Í’Òô°³™kZ·Ë AR~‡ìA‰…1@,Æs,ýã?û±™5öG³p¢ÂôQ‹zQé5ä…¨€1æÿáÖ[`M”ðäu Ö4…Q];q8¥~Ó~õ™OëÕ°:GnΡ“«åcöGäãÿµL/¿ûåRiàÚìy;AÙæ¡AmŽ” LÂYgf¾‡ÆÌ2-¿²cç‹Áþá¦Ù™ìË4º·NLŽÃc%ð˜¦$ßãVæhDC;²@v1IúôžùáB.8ಱæ$»_dM¿_¬éÃÛQ!úÖ€óeOn'©w¸¢›ì5è÷iü!þuâ¸Aÿ ŽÁñ#SÙ®Ì:þ‚FOÀŸMŽÞZŒÝÝŸìÿú­ uF)DÌ,ñÒ Ô´øQ-ûàN=ô;²eÿ|Cm¥ ßÀ.r@|#_ÊtÙ;½íRôÁàŒ?œ Ìø  »‡zÕAu vhßÛŽéØµÏnž»KÒðlì¢z6v>–†I˜:~z*1•813}ës‡MMÐ,‰&,W ®¬MOX­Æ)t˜¢!ët¯è/¼6±Ú endstream endobj 84 0 obj <> stream xÚcd`aa`ddäõ‰ŠpóÔvö Ž4 ضÿóa5ü¹Œõ‡ ÃYÆrL?䙈³È=ôbùÏÃ$ËÀÀÈ $~óƒÈ¯ R$üYˆh¢HcÛÔÄâ’Ô¢ÌâìÜÄ’ c=#çü‚Ê¢ÌôŒdMCKKs#KÇ\ ÒäÄ<_ âT  'G!8?93µ¤RAÃ&£¤¤ÀJ_¿¼¼\/1·X/¿(ÝNSG¡<³$C!(µ8µ¨,5EÁ-?¯DÁ/17Uì=0霟[P t‡‚o~JjQÐ…L Ì@×.clg`fddÑzû£ƒïWØ÷’ýŒßÆ0ÿÜð½Dtö’î¥K‹º«åÿr±Uu.éž-Ï÷Shí‚Ró¤~W]ZÙÛ=©›cÎìYóå»ç×LlîX± |Þǭ˧Îyæäµ gLY³`úäÓ»jÛ3ºêµ$ªf×Í™;kƹ§]º¦µoìšÁÁW¼ø§ý¶ßŠÓÙ帘§©þçáœÄÃÕÃýŸk?÷þ<<@Ìûý¡,ÐÎÄ endstream endobj 86 0 obj <> stream xÚÝYyXS×¶?9ç8Ô4-v8Ç:µWm«µu¸­Cµ¶N8Ï3"Hd@Æ2•y$™œµµuª×©¶¶Z¯ÚöÖγ;ÞÍ{};½¶××¾ûþ¹ï{p¾óñí½³†ßú­ßÚP}úP`ð²ù V¬Z1vù«ËBÇO?Þÿ¿ç}/P¾I¾É¾‡ûà5øÝÇ‚®ý}ZÐã°qy ÞäÖ &Oj y<µ$˜z<€Pý(!õ5Šz†šLͤæQ˨õTG)¨ Ê@Ù¨RÊI5P{¨CÔqêõ>u“ú‚úZ(Û=aüøç¦ô¼Lßû2±÷åùž—I/ô¾Lê}™Üû2µçerïöɽ»&÷îšÜ»krï®É½:¹wû”ÞíS&ô¾<×ûÒkϔޓ§ôž<¥÷ä)½Né=pjﮩ“Ç?3q¶$N*OŠ” •DDÊâ‡-“Ä…ÅÿæŸ$¾CÇŒx!`ªàejvÀkÔ‚À%$ž+¨0VÜGF%Q*Á)êmê¬àzÀÇ‚[n 0õ3IÇÔ@j5„ &™xˆz˜ ¡¡¥†S#IVFSOQ㨧Ivž¥&P©¨YÔlêjõ*õ5—äk>J-¢SK¨¥Ôrj%µ–Z'Ð ‚Q“À,ÈXVM`ä ò‚BA‘ XP"(” Ê‚JA•ÀA½âC9h#e<)Hü=àPà†Àú@ŸAñ4KïeBÙ~ìžÏöý{¿´~?ôo ÐúÀ³xNèôØà1ƒ÷ é;dv° Xüw¡AøÍƒ‹ED¿øðî§BN Õ>"zdÿ£=ýØÎÇW=þ!gâ‡òöa +{â¡'äà Ç#L#Ù:*jàÏ‚ÇÅex†U„úË\Âëh~¹æª¬]«×gkAËfÛuV®œÍE•µm%àÛ®>½$N/‹«I¬ç„çÊ ÄZXÈD¡'…D¡¨î$s÷èj¢”‚ˆA”HfPÈAÂ&TIvº¼ÍuŠºÎ9`0²¼!•×Þ ®5*ƒ[o ’ÂN¤»ó¬OJÙŠ_üŒ±aæÜ̦mG’ÃÇpö ï•Ú³–‹p^F#cÐz¼€vê@gÔ‹™®±"cäCœ‚ÓÖS¹»,{ªw’¥Ž†–êÝðWhø³ýUë:ÓZXËÎdS0-*=;Å ìÍŒY{ͺ½=–™¼w)Hy9ð–9MùËÙ®RfcdÎr.ZŒnxétH1¦»*ÎÒÉûÎ0Ez[:—;24ãWhVAïYW}‡¼‚C? ˜[óÕ‹ÊŽŸm?ì7c¦óê‘ _?gÅâ —.ÍÊÒk!Íô 7š$¡³ÃL"µ£²€•ÑñF‰1"! 'Ÿ:öö±“GÏž¶|Äæ3(xØÜçOOOS“ä­«©ñÔªjc8=ŸÞ`+ܾ¡.ôð5¯Ò¡ >ôÕ&/R"üêê'²-F+°nG•§Vé”Jâ1WŸ¿|ÿ‚¨—Q Ä ¿Xë“££Y´–©Óº´î¶˜>gë÷±Úl6ÈcÍLŽMoÑÔÚìœØ”ÕYá°¶„•±Âtf].ÉS­½Î¨eñFcÎ,⊡ Újõ4ì©è0±fú{~|! 2gÍRe*t ˜k:%gþá_û!š s·ŠôŸ ¯¢ÇÐu‘‘†l_œ8ïil«î„FhHwHY O‰ç…_&–'yÜ••;/Îm ÅsÆâ%xñà(´Œû>|·ú†Õa®†j¼„‚ð n,Û–¼„5aZ”ÇÀ‰ºo.˜ó¡¾2àþ0‡Õ23õx îËá@ÈA\ö;=ÖÂwíÊN›ù·?¹3Uƒ#ƒÜ´Í“»·¼ÔjÍ7ÚM¬›v‚Ëì-¦ãbEÜ8üàt<ð 6¶Bîá,t[¾©Üì.eG¢SŸ5i;Ø|¨®9Ä–Ÿo‡2¶§3é°Ã˜ ›`µ%ÇóKl$hÂ_¾áµ=±9à{™hxÞ0zÑ«‰ÒXÅ6›EGA˜=±žµÑµ/Lu©R‰J;óý¸ÓhÆÇh)Ç”Цá‘ûwXU¹*yýéI<„ð¦Ð`›O¿‡Ú*޲9èahLY a³ÝÉSO“Õ”=t•‡3öó§v•åUX+€ý¶‹–óг½lá{ÙEÂÂsè߬^Â:¤ —“MK­ÒK8Çн‘Åïöù]N H+0yÑ:¯oƒRи“ÔíÉÜ 4ÎMÇo)ná¡ØZl-*ßWrª’Ä_CW@Ñòi¾´*TlÜ rbTç•0rH4g¥ë+µe³ÑʹhÍ+he–#D_¨ÏOèµ)‹ðôExf(ž–¼&D±0\¹‚œ¸%‹P?tõÃW‚HNþöÈË ï§½‚cßù´î@ß·¾ÿIöMm™oa3i¼OÂSðz~SŒW£gð8´ŒœÁ£‡‘æó£=Û’ ¬FŸ­á³õ¨Y¸~¦Á´Öõ§Ö¾~ .Ã×®¯ßûKÇ®ãη‰à}T…Íé9ªr`KÍyù<’1g"¤È‹3¸ ]’ïÓàw¿3y3w†{ ù¢á7}ÿ–·Þ™I&l(‚bS1°õÚ¾«žÙeŒä$b´›ŠI•«=hì›Ѽü–ÐÀ¢×ð`4GrÂò$H2ʉG»‹^< ÅÆjÄìstR²Õ˃ÝdëËd ßX@Lóä–íáªha9ÜT ïÀ{™Ç§žŸÿ,ñ•PŸQã‡÷þI¡$¯Ç×+@Ã>A›Ý»îL‰w3;½†p¾«Ž‰ˆÑÆpnÊVì»Î´£B ™¡šWÂ6m\?Û¸ˆ '˜–Ë¡™GÎ/˜Fh5TÄ—(LñÀjܨB¢a`yÚ¦E:UŽâç ºÑaªæÐÄå>04O+‹²DX#IKœ¤7pô¼‘ /JwûžìÎðÜ}è´¨(¡%ªØ|SžGÓ°í`g[êMÍœÍKÏ6á8 ]å&’¤=ÍÚÍ4ìǵèAò»=8T]›U¦³$ÃÐ^b¼›o¯o†÷n¤Þe것ºHÓ˜4 fç.ËÚx×…MKígy+¢¦L¾ô"y™²Tù5ö9~‚4?}p´Å#ñ‡"TÂ8 Šk¹wékß«ðPܬ÷áï¶S½ï?H°>ø$ðØ?‹”XNäDîÖwÛ܇ÌíÀ6Ó.gÎv¿ñá[µQ1é&5°±bß@ï<:"‚@Æ[fkåéÓp1Û1Þk‰1ÇSv³˜_8¨]²VTž&¢ªíмtÑ-Ü„úBDu®¶‚fh¯ª*®RbC,›ÌLÕL…WWÇÈ" œýóW’3ÜIØëõÎ wnÛ ìñºC¯ó’µŒD)ŽÉé ºšùqÂáçBŸIx‰6IËÍœËTV5P§(I²²( ?)zŠymÝ’W¹,zƒ5ª :ÙϽ÷sŽØ÷ç÷'©]¾QµÈ¦ܾ€œ7ëý¹+e<† |×׌ÛÜòVóÚýò£0 ùö'ôÀíI¤?į€Mª-[Xt–A5]9"ý]X|”4v«<¶@¸+©9«P[Å,Jdò:.ì>DºV_žIjšTu¶_£œhlW»Q3zRân¼I4ÊÏ>N$ÏJÎ)›X.÷Ô:*ë9¸0ɵÈ̪iÌ‧ñcxàO ùópºÅ}Ál³æúÏ#­œP³1!+-qÓæx"°  ¹Ì [>tÉÄÕGïÊ´l:»ýÛ7‘óB :ë÷»i­ÍYÂãH&f÷†ªµä Á#FàA˜¾…Ñ~œ®qµ™„ ±…AÞT&&>wï»ÃàÏ»Œ¢æjzºÊu<ÅSH×i²ÕÒˆM’ QU‰Þø}§®Ó“ƒO’lw¢i.û#¤?ˆ´C„ÐEV[!2ý½'ðÀqäúrzœ¿V3åš,`aí:[— Æ8uZbغøuÀfÓ«Í›äûT­9ÐΚœ"Ó÷å‹5yf coì|îE‚|ÁT¤´¸Õ ß/šˆXKtA؆‚|³E/НàktT|N —J “üzå‘x/»cè(©¥G—¡ÅþcÞ.ûì=® sòõ)YêTHf…m²J•«¾´Êµo3Œ›¡›äót*"£U= ‡Õ‘¡öŠ©Ý…Ê`ωï£×.7¼!ü*Qh•ÈÈ(•™Ñ ˜’mžäªMXÅŽF¤¯£'ê¿EðàšÑÜx:Ú"¯‡l±ÍÏ™éCqf ‘’U†*`?¸ùÆG<4¥·JjHûk¨©+ÞYZmiý;JÒÊå% ñå ¤Äz±Z¦0ô:25él—¦ÚÈ•©ÊSä*€:qùx¶•‡×2ú)3 {DvæÈaÏ>¿ÓDX±‡ˆB¿¥+˜Mdùóxtº”[ckÕçýGE]¢Bæõâóït¯~eY²œ d;)U—ÁÕƒ¿î<ï" F}. èKÂM~–3^~=ßeb Û” YlX¼q §¥…©$üÙ˜àN¢ãe–Íe.wÞüühÙÚPg0½i»g¡ŠŽÏ%’LÁ@½±>µ.±cMÉX¯Æ&-2¢¯CîN ¤u+ƒ?øñ• Âs­â2f§K·‰ÇõÌV©q-iZqÞFš»“÷õg–"•Hx=A¯PA!Þ™XÏÙéZ‹ÃA†*O¢3Žûå̱dT ºØì÷ªˆiöä¬ý'¯ÄHî•ÑR™¥‰¿Óǯ ÖÌ9ß•³¯]BQþ_a{Ó]³ê½„•°‡ O0®á„ âhÓ¯#²‘±]Øñ°§íóÉÊÅ¿¶ý¼©Èj¯Šùuôö­.\‹aÁVÅ ͹ùµ‹a>,ŒJ\hôÇòž´öX¿í’°í¾¦ÿRZ”Lÿ¶û$Ó“Z'Û·ºh„ÂÂpùÒ»Ÿïï6nߟüw>õ7áÔN¤ó­a6cìÓ€dG^Æ 1¨/ ¸…â„—QÿgP_üh÷=¾ûž'ˆÚáå\(±Ü8°0ÿ%³ü?« K£Âd∔H˜k^O¿b,†¢œâ<ãeÄs´Àåá¾} U}$¬¤ù–BMyyiYE£ºÜIäpí¶Û뢬ڼ,Ð@ª"+ÝHÄïV‚òµìHòFuDwFu¬2QAÛ]R¶ÿÍ=‡ß÷‹õÕd®‘¹ª`GJ2=¤íPª©r6‡NÜÑ lÎÉ5Z JªòKLÝâÞo<Þâ’¡!¾Do°Ðáð»P´@…º$Ú±&Ä=׳À=·aZHnV^&1'-]©MÏ„¨6‰—.ÏI†kZ¡ÓZT V¸Å™R'ÍHT®ÛÛÉ}{Ðãõ—Ú¿oÿ¶ó»ŠöêŽ~¥>YÌÔifH“"2âeK–%-¸ýQä»Î/ kL®{îøÿ2œý îÍ úÛ¦%‚¾ûyÕþØXoUn‡ÌtUN©âÙ®]LxŒ>Š‹¹wñoŒcþmCÓÿõ¡ §¸(ƒ½žøëþNòã ÿE°™y.«¹ÔÒvúü§p­¢½ µ´ø0˜M&0³Ej“†KÏÙ‘¦›7Ê0cùôåêáÙ/³ ²Y9cô—ƒ’dì8èÓ?!!!ü Ä^G8‘¡b¼³e‰6[›eаÂ/_ÇOfô/¶"ÿ7.´Á‰Æ»ü}hÕÕEþèo²j¦Þ¥çq;–hXÅÉPs— >¼É:õlÓV+kf„>§ùÓzÓо͵½bkùS°Óp˜è6-üñ­ýáKø,F»de 2fÓŠ\B³õ,š×=À@…¥Ä‘Ëž …¾o©–Ρå{Zã0šäò v Ðfšx) ýöT2!Š'®3êX £Ã}ñ\ü ìÀ‹CÜ´u/¼Õà­sî67’@)é×ᘡr–]bŽÏ'æ´8(‘Ž‘øÁ¸‡ÙãÌ=¹<®kH¾C¿ƒÃ[h]–ÙÎC^yi^áÉ›6ô\e…NîSº¦ 3‰ÇÇЖ|ô¿kéÖKÕzZð—ÐöKÂN÷}%T‘>ÚÙ-ªU´$.·‰7åççÙlíGöé8âpUÕV;YleÄ™ó~µZNÇÉ,m¤…Òw A—‚‰—ZZù/p¨/("¢yõ¾»VÛ4…©dÚMQêÒýÛÐz²ÑÅÌ€eßÍ»’\­r¤Ô¼ÝüþDi»ðK2¦@gÑFHKKÑj5šå›—†/ßÌ"QïmîžFè nÎ1M¥ïššZ—UMÊ'ønùU;Èoo ãqë£øléf-Ê M}r>¤A:éËlMiMeuZ•$I™"]½;¾ƒÿŠÐxÛ%ËAóaóA¨Ê-sæ²_Ò®‚L3BÕ]J`îŸ?"û¤™\…ï)bF€×xFØÙÐc…KÉã$2MÁ.Þ®ÚBÈ%ÔÅl‰®|“7¡Ž‚誈²íCwOÜõÜ®‰¬PeÑXÔ…þ»½ sÕ‰bï®OvÒú±µØ^l)6áOB„‘Ã:bÌ9b̘FI#HÉJ5=fZf|zLªdãíu·7#*«ÜX*…{ŒäÝDx¾î ßTY¯ ¯N¢%RËnÿ—y¤§¢ÇÐvüZ“Ÿ¾·DÃæ_-¾/z‰Ö'±`ðvÄ0MU¶cwc÷ïœKþE‚!!Hð{uqÚKë8‚G£vÁ.ó.`]¬Ÿ6ãÿˆg˜ÿs#Ñ¿ñ®­»!w7?É¥Àâ&žä¦M͹‡ÎÊê«Ø ÚUnˆáñ>fC¸a§¡N×v:<ÆÚÉ£}ŒË^ØÄUÐ{`ºh•MfN0ÉHÌDS‚~5h$»z Y Ó eêÒ¨šUþAc.4¦ÿëƒÆÐŽF¸ÏvüÐþ]çwå{j÷ó×dã-M’ódΈ̈#sÆRÿœùqôMCž.Ìž&¨êF@ ?žºþ‹žÆ›Hé>F­w¯w¹s–ñx#öŠK#H,`ÁSìŽD|;x*]n¶·³Ø­qÆõœ0ƒÀå°p}Ö-§ !·ðÝ_Qù –qI<ªv‚š!ˆúŽ<Œú ù§ŠÅ,:Ìà¿t©EÅ̵ýˆýŽk†£Q¹Q¦lÿ,¤Óü÷•¯2ëWElåÆÀæŸ4WYߣ(kÊÆ‘ã€XÙJr¡gòÚ»‰ùú f_òKm7¾îU9չʞbûÒí›)’ÿVvùÌQ8n¬šù{RFxÕÅ¿|…Ìä5´»ÖÀA&1;UÊkM:ˆ„ÈœH`Ö<:Æxü­ñ—M÷ðßR'ZAŠÿî ¶žâ÷Ôê·ñóBª¢äº°×Õ{á´vV±xždXùG<ç`Ünr¦P&ÓtÛÔ[Ęõ‡›y("ÓW!¡|†6—¥‡ü_7ôÈR‰NôÍk—Ý÷U¥Zfì7µ;[ªšš¡Úc›£*79×›×ûbèVEÉýóV•KÎü†‰º¼D»~B¿~6v>¯!Êuq,™A^¡FG¥_Ëû¬;Lâ*¢ü‚/Ü@ „ Å‰Ä‘âˆØm©©! qÑâ0#{7$GIHžªÖÒ) S1…åUEÎú¯³¾ÊbÏϵ’Áó$AßÄ»"Õ/ ü“y8š™x´6ëxñVÜi‹ÆT‰^¦çOͽÉÃn‡{Ímsû¿0ÜGW¬é `*ª}³*P¼©¸–Æ+áúÎÐ×> Ÿi@ÿoúìÏ=?fIþÄÂ??ø_:*ý endstream endobj 88 0 obj <> stream xÚUiPTW~MÃ{W4¨<[{&úžZŽ“2QQ1£ŽѸÄÄeeÜ ÆÙ¡Wš^èf?ÝÐÐÝÐÐ@/€Í"j4A@EÁcË81K™Ñ*S­ÛS÷ÇÌk35?æçT½:?î=÷s¾û}ßQáá”H$š´=þƒ½›ãßÞ¹!>>fyLLh-6ø&œœ!N 'G ™ññ?ÿ1ƒ¢¨É¡èŠ…“Bñ-!Œ ‹¦Ä"Q87?fÁ’ui™rÙ‘ì™[2ÉNŸ¯Î<¢ÌNVþg‡¢Do, S+©ÕÔê uˆ:B£’©´°lJ&¢¨‰KÍ xjµ–zŸÚ@m¢6S[©mÔvj'µ‹ÚMM£DT5Ÿò‰¦ŠÊÂÞë/ÛÃ[#fD|O'Ó×™õÌiôÛ(¯OQŠð^ÙírYê®ñ8ÝÎ:»ÛT¯u©¹"Z_šoÊ/ÜqL»{i|ìnQg‚\TÊXÒû~õ­ƒ_~|ëàÐ1©£Ðaª)CVºÁéªçÁ«¨Ê«þèœtÇé?Þq6Ï®©ÑT¡ÿÔ Fâk’ÄôÄÌÄŒØ]R¥^¡SêòŒJ#(Pn­¦³Ò5‡ÍQ9tFú¤ÿÛ'ýN»ÓõÈ”¶&x26žßpaãùg¤ù•ù6½Ñj&—¹§ Îpã°tèø•ãCGëŒ.½«E•Œ\Åž›GE†_Åq×ÄA.¨•¨«•r@s“ÈÄU‹.êïüè©¿aë0·Ã)„#x-‰! f‘Åä2÷Y†WrWaÐÛ}Îf³ÚÁZrÊ5\|²û#@FšD×m‘€#¦¾Â3ðî´©¼IˆÌ% ¨(«+hûfèzÓÒý»³—oᶃüaqŠ*Åvµy4º?€å8¼†íÂk‚ŒÄmv[Ü€zî¨×ð„&[rȤE?î¿Ï_€›ŽÖVÊÙÒs€Ü´ËWÞæWThx-ÍÞË‘›Ç‹pšà„G‡VÕ*ËU ´kqɺ ¯ª¹£¶ÅÏãMd¾d5³u“*þð‡ —9¸ô]cWU‡µ£¼BmÆs°îfô¯ÙLì~(!aºK€¼f> 4žÃ—-þëörØ‘G]¥æØ³ à^ù w7ñÐ×Üw±­µ±½â FÚU_fà‹kvƒÆ¨Åãiü¾|?¯§   Ê„Š#xêž ˆ@zWŒ§âü9í¯q6¿ÜùŠÌ"ãß™MyGÆâqü0|áë¼\娪gˆn­MiP¦2h”©G´Ç!Þ4yDR;:0ð\ƒ«PQŽàÃ}7ð^¬‰n½žÀÛ×ÙW†$Ÿ¨ÓvÂ>D(<çÐî;ÀÓ;«ÿì!íý¦!–[MA±¥PÍþbÈѶxx°[ìå6^‡©ÐÝ_ñv¦ä¤±IÛä´ÖÛ…æÀ’,Lïu74ñpæ„;Ù"ÎY‘ܘ£——A ”ZJ,úJ)ûÌSU™(vÅÆ…ëåþçUîCF&!)i·Z؃ëÁý£ðàg¥Gö%6Ã$¤ŸLf2õz%G^C)Âc´¯ÆÙèÖ×fñ&0•ZŠÐm›Œ#óé­^¡®ÑzyÌá2IF±F2$kÌh=åi:ɱÏ}*Ǿ,’²_æ›xh4ºÛv G…>ö9 Α´æXTÜQZ¥6É^v• öa;é§ÌBIö¹\c«ªµMüÏ´§ÞîóæÖ(øƒ áf°æià´y_*G&F–—/“Õ=ü´§ÎÙèÉuÊÿŸTsMÿxwªTåÙ¬ºdHy2ůØÝŽ¶áØ¸‘اxepª€öi™YÉ­¢jS¶ÂehäÙ{—HÍ>•ëóÔBWÐM.‡·A_'çð2:­ž–¦¶3‚¢Ï¶änå‰2™ÉÖ¼îJH¡›êþ›žFe}3›ÛûÕÇR^»ÇÍQÑÀרcsHªáºÕ ‹g¢|†ˆ‘0ÍÕÐ8ÂqïYÅ/ÈÆ`ñJL“©™FT!W²B»Ï™é1èYoÛ(œ‹Û³„[ ‰ n…†LT™kVeôI¼'.À¶b&’¦%¿6ƒ#Q´27_®¨Ó7ñlócÒK³Çe:­J]›çåÙÖJ°š+½tƒÙáfÈäB ]ˆýxà%žÀezr}>O½Ÿc—·8ŽsÀ®Ô~õ¡UøÀ(ž(s^€UáyÁu’X:[§S*kõ^þ{´mõÀ‡€{ÿê6¹Òø$hLU@l·6+S›h›®«‹Ç9xã*·×AÌ2—#Ë¿¥[smJ…Æ(¼…Å·ˆ~ ]£ø§ÿ H·¤×çø_2vCt;N5›UNƒÐÚ]ïðy4Õ*þÏ‚|¦ºn+/ÎPWçùø>’Dÿq›<þØÑŠ+v3M¦úTî]Z‘gg» <|T~up­ ÇUÓDae¸Hqõ{ÆUMˆ4Oÿ"²w<·csñ4{±ô_Sþ Ÿò<õ endstream endobj 90 0 obj <> stream xÚÎÏKÂPÀñ=]Z¶~RtÈï(Ê\ŠA º-Än݆>ThÎ=_.;Ô¥`С(Xz˜‡èÖ?àŸ1O‚.õìÕ.m—|o_À°,àªçbUªeE©V º¨{÷qöí÷fŽn34h"D“aºÅ&†ùZ ü\ œ­îø€Ê:Ã0O®na„‚¨v¸Ýl˜®gàn¹\ÊÁ‚ ”᱂p».w $“RdâÇ> stream xÚÕWipSWšµl"ݲ4BÍTú=B–Édk0¤& „­1Ø€/Øx—mÉ’%Yû“ôi{ڬݲå}‘ ³Ø˜°³„ I“@ÖîLR“©I&Oé×5™+'ù=¦Tõê–êÝûî=ßùÎ9—“2cF ‡ÃyhCFÖú×V>óÆš-ëÌ_úBò¿?&ÒS S‹ÒˆO2fü4+5ñðŒçØ÷¹Gú·—îù]J çào’OõƒÉgùCø™ò4~Ì97;åŸ9œûø<ñüâåë6ï,(7é@¬ïðØù«×¾Jä•”,˜??}þÝÁ^˜üaz°dz°ôî`ñôË‹M¦g-^<=˜žµxzÖ’éYKLÒ§ §Ó .™^gÉô:K¦×Y:½ÎÒéu–NO_ºxþó WV–WÕÕŠæn¬,(UÌ]W›WV’ÿ¿þÅ Ýû\Ê™”;œÏRÿÊùš÷_3Ø”Ÿ0fp(Ž‘câ˜9À±p¬ÇÎqphŽ“ãâ¸9Ž—ÓÄñqüœ'È qÂ)ÿ”šÂIIMIOù'–š‘ú×4׌y3¾¼çî!Þ dA¿÷ô}#3Íúý¬ÄýŸ?Ðýàá‡~œÍ™ýÑLæiηŒA ÒS¥@!OG]³qtH+Ï­±è¶kü3£~J­x¤ÚÖ©·ˆ|´{ös[kGø>Fûã+ƒ‰Ò©i£›háF[Ì2úzƒœ½ÿï BU®­j5P`°©´:%É_¢£)šàû‚´1OrùÙÀTù˜*O™¹è¥‘e_13iÌ"fÎÍÝŸäw†xÊ™–¬$hA;äp÷M”©Š2ËZ0–ÿv…¡ø·˜[KöaÅìL`çÂòÞg¿Ñ¡&î øâàÐ%›ÍjÇtuh½ZÂÄÕ)ÁP¸}u^ Mõã£cî aÒ³ ÐMf‰¹ŸäszGw6Á¿u!öq6SÀÿ&psâË?ì¬.žÇ>oþ¦_êsg|S}‹}òËNMGB€}t ©®5@B›³Ž2ÙBg»/­( òʉ*P×RuëYШ1kŒZI~nöV@nŽS}áΑ[Þ·º,.p¡û{ö¯Bñâ†m&ƒI…Cç4:¡€™÷`ùVY•¸Û¡^'ÑËD+‹^†WÐꑜw‰!èt¶»\N·Û…þá =]Ì²Ùø ï|Ë¿õÿñ,óÚä49uvµw·Iý’<ÉÞ¢MgËN“ðvOÇ9«Ãî'rP´žP±R#þ7Õy[ë¶Ã>Èk’Ç“xÌ){M3æÍèl~îí#‚X{ '¨öו(Š+Ê‚%ƒäÛ0z­uÂÕêÀBç?‰ ‡úÛOõjoª¬#A¢ê÷± uUê*s%2ò Ú²O¡ùT`ÔÝ'ÄX:ÀlØ?@Gð£`aÝ”Ô^ eÓÓBƒÓäwXgì0󲎺Z¡äôä{¡¦²¾¼8«êuéë’5òù«öëŒZ£PƒÊN2òö“Ë5Q³8±Q•àí3Ç+TÞQÝv6G¨ØV»z‹HgÔ™t€ ž(Ù u…>Y‰¼´¢$Z žœ<½¹’:,‹Œ’74¬.Toˆ±˜ZÛ­tìm&&´Ò6¬kÈ­±j‰F.ßaÀÔÐC-4–)¥¯§¿–ž¹@­ÐÊUʆ#b8r†ƒøQc“-"†ŸiTŠMNâUF.0))¥Q)]#4Ê G9}ù£ÄiˆŽû‡ÝB«Ý2U³CoÓƒ@lT¨ ekðÎdÚæ ]žg×8£Z½v/xÍ•[5 ‘éjDOaâMJÄnæº;]Ýö.äå” g/«eŸÔêœ&Ñ Ðf z— ´Ôª@z7îÓ–d² ¡IkÔ€.•ßtì=tû!f©Ðæ2{}?kô¤Ò|y…ñ]Ŧœ”¼ß*Ø,x¬½2´ð;ÂËeñ}Ï<ÌÃèƒÝ·Ÿ >`è^®fg¬Í¬«¯”•›Ñæº3ÇHv,gÜÓy·ïÖÝcóXÐÅè¶lôرôwákÂ9&±<:;±ã<ifþ[@ —ìôb KÈ“‡"ñ¡ÚíA÷`äBPÐ-“P¥«Ö‹²ÙÝB]µ²DHîi ànµ·žaª…¡·Ï}u ›Û§uUC9¬*}¹f­¦V#‚įÚ/?H¼ƒ·ý'ïv‰•çÔbÍ‘Uf"þ <·fûNPX)ø` ÷öû›x8;œЉ®îìÝ‚ {Oñ¾=IÔ~H ²Ëñ1˜õIìf'²®ðë™ì7®¯p°fçªyŸ3™ß_Ûw'̆ÜâýE†Ã%Ý8r,®gŸ³à¸G“˜‚`s†½Ÿ¡kå$äËó5ùéìBƒÄXÝØ Õ*AeFj®Fej M< l”ÝŒ|\O¥-¨h ôÜ>è7öáçÀ ÚÖÔÛ0ãpvsY½ _h9‚¶b\ŒO`,Ш ëWìbÓ^´«êÜiçYp±¬ž~æwBoœn<Ôíõrr|;-Å?—oÊ'+$˜.i‰…‰™‘©NUHP{C½„n|Wlö¶y,‡]Äò—cþ7àF|ôœÝárã¶³òL8Sè°õRÊ  ÷îÙP¾ [uÝÙ#¤—çþ˳œ¹·Ë9©â}“Êñ‡ÓžyæÓ&qbE”“Ø1Îl;Ÿ–ð2ß ÌÜóY];ˆu·¯(wŠD+@ö˜¦ØL™ 8Yk“ ò ÐG5Óâzê b½x-Û&4ipw¨QƒOã'ìܘѱ3L0üÞÄgØ“¸KÊIثܫÎÏa7aÏ1ªñÛò&µŸèg¯£ýS* ½sñÎûDsûÜ…Õ$°©+Ø{a#¢xö½eÃpÆ>s]Àå˜Lˆõ`ÂiU±WôZ ·Ñjh/²ó ™nvFÚnú®¡wv÷o"2aCQeÖ”q\¾RÚ^ØæábÒ¼ : ®¬UoKÓE‡áîè¡ðþö ¸ãíoÙ]6Æ{2O7((•l{Ο6*ô Ðíîvuu23„þ3Ñ®A"†Ö©êP]PꈴǎnÛ ¢´¬ ñèÎö=°Ö¯¯3Œ:Ð#mòÖ³Ïîi;üö%@CÍû I(W—j+*Ù4¡ü É‹+q~—:eÎäAÒ¯oe׉™--SÉæô˺¡Nkȶ‡,[Òzí<“²R õs˜Lj5´†Ý=ÊlÒmMІš&Qz‘‡·P™µs=„âæÈcH>>r»õº §‡±ýÝùÄZؽXõ«ôÐfÞà7Ù• „â†rÕþºÌê Ø€VØõ.ñ&Ä»zú~v{æå(SŽ)ûS,0©Œø§Ø,¤äF9¶‰]ñüℾóÆïZׯBP±‡ /έg™Ðê²»Áü:=Qj™^„½A'2*ÅR±´RY ¥ RÝÈÁƒÑÀÃpEW>l„²•ò,“–Ây ©&á»Ýê¢c¦á‹X{B…’„ÜÊ=^?WsŽè‡>wgônÓMuûd }ê-·Î*m–Gmúœ† ñŽ#ž=±âÑd˜ûÞÙg’Ö°`U [° a|ƒsó âh¶‡¯0ÍB«Ûæ (= œž«MÚ:CÍ&V.lÈX»b ¦¨&ÞEÂ!ßçà1fýÝ·ÍA•Ke «4Tg±yX%MC½"okæÉnWö“>žõdôldÌ÷uÂ*î.$2 hmýæI´HãÀ¤€5jú‡Û&F’÷Ø&“]mU%mSª“jV¼„ƒàÊÑ]×pAOô¶'±˜ÿÒú$y·NuâïÏ'Ƈ'!qK­ ys}§®Cr¢wà0ÚÝ_1D´@Äü¿¡³ 4D.tûú]çJhK"âŸÎ«°a©}¶úWöOx”ÉH¾îÁô 4â ]öÒ,6_h¨OH)Õ:UmIQYîd+(1Œ^žító©ðXpXHA¡~ÙèbdÏ×o³Ùf¤u›i" Ö˜ÍïŠ]<‘d’3©¤a¿ª´.S´Ö£e§ .'ádß$†©®¹nÜÑ(3CøÌ9Ær0ñ1Ww zбÒÞ\b%ä§«²'DzdÏE:è o¨}³µÉ£Æ^©(×TÉó•{÷êDÚj¨¶­;²ý o¿ùì?ßÙ6šAª¹"c­F¬@ÌœU]F%ûà Ê—ÆûIšgö‡âþÖÃ}ƒ€zZªŠH ð}ŒBL#T™Œ"]ízÖ+¤“jàÙvÅ÷ÁªêÿÖw_÷“ÛT|ÀaG^}'ºuEÉ«KÄOþÂóè4s'3 L¸_Ä¡º™Yµà4}•g3/Oµ«¤>Oº§1} eCS3ÙÖî"͹§P‰|ÅÞŽê8yNŒµŒ¹ÂÖ¨7Ôqì|÷ »^f”¤ªÝX[(¹9¹åü¶ícÆŸǦƒ±Ö¦%öƒ——%™j1 Ï;èî¿ÄÐøæ0R]z»†àß1L]O·qùW¥ µH­cS3Û[eo’ß5 ^åVì°%a(r0Aü;­MmÐè"·æÙ{4'6Z˜ZƸìà÷¥y_™u¯sÖ}–Y3¿½ïÄLâ…i’tôOsþ©Þï‰ endstream endobj 94 0 obj <> stream xÚcd`aa`ddäuörsÔvöuŠ0 ˜Eýî“a ÿÙÊúCšá‡ ãY¦rÌ?DXdÞ‚Èçü ò¡ˆÔŒ/…X9J«: Œõ Œœó *‹2Ó3J4’5 --ÍuŒ ,sS‹2“ó|K2RsK€œ…àüäÌÔ’J ›Œ’’+}ýòòr½ÄÜb½ü¢t;M…òÌ’ … ÔâÔ¢²Ô·ü¼¿ÄÜT°£õÀ¤s~nAiIj‘‚o~JjQÐQLA Q@3X3032²,þþ£ƒïWí¾´ãß§íû>õ¸Ðw÷ïjßß·®ùiòý…è£Å·vßæøÎø[îÖïD¹?Öþ_ÿœRôg;Þw¬çøÑÓ]GxTŽ+~ŸÆ.¼ç»Û–îK+·æt—tûuÛwÇžN_Wq¤þ^7ÇwÁ¹O/­è®’¯í®èî,kóIl«ívïn<]{C¸¦éDÓaÃM¿ýVˆþ6ý>õ»Ûwã¥ÁΞå>¿­äù~Þï>óãèqÆŸõ?YD§ÍèîïžÁ±º¦»LîÏG¶Úß嬗ئ·þnß½h1ÛŸŒ?Çë»;º«%³§w-–ûɶðû\V¶êßöjy¿ù»9~;±ñÕÎü0í{üÌ™3Ù~ÇMf?Îõ]Œ{ßžïb‹xxå¸XÌçópöððýÈNÓ> endstream endobj 96 0 obj <> stream xÚcd`aa`ddäõ‰òô ôÒvöuа ˜üî“a¹ü³‰õ‡4ÃÆ²L?䘈°È200¼‘ÏùAäC©$_ 1°02r”Vuë9çTe¦g”(h$k*ZZšë(X*8æ¦e&'æ)ø&–d¤æ&–99 ÁùÉ™©%• 6%%Vúúåååz‰¹ÅzùEévš: å™% A©Å©Ee©) nùy% ~‰¹© `GëIçü܂ҒÔ"ßü”Ô¢< £˜‚¢€4f°f`fddYúóGß/õÚ­ùû¿/Úú}Ñ~¡ïúß•¿þn"\óãÅ÷¢_V?Þ}‘ãëoþ;¿Cåþ(…gøsë7C8Û¦¾7ÝÛ·¿îÞÄ£²ÿ7Ã÷EìÂ{¾‹°mì^׸,e^wY·{·GwÜé´íE—Zwus|g™ódÑÂê¾zù²îÖ¦®Ú6ߤƪnŸîæÓ 8„kšÏ5ÓÜÀñÛf±èo±ï‹¾K²}7ŸääÐfÿÛFžïgC÷‘W÷3þ4üÉ%:mfwo÷tŽåµÝårv°Õýng=Ì6í»ñÇÕß™öȰý±þs¥±®»³»V2oF÷¹'ÙæßÄÌÖø[9Ñô·O7Çou6¾Ú™?¦}Ÿ;u&Ûï¸Éìû¹¾óqoÊÃóo¯‹ù|ξ:" Ô‹ endstream endobj 98 0 obj <> stream xÚcd`aa`ddð ñòrÓv ò5°00‰™üfø!ÃôC–ù‡8ËïøßWdØ„~Ù±Ê200t ‚È~Ù "Õ€c²3##‹¤†ž±s~nAiIj‘‚o~JjQžBP~nbš P £!#ƒƒ0H#“ß¾ÿLÂr;zÖüä)gü^›ùÍw¢Yì»»wNÚ>ŸãÏ4öè¤î ¹Œ¬ïïÖ°ÕvWwUus„göí”ÿq’}JûÔz¹òîÆšÚÆ˜Üà¦n¨Y÷ìXÃxàó÷ÒW̯¬üÔ¦“ÝÏöZÚÈ×±7«9:x¸9;Häääfåä45µ´uWsÔýg_ñ݃5‡­-¯=¦º¶¥ lU6[fWfwV7‡:ÛÉÃ'ž9pþÈå3Ýï8¾‹þæ:£(§Ö­ãÒ®ÌÑž³ tÕª‹–¯/˜)ÇW¾à‡Ó¬ïù½3³ýíf—ãbžfÏÃ9‰‡«‡‡û=×^n9S/Žÿ"—¸¡ endstream endobj 100 0 obj <> stream xÚ•”mPTçÇŸËËsŸBÂfSœÄ{Óf’Iã„b©:uŠ!­šHe[HÕð&°ìî]vÙ7dÏÝWvï¾±»°¼ˆbDZ©T èR?ˆíDMÈ0'Í0mÓLê<ëÜtÒÝ4Ÿú¡3ýr>üŸ3Ï9sþ¿s”“ƒ†ytûžW÷ì«Ú°¿¢ºúå[~Ñ6¥žD©§²Rë³SßÉ‘ëå=•[ùðO¹ëBï>–‰¡ÂL´>š‰Ï§~P„²&‡{qcÉ+;ÛZNt©;žÞÛv¤±£õéjáD£¦ãxZù¯„˜GêÐa¦Eͨé@*¤f*G;ÐNT^C{Ñ>T…ö£tÕ¢µYˆAY¨Ý`ö1—³.g}]—ý0ÇšóYn ~¶ d‰ù¤])œìÓƒž¨#½ã½ƒÇ"Á8ãÖAäel Xí¤À–¤w“ÌÜU/eÓ-©|eÌwÄÌýQØÄËX~­].(½_‹Ÿ† ÞsQ¯Ë7è7»C¶Ñ¾3ö AœðE†x'kN Öµ‹éRnÑ.B÷²°Z~­ÄCŽâÚ­ÖŸ¶Å»‰X,Áƒœv'¡{ä—•›Ø]›- »£³œÈÂüýáiï”{Ê9¤ÀºHo-R6ɬ.Qñföjê²ò«(Û·EƼC1Nb§šÎw]BÉ e(þgeåBþçpHÛÔDèAö”Æ)peX7`4€Ž!cŒKeÉ_(­;”oRQ÷:’(${äú®\[y¯´‚›Ý¶o&Ä]¥Ê$C£5J:ƒGþq® ×_öò…Ù¸÷aúˆ§†˜Ø7ß>p«…†w­¿'b2eHZ•fQ•qÚ ¯gµ&½ž‡žÁÞðIB?ÃñðàðH¯“—©(׺N~wwl×zbü·@Ïß ‰Ùt µG)çévm9‹ô²žgn‘0ÍÝü("kùr;ErZ•‹eA .»;ííù?âD¼ü~ÙŽm5¥[yÞæ­»m¹•¶¨=I_JC9W½X *3X*VéSO(%6aTÜV¬íîÓhƒÆ8¯øôÊW“µXqOè1š`ß(O7á‘°o8ÚøZÚˆÿ'¾¢¼ûÿUL¾­N±ÉšÅ¢)úzå’b’¶ÑJûtnÜ:ÔÊÉ,K—:Ó„bìcùúf¬8¦2!Øã“îôºÓT§å0Dìa §cžñ!c°ƒWÍ`¶[€”ÒB¼—ηÝÑ@†cÑįûÞá߀mÇ[k¿Yš›IZ¨aè KtcÚÎR;•¥¸Ó`Ôh¦ÿ©,à*)}üÎÝKËé-×yU_¯Š³°‡êÔ¿¬Ò{£FZÆFGœ<„Ì!}úlUÞǧº=:m·¥+R§ò’Ì_R¬ÒÝéïTýNþnq°!ÒhóÛNÁ4¸cw&W&VN¯¸$—ß!‘)œùã1ƒÔÁËk±ºÇ¨UGLqþ4–‘ü¡Œè‡¹§ñp(íŽ1 ÊdtŒÚ®!sœÿO1QS¤˜¥Aº_)bxs|o Î4Ò?30°è› -‡—CËÿ€É%I «î–º8Åì·3| :K— õŽðó¸Vž˜.ö]Xgš´Žö„;`Ýq°ª,*S³©ÅÜlÓY»p€ÎÏã)ÑyþûX1l“h¢Ò÷©yÅ,èý½áô%ö€Ç.Z¼-®wK°<´=Xînò¨ÏÁ¡ó¾©béBhÚu‘ôI©>Z.aYãa¹5ÙÒóñæ¯óó>_s%«zGuDÛ_úõãÿïC¨ endstream endobj 102 0 obj <> stream xÚcd`aa`ddp r÷ðÕv ò5030‰™üfø!ÃôC–ù‡8Ëï´ßWdضÿra•e``è‘-ü ²ADj Æ*!fFFI =cçü܂ҒÔ"ßü”Ô¢<… üÜÄ<4A FCF!aF¦Œ×|ÿ™’¾Ù÷o*+û©[.ô}éCá ßy¼Mf?нwÒž&²w§çu—tætfwçts$?aÞ°»õ{0›pÁÞÖÍìåÝÅ]eÝñiÖËÿ8Î>«eR­\ew]uMSD¶_K@7Ä–žg?Vmf¼üáûÔÌß~¬]sôðÊSÝ—žF)Êwÿf4°uôŽ ¨©©hî.íníiénãøáζê»?k[k^G\eu[[eWE7G›K—k·K÷ù£—^>x~ÿÕãÝo9¾+ÿ–9ü›Eý7—÷oöŒÅ¥+W-Z¼jMáü\9¾²…?œf}Ïï±”íwh7»ó4{ÎI<\=<Üï¹örË9f…‰[ ÿL;¡; endstream endobj 104 0 obj <> stream xÚ%‘_LSWÇÏ¥×zV*âfÝðöÆq"T0"f[¦Ä¿Y AљŊг´ÜžZ¡¥Ðbo·WÚ®å˜&Æ©#ÑÄÅニÉ^tnÉÜf–-Ó§s›c²]ðå“üN~çœïï÷áÏ#ŽãV=Ѻw·sK‹ÓypÇâÁ'¦UóÏKCËô‘^ÍéÊtÁ¤¯ã…—‡øÿ¬eBtÕ"_¯\ä«ÊEn2`Úºñ‡aÅáh¬s8Z¼¾ÜÕé&bMûfq[ssS­Øàp4‹»=’ÜÕîê.â–<.bçÅ#Þö.‰„Ě݄øvÕ×÷ööÖ¹<þ:¯ÜùéæZ±·‹¸Å6É/ÉA鬸ÏÛMÄÃ.$.e¯[b‹×ã IÞ³’ÜgúAÇŒˆ[Ñv´ñeˆC<Êrî²ôdEéwXÐß,pú>ýŸªÜÍô7oÏÁ¼¦ŒõÛýГôöu§|„ëF=œ¸rÿ8LÛ‹03qˆAââ¶îmÑ6Ô©Ä?L"K E»~Íü-¨jv:?ÿœž‚ Îg…$ã#ѯزµì`¶ÒÜ D5\QJJÂmŽzžÒ'OM¥h©©Jƒ4¨8†AQ£Ñ€?:óhÿÔaãv [Ëxf¶Ã—³ç¦Âw¤ñŸú¯Ž< eS÷ﺡ ï¬w0ˬ6Oß@…™ÑYõ’ª‚†ÇcéaÁŸé;ÎÎÙ5:!dŒ¸ãªzÿaZ{Ôúwì!`º®¦k¨Å}·c×=ÿèž©¯³'ó=™cãßÁüìÏ”ÿã×V.@X BL‚&L‚::Z4¦ú٘ʼÀQî•©4¤ÿXU¸;uýãÿ\îr>‘‰{n½è‡£ª- A- 8<‰ö_†œý‡Ôtz %ÞÀtÛyVÉ*™pkã5ÙaN›ÍÌþ¥WØ u¹€‹0—OÁŸ T`I]dͨaÃ̤aæºTŸ-êH@£­…2D ºž•¿n¦´è¦¿§[pEpFoÉ Ô7cf§óË ßtÅú^ÖjQ­å·,¿•ߺdµÒ—kÿú½hd endstream endobj 106 0 obj <> stream xÚ]QËnƒ0¼û+ö˜*ŒI“ÂAâЇJòÆ^R1–!‡ü}ý 9ô`kv¼3»'UÃ=®|ÙY¶¸B?jeq™ïV"t8Œš¤ Ô(×­ ·œ„!Iõ.̇˜’ +ÏZÎjÔÃëõR§PØÇ†Ëà °­nxûXVœÝÏç ùv~Ëj°+ÕÜá‹ç>­Bë¼`w­ÚÀ´wc~pB½%EìÒ¸‘‹‹­Ð’œÒòº.jõïí]/oÂ’<=¸NFÓ}AòÊ«è>¥#>z|Šøä0<ó<çó0gsÌþü·U*暪·èÀ¼[é0Ï"Q:â¼-뉌n^Qí×÷1?S–wk]á/B´>…Qãó»Ìl¼*œ_$8t endstream endobj 21 0 obj <> stream xÚí[[oÜ6}ï¯à[ÙåýRâ[ÇN|‹›KóàÏÞ$ $v`oŠößgH‰¢¸ZGNì Áb%Š"gg†CiWrÆ™ÔLr|=S_É WLsfµcZ3CIðx‡ a SLH´—ç ˜ÁYˆ0Lh!˜ 8;Í Ú嘢s0L †Þž¡©pR0öÎA¼gÂkˆÇuà†´ V1IÀЗI[Æâì-ƒig–3%¬eVBŵfÊ›ÀP¥-PX Q‚  msaÎbQï1«óŠçóPå<®Q€k‰›¨µ8‘Ü1 ÈIe‰’Pžœ„PÁ¡SÅZ*nâ œ! zÀ÷Ab™çàP*0,ЍæÌk/™gž&C`PÞA š(B²À£"$ @©õ:b]–Å„QK+ p’,E8 !Å4›tÁUÀ¥ é6@‡Ö‚cð¨"-žCtÄIh)äm Z” Iµò8RCó‹i† p$©‹·d2’:ƒ£ ze²(Ëâ…&ñ’J“¨HŠSTE%©¢ Å I…ÀÆhLJ‘x*iOÖ€‚%›%l€%™&K 4 h£ÜÓ¬ÕJHýí·éÖÅù‚N°MxÆÁt ¶“ ³ ˜ÌT€å¤L ˆ¶T¢á§R îc ÷Àz* b;%±œŠŠØMEò¦hˆM>œî]^œÎ¯§{[Ó£Ù?‹éã'ïfëé´–Nß<|øS1–Œ³•“¡w0»A”€ ”-ö[ÄSðq=¢F(“¶"ðŽ¡u€:Gv݇{‹x {P´‚ í+ÇPš]a—Ññj;€ƒ«Úàáª-Jrº¾ßâØol+ZÞ ˆBúÀœg=%ÚZƒûAÜ´ûÁìêâóåéì «hÄqôï§Ùt-p¸œ/hݦúuèÁåÕka.w×ãºKUtÏ­¯Ðà3ZËÜ-ñód~võ:ö (ƒ­´M]Û'–cËNŠfrO¤ý ‰ó×bæ~Þü„ð%&äÚ‡¤³97HzW?>éã”ʳål=ó>¸T?Ñ#d%†3ûÊDKjϘ'tµç¶Ôöèêã=aó ò1Ïv“ð%¾hßÈlKÝTŒÄè@¶?lñKoyaé#¸;=%Ùå†'ÓòmcÆy]CÆRjÝÖ§¶FòÂ0RÏ8µA£¾ïy Nž‹Q ‘òÒÓ1>Trdì †n›2…Dd_wle¬0LŸKNÒ˜¥˜ÈvŒ×öÌNµÄ‘Y´ïô®B`¤^šÞÿDˆÔ&δãºá£á¦‡ås“ê:æ‚À¼7eçTÕËa'¿ì®_¡Wø‚ÑÞ1>â#v©ä¥oJ©nùh­$‹M=¢„ò.õljã $´©\¶óœÜ/›1a‡ˆÆb’ýÄÂÞ¼;ßx¤±¹2´óq_™{õûßüÓJ’…œÆóµîYcÙÂ#À—M¯­Õ5) ÎoB˜zEënÔ:…;^ß´õbyŸe©‰­åc;c™A0BÉ¢cÆ{Ë1›Ùn˜½67šé‚Qž¯—6¾çª¹ìÍMª ºMÙªÍ3º7èG¶K«p(ò£°"o ço|°Bê–T.Ë⑼ÛAIùù±¿ÁJ,å7<Æ¢uH1íDZ‰EÌã•Víccâjiš¬FQÆçâÖ=Õ¥öM+z{zÑîR“2ÍXN÷¼°±…5¡³nº\„¥NKíòƒ0KÇé”\Ò²"ââ"èªyRÎÝsƒ~ýòs…~ûásŽ<]‘'åד·ùrç÷£gÉž9ƼDžøÎ¾è[_Ô¦öEkúäUØÇ‘·´ Îî˜yþèé«Ï`ÔbÀ¦äWx£ º¤EÒbÃ-Î(M|h;Ýc¥ ï%îë)é̦ðÞrVÇ+Pa<ÏŸ¿Ü߈~?Ä‘º³ˆÅ‡"– ˆX–~Ã%èÉ`Ïï¯L§D>–%'J–\Ä(-©ˆëÏwwßÛ„²ÝÇC4éÛ6¥WNFwÙ”öµA¹*Fõàr2WG([d ðŽšýÃãÍÍã({yÉk}tWÌøA+Ò 3´nÔÌT¨D?Ž˜:úø"t‡"ølloB2Ö…“±ã‰±7Š>°Æ†i¥0%1ÈŸb°ÕÄT1¨3K ¦ê˜Av™ÙÚßX;^£ð6`0²³QYµŒp·l*UÞXÀnLí?ú듃í'GÇi“ÃÃÀMòï›KI!ý†‘Kú‰x9Ûg®Â>ŽgÚþóÉÓušÇƒÛ3©nÛûql0ѺݣqQ»c¨"{5€q ª‘YÒúáöúñ£˜f ˜”¾³$IñUI’a)Kÿ–Q=jª_¢Ç‹ÉËΫÇ;ûÛQòr’$Íñ"åÊä±åE*³äp¶^û:ôãxq×Á¤µ¦6Î_ÍóõÆüíÛÙåìütvõuöñìäêýäô_ 5ÈéÉÛù¶KÿZêö*´%ÉsIä2çе0¹d™äY¢ô¹”Ûª,Mei*÷P*—2•¥+›KŽþÛ^0ÙaÓ¸'so›[ÙÜÛº\ÊmFè2B—q¹ŒËeÉ.KvY²Ë’]–ì²dŸ%ûŒÖg>ëðY‡Ï:|Ö᳟uø¬#d!ëèæ8dÝL‡¬#dÁÑŸ@þ[`… endstream endobj 130 0 obj <<522e232b9603991101f9e44bb0878b11>]/Size 131/W[1 3 2]/Filter/FlateDecode/Length 343>> stream xÚ5й.„qÅáslcìfŒ±ïŒ}ßwƾ3v‰V\J$zTƒR§K!á J‘à 0'ï4O~9y¿¯øÀïoàAºôÈXY+ëe£l–­²]vÊnÙ+ûå ’#rLNHÔ ½k'áܳ¦Œ—S„ûÕö™ gˆÜ#Û#e’œ“ rQ.ËU¢ªÀî£d²\'ZŸm–©Ä@»-1ÒEL¶Ùâi2N&Êé–^bêÍî3ˆåpg[~ë,b{Ì:›Ø½²Î!Žÿ_'—¶ä§¡%¸oKq¾Ï'®S­ ˆŸu!q{úê>hKñðb]L<ÞY—OµÖ¥Ä{¿uñõmí#~άËÉЃ«+ÈèëJÒþé¼°®&SÂ75¤kÓz“ô|Z×ÉÙ$[d›ì]²GöÉé—ÃrTŽËI9-gå¼ È%¹"×äYrü§°=@ endstream endobj startxref 74887 %%EOF glpk-4.52.1/doc/notes/keller.pdf0000666000062000006210000024774112175147600015612 0ustar maomkpasswd%PDF-1.5 %äðíø 20 0 obj <> stream xÚí[«-¹q€ßó+Öã9pv[*Ý+ ã@BL†¼Ì̃ÉÅ„xÇ8ò÷SWIkµjÏ1$Ûaسw—j©ÕR©TúZ«Îã7øø_|4x´ÿøþøËo?ùY|ÄvA,oÿåQÃ5òã-†q¥öøöŸ¾ûô}ŠíûT*þÀ÷©†ïSKøÿ.øw.ŸßR„OR’ þDù]•d,ÉIKñ§fúM% KJ)ÕT²|Žd ÿnSnÚµ‰¤âJÒ6åÏ?|û72®Ðo¯µÕÔZÖ¢:à§V ß.I£¨‚ª·áš·Š Iª]T3k Üp¾õO~ˆ÷-ÒåÂŽ|KáІ„paµP©ÚºþÔšjùÌ×{[JÑšÓ£]£Q½mÐùJYj !îþÖãUöC¿Z¶Û[¿ÂghÚ4F<’ôÀP>Aƒþâòô¹ÇO—Öž‘nZ¹ö˜Ú…¶óVîBÕÇÏd*ƒnC=¦½–·¡T#‘ÚÊ#¢}…Aµl&V]6#«IšHLã!ÍcjÚðÙÿÒðï͈ÊsÚÝÍLY^µ…:~lh4¾ñûÏ6*Ϧª­®[«!¤+Ó<¢Vÿµ*´M£ZùŸ~~ƒ†ôéPQ,W«ª÷ŸßJùôÇØ—µ~úæP)„«¨.¶õÞ—ù‚¬å_´che<ó6OR®Üg î•F kÓ»¨V1Í7Àßý“Î9êg,§Jß`$ª­ç*6Úf)l„Óê¿Z™±¿­ßœ[^ZúK+ëÇ­ÄO´£³IÐ÷û°»±—X.FRå*öy¾ –¿¿p9CW’ÕÍžæ|K©qš:ý‚¯¬¾¢~~®K|ÿ*vuº7.€½¼Ü=†×Û·Î ÿvš×8eSã8iw-WzuÎO•¦åtÕâª6oK̸ÃüÏø«Š»Ï0¯#–{Ý&©@ÝÛù´Ä¾LÑVÖLcÆå¥„cß|¡"ØÜ˜"Iã§—X@½…5YªÜL}Ëi ëW5¿öÏ6ÊñÉ£Çið àÛã•—·¥^¬›_°xÀâ3ö<¡í1)¶Z>Jü?¹N)Ÿ4»ds~6‚è0µ;^f³¬(EÝiïHÏî”͉æ ®iûTXÑŒ9ç}Dõ?âg2Å”âhÂSh$7©MV•UwA\d•ÕõN·•W[T^¶&Wýl ö‰×¨<‡³ ürò§§™a‹­-jå´J¤¨«„ôŽI^M•—ÓǨñÞߪy›A²öcÀ>Òs“ãn†yÛëpc>šê¼j'w¯ä4dÖ|2Á9B¤žî2·©Uönš+a¼äfÑŸÜwàÇÉ8â•ÐiãF$4‹¶E\øSð'®!0àOÄÀÙ¤äBq~øŸüT¡M‡÷©ú[ß G¸^¡ê=ßžî›o¿y\iôÇáV\è¬îq)|ÄæÕ¯ÿøù®Ú®¢º=‘nãÅÏ7õ¢ê’«UgÁM'U—Ò$µ§k,ÁM=ÒZÃ¥Òð†µ.Á«z¿`i¢€Ô×঎I“RŒPP½v ÏLpSGk¡m~Ï´Ñ~gnSLpSÏZY¡Íá; êÜÔÜ –VÚg¿³`,ÁM=hÛUJêQoÇ‚Wõ2.àÊúÕ¹í(¨KpSÇ=?ì>Vî.Îz}Ó­WäÂH+â; ÊÜÔ±³èƵžðõMǫʼ³ -ÁM˜¥QÕQ—à¦Îñ*–ÒÓ’v”NâëWå<¤Kù;8Îë›2ÆHðxËå?–à¦ÞT=Q_¼óçÃÜÔëÕ"•üxœ×7årõA…M•ëóú Lƒ‘ø¢´»°Uªà¦ž9`ͳAgõL,Î7õÄ®!Ǥ}ˆêi êR{!S}—Ï/ÁA›ˆ¥M ‹>^íú¦ŒÖF ŒW´ÓÔqS‚¥8IAÕãœÔéÖ¯ÞM½LÁAç –‘UuX‚Ã’Ì0®’T=/ÁA=QiBÿ­Úm^”¥0ë Â!Š0V¯Öò,–,‚ƒzçÒNã.æKp°F6 ÌÔ^Š€Ó‚-»375õº‡Ii°Q¹è4*Kp˜ÒÜXij:GËÜ8j¨(KppEä½3þQÝK]‚›:»V,ÄfÅuõ%8øEUr§EÝ(?Œ.:ð½3M’wÈíXpS/Ô½XŠË¡zô>¯«½kȴˆÿobž"¸©w­{‹“¥¨/ÁaUä–× áþÁ-ÁM=^¬ÕpÉóú¦ÌKyMygA_‚›zó’½³ ,Á!¸`ßXyF½sp’–à¦Þ ¦PáP×÷y}‹¢‚̃ÊÎüê°7u øK+ù‰ÑÂÜÔqhR*Š‚±7õªÝ€“SB:{rÜÔ;T*ö‚‚ѧàU½¹” £Ö°7uà(h5#¿PÜÆ` gêÜëÉ…y}S®WÝ{±7· 1+IÇC*î¼UÁ«:†aöÑGA÷‡#+(jI<‡=u>¹" ­ä¡’<ä`w¨×7岿{ÅÁŽß7õ&f˜TÞÄ£‹à¦®N”f¯´\¨^Ô!-Ù7 6`°³]ß”A=®:"Ôæ9"zÔ²8µ$êY+gÁM]©ÂÑ; ÊÜÔ+Ç©ÓA“ wÏAÆnò ‘ARïz;ÜÔ»ø\\‚†´}ð˼ªÇ@»bY©H;ªå뛲ºZ+kãH.ÁMĸhͬb]"8¨s˜F+¸Ô®ašnêIü@©gm nê™w}dUç0Ouö<Û°va8"×7å"#JqSTí¾u)j±Rm‚›zÕðsÐ|uvÂ"8¨§¦ñ¤j·y}PΫVÕîKpR„M{^”ù©(Êîª]—à ²„ðÝz%/Á¡yøéwVõ°u޲i÷aZ—à0üR»îéH=,ÁA=ØÎ©¨qå%8˜nв- C-½-Áabð, ÅÔA·yå¨Å+Ëã³C7A“ÏŽ&XäÌgÑ‹†}ûO‚ìnÿÉÇò–kòYtðø,ù%çÉ᳌EÆ+a¹³òYZÆ<>Kkš+峯ƒÇgi½eQgÈÝçžcî.¯]ŒÐÒò«Ghy—¡å]x„–vX¼C3BK‚=BKÛ½X6HG‚Rkcº‚øccR˜êÜíxD èaŸ{1ÝN/¦$Æ0- Ï…îaZHE(Ë´ô¹±¹šbwÅ´ºÇh! 키9Ã-ä¸f¢((Õc´@o#ëÆhÞFVÑ‚½6FK‚á"ZôÅq#´xY<@K/ÅÓî‰è¥¸û¦è…ÛÎgñš əϖp=áY¼.¥—ky§³$d;ÓYz¹¶ÃY¼öÙ,Þ1íh–ŽG¸d–Þ´ÅÌ¥ïG2[”ãM2‹~Œ3™Å^Í;˜-|\×á²¥ë:o\¶htvæ²ôM²sYäârY,eÖ>¹,ÚRÌ.—­‚K&—Åë–=.[u1œ\¶êjxæ²³Ô¸l•m½Ãe±´¤Ë¢`$—ËV¡“ËÒûGð¸lå첨 .•¥šÛFe©ææQÙª;ŽIe+Èbt¦²¨ÎØ|RÙÊ}áQY,ˆkTVüˆGeq€8´žT–¾6\*Ko|ËNekÐÚT– o‡²xÝ]&KF]w&Kv\]&K3&ïL–fIv™l‘c¦‹ÉÚ›ð3“Ź.êÆdɱ%—É¢éOP?î~˜|TÛ¡,~<ºL¶Èvv1Yôæ2Yt|±íL¶v˜læ!YH–ŽF¸D6Kس l–С²èú˜5Á5ªGMèÜåŽeñºyT–ÉÚ7*KË`h•… ’¥%×%²€>úΨPP»Ë¨ÐGî@–®‡Çc)"©m㱄„æñXŠw:ìä.•Éæä.¤4.˜Ò¤Ží¹ÙÉQÙ MÕ¥Žu+D›†Çc)È”ƒ¦“˜6Ž:bÚÂä©Òv´èòØyrÔj¯]{öX;Æ—¢n<¶Ú@y,cï™*ž© ï¬ßQвÛïê1רÒ™ÝQE¯&GxÇ–®={ä±è¦Ú~j–Ü\,.‘-Y+3k/E‡éhíEbÓ…dQP«ËdÉóôÉ¢`t—ÉRVw&‹¾(U—É¢ïÉ»séâÈŽ¾¥^û™YrDÉå±èxrÝ€,鬑e¿³™%Av̒둵JdÉ‘ÅáYÛ:’¥ëá1YrT9îk º{h–61sAkº«iÉc²äØærYÔÓµä1YòlŒ”ÉÒu‡É²_\H„ ·“¢ Åä±ôI¨59y, *x<–ü-GÕÆcI=4Çòv6ËŸÇòvv;0Ëo%eŽ{Ç’vH%uÞ}å› Ç²ú~`–Õ«Çc©”QŠñXŒâñX*å ñXj{Ìå'Ë‹ÇÒuöÌ®Bå±¼F&ÇRéØÌÒˆ¦äñX*åý„ñXŒäñX6>Øx,Û1x£Øš&ˆˆ‚.DÄJ ï(Õ=. µi7ý¬mªötx?.K‚:\Û¢xŸ‰bQÐÜã²ÐÒ„ÌÒ˜–”¸ÓÊTçNoejßû¼5ÅëÖ(hî©chCöÖ“ÅÒWܲËb1 i7€®¤æl(ÏÓØ<©{Z§±ï“šBÙºáØ¾ý¾+W}í`Ž\Û»xΉcéu¡{dìïıöÆ÷Ìce›¼€,^w—ÈÚ[ðéŽì-øÙÙÁá‰dGÖÊHvh(5™ìÐPê e1âäw²ÓMÓÙâáºéÑ×7&¤ö®9bÙ1ôU¥rYJèŠf©”]©‚ÙÔ“žÀ,ö˦ ïˆe©°Õ˦ _%:‚Y*å0ÍÀl YÞSÁ,•æËÒu÷°l zÞѰ, òð°,•²çQ,›‚Æn`–oV<0Kê;—å^ò°,&G؆eI;¹‡eÙ46*K×݃²du­nT6…íkˆå¤._ŽT,ËV –¥)•¥ëâž”åÉØ7*K‚Ú=*Ksö“²$¨Ý£²ä'`ß“ ú;â1ô—aÙ1ôPÓ‘ËÙÒ..;díp¸ì…hqÙ! ‘ÃeÇú¢®€ÙQôTÙ‘Ì9¿¼È,Ö£KféK*qƒ'´cNô…óËËI—­P\6KgfÒÎféÌLrÙ,JSÙñloаŽ|–ÀÔÓÂ^?:Cˆ‘D´ø—ÐÎS£FhQ“Kh{Ö>Y JsY^ëŠÏŒ¶®øìH [Õã»Æ!QÐÀå-O)öØòä{l†-¡6ÖÇÌô^I×Íaç KŸ‚ÃqÌÔ7uÚÖñVú¬^4žê]#ë³új–³AQ o:sH#[O•óµ×rS¶†Ÿ”g¯¨ò씣2¡XØZ={«%]dZIAè0”|€¿Ëi)bk’SCy,ýß)(¿õ'~· öDtšŠvM;1Á‡=΀~×z¼üŸèñ,'ŒW›àãïúŤÿ·ñ¯*üvŒ¾änûs¿¨ÿ¾ ù¤‘¼ ø|öò‡úèÏiíÞbäÂîÍZu30ÒË6>B´§x|JgÈÛÇ©âgqLn†=ª¢|}锌òÐ60\Õ$hpH¦ÙÄüühðUùÑâÿJ~4Éh†»N Rùì°æs³ iðœVÅQ"Å ÏyAUBIó´LSßQž¿j9ç(•bN{Þº¥Ò³4|I’][ŠÖZfí/*©KgéKF»¬Ý§¥¤Äø³ j’þ½%˜m’%QÒ¢­üw’ôoÿîmÄô’+±ŽOßÁ¥=[âð=s% GM¦a}“5ƒîÌ×ܶԕ*³;¬…uË+Ú·z5µ ê–o{öV5gdí6ªR‡¦Lœa{Ú|ÊfHÏ™aO¨÷ñqCÉEùaVrÍ[öÔ-<çØæÉÃu=õv´Ï½ÚD›©¿Ø Ø_¯9뼽ͬ״¿f¼©„½”»ëÍˤkO¸Y&(üÑ,íâj¾*K»›É1PÖKñ7qMIËœg>ÇibÖ©åuZ=OdKœåQl°³¦„M?>à_öÛïv,iïï­_Ò<ë­?ÛŸY9çCmä•,•ª1É­i[îjë!32iâ¬+Ûä3ɇF-=k=¤gÅÛ¼$£æ‡‹ÏibŸTß>í¹K™¬bÒÚјO ]y×ÅÍö½ô› ÐsÂ|µ ùÔþtE—ƒ-íøL vÇõ—­Šìät$øAt¾ÊöQÁÒ¯Zéwñ‡Ëôb}ëÕ²íίÛ.:¢„V)ǰ¯Ž)Øw]ùA8¡SÔ¡y+ð×S_þ̓X·gUòT3‡¢÷Ï++û Ìÿ[ýÊk&a°´µ‡Ü¿¹î«MÞŒ(o†eµpÖe¾AÌÛò±ž%¯}ZÒøsQ /yvë}rëCX³öE4Ͻ|ršcCüe΢B‘O\Zt'že& Ž6/™ß¼½ÿâ_õSºF£27–¥òþ‹_ÿÅ/ÿý?¯_ÿÇ/ÿì0r> stream xÚå]K%ËQÞó+z9#¦Ëù~€ÌËFB°°¸!å–-cÆ’W ñçɈø"£Î©¨ž[6èêª'¿ŒS••ïª|ùíK| ë¿øÒÓKïáåß¾¼üíw/ßûQ}‰á˜a¾|÷‹—R‘_^[=z}ùîç?ùð9·ð9ú?~ε­vZÿ®_si~’*ÿîž ýß­]~TÓÇÄTt¡.k¥¾ODZé>]®-?î„dùa÷~Xåß½ëïõ|»‚ñ£”kËó\­×.ôË ÷lŒé£tº+={’ëÒß^?þô»¿_³úóQuÊh É·­r¡"—Å„¶(ÿó`1@ܾ8®RðP‘®0Þl% ™¥µ«Ó5¸èsð•1‰|¥bOÜ׿ûƽù¡±VÌ€ð S¾æÌ×M@é÷é x.8âAzµµ¤Û¶¬©ÓÏ\*=Šæ(O”}‡„‡Èvlä?Ù8áÎÌÅ» nªf<ÀÿŽvëeíz\”Ö5Rræ‹9åŸS_W,í´· Ö€¨êêïz š¶râ0æ>åƒô æëx~úw>í¿jð{øâÄdÍa}PÕ^t"öý’þëýÛÂÝsÏ;%çøæN9ø"ßûQy‰åXsHÒo]2¯FçK®Å0™/¶F·ePµþUãÛËÏòvÝ1­;êC7̸.P/ø];ý.çõSúÍ?£³Ÿ:c˜à×.¿(ÅEbmQW]—ÔSW÷§*õÕõ<W›ê-7֨ξ¡2×ù÷w’”þ’¢k$ab½±Û…EÒ“š:ÏG>ºîzU1ró‹ŠyT% Uº'tä'›`ëkhÿ’t¯”M*oX´-{Â8D3‡~å†&‹K:™|ñ âû6R\©~8ÝOyVsê ?‚ü«3+è<=Rˆ{ê=ÅX;V׿‡¾NIfߊÛyfŒvÃæ5ieœ×ç-e[þ÷”íW„€Ø™[¢ê|Š[)†[wâÀ·Spm¯d,ÛG>Kè‡h^– Ýú50Ð50p’Þß`À¤°×xÓ€éΜ>è­Fœ°Iîmíߨ !]myªoµAâ㮄™ZÜ–†nò·“THâ¾é¸··­’ú{Y%íÞ*Ù­·¬’4ÞgOWh¦ÓÙqt!…¦ð[DrïÉ9´½ì§`YÓ_R0á“^ì¼jÚ‘O½•£…3>é}xˆúõp­ø‹±‘ý|qÕ™“àßÇ×»«_?Q×xÃ6ëpïäg ɺæ¤wΧ†åWôH¸Ë×Tou-°y„øG¦¼±ô‹3Îâ±lƒ´íÅRÔ,‡=ìÓR=,ßi³CÈn®ÆvYp0ÒB¯‡@I‚?üîå·/KÝ—ÿ\ò¯Ós¿®ù;J|ùÂ@1à?^þéåÇgòr´†ÞÂäõ\È—YQ¤· y"%¢À…&•ñ_(\È×lÒ;„¼SÌI y¡{R®é(L]¼ÛââÆ¤¤íJ0ˆv4D¤±*ðLÞ×#roÇ#. p!ïGœÔ»‘©;™#h_ˆ+Û«Ô9&SWŠÑ*p!Ï´/Wï¤%$ò‚égàBI][¬ÉX’<¨òpäD½Q¸œrw<“·qtºw]{€¨Û<ân_ˆû‘ˆéjq§`ÚbLB-Hk2§\È‹lõZƾ€aÀ…|mêl4ü/Ü®»}!ŽÇ ^©ŒN¢^±ò5cÔ9Iš|áŸÇÝ~&^h£Þõ£Ô™:ˆàB>ºñº¤ìãÕžsê.n·O.äM¦lM]òµ`8äÌwk¥XÜP ¸WÙåk;Ï˺ò"qqXÌ m9/ÉbÀ*äî\È3‰š×e3Òîòd€C^‰Siï0,`à³ÜY[u÷Ýv¨—È^½,Ø„ºà‘óH×j)õn;ļåú8’R7rZÀ%ܺŽ{ì¶CܨwINÑAkC߀³BÌ.KD‹ Z@1À!§§ZÒ?$PÏÝvx‹Å󀎨U¤óðtI¾ÔfÄFì­€Ãæ…$â€,×]2Ùƒà¨ÛȽÛûÂ@5àBž]½‰öÒÖîÑ€ y!Ï{õfÕμ+оP7Úã«Wí²4.äƒ<äÕ[!qP pL¢9¥f\`;ÀÅàŠ˜¶Ma:.äY¬“°ûÂV`Þí qŵ;L¢µ“³òŽ‘’ùD>0r.Öp8¢tÊÅ'eƒµ}!^¦A¡^6„¾0Ð ¸J×p/dµÇn_ˆÙ4åÎ!fyg‘ àB>x —W'vÈâï¼Ûw% ß­Þ$ÞMd%àBžy?RoîLžÉVUàB.µqÔ[2“7–“.äcäcÆ!§lL:†Ùt;˜˜ö`äQ£(É›GU¶…Î#5ÞNdgf/½Ý-RŠSžŒ\È'‹'Ïä)î‹1{¥”Ø*òÙ+%ö׌wUÌÄ;æM©‘r•}ÀšD÷¸Š7Ú¶# Œ»mG‰!‘/†ü…jÀ…<±Øƒ¹º'0R.;Ä%݉£”ë1O².å&òÅu)óóˆÜ”‘³ ªÀ…|Š€€¦ö­N% ó©  ¥; J’}¦ú…R®iÞé—´\jÞ§¤¬x,äcp!_ Oº‘€’ïtcZÎ/-àV¼Ìx§yÓògg:iõ´<Öœî´:…Ä"i˜òX ¸G˜7•ìá/ L.ä  ìDvu¹³w¨WÌ›L^(‘ŒŽ yÁ£F 3yÅ£2p!¯b°ˆ˜*3£kRûÅdP&&F¬A€ yg‡q°n'ê±[Ò¥3Ì`Æ œ9GPÜ¿T§8xÃsÿ¨—yE zf¼³è¹·Ã9`òƲ\grê-p=&È»9{ÝäØ0¯,c7àóœ«EäqÞyQDÎñxhDÚ‡ÆÄÎ^Rj¼¡œ]KJ¼ó-‰œíæÎ9Q™—a€CÎ?u‹ ¨ýÎ-¦EêêcGrö±Éƒ/`f€Ã`MãäÁ‡ÓÙ®'W!}³y:;x§Ü;xKžC)¼oC)´¡Ynj †€‘ï5$.Š}¤Ë0ÀF¼SiB:dïTQ5\%cOG5À‘»,»48F‚4§»è ñ¦¶ 1 p”³7ù÷¢b¢€ÅÓ⎢*&p!¯ìòh<’ÚmÜÄ#IužB›¢ãm¬“ToœòšøÀ\ȃ°_A0…€nÀÅhë’Õ.F«bn_ˆ›pâËd ¤|_&Cˆ7Féj½TŒ¬»ÖK–(Â…<Ëc p!‡W"îÔª~Ä=¥ B‰ÑP»ÞÅñSêr”~—# ³VžnJúˆž§KF3 hÍoœÚ]~#¥ #Ížæ]ö$Å!2·¨©‡ÈÜâš ±áÞÈüÀRÑÍü³ÂßW¢üy—WJT=ÏY«˜0v?k5EËZNlî¼”—ëlt?fÜÒSÆß”zHP’K•D2/ÁtWÈEûþ©Tìœî£ð„F·“æd‚N4„#q-‰¢¥¤L0À µ(yER&ì¶ÆáÍÛ¸„TÂ8Á'É‹ҲŽ %€—dAïÐ$Ën;±0ŽLSB¤!Ë’ p"m,òÖß”i«»í„ñäZMb¡ iDn;EQ¨ä¦„ƒNxS>Ä=¤xe6À ²RZ“‘3b§,Íp¢¸¬®×ÔWÍmĺ'F,é€k­²){¼É ayj:Á€ y’ðt/ȯ.`p!â™,®BWG€gòÚây2˜€tÄpäO\:Cf†çÿ ÿ>p!ï;êϦ3ý>p!o ç¬åþ}0àB^EÜ,B–iý>p!/’Ü]É«$7pÈyU¨fžYlÍ€ yãwùl…&õ`€CÎbfÈ,ÂP€ yÂÕ"…$ï pÈYÅÏ+I”òˆ0R@`¹p¦J‡|‰Q„òd€GŽØJîJ7à a!Š6Ç µL .8ä¹¥E•n€C.½;© Ü.€³¢[YYןãçÜvˆwÄÃ‰Û px‘–¿,ãÜRxù8ƒ»,Óe6pz7ÀÙv_%è`5œMÍÓF²K«ŽÈàÕN,rE4D‚¼P¼¦ïöEØ!˜›™£DzMÙÈ+šwª5É£äÛ\+ßzç¬3nçç¬ ç} ÙÛ*×§W%C];ÕÚ„7³Ÿjí¸ô=ÐGs·ÝÈÃ^.„ØY)¼ J‰X} p“Ë+"€,—À)µ`Þ"iˆT^ÛmÇá°ìâîž›+8ɹÁ­ù'Û'à$çx.Ej•h€“œk]z¥|bÙmÁ¯Ò&KïÔB›Ývªx„X3V]ŸÜMY-ã“s9«Wê>–ræ\ŽN²,F#Aä¤ONº8ž3’ÄÞýÁŒ reóQ@î²ùÒÅ­§q46¼o¦Qt±¬IF½×4À©&ã0ÿfŒqËKsF£È¢©Ï^àTÊ÷Sxsí‰@záÍ¡ñÊ„ Õ7u¾ óR̬Â}ŽãÞ×}x©#I]m<Ô¤H]§@f¢dUÒ© R¨{œ§Õ6Ô+饄%ínùMD´ª”pâúR“0ðÁÑ; Šën;¢5M^’w‰iGåœÔ •M5ɧ á7 p„ŸÈf Tž àH3)(ç%á— pÌA{EP@ŽNG¢1[SI_†­ pdšè¨~4ˆ´ºÛŽDk(å+,XË1¾YfÏ %Æ«ÍÒÛŽ@(öP»>í¶ç4ˆŠÆ»9MÒEÓ7§JºˆþÂ!i»í¸/R_ܘ;Í Ld-æ@eôŠŽ´ jåTHËb€÷V‘V:éKE»í‰V)°j*Xµé8Œìt­-R;À‘Âh¡¸òœ6àg”ÊŽ!%»xµ¥l²fõ¼¥ª€çóÅôå&)b¶C,¦3l^Ø£‹žÍK½I\‰¤òжC»øRþM#3À»vïF¼îxFr½îÕËŒ‘ºeà³ùœ¨bUæ0î¶³@Ü™õR³8ä Î'F.o¯p˜‹’¼«œ'~ïW9ODñºn¸€Øgw7œTó/‘· 7Rg1·ÍJM¸‘ÅÍJ­íÈŒB ûsàì~ ^T¤dìÙÂÁp C…Ýv¤–Äp&¢ºKIezQÝ%?yMkÀ¬/ àÄQØ]£¼Z‚¼xq²Kj>ve·½0 1v­’aà0Š^…¯Õ ²$¸í˜ö2î‹‚l}<·v4UÞõ pœNÒT0éõd€ã!1sµphxdî¶ã¬‘UUZ”°.ÝÇsäNÓ²‚4|¹´,Q]8Èh;×gmuÂQj8ÕòXXüeæÝv*?„¸ÀVIÔųU¸·D:¿L…ö…´ŠÔ1ê*"ò†\êaø¾çzN­ã!W› @ÿ!—œ|œÀ”x;9IDg¯N–—‹o–'㆖PËŸ«< àT6µÆÊúä.cåiÓ®öèwL[™ÿ¥"«Ýoˆ‚7Vöv+xcÅßnÈóÞM¨Ìfñ)€S©Æ)«]Û (MÂÿ[Q}Þ ¡2pm¹ ¨8|Ò«Ují)™œîj§¨6Z‚:‡¡üj»Ã¼^³£þ1aÁ à„Xš%¸]äµGœ8< ïP0 pâð ½e ˜¢àÄá9*–†ˆyªN(žkPÈ¢Ï()8e&)r©ëëg à±°,^½R Ùµ†)x’TÓÄX Q/¢Vpª¤ã”L¾Tøö$öÞ§hPÚ…±‡]ë匽I98õJеMŒÎýh³cf{EÒsN‘tQ{k HzàTIOÔNH˜¦á­[¼ò+Ô‰…]~e€SVÍ‘º%òP±-gà•U£RLv^“/üpʪ; V$T%î À©bë¨ý’5Rà¸kT®Nçh¶N¶Œ½¢x¬â½~òˆÔþdL5À+îã,þ0"Šû ð¾_?GjÍ*ÞÝÀû: ÷ꇔöïÝ)‘ãSÅC&¨òÅ ^#;aê ðÈá\¢$\>ÀûjLÏUj¼éa ð¾ÓÅNzõa€W,ŸÄGñT,Àû²O—xAÒÌf€C>,êZ¹Ÿ px†‹­êGlPœ$€ÃÀëhÊ3MÜ<¼ÏÁ0y‡p¯òÉ+Îæò)_&àÏ=àlmLú5(±‚8U¡ü¨]+÷[ppw+÷é«WÜ›´ˆ4IøDGèqgÑ—=2gºg¿qÉ(÷ê¬7ùô§ˆ”¯Ý•oM®Ý¼¤|ëwG¨™JH ¸û¾KÇK©ü}—¸§„”=à>U)É VœRÖîš3& àè_ÅöêÐ<8¯4±vQR̤î³ÞGì¢ôŠëSÌ$œ"Rèªùp/§ˆ”w1}‚M›N)«[ú@JØóç¶“ jÒ× Ú-'ý2@+O8ƒp$¬}ÈÉÐ&§p2U:E½LùøŽ´¬îx¤FÊì†\Þéâ;ïü²NV¢žž“Úóî1)Ñëi)ÍÀé•›R©*éS,er¿YþTKµUç©z³ìTvÀ¢\9Š‹¸ÚGqY{v- +ðJß:˜_ »N}Gìt¯ÐóÝ^£¼AÒ›PýÑ p2ìߨœ €McWNP^A„¾vGe+Éç»."´ºÔÈ&XœÜvR ¼D$.#R ÕÇ)VisHª!ผruõÜÒ¯®äç·~ÏZ…€y«UÈÝåbà®e{˳H\sÐ~Q?³ÛŽ×Îñ²65&€Bð6ݘ*â[Gè&ãS\8!µdè;×Ňœ³éœgÑxÍòÕɃ|TM¨‡Nô#¨½4ý(xÁ’ kLc%»íoKo “ pÒ5’¶è:ryW€C‘Lzõ:6à‘WØÀQÉ pÆ>‘ö úUŸl€÷ x2èùvñΠ'röùj·ì÷Áyë–}[ÉÔy4À!H‹Ä¨8üÅܧ©ýÍpnjŸy»Á+Ë`öi€³•ðhƒ¤Y¼ÔaE ¥cƒÎÝv"eïBÝúÃïëRg·˜¿.uë“”åät“JåÎéætk<¹ôŒ[—ž$쌧€ ÕïüU®| GÐó]8‚tƒD/4»+_l¶—–tæ¯ÑrJ!¥ŽÑþ4Y¹‹ÎP–7ºÆ~hý.öÃ%òùYâù|Y¢úVý·ÒRu?nÅå§ W#ÜÅÄøE‰›–7V¼oÔS<‹½ë]Ö¥Xl#,pþé܈‘"Íòr3uüã\H’t}þl°þg8æwa¯q)Ý¥Ä%üg‚KÅ8@ÃØ«¼tÄ9Bÿ[ÐÊÎR‡úbÅ¡%¤¸ùË‚gùDQb0UíøÙÇÅ&Ñû“. ý>þ:•ê…û¾!)Ø*Oø—:º:å[Iv4Ñ+·ùÌ!ÿQŸyÍ š°Åüµ²ƒýx7:"š¿=÷gÆÌHÖKÿŸïøÊ)ć.ö˹ÐÙ¸EÒµãè'f‘ WS[N˜¯8+iÜÒ9€EÜý­|Êwþ\Íö‡Gf›®Ñýyd{Ž4ôÐĽåž˜¯2F•Ú¬Ã\Ï6éìäP6*·'ÉÓ\É3]ÉÓÐ狞r=’§æèýIoô}„·U•ðÃBª{BjxBª? ©ü’ÔW)…ÑÞI)˜0ÏhûÚú§w]ª)•©šÿÿ<ö+žû ‘6EZ}¯H›žH«"í°aLøÅÌïê¹Ò¯>J¿þ†ô›oK?¼ÀJiÊßý¸WŠð«Ì}¯PNÎ!l8Ÿ-Þtw>ÇœÈÌáÃé„ó›ûô¾œ“{ ŸöÔÛãf©ë›Î6äçxûlÃ2.Ë«N¹«‰eG¼óé¬ÝNj­8´íÔ޵”£—y>‹Ðz®¼ò…ç;Î"Ìgö¯œEh§ö7§¸sñà7M±\ñÍ)þ„)ž²‰N</þHHÖ£uù¨\ï`ON’C•pž„O~ÂsàtÎ÷ÎüÎv‚ñç©œõnÄO%Ÿotk䯿ê,.Û¥}øúÓ÷êã!¦ežúlº÷mº~–Ó9¿ÿâ=aµA¿ïAùƒg¨Þ’êÍ ¿V´`”Õ]È¥ú¿ã‚<Œ—cô÷§²žoôÃ%®ùÖš†,D^ˆ‡KÃÜŸÈ:÷!èôTF}>ÏÓNÃŹ¶9ð'=¯¾="w]¶÷ÛC«©w¼ã˜fw{G ãÏo>LøÁ€ž_1 ÇÛ4—Çš»ò·Ê€Òì0ì¶Ÿ–Òîó£¼YLG÷\c޼)ÒÎÇìòýV…Diõf’¢•éé¼úk(úÅÝv\îðÕS™¹üqw×§«¤-Ÿ„Ûè«¶å‰Û¾&±"[÷ßøÚ´ñòáò“¥î>ì˜sÛGrø²lj\§µœzþv;¿ýØk;LÏ]—7Óí2þ™žêÝ›dj_6› Þ»]ϸ–éžç‰zCñMœµ.Ñ쮯ء{|¦xï§ÃÃK??ŸuÂal>P^œ–ò ¤šI¯ý<éQ7ÌNÛA˜œÒó _mñDø›öüÉoî(ýø/þ¹Ñðù endstream endobj 27 0 obj <> stream xÚí]‹$·ñ=¿¢ó6K¶}”¾lò’# B0^Áò`ð9{ÁÈCþ|T’J*õ¨{{voÏ0ÇÜì¨KªR}WI½ü¸¨E¦jñzñ^.Z~û°üú÷vQRD—‡ï§…wËê¬ðvyøÇ·—G£ü£qæNûô·S飇»Õw)¿À>ëË·“ùé_¾J+;¶²—Â"¸è»ú<.^DŸŸŠ°¬J8ÈÏU}Î)áÍÒ îg„†>2 ú†´Cw«r¶|9úša×AÄ-z%·ô!ü0A…¥A÷œ ÑÔç_üfF&g6 (5ìC]>L0XDÀãe‚ŽÕ}fO~/TìêþíCDƒ8‡A¿ÃÅ´Ú׌cV¨PÁOÒû¬ŽWšYàÝÔG4¦7ÝÒú.èKÑ/HŽ2 nAÖúl/FÔ¥Á^’q”E |±ÃMÔUÇ',éÒûë‚PD·ž)«Fm”ÕŽœ—ÄùD‚ÊÁZÚh5æB8šx65×=ù›ÑkÕg’Å)™3ÉxdÆ53@èÚðœ|ÿeQ«÷³…’¿ ÞíÉœ ñž6‰òs—¾Éü-ë¦lƒr´e’vu¡: `£¦O(¼Èl¯™«ºª„©\ÃY ÜcG+ýÉâ2Ëzhë`èòœöŠ<ƒDoŸ}¿$¿N!É»âùí nØUÁãsÀ+¼’›@Ã4ÈÕeÜÊB€¹Šƒø}ßU>ø!f%#ÚÊR9§°¨‹D»}—ØQÂo™IªŸcŒªÝ×&Å'Îï‘,ð¤GÒ—¥,°ÈßOYäig‰¯‘Œ4ËÀÓé/÷?ÅÑ<8¡;ã ;ן‰Å…ØMóMM7ëšÛBö¥Œ‚8Ýc{2?Ù8¦8ì‘\Mt¹µ¬†ž<'&Ô£ï%4/Åt-®#«†F—”²Tõ“Eë+*š©{’ƒÆØAÜ–h…ÝA¢å„cÜÆ¥ž$½Ÿ,n÷¬Î±È¸õ¬-:æÌ4’‚I G×évN¶:j¨Â’)±õ£°‡­6ØÈC"a°·®7 ÷¨lþ @0½Éª=Sùm \XõÍõ¼ÖV¿$I›¹bxâ€%ˆæ™UË‘‰Ž«†˜§¾™4 e­;²¶¢ØÀÊ“Á+°j#¨j´Žl0TBQÝ[–èØžVCÙÎ ’êú$JÅUÖ˜1*?6õÌäêOgœ­eÞÈ:ŤûQžàgéTYÅ«8ß‹:ÂëI{)Ö» m]^EçãPÜ…8²cšÅdYö4Ó${` $ÙÄÂÐB5Ó8î7ki— Õ Ä“G­ë_»êIåÏK½ýÂ# ÀÓÄ&È\(™¡·áGª)×U;ÅdKR¥†yAÚÖxÚ)¯L8¿ÆÓˆ ™C/s]Z;®½ºµâƒc±6€™%å²Ü%›µR_ÆI8û«ÖÄ”QX¿‰Unè*ÈãrÞŠ&€Çy‰u¢?Tkå§y9Y9ý~žî¨Ѭ’oÏk°î¬T•¿<¶9Õ“Ûò;])8Šy}Y~6±X±‹œE‰—jT óX[U¶ÄEÅ#5HƘIé+f\ªõÂÒVü5Kz(íÆLÇ6aSÓÇ;Aø¨QÅXûA8½ßw°³N€–Â߬¦vôD)çn µ©'ÝÉJÈ==®²»¦ÉiôG¶B_N}ÌM­%çUq‰™µA›IyºŸÙÝ·°)ºíYØgþ³Û@Q×:ï–¦‘–±w…fùýŠ…x]“úS¢™©Í›­µKúEÕï]çòÊÚC:·ÙXüÌŸ:%‚;êY±þê=-×êâ&JõJ^ÛÝe®• ±5$Ògúe°kx¬¡ Ž54øWjh4´U»M0(äÖ.”I“à:CÍÎZöCò•)4Ï+ÝÚ¶Û¯kËÄç »åY©ÍëY~hPÐíWhˆ]^ß3—Ž$øÆÁÝ Ó‹ísuTͨ¼€8?®*+9¢;ªˆTn@©‹)qTMÛ)%h…(kA]Æ %[–aý¦½Ø§‚Úº8ìá¡‹ëB:}èâæ‡.ïæ V`ù-Ƚò¨dóüIJ![OâZkPyºUC²ÓÀ%8õw®wSŽ:=è £Ùí ÎL”Êò2ïlƒÖž-}Åi—9vLLëIN’V@lŒÚL²î]§h-Záh.¦ï’pS#€w¦Zí’\ÌAÍÙ1F §:Š<Ð…—ñºðu¤Fˆq§×Îè"ø‰÷.óO•º*¸~¸ú¢3¶€™Zƒ˜Ú°êgYïæ‘Î¦ç´§äEÀ2Õʇ-Ù|š‚ü—›â¦Œ–óŠHÑÒòÎ[Í7 °³}j-\8>tãš1éÃ5]TãyÊ‘éç-´ä o£'Ç @ݾ¥.J[w]lSÄaIÉÈéYú`÷аz¡l°Ü6Á”B´\ ØŸ”Øñ[)Ùi•5(ÎõÆ0ÔK‘©Æ'¥ä7q¹Q±—e9Œ%wwu·Æ”“–±Ž[¶â€~ZÖ6[µ¡7á{€[‚žg«ç|°QCb#zÏ£³Õjô‡ÒÎkWK`—ë#^aë®ýLvÛ½§6¿bBï© ZC'q0ÅUX¦4˜« Öô±¹f1'•Z¦J>E·A£“JžG{ãT™çÙ·M[_²Î}µ/!61ÚtFûˆbKÞÌçe¾ª~31MJùâAxãé¿{X~\„‰aùO*" nûáBªå©$ë¿üsùfùº\ªãûGLk®àƒ(,øw^zD7ŽÁG†{ÉÜÕ¼ö‘ÂTd Éë†KmNC¾Åô=Á)0 ë‚k‡‚SQ£óÇ qØYeœÙ`ÜŽÂ °¯_áyXïò=ŒÇ–]J` 6ƒf6øfö'Åþ2ÈA»œÆæAÒ.ƒ>ÁD¡}ùµ«W©˜×¨WÛBÅ·*`$¬ Ýð@ï=¸}ÆG\êóœqÛRåÆàZŒÂ?1l íMÐðI¡?5Ê5E×|¢Øíj#ÝW˜ þ ù¬KR9‘f^© ÇÔ)óUÌPŒCð:`B¾£³çÇšãS¤Ûÿ*Ö„BÕxº0ŒÅÉXxí˜}ÙÜ7¡å-ñ®^ã; ¯ÆáèŸ:äÚØ°Ü@ÆÙ`øTƒñ4o‡ýütNçj#²Þ[Q ¡¿•ш‡‚ ÖiÖîZË›&+Týo]A€«Ïª¤ú\8\Éw4¥©=^ƒÐVSQ®ÖÈò¥®~åψˆ!,a¢¥|Ceo"ÇEÙ¸4z¾d´gRqð´ÍD’‰c©€â©‘áEE,ÝŽšFO­ ¤Æ{/زõ?%k%Ó‹ Còˆ‘®3?9î$t* ï^e]Óÿžñ>d]tÁù>«ªÇóŠ¡!Võ°6š®«HA¦¥+j&Àa‡uPÓLBè/'™Y·}Jƒ›¨ôž? cm…n‰M oi;lýu®‡Xh¨ækYn‚F¦ TæwØ«æÁ ‰‘TzÜíçYºÏàV£ÑLVׯ?ÏDôÿ#É=W&¬x¯Ì`ß…ÂGßU{òxÜ[MoóãX؃;1w^1ww=ÿóÞ†1 2yº`Õ÷¦4ºsð4Ïí0êO07Aë9´yCèÏå ¬Ê/!®>ùê~Yä#2¬‡޹s`þÅ`Á§^m;´¹2¦ âM–UC–óh4¿R‚ÇBFÐÁ‘Þ9{ä×Ùû¥Év¨4ym¢¬7{ŠzÙØð5¾¥FÒEÃh¨×çóUN×_`_™²v~ÑÀ{{š^½pt­tx}…—ó5šö†N>ä/,ÛÌÃm>ËÞ¦ù0½?ԮƬõ5G7ì;2†zÉ s0¿7çúý×ZPø ÜübéÎÝî$9¹ù–§µtÏ=;gü0½Ðrª±w¡AmpìÜA¡‘´aäïÖNf÷²™}¸ÊMÉÞ‡¬H³+sý'^"¤â—_ »Íìd{8ò¥µè2°+Óùœ¾Iop P8 RÁíRPÏ] ¥ï_ÿâç‡$I endstream endobj 32 0 obj <> stream xÚíZKoÜ6¾÷W踛®rø’´¤z `ćlN‰Ý8®´Hѿ߾DiG»NÒCaò®Hçõ}3Ô64ª‘ø§÷²ywÛütÞ<ýÙ6JŠ^öÍùUcp]ÓöJ8ל¿³;j)Zi¼ã¥ÜQ}Æ ïfßj­p”ÂOÒÆ‘a´M#MZÁÒ}ÿöüW”¨|%R6­ÒÂÚ,rv¯ÿ·n7F¤™õ^M'zÓÓ<êPÁË™4ÜUõ‡ÿ’ž×ûP¨³JÏØ·àýî¸cÖQVx—ƽ޷Öîží[åüî%³(Haó÷œLz~Ȧ4z.h—evV8(;`5é h’L®ÆlVõŠYÀ “5TŒ||œ•zÆÌ6¢Ëamv0ÜÝ\¼ù|{¿¼ãö®ô}Zã7ƪÕþr-hON< <¯·ŸÅ-è| ÈU8Ǥ;~vtášÂZ­é5­JŸPŠ•ô?cž30ëö"=ïO¡ŽO½ÀìÄ@5#çŒ# ÷UF8 Âl\6¬ôä,o.ß8ÙZ péJVâѯ(ßwaÄ ë[Mq(võdåh_‚ò$YžàÀã÷^E›£wq†Ùŧ.ø-¯à½gT†’ ¿LyiÇÑb|\;$)ùÒ¦ËQGçt®‰î‚1Ìo˜¬êi Ñpg ž$c£Ìl¡Ÿlý铼1Ú* l†ÿ­Ê£œËÁJKßÂîÉÓU ¿úô'‡Ý€×Œ’nÈë¬$@%OàÇ,ëágŒ;n?~€ŸZ‚6Âdø|ÿ‰‘Ñú^è¼\p0]åÓ†æqzJ?2:¡ÊúÌl'äà‹`ëéÖáZ-°¦¥ìí2èqÜXÑÙu².·1´Ëž{Ns?p5çDü/ÏÉM見ÙÄ)MRŠ>O(¨c"{®²ÀŒÖÝ$ªkqzú¶N­€G/‘ÓMÆT;J(HÂaÍ÷&C°‰õ-åɰTÝ ›¸Â‘„”Á„¾ cAà€ËÌ>¬è§>ñ³²ÛÂä‚ÙºÉzòÖj©ˆšª¸¸æQf"i.ÕK¦w“Š,›ò9·”!çó‡Ë;F›V÷"aŽ™F°ŠÁ ,VˆèˆúL14!Ï ð¢+Q]Übªûò—›‚›`]6á fë¾G|`«åxÇä0Bfl»«½¾`eÙœÏo¸"FH½°SGH¿€Ê£;öNmC÷k¶ `eÈMca ™âݧ;*y?_ßQü×%º»“3Lî:*Á6a/½Ó¤^%ýòî}Œ¯’av.¾ª&C¢Ïp˜z'™¡‘byÝn <¹§â"ÜÊLó¨ Í^&X¦Ïš _«ƒx¡‡fÕ@š”d>ã`Õ58=®]©Ré9î"2[̤f«:%dWp­k<ãAª*Gž3*bju‹>×7U‰ÙV·ÜNA¸ºQïØ"¡ <¬M½GxÃÖ‰ZtÙ ¸þý’ÃÄu7éå§½zq‹cÔZq3¬rÁ² j©Ç•lKåµ÷¢¼‡¡·,[”Ùo9«Tµ+VH0£»ZÓÝœRê(s¬Z?[¬jªp–‰,¾™µ+&z¹÷Š?Sn…°ìýkäŒÄÃ@ÌÍ`Ø\¾Z0e/ü²ü£úÁò³g8„Y¢Ô–Æ*vÄ€Ä ëNëÉÀ•jC!4ž?æ*d±V›ÏS±×‡zO¶®oóQœ{Ê5n$ÑÅvŠˆu¡¥ÊOgé–zxP÷?©kÌp·\?¾fÙºœµ¤&؆ \®³f[Ï|šD˜O¹-»+7ñY¬Ä$kÝC1¼I‹Êx®‚K†ò«Z$l®:Àš¸˜­“6`-¶_tKåØ-„}Òª}`9zu¶§¦|tVIï^b—R­†³[Ú:7 ßóì› g'o*&e°N0+5Ò-ëOÚ´…5Ô¤#´|GxȦ¯C²3bàOç±`(clJ _Üæ¦²1­å«c%[³øÉéÞs*·ÊŸWQôqÙ³3–+™p<²o"´úš5©FÊôl5ÒgWÞ§¦Q§ÿ©Ô€Î'÷˜øn'> stream xÚ­[K¹ ¾çWt6—îÍ´"J¢¤Â"—~ ·Æ^]~~xýòŸi0íÔ„˜— wGãÚô ÒÀ¸$NoŠK“†<)˜ºÄ²<[¿—‘ŽT–O£ó"¡þž·‘¥ºô~ÈïKÌ¿” Ò|,%Í{à „h5é‰7 NeIoi ´Ò‘wõÍÁÂþDU¨Ñ'B}‘ù—û‡›¼½=üþ§w¸ýª~û©¼—‚UXÕwÿðµúpûñãí—Oo®ù·°¸ªŸmÐõþç»?n®×ûÿ}¾[Ÿþ|ÿp÷y>2}¹ªoôÞ¾z}}¸*K°VE3.ƒ¥ù™´´î¿ûòæ÷ßh¢ׇ_$}Iž‰*)p°ZµhQ¤'Eçߊ­$⺠Xþ`B6„«Æ*¶ökžmî°(x>‰Î2›¶…ÉÑ*?Ñ8’-8”·´ž‚³ÃÑøìz+òЯûÎóoH¿e ›g]‘GmûαìæfRGóv§rÞ±meW˜i‹ë¶²ºcéëèÑdõ-7*†¥`7L’ÂòÉy‘”“˜Óå1S¹ dy£Ùýhr?XÒjP>’)ŸÓ€¸‰Vµ£çO ×:¹˜ ¢†Ä¯iîI¤çÃþ© 4#—ásðuLÖRöa¾!72ÌVrõ÷Bz™F›#1Ä@ÓŸ€Yæ0U–^Mv>-„ΜìAÑù7AI–³´;v€aÀ¤5~­ JJ…@C´ ŸIéÐÜo‰r7ab‹ Ù½ßK`PÚ6 ïG¦Åë(¿~µn~âLwˆ Ù´ù©¹¼)¦ªiZ€g nš®ö=š, s 7ð‰*Ç žš›>–iÁNʱ sÀVoPM朙yUŽi€VÆä„a³Æ‹þu‰IÒ°1Š—ðTXb2€Æ¾Ä‹Çvl?—}_+ç&bø”»Z’I’Â0$ÖsvOf€¾N‰’Ýó’ƒþ6Ú.§.M[E'<ª‰Y²«6!áÁ? &ú¦èÍÈ‹yPžG1-­OÒ›@“9‘Ó¿(ÎyøUËy´ùà§ð/?ÄL±ÛÀ7yIÚôÌ ƒ²%3xhY1ð&986ÞÖM"ÒXS­Ç¶m*ñENå'Ý‚7d+Ø8…½ ʲ¿ß‹ä°mù4"` ˜ 3³BйR¡YÌ?á;¹oˆ€E`Ùì[8š ”‹(!å—²x’ëɇ ¥aÝZ¦YŸüφיº…>šËaùžXÖ•·4¯à‘|×L à”òZ^œý'ÒûÏîos_®hâГƒM6÷(æÑsÈã¸jâf‰K˜ðçÒd ‡iôwÕ(Ö&q–=›ux7ÔmMÝsëÀŒÔº;&¾¾ú¦3k+µúy0n‚3ÿ¶Šk£{‹Z†ˆ{V/- 6kF F¿ZÝ¡']-±ºqÃwÔ0A¬aLÝÂÕZâq÷M.F›rÔ#åÚÎÄ ¼Y”Cš9ë%(: 'É·ÀìÁ÷tí…Üü3¾7ÿì„+ͿЛ„bç(…`7ôƒÕ“œàpóð™AÙÍî¡ë›ºbU4.½»-fÍ„¦@îþ ,Z¼ÜpÍ=‚I6Û¼Øä…µ %Ë>‡Ôû-A%è {¿6\Þ>KiFt^6·×)mù̈ÃòNϳ˜ó u!ÊSÞg¥±Cݸ~â"ø›Val Zã&‰ ‰ó&ÉBmñ¥ù LÂµî ²b'wòcÏÔœÔ ‡î(tˆ”üÙš½€ïř߸â»òÛ–³OûkéOÇY¸úDòš,-P„€´9 §âñ´R¼Ã7_nß|½]äû‰DéØÖ7àB¸ÍI!¥Ž9©AøÜ yÄZGÞÿ!}‡\æe÷y¦1h{³xÖ<ÐóÞŸƒi?€ÁP–<Ô@Îèˆn4jžQ{¹ŸÁ4Š>ÞófqUä­°9Ö heW˜‡7>Qô-=íÆ““W]œ ðÛ›•Õ4òÎí—7ÿ]\týx%7›½f mÐó”¢=­º,/Ûý+÷Z¥G‚ôz·±Œ–s·Ë|gŽ=Îæôr®¢Z¢ $†½ýUîYDß¡·Â—R°2aše;t+‰Í쭨嗞ÀÀd§ÁyÜ‹C~s­áåèˆ¡Žª%~ÀšœÎØ …¼Ùg$Íó· OKÌVˆ†áø¶VØ&â~8 ÅqØŸÿêñ%ÿâ~Ï®î9ku½6ï— o­õ$Ó,pU? }^ÞÐÊy¥¿¸óPW²å'´g³Ñç÷ñÄ1F<Š’ò¨Ö y"Ÿ’ ‡6ßχΤ£í从œmûhá¹1çã THÊ…°€B @’e(mÓT¦oƒ®¥nãÔK¨¿& ÚÐN@f*ö½\– äU mObÎN’/),@L‰XŽÊ˜KW öà4Cèƒè ÚÌW– f ÞÒš|'öbr§yÛëkÚæ^h–YÅÖ)ºSPò*Û·­ 0)³ÏÃÚå8ÝïÝPþAq-*¿àÙe ï§¾uYm°ÁîVn°Á\[¶Í³•ƒ‚¸hþè îí 1/[ ˜3MÒ¼†%Iå·!90C…C¸œÌ‰ùÜŸ¯•–"tlu±t%gw¢óápÇÉ„°ÒæÀ~|uî õÏÒûVMnqf~ÈÛÜñ‚ÆíÝöÜRvr× rnÑk@ÜNþü˜œ ˆ½Éð^>˼lþ'Û=Ц“µ}¾&@£üÊ‘S¯•¢íBó#O7h ÆÍlQ vFëœ%Œg„ÂvB? > stream xÚ­Xms5þί8à‹®c ½ëŽ34„Ц-o¡|ˆ;Lp®‰‰_RÛ¡“V»º“cej¦“¹óIZí>ûì£U«÷•¬Dø'+¯*ïE5]TÏΪ/¾—¾’‚·¢­ÎÞUÆòFWcg¹·ÕÙå9›h¡&Úº‰6>ü…w'Â3üy‰Ocø¡9¶ëF0œm-̨µ ¿§™ðWÕoÏ^„ím¶»¨ÆJpGK0ájåÁlàq󸑉››¸šT"³é=·&X›7Ý|Þ­ËÂÞÖráhú±  Á¶~7Øèí£ÁºlC)Z®“c‡Â›îÊÁfŽ‘[’\±„y›¶…í\±:‚G#VÑ€KânceW®KÍmJv2žâ…È\XènÍÆ˜TBÂ+1;6£Bœe=~±„£‡Ü©™0K†qGCYµ™­ ÎÌrïò¼çè*+¸h¾“¼ ·i˜Ó°l+)y `¼xî<ªå*NÓ<$\Je (ŠžQä‚â2ÁSoÁŠx ivÂ(‹1x³&.°JÇJã4×%ë´ÖâjšaŰ2Ì®SdþÑ*S3}s…ITÁâÖiÌûR•¡MÛF£ŸÏ–ÓùÝeW­tì««ùí ¿þ&.9ÝfË-N 3þèks^­/n¯aÔ³''#|ÙùîØ“&õÓÇlx#“ŽØËÿQ’(°ÿM“¥Z"ßNìÂ\í{]òëȤú¡Ü'vQÞ{fYëû ¬•;Ôk[òZšôâãR:ÖÂóVí( ±Û^ÖlpÂÉÔðŒrCR$7Úd!$àsŠ%‚eV'ë('ýꤊ¤ƒ gûéÇÒÅNåÒ3Jfa¥‰FõoåÊ ’(;=Þ¯ò†ÑÙûŒI ’«†4)‰™àŠ]a,9’Ký@óÊ‘Š7‰˜_ÃáºT2ä¹H‡ê`{¤Ñyv\0 õ“\•ØéžàYA’ˆy'ÂdO‘{:¦öHP,+“Vìãeðàø‰‡¦t‚‡s¢xhú$÷*÷9Àh4Ž<ë“êËg²€ZWhU÷ ±Q2Ðùi"uTvT1¬tÙiEÅPȼl¹T‡ž«ä›$•2nð/œ#äO*z£{ÈöIä—Én‘’†«ÄÈY:dn€ I㟖â2\&mû«°¿¢.’x Òfä.1€€ª‘¤ÛIR@ðë¡ÄêQª!©Ñf/2)îݾCPy;È äDÅö=ç‡UékÞï¡ßä£Ç»|êŠ0£žDÚîÈnQ­ÍèaKõ’K_Ú)Oa…µu!u­æÒJ¨c®Hà¦ßãÀŽõu©ŠòË}âØq©ãWCíØæj3Ðú€jŒÐÉĺ¦/°“ ¦ŒE–j:ˆ$r£!nă”äYJ›%ùŒAY2í x)!im ÷íî!Ù±nð1Ý""ë£Ã2ªœ}Ћáþ²ËôI=‚ÅñÞôÀUü ðÐ[vÌ[pܾ)†4rPþ_–-Sn#ò<èR%Ó×LyðˆÂ[Ö~H“:]” ÈePsj C‹J ².B©>û8zFVÃe ìFSçòm8§Û–s™†¦Žò·ÚÉwÝ6|˜-/¶³Õ'­ÞÁÓ‡ u€¡»ÿÕú>:6]-'BÚÙtË?ƒ¶L°çÏ^áü³:ÈX7b_C‡žßÍ6Óù Q–Ž·>Gzs·î)ÍžÝÍç°"eúDº=…Cöân~ï² ðÖ4~{K+¬1cãxj-â&*¨^8ÏAð Uõãz>‹áûÃÉQ:¤vÛ-Áí킞0Õ„»>龫·×Ýj}ÿ%t?–­š¿aE·ž-¯²Ù|ÿ0ÛÒÂé|öþ®ÛЊX<_^^\Åt öÕÅöš"Ô-†<«~þäÿ õ endstream endobj 46 0 obj <> stream xÚV pežÎLúÿI²‘Mœ]Ýi–*·Ö@Ö$à*’R ,÷™“d3Wn’Ìù÷ÜÉL&3™I “È Ä@@š¬Qøžj3Ø­I—ˆc¯Kô'Ú¼ NCGy[áðÚŽuh#Z_$[«©Ò”¡rXÜTÖÚâvµ¶”¹b-Ò´ˆwžð1€R²V¼ j:-£çø ¿`&!7Éo­VÄtùgqû¹Ø‰<.´ô±ïÛ ¯ w:N¹Ž4s6³FÄ]Т3©Å¥HZ¦R?_œP½"=n™–<†fÃ…€ð¾üà¨K˜Â1Âüg0Ÿ+¬¥ŸFI«eÉpˆLÆ^DvƒÙÑ»Ž}ÜÝdu››Ðe4ô¬}[ʪ ­Ó¾(I{)‡R‚¢Œ‹µç¡¾5ê¹Â¥ZµZ®+¨›#ü¾@²°Â Úüº†¼ $R]–¸ g¸`g¾iˆÁoŸÅÓ.~“Æ<ç²ÅL3½?~ÇÇ—<°AAuãÊQþ5\-Ä]t½ÙØpmãUN"q Å Yïi8J íôyôæïÖÄš9¿V\‰´Eê*YFÚÎͨírÈ|k†5ÑyȺ…ÆþýOtu>c]e¬2T«`tÀ‚³NÞù*w Ø%5bŒõõõVÛÀIÑàØÐØà?¬õözKKºEyu•«î(VÂ"c?ƒßÝ>Û1±‹¬ªp‚Žv½„AJIŽJš—–—Î=i"uMmf÷ŠZ]oˆ]àH^¹ŒîrP\d⼇ÔØdo°77yšš] ¥åβŽìýÙÛm5 e¨î©­’q‰n°)”H=zvÛƒÑÀrubÈb·˜M=¢c‡Æ^5A™Ut65ÚƒTrY]ݺËÓÖl‚8t=ç&Ñ5È+T€7ÂÇÑA|ÍÀß®ËeÐuBéš4eÒ&TŽJ­Õèõ8[ÜÕ¹¢¢\‘Ñ_2ÀœDû>poù}nù6püdnn1«t›µBÎ@N¾ArÏôŽOŠKR'ó½_=Îîíúí 雊¥™œiœ,5œ:Ê }l÷à<‘c‡'וÛßßoª5U6š÷¬ó@ÿÄá‰î¯,N«ÃädÉw¢ÜҺ͜ƒw(–šú‚{÷´Z‡¸£ã2–ÖU¦zág@D•ÆðŸÍö‘û—˜¹rOÄÛI"ÈÓ—¥Ü¯DÜÀß4žA¶ã Ûc;q'ô L5DøXX%$QåKþˆfÂYosMð0Žü‡ã°ÿ,ÆQd†˜™ ½Ÿ‹;€o µ¬†Õ"(¯(UÈ=å>Ÿ§©íý§‡—’˜dò›™dÚåYx:3ŽÆN4Ÿ1šX G&`Ö²:ŽP¹®F¶1={-R ¹EåLéW}‚Þ†úñƒ8L|(hNƒ“ÙžŒ†Ø>/$¿Ÿõµ0[ªË¼_4‚öv]&CD è)}–XFo¬;ÙÅ|Ì:Y.ëWðÇâ{¨»»ë†à}ïλõ·{·Ø¤Ö Ô+ Äj®œ5(åêw"(SZ2ø}ÐiwýBå Aµ÷öÞÁÃáÚ·m‰½~oJ0‚ÓæË=ö`=@/çõH|Ù-™l‚óñ zªé—’Tá=v6;eùꌕÌ"Z†Z} > ….;ÑÖÁQ.¹È•ÚÆü;7S‹d–S r±.ä‚Ü}õα»ìñFò¯]î,vâ|£×G“T;GðÏFM³EE°Q‘ßDœˆÏ]@K$’?>ø_^uö endstream endobj 48 0 obj <> stream xÚV PSW¾WàÞ#‚¶ÄlcÇæ¶ÝÚ©Õ**ŠZûPñµV­(j•*oD“€òBx$$ä¿ä ᙄ@$øÀõÕú®ºbY«mº«ÖÙ>mí¬íêœÐÃŽ{ãB§ÛYgvÎÌ™oîü÷ÜïÿÿïÿÎ¥©ÐPЦé'âãÞ^>÷­ «Æ/›25::ø,&ð2˜0,01$ðT(YF>Æÿ2/슢“Ÿ î³G÷?¤GÝ5µü ô(£D§ñè»â‚JåØŽ¶µäù|^w»Täñå{·IE§«À`¬$¼r§à˜ÒÝÿ´›WFuõbG¯¨÷O“øF¢† ˆ<ÓNÖã8©“ÁñÍÕX?"ÑQó{è³üõ¬BŸ´e«öp›jùZ¨E˜cäИӳ–ÎNMá*nmmryÛ s¥8•ˆÄYÑñ¸KãÒ×uœ”—;zËY_]o¬7 2Ô´¢=¸ZÕáÍ»Ž;úD÷Ïàëbc5˜„õWß—Žû)ž›ê{€¬¬UoÒIK@Y®ÒÇÊŸ×-Z9E 3P>k̇àzeÏä›Z5>}› eöÞ],£&bŠDr¯Ã´Õ¹ Ñ)"‹î ^\Wlßôík²»ÌÍpöµÉ;SÌ«`-¬2.MOÜ.ËØ‘3!ézÅ5d¨ZcMr×èçyw`’’þ¹'dg`¾¸°…m÷U&qä$›^\±BªÄåîl6Cn>Êá ,¸Íum&ÔÃ\†3: #ÌS9žöèœz!õ)nÚÿ9V_ yçƒLÅ\óóêH8‰˜Ah‚8˜öþÔ¿gzÕmZ!#ó|rÄs7U›ÁŒ,:‹^P­>G[º}câÖH‡,On{ê•—àψw‰{ýxëËÖ⤂4¹Ï7 ñÆ)y u¹[Éfg›÷sÕ‡Ýbë:%9rî臇Ï[í6›ÅÁD¦.]2¨È1âðI¶«Ùv^ê"òBëo¯Jã M…^›ºV²)~㪤•º ­V¯1bd—½þc©‹ý/2—Ãd«»€•o7æî³à¬³ÕØë뛜5;ŠÅ;7·gú2m‡ JQ‰J£^ˆw³  Ü•Ó™|6ålÒY]gÓ; õõΓ‡z.\ä"Ó YG•MèÆ@ÆÚìì¼4Yª,}«pE²` Šíi¨íþ=ÇœÚóØ‚ëÐÅ· VŸDÿ :¾B°•$¹1ññÅêØY•‘H’Š#ÙÝçåGŸ‰ÁBü½Áy8Š‹ñâgÕ¯L"®ú/H–àˆ;ðð y„ÎÄ‘dŒà•‚wT Þñ±Š«oÁ<þ‰ÿªð`â$Á'»[èöà†¾öÀ<±¢™íh¯Jæ’‚éiA‹Òå†-Ò–ûó™ìmæ}µ%ŸÍ?cpä7˜Æá84‡÷6æd¦¢Ë,n$:±~q3UÚâJá®H\pì$‡_e¡Îè„:ôáÇ'.Üë$’…Rá—@gÔ …¶ßùO'‚=¨eÏA“Ì—Õ*ónm•Õ–ÔÕ•!#[®Ö”¨Ë’$iï$%.6"%žëf Ìšzh‚Ö¦¦ú&—¯¥ÍåŒÍ³Å'k•Õ”5B9Ò³P¤Tã×»Õì:P¶džwÉß“ÔÛuv­ ñìÅ‹G0s?( y…¬»¶°˜ƒ|•ª¬¨LU¦*W=Òw22;Úó}JŸÚYèò¨FßåhæÑPSÕRFßc´d`¯`Æû½Ó»Z‘àHfPoM⯙óÝéoqZ¶">1õm@‹™\}ínn¤Ò˜×ˆÕ ­ IVRûFÄp[D81âá'FH§n‰¶X,Ö‡£ÿ |!¬… endstream endobj 50 0 obj <> stream xÚcd`aa`ddä ñö Ðvö Ž´ Øæþó—aYøs>놲Œ?ä˜~È3ÿg‘{èÅòŸ‡I–‘AH2üæ‘_@¤:Hø®+ÐD‘ƶ©‰Å%©E™ÅÙ¹‰%ÆzFÎù•E™é% Éš †––æ: F– ޹@¥É‰y ¾@Å©@@NŽBp~rfjI¥‚†MFII•¾~yy¹^bn±^~Qº¦ŽByfI†BPjqjQYjŠ‚[~^‰‚_bnªØ#z`Ò9?· èßü”Ô¢<  ™˜®]ÆØÎÀÌÈÈ¢yýGßÏsßËw2>ù)ÍüÓÿ{¹èì…Ý‹•vWËÿ¹ÈV]Ú]R²°{¶<ßåküšÏø½á(óÃï¢SZûº'tsÌž9c®|÷¼ÆþšI«Š§EÍÿÎy@brß¼)“û¦Nì›Ú=…czë¼\¹ß*š3¿kôÎé\’×-YÙ][ÓWËQÏ>ó·æoÉçM;ºÛº%«kë*å»+¦¶Ïj9—³¸aOùoÎ0‰æŽŠ¦æŽÆÖŽÆî&ŽÊ™u³å&w÷v/™ûý¶DÍoSÖò9M3fÌ™2_®{jûê®éík;6v¬ãà+^üÓ~Ûo¹éìr\ÌÓTÿópNâáêááÞɵ“{ç\ æýþP=»Ãc endstream endobj 52 0 obj <> stream xÚ¥VyTg¶ï¢¡ê‹¨‰´Á«LÞ3Ï]Qɪ‰ûn‰¨,‚@Ë¾Ó MÝ·zºiö¥Áš-@ˆ"¢€É'¢“x2‰1“1&Çy“`ÐÛy圼jµ3gòþ˜äÍ©Óß¹§ºîwß½¿û»%ñô”PõÈ‹Á¯lܸ`ïÆ—‚—ùû/u½ów.“8—{8WH3=…Dáâãtêÿü§×‰„ê™áZsv­‘ˆ«ä?Äå‘É,Šš"{üÉÅ«×nÙ™®,-«ié8sþ÷7]¶té²§ËÝÆŠånÃÿ±j¥ÛXí6܆ÛkõR·±Âm¸ÝW»½V»½V»½Ü^Ë܆;z€{Ÿ÷>nî}ž^½tñŠuŠ„£i©QÉsw("£’群ˆœ»!35*12*ògŠò^æ1&yW2.¹(¹&ù³ôu“Ü‘ü(&ÍG"“̤J¨RJKé( xJO(#e¢Ê¨rª‚2Sª’²RUT5UCÕRu’Ç<$”ÄC²Q2B¥yøx¥¬´Ès¶g—Ìë:}ñe>'懎L™5Åê½ÂûìÔUS{¦…L÷ž>>ýG'¯Öòýλf!%ýÂy]~ˆ‚ÓÆÁr÷¸0çsF¿0Ûù!F¾ÊHuqE.› ©éAÉ»4»<ؽœÐOá ÄéRdœgåö¾!Û) ׆_zS2šEkŸß±-pÏË{ƒw©ÕÚbP‘tçRÆŽÑ^Q´æ ÿJ$¤”¦@ á9zdpäÔØÀc×ÏÃ$A_aæ¹yK&hîö”ÎÞ–öÎ^EK4{?²êuçz ‹íòDß'ða\„ÓŸÀY²7ð·Î+ò¶¶Áê@F_ßũؑúÜú¼”’3$ £WU‚Y|*ø tt4!²šãõû!šìT/y’}"­¡vÂ3]Æ–cÐéí1&¢¦&%F ž87á”à£gpß­¸°ÄBdï]lûtþJ¾¼»ýŸ¤‘ Kìéiµww¥‹AK§u_æûqÔö~œ‡á[8ã)”Ë&{X'?4y÷–ß!ç"æ: Ä2z£ºµÜÇÉ'.ÎgeΫM_¾ƒñð‘]ö`[ ñDXý÷Çä8Š;˜VhÑÙ”D69’Ô´!$+$ühlF´.JÌér¼&G;>#~uL×"~å|3­1 öAHzxDÒá´ƒpÈUKé¾Ñ©ªÞ( 6÷;oõû´£/ÊúŽö¢gÈjq¯ !z0²z˜§õ+˜§ÙZ´9s{nhòöm™åÙ5d µ£›“…÷$¶ÅD*6 ºÂ~Ý—Æ/Vü±ì"{Ö<¡Ÿ€ ‚f×QñË~?ç­É~Z þôxŠªûyõú:·âcRçìvÉŸ/Ü‘»+béæHÁXt|áøÆñM7ßÀ-¸Óó‡«gßm¹W †>¸JÈg…˜»Óäºr¨Ÿf¤>|¿·k¨î4œƒ·Rû#~·µb<~*¨ Y±…±°vvD%ñù#ê³Úf°•6»xý­ŸŸX¨¦n<×OáoqžÂYÒžŸŠäBŽMÈL–£Ï0àoAò©Èæ³![Lú"á¦Ïátæ Œiû"í Qá¡qÑ©¯é"ÜÝSìÀÈ–¸0ÞáÓ}{#z¢ÿä¹^ÙŸp¡s±¼­Ü^Ö&Rx$É‹eoaO’0Ó©´÷¸1¸l¯‡ðô«oÄ žuœe/Día²‹’ÓÓ4ö#™¯7Œ ±²ÛJµò°=£ÍÑjëà %¿&³šˆE^/_Èl ÝÆÊnØ×6ÌÁÊ?.w7u;†Ûq…Ýgb×Ý^‰²ÉçËrc+_)öL}i6'|Çäd•f²JPò…@âñó>N«F†ƒK+{÷•‹Lë«»Tï’¯…UØ•B¬|‚–M^pìäàˆ*)==9=^—d/] ‚{"ËÔV­ì»´Ì9ôfZЖ-9{¹éÎD¾Ýù;õí¤´ý_èq0Îg)¦U*}5'*˜ o0uVÞÂÒíЮ³ç$ƒôûI/­Âg½ÄsÄ a%Å;œÚ}ðp.›”D¿{-b@ ¦ºÒ i„™[’ãŽ&‡É s„ ¯^ÚpÒt¾ÃNd™Ç[{M=@0ž~ .i›ÖÙI³Â¯O#å`P–È,~V1]P`xÍHð I´ê Ml%TêDe:ÎÜÝvw‘\Ï4TÕ¶ZO_­DøŠX™ÆrS‹]]¡Íá„[Ln¡6^¤ @¥SA¾˜•Q¬$5ùЮâ. ¶ãšªiÌÿJŠO`šß¡«ŒåV”¼rKXÈA`nD\à£a#æ!µYö#¸êp|Êõ”¹Ð¤µ¿8I—t08- ^…à–ä¡Ì^Ý  vO8a²÷4Ù»j;|e[°–ƒýöbðýv pøà·ŸIô^B¼¯áªÆÉ-ay= 1Úøü"­¦¸HG´tdÚr€–ª9(æK „¬e”ú¢F¶tÇ,ÕÇÞ±ˆ“eäÊMëžSqqt¡¦´Pi*µr´ìë±Ï5 8 £~vgîØ Ï—çLªŠ ¬†V–j ŸBiÆGÜŸ¥å×L•+o… Áõù¦Oî“ÀÍ5 »ýKè¦u(˜Œ ¾‚‹ãZ[יγg¬õÖºÊzSEY¹ÑÌ §}îÂ@¾X*’‘m¨ý$´ ;Ó :ƒšhPiJ4+v¬ Z^¬Ö•êpØ·¾ÑÐøÖÜ?†g >íÎGû`L—¨+"—Ù{§±‚ëܤ±®4‹ cÀ_·$eMá±²š"PC‘¾Æl®ƒzÒ–Ò¬HLK;<0Ì¢7Tà|Ó÷ú“úA8 F]™x%¨­0Õ²“t­U›Å Œ,3/£4ƒUŠWÿêSº@6ÿ6ïj>êö€sæ7ÒžŸ:¯òÚLNø’9«Mb âq«£VÄéÛ9¯Yââªãf]",©–4Kê,“ʤ¬Ö=Ý µïÔt´¿ß~Ñõó-«®¨6VóÂß}s³î!Í¿4ïWÕc £]nQîþ%Ñÿµq©ºD]Z(R·Ô\">)£¾qùøð‡E5ºüD©ûzêbÕ¾É_Æ*’ò¤j·ã>a;óo$X¤‘˜K‹KÅšë]¹œ#ìÃ9LÃÏ™ãJ]N®rˆ‚aA"E³3T.LÍ÷ÛÂØÜºyìÀàáóyo‹7 §£?cÙoG„¾µ¶q8úêå# œá××k³uVvÀe «X£Ï%9“¤0ªÝ“•’-ÎÄÈšTGR' ”ôý£ý=þ«¥U$=ÛP÷S¾d Êd¬Ô  +Í÷ úoÒÓ5‚úq¾Ã9»Ë§×ùM¢×dÜ%?ÔÊÈþÚlÓÆqwëÅW¡¶†Ð݉ý§á#ø¤uð÷moT Ã0A¯ H Ù½šKF/Æé)ðrͺd¿y°"Z“ûJÄö ÕŒ©ãRï0;ÂÌÍh H§!nqqP=ÈHQp.•ç( ò (;Ù2º»¾Íþa&Íié—aw^xô«G7Á&"°Kñqö\nwŒÊË,PAÌj}[Dg‚>·H™öZJù២ן,âu× ­%¶WyÈžë|ã â}¥£ý&eWzÅ©„Ä (;y¾ì“¿±­´E_\èÊwŽR«•7Òt©®Œ:ÑæE[”c¥¾–Ãëîd›&3Û"æî¢†$"»Ò¨Ð‡€âÞl~Á5›×Ç}%„9œŸ§šnI›]¬°1ÕP¥«ÐT«jC«§æ =yrž¾D/N Pæ$©sÒBvo/&%´ *CmU­ìÄ‘ÖÃÆkòÒ!‰ì9§8ÅþN|æ¸xgŸÇÇŵ¼¦¬±ÊR[eã]=³RÁÔA[‰!Û¥¼¹i‡ R·(6Ùw)árÜ¥”3¾Z£«TÄjãتãô–ÌMÇU÷„ì³øñ4µ| ŒÂ…‚†­ÿßû‚«Çÿ)ÌÊÒR¥–ÏÒJÈrüïÿÛñëo†òÜÛŒ/Ú©÷ĦýNŠ)˜"WD'Æ$ÆÄðM:’¢Žq¡Ìqä1.Ñ,-#z¬6›µ®¹ÝÖfk¯oñ5•ÊÄ;„5t~æ½>SÞï3ͯR©,f l€‰Gr“ †<ÿ}ì(‹‹›å[è—_4~ÎA‡Éq²òX™?ä]©×pÓUVçn3¾f´[i!¬Œa§H+×L}¨|ê~ª÷·S†½ÙUqÁ?Îü_iaí¯ endstream endobj 54 0 obj <> stream xÚÕzxUº¶ÆŽg&…,Jv™¡l–J*)@ ¤‡t§9=îU¶lÙ’eË–¬.uY²-7Ù²eËݱã8§@€’R !› 5,ÈRŽÂäîþgl+À²ìæ>Ïÿß{ÿG~ôŒ¥™ï|õýÞïaœ#8†Ý»qÕŠ¯D?¹~IÔªiSç>Ë~63Å ® n>8‚Y˼÷ûˆ†D<Äá„¿qû>qzûö^ôΙŒÞf|Éy.ŒƒqFs~Ïy†3›3Ÿ³œÅÙÆ‰ç8bŽœ£çØ9ŽÓÊÙË9Â9É9ÃyŸsóÎwœÿÄplÆÇÁ&c3°°ÅØjl3¶KÁ²±L™17Vƒ5a]Øì86€Ç®bŸaß`·ÂÂÂ"Â&„=‘ ˆ%?'ÍNÊMIOOdæ¤'$æüâƒì”¤äÁObSR¦M:mvèbNèbîðÅô©¡‹i¡‹é¡‹gC³B¡Ç§‡Ÿz|Fèñ¡ÇgÌ]Ì ]„Î œ83$gfHÕY¡›g…nžuç«ÐS³BjÌ=>;´úìÐê³C«Ï œ8;$pvHàìÀ9!sBvÍ Iž’<'$yNHòœä9!ÉsB’ç„$Ï Iž’<7$ynHòÜä¹!ÉsC’çΞúÌŒ…™anNBöë2ã²3ŽÊÄdüÇÆ€3)ì©ðiÏsVsÖ¢ôÜÁ‰áÄq8IœNJÕLÎâ$öùççCÎ5šƒé8#9£PZßÃËǹ—Éárîçð8pD©>…3óçEÎÎ"ÎÎ2Î+œ•¬dL0#0J_ fÅl˜s`N¬s¡t.Åʰr̃U`•XVÒÛ‹Õbu˜«Ç0?ÖˆÒ=€5c-X+Ö†µcX'Jÿ=X7ÖƒíÅz±}X¶•ÃAìv˜ÅÖ]RIÅù*ìž°˜°Ì°ºpNøÖðOGX"Ȉãx&~ƒˆ%¾'ï'g×FF<2êÄè‡GwŽY;¦ûûØÌqظ“÷ÖÞ7ò¾7#ã¹sîŸÅãò.>x0Ÿ?šß3~éøw'løÝÜß}ýûÞ‡â¨q”›ºB«è¯á=rîÑ­=þØ{Ø2Ÿ¨˜øÑ—þñÔãóï™ýÄŒ'nNNþüÉô§ˆ§´OZñÌ‚g¾ž"û÷ðG¨>XâÅÊa€'¾Uæ%ÆþS³2Rñ2‰Wùõ îxæ–’W¨•Järf3n+³0ÏfÕIæ8‘¹×ª·k퀴[lV¸…^EÙá˜8À)>×WÃ{á½6[©”ÜN›Öª¥¸gŒÀ`4rxµXyÈæ¶º-¥¤]gÓP(€1”V¿R|ëi”Ùïr;? ~Å@‡ó@y»†ˆMÔ'QÑ8W(€ngƒ%Îðã@j,d\н‹¾G”èÅÈó2©\¹+c“*:¤·é|ðµoÿ9üZ°–çyëäÁS€üdÿìé"B3eõËk—oÙ°u}ô±ˆ¯Q©t hMZ #ƒ¸¾!Â5ýÖ…V+7ÊÑjx¡±ÝC2³ñþþ£¯?ræÍk§m%û‡sLž:ïÂòÌv¿×ë÷åû2(ä£6¤‹Äkl}dÏ7 nÀÅ×—}Áýüûày^ çpÝpìK±,&ÕX™óâÊ\añ*7ʃ“rã(aM(+¹ÿ´Î6- UĂ̧Ÿ¡–µ-©ÇȼÁïi¥/¿>ËBjð„B¡Á`DôÇpÄ×Âp|:óÚ\‹ÛVjuÛHî¥×O‚wÉO'œ;oRì´Œê\¿ÏWÕØšUžNý ø\ (B9r–ÛןçÁê§ñ¸Ã.JŠsó0ŒàöÕ¡@Œ÷ã 7*™&°uÑ7¾<Œ"€ÕdvÒ­w((H\$J\Âàó˜ ™°"‰BòƤA™âð .82âöHbØC Á‡¼º`7aáÕðËpÏf´m€l¨®©÷åÕfg‰óSÎOýŽùâ&¼çëWàHæ^Z‰ï0Ä奥‘0†hR6i›À;àMß‘c6›Ý¨d6­€oËß] v¸’8Ö¬±hMèC-ÐëŒZ’9G¨Ì*åÎJ§«©uoÕ>@Zñ½Ææ¤ò¤òDs,ˆ 5ÏÏ-Pè Àr°¢?ÿÔppÅÁGka*Šï5˜ñçU×¹AÈ…ðŒ8¸aûáÜ٦ƎŠ= ´+ª3IQ–"=§BÜ@ך “´ï®éx…yáIf%3…̨2æYÈÛP«ôi}à=p¼·ë8Éý®¡«dè#aØKp3šZ6Æç­"M ‡ç$.n~G-ómÍB€^äR 3†!( >Ã)þR{¸€Ëèú an…±0„1MÿEŒ9ó³#8õ×0Ò9#gîÀHØU¿3n…£r¤üÁéþð½·æóÝD Á £o7K6ivS˜ vm* Ë„t&ƒÅDµØ“éÉ8³Že@’Yä(¶”Ò„»Ì%v:ø&1Ðïì¥L¦€èíW½Bß^F0W‚ÅiûòÍháúÌUÖ•ž­‡§‘¾ Á=ÔË.ßJ´6ë’h 1ª‘Å·+‰¸4m¥ S1ª8™â÷eúC~6 i™r ®&n8à¨7n>qfrYžY ò4Lfnð`+Q_a÷Rp4~ñ|"3ŠIºøœŒ¤Ýë”›A( fïQ^ìÛðoo©x“ÁÉÞY?F]ó¿øúûp/úZ|íoQ³Äpò²áRQzÅ0µÎñFö^€±§Ïû¸G $y -Þ½€<×µj J08ó|Ãÿ‘à,]†²ë(Ûüf‰mŒÛzA[›µ—|O´…à u1©éêîz ¸M¥ÀMBм*%?ŸqtÎÊgS^Væ5øª«êë¤5Ù”a(¬0y÷8Á=oß°\Gêðí1iaÿòû=7,¬©ûx\é >éÃÚ.‡Ã¿Çñ²ÅY9Õ¹>_uµŸvŧûÖ#¿›ÆD0#™‘Ÿ2x/=Þîl8k±[œ¨~­„Á¦3kAÐÄÊe¢ÄØÜ]€|$×iða#$¿qN¼T4¤ ­¨Vú`F œïÅš®@å@8Ä`!îÅ]6›ë«M_1c™{f0C0ØÌX8¾Nu7¾o²š-ÀJÚ56-…–JÑ(²cvdlëÁÖ=¹Gò»} —4ÕðÞï½qõÏ /ÆK&¦®?ñ§:¨÷¹%‘Gt8p„ûí÷pÏHH$ŠdT‰•Y Y$÷ûÊ]1`ùœ%zýcø@û—0‚Á£–àÜ¿lÉòï¥AUI¹½¼1¿IÞj@F]g•]#]h•·ˆë ƒXž•Õì¯lV`1ZZ£Ñ”¤Ž((“{ªåå-•RdY¹z½^§¤×I¥ÌŠ48ÅV1xÌߨ|,FÄÓ,"…L3‚‘c‡ýÔø1p±Èµu£ù VRËÁ”@ñi²Þæ•GK/\ð­[±¥há|* ˆ¨§³)œùƒÄ† p?ï .à *ˆŸv'͈¸lC4ªîÄ@!̲´ÐÁÑĘûkظ4ŸÿcŽ—!ÙxVJ°ï›ز­"Zt;èÛMDb¶.‹ÊÀ´@.ȱî¡o ¶§¡®¦¤ ¬À-;7‘oW:‹€œ”Jt…HõBrÍ"Ÿ¬B^UT•r(õPÒA­CçÐØI1Ðûꇟ2À,•n¹œ¢ìü‚ÂøÄÝI±)d0_ø »9HŸñ^ b§a<ûÞ:dk  ßÎÚ›iŒ¡4(D:eˆ¬4\CœÝóé—'KWo¦%‘,Ô ©Ü»û^˜eÚCCZŒ­ù¢Þh÷@*ðMÚÕ±…Ñ(®Šs«ë×€•`UœdµñþPFן®Åš>€-¨äŠ‚Q<æ~Ù‹&‚|äCf|Þwã8 ŽšŽ²oÅüŽqðŒh4@ öƒ*x?ûmû¤')ð\1ÃeÆi§xl;£~ßê!a“vêÄÁ—Ѹð=²\©SkÔ«—Ï_½h³V¯Ö5â€EK^uá©­'6œˆBtP:¸Íj±¡é$ǧ(KíNîJêø:‹Úf´!Ï{£¯¼|ÿþžÃ{Y¬K–5hLæ‰ßÆò4z­Z« øq±1ñ»’ôz­nmš• ùeòýñÝ;zw[õèÅ®ÄÎA®‚*µK¸'½3½CgÕZ 6T7À^]]‚Z{C[}‡Íá,1— µíÚ¡…†¦!ÖºZvBÁà:dÝð$$÷帊ZãÚ:’¾Uï@<‘4@“‘-—ïܹ}[âfVöM$ÌN™ÐHT¨ð¼vôõ£û­V‡"3¡w§U畯<´îØúãH§ÁÉhо?ÄòtF»¬=¦ ‘ƒ*q¥¤\Æ7,z :N¯G5K–“ªVÊ€‚ÔÚtvÊm®¬/-íÙ××Õ×üËÈ™®5û2ý¢º_®OkWzŠÁOÖ va¸3Œ–`-Í<º$2c=m4rŽÇUeó”µVt9ZHhÀ«+º$Ë%¨ÝĤ`ÈDõCµ–ˆwñCúˆ@!F•TXZT¦«ÑVl‚£¿h8) ÎâkÝz{C®Zº”Y³‚Y³ŒYW[÷yåsnïÝ[òÁÍ­´ä#ð] ëk™¥”ƒ?¯<±Ð—çØ$ˆoUšÊo¨;ÑÞçW]Y—Pg‰CteoÈ3"g>åÁ—q?ð|òcÂæµ`-9eÁ+“©|oÊä<\"µúiøÚh#š<öZ FâÜÞ3à|šýqû3ž_ýì R fŒàyKŸn=‚‚C]åvîý÷ÄI8Hœ:ëqzÖ¿ON±vÓÁ^¢©ÒZCA? ÞÖ6Ow¥ZRïxëˆOÏ2óÅpSë-∭>®†ÃC‹µt‰4`–1»G˜”‘”®Ø È"\ÈH"|¸ó¨ù|O[{à ¹å×ø8§ªëJ±$Û’åKÐhˆ&·ñ)[l%ö4Û›)#ŠH€`–ÿç(ž./׈|Ãü W)€‹6抪ò’rÄf”Àç‘Õæ²½|÷zA2}»œJd«¨j£†¢™¨²Þ À–â^…Û}áÿÞUÄ^»¡ MšŠÕšù»víܱظ©q.’ZZièÿ˜hݯГk ^ˆM¥HI¡Q Ë ã )€œÍxsµ¥Ž ãqpÚØµ£-ÎåØrǵa»ì+%ø±¾ˆ nødÅgÜo‚¼ÅsX&§ÙWÂ?Ùpò08GÂûêõ‰Ô:°Y¶=Ù`ÐôFÔcä å˜ J£JM3[ÐŒ¤)¥ª¾ÙZQsó³Ÿòâ…U¨Vì\ºP*ÖŠ¹€Ü€+‹JÚ@˜TNƒ“Ýû0Yy¯Pa$¹ŸÿI}îe0‹œ4{ñSÔ40±M|SçµùQò*µ:%­%À¦úM{’ï~WŽv§¾FdQû&âäPº ¦å£  ›˜ðÃ?q[{nÍã ï¢Ö¸é,”q[YjOù3pHµèêÑ$JËÊ®ó¼É Ÿ‚¦ÝM|Ô¬¹Þ7¨¹iÞÐ"8C¸Á‚œX±Iµ õÖ,4úntœF‰}MA'ß&.ÉsJöLâ¿ÎL~yò8ó”Ma¡"2Ù|VwÉ?'…Ñ{I­«Ö^kº}”T&%P‘ éƒQ/j-á«þ„»RŸ™MHõJ“yûF|Gé‘Z~–rðóì ÕÜÕ«ÜÞ»N=ñ`êõû14NgØÁ­†W™j"6UCåâÿpã]ÔVû`iôÕ>¬Jk“6žfÔÌU¨&º[-{©Züg7"ƒ"žÚ%©¿5§Þ(‰<öE0ý n_0âÖFÞ“S‹˜‘I«óƒÅ$3ŽaÖÁ4¸ 1ãUp1QàRf<\Ål¥¸} EA$‘«ÆðÑÛ _†ÏµÜKn³ )ñ)8»jϼ¦õÎå` `îOf–2Sc u2ƒ 0/Ãg !×X<†ròWEÍ:·¯ç.É»+‡,ëòY:—e顃õ°Y‡5UX»(¨Ãk å:IÞÞK å5þËçî2¹ÿ½|SÒ|ë©vì‹ðൠÃÛrtMÇ èéMèù—™õÌø3n¡KqÈwAüÏnQ*))°íÖJD§Í,Kš·[wFú¸nT}qö\ï¾wšÞð~ð.áeÂLrc^ ËÌŽÚ ›Ñ¥¤”@#×id¢üœ¢ìaU†:SS$<‹°ùòK“ƒˆŠ­ß|¶¥½¥í¸•N¼®ÁÆzj|Dl¼6y0žJ@¦nxOF8Û„|µÄ¿OH°¢ˆúÐc´£°´Ô™Û¨6ü$xW];Ç™bI²°T'oˆJ¡ÕêÂß3£ÄÁÓp„ yì3˜÷>ÌûŒk…6LýD{«.–YúlS–>J½®`{ê†ø¬%`)X^·üÕØÃñoªë µ Î@Æ»St)Ô&œ;{pÞÊîÂÏôGãI)Ö^º›¨3£ÛÌpL9äðEp:ë̆=Û[×UD9²,ÙÆ, YEtuX[¨þ3ÏÔG<ƒs7à ·»xÁEÄYð¡´oECœ-ì[Tk“vlYP°ñÔà"ÞíEC2#úà 4xÝyòÀþÞÞ îc€ü_Ä~G_þŽ1à¶çŸULj°‚ õ3î’(r¯ ‚Ç—C(ÓŒw7ècéÛuÐʈ )£ÃóÍfÐH{ˆžvKåÅöÜpžà•x(€O¡\=ÿÊ+Ò©‹ô­X/™ Ë–íÞUãÙÈø—ŠhÈ0kíFÒŒWš²jpœŒºƒãž}>åòâµÉëv-Z=KK*ñÇÀ¤·¤0Œt.£[^lPj(-QÂL€ÜypâQQp:œ·Â(f\Èl¡——³wl× ^-d7‰´Æ¡}ð4¢¨*¨ Z-eõ×?¸ü¸ .o?°¤gµg>X@þÿ¶É*ë >] Í’È@CÖû°å2÷»ãðÏA€ µWÞ8üúÁÌg«º=•¥‡H;áÐYThXåk3TJzMáRÙΘ¥« ™DZs4eI@* ç#N‚£´$•Ñ_}ïƒ#§Aœy€ž¦Fg/"û>ûåeoeðÐÊ c[k"¿; 7^Øp‰û]Sp!ORK46èbhæ0›«ÝH‰¡‰8q$iÕ›3[·¹Hnp_ù¥*ð8°ÅŸìIw§™Ò9ƒÙÍû+ÎýîÔþ˜Õ«ÖÄ­§—à"‹®H¸l¼Ÿ•–ŠZ yçœÈY·`Rq=´kkòÇ×`ßžoü§««½™DL–}/ OÕ¶ªzêþè×Ú™ ¨’pFÄÐV ó°Î”·ÕÁi§—™áp+±‚hnÒÇÑ‚á0ñÌlª€Y0ÒÒg94øº,m(¸B¼3x:2,s’\W a)=áš¿f×.±8O-¤nôÒG ÊJ<ŽGc{cGiE¹ÇUY!÷UÈ]ê25“©ÚÂE(@o‘že饿&@í}+¿\VZИԘìOr(Kd ˆ”©ÄÔ èhHÚ—Ù‘Ù™Ù„¯³©C{IöÖºŠÒÃ=o; Èb•>bb>^ª³kA1(RÈÔ*•Š¿;aKòÎD…R¡”«HÔP‹r „ßÛd>HÕ0‰—hòëâY«B2ˆøæ¸æøæüò¼²ÊÉW;P\v[©­:4€É5p‰7ž¿¸ì}î7°*y}U»Á»äMfª}•Rt™F¯Ñ¨Ù1µä5!6¡ÒkèÁc\=‰&D†KŒoJÉmqyO½æ}¯^Ì_¼fEú&z®VëU´Iå@“­8÷ó“àbAÉ ¤’˜5?g5µ,ô¼­sÛë¤h4Õ«U4H¯L­w¤RWWî†ðÎæ– •rk‘µÈ4¼ƒ*÷[õ#ôJ aº©‹6•8vÇžÃüæîæ=ÍÝ5õÕ~¯dªˆ¸l}ôà¹Df–Úáá|g„’Ö¥‰´Q©TiÕñ[øÑ+¶.Û´’„UD[…ë$Å:ñŽÝÍéð‘ÈA]¸_þ(G^ç‰Lyº^ÒÀ’QêuT—?ê©À—W—e"SdÙÙ þCÚ÷ÚõúÓ¾|_2eÈÏ9@\.nÐýÒ§¿áÐÿ%ù>ìùBŸ’U7rõ¸}p4«t5ÑÒ„XX¬]¨X¤Ü”?u(2›¢¤ÚŒüQGÖT ³‹Eù;;½Ô› þt鑪÷ìWÀq˜.S¥ßAÞÀýÎ"ͼFpób¥šuÿ4(¬î_š¼&qði¤Ç|ƒÛ×ÌêPC46!êLj! N®L’Æ )˽D\¢çMÚ_u¦x“ËSÆwMÝ3µk*š-,*›ÜŸºµÌZ8Çïú¸ó“®ìåÍcbþÂçöÅ$VJ*«‹pH—½>k?Jû‰ —ieÛl7¾•ál…Øn¶bZÞ“î„w¨íý›ªBk7 œ&'¢Á†q Íò;ö@»Æí¿•¤„1÷0qð¢£Â1T%ÿMç%wƒ!¥O~gi#Uw‚s' ëk´)4ó'0ìøÍh³­vc>ã >áÃq¨¸ÞÄK š¦Æ,öXj5xªDdˆ¬(΋jc_ïãá=_þGð9ˆ»Œ¥×ƒâ¸äÛ¬f´<ÝK±MQ#n¹mIß‘Á=¢2ÔLËÈ£ï~ãf;Ã[@ÝÙÿ8êe®âÕ£Gm"õ4·³¹VÁÌD4ÂÜazµÖW]Ûbkd3Þ`Í—ÐL?²5’T=ÉæèYxAmuÔðnØ£hâªJ!bSmûiØOÔX+¨f¼ô(J×ÛDf‘I4ÈkfF I2»¼Á[¬:8Ÿ—ï$ú]Ú9³qYÃòÆe­óø•C”  ?[S Þ,Xð ÈŽBwµ¥‚­r¯¬*7»  gÛ~Autžox> ?ã×¾ê½~EEúˆ™ùxc•8›JC±^)Z“µV´Vº“¯Sê”z%êvª¹OQŸu*óTö€Î©cÙ×ܼTÍBÚݸ“Ð!ÁÚ?€ª·¡êJ8lf@7±§Á°Ž62;¥-;*Áxæ¾)ˆáÌ=ÿñŒ¤÷‚Æšú&ò§ÒBÙ³ee@díú©þˆúŒF ¢ûpì_oÂqpÄTT$\:ìÈ—¦áq>óÚm%ÏE\íƒãnR{ÀTGɈ­›â©—Áæ ²Ó:±ÂàA“‘§™»í‘g¹kÛÞ>çÞͨ¾>ÈŒ™Ëžµ ñµÁ#áÁzª`+ÉMU"_zËîÖÝm1m ûC–CéRcø;×ï\0‹ ó"/!)®BìÉ_W[YSY[Y[åu¹% ¤B⑸äUR Ò\¥ÌˆnßéU›´NÔ" ä4碡t²›)»ÅÚÒÍï=Ú7ð ³HBxu%…(Äi É‘Z©,Ö£åvÇvät¬F+°‚Êw…‰¼S©wHñ¿B†8 kj–þKî‹­Œho4î ™ãD¶F–I¡a‘ŸDhHdvž­•†§ˆöÇñŸ±øb Üö‹Õˈ¶&C,½„@“Ô%mˆ9¦Ü‚ƒÖ}5$óàЭ&c†ßØ:Â?°÷Y“5[7©úÛ©ÓD·ßrhpÝð‡__s7±áþa«ýCVLjt›(ñ­¢_7ì;w½Fd«‹„óž«*óÑð-¢Ãk?~W· ëð ×ÿ =‚7QQ¿®©XâÈü§Þÿ¿¬{D3Ôg{1e0ùrøo‚Y½M†&˜D¬D…¢QHì}¦½u5m`yqÊþå3á|–8ȶ* ‚" ‚ŸàÇßNZA+ Íêµi¹½ôжÄÏûoÒå+¿•• ÄYëgÝh¨º4³{± ±yx>ÜM_\âÄ)´„ŠÐn‹IÜ¡.4"†CnZ F°$¨¹A¿›fŽ ‘:Vdjê±2Û›4l$ÚÝ¥oßiÌ¿TéÿBCM«¸.ߣoÓ}‘ðòeî%xfóÀsâéÓR‹ Å ÕøkB›è¸¡D_ŠþÕhuhÆØuxÓ¾<öWzu,ú}9pÔ/ÁqÌCtHReJµz­Vc$ h2‘ŠÐdbPªéá˜Î'€š=#mx©ÉZk+©ßwØßÈë_’/4Jinß lÚ Èܵ‘Þª³Ò.à°±ç@—zAcÒÐ ZÊ›KôË•¾ÂaWi¼ˆéw™ÝâÀùð†ÈοHÄP’Ãl¯„È„蔃„Ôw·ƒ!Î3÷ÀGa8q ±b&ÅŒ§ÓfK1¨õ ?ÞÈë!ÀÙ²K—Ú*– °tIëíqÖ( éç-Ù!.ÊÑä€y`Ë@ñUã.4Áö‚¾;sf¢A[3y…"‰$?7fÓ¶—–önöyÙÀC·§ÆUÚÔÝÞíïq:Mö2@¾…jgŠâ2õ[™¿†‹8b&ó¸ú‰ù?¤ áÄ Þð±ø¢©¦gßrH÷â5nm2=Vâ .ðÀLsy=ÎìrÔ¨p÷KcF:ÆŒ2ýõ¨Ã£©6Š$#¿ÿÿ`'€y endstream endobj 56 0 obj <> stream xÚ¥Vypå_Y޲ Æ¡ ¹-»N !!—„@È“Ð&i’ær8¶X²eÙ’|È:,i¥·«û°dY²ä[¶c'&‡cn.§áÈph¸ ¥S¦™OκÓ~v…íÐéûv¤Ý÷ö÷Þû½ßûDj*!Ò·íÚ±qUöÜ윜u‹²ÆÿYVÂÛoôŒ&%E$-HÞ›’¤„É{R©«ëSÿ‘–r/A¦ÿ[âÆ´qûÕãölnß~'‘*Uµ•õð‚¬¬‡²åeEÑBeæì¼9™‹–.]2/󡬬¥™«J¥Š¢¼\YfN®²PZš«Ä?žËÜ*Ï+’*5™³—*•e.\¨R©ä–V,+,Ÿ3/SU¤,ÌÜ"­*ª¤ù™kå2eæS¹¥ÒÌ›ØܼeËKË*•REfŽ<_ªa´“,'²‰5Âí‚ü”¢I1¸ ‰û‰YÄÄlb±„x„XC¬%ž$ÖˆDñ±‰¸+…©Ä ¢˜¬M™/œ*|'õ½I¹¢¹¢+“×LþŒTO!¦\ºþ¶iS’L:ê‚ë‚«×…hÛ°¸³¢U&«¨ÉZ+:;[[;)ü”ÿ} Zy]€ÖÅ„h/+~Mq8¿X¥—EË{¨4:|^;Dz,,k«£aUá¦âb¬À N‹Óÿþ»h •>ڜߒì >L"áè¤û' `têœc/¡ DëÆ.@ê  §)ØŒñ¬d ›º³ :¯ÁOÙƒF7™>º§21:?!xésá(;ºAl·º 6›N·f¹ÄÜý6/’¯à+ùr¾–_Цò4ŸþÞüâƒðç`'}z°R&0[­FƒL¹zíïÖnÝX½ÈEÓ_FY4œiA‹ÿ‚¦œ¿ôåÉOüë¹åÈgÏ<·ìÏè¾®\&·‰2ƒÕj2.›Í  ÈÇ uÓ`¡ó¤+&>Œæ}jòD‡¬è>þ7°ŸNOÖñ¹±È'ɲšùisL0| ]¼&L “÷‹¯Š¢¸a~=TÓˆZÈѼä dx#áP 8 "š½}!Ô’ÊæúH{gìÐàîø~ª6jJg›ª}'¹V¤¾¥Æ¯‰VŽÑš«³v@†롺yÐîíƒ×Ôå²Jéžc/P§`à\ó¡î qt;‹7%úúfçîþTðþÈÑ!ê$ŽÖ5)ËÊÊËÔÁêÖxW¼‹Z1–&tçëðDALÎã%ý»æKù™½8¬é,çlêør «O\Jh¨j¨²èå{x²fŸ¾\[ Uä³½…C_ö£™Þïº Œ¹V³±ø©X—|qÚ\ÁøyÜž…¸d¾“ö TÚkHvA˜œŽaEêÂÊRe©*Xïèhï øÝ_"V¯xfËV0A-h¼]n\þ(Ù¤‹”)dUò*‡¨7à‹á¶o®%S$Î(ñÂ9“{p×Ì-·°{ñóDÚΞ?d°Ù’‹7 £³Tß$5ù,0Aktôõ³_ÑÀ-f+á c9f¶Îš2›Ÿ9ö¦eb‹g(£f/VÝ×pz£W[/óA ¬Ã;ÑÂè­õÖzБ›ò^¦º £)ÖßvÌêÇ\W=¡Ü¹HµÖßGCØw49˜>xucçb¢¹»;Þ:4"¼ DþŸHLMbí ±ãxbwŽ1ŒÎÚ5[Žž z -îk>8ûïó©Þœd)tñ|²Ng ]ÊÉ£ÓFB¯?9'fjMJ|Ñ !|Llö¸£,8áj‹}&qÅ\1gÜöt²ŽPbøó¯€<î-(¦AÑ 7–ÊyR¢ZaQŠÀœ1ážW›§;xºÍò¶7£4$ò¨¿è [ry‘j»¡Â‚wùìÁ˜~³ƒÒ6NœŸJGõdñÖ§œÎð”‚Óy}ß@6õøÓû»'Àë55Eu›Áòà£~mñ÷à+cÉl¿¿•ÆD|®255uI4mŠ;m*›v[bêåÛÚ\iièê]ÿÆ&‹õ endstream endobj 58 0 obj <> stream xÚ­ywtTåÖþ™L2çH‰áh"x& JC!€4齦7ÒÛBÊd’™Ù3“F)“I&…IH!4PEA¸€€ñ‚pEÜ'¼¹~ß; ˆ¿uýüãû}keµròžwïý콟]"aìí‰DÒ{¶ûŒysWŽ˜±`éh7Û‹ñ¾ÄøTÝ‘æ ögÄñu;QŠ¯Ú¿Î0’ô¾ôÉüþ²íùMÛóMúp­pbì%N™¨us;ÊÍmÌŒˆÈ„èA±®C}‡¹Žž4iâH×1nn“\ÝÃü£7úz‡».ðŽ ò󎥿„º.‹ðÝè›à:trPllä{ï¼7Ê;,fTDtàÃFºÆmŒ r]êã½ÉßÏuVDx¬ëBï0×.Gu=gD„E*cý£]DøùG‡S]{3ƒ˜¡’R·SwûÙÌ\v©Ã:;o.¤WU<œ‰c^bz0½˜ÞŒ#ó2Ó—qbäL?†g^a^eœæ5¦?#Ð;Þ`3o2o1C™áÌf$ó63Šy‡qcF3c™qÌxf3‘y—™Ìld>`¦33˜™Ì‡Ì,f63‡™ËÌcæ3 ˜…Ì"f1³„YÊ,c–3+˜•Ì*f5³–™aÇH{f›ä-Išä¦Ý0»h;µ]µT! Þ°Oµ¿ì “ maû²õìMΕ3¿4襪=z¤öTô îùY¯ˆ^'z¯ê}ÍñmÇ—÷qì“Òçq_?§WœÆ9uº%WõëÑ/ºßñÁüùWŽ¿êþj¡óHg—.µ¯õx­¸ÿ«ýÕÞ°eÀí× Œ+jÅv°ŠVÌ2©ÌNOÎbàYùQ.æÉÖCs„P¶QÄ`±Ô¶ôleç¨`ŸBü T;ȯgNŸe)ñpƒˆdÙ "›zíï¾Å+,ZyŒ²û_í¿$l…Z¨KKËÚ¼¢ !?©LÍ9ŠQQ¹ Û>qjÄ^Jó%ÛCþ;¾-ÞæOÅìó JˆŒŠ*‹lLPR›«7èõzà œ¥€Œó¤¦‚4\FNVNáͯ°‡€+_ùß}è(:cåÓe&ÉO'¥x‹dð`Cbé‹N!¸ðmÀé;q:¾Œ}‹‹ÀF./˨¶ÀèÙ‹‰|5±K%R˜S IïcÄáyùö¼àr³yŠwãfzyy¸ªÂÞËÑa¾<þó-À©³²Ô Ѐ¶"áÇ¡'ÈX þ@¦™¤qJéVV•+ÀÝ/?Aùa´+B)Üâ;Êß­Ä}­¸ß$Z¥âÛ˜Ècƒ¬¤L¦xHVl”•@E\Ä' ¤‘4²ÉñW% ¤¿É’!Þd‚ŠÁ·“]î¨tº/QOˆè©çÏÄìöýÏR(Ê-È7œõz]²>ŠXè¹^­Öé « Ë¢k×¥-:))Är)Öã"þ$)_ÂÒ»á‰äö).?Â×ÇT‡‡ÇÄ„‡WÇÔ×WW×Sð5Js‡³Y²ë&æß”Š^x‘‡¯3¿º´á‡I¥Þ°¦GùŒ ™•9Þ‡iÙ£wOÝóÞŸƒp¾ªÜû}ùœ«p#ä"ï‹- ?¨NÁ=øÎÀÙü£ØóòV 4ÂÙ„Š¡Ë`*̇i0[õQÒÈ¥a` Bš-Ö½Ô;‘—¤x £_ †XaÁGc!¸PÖD¯j¯á:·±šÔÑBH¨¬Éø-´¶~ M4ÜCØÑšÂ…íš+øøñÏV§CÑó»h EO~…òÝP8uº lô×Ä‘8¸¿3fÙ!0–5í®I¨ ÒmÞÕU}~´å$pßíyo’Þ_3yù²œ;«Tô¯1œü±ÈÊêpºC´,3,ÃsKRFú\Pvi¯¬»€®Â?fqjCû ¿àû÷¦>’÷àcþFíÉóžcxkꢩÁæøz«É\h=$ Öƒg‹›Û}L9Z©Ú%Qžaë6j¢uéºm¤ë2t°…“wªTyP&ì•Ýh™=Œ ˜î©ð‚ieAŸ4eZͰ“kŽ4…Ç„${ºÝŸ‹tüî»_*nÌ¿úFe7¾øšUô¦¸BÆIü86P«r6…ÊvÛ¡­íì¦Pnbݵ…ÍŠoZ‡ˆë(ì¹›…4šé©äTçFçP-”P42Ôˆ/9tŽv?â|3¾zÓéÐOë¬Gþ›¸7ðØsÒCÂëÀks`‡«X“º1£8|ùüwÅ¹šœ …Ž¢š©‰K[7|aCÞúÊt£–¾ã¶@úf9È&@z‰cvnaiËÑëЖ ù ¥?XÃÉŸB,ŠñŽñ ˆÚÓaé‘ÄOŒ:£®¸Æ2Kuu¢%89(cÃøsÃÑ^!ÿ ¹_~@¹¢KgqPÕÍïZ©£î¢ß½ywåèŒ×ùjs±Oóa¡ÚÔæ\’/x„V'™K·oÝuÊóãwI?ÒŸð$J!JLÈͼÒïÿE¿”ùHyçlX·ŽÃžä2?ÂN©·%€¯¡œ»Úðð.ÍÚý`]P«a-¬ƒ5‰a‹6dÆv‡O¥øùÉqË÷÷¤b¤ø„ßj#·JŽdɈ#h‹³*¸hY0ñq°ÈŒ¥[Oåå^…b ¥¯Lµy2‘(ƒG“þÁDoRè<öï‡}ÂaŽåÍ®*¹½÷³îÅ/N`µúPì^¬Ù{Hþ'Šø Û³v@÷éçm.žY5C€¥~ëqæ$þ-Ûá,woÌ ·!ï¹ ÁàѶ¾0µ%Ú’ÈÉ- ¿ †r™ó¾¿ù›Íª}þmñ•› >jå†xóøò”ºøa°ÐÅ}ÚªIãg|vS€“ g¾9ЭOó½[Uâ`›æÝC¿»4p¤xaIÊ–‰°Â¹ƒÛ›__f٦ܖæ7ç¨Ï7È£#Àê4öË1ÂrX›àåáãë Ó8Ò÷ŸÃÐ^ÿö)ìn«:É‘>ð›a„žNhC`ã«•-µ‡v7Q‡4n,ó( Éž¸w7+tQ$F²MV~´v"‘*¾KãTœ;—¸oß¹A^:íB«eW ª@Eg5+L™å!&T C—»wþ¥€o']&Ò"n¹Æ“¾²õÚ¼FÖàbö§¶Qsf®š4˜" ´v¼mu:þH i¢Ì}ÿ8~Ï_œ@FãBœø#*+€¼A ÖmI'o¸N"à’Õ;ð°Bþ3¶ãªŸ (;n&ò–!4%À•‚±R[Ø2ÈS YE™l»s@óêC#€“ß'‹Èx2–xQùÙ`íX%(Üå¥MSùÐjö¹IÏ ²“ádp(.Æ¥¤?Ž&S¤ß¿]ù.‹ÄÝH=”}甇gîY¼u( ™ °`y´l¼*t¸03dÝîáe´?ª]^JœEJ‡ÎSÏ}âØaQZÓLmßìBx &y’x÷4_¬lõ¥Œ¹ò·)p:»+;çsÁÊè–kÃ|'@`¯Á¡ ì]£*@ñ+?@ì‰<-bYÛ„‡)ÜkO ¿Áw£MdÈߢÒ°âèPjÅB2Œ!ÞÄÇ‘±¸T!Oº_×ìø„sÄ?À)*Å_øfcá5¡Æ* ÒL¿ÉD©a¯ŸyC£š,DÙz€k°s×µ® Ь¡…ËQ,PšO¢½¸É*Ùö8ì¶áPþ5ËV j˜ '¹ö¢í5ͦåÆdO÷ ‹î(~‹ç /ëó)ëîàÄÅìî8MQðÔúëÖ{*¼™ýR‚(’å/4‹yœƒîùùG_×»XÙ(MD.…ô ¶U— i°yË–ô r–´;ã¶ÙPxE¨¶ÙåþþÓºìú(£v]‚;/wÙÃ~`+È8ƒ¥†Î%•¹i[S Õ%Ìâhn7Ùr»igWn³+`SvØ^d4È|M¢Ð¥(~c‘Š×°–©ÞL&}ÉLà&uG”¸Ý%ß VY Æ |ü¦üµJb¹ÌñéÐg¦»Ö‰Õ×¥¨îƧ™5@k™òGúkØHX?ئ˜þ ¡±ñ Öf;Ô*Äf=‹êÛå¤ä¤€K!ó³ Q×ÑÛYßyAöÜøã—°k×ÐòÂx±ú9pdŠ, @—‘@":O9wÑf·7êÄIuRLêçéôñT¥BëeÛÀ¤Û¦«ÒèuÏuVüjelN¦^—­Gv>pÞšª×åWy ñ [ ÑpÒ­Õ¯5ØbÁúHEçT–„²¦cb„f•ç#i‡?ÞãÑ‹Œ ¼5Ì&o“qćü(↳pŽÀ±è!oÈ?ùäµb á[_ÞüߘI¶’ròúÄwݱ³OÛØèx$Å8<ÇãöBæúÇþ“¼® OþD¹9,㱪›™îÈp, \»CÆRA±J3uÄŒí”ö…Û¨C‡©~¨¡¥5ŸðXÄB™†z0wí³È›³bÞ#CSøÕW?…«ÜDv‹ È¡N³ñõåhþS ç"ËÊÿ] mдqg „˜¾»ýwSoîjÙº\(LQPžOÓe¨g%DÓŽ)ýpòý”¯άm\^AÛ‡vZ-Ü꜎×DÁ/Ϭ¬‘_Ä_Dgžô³.ØæwNºœ?úéUß3y7×C¯5e¹bÈ©Pà†nzÊ.#5h©sX½Ïî14`¤ÇTÀ»G¦_,Ì:œzž¶8÷k3¶gÔTFC07sÍŒ‰B8LÍYypÉQÍ]³® öÆ\ d$(Èz62 i¿ª7ä‚Þhl[rêÖi7­3þ‘6©•­’ŠŽuÒ‰xƒ/i©­ÿRÏYÙP­¯.*l‰!Êv¸]WE9$]£ÖªÉG›œÉ2Ñ .¡\lp©?ÛåšYà¿Î«ûòÏ©q%þ˜ÔùÔ9/>GS e`ÈÉ)áŸuË+#}:Ê+?±§`PyaÚP]XøGÝò¾Ð™‚!Ôšt*ox§3'¦è²µ¹ã²ý$ÔtÉ›MAð2øØÎŸ€J( 4èLîd¼¨¢3FÿòìeÈÎ, ÀõÎÆ4ã–b fäeã$1ÇßëÌí~éÒý–³ ûÆÖ§#[%Ø£UŠùÄÈ·:òA+yý÷$Ö¶™ž Äö8“Ž4+±×%ÛCþ;ZÄe|Mbm É[èä¯ÕÑáŸÓBI¶òþqú³¢gË‘ÌìLÕ»SIEÕ{šÊkkl«™ÿ݇Rµ'UulGO^÷}ðûÈá¾øºŒªª2'Z1Ä\swô½ýf§¶+ëîáÄs-ò°#xû+>Û·Öûp•Ÿ–\W^Æ.‰V«‚³ö帞¥D°+°ÅoךÒu´,ÍZ?7Ì”XSWn¢MmQfã}mÓÁB:7<á7FÀÊ÷Y­ùP3?lÚÆèUàɽ÷ ú´@¥œ…ý­¸ |—ÂŽœ±Ñc­OÓ!޵ÝÄI¹6¾P™U•âf hszrKoÊ“pšØ›Çó,¬reÏçg¬UtÞ·°z}~IíN~p[lÛšK4{{þú#:äÃ~"2Ú²L¯õ›8#)åч¥±¨/,ÝuüX~5ìƒæ¨jÿãRðí¢pM¡þÁ+À«cZ’+ÁHgAGq±Ê‚÷Z,N;nâª{ɶÅKÎãÄmG„­pZ×è£Q‡A UWWc*ÛþåÔ]¾ïPÎî#È“~? ¥­Àk Ø« ` hè|®ÍÒªÃGÍK  -­¸rì¯è²XÙ&ºtYLE•ž£ _Ÿcü\‡:XÙÓó*äÅ_ÿl? eÛ½jVP6ì1hvå?E›Õg`ßK‡•öÄ›…ЪÃÖy(½lÆÕÄìŒÚ­9»¡Åpª~_¥ugãQh‚¶$«Ga"çžV‰ÓÍNu71íl×fÆsø\v˲¸G¤¿Ÿ‚¤m²íÍÌF¨üiÅÚ¨pï &}Ôæ×G÷¡´¢ Ýi³Y­M<¶ÀðÝÛö1œ…fšS'»·¬ãnå›%höÞ·Rœ!Îà‘cÿùñÇ{#lƒm©Y )ÍÅ–ÆÕÖo3U·4®üpÂÊaÿŸê.ýC]ëh}±ÁË(³Ú’“øTáÒ“·ªªœêÚã.ãôËMíž'å¿©0§ñãàa•jõ Û,ùEUu­À} Cb© IŠNOð¥ s~Ïg½püÌéÂK’ÌþÕ¹UT¼n;‡ËX¸ ÖÐæä²`Ó˜ž‹ý9|ôçÀ´ æÔ­mØû‰Óå'ž•ßÇÅ……fØG«÷Öî?PÙ {a²Æ«Æ –€? ¥§ÒÃ3|mÛ×NVZi=]Ú¢-ÏJÑZŠzñgŸEÁ…<µ§B~½3è¹I;ô톚ÚÃÝãJ·é“Ù­lÎæ¶_½¨OÃ"ö ùƒ)àí§¤õi1lýáƒõ‡»øéXâ@z8Ñ]á þ¦ÈÝ´év¢bõ3m†[h›Ñ]&®‹}>åÉìÿYºxBÉú»9ȤÔùœ~ßFcƒ†“WHßo!G?»÷˜ë9#†òd ! ʘ”äÈõÀM_x‡ÒxÏó7/}Ý6n%¼ÿs¯?9ûä¶ü ¾ßðhÇÅ/ß÷"þŠŽG±?µÝùʶ&ƒN£‹K…(.¢2É\n)jh­÷äW¦Càœd/j¬ 2‹*œ-Ñc‚%öcùôÕ¼9ëÆf˜Á­ò"L„ÀñßhŠuÙ[ž7öÎÝ}èõ*¦¼b¯÷>]%…žÝÿÅ?p$l{jQpƒ_¾w> ªe…sŠá$×T³û¶€v3ÚªOÛJÕë?~îž>2iaLIÕdmIËÒø×ù@…ÑÑÎ2•FÔ*9ù†¨:õ?’©Öδv1a„ß5I~=‡¯Y¤è.æñ +yçGËt“Â\‡eqÊoH=K^¾ŸÚ|¡îÂáDôrÖ=Ì?`|W&‚L:PÅ—[³óÍPÊÕÄ—ÆÆ)SÂ<Ú §a÷‰êœ£Ò,Î(ÃðÂ\³Œø±Öçzš·öêuÎÔ«·ÐÃ~¢©×Kx»ßÉôò³ endstream endobj 60 0 obj <> stream xÚÝ—‰wTu–ÇS VýÛ…¢´æû=Dô8:,ÒÀ¤EPE!@ {H [%©Tjß^­·ÖW{UjIª²'•°!e‹ˆ‚" .Ø `÷ØÍ9œ3íñÕô›çW ÑžùfNóÎMåWU¿{÷~¿Ÿ'gÖ¬‡ópÑŽ· ×-úýú­—,^µ<ûÞ?gžËÉ<Ÿ›ù§<â›M³~z 7óجçØO¿Oú·ïûuNGõHöYøPö™ÿ0~æü?øGçæ8œÙüÇŸz~Åš[vUÖ·©Íîp²g⃲êÚÚ%‹/]y/øíò™à·÷‚‹g‚f‚™5+~^³b&˜ùž«î+g>¾rÉL°t&X6Ì|óª™Å«fþµjÅâç—½ÒXß$n­jž¿¹±²ª¹aþÆÖ²ºÚŠÿõ.NyvuNmNçBÎMÎw9ÿ:;“Ãæü„k°!gSΛ9Ç̱p¬àØ8vŽƒãä¸8nÍñp¼ÇÏ p‚9åæprrsF9Õ¹ÏæÒ³¶ÎúÏûRÜe\ñÐîï˜Ý=§uÎí~•|ðñ‡{øÉGÍå=øgñ®z¶$‘ùªŸé‘p˜úÌ+‚|.e1é€BZÚâ!.sMJ ~Õ³OŠÙ…5ìmµnM (AJëüQWgúPBî‘×ÉE­åZW`ô›ø…î¡[ß?ì¸è¹ˆþÌ¥í.xOo§ˆå\ß„gÜ?áu]>aëýZ‰A¢Røä½±žÔ‘’DAqÙ\¥š]©zÝ¢1k¬4½[]"ól‚©•$$sù7™]™Í‚Mº}/)Š,F‹Œˆ¢M" ¶nW8p¸÷½·…iœ‘¶Eß,+–K‹Õµ’J¨EU]åï4÷#÷à×á ›Ëîòêl¡ e¡Ô;Wo¤Òù"$¤|½Þdt¼ãxÇx`(–†atP|d+ñ9S+˜ÛÛ¡ ICÊhg²³“àU„¤ÿ¦,V à]ç>w&hëlˬIÌÍì|?ÊÄ™ÿ˜Æöìô»–PP´ÅEvt;#ÞÑØûi@¯LBB%24±{„”HU ͸>êÑ Þ.g×F$ìøèÜ÷×y¹CzêáÕý«[6èZuÍЂøM»Óõ‰OaôFè›s*;;Ö;(B¦:£ñG¥-;vÒn BF¢iÿph4pÀw€î¡{ }¼kp+ñ”Ôì-ÉÖžÇNÕžÃp.1󘻸ö¬Pù»ØGÑK‡–ý•ðs™ðÿÈ< Ì£èZÅ·ó‰/ا†7KØVV¨P|fœôñkútÿ ¡!LELŸËãñЌɞ9þα+äó8Â$¸,N£©¹2Yd M¨kü²!—oÆ=F2pµ”AMB[:"U4µ¶³v‡°¾¹®¥AäNÑÝîÔi¦IÈwùFŒŸà=¹­.| NÚîÇçÄ7Ó'…“1ÉjÔÂm±ˆ —Io£5ru  ‰§Ñf¤6ê5$ˆ¿ŠA3´i›mì#ÿaê´Ú"ÀëðLëAL<~Ýಸq]\!ÛB6tœëÆ•rƒh«ðŸü‚Y"€“vI¾Ë¯µé‰v®¤ÅÖA‚Ûî¶9q‡t»{:o AÚíóüésaÀç÷=Ù>ù¾(gºOn˜Ç|}^ப? W!òƒ/msØ\àD89=¡£ÉbP•¨–í†v0Ç,aDó éîrwM2Z¡ÃçôÛü(¡öʉfЉM²öáæd öá§Ø|vÞ¦Á% ÏÂpz8N3UcÒ˜µ5ì|¡Ye‘Ôm»¶•Õw_ aÔÐ3ÿü0óè×€Žuì#ñF¯…é’™L0´„óÝ%¦ãb³Šù‹¢á_gשáwÞøæ$óŒdü/xÛvp š²#kŸVi\ZÇæjÖ½žÿj#ûp㓚2U”¢Çó¿g2yÌ Ì¼k{¾Y„ÇgKMi©Á@LzÄx+ñ0T±R–´gïó$ÍsŒx†=éðdtrüHgl ÜèÄ`éö_&‚3Ö¿S—`šL~§U2÷Ï—Óÿ:s=;|)Ÿbç;Ö >{‡BîUøîà¡;îräÒûõ„…K™M:£±jǺ²MxÛ''Nzß’NpY€®1+̯HþÓ;û‹þu­&\ã…l€'|íü¿4Ú+ªYÀ>oýrZÌîÉÀóçó2Ož¸ª4ŽÂˆÿèÂB“ýešÂ2Saö‰€¤TžœlÇ''˜"!ÝLC kü ¢ ´­&ñk¬OhÖYuf½¤¢´è-@:n1­=£póè—ŸÛ=¶¬wœØ7PN¼ 5+äÛ¦¥ÞFÑfú˜_²sCàÖØUˆâA;%1Èš_©^ /¡uãÅŸ‡`8ÜÛ'Úëõ ¿Ëa ¯ÉŸ‹¹|—ýÿb.‹3jÛB[°Ìõöu÷§¤!I™¤¼ºðlÝiò<|4ÐsÎîrÒ@#—ÉmÀÆf–›´ˆGTö–xì…²€"ý?¥bd‚·Íga;(Œr‹©yñÂ3ÄÐwÛOìÈmÄã[ !vÁZ,M¦®( }¾Gov~¯æ§Þr!ï“S ù-øÁgöhÅfI;´"y@ï‹vwª6,¶³‹V7xû|Ã0€¼<ÓÑ}C{­”°OëI›Á5*Ðå cK¼8(ænUP¯«§7³6¡YkÖ‚ š] 0®>º'ÍBGȶ‡³Ç<¯î ]¢0ï&æòKo$»ÃmH\«¬i¨‹ÔŽ’ÁÄ•®óž.–6÷äXÇp÷©a@ÝF1 ªÍؾ—](¤š´MÖFdæU¦ŠN ~*<áÞóUÏ‹y‰à'ÀÆ>QX´m&‡Á-4Ò– x³ýB'0«…î„§ :Ñxñ@1Q-íõ5Û›Þ”¾)Y¯Xüê>ʬ7ëÉ5¡hvÐn<½F—°¶e6O¡N)s³™IŒw$ÞÁ •ÛZ×mm¦Ì˜T)å¾™Jvôu(ƒ²ZÅþ†ÚDÍ(yÒC‰ÔØ)ÿåȇñ/fêbã:ö{ê\ûCù‘|¾CkUE  R'c½'¯M|yê³@4õÅð2S“NdU±¿šäF¹U†»‘Ÿ€==Õ†/!ðmdš*œÈ“UE Ød&…ºR¾®¢1ÁÒfO¹ºÜɘ¤Ðîv`sÁte×j.ßeœ²¬VPש¤o.}ciÁ­R¯Ð¨ä §™á(â'ÌG¬ ~žÖ¬J8™—…À¢2©Ì*éz¡Ya–ƒUL§!1óŽíNÛô¡X]‡$mf¥¶J¶ïL¦Ç²Í:@÷M2*¡ÝïôƒßÖx•Ø\u2ª¥ùl&µE…Ø-\o¯§ßÙ‡ü¼ñº±¢üVÜ—YP#0¨¥ßHôƒè·Ô®DÔ¨÷êk X¥Ð¢7ë0œ(=šå8Ü݇™UB‡ÇêfÓ™²©aûã%&ˆ1ê묒?ªds°Ž³ÂŸ9êñàÌB`C_ì¹ñ樅jµˆµ¡@ÜÞ(«·¢-â3Ç0L9Fè´o8öÉÐõ«>§Ï᳡ ‰mE$&ÊjøÿCŸ?æEØ58 æµlíæf¶_â·3Eï lÜ`ÕhË!@Ì‚ÛLÁWöÞ\JAi;jã‘Ú~ +ÚÙçl”Ûì&q ‚Ãóß>6£&Š ]ÅRöG¡Qb©åz½ 4V¤åê49iáÉarZQR&Ñð=RBü·‡`Ø<„ ÉåñaCXßbNáŽÚî±Óƒ _èìpEˆñ0A¹RW©©j_»›Íû ÝMçFH'φËîf~-ô§Ý£‡ã‰Áä š{ØÜe«ùùø¦í?³V‚Û%/³,3GÐlË  ÉÂÊÈ`Ç`/AMîNâ‹ »€å°/°ü5¸È«p5=qÎéòxñØÙyÚ@ct“Îd”¶ ËK^¯/´U|ö(éçyÿ4¬aîÌi’Šp=þá¼E‹¾ ´eÖ&8™“̶÷ò2~æ•ûÞö¾ÄF(Û[]:ÝDkAö¤®Æj²Á„ôÙù¥Ðøúw·µc.5¶Ú6°)¡E‡§C‹äA]ˆpr“Nw‡;y†iF?= £Æom= åªrmE1[ˆ­tJämˆzÐÕ}ŠÙ/ì¸|áæç6äæy«D$°¹kÙûa3¶gyoÝ\‚“·<ïãã˜âµv°`vT–7¿Q ÈÈUÛð#'âî8K];|® Ë{† ‰x½ºqû½Ô§k>Å8Ï\øÅvi\S¦ I8 ï§{ŽúJ’5YRø²O7øß ¡¦R†…PÆ(¦Z/b®¸3z‰‰ í^‡|(¬ò)1š‰,z±±¥Uå›6¬]¨R—î#ápðïà1æµ{«­G u@5EÛÙ2Ü«‰±]YöVÁ;´Ãdg'q6v2˜öÂ!t¨¦¿ŠØÕÚ·Xô&Ut.³‡ˆ=ጄÆRçÇ9¹‹Sk×dÅKJIŒò–µ•/bÊxeb÷â]81Ø=–•Ï|/VßD‚™ƒñ`Ñ9Æv0 2½O¸ûö±ýƒ¥Ä+P±TS4ÕXس(èqG‚‡º'ñ¬|ZÜÊz]“¢BU®.§šõøRäØxtÇû€îÞ¹õo—·Ml"µÜfs«®M‰˜y¯ ¨MìCËM¨Bš&Ý<ÇXh²#ê:24 h ³©šÄ#쳈©cÚMs3Õúëš”fv#ϱ;½÷(|¡»Áƒß³$ç˜ LAØ4 -Bì «³L ‘¿œQb¦êS®ðË%~ &QœY’ÈÞK?f&¥ÀÊ+Óì®m/“–¨—n¤’âd*í#­1…O¨V±¯¡¼G”&ÏÁ‰“'=Q{ÂßÑsì½þNƒÌ,5J5{„&…IaÍn¹"µã$­õVä䌵êzbøÙ›ðÉÔi ÃÔ;üãÆì1esƒSGðo§¹}—ÿ±¤6) ì#-‹·]¬{—ük\ð2·a§ýmŦcˆ³+‚  Ü–gï{PÏl¶1­IrÙà³óü/=p?ýÀlÛsîÎ>1‡X¾3O²œrÿ4ï¿Ã4oD endstream endobj 62 0 obj <> stream xÚcd`aa`ddäñ uttôÓvö ²ñMÓ÷ý:ô³‰õ‡4ÃÆ²L?䘈³È200¼‘ùAä]© $˜l„X9J*Ú Œõ Œœó *‹2Ó3J4’5 --ÍuŒ ,sS‹2“ó|K2RsK€œ…àüäÌÔ’J ›Œ’’+}ýòòr½ÄÜb½ü¢t;M…òÌ’ … ÔâÔ¢²Ô·ü¼¿ÄÜT“õ@„s~nAiIj‘‚o~JjQІL B  " ,L Œ , Þ û=~tðýXÞ½æÇê5Ûç3~¯¿ÅüýÜOAÑe=rIÉaÅ:ÝYì˺v]Æñg*{ZG½Ž\FÛ–¾‡Ý;v<êÞ£²&ƒ]§cúy1w¿¿ÿòv ã/ßK^1_÷=Atö¬­kfÏ›‡WŽ‹Å|>ç÷o"?Tø endstream endobj 64 0 obj <> stream xÚ­’]L[eÆÏi+YÅObÍÜéÑÝ&al&pÑL’ØÊF·ƺAG>Bi{z ý„úÉ¿´Ðrh)ƒA±­| ˜1pıé¼Ð³DcÔ ¢Ë"ºKst‹X¸™‹WæMžäý_¼ïïyž?ŠˆDŠ¢ÏÈ>,,,(y;_&+ÌÙÐ%}ë«kmOqÛîU”Û!àp!÷²_)ý-ì@„{~Cï?»¡÷žÛзxýþ"BQLoòdg¿“•½/_­1Ru5µ4±³j±77w&±/;;—8¨"©º*e#!SÒµ¤JIó—⸺ªŽ¤Äε4­ÉÛ³§¹¹9K©Òe©©š÷weÍut-!'u$ÕDV‡Ô4Q¬T‘Ä&zÖ¦æ«U=MR„L]MR‚ ê*AŠÃȤ9Ф!!T*@…Û…+œ;}hKpÒ›qýuyâ;!»¸&Ê6÷ÓÚFJßoŽÆ>Å“o>fœLâN‹³L¯”ÏÔ|ñç%–3í>;Þ »ÛF¿wî\`­­]q)ŒÂcLœ‰÷ÆÇ~–ôDCcp[¨ú´l·2I´´\A< Þn“Xý<> XãTKÁÖaµ©°tî`²2Á­l2YVYúŽÛËC Zu*­ZkˆFFc‰ž$¾›a)./*3XüïXćlÄnjÔPõä4uÿXÁÌ(+¾Ë®K|¡Î D°¥ŠÏJ^“mqô‚׈Œ./..6²ÖKÁêæϱ`K°—ïF,9²7¸ñ‡_ËÌðvúxx¬ËÕÓŠ» ÁM{Ž»$z­Œ˜µBWÁцƒá°7ÔõúýýÐ ¿¼1P˜žœ …—®ÏO_…0„ÜAÛI;(øõ,ÃñÑáK“º©Sx ”VÈå%rê¼ÙŽ¥¯°Y>º–·ÜuGÈ*Øœ _„™ñE|L÷H'ÓÙ5ñÍÜÄdl"˜lú¢þŒtúüY»ÖTàÐXŽJœ&»Š§¦ÛÃøDB¯;8Ù5ýMòè¾ëàNL\»2w°©¡&…N(“©†Ó6­ÛL~E}ùþc‹¤ËQ’$`æv&*…hp˜ù823Ǧ ìûÒ©|üÈkÎÊÚ:

–Ì“¥Ê[êù–[žì(WYýŽò ´¼‘´/UŒ—A P´¹wqêÿpÑ4Äå3½½¬f(%Yɤâi¢ýÅOÄi^ñ¶ñ´·%üb1»òÒ?¦IR> endstream endobj 65 0 obj <> stream xÚ]PÁjÃ0 ½û+tì#Ne()a9t s{hoŽ­d†Å6ŽsÈß/vC;H §÷$=eUsjŒµÞJŽzm”ÇÉÎ^"t8hCò=(-ÃV¥,GáHV…û#Bv¿ßÚöµ:ó[Nß®—:?€ÂþA¹,a¿Õ͉/SÀ±1½Æ@ö½Nœ‚_`wT¶Ã—ˆ}y…^›v׊'„ÏÎýâˆ&%e™Æå›¤U89!Ñ 3 a”–Àêº$hÔ¿Þ¦èzù#> stream xÚuTmLSg¾—ÖöŠˆ±Úùq[·)è+: *J4:qÑéÄÁRë…Vúm¡¶Š­-ÐÓúA)‘¦E3çÆ&ÓÎE#.KØü¡cÉþ8³-þYÌÜ’ý{oy Û[:Å™,7÷¼oÎûÜsžóœó^š )š¦‹ŽÜ{ðÚ‡nRä<Õúé#“e.Ìá_£ø×i~M¿VÀ/²ßþ]T°Š¢hÓ¢œ­_³»K­%FT»˜*¢éùK_-Û\³ûPýÝï¹f-wÚÔ~ÜÄ™µœÉÄjWj[ŒœÒÌgöJ£Ñ`1jZÔfNËé8½Yϵ(̓ޤUšÔíz²Óè ØÄ©r^…bs¹BQQkh³Î|$/U­“oªªª,“W(Uò:ΨQ)õòJ³šÓ‘H*¥V~Ø Òpf«¼´Zm6·½µq£Åb)WêLåcËöuer‹Æ¬–¿Ë™8cwB¾Ç 7ËßQê8y^“òüRkеµ&ò†œQO*/¤¨ÅÔz5UAm¥ŽÑÍôIЏ©Ë´›öÐ^ÚGí§tú€j¢©mTqESBjÕO iý¨`{Á™‚ LpC¸_h~Á{Š3 dKÓ¿ðH)A6ÉP’I+ØdÙk"›,– ɯJ£ò4ï&Ð4AòOf‘xX„kð ¼ Wà7‹%h› ‹fÏ“"r"@s‘­D"òl”áðÔ>Éóø|bý,WŠ¿šÌÓªä“Äú"}0ÀÄ\Q;ÛN·Û›½ƒ¥6—§ \à u vówp\ï @˜X4“AÔ²E²Iä“ò¡¬%O¸Îʲ£¢³/•6›n+z( …Â…~wèL8{Å¥a7x±»œØ#=±~ƒ4›Ä`qú\ÐýŠ#ꌱA@<ÌðWqãÿ¤›<›“{|²Py@ä>¢l;î:×´ÇU>Æ>vüÞÄÅ?ïþŠæÜè  áî ×ÿជCÕž_ÐŒËvx£u7ö&uWÔ_µ2SgDÖ¼¢ RV¹*M2ÍôöKó?­­  åHü­)^èT…ïÀ+ñR¼oAdE;d¨â…s…¯,~jGË™bÀÚÔä‚$d¼[)ÌTI"ƒ¤þ îŽw²vðtwufß›š’º:‰vƶÇنƒ áמæ¿MÒãi^Ÿðˆ¿+!¼-°ZY<-Æëqek ÛuÑ÷?ß>÷á2ƒ¦ÄÏ!Ù1.Cö¡Eh)*ý•°¹ˆ)~<=q¡•á x©§t7.a³±¬É$$,š£õ¨rä{î9¿Ñ·ºá|ú}îÛ-±† ƒèÐÂà1(¡õ6w]7á¸N†5dXû Ô_×Û0rîkO”È8Ê f1Ür µŽt¤ôý†ÈÏGoÁwÌ¿¬Ô)^“ʳÒâ¹PÚé®|Nƃ(û<óÿÄ Âê:Œ¤?»zåZ`ØŸç϶¯÷بcÌËg#¬nÀȱkªO÷ôk€q:€Œú û{î±Öx}ЙgOX5Fl#­©Ž+ç?vU™[áSŒ>!¬&¡æ¥hs¦i¶Ó[^Ö4‡ç— ø5¸CÒ×Ùw>þìÊ Ð3€Ÿ¬‘vyÂç€q8s7Î Þ>;Slº”ÙA~6+bb¶PX™,š.*ôÍK¦ç¥/‘w>z¼ä;E÷¼ endstream endobj 69 0 obj <> stream xÚMÍkA‡çM"]Û4Æ]+‰» ºôP-ÙÝVãQŠŠP¡ZOuº’ MJÙd[„%«£RˆKný8 Þö/è¡JCîÒîÑC)=ÌÂ\ÜqèåÇË;ïïa¥RÄGs3 O¦Ç^¾šz:7u÷™µT®-󇢓?}ŸþæÓß.„·PxB-jÉðzê&BèÏež¿.ñü™å)F‘xx ¤‡³W¥êëE¬ßÃú}¬±þlèØ0°a ú¸Y4W+¶Š«•ºµj[Kª]UŸ¯¯Xª®¾YW—ß+¶~GuV˶mUøjWm[Y|W®ŒÇÆ(rÍ øð>Ï𾢋 (ÆÐrÑwt€h0 Xƒn‚ã'£Aô¼vG![æ>¡9ÁkyM×m5™t¨íÊZf=º™¤%Ö;mÏã„Âdò"pˆÀÑúñQΣ V9&¯‘Y“åbÌm»*î*gõ¿ý$Eçš-ו Ë›óÄšÑfç蘎șÀ‰1B"?¡µ`–°œÀoqm*MžÔ¸%ýWÚûe •Éž¹Mn½3zÄþKöI‡–DNÉ[d? ¹˜â2LÒ&kJÜýCÄ~›L¨ì‘m¡mê£,RôýîA·›NûCñ0n\ûc‰ì¥ endstream endobj 71 0 obj <> stream xÚe”MlEÇçyM‚’·‰h©‰Ä‡þˆíX¡M­PL¤TU‚"¢¥Nidʼn*S§j+K­×»Þ¬?Ö†˜¦)í©BßR)7Ä¥ Á ‰CÃ…"!¡Èr¬ç…—{û<ýƒoŸ==>µ|GôxEOôö‹^¿èóˆ>ŸØïýnÑ>1Ø/b0(Câ@H yÅ_ô¸Ý<8çò‰‡G€_Å÷½>A·ÛÓçð ÏÅ®³sñ‹ÓÓQWbÎuúÒü´Ëãúè’köœw>áyÅ•¼0“HLÇÍ­±³s‰„kTŒÍÄûêõóz;  Ž‘çI/ñ’×É›d„œ‚÷É™$S$JΑ™%s$AÈe’†dA…EÐ y(@t(A>…Ï` *ð9Ü€e¸ +p ¾€Ûp‡> stream xÚcd`aa`ddä ˆ r ˆÐvö Ž4 ضÿóa5ü¹Œõ‡ ÃYÆrL?䙈³È=ôbùÏÃ$ËÀÀðGDþä‘_@¤:`Þ=‡cN͌ʪêº*¹îÎ)†=í= ý©=u¿•žJ4Ohíoîæ¨ª®)—ï.ŸÕ:¹}_Ù¾²ýª‰ù•Í5-µmÝåå³kæÈMîž3mú䙓×.œ1eÍ‚é“LïªmÏèªoÔ’¨š]7gî¬säº{šžvMèšÖ¾±k_ñâŸöKØ~+Ng—ãbž¦úŸ‡sW÷~®ýÜûðð1ï÷‡"Eö»— endstream endobj 75 0 obj <> stream xÚÍW{TSW¾>‡ÇÙÛ·rLKö;Nc­cÅë£Õ>´í¨,Z¡>IDyBvÈÊ›Dž"EíÃÚÖ)ÅaÆi­·Õz§gf¹ê¸Ó{¼«wÈL®ÞYó×]IÎÚ+ë·÷þ~¯ï÷š ¡hšžµyÍ k_{bóË›"­X´ÈÿßßbÊä[ì»?D|]üáWÿ{UèCE_˜åføŸ{g’'5Ÿ²pÙóë6mOLWl‡\ý§Ï_úÇïMIyjÑ¢ÅË'‹‹%‹¥ÿX, ,VL,–Œ—Œ—Œ—- ,»–®Xؾ<°}ùSÅâÀ""°œ¼§ÂgÕa×ñ¥À~Š××JÐZÍ+[·–––è–ØõV®¹º«ê[ŽDƒÐ[ôÞ«éj™2½9³c‡kÐA«Ó §ãÈ ´#I$n½ÆnRaJM_ÇT0žƒ)‰Ò ÊFr˜Ñ ?,xêº[U­©œ•!ƒì}/¨ýX(vÏñ­lQ4*:Ú¹®§EíN#·P©Ñ€ ø‡Ÿ=5èäÒH“ŸïÀçÞÀqîàÞoWI¤GÀa!¿Û Su©\Ê7"(õ} ¼Ø*g #‹_Œßµsûc¹%ŒÉÎFÝ&yüvÛ«/sZf‡5¹ À¯0sü+n<&Ï·aê°n¿8Â÷ùÖH¤5à° ßÅ‹í`¸•“âtOPd˜ó¾) k$ì§¥*I„ÌEÊÂδX‘¶eºÒÿyæj‡Žwû¼DZºÛʶòwM•˜JÆËŒ»9g{”ŒBiéâ¿ !uüúKZÜE*ß! ‡|ðÛQœìÿ²Þ®qXíÃ^l Æ×9V%l׈9?åÎbdJKwÛÈÉKŸ!øž}=±,ɲ²T.—³õþ˶XC¬= “™I!¨j7¶ç¶fœˆunCÑ+{T¯A#S<¼¾e#Z6$gn0þ5œ ç¡øM©<â7¨BÕ¦j;Ûu‰üÝv°;Ù˜ÄÉ¥ø„‡ÉGùÆ|SÓ­½<~ *‡Íaë:ÜÕ×Ób-rÙ‹;¶‡÷ÄöÄôÄÖe„; «rP.”ï5jH:*<@Th¿=±N>”Õ}%úÊkŸh+uUÅÐÎ;söôÉ“ÇÏô#èS¤ÀUŸ¯âQN^~aqQqQQQ±%>®RgkTê‚‚ü"ˆ‡Á±³—kñ0Ä‘ÎÓ_G‚ÚiüˆÇ×õI°wÌ'ñ¥ Á®Ãú$•ý„q7¬‹ÖÅL°s“ãw<ª4U  “ÏnSW¨êóâ¼sâ£o‰ ˆL¸5ߢªEÐÄÔš,MÖêñ+£xÃ(^ïht6ÙšLw? OHÓ¥qù(o¬Aq¯'¤IÍGy_;8ÒaëàH8N¿W/µ¡(G̺ûnI®¶¤öøÛ[ñlòų(jÑÖè-ûÑÿà„n7~xóËøü­à¾ŸÏL —iéçq^þbÅ÷½‰ðT„qÊE‘¶Cqƒø¥  ¥²ª•»ÌöÒ‹Oð(¥4!K‘·Q»Áÿÿ]ïÇgð^$„ÝÅ1W¢þ“½ÝNšLÙÚ…Ò^ô‚øLC §Ä•à";ˆCx;оû›®=VXXŸ«üÏí¦7w¯°¯nOínS<‚«ÄxɆ½ýöÉ„Wy-нº%õ5×0*³®µC¼.O¨Îr°Ñ ßaXßàÛšèÕóti<ÁóôŸ–ŠsUx©à›)Ð8® GŒcÖ§´µ’y¤Cz£Ê^œ”)®¢âÆp7c=ŽÞî𴺎”w"ˆÕÌ9ô¦¡~µ]^.3Ë ÀC3™T¹?Ÿý ße>à @\pw†$û@éNÜÍèµåv9j9œ®Ùðtº*.îÏLsea/¾ éÈÕ„×.̼PäÆû\x•@»¯ãÒá` ð dª¬6'žõì§/ ?qÆÍ¹ø!~]:Õ0l2›,Èíz›–ÛŒéEy™ñÛdÛ,abËwveŸÐô• /4¹$¦‹îË—šå“ÁÏ/~f"6–¦R•ï×BØíQ¼o”pß#Q¬F Ø1†kÒ0òtsoª¨pØlÞ3ÇÏ;Ó(4´4¹ hÒ‚u?°ÎfÒ•–£<öNÄGÔ »Û ûxcq±V§Û³3&.F¥TgdgBlgÕEÅ ;ѵóð¼÷„§Rø_÷=ë¦>—A†>è@ ”aʰÖT<ˆš!ÛÕš%È¥j…rÍßrß möqƒå}hmÊ&…<;SÁ!µSS_ù¿°=m÷òKAö|hý„a¿7„²=‚ È–>þ&@Â;í•U„íºcOììµ;sQ>ÌQëóýÛðv²QÏ¡M·Ö}¼¿IÓ˜Óü~÷Ÿ¾&óHW*A¥ÞRŠ´(//G§+.ß°9b @6£Ùa':FÜ|ɺ‚‡šÛªm"í6Þ>ìžáÇÛ ÚÜ¥É| @Q¥´QÚÈÜÇÖ£<”Of l>Ô\ß”× ÏRç(bÈŽñß *¼È6j9U>T~ 5˜k\fx“* •¼8XÍ8%€{'Æ_!y&Á ò=N`y|ÁÙŽ Bi/fTh*@pã>ÍnB.‘ØRÿoÂÇ*Skö=p$¢wqod5–bK¡úr¦®¼ájOï#7ú>·VÛ«-Õ&ñF8;$7l#`† ˜ù?­’p @(G››¶*ùÙÔU…²üÔ\ùÎ;ÛîÄaJ[k<¤@ßK0Î#Âñò¼gùæ’4ŽûÅÈ–#<²“&µAü Þ'>ΤE%pw Šûñ=«·Ým ±â> @WƒíÍñØùg†Û÷ë£:¬ý3ÜydPï{M"‚'žDâlø«Ëâ4<OÂA_àû8ö2ž²OÁ±z¢õ~å*VJ¼€½ü‘€ƒ0ä>Fƒ*V–«ÿcˆNŽWJs’Ðjôú¹üÕ¨ª¬þ[CBá÷êpÙµr¤VÔ‹zË{t5êÓü´)û¿xf‚AÄMDðáWß<·5\gýƒH:¦=ü]%HHG;HP¥ ºÇ$#fÏÎ侬!BüSpÐM,ÁLgó›Ñ¶Ì½‰ð]€›E¤tåι!»þô1/DAÑ߸tü­/ÄIÏrd´1ãç÷w:½„ß»ñcrw‰ÿ0þÎÇI²µû fÖf·µ4Ö·shd©U‹ŠAOŠŠÓ¿~Ïæ?Dïõ¸GÊmÖ ÒœŽK w3´y™»âdd Št žu™g{>qãÉ8”kEm¥B¡Ý`ÓÛ 00džŸ|4¸‡ø_(.u3¦nóP£«¾©ÃêF°Žj ©¼xìH0ìàTJ< ìcR­<>»³‹«cúQQUŒMYžaR’Xˆ—ûßB¸¨(q· Ä³|û…0¶±ÑŸßƒ ÕJnŽ w¯m[ë^Ûñl¸Yë(DÅ(/_­Ë/‡kvI£7—íG9Ö<§ËZu5Bv·+§>]Q©Þv2m€ûyñ<÷ǾñÞ¸UÛß’‹Ràð¹‰ùë)®ôKÝX}}_å4™ÕÍvÓí{^’ýcÙå£ÁYtÞØðüÏIöŠØ›/Bŧ²›w‹ÿ€S ³$WÁ´&=JBIeIfª¬‡yü&hóÆl"€þkÎ H4)׮޻ï©uà:iòºzººÑ1äMëN®ßåÚ^¾ÁÅ0,†÷ß÷Ó­!ü¨óïzˆV¼Áœû m=_L”âÆ4"›_dTÆÆz¿âYàørŒ–¥ Di…|†3FØA¬Áéi’41monnxFzŠ4ÞÇ©ö,IóãM:&Geªæ‘³¶¡²ÊÕÞìqµ7áö ³•¼´\ç1 Y†-ä<>°sý{ð'ðÄÄGuÚ…è™/ÒßÓC<¿Aò³~…ùŽ4ºûmn›‘†<Á4¬ùH§«š|«ë°ÌT݈[à&;Ÿ›:É>u²iꔿM>5…[2ÿÕŠç¼ïfÿ/umû¨ endstream endobj 77 0 obj <> stream xÚS[pS×½²ì{ŽGP u ÷’6a2m‡8-q Åäa0Pcì&8vãà·t¯$K¶ž~nI–¬‡eI¶$ËÆÂæáqˆãÔ l034MMȃ¡u&R2C¦)sÔ9­”éô£Ÿ9³>öY{ïµöÙGD¥¦R"‘hÕ¾]»÷äþìÀ«ÅÅY/fe%cÙñQñµ)ñuâøšTrŒµioþóÏië(ŠšøAûW&±mUŸMýA&%‰RÙY›ž©¾¶WmZ_X_y´©n}±¦á¨ª©:ùŸŠ­ØDåRÛ©ÔaªŠªMi¢øDÅ•Ô:Š£ž¢vRÔ^jµŸ:@•P)”ˆJ¡6R‘L4•R .KýIj, ¥YÒ¾•D¼Z%¯ãÕbÜ‹e²KÕ¨z¤æÖIõGà :Ó8v„•|.ÄÍ êOñUÙtlúäôèò%y¨/ì ùüîÂ(ØÐ°í´¾Ëh6¶UɳK^(Î.i5µš¡u1¶º‹Â¨æöá?¼yûð|•ÜÓæ1÷u#=à 9ˆ½:ïžIyÑÙßž-šÐ¹µ}Ú^ôŸžñt¼ +¯+o(¯Ï>(Wé…VU«Î¤2€šûµ¬ƒî³y\çü9ùòì_./ÏúÜ>‘銕†ëòß}u*ÿÝ¢sr£ÓèÒ[Q;­iÕ6sÀ‡-~ÃJùüñ+ÇçùM}À‚$7ß_Äá[ï/Ц®Ý¿ŠóÄq6Þ"Óx'hCY¹í¹ „ú÷1ÌÜ Þp[Çà4ÂiÞI²È¦§Èòs²á!ÙŠsÙ«0™žt¹nð …]ËÖÂ[%{™h’é/Àé€Ó¦þˆ×áÕì$œRG*Ù@JeÐÓÝtùÔ§ó×£/”•4½XÈîþ‹ŽóHÒ±ˆÝX²k1sv óKyx‡ô<Þgd!kÈ4ó±fGhR¨ «žûkÙgÜÜòÄb£'&º&…èÀýԨУåZhé]…BÞ€ÏêÜËŸßÖ¯²«Aèà–Ηê#êáñþ‘Q²íÌÞuqåîK,\ørð|ï¸cÜ>HBT7qε‹7ð/½r33v½q ï_¿.}lx4%{KS{!Bá§,³_^{Æûwäf°”üp ›ÝN·C‡­…–~gP´Œ„9pÛÜvרnÜ<蓯æsn¦ó¤)Úõ9‚îþ„N[õi@‘Ð@”ƒso‡ªm‰d(Ûy“B/ïèêho‡Nè²uÚôN¹ô¡Aámt6ÊÎÉßÌACo}¿ÒÞîhƒ604ú.S·LÐàæûyd&2YBv·l`GsóÃ3ì'ôµGæ[ÉË]v®ž4\A‰š¿Çenæâ{ï}È~“Gœ‡‰)­¨x}*ßi›Aë-<¿˜iÁ+ö-`IòH¿Á)ñ§e1…MÍ£Õ³’­GèDÒ/ÆÈ,dµ’~Ãk ¼ÚÛå¾¥ÃA÷P¤¹OàÚÀÒÝg1s}–ÎZÕ°D03JQ© šÂÜWtØï 7ûøÿ‡*0 úû9l%” êÕD£¿NÀÛ:¥°±ˆg?Êtáì¼ä›JàÜø“ ãg•V»4æ&!`ä¤w/ÙRZú€×ë4‰6CΡ£Od@ïç¹R¼•†3ŽñðHôÔ¹ÁÄNŒ4ï刪šiÒ~¯*AÏ¢£þÿÒké;Ÿþ˜=ešªßoü­EÑå?áÐ’[ã»e$µuûæŽõÈÈñ=’‚3Ù>§yî>ìù¹,ÎÅ4y’%kˆ:ù“ЃîÌÝùŒµÒw`æW~"/¯,ëy6ÊïYn'M– qfÁ¡Ê<‰_Ë[’ưÙ83bì¯g‰„V5yÁ¯rÒáûd6›–W¶¶¨5ýº'9Áau&†¡¬žPÂCksr´›1¢ï_þÎ`ÂÍCCáà(+õ]*ôgkÞx#áí#<»(ú:9]ñ×ñ±0Pg« *F+/˜¦áCÐ2 z†ÂZ¯šûþœ2ûO°9t3ßQ¯ñꆸ‹¤‚þÕ>¾¸êXχ˜¨9XÃþ‚t¾)d s£7¾Ó…ó¼4 ›.öþ:cEoFº5ã‰Gé>ÁíêXãîÿkõ¿‹Î$V endstream endobj 79 0 obj <> stream xÚÍXyxSeºÏ!ôœ#Bc4^5©((‚€”E¶BY)”¥iéé¾…¤k’.i“¼ÙÛ&éžntIš–Ö–P)¢ ×™+08€¢Ž3‹¨ã\à s˜ÇùNJ¸½ƒ÷>÷>Ïü‘ó|ÏÉ÷~ïûþÞß»|‡àŒË!bÒ–-ë–GFN]1kæü¹ì»9ÞYï+c¼³¹Þ‡Ç22æã'ÈwþöjÀ“q~2û4=Ä>ã'á'g~\œÇbï‰çfÌ[ºfãöøT©Bm®iq :~òÒ͘]‰‰³fΜ5ÿÎbö,ÿbîÅ«wóü ÿæy3ý‹ÙþÅÿâUÿ"Ø¿ðKû¥‚ýº‚_ñ/üRÁ~]Á~ñ`¿ø|¿Ô|¿ÒùófΘ’žš±G’´.=>!+-hyzJ|ÐÊIBZ|Bü=b„ø38q\1‘ÂI#²8BÆ9Êù ççKÎWœ?—ˆ«œkc¯soqÎȇ8+8+9¡œUœ5œµœuœõœ0N8g3g '‚('Ô„†Ð@è=a Œ„‰0¢‚¨$ª+a#ìD5QCÔuœçÆpÎÎ,Ž“XEœ³tÌaî3ÜÜ/Ç&Œý8`^@;AÞ¤vÐ4Ý÷@ì¸àq”Œž°|âä‰WJ›ôø¤}“ÛÓx3xß=ü-ÿ£GT$^Ò$ESeÄ—h*MCÏów•¦g@<ו¸_h!{-í{¡îOéŽâí̱²²>ïä>bšÄE÷ÎàËå¥ÉŽìÞ2º§½¥÷ æK´(Ÿ ‡pÅŽ¤õ1©![kÃzâ‡7‘œÓðI›ë7ÆŠ TÒ6¥¾DXJÊ@“§’Ëv¾%Ù43I†Æ~ñyíh‚ÈM£šžøã˜<—JÕS(õÎw#µ,«GÕ7xÑÍ[!ü(ª*t•@75•¥‰˜*ε­:ÈŒ[ÄLg&þáiô‚è0 5x\4¯ ­>DC‰¶h‰ÌÔ%òþ¡)Æx»’:_sÂ@ÎÞ$c¹±L§¢™| JµªrÍ;˜»-}$‚¸zO{†SÛ_ÞÇÚ6nùò²>ôfZä&œØ²’+\4eðÑI²Î\QƒÈ°kÌLÑF+ŒÚ½ygÆjXM3sУ!ˆ'<ç[{Oš++ì`£õ”Ö¦0a8uÊ‚¬´‘Ò­°¶7dHz5`€î o‡Z»›:ݵ=pꦛB°Äާ/²¥ÞgAñ†°ú¼¨ð‚U?i - Á®µƒþìè—<5q넌#”ºg“Ž·¦'·+mhcE¼‹ã%ojÑ5C“#ìõé÷ ©Ãh „¦27x½ÃÞõü(ÅkÅêSEÌ|lëz¯K¬ó¾@2ÿ¦ xø¼Ž¸òl1$Ñ»Û<û;{z{Ò÷E ÕPj-ý_*n­•`ýãõ¸ã[Ç]ßz±o#ç7áó'„ÞzÒgß(|08‹§üe â¢XŒOß~ÖÀFŠ×ÕÖì3âõá3²X×÷Þߦ>ÿ&=‹OoNgÚP˜%BaY”d­0¬þ…Á,Ûç}d„•6ô5x#ù‘¥Ñ¥1™kc_ƒ%°±!¼?v8âlÎ)63ëÝ7PÞƒ¤Çã#/©_é!¦žÿ>Cº÷Üî–f·µÜàV¶fuïÒm€·èD ¢Õ[Ó%i  ñµ’Îl'ô—ïc6ynÞ¾å]D}èIkšhª1ÖA-|»øÈ‚úC¾1hž÷|Ë•v¸g"½Þ¶µq“~æá‚¿óùhm Z¡UÛ¬ y×e7…ÁfˆÌÙ™(Û¥MÀ»æ¡‹|ÔˆS<ïÕÁ-ËD€mËJÈÞ Ñ€ É•®ñò+ªñÙ÷ºˆžà컵”ÃÚFñ ¢ØˆlÇ< Bè"3DÞóÚ{ù&¦™¢`–ÆÜdj˜‹¨Æÿf$jJÏ-Îâ$šâ5àz߸µž¿G-…=åS ¦Enœ“°!'VÂÜŽ9¼~>M£1€‚½x¡Í¢M”MeV‹ÉÐË5ò†fB.,…Å-›n8^tÎÁgU—Oœ8|ä‚ã .üy®ãiC®À 0”Um%í“U„T•ÚªfCTh>¨ ¤ReÜê^ïxJ€í‚lŸ¾=µÌZÑ‹8A]ˆD ¸FyÐïL~‹y¯®èCÈž%SÌLl6#X|Eüµè¼[×½ßd1Wè+ …êBKa]Ò±²> ÛHGÁaÓXe"ÜÙõ‰PÞD£ š´ŽRGæÙ™!@g“¡O—½*âKv¤öwïmëBCIC¦ü:&”?ƒZ½%úõ¨·: á³o:oµép{ÔÓ#M×¶v¢—œ×qò­@ÔKèAÞõÜå’¨J°ê¬@7Ö«óDÌ%*?W#T€R‡;½ S¿…¯+œ¿7Wk¡NÍí‹6Wš­ú*f›«fÀxggW\u¼=N ôl&™&“˜cEŽxØ)EYR©DšªMú ²H 5"´k,PÕfSµðc’çõ ȶ®Z¦Ø$ʇ|\AîtHf.Ú&v{'8Qê šãƒöù»æVí¨W犀á(™i/,–ä«2ÞCæ2Û<¤é€îØ><µät´ôë{€F9ä>x[Û•Eó<}ɺ ¦´‡ÌEÛP¨•Ãc’\C­Œ:#iôp+7Òu†F¡¬Ú  ]ÔíðÛ/ðíõµ6ÇÁ‹W-—h#&­Ìt±ªIˆH{¥¦@Ä\¥òä 2‹I%(´JC¡Naü—x|s(ŠèB¯àYç*"ŸÂø º„€ï©=S ÂÁØÎ˜Úµ[ô‘»5)ŠRuI&»†,Ys.Њ²R…ÊtePN/¤äúâ&a hêMöÖ#GkýîÙâÐåóJ#E)dk´ :#(”#µLî¦~u ]ÌËT”)Šr’–$./UdefÊùÎBgò©”SɧJK¬™0Šœ(· ½èç';°Þ?rR–eƒ£XÆF.Ÿ\(ŠeB©B™Z†)Yä£äÏ6ÿ:JºYr ŽP’ü È2±èQª¾ág›G˜ø¯0ßM‡—]wqõt߯oñrX¨<#P¥’{rõ5# hô9v£7F´„´YXÙË?…y´ì¯‡ÙugÆe6²SR˜Û؇ÇöÕ ]&ó†|£{·µI,º]ñK·»¤+ýíüA5m#ñü7ù4š&ÎûOfŠ(6Dï¦á;·w<ü²iÏN(ØÑ–ÕWÎÖJ3ò)“ólïA o41ãWâ²*­ŠÝr šîZ5¹ßÿ%`Žï♃M;¤DŸŒþ"ÀVŽ|ØLe6¦Ø’ ´œdÆ1‚5Ì\æE4i1ˆ¬¤ÓÐikqÐÌ* ËcGäJörHyç2‡V‘-ÒN…S'*ÄCüßáV÷È´kÌK"9™¤NQdÊhäÄÞ k·|ÕâÄiÓ€ŽÝæê!eîz·ÕÝèdÈ¥~7n×ñmÔù6D£1B'¸ i¬†rC¹®ŒfLÔÎðT±p*d~£¸ÀÒ&ò¯Gq‰y°›hõq¥Oë(oÌEÏ3+äÊ¢B¥â±ìLIþe RÄbÌ9\6»)y–©Zf»Íl9÷Á`4Á ž©“é4z<ÁÓZJ£ÊÖ(Øí¹nµ Š âýqwˆ.7YÀæ ³Ñèî48êU¶*{uE‹½SÇVKfsUÝRV(ÒPÚ’¢•**BP¬Ì“ªð½¹Ü¬1Hö ¤­Ñ°êÍ-û(JIÑ«x][®Ý·¶ˆ½Bª +ó5òð>c+Á5\ ˜I©äOô\¦@¡V+44³ŒT¨ðAèkªž­ºWtTq\ïD›:^«F¦9|pŽhõü—YŸ ß…Ãö¡&šYJÉs|i©üÿ©~“©”)ù[cž}Â?SµÿMä¶Ëd÷â9òã}wÿÜ ¥z œ9ï¤ëך¶ýOcð9kÈwÿ<ó9ÿ¢#÷1öê€;›“`}ß‚&ÃW÷îûßÚ©ÓðG³ç#[½¥ šè ³Þ™'džE’£û Ö„õ,'½Û ¾ ÀO†|ÖÌŸž§g»·Òõ\CÝ]à~û‹Åø9 GüöVFÌ¿Hy?cµ$%’‚¼Ì”8 ¾ìn"KÊõ•"ÌÎí†`­kCóÜÄG¸(FÝà¢|”ÉOÚ’²+=Y•š©H`Õ¸ìô S›iÖÖV{]s{ÓÞæö†fÉb2W² >ŸMY<•ÝÉ~õØQL½È,R=½ÑÉÃ"4§¿Š\¿Ìôé¡Ú½ˆ}@Út%Å¢‰J›7¬EëÛí$i¢„ã¸Ö%ã°Œ§ÿà÷ã†+ [7ÿøð?ñŒ endstream endobj 80 0 obj <> stream xÚ]PÁnƒ0 ½ç+|ì4M¦í!mTT¨b›JÛ{H ‹T’È„?HQ;Ø’Ÿß³ýœÕ¾²&@òCN5 3VŽn"…Ðbo,K3ÐF…­ŠY Ò³¤¨¥ÿ’Br<NÕõ¹n>딿\Îeú»;å<{„l««}3‡Êv„`Éi™8ša÷¡]‹O+öMÉØv—¢‰H3yÃmÎò<ŽKï7)§qôR!IÛ#œç Ê2ghõ¿Þ¦h;õ+‰‰×raf‹Ü ]U«¿‡=5-{㢣u¹±øø“w~UÅø´²mV endstream endobj 82 0 obj <> stream xÚcd`aa`ddäóövò Óö vò54‰˜…ü±áTÿ¥ÃúC†á‡,ã9¦òÌ?ÄYd^ ‚Èçü ò±ˆTŒ‹„X9êZ:Ss J*‹SK Œõ Œœó *‹2Ó3J4’5 --ÍuŒ ,sS‹2“ó|K2RsK€œ…àüäÌÔ’J ›Œ’’+}ýòòr½ÄÜb½ü¢t;M…òÌ’ … ÔâÔ¢²Ô·ü¼¿ÄÜTˆóõ ”kiNjÐUŒö@¢‰‘‘eó¾Ÿs;7ÿèßÌø D2ÿ ÿ±Ytæôî‰Ýýó*{:åZº;:+«í<$Ê:žúÍÒÍñÛä·ÔoáßVòݺ›BæçU×tuD”Wvvv7qÔOnž.7©»·{ç%¦4^uø.ÐÍñÝî»Àw¹ïúòÝ/’V,ëé™8¡¿ŸãOØïç¢Qºw/äø®òý;Ów9¹oÝÇý¦6p,Ë]?'²;ˆã·ÊoößL¿åäºýO4Nãà+ŸÿÓqÛï¤é웹6s¯›ÀÃļr\,æóy8¿8,¥ endstream endobj 84 0 obj <> stream xÚÕ—{TSg¶Àsœó‰b)1Sè#G{uœvFÅ'ÖŽ ÆV õIÑúÑb§ HB’ì$äABDžŠ &‚øˆoÛ¹:£SõúªÕÑ™¶vYk[gÕŽµ;íq­Þ/Ö8íÜ»ÖÜÎ7Y9k¯“ïÛ{Ÿoÿöã0¢ÈHÃ0±K3Í]˜ùëÌÔ‹ÇOHL Ý›+ Ž‹&ŠƒÃ"…uÂùgÙöïÆG='1O†®ËŸ]ScéUô"½Äþ%Nô †‰–<;jlRJúËr‹*ÕFGËÿ™ë+ó׬Ÿ˜8>é‘0aê#aÊä°0%,„×Ly¼æ¥GBRbX˜&……°ž¤ðö¤ðö¤ðö©áíS'„…°ž©a=/ML;ñ•’¢Ò E^ùð9%¹yåÅÃg”¬Í>³J‘Wœ›—ûOÒ3ˆþ3V4>âÑ»¢¢>øB|7B ‡2H-zB'’ˆ†1 Œ‘11f celL#cgŒ“q1MŒ›ñ0ÍŒ—Ù(z:BĈ"DrÑ%&‚IcŽG¨ÄÑâ¾È쨨¨V6‚}›C“kƒ¾ŒÞ5Ø2ä·C~ózÌ©¡iOH‡~ÏìËõ ë+¿«U2(º-Ư¾ÕJk UÕj ÙÂLf€0ÿ=á LX‡Áetq9]!¾d¥Î‹½ç.ôaä \>p4qÕ²µ_[¨]%<íš3*+Y?Æ‘427fîYqxÁûÊK4fCqØœÌù²so–ížÕ2’aFÙÒ rIH—þ‘ƒÃ–ãý}›7÷yvÂ,q¾jUZ”PEŠ8È2.(Y­(Ϋ͇\ÈmQìX燽 áäõá’^×wœ‘‰H$_÷3¤Eœš-n ­Æõ¼ð9W½ÞX%Ó€Ú¢"ÇýÜ ŒÜ|Ÿ‡³/í]â"’àîçÚà$±r·„Ø–Ù$¡Pz—•|}ºwe&EšbE•¢ªÔ\d.«ÑXZxÌÄg¹MM6ì<+ ܽnñk©êE<-d7/nñãz™»Èˆ}ÿÚ—6?§‚ZÊ)«°mâiÁj„F‚7¸VºIvˆÝ=ænõA…ý k¡œâtÊ}DéÕ¿ “q‘Ü|²7óâx ÕõȞ硽6c:ЛuÆWã × S1J¶ZX`mí'|½DRµ½{wc?S%ûŸp®¡#™H8Km%ÖRj®©fFBåz[+åÀf¶SÛ;l2xÌ´±ôrBÚƒ_I½Ù`&B Û`ѱ‘X8°»›/ßô`ŒÅÄ˵9í­2³›† ¼ð0˜Œ¡p2ãfú1³§û™#Æß`¹ÿÄnt¸¼ß,¾'Lâ߀Œšì‚7W–½iDøŒœˆ¿”]úz¯ZmOÍ­u¨d`V¨×—¬ZR¹–Á²Žò@Å€éHo䵞O>•]ÿ,çìP½´Ö†:ϽNRÃËzq²??ÁÈ‘¢»øš¥û[ÞßgÈ}!É1KV rÞ¤7èÌÄÄR¿­F[¥'ÞШ³éhiÐix0Xho$Ó9•µ¾SÖ ¦ý}Û¶wîrÐÄ=ú~]jÊKº%| [³YEj<à– %üä;«g%§+æñ áe{Í£×¾©ˆ–U7è5|=·iÌg57àà0g'FYìú^˜Þ¿ÐM~áܾ¢)M‘óÿkäÀ_Ê­‡*‹ÑI‰‡&ßÞM]ÓNÞuºn—›\Íz£’nЄ7pu 6×Qxª)aF/†ahë|ƒû! q.pSómÐf²ii¥MaÞ…|yá2ùò‚ÅñtD¨Ói píí?¦èG³g›•qô™’ñ™ñ™dJ÷gÿŸ #¾Î×G¥²%Ž(É­ÖÖvøag™/ßJÖä)²iÁ/=û—Ïû®ó’ký%¾ÜyÙ*mÒt(Ÿ>ƒ#„øÁXšî…ý«÷a"=’ñ8á=@º:ŒJrò —Tp¦,cV]¶6GóV:x^~¹àRÑûÚV“·'àmèçå ª ÊjÛFÓ0[Hãj•ᬳÔÿ[p>â€ZTòôE ¸Žv[;]Óü8áî*²è¢½[‚K¥)õ¯V,O-ÏU-§53£}þÞUG–^¬:çàrû‘£{÷¶ý¢q²òÔ[¥ï$·Ò陎*mÿ~ﵯ…å>Õׇ©%êÞó¤9]œäNw—±ÐÌI¾NÍA¤â¶¯è@õaÚ¨âpÈ‹ƒ_þFx_‹ÖçÈÉ1NxV|N0H ³kÓÓ jêkŒÕ@V&ï<Â£Š³û.r¿SˆMåA:³þqñ>µ‹Ùj9ßÑ™L¥ªWA%vVúôÄÁîìÞêÿXxÒ¶ŠŸ ój—æg®,K…TÈh›»oå¡e”gá"\Þî;ksºB¯O­U+«g•`©Ö«ËW¼Uö&=ª%ròð^óý¿ÓìØjÞbðԻ–¨Å”5;ãp5Mèó»)9!…¶gÉ.8f¿~Íé¥s™ˆu[ Z^øW£6©ezV¡éUŽðsT¶PYϪÕÖM<ÒD§o™í‡}æÍ…Dr¾£Äº„¾<„¦ˆ”Ðôü›9“³KÇ\ˆ1WþoSK'÷)Æw`Ô}ᩎ üL` ÚÒª•¤³ÍXÍ wB•·J¦¦ÂmùÜ¡Éì?À}áGpwþ£ˆ<8KG²Øão¯™ÍC±ª¨bCYe¡y-l]ƒÍÍÕ4ç7á ëv/+,sp²h±'yÈ çhËÁ_F,KzÝN?Žï‡ý7¥kñk endstream endobj 86 0 obj <> stream xÚµW tTUš~!ä¾–y–Æi|Ï¥íѶ¥dUDhwTd‡„„$µ½Ú×,õW%©ýUjMe'€ꀲXLZ;¨ ‚ÂÐŽÓí ¶zlççµ§çV =NŸ3súœ>}ªêÕ9÷Ýÿþ÷ûïÿÿwó˜Ñ£™¼¼¼‰ ¬X¼|ù}¿Z\VöÀÔYÿ’›žý“<*{[~ö–Ñò:ù»ÉK®¿[pÃ0ŸNÊ=Û'äžÎ‰¹ç=ôÁÍ.fòóòFó÷Oòàª;UÊM5·/¯Ú¸©¦òö2qç&MÍ6:òWo&¯èμ{FýŒ™ÂÌÉ{˜Y’÷ó<³–y‘Ù€Ê jF3L>3š)dÆ0c™ñÌf2s#0÷0÷2s™‡™ùÌæQf³˜YÂ<Æ,eg–1Ë™L)ó$óó+¦ŒYÉ<ͬbîÅä1£˜hž1ïʨYù“òŸÉwä=zÝè¡%ªDÙEl5ž„M…ã ÅÂïÆ|7¶aìõqWÆßQ”_ä)úbBýDnâÀ¤[&E‹qùZMiRšb¢¸²à×_ÒwŽüÇuF¡n0‰ Æ–ë÷¬h.m^ÑTã(€Ž€' m8Ær-¯Ãñæ×Ý>·|¸SLÖðܹht5–Þ,6˜ :¬b¹ÝžÒ–Ò¦Rwm}Å+Ðëuö5íÂܵ|#g 9ë[ŸÒJÀY¡¨MMædÈÔ ™«É#Ó²O*DjƒE%S»piå©¥Hi2étSRxÙÖÚÊ`ƒ[1G{PÜŒAÜ{À°é&…ÿïëG©ÖPÉÇAЏc@Ó­1éjww4¶ïÒôiwiÃŽ°MœbQ:7‡µÁj©&ZÆvotwzo4âú AcÓò&0ÛÌŽ m¹¶BãéÈ-ƒã,„=„p›9ªáE0]:xžo^‹‹äB5 P\kŸOzšŽ ;k·êLuúЀ>bˆºâ–b¡ýݽÇà8>Vst9_îÔÖB%ÞÞQ»›÷ý¸‡³·px™Â|ÒLÆ(TÎJlÄ]U}¼µy{$èÇ»vv—ó9—Ù·iýѹr!á¹³‡ßšìü¿rÅ]ý_Î.«³&º¯»Èi…‡=Øv°ï@WO¼7Ñì/i ¤‚¤a‹èy˜­fûÌgf­šµzéú“Ýl=èiàío¯/¹¼úòª+Ï„íakk.+#ô’ê !°¬¿¤t_é¾'_6ùM£¸Ë’Œ¢‘]«Z[¾ng¥¸C[).ÛXb°©­ ¡¹`Œò­†ýWŽ^>~ùØÛ%’?€(Di6ù—”Ì:6ëøÌ£f¿9h¬7iriRÖVÛàÆ’ÌæÌæ77IvÉqà"k†LÏÙ¼}C$ùN~vÌ~…ƒU-éX¼¹‹'‹%6)“i½O#ÈÅHi6‹bÈœ^CeÛîœÃ¯€5oiÞ÷;Ãa¸øâ­©x‡ÔoAÿ_Yó©> ¸»9žȽlÚ&ix%XªZ«×î·z«cåþ ÀV$ßi}L~ä[a±´pïŠ=Ož\ù^=¢#ðr²¯¹3Ôd†¬Í¸5Å)²J¾eˆüdø{…¹š}Mñ'sË©¥ÉªÑ…iÛÏPZq{_AtÜ ~—pZ %®ß’0‡”|ђͲ¶ ý­v#vYs7JӘ܆2 Š§FpÐ2Ä3s‚Ýí¬2˜µ9gê¨-ÉwËkåÍdmwî}*H%La¥0lgÿ#g§4u…¥‘¬i¾hE~}}6©âzH¿Jqýn2‡4$Ê]œÔ®õiy®gdòLdS£ÃÔ`+æ'˜Ý´žñw÷³;â IžÌ@ÜÖX±dK‡Àõ@Ä14áºÒå\é®OP|w·<‡56ØL`ÄÜÖÚ„#A}DˆÌDHnÝJ‰{¸˜ ì C_ŸÂöŠM^¦¾¤‘hè4u59_F¿±µMÊ»R­¬0`uÔÔÉ“ ¨#*%ˆZbZ–/#pRެˋ™¼CDMIyVvœ"áIÒ†ŠO¼#Nd$?V-MûdÝya^ñ½÷5ü^hI©k·îru–P: M¬=mñˆ€5HWí¦®ZÜÍÐŒÉr®ÍsŠoA«g;¯JêÓéD"-@4¹š0Y&? ˜Î.šéX¿é‰øë¼›…“Ÿ¤|}-}M}pcïÑÍý9;VA1%|¬LhÓ|Rs;>?§¹”߆dd~ÈËÿ&çž?§ÛúŽøÂá8DqZÝläwh¬z±|›q <‹Ï5^Á-ìÕ3—®ñmЩºœ³•r6CØLñÞ!Ò4ĽF¾¥ù/Ï`+º6%_¤pÓ\9_.¸ã¢<š°Âqèoß³‡öEÎP¶¤ùË(ÑLÆ,’Jx&E)K¨šŸƒ´”Wİ9)ÈÏÊ_) ÅÕ -øƒS—¯ž:^öKÌ.3XFòˆ{miÙÂÇøy°î#ÇÐ0vþ4QdòÈ$²RAŽ öÖ@§§ÅÁ÷oݽ&úÝÐøŸß-•oþö~R,œ€LÛîC°‡Nêü"_ ZDuù& y.,yÓp »O+’gd.ÁØÿbøIÍmõØr$@3¿ýª4SL–q¥Ù…йˆVÛN«ÆhѨ[mIáyp6täU&Z‚`š¢˜ìEí4Ò)S Føg2HnF‰p$Ú©nÖ òÄèØÁÔÏ}Ú öõ/N%cÝ‚ãèsÞM° ~Q¡[Ü`ú¡½N{Š,:yêYwªESÜsJ3D~9ôò)î ËÈ kÐ9+©&¨ j#µë4;Êà9,³dJùþc ?ÚçýûY‚å±]³ø©è]ò%Á˺}M>¯[×cÛ øÃ+o~%À.Û.±£+X²ÇÛ¬˜pkâ’'‰o oã+ Ü¶SWßX__çÂ.d1bhÁÜ7Ñ+6ia<ºÔ9ÛY¨ð¯ëPb³Ü®à¾µ¸šÀMøÔ‰ž£üçèˆýšfàÙò›†/…Ÿ´ÙÏäV8B®+ìk¯¼~œ?½+±}vÃÓ«øÕ°¾ßùÆðœ=CP¦8Lî[’ÃÎ}~m˜~W³ÜE£Y¤¬Õ.é¨vƸ1, «ÉÌ·vJ¶”Šf’OP¯Ø,ò2¨Ø¡ Y;§B%Öjj“µmIJŒ´kÚ«iNäÔ[#|ß„²l†ŒÏÐtgÙ n€0ÃØËXîÆlÒi% ôJÆümÀÊ>D^ eê÷Ô~«Òl¢-A«ŠÛ)¡Ñ§ÍI`?àöH®ÏêRS´"ÒCCÐTw•ÔöÕöÕÐ_I·Þçôb7 †¥pøÕC%‘Hk*؇¼tJé‘6oŠò\ÌQñòäÅ¡Ñ:”ú!)@òtùgäcrºÛÓöH%ÿ(ÒkœJšhI‚Ìši5+)›)‡ÁÉ·±Z›Á‹§‰27ù%[ý©6c V¹lujs‘|éU Õ´…&ègÈP¦¸Œ*;A&æ¾Üçÿ•½KÑ-¶¨ø‘#0#­Þ®¦¥0Ò3â>ê•)Ý;s‚û\£·ªi(“Âgô’A#i–”ÂH{#Rîõ]Œ¶¸sÜ_²í‚¬5°½]EuI»ð)jûþ¸U—‘=iûx&¿ ^Ti+è½Ä²wk¼Êa»^¥a¢•gþ§Α‡²ÅŠ(ÛaðkøÙœU3Œ€{ë¨<¸qÿ Òé='CÒ¿É'Ùe y¬nÑ} Â&Ö{×ûw’ €CˆŒ‹œýƒC¬ã›_F¦£r‰,* ÙÕB;àû'?úw£ËÇf,˜·rÚl¡Íó­}ßqžò]u†üü 9¢ìZ÷YîE{³"Ħsrè‡hwôO=í¥ÿí&ÔWþ²ê0 /¾JòúãbÂÊ„ça¶¼·ü„¹àéùó/^wqP€;A kŠÁ=úæÕƒÓóP窣·ÕHO¡¬X’Ó+Uä[…k  éŒUò2‹DÑ¡Rç6Áu|$R…µuX¼J¦Õ!-´÷·Ð”ÑáVˆº¨&ïMx;ic¤*EÉÒidº|„ä“q·~_½ØÏNßZÌíöU» TCô4Åã¶Íé5ÂfwËã››·ž+35SX5P~@n'yH‚‡ðy”KÏ»Ð3°&¥:…¹ kÚÛ¸ªNšìNºwV‡LI¾¼m-±á4¡ša½ÅütˆL¥µýSÚ;§¡Z³E£iµ%„ßÉ"z*8ÜtáâáË|ˆíÔyE¥Õ¤äìšµêÍOé^:È ™ÁÆÛšº„aÁH%Ú’OP·Þ«ÓêU|QÝÛ¥¹ª(¾6\‡®åÈX¨ôTÅj;7µ„p ¼»sZÑ«ïæ/¡TÌ—N‚ZáY2„èMÌ>Üf Wòósd²S2¦„còzj—Ê,ª¶¬7olB[<5az#i¶Ã©ægQõBÅ{È”ŠbêìØLÞï©ë–Ú`­_ùª|G‰´>º>¼¾uk°® %Üq¡çj×ÕÞ«Í¡æ '„ûP:LRa_#Èã‘ÚhÑæôºÐ‹dF>'3ä\A/Ê ö¸…6:£ÆlѪbvÊ”ÖPvA€Ì!Yãeù1ù¡GÆúÆqû嘣cù§¶+7jë§ýù¦ÿ7 endstream endobj 88 0 obj <> stream xÚ]‘Mnƒ0…÷>Å,“E…!)É!$ýQIö"c²Èíë±i]`}~xÞŒŸ£²µˆ>í$\ ´²8Ow+:¼ šÅ ¨A.ëίrl ‹Ê·Ö¼·#BtIг–“ôíåz©âöáÀåa’u_‹æ1/8ÖºŸ Ë@ôåüæÅ>`S¨©Ã-iV¡u^°¹–Wš»1?8¢^€³<÷vq˜ÈµÅÙ´m«oÈ2ÎsȪ*g¨Õ¿ÇPÑõò»µ,‹Sw2áñ>gÙéì˜óâD\y>—â}| >>:{Ï ÕŠ4pJ, ßí´û뻎XÒˆåkpãä\8I 'œ×K°ã«W¨¦kQüÏôåÝZŒ#9¥3h|>£™ Uùïm°’‹ endstream endobj 22 0 obj <> stream xÚí[[S¹~?¿bÞ6©¶î—­­T6„Àa°„l|À!®â’³µûïÏ×ÒŒF3;$TR†Q¤nµ¾nµZ3¶à+„.Ç¿+¤õ…”…Æt…ѼP¼p̲ðJBœ1ô4(+î¹ä…ð(XUÁ……Ľ„ …{iÑO\IS  ѼàFØB2­à V(ÁÌat”BËBr¡ MÊxQh°0‹{Vî í<ĉR¢4( ê!B@ËP:VX°jhA¬Ú™Â°BT‰q‹S…“(1ŽÓèÊ¡Wa-5{ô´ºÐB±Â30  R«Âeеp¤3±[tv`£ÎÀ¡3>‚:ãOB=Ž ¼.¼Q^áU¢ÊÑ…KTX6à„¼bÔDQp€pÄ‚Jæ-]!$¬„?.H"Xa*tçÉ5YŽá€Gæ ìdPo@A¨ 0*(‚‘n„"£Á`f(Ósaƒx $À€À¦HKKN}1Q.¥¡Q-5æâ¨ÍÀ¿ý6ܼ¾šSkÂ÷‡›0W$`H¼ ` "AEŠ&)Ò=RhÃh‘äY$V‘”„Q$aIM˜DÒ _¾îÝ\ŸLç†{›ÃÃé?óáÖåä|:ŽÅz,¶>¾|ùŸlZIå4‰Ýsåj•Óü³ uª^MýÑ:&Õ:!ìÖ·C£GëCHÖ­nS;òÌGè‘LÓK½ b•4_wÈLÍÚ7“šÕ-Ó# ž)”ôÈTïT©œã}ÕØŸÞ^ßÝœNo³ƒ Ã¿L‡{èËÍôjNÁžêÇз·D{‘]/a—-vÕÍîz²ÛŒ=õ¾E‡;ô-¥·gg` "h“ëXÊ~Ó–¢›}™ÞªÅn;ÙïǮؽ§-ƒÚ»Wpš²oèªJ |¼‹†îLÏf“õë> ´K8%Jqã›éd~}ó¬8œ×wó/wÐÝ€™Ó¿rÃÝsrdz»Óéͳ³¿g_Î>]þSüõ “Âýõüy2»¾Ú˜Ì§Ï6~%~f°%‚™ûLþÂØ/ÏãxAój’a.ãÉ|rq}ŽæØdŒŸŸå+Ù@/¹[öQÆ×xÅ·§*)'å•þ‘4¡ž¨Š#СwUCãúÄkµ 4Ò‡}>š–‡>Êù8^Yfz-Ôü´®L+ÀÞjuÞÆúê!+¢›Ð—zÀ³–Sq¬ª¬¨Š£®mÜ ì¢|ØÙÁ_¢>ZòDV–ϯ?-»Â掷 ¶N±Ð לæþYÚ±T8_$šE{9È1<Ê ’¼MÄ¡?Qô{jÁ8x:VZ·âlŒ‡VO>À¾®}¤3¯ÊÛÅW0‚„®Zb¹úZIŽœ½ðVz C´ZÆQÉÊe&TvmÌ€b¡ –rÂ…û¦†?âGk1På5âb™ ÿFpèŽã6ùE9?Ã,lëXYÆ«ç,ÑÖʧEúoyŽL%#³ wΫ¥†DE uÝâÕAÞ9‚„¼•8ËÚ`­¨m¤ó~ŽÑú‹×rÞÜeZô@Ä LØë,úÅk˜M¢âÜTXá½±ÞW±ö°0Š˜«ìãä€ô¨¾Më”vfÒ‡b²‰+ <¨å¼\ÉX[žsôŒ³§µ.{÷òÖ\ÉŒ×j¾qþR’ÎÄÕç¿;«ñÏù¥äUF’W9ô¶.â* EÍeð>â68Ëø°c ±®â’†z‡¹—Ru‰3QjªVªXU0JNK\"õHˆÀ‰íuÏØCzÚ¤²°ykTµ”ãIV9EMÅ%õ¶½ò¸bùÞ')$——Øêxre%]¹¡–XdˆhB]H‚b}ä¬úˆ’ÛqÞÝõ½Ñ>!¤ÑB Ë8»’} YS «Ö2p{Ié³·Xôh‰ˆ”ýb¹Š G²¯‹3ÆtäýD©ËdW«¼^X©ž² _\×x µk½¡·,rræôTw¥%±–;Ûr¸8‚£ÉºŸf«bd=Ûî~Um»lJèªY¬ï–q5p倘ÓR-¬Hwk¿¼ÍxÿàL†â²[:R¤œ6+÷ÁWö-z}Lo$è]Øðàîsº¡>üsv6ÿ|Kß)o·f7·óñçÉ Î´Ã·“’Z _]^ŸÍ®Îétx+pýîj†ª)¼'T¬On§AþÑèÕûñ››û;Ü ݘޞÞ̯̾oèkáõYC©º}8ž|y=žc UÃÑí)½o1^©ÑkÜËáÖ|r1;]_L 6<˜O/œ†›“óÛ™ëô.e[U¬IzS/•Åîï?†ÆÍÙÅç‘òå*v'—Ó¶ê-%— g[È)óPäö7övGoãð‚±6rž=-rÈ`Ö¤@ê­åM¢œk"×R½r¾…«“5*‡ÛÛ‡{/Æ;ïœÉóþÈ –a 4Ö¸0UB+FH,Ë0‘¬XóZÓ×>4Îx gÒ¬ I®w/<4o{’Ï=IßÓFÇG›;‡0Çú1WjÑ“DØìã=I`ùa Ò×j´€Ít6Ñ„­¥z?äd 9!ŠÜ»íí7ÇÑ‘fÜFN>ñtÕD„n­A­šÈµTï‡Üª¸Ï9Ë–áû?ߎÆpç-¾èPêëÐx•â–/F+:£(ÖDx ˆhd5k`ÓŠì íû!ÓŽë\fÈ^#óûhüfë²÷;€ÑߘÊ_ŒïðÅ*H˜_€¤²sµû!Ҏל=x™¿·÷Ç+øêáVç23ßz™5ü)­µ†?yU­5ú¾ ´9x¦Ü[ú÷ÂϬŠï:s¨7ïF£Ñ.YfqóßËŸ¬éð'i*²¬íO¦¸3­ûÁ!ÜI/‰=;ë[[¯ÿ«w÷}Cër¡J\ æ.­°œ+¿˜z¹˜–+¤ÌòD©ÓÉÉû½×1åèEþ»åJËIxäJ&`D¯#›¾±MŒŠ÷ó×öž<íÎÒÇWû{G¿¿}qü~¼µ?^£/YÝ]¶¡á¬wj;† kƒÒÈ„…\…p² ªŠo¢Ò¥z/p,kƒ#ò½ËfèŒO^½ÙÅ£ƒ×KÑáO‡Žá])ýçÐXÞ‚¦Cï~Ј4²óбw²¿¹wÒ,â!¾×JÒ‰‚§o†KA_©7 \d—\ï~x¨ö¦¤º§ïŒG¯CþÉüâñ•¾$ÿ¤¹3’Zl§†­ýÜê&n-ÝûAgVœü9·÷€î¿o¶ßŽv(8솮~ÍëM«>A'±ÞãÀFqJÓ¯Q0I§TºVìnéÞ:·ò¡É}¼îèhgýä$ž;2IúÑÅ“žu…-ϺVHx]3е|K÷¾ÙcyvàÚi¥ÉBšÉbÚööïûHøwÖwx‡‹Ý#åÖ ó8s®Ñ#%!jÆy×J*:÷r-×N+Ë]‹ßõNþÜ}wÍ#ºV¥}b×’ÕcúA”hdT®•u¶tï]ûa€Ty@s÷€n}}ws'…îUéž6 1:Û~Fiú\ëYAK÷¨$ͬš>ðº]ÝÎÒýÆìÓ§éÍôêtzûAˆáôòlrûypú/&êÙðünvq1½¼ž_L?Í©¶®¹¡)†ªÉ§Ù i(vŠr‰ò%X¢x¢°Áùº‡N”)ÎçÕ]’&R_™¤É$M&)¥•¤ÓyÝ×á.õR”Þ&‰ô+E‘ÚL’`L¢ÒœMÒÒ$-mÒÒ¦ñlÒÍ&É6I¶I²M’m’l“d—$»¤­Kc¸4†Kc¸4†Kc¸4†Kc¸4†Ocø4†Ocø4†Ocø4†OcxK?ù?—ˆ  endstream endobj 109 0 obj <]/Size 110/W[1 3 2]/Filter/FlateDecode/Length 302>> stream xÚ5Ð;/ÃqÅñsªÕÖµêÚªûµnu+ÚªK]þ!‹Mb‹/€W`°b”-ƒW€Ád‘˜Ä"¶âä±|òÍy~Ór9D© ÈÙ*Ûe§ì–½2&äŒËQ9.rJ&eZf5È´×ÚC„2Ö”…DâÀ—,–srÈnÛ5Ozå¢\&Ö’vuËbóÉ–|é—EÒ'ˈ­{{SNìüw±ïXW‡çÖUÄñ­u¸¼°®&®ï¬CÄC̺†xYµ®%^}¿?€·3[êˆ÷Gëzâc׺ø¼±n$¾âÖaâ{Ï:BzÖ­›H¿ûïoöDÉÈ‘u3=±n!cWÖ™<µn“²KöÈ>Ù/å°‘crBNÊi™’3rVÎˬ\’+¤ó üز2{ endstream endobj startxref 85468 %%EOF glpk-4.52.1/doc/notes/scaling.pdf0000666000062000006210000012261612175147600015745 0ustar maomkpasswd%PDF-1.5 %äðíø 20 0 obj <> stream xÚµYI5¾ó+úøž˜6.oåfA HÀ$sc8DIˆ‚2‰2òë©òî~î·L‚Px=Ýv-Ÿk÷ôn‚IÒ0¡šåôìvúþzú★;]ÿ1X!—i¹Óõóßv7Ì6òF;¸ÑÈ¿j¯Ü.¾3ôÎò;úgý­â{kã{c÷³ÅT4ýÙ^aÚÈî•¥yùþ÷ëŸH EbˆÅP é§YK’0‰#¥ šApõ1 i£p,L*“(ë Å‚îÂFh©J©ÜgDáåêÂ>iIú8½W¸‹È*$ŠÝ))=?ñ{£÷v"Q6Cãe0 œšf§„]iØ3ìËàË%€;Æ4¬‚¸“PÑP‰¿Œ=ï@¾Ñ·Ë'’hÕ¯Qz; I/ RÅfHXõH?­UcYú$­øñ—_.k“†¼‡5±Ä M´Ö5ûYO#æÝa§Ž+XnÇ»‰ &|,”•¦±†Œlø¨Yb1Ë/®X–žOM“¤£‹+°Áhg„´ÁxøÌiÙ‡´Ì7ˈ'<ùó7*d‹V¥ïÏÒ÷¥Èaù²QˆëÁv'Ü4çÿìwB”mœ<ËG‘W|>‘ž`%"È^Fæa 9 `ػʊ¯R€ÖÂéÄäf7û!â  Á6-œ§òã³…µ¬8u*y›àÚŸ TC•¸•Õ–Ê‹@Ò˜Âd P¯¤ÑBÙ Œï4èUvSYr#•9¡õXýÉØd{z?b3Ò¦‡vQ•ËØœŒ€­Þ‚–×FlÕ)lûƒ^) ºõJŸí§k6ê,6ê¶æ¤ÙÒïq»Õ–3C×pÛ2S˜­á†l“† c ýr¤ÖŸ ØÒiØ £<€!·ª˜K¬Š'f úêeIð1‡p¦É«øÙÉU. ;B&´ñk kÒo—[¯FZzKQûB7³ý!K¼–F­2rÊœFׂÏe ![Ïý¬´žÊ4Кtš-$¶÷‚d!ºÙ¤>Œ5®&Ôµ!¹;W… …B*–¸Œ°¥8šAq±|@ 1Âu®[˜Õ+Aàî UkV´I(“*$—ëº(dÞmT‚^¡¡ÏõØHípžTc¨må~ËÕÎ¥ÞvÁÉ.5ÃGd¢$ÙÖ²‡Q…°@ì #ÊnrQ¦3"üÖý:S/LÉñ££ÖBšî¨“B¥ÄLΡ•Ú­NHÖÓ¥bs6ïoy·KM‰ì;‡›…Êxuû®$n÷hŠ\ØYÿÙ•^Â'}4™Å†ú”õ%xÕæþìr+p=¯8‰‹ïís4oÁKæ-šÿz€àê\+­ÕåºD;L#‚[Õ§M ”ŽVC…ã…»¦¨vC7p‡ÆžÍ2›)šþ^i»6ªwHÁ±±­T‚µØÆbl­`¬ËÑoTò*”}MS8…ÜÛn>vqeºÒ jédJ/ýîáõônš2ñ?“±¡´°‹åÙß-ehês–òâõôdz”®{5%ž…:KÎ@>Üö: Ü1¬.BÁPâYœ‹˜«-|¾„…tøÎ4šÈ8ÌPe°S.`U•Vå©2¹ µöˆëe*ò*3ÓœYcé¥uUõ&0î0éê6ô2r‡³¦¤D šPµ÷v·!Nv«âû–›ɽq ‘2‡ŒD²Ñð¶ÝÃùöé«×¥Ø´õ4œ«eÅ×·Oß~G •¸{öæÅßâîý·ƒó#k(ì«E[o×Á—oÞ‹·w/G¤ȵ_¾ÙWmŠjàØRñÙߎöE;ƒÂÞKK”¯B…bŠÑý‰§ä®›õ®í*ë µbßÔÁñ ”\™é´—ݾ½¬ÖQ.¾ì£¦Å…KÙʬ>d~ôÙ«ª" endstream endobj 24 0 obj <> stream xÚÝZKä4¾ó+rìãG¹lƒö°HpàÆÎÜhN œàÀ ñëqù'íŽÓ̲B«Öf’²]®çWebàþŸŒŒáÃÇ?†o_‡¯¾×ƒàÌq7¼þ6 d‡53zxýå§ÓU ~U`Σ{ºžôõœŠ«ÒÊÔþþou–æÿFy¶êt!Rz…†^yr<ÿüúƒ_ÓTk:ËP{Æh¹÷é»­¾ Á´Hßß5Æûï6ÿ¾«Á0gè«eÊ Š9ŒÛáœ'Á 2íÒ"•ƒóƒ}6L›ad6üÚà`”ÌÂ0*&â*ï_nØšé'بuÌ(Z$ÍÁ²p… ‚•xJzAþ’t¤<õd ýò(£‹J’>‰Îx:äiNúÔô£w:™MB^Ï—Àî(¬f üÿŠél>:p9@MfÒðuC’Z0ôH?AÜå߉ÈUR’^ÖžÎÎ4^[Œ×œ\¦¸c3Z®Ù zq{«Ûi3‚)Ø`5fÕjgÄÜXM™£+ÏÌ„3ú½’KK Þ.¡t4…0ì+oWËÕO¢È‘’Ì6ɵ±eÂ&n¯§¦ÔdI·Z1L‰ÿH+õùÿ …Ë Å&ó>/miz6Égï “¡WZ¦xÖßN©õ4–HÜÌKcŠ¹Ð¿i„éQq`<±!çF1´!á‘SÀ~þ]74º¡qÝ“çëÔRð$§…(æ·ví£†è©Lw¶¬*V^š[ª¿e±æîò“¹ûýmnèó$ÒŸŸÛøå( »ÊþtÆ>ǃÏÜÜ‘N fzúbxD ˜QƒˆyšÐåoBô^'4`TBa¦ð•¾ÈŒ*âH£<…à‰" ÆŒ Í›=ƒÇ‘aB+0­ƒeoEi¾¼Z…pE^‚™"!‘ ‡€cÆ :Á d#… î” X õêÔÛdh B&uøGµCàj .`2¬®ñhƒg€ŽõKæÜ^ülW°fÊQèNnÍÍÛè¬r!í –”RÀ±ÙŽã¨Ç7[Áq¦ÎF¡*p,˜Ûƒ½[“&lüûœÁ–Ûl¼Àru:¾r ˆxÇ&öáco–"â‘ÿˆ½æ„÷×V€³²Ì&x|«;ÏÊ +鿆fYUJ:$«kG£m˜Àăû¾´¡„•äîˆ EÓ{ðÿ €‡Y©@eÓZ1eŠìbo ”ÅRR@ý<÷«ÕuK”m±ëÀGÀbyŒÒ­ÚÎ+ºD3[ãVóɶ}4˺Éi§[-y!M½[šÐ—¦x i.Úf0I3âJ$NVH² ùVÏ4ÜÖÚðm#Â:§j§b­ŠÕ ¤WÅ>Ý'µë}R¨bðJƒãq-ë"Ü«98ÌÆ>e÷ùHë8¾?N½æ˜³ gÔ»dÅî-æZ¬ÌÁ‹˜¹[€“sͪ«nŽ^§¦,ÕHX‹¬¨;ÈMöAŠ©¸žl¿ˆ„{‡¡6ŠHó@©Ež©]D–uRDo$‡ø‹¥_ÝqÞ<:\®PᘧÚ.ÔP‰"®N%e˜O%Þä4§æŒC³ÉàkwN ›3iö{¬íž¿ÙÏæümó6ô<ù©joߺ±ÝRÖ>Tʾ冧¶!8ÒE›I¤'·îÔ³æá©%ˆƒ:Cq¦µÎ¹ÒJ_9=-;C¦ÑJëÝé ÅÙ8í¬Dõ9ÓŽö”g+«.O¬ã}pq*Å5mi*”æÅõ=—AÓÁ\=Ê2.h2KmcSÎ üç`ÆÓâ‰`i¤IM ¢ ^†OÔºeiÅÍö3¦ŽÈ­¸–v•9”q¦;Ë‹Ôw‰ïs°‡üf:vÌÔ“mîe¦ÈÙ=v‡Ú<,í Û* ²ACÉMT6-õiÎOà/Úôm4™Ùk³oNø2òή‘2¾¼²¥çÕ¨*=ŠØ–ÄɯtJš(çÝ/SI«öš©K¦e¶ËÔ¯Íæ¯ë´NÔXY4&‹¶+=_½eÑiν@ŠDGÅ™±‹;Û6Xš‘iº‚òSytñ*,ÊI £ /覠¬¥¡£:ëಪ±.ÝSÎð‡Î.i¾30Ë‹PÚaÉd \FLV©€ú$¿ÁÝA‹€ì'é-܈Á;Þ]W+ù–-IÓðy—Öûò­‰{~e¸IÇIô\W³-ÕbóySæ6þü„õõ=Å^ë+±;p)uºÇN¤Ûl2]?š‰ÀÜ^þ)Y²Þ›À;MlbÌ`6ÛèÉÕˆC|‘®v‹éjwÝÊ/¶Ÿ(êàß4™^ª.PvŒk)žE2¶§ùÍšZ¡ °º€8ˆ¦ç±K/<å±èr¤‹‡gùϺCÅÛ[¶^98ú üÈQ ûÁæÆ{,«¥à»‚]uH-㊄]–Ïv@?’µ@¯ eÉ'­„h.¦ãË:ý(PòA[V±D ·$ £Â5ñ¨G:f]Šíôþ»×áÇ/þçøŠ¼ endstream endobj 27 0 obj <> stream xÚ½[K#¹ ¾çWTn6¶­•¨wæ°²@rËtßâœ:»‡9ä–ŸQ¢TR™õ°Û fÜãRI$E}üHª§ÿLj’éš9ÞMg…·Óû?ÿ~ºj0WmÝU;™>ÓÏNŸ­Iß[}Õ^Ÿ/ZºSaTeÒ_é;KßküÄ‘áTæÈ#ÒhŸGžÁŸÊw8ƒ•´¾ åû¶B‡é’”)"üƈpΦŒºOÏþ $k©NÑìJŒ®Z€#YÙeL·ÌkΤڮ9–xcÌ‘«ª>ÁoÌÝF¼rzxᇚ[åÆòÜ>Õ›~°A< …ÌHz‘ý°S~ø·›É)âvÔJØÑÃôRªC²¹]=‰ê''ÙE`6m¤ b¬:u€=bàS¸¥•‡Pº­Ü¡­ö^9: )ü§JìÛTWTA4`—'ÆB‰Éh¿d)ª—‘7y+Å‹’ݘ[–u­Ä:BDò#·ÌŸôjùåwÎY°\7‡ç57 ‡¼;l…˜É•¨–P¾ "­ò{.ѵZ:óâ@Ù(Þ6£Ð<µ,Öö 2©WÜ@hO*•[1cIhµö®¶‘÷ÛÖ§{{mÝKÚÈ&0óµ¤ÑFP ¼ÕßúZÜK6ч‹{¬ú&)¼±5v£Jj³±P÷Ê}ã8‰aBwÄáQ0òO­^°5(HçzÎàa»p¬âÜ·’™›ÊcªËY9¬\)êº#EÝe‰XÅŽ¡6FЗ‹4œ7,Úö:Ô“lª:4ÊY¥˜uZï\ÝUÀ–T÷¬6Sàz´m§UF"–‘˜ÄC®,†õÆäŠÆFËgel~HLˆlµ?ŒÂE ~ÁZTÏ’‹¶…Vd²> stream xÚU pTÕÞ›Mî9˜bÖÕøè½Ô™v*‰‚ÊÀB )„‡´’w–GÈ&’ݼ–@6ûüï¾7›Ç²Ùd³BÜB$Ä&Рȃ[p Glœ·è…÷Úöq ›ü£tã]_ Á«Óƒ áÓié©(Ø ê ‹yÐYš  O6¢•Å ùœŠ<D/(»Fy!rÜ·¶{M`í݇iüË4þ0Mh/ Qi§Éû®øGNYcä¡ß‘Y.¿§ÃÞ!L~žZTj.âvªˆ*XÁn«°¿ÄƒKpƒó(—Ån|°Ï¶_Eïaµæš<š79F·E>njÓZb¬^Ãyß¹8!=ÅÙö݈SK¨¾§l8;´ÖÃÚòªlCƒ¡êqE{ÝžN_ÛžÎ:Ÿ†3‚Áb´`RB%ò¬(È\jÀz6'oàø‚Ž\â§ ·«¯®Ò¤ô4gIï9Ù—£dBîBðAà» ¯÷{O´½Ü|¬Å?,XA\Øa²é¹ZPÕÕ蟭Hß™™;g¹‘>³ñD%Ÿÿ‚Ä“¤ Câ9 Ò§‰”"'Ö± á‰UUKðM”ËÞ·(:7¼íýâƒíNŸ½>‚¡gÜ‹„Z¡j`ñyEÎöÒMÕ XyïéÎcs+´š[ñÚ=êÈbMÊßFɆÓùgDŽ"KäZê šŠyú6R¨L\iE¯Ù?8á™‡Š­»×ÚlòˇZǺá8„7ï-ißä+Š/¤åWD®ÏŽäýryfá¯øål•Î3À“Ìxr'ê´BÜq¶‚–îzñ€®úÝå¢.2VpÉ‘:S¹¤a"’Q)I‰iE¡ )—‡ ã#%Oi·”l,ª×´ .º4ÕÏÚŽZÏöö†zAX”Ùzömô®p*m¥V%ö³Z²4¡–--·åÉ9t à:Ƶ!zÛdª¼Jk¬ãè ¬^0ØÁ žV¯Ósæ ‘Ãw8`÷‡¸ÏÙ.p6X5˜^Ez‹!J×ãËmêÈ: Ó?AvŒK¿!;够õØ­Í߬ÿš&Ði‹DÃðpÿ[4‘$é±›=o Þl‚ ìÑR¹`,×7TåålÙJ(ñVVÞƒóXðÉ­~õ \€¾§YÖËkÃTV£˜u­¦S“B&N¯?# 84âý4§ñg4Ùÿ—…ºÍ%Xv¾±µ6¸°™5š-—`~Q0:ÌØÊz¡m|OWoïÁæ0ŒÁuîeØ€Ö¬TlàV±MM榦fpò!VÖ÷Ú%íìùOU¬ä—ÁŠÎ†O°Ód׌F=¹ÝÅa;ڰq>ué÷\÷çδc±ˆ×Å|?J Ƥᛪ)Ë׈JTÖC¼Õãñ8]ÇRœ:uä5§Çíq4 ô@êÖ¦Y×PY¹u'o_/ÍÒ¶ P¯YÁCµ¢¸Fµ5gk®øæ¤êu†]òRê~gÛëboDR8zK$Õ¨¢Ò>Ä“ RH3ÐVsÝŠ[åõ¡`Otó´PTòÝ®‘h–k=t]Ñ~—U$KN“ê—ý fâûß…p/™þ>I q_L’è½—‚üÿîY±IÖ#W4ŒØ±­ç¤ƒqL·¢½ÝÆ~2A“8ŸuXQnVr *’¬eË+mý¼@ÖîÙ8^yîŽN“xÏßò?;Xíª¶U‹ïyeU®åTÒFõrÃ’"šøà5+Oó$×"r<~þ·ã9DSp7öƒqêêƒâ½#ä{¹Qˆª «µµõîú@`w{Ï» ‡Ÿ£)Kèm3iâG÷“üœñŸ±Ú‡Ø6d7 &±) ÞÔXµ>·(4 vÔ´¬¬ùÞăäLJ¥?çÆ‰Å¢Qi¿XÔ]ô‘?k^íìêèê·÷`ƒBu OÏ!¨2¨KM“F<×£¯ )J£å>‡üBG`'à@­ƒ&‹Óby$áf¢ñ¢PÈ\ÄÏCË^ß~–kaÃîÀôž©¿¡©Lù·M+êí5åó4•Ï7pUìú¦±~þ3dß×'ˆHmâo.îlúWÖuÑçæj½úÔÍe9uU›5JN/JÀ›a³y àªjÇ~ž¼‹úÜm§þÇ`”\ï‹,n!¥ÖŽK7º7Mê}&)Ñ•4MHšþí´‘éÜÜ'Y…B±éÇ;þ é-å endstream endobj 33 0 obj <> stream xÚuU{PSWÏȽ(´–4Ó¸cskwÛ­¶µø„Zw«H-”ª-ŠUDå!(˜„@B@^äË;yA ¨ Tè‚XK™Z)Õ­­twtí®ëê®îºmwNèq§{£ðOg;wæÌoî|çœß÷}¿ßùVd$‹ ˆ…©Ioe¾¸}sú–+ããÃÿV‡–²BËæ…^Œ=‰·à+‹£ô?$E=Íb[ž¯/<^c2+k³,x>ŽõAÌç,~ny†Ôô=„µõŽ®œ‚ÂÂññ+fÁªø9°r¬]3æbÖ&΂„ÕsàÕY8·=qn{âª90œ8w`bBüòU›Š…%åâüÒg¶È/=“^,Ìýä'“IìrVñØÄãw¾ŠH¼’8Î9ôä]n…FR ¥ÔŸ8ð{ºùo Ü„Ï9§…F(fËŠa‰gæ½$nà*²_åL£ª™å\œ^©Ã x‘ÂOwãL”Ìw°Qz»ÉáÅB‹Eh?Nâs¦Õ Ñ©ÂìK¹:ØÁà¢ù‚qÀ|Æßë=Öçë -®Çy/ÓIبY_ò^åÁaP*6Ži²¡Õõ·fyèº$Pèzĵ‡ë¹02v ¨›$¬§á¹¤WßÞ´i¯B\QVQ&>ÂS54h Ôz†b±h}T9»!˸'ŠAÔXÌpZÇ=ûáÈåOÿ~¾§Pܲ/0kéª×žçCqSÅ uÜåï¤Á_í.6+AÊÆ¹‚tÍ<Ö78T9ˆ:¤Ãœ›hºÅՑɇßxG@)HXòÏ·ok);ûþw—Q4 #å¿;Ô+o‘5ÉÕöêf¹•2œéqÿÄG–IÊNN§\Y²öåm̽öý!‹ú5ÞÅåܓΠ&¸EëC§Ì2›Ì"[ô1^z¿0Ž—áhž©Æ$iÕRzv+˜ü¦fôF(—çìsöµô9ŽóŒV£Õ`Ó?çAƒ>œF¾@-à×B­^”¹‚‡É"é$ V½,TÈE¾ßcéá;À¡k*ˆW“2­$ç>8ÕÈÆ¹¡“’Ó2cSÓ™¼MÿÌz¿N÷áíPÁßü8“ÁůUágñ/çR8EâÝH€v".JE)Œ?Л˜ƒ¶â=|Î Ô­"xÃu‘€æ˜¨è)¦¹]-=ö£p.oX׵ݞ [sá4¼â@¶º±0 ÑR9ZÐèÖyݳ2UxåÁÐsž¸Ó_ œÉ«>ÎÈ÷¡HnÇÉ3ž3@¿»ƒÎ ŸÇÉÅøiZAÚß¼~dÆ`òXëy¦p¹1«·pNÁñ¦AêJy&)RgVžîäC³¾š)D“ r0èÎês¯¦­ËÿÈ]ÕÑárû;¥me|”‡9Ü—HÎHò¾´äü]=gùð—?]w´Zt-Æ9G{BË%qßM¢W2¾âÜîmâJ}dw@“Mã³d~UÃ6¾™ÉOá’³ï²ÙitB+L-;¹×Údj24)ÎýSÎÑ.‚¡Œ¾CvQ“P/j5ÞÏý7›sûóÁ½éiéy[é·ØeFz(”‰¸$¸Œm>#õ ›sd\üîæ5ò]4CgàÉgÒ!¾Œèú¿Dê<ÅdÐ4D£ <&g§‘šdOÁ‡*3^DùØuheXô×{æÎA¹ŸýÌQB„,.6õÓ»Ýf¶ŒñÎŒ}túc‹Íj5ÛõØË(jRgE%¦S4:K´[?æ»±Pê&ƒÝÚtc}}ƒZ™÷oú¾íÙ杖Ju½yyGm-ŸóÝäOÈäMþ,™Šð4Øô6Fòh Ó¼%$¨ô Œ=²…º¬Ÿ'Òӥͥq,ÎC±ä1»cêáµáÖÖûBñ>Æ Á«¨gš±‚,”Î}FñòrÀfü G йó6Ad"ŠÅ‹hh,Ė𸗬·¦O0&pÙܦv8 ý²Na_®i;¼ÛuiùY¥‚‚Ê|H„쯾ll‚f]õ(qœD¯xB/ùF`­ÓÝ¡$®¨ìéÖæÐ²Ãé)AIå ‹øÕ"$ –³‹˜NÐzôfgÎùòaX„bo!ÍG‘ (ÇÒ;`_ÉÁÌÛÌg¦†J§¢É‹)É+>¢o:ý7Dq™«gF¬¸R*.uË|~O[×µÇÒpì…)L~Ôh!='‚—˜×Ÿ™œ”‰Ô™4 ÈäZ…tç®üí@-9„\¿@IÀ•…sæò‡žòèÐdDÓö:¼*ÊÇ6ôF½¨£l¿µ¦œÆã$”ª$EZ±–yÆ’ ^O!™[d¦Ñ8é³:ýü£ìÏ WjÆ1e¾*,óÈî;x¿'ôƒ„h‹ÊFö‚[Óž}8z¦K S^ ©)•VH¤ûDï¤CÔÙ+픞ôÚZÀGyå®òr™\¼ûƒ’Aþ·Ð‡~Õ9Ñ«ÿ¯ý·Ú‡xí§}c@¹q¼”ìq••ÑPQ+UJ'•l$Õ]Š@ɧ%Ë.jíj;Ø)3iî8¦w3;ÈGü)¿5L¯™— PØ!ðî4W7Éœµ”ެSÔW+js2xvgg¥è˜Ô7zÈ S} ¸ Ãåjq¹¾Nw€y½EA‡ ©¶] u”š™DQŽÏô(È] ñï«m*›ÒÊdøÉ'gûû0ý$)éi–VÑP.—×Êjåµò:ùC¯60³¹²»< (R£ó¬¸ííúpo(© ‰ ­lœ$~Dóë1ÑÖ˜ùú˜ÿš?º€¿²(Þl6[~|òC¹?ì endstream endobj 35 0 obj <> stream xÚcd`aa`ddäò Óvö Ž´ Øæþó—aYøs>놲Œ?ä˜~È3ÿg‘{èÅòŸ‡I–‘AH2üæ‘_@¤:Hø®+ÐD‘ƶ©‰Å%©E™ÅÙ¹‰%ÆzFÎù•E™é% Éš †––æ: F– ޹@¥É‰y ¾@Å©@@NŽBp~rfjI¥‚†MFII•¾~yy¹^bn±^~Qº¦ŽByfI†BPjqjQYjŠ‚[~^‰‚_bnªØ#z`Ò9?· èßü”Ô¢<  ™˜®]ÆØÎÀÌÈÈ¢yýGßÏsßËw2>ù)ÍüÓÿ{¹èì…Ý‹•vWËÿ¹ÈV]Ú]R²°{¶<ßåküšÏø½á(óÃï¢SZûº'tsÌž9c®|÷¼ÆþšI«Š§EÍÿÎy@brß¼)“û¦Nì›Ú=…czë¼\¹ß*š3¿kôÎé\’×-YÙ][ÓWËQÏ>ó·æoÉçM;ºÛº%«kë*å»+¦¶Ïj9—³¸aOùoÎ0‰æŽŠ¦æŽÆÖŽÆî&ŽÊ™u³å&w÷v/™ûý¶DÍoSÖò9M3fÌ™2_®{jûê®éík;6v¬ãà+^üÓ~Ûo¹éìr\ÌÓTÿópNâáêááÞɵ“{ç\ æýþPa4Ãu endstream endobj 37 0 obj <> stream xÚV{TWϘµÕ6Ö:cév·[ð­{Z«"(*µ"XE­Z $„òøò~òh”ºˆV-ZPkµ[kk·V¶¬»­žv·êâÞq/{܉šÝmÿ©î¹3÷üÎÌ}|ßïû¾ß½„ 4T@ÄS âV¦.Y1yUüÂ5Sg̈ |›ÁMpQ!\´ Åyø³çÈ¢þ&l¢@@(ÇúÕOúWžâ{Á¯ùnÌoÇ Ä1RôÜ‹Q³ç'$­KÏ-Qêí m¾ŸoÎÌÊš3=&¦=³fÁ¬ ˜s‚ÙÁY³gÁœ Ž™3'¸òœéAœ5'¸òÜàà¹Á1sgÇDM•ææeNJ”¦gæMZ(ÍIŸWZ”‘—ž‘þ³Ÿ¼ç£§ggWB¾%n~¹rGÀ °àOÇ8ˆÐzÂ@ L„™°VÂFØ á$\„›¨%êˆz8D@Bñ‚b3q3D'œ"<ê {*칇ZO]¢3é¯G¬9qäõQ‡G+ÆÜ yq°ÑÔË Ë T†៹«â4ªŽX7ÐûðÄ4nl/žÀ§Àjr€öÔ8L)È‹JÔ)…+´oýp ÆA/qEÉhŒQ\¿Ø·¯¯õ= ¯]8URÚ)ó_M\–œ´rÕš¡Tt CùPfX©}Û´:dzȀƯ‡Þ;~àóãWOÁ$8üÄ Ñ˜J™´¹CÖÕÓÖÑÕ#mËdÆÜ ´ðÖßî%Ћ¸ˆöÞ§ Rei†,&' Ùz3Èì,³—5qç­¥u%®Òñ_ã%qÂ%¼Ô¡°È[a'X›ƒ(ñ+”x½îôº½6¯iø¶$" ]èànõâ\RÚjm…J&Y‚câqôb]]®)×n§ ¤¶IíÕxPT<Šä{U›DëÑ:j„sÏÊT{‰ÓHÂ-EÏ ¹ wWˆ_­JT¬Ø³$‡)»"ÏÆŸ]ü½ô;¸ ÿØûÉ`ÿÇmW`Fkñ84 W2xËðb£œ|»îBÄùO{ºûvðAQ聯:'Ãï B…YL$æ–eUeÁrx½3£ŸÎ9P9 é7´@«¾åa¤jü(½í ŠÌñÛs'…¢C'zD—Q$%ÞíðÙw}l  ‚Í¢ð(œT€Ãg ¢ø {¾ðyOÓ&òÍýÙ}‡ûýýÌGIÔöêÂ’b­¯AéÔ¸³øYFt}&T3·úä»ýí­,´U6”zh”Œ‰#©ekS—1¢ï7¯ß}”…[HÔ|Á4«›c;VNø¢Ëˆ~É Äpó“ ß´\oC¯lô$í  .M Û C±­:¢KlIÏ¿5×ø‡cżoúp_OkkWm'|}뜯™å&9”Ò2 R I¹²ÜÌŠLÈ€ô†"AÐí ¦yÚàCÓ}ãn ¡Ø;3Qˆh¨“[)–R.¨3ÕÝìÕogñMª¼L_Ê(Aiª:¤>EOxÅ[4³g½ƒqûvœ«‡éxl}3g‰o‘¢¡ü“Yئ*()),É1潊T« E[CC5:­uÌǤˆë{·8%!¡|ËÛô6’ã™(%ÇÏ=퇶îES‡D‡PÄ}›Ü¼Mn wîÐËY˜¢ÅáKçfçnZN–ã”°ÒrÈvªÓG‹Jwµ÷ØöòÌåÀ9ÃÎXZtÈ%µä˜óè²¥”Áv(3¯!Õj‹‡å¥À V]¤Àb´ñhG³e'S µF'л¨áeÃSÄfª©¾±½®ùÈ`- ktÕì°51ˆ =NC9‹oSŠ*CƒjPUPÉs¥²ò,C#VÔt£5>ôZ'ÑHTyMˆ~…ŠÅè4YouÔ!ÁêÛ8’MdŦìäÍùñOã1 1Ì—0è÷e²š-¼Q®*›ŠWªšMEÁÛkŠ×Á›°¦­°¯´ÇxоP8hëóíÝéënìúZëäùé4upÏøˆ‡Ðº;ÂŽ_Ž­Á/¥är““·ck÷û]ý]ï×yëvÔzmN»Ãê2á#’ŸO¡ÔPÉ;MË·[Nlú¨&h2Z4´MµV§Mžž8+eZF[­«2¢£o³¥ù¿üón|ýÒS #ˆ;¸ðï„{ÿ“7vèKYü •Ÿe(`Ô9h©¿Š”f›;XºâÎnÊöd¿Š7¹‹ÜÅî¢ñ6•Mé1Òf²O7tv|ÚñYà•Ø=NÕcÂÿ’(Êôr†ŸIp­â±\‹¦¤`TT+6Fg¾¼1J¯ÑiôU¼žê]:¾ÉŽI²/l»°õ|uƒ±Azÿœ¹Ðú¡G o’ò¡I-GëñrªB~ßlÕ³7"<—î@iµx\NÄëÑDªéçAŠáç³ØÍKrq©b<º2"p4,i_r|óá­§*Nòu÷sÍ`áøö“™R?˜ß˃Obïÿ/VaHéE/ù¹ Ýã:QlIJ"* W+Äií”臖VC6;ìå?Å¥!CoZKîÉë•/áRûá?ìÞ_ŽÒ(,‘8’Y©¥›²èFq¡Ø$ÖÆF¼aS{á>øF# eë<×sè4ãð%,h¡Ú¨ ”ô“wy&&t{%D˜‹—+ÕPBK›óº;¹Ç»Û÷-7e²r%¼Q±!óÍMù‹a1™[1è9æ|Ñá?kqØÝà¤]s5SM–‚YQ­,^÷–lÐ/mø …]v£h,ÛíºV]€:骩Õ yüQ×Ù…"†D{ø|Qáy¼ô‰²_úÓNºÍ5U,¾E•+ JFKA±±(ÇüM<Ö’J¥¹‘EWƒéà²Ú\LÙ{ª› hÑÅf©y-Hy©T¡yaüÆ‹²¯ñå'ÞE4Ò³•j†&C£=ƒçJ¬5. OŒ¶ªZW3‡JÔJµ¢B#«È†üÀ¦+ýTy¾½ž[]½ÃqéºÄl±Ú­à€ú"—z A⮬Uº**jÊ ŠÀðíþ|ª¶›^ü<Š“èlUNþ–`w:¬Ö¿Ü’¸ëܳÍã7ùi›$¥wi¬‘2Öètzýò…Z]¥Ueÿ~Ûþ¼}‹ž—M³Ógö> stream xÚÍytSWÖ®.¶ï¹tbE‰a’{!e ¤P’5ôzsÁà"wKîE]Ú²ª{“lÙ²ec0¦;ô BI ™„Â$“ &GÌaýóŽl+3ùg2/o­÷Öû—XZûzŸ}vù¾oŸËˆE à [´lÞú¹kŸ_5oå’ ã§½âûÙ$ï\‘w^?ïüïãd9ùð‰ ú¿Í zR$ê÷ã#¾ïÔ¡¾ïUÃè·h,ýÝ,z±Ÿˆ =*zRô{Ñ8ÑTÑ›¢…¢U¢M¢í¢8‘\”'Ò‹l¢ Qh—¨StLtVtYô±è Ñw¢¿Šþ‹AÌ0f8óó<3‰™ÎÌc–1ë˜P&šIf²˜\¦qm—F„&ï|)<=)42*jÂøñ¦õ-^~Å¿˜ì_ø5q¼1Ñ¿˜ä_øž8µo1iBßb²ßàdÿ3“§øþ‡'û·˜âßbÊËþ…¯)þ½¦ø Nñœâ78ÅopŠßàT¿Á©~¦ú-Oõ[žê·<ÕoyªßòT¿å©~ËSý–§ù-Oó[žæ78Íopšßà4¿ÁiSÆ¿4qv¼4!5e{ÒÈ%ñÛ“âF®Œ—†Æý·ŠD̰ÇDc˜ú0_´ˆY.:.:Üg.2ˆ>]}6œÐ‚ÓŠú‹ˆ‹†ˆ†Š‹Ä´`$¢ÇD‹BDÃE#D¿½ zQ4Ñ1zÆÀcd cf,Œ•±1vZ EL1S”2eL9SÁT2UL5ã`œL S˸˜:¦žq3 L#ãaš˜f¦…ÙÅ´2mÌnÑ _…ö£Û)Eß3³˜åŒ²ß¨~™( -ð¹À;A¶{mCû¸èþóûï°pà3½ƒ~|pˆqè+CÏ[øÈ¸G~®¿%¾ø¨äÑÃ’1-}|Ðãöm÷˜1âÀïžø]ÞOÈžøÓ“V>V+xFŽY?jæ¨+O½úÔç=ÏLò÷€Q|.t2eØ#‘=(u¢!gÇÍ$]ö·,¹SüÃIñ%|éB’­I—çæ’¡dè2 Èk@–œ! ñ³d˜YgÕX³š,fŠœy¥¿Çƒ¢ð4Àã¿ÚŒ—âax˜ÅRb‡BN¼Û¢1kxñ%è àúvKóíÆàô“géVZ½A:È«K+Êý+ n&o™ä…h2i,’œ¢Rå*AÁiÌ: obK Î’ü~ä0ž x:àEËñò{à¾shÚô1aâªSÝ.WUCKbY,ÿlàW=Þdš£—Å] ø5 ®~‘ ÒoåÓYqš÷Câ®Zšˆán6r yÀÅH-íÂÝ<£½+˜°rÅ:[Ÿ ‘s’#çv: œMúåÈóò ÔF5h8·G‚µÞþAû£¾Õ{Ÿtbþ†GÎÜkÀÙŸÜÄC%ƒÕ`®¾ÚQçJ«IJ”¥IÇ]ÿôÇ{xð q2LP°›õái11EŠFM#¼ﺎ·X¬V°qÈ`јh"ôìÆŒm9ë`+„†—k Ô&‘þP:­AÑ+HY ,â‹Á^i/jlÙWµ83»Ïд£lGYdADÀlõkÓÂ2U™ºLX‹º3Îû¬ÁûT ަùý Ç}¾ä¶Ø‹Åøc‰…»–Ÿ®\nlh«Ø-КWÏ%'æÅ¦TÈê…ZpT]œ }°¬m!yýy²˜Œã (%¯`Éê…Kã‚áDgû N|¿¾½p?tq¸ß HòËà툴%œ‘ˆ$vtÃsï>šgZÞ.Húáæ«É ‚x5;Ñ.ûNsŠ ÈPäo ™÷‹Z)Îý<àöƒi’²5ÈÅÚèwÒ8³µà*¨¯`7¿µnQèœeÏD’AÔ+.™R«³j€k,­mÊàA(.ÞßwáÈÙÎ ö"« ʸ4–螆°ÜªküGé®Þ{HÞ‰ë÷É‹ïàø+‰ÍŒšµ ÆsOÿ8ÿÞ˜¹„òpJúΦ]É• ¥)Õ´ZÏÔ;Àí×OL²r¹ì„ G 0çØÒ‹±Ü²^"¾fZf¸r¬ûD›¹Àb¶€lj‹n_BÈÑŸEÀ|î•7ÖOçgÀÌCùŸSƒ5ÞÇ%…èâG­ÇÏÝŸÊÃÊk·%kuô¹©ÕÅš—Ô)Ïþì7ŽvxŸ©cöþë? ðák#  c–ÏNŒŽLÙ;!ÌžÒÈÕ¹Jk²jâ…THËÔ§pj4çbÔeO†[xžÿž«¢ÑB9ø%2àtJq¢%fÃÒˆðå‰Û[a 7ò* ÂýùBöœØ_v’ÓÓº‡B¸ó'Ê7{gý+'ìîå„K}œ@> üoôüÞÏœrÎòxG{˜ãôÎú$ÀûÕ{’’¤]eÀÙŒ6«€§#°l´³Úê ºxi”¢ JÀu´ªCP” „\z€næìùçaÒñ·cNª®Àyø¶æ¯7ßßß~²öà@¸6¾‘ô3§ëv:€+)° ØŠ,†"¯u®V•œ‘’“´áØš–¹.%ËÈ2‘l%Kð3d®ÂyDZ÷h$¿ºl®WÊŒòcþSñK=‹ÛÕ  V" =*Ê¿;¢51< ¯1Ÿ+eD™ÅEw³9ãÃú˜Ê,ø5UÎÒbw]]CC­9ߦ´*ŽÌ98çðìâôºdHâ’ãµI¼ÏBjÁi ú‹› ‡xslG–#Ç™í\üåò»‹¿Ð›t&Z¤¶R»Å²ïþýû÷;| ãp²IŠœÕÙé$íLLËxaâ /Çá먳ɴŸ¯ñÄ&낆ü½Ÿô5©±ñA Û$ï9Ü¥}¾Ãµ –&íÔß™èéÂcè±òz%õÚQ˧ ª&&^MI¸Y¬<ÓÒ x;QÇ.K»BC!pnV¼ÛCž@âK½ûÕÅ/ñ_®Ãçi<…Oñ‰?Šw>˜)‘þÇ]ÅYRÌ"ña_0Ÿt³¹ÐCœ1ñ¾`êðRt׆œõ¥ýÞs—Æ–¦¤C­Ç±ä®· º «“ÇÙëW#Évh#Râvl[¡Xë£Ð~ÝÜ÷ÆFJMß;ð^Õ2xäGøÂ— ¿wö¸õ2-Åg‘8µ|÷=í?™KMePŸ/>9Û•f“[äTuUË(Q¶^¨=ÙM¡çê¢w×n/ 7…ÓÃíKƒ4ux4ùJ‚ßdÝàÖ»r'4-‡åܸY ÇòaÌn:+O7»|*[Pc¹µ†ÇÁ¬¸ó\±Ž¦4?ñµ¥¯ôD,¯çd[­‹iÇÝqⳞ`ïê/}-þ³á›Ùn´¸ CÎÔŸ9W8üáO?˯€µY›vêõ:½ÎÀhŒ£ŽgG{N%õ”ÂÔ%|5èšÌŽ{_ü¸ë×–L`Ñ–ù³Óe™!¸Õ¬"ß ôȨ´ëí2-Fp‡Ø (‡ 'þæª+oÂdnÌ”¹/ðàÙ]²{Z§ÅMO®Ðh‚Ášº5{vÙöA.ÕS8?…G v¤ù–½ÿ†ýŸ»ñ©úÞ’ÅŸüAÜò›[2¶§%[z[2Ž•B´I[G‰JJËlEW1ws×0wòvˆ½´¨ÄVf|¨ ‰ŒÕÄR9ÿj G¤øÊ0ÖÒ&€Õh£êÄ[‰ö4Y›xêŒ:#®¤½Fÿ€V?áY´èÌIœAnN¶*ÿM½A¸™„[9)D™“Ÿ«Ê6xu!»›,>¥†¢_è=½Ü•Œß$Ϲx‚ÝÆÏ;±ùSñQ<¯¯VK%4Í!¤"Cåd@ΫRòü J*òÚ,·Å`ñ £¦QoiH­‰‹O•G/Þ³ò}Õߪ:Ó†˜ñÐB<„s"h7ï…=\µ©d§³Õú2=Är÷"ñѰº0^FãÁþæhx¨ 0}3ÎèyØÈà§Ü^Çõ€®Ï‹iò¨ç-M¤*ƒo˜y˜‹­Qnå¥8у¶¾m»H‡4#F¯=Ä"+L³Ë÷Œ 9MÆž&ÏŸ /XòÌÉ´ÎŒ—¹¸ ÷9‰Ÿ}?K¿ kŠj¬5ƇҨ%·=¶§"rz[7ùÜñ›Ü'SPºN‘Eâ¾O¼ï+ÊÓMAÿÂøÓOÅ]{#tøT/MoWocÙðDÓ^Á[‡Àbð9ÐXanç±–uèË´tÒy¸õFýåßýÆÐÿODß÷¼ïöösc0¾LÙõ8u&¤Páhé.¸ÜÜڼ넩 ¸Ýlm½>Æç^Oe¸PX„fgOÀÅöLqc)S6Rç¹—²Û·›i]>9a¥±h®-ØÅïb逢ª™j2í0íä\lNñeïõm"³;?Aȼq Ô|ükœöNûZlÆ6_lºQk‹v»ŽuIÆDÝJÕŠÌMÑ«#çÁ|XP»àXØ‘ˆ ™ïªjõ5P«çÂѶ(m¿†Oé-;Ñr’{»#ÊÜ)t ÚúXT†CŽ~.&^Z½gSËŠŠ•¶DS’N[U¨½ÍÜÌw{È6^ô+^‹G~ØôÍ_ÝõøfÙûê´³9QGƒ>T ¯ —0³ú>4}èæH Ö…ò©¬XÖSm¿öZ{P«³özFMÚÜÍêhQ4 Q-ä#ØmÆ­¹Ú2ÊežŒÀe­ô˜NpüÂD¯hV8emT6ã©ÎàÎk8ìâU…=ÆËIê›w;÷w¥}É$Xõ»¿î¹kêSø —÷Å\ öÔ'~„›oŠïŸÀ7$6×jn=rúÐÇ—«:ì{+KsVdÓš””âe9š8eœBªZ–=?kKèü%Ù$ˆ²e ¢Ú@i´²ì£>ƒh¸üþ{üî?³ä1a&Œ_—4‡ë&!ñw=·'vîã*ü(ò—Ö1Ïóðj>“¡j:Ç¿ /©>ÒÿbnsâPVGðý‹øík«oˆï7zgKä5¨¡^K«â KÕ¼Í˰]Ál9æ廓Z6qbïþ²Up®wï,-Ž1Æ7‘l“üÈŠïŸ?ºtɲðUÂ<6Ù¤-‡ß Ä"¨4UÔ˜¸3¬Ø{ôdÊŠYcòÃêÆŸFÞáæ/þíî*g< M´îðITm©ªãϳïC·ÆJFÐVÎÃ}êrÌf=)Ó{,áµxÂÅùxRê³Xšuá‚‘LA¦ð™d…S—éŒÇSïj7í¢ÉM`»á¸Þ9Ûg’ÄQË™x•º±q´uña´·Æòï@äÙ‡Á’ä ]O6°j£Ú6(ª,³—¾Rö#ܤ=à«§‹«‰¿ÃÖå¥äEß­ ×sX•Â…ãx¦“i¼…0ƒ³%x[d±}¿æ{2„ žH‚ó1‚G×á|GÃGFsÕûœUmÑð™ ŽRç%…nŽÛ«`Þԣ†.èäŒÉGw?ý¼~ôl¾Ýzëv! Ýtέ>V‘Û’B¡Ô€@£Ti5ëBÂ×E,ÛºU&KSI“á·(=ÓV!@ia¹­ÐÝÖÐÚÐVRQV^TY‘[žS‘[¤*UA.÷ŠÖdÏ¡ ’:ÓPl¢©SøAÍAw£(£,«$³aGÃN÷›¢0‹mY9Jßcz¤zvìo‹ßßq4DkQÚÀÂ)b·ÔV”Ù{îøàh‰.èÙ ¶DkÕ@>ääe©”Jeȶíëwn‰ÌSä)r•…Øž¡ÑÎík,8Ä;ˆTîDnm„OF(é ÉÑÞÑ”Q–VšY®´‡¨ìyåP EVK‰™îÑ[~4#;xž3_½þÖGâ?ã ¬tUÝ)†¸{d¼u3QZi–Z§V«|ú8Ò) *uùj¡çzOÇѱŽJŒBÅ›0›ŠœçO9OwìzÆÜe‹b×kX•J§ŒJõ˜kaÅߜ뙅¯s 4yfÊR~Ì.Ï|O[l­M§šX§R []#k‹9¬:·-+Æ"xmóêÊ\sŽ9ÇÈõ–½¿ypø¯õO‚3%ÄÛc¡Ýnµí9ÒÔÑ´§©ÃQWívº8R…“tëzLEñ‰fÚhGúê$ȾF …B©QE¬Y·hÃ[ks¸ íª(:Ãû‚ø³M±xTp/âïþ¿8ƒûß–P|n¬N ± 5Å•8mÕ¥àæÄ·À•V›h䢲’’fý)½ëÔíº‹® ×N!QŸ‘) +“ÕkÓ ¿Ðÿ!õÞùl—Âçnp/ꉻð@ŸÓÕ¨¹Q&À\Íì¼9Š5ãW@6dYò « hfrî,‹Þ>~ÏøöñT›”–\:ûÙb0—š =WBÚïìþ²ý k™­ÜRn$߆ˆ»Bw‚ÏJ´Ï—„^_ö¹ÌÝ´@E) ËÒdm"Ì6°ˆ6`fî· 3šr]y üœÞ^Úûßt Å%˜; #3Õ9XÀáDð)y%$¶I ›~­H)ÕS"ƒI8ŒÚ*l½]â#Üü:*˜Æ©.À9Þ•òhÖO âF}Bà'ñ#wÂð€—qÁ“ß›äÿ„Ó+ø>‰Üö’¾‚Ý m»«sh¢r…Kõ›5Û>ª}Ûƒ_rzŸs1T8TÜ hôÎ’H{ŽM§DoØHg·O ŠK6·Ñ<Ï© ;-ÛÃñàï~Âq¿©T» VÁfYøî=„«‰F¢öô8§`7Îë:ÚsQVJÉ´”{çý#gïµÉ,4t èãQŠÚÞç]Ì.Çÿò•$É2SªS]®êj·`Gù×_v­¢ƒÈÐ $ˆô'ý¿""ÆÿRÉ©£5Ni"ú¢xw m™DeDA›ñX«º¦ÙÒ\[oÎ ¤A’Z­ãÄ ):¼PZÐw%øZª¢PX´å€€»‘Ã\YÏ7±°7¯d•%¹ ٘ܣk&ùtÍ ¥d«Óû@ÎT{gJ2쨬é»'5¼U¿ á­–é!&¥-™‘¤Î”­•ÎZiË.®6UøºÜ™U•š”™™²ñ€´‹¿ »¯Ö¿‹Gâ¯CjŽ9o_ó¡Î]Ф ¶¡J–$€BŸ¯S$/K\ž¼<}KˆV¡Uè”í”õ¹®¼ºÄóñç“.híZß+ѦVpòŽqt$öQA/lý¹ °Mδ~Œ•ïaå­Ü䛡ŠÑžzý Á@¶¤7o®Œ„áä‘qTápdðŸžÆÁÂ>hpÔ5rÿh-Z=hõHiõH“Ííÿè?T× §rùñŠÇÓ& ‘°9#=Æ€O„S’"ôizߣmáÑ£ k¶GðoÂÚkYµå† }9çÝk¨§mõp[7îë°Ù÷l¢ ðÃ!2håô>½æ o?Uø:©…ªdWló¶–m»BMšBßKXŸ†ÒF‡†lYµeÖd_šç8‘<¿Šª'wmM¥£²¦²¦ÊiË)Ê+Ì+—WÈËåE¹Ué驊,}|‹3­…ôÚäædOJSŠ'ò¥…Ýw `³šÌÍ!ït]ø˜&‹Ì‘#§¶0›¦8fûNy²J¡ÈWçÓ ¥v„µ¥´ëÍ3˜¡ÒQ\aä~îÔŸEñB‚Þ#jÇüÿ¨})²•¢ÖÃfœ@Iê¬x^E3¦HˆÔG—”fiðyÔê°ø'U€ßpà¿Ø½íjÔ‡ ólÒ‹ÒëC+öÃ!8dÞïàÈã½W%*.LªÿU€­EǪ7¬Qv·òQ‡Ût¸g߀‘§—ý ‚k|ÿÜ}§v÷ž:4Y»†—=ÈùWIúù©S(I•“À“ÇØTe©KÀçP›Ózâ7=ÒçÃ/BÿüðÞ£M}Z]1Ïÿo£ÿÙ5ß½Ë?àŽ›·~­,êÑeó×tª¹1©c®…Êi<˜í£³tØû’=y~Ç"A‰4C#7«²õÙTbpo³2ƒ³‚:î ò©¦zÝ6¥&µ>“‰”Uò,ï ¸µ—¼÷33þÒ¥ÿõ²F~^°G׌_vã›7Å7ðMœ$We/OˆÎ×çëó€S±ËÌÛw%ŸÐêJèÕ-ù[¬ÙŸæ{}ê{9ä,Â~š‡’'…Ø¡ŒO×è4µÓÓÑ@îÉ¡£^¡úÞüÏD òÝŠs¶Äh®±Öí?âîîö¡Ñó2 邸k3$4n.u¹:YgÖš…"°Y|7À7:¡aÇAh沦ݵ-P¸²ûB¥vR©}ÿ¦ïŽAŽgbôª³¿¨•á$§ÅKýzÆÆaþ>·t• ÆOáø•h@†ó#a”ôQz•N¯îÎÛ’½.—Þ¸±«ÂVaª€=О^'m 7¯„u0G7}ÞfYNŠ:¦Ãú ùŸ~##,ïÓ> q2—nâx:é&ãxIv²\ž‘ºfãŒz ~k(- Ê(.w•4v´v¸÷ÚíFk)pçhñöaAx¼n==Aü¿ök8šDF«ž›ùSÌA?[!é{›2g¼ñîåsÅŸ¬£X³S"wzg•ãø‚²:–l-Bü€€âƒúÛ 0øÃ€#ù‰#ÞN–Úþþèÿ{/¨C endstream endobj 41 0 obj <> stream xÚcd`aa`ddpq öòóÐv ò5°00‰™üfø!ÃôC–ù‡8ËïøßWdØ„~Ù±Ê200´ ‚È~Ù "Õ@Ä-!fFFI =cçü܂ҒÔ"ßü”Ô¢<… üÜÄ<4A 5†@}B LŒŒL~|ÿ™„åvô¬ùÉSÎø½þ6ó›ïD³Øww}>ÇŸiìÑIÝArYßß­a«í®îªêæÏìÛ)ÿã$û”ö©õråÝ5µ1¹ÁM!Ý|å ~8Íúžß;s1ÛïÐnv9.æiö<œ“x¸zx¸ßsíå–3õâø/_Qƒ endstream endobj 43 0 obj <> stream xÚU•kp×Çw‘1 ‡&ÑDn’]•L¦¦b'2¤4 †W‡ 8$PãX6~ ÉÖÛ–lË+É–tvõ°¬—mY^KXòHpˆÝ¤œÇ4:4„L“IÓN&-½R–™ô ¦úåîìëžßùÿÏ9—$òò’$ ÷ïzywÅK¿ÜVV¶³´$÷ds£èùa"Ë.ÍÀ÷P…YÐ Xˆ9ÇÓW'¿–dVf~úžà §—Ϲö!’@1õægŠææ}¥@‰yù¨¦]ú€V.ÂwÔõÒ÷Åûhq&ßÈÞ¡cx„WÌÕë†vèv;âOoMÊ:.¦l¹CÉ3©EO*õaê6e<Ä‚©V 1\g¼ó_B1Z™ÿ·Øž:,¶#]ÍÖ‚‘ T‘ϧ¾‹biÜ4 .»Ë®Ùr¨UTƒ]8ÎÀ˜ÿMï8å! ŸîkÊzV?–-Ia·‘eQ’-Êî–z\=,ÝnwGÛ+岿3É]8µ{Äq™¸ŠÇç¾iùZvŒ½`MTé¦õkw‹­¦!áKp~΋ˌ§‚v® ïâÂIvwïM¸Ð¾n?íŽ GÏÍËN½ðAÛPè´¡Õ \©Ÿ´DuÃï£Ãzÿá Ë7õÖ§aŽúËÕÏ¿¹vñ˜GCcw 8îtP8wgð´U@“7NäÉO %Ϭ–š¡ ÚÚÌW+î&mÌ:˜Iœ8wàØÓâýb‘øø³Ò…ÍÿBýõfØgAÓå°m.Ièê÷MçÞaàdüÛÉwÇæ/œº“0ÓmÂ=ø¦UÈJ_#_O‚BÙ'¥Ûilµ5»ln«·ˆ5}g9ÖF;âÝ·œN«Ëæ¢òÓugè HƦc3á…œ8,8éNpw;ÛZw™ž¯J ãQœÏ7ˆsªÀãçâ—DÿZrãR§Å¡Ã££%ÊöánŽzâ¼w=à&b‹þo$u&!zÒGOÁQèëà@Ù¥×B3e™FFRÃÓS£/Ñ» òe“Ú6{xü“‚mi©oûÒÄí‰õäüÂÀ‡ñ³Ó@ Dm5 œÖö LSgæn âÏ`ž¢y´v^’¹?³Bªvõ §Úz-‚8>{èä“¢¬öáJ~û‰%í8ßyÞ /RͺbÝO€nn¦+9 )jØ64+ (Ÿ¯¾Ž~}­š¥aÚ”ì7¥T¾ÊÞÃ꘥҉‹7è$¼aïS`†+V!³Ç'Þ½#Aß¿- ½:Õ| ¦`x¸|`:rñÿUmÛcÚ^”¡32Á€>˜J!Bæé Îxû|ÃÁðS1 ŽovÛêM[+ÅmûÜÝÕ¿Ù TEçì1ÞN}vôJxÔ…Aj¶ñØþuµâÃìÿ”â}ýÉ/fŽÍÕÛïnd@kU9,µÅ†2x™ZwEó} ¦gÌýUˆ|‰ªr^¦¿B—¿’ /ЩÿèðW‹àƒ µ«»ŒÐÞ¶J8ÿ|´ž~êöuè4—öU@=T.J5¹ÈL<<ß;yóRr¨Á)öŽ´î¨å沺ªJp€ ‘¤OÂ"襦¹ñàÆÓ9œE?\;­x¨ïç‘4™ÓŠÁ3¢Ûeoo×6¥0Ob­üBè4æ®±^(,.cϯIßZH'§Ç€{wnzú›¯…³àÍ©í¢íàtu±ÊW f-h¡£Ï2`n7õÔÁ †.£—éÞÇû__à0ƒöaÛ KWéáC·™Ì¥eÛwÔ•ã.½-->yhxjtd†!È&U†˜9 Ô?Ð=#øœ²å˜N»n×nS¡Åoè©X¼|’™uR…z!³-Š ¥/V…–Ñ+ò6Æ –÷¬à VŽ­øheÒ_P€®ßû_?m•æ endstream endobj 45 0 obj <> stream xÚE•y\×Ç'$dFDTÆyj—™¼ÖVl-¬O±µ²T\ŠR·º K ì„%CXJ”-p$(‹ !Äd"Âi]^iŸµú¬XíC¬¶Z­z/¼AÛÏûç|>÷ÞÏœû»ßsÎoD„DBˆD¢i~¾;¶}¶å]ïu]]&7‡bÃóœñ=¶ü«ÿšˆ݆gÅülÉë!š=SˆÄãé“ñ§“ñ-!ØI ‰HD%§æ»¸,rvqqóŽOЪ¢""Õ2§Ð2Ww÷% en..î2Oe˜**T'['WG†)åja+Û¦ÖÊœ>ŠT«–½ÿ¾F£q–+“œãU/X(ÓD©#eÃ’ÂT»Â2Ÿø8µl½\&{¡ÙùEôŽW&$«ÃT²uñŠ0Uœ •r½K¸LYNÈ AD b§v„=1“p$hbÁ#fsˆ¹Ä+Kx+‰ÕÄZ‚¶!D„„&zE¤(KtÞÆÓægñ2ñ‰N2j›,µ—®—>$Ó©8ê ¯wàç`CíóMFуA1º‰³0@aj5ž‰cÐ@ïòjG^h:šYQ…` Jò 9ìnp]õ¦·a›L,†%°¼ O;m‡ðô[kU\d(áþŸ¥ É­ÈÀÀ5š¶Ùú¡é‹/î*'//‡=ä×hs:‹¼"‚g`Ç/2!ôTNQ^1{F¿9‡è“Ȧ‰á&å0~hi-:Ѻ"Þ¶CÌ¿‡RÔ$­¬£128Ü„š¥•P£Ñ@J‹›q3™‘M TrHXI3 Åh„šJÖ×'›Æç˜DÇFP鈘F—¸ž{=òû€ûîUrð¯ÄçŸÜåð!x¹v®8¾ì²¦à‡Ú®{MÃû®Á(/3 øÌ¬½¯‚18àRé@ šze¿šá’¶ÆéÀ&X¾à«tŸ¦/ܨ J¸,|›¥K`”ð½õŒÏbê¡PÍ®ûtÄK…Tý ÔÄA2BŸéÊÆÄJ[ ·¡£ã6´ØÏ³Ä®ú²6n2ÍUôäÉïǾ'(èŽÊLóˆ¾Ê<}Œ\;4ç"©ëuì€m=ßwÛÔ†ê–òÎmC$›5ɸ îâ@Û PwŽ/sçàÃím^‡7ãè9:pšDÑOxRÚˆ¼lUÒ\evÐîôì¬5üB}rãwˆBóêÝï_›­HòGèñiL ãè sãðà·ž‹Î¼ûö ¿Ѧ”#£éHßNHg-½—*Zê<ìÊAfþ†Ä ¥”^UU”Ÿ YÙ°›¢'tº¨f»¤7ÚV-À¯ùÄqÁàQy®%×b‚vª5Á—“ärw !‡;w±ÂåpÃ÷Ú›µ/ù¢W,¼\ÜsUŒÜ™Ȉ|'»+VÚiè«õt (w‘žùe­Ü퇖ù¼¿€½8Ý#tfV&šˆšK"³…Áz)ÒóSl_<Ùü†|Mhöˆcß Jù/ýŒß‚4Õý!&XN‹ˆ¤ÐVҘӜݚþíŠbý¾l®@ š«×ìÙ¡Y ¡P²³6Ë/ìQ»!+ý¤²*Ù(4—Uµ üý`(ÕV…*`;E?‡HðK’')ÂÀ 6žJ=g(0”Õ\m®¯O5GgDf,~I8ú¢ÝG4÷B3ÿFÝÈ¡P£H1¶v”ž@sÐL=‰ŠÑŒÖ“l=XsLQTz(ÆÖ§›ª¾Ül(èŸKñ,ü*fp"G?ÇFD}r‰ïý"|I»ÝÇb–žXáÛ4þšŠ¯0¾ Ê9¨íëpˆºÖôp”­‚n°¬;Û`øÃöÔ¥_@®úeûÔò¯ŠÎ˜ï‰ùþ)³Òbj)œ'Å_‘WC©¤Ñ8ÄÖ,5Tí?_Q^R| *”¡R]ÚGX”íŠ_Ƽ%  ìî†Ø“$œ6œ.(ª«¼ÕõõËEÿ:‹ª…W÷©»PC—ºþ-ᘀ/óŽB5õÕEëw—/lõfa£Âß/’2¥3ÿnëí‡KÔ˜ÛY—ùËí æË4}ycJÖÏõôØê¾Øûë›.üÔóROëØÍ:~ÞdÖŽ!ŨÐ8bôCâ/Þ ØÀ¦Â–„£TWé‘jKÒÁä4åÅꟃÐk(F¨2aò7v3ìІªåàAá™?/@–~ötZë)<ãc&  ö¼¶ ú`Ò¯zjÛ÷µW´iŽª,)ò…jiÔ;‹XÁOÑÜäÜ!:3þžxÜ]gþe¥÷¥ZçAŽ¿‡?gþ4Ùtnâiú_¦*;×(© ‡Œ ”ç6ì=ÜÒ[&ŒPïY…NÒÇOmÓ¯Ôû*=¢T[!ˆZö«ê<+Ür º;jz¨l´”™O.ôŽ ÜÒÒÇÂiër/È÷ëLÉV~® …[Ž ªa:ŸqšYC¢ùe¶reVI/G÷òxžÎ6–ü¶4{‡cɸÖà†-@a»7S@ÿ愤~N57Q¨V‚å$h!_—ªôL†@ˆhHjOìÔŸ…Nh+:r¢ÖÒÞ<-`M·–¥ ƒ®lR‡6Þ¬CPçØØ¯¹‚¼®´ô ÒÏtH…<˜àa‡÷64—–×5vuæ«9H(ˆIWeeªãCI”‚"¨«6‹ïÔ×uwxø*mimªºÖ£­û Ó´ º¼\dR©™UjJêª3›¬‚rä!òf¹AprgŸ92…™w}‘®†HŠ' ¶"Ì¢ñK †PÊûÁf¡ýìþ8y…–Œ“Û?oÜëAÁ½7¦h—óð0ó¶ÏÉSt··u¨sÒ[H‹·|²}瀾~u¶V4í©ã•§+/ÑwÑJ~=ƒe“¨/îÏP›È@¬fcɦ½…õ--ùG_&×äí;ÆÑ¿ñíL“ª6>69!1Á”hi4×6±É&޻ŕ›¤8¤œ´Ø O5í··6ÚOcí$KŒöSЭYÿÏÝ÷ endstream endobj 47 0 obj <> stream xÚ5’{lSuÇïmkýÁê@°RQî½jT@2ÆK’eâp ŒÌ `ØÖUÖakïºvëúX»ö¶ç¶·íúÚ†ÛØ²>fÁ%btFˆ˜ðˆ C0(‰ÄÄ{ËjGb~É'ùœ?>ç|ŽÉdŽãOílhܵ»ñõšºº··Ì¶™ÅðÃ{ž'„ç1á\X!©°LFÌÖÊþUHV`&<=Ïû‹æywñ<_+A6¼“á8êìTVn¨¨¬\_c0ÚLÚÃm4µR½ŠZWUµy µ¾²²ŠªÖiLZu³žªk¦Û4ºfºôùÚkPk5´Z¹­¦[×®íêêªhÖ™+ ¦ÃÛW­¡º´tÕ 1kLM+µÃ §©úf†z¬^ñ˜5±“Ö˜¨:C«Æ¤Ç0\Ò Ñâ¶ÛˆmÂj±]˜\‚ᘠ{€#±JˤS^œ¶d½þl–ÿ¼°D¸0›»¿Ô.¨„¢2~œ Oº!ÿågËVÑo½ß~@ÛàÚH\$ç=J~ÑÔï?Â-t{Õ%‘$ijr›¬½i.ä ‡0È8ÄåsÇU}š€§Õ VØ&G`<4Ê¢‹òß ÇDEadÐÝ$6èYB0Ä!в‘Kü°jéü³ò;Ù-$ôz >‹GïVƒ mÿ¾ý‡ÛÓ÷G8&á \Àôý;š,z@ø³ Ñϸ—‡($àÛÖòârK¡¸:óµWùäUiqC±JÉr¡(DP¬?â%¼¸œ.GÇ—³uæÁ}¥YI±L\ ÊIØ3¥x m9ϵî}!ÈysÞïz` Ú¸©â¥Z±l”_L@Æ¢lB•r±~ÂA¿n7«üv¯ä‰úbD X6™>ûµj\7£þÿ _Æ/ã$œ±Ÿ4fu…öƒ)}¬5NGu±½£p]¿yóÁ‹EŒ³ß~äŒbD XŽFåÂ?Pþþö ”ñ“l¨ÚOò¿Ríï‘`êo ú®`#ÎD‰$pÑðH†ß­t‚˜›•› ^K½X­ øô#O¬ ÔŠDÎðs)~  Óò<ôÀø»‚~Q5w¬)ãzÐ7Xƒà8Jfàr8è–< W˜, ¡R¤.0’fð@GèHØÏA8– 'P9ÿÈÈ,¯¼‹ÿz¹pEÊŸ/Ê”Çz†é½Y×9Ü3>™›Èâ«sRe£Høì>'t?·ÿÔá/ÿ˜æ©tÂöNx7ýfK‹ÓÉ0û(=•È$2ÉÌÔ U|<5GÑ9õ‰}«›EÊÑói`£áDöÞ™LÐ`Âg ÁìuëJ[¬›²Âìc'û=ž¾&Ö•¤Fì#f]‡¡Ã:dÈOf' Qóè ¥½~m=ô€ °SC\âh–¶è¦vÍ'¦âð’Sy^q‡¨ §B0„¾:tzÏ‹uÿ{$ džò—ÏŸ?h,ÕÛ^ºl¦ôP¹eL¨I$“¼qL.6%ž$Ê6*Ä YEÙÇ ¯—e9…‚Ÿ}æ? Ã*§ endstream endobj 49 0 obj <> stream xÚcd`aa`ddäñŒ Œð Ôvö ²ñMÓ÷ý:ô³‰õ‡4ÃÆ²L?䘈³È200<‘ùAä]© $7 1°02r”T´ë9çTe¦g”(h$k*ZZšë(X*8æ¦e&'æ)ø&–d¤æ&–99 ÁùÉ™©%• 6%%Vúúåååz‰¹ÅzùEévš: å™% A©Å©Ee©) nùy% ~‰¹© 'ëçü܂ҒÔ"ßü”Ô¢< “ „˜YŽÿèàû±¼lùO®åŒ[ž|_ô„ùGí÷Ë¢ÝßÎdŽlµ0¤û·Pw¬nm~ºS§Fwx·gŸÚnëŽW+tïî~8kï» —ûžtŸáø]òûŒhf·Ûì²/ Gº_vïï¾Ð}qÚ¡oN]Ò½¶ûBÕ|ƒé!ÝÝîÝ݆õÁeJnµYÝ@»»×üX½fû|Æïõ·˜¿Ÿû)(º¬³§@.)9¬X§›#‹}Y÷Áî£Ë8þLeOë¨×‘ËÈbÛÒ÷°{ÇŽGÝ[xTÖd°ëtLß ÏW¶à‡ó¬ïùS'/`û8} ×uîåxx®Ïæá•ãb1ŸÏÃùý›™û¹Z endstream endobj 51 0 obj <> stream xÚ5]LRqÆÿ@<ÙÇ$m 8W¥ËjËÑ\MÝZ³Ù…¸´6Û@τ‎žÁh8ÀøxAEÎ@Sv,›‹µj oº°‹òÒîì²–7yÛÝ9x˜…c]¼¿wÏ»g{ž#• aŒ›ŽÞ½k¿:0dÐi=¹ôzGŽþTÖ$’ŒX2)$R)µ¨Œƒª¿:…!Ü|î„Ú3'ÄgkD—kP¼:Ôk. »á¡ü~êéŒÃã`7éô8}¬Ëjí6[­]¾éãžr±dÛD;Ùi³õt]V«ì£)Æ=áð’CÖEѶ&<¤Ý7á¦ØÙÖëbÙé Çqfí7û˜©›í$çf]ä0姘Yj’¼íó²ä=M‘õ—Ìõ5ࣧgXŠ!‡|“ã­W!ÔŒ:ÐãZû-Ç 4Ž#jG+x ÏI‰¦JQ –ñOITV®ˆAýz!ASõ£:Ž+º©f’ eѼ!½êÖé·>¿”[‚‘òaãsˆÄãÉꎼÚŒ&b…H6¶:/íÈ+­+± ,‘çù¼ øx6˜« bªUÊV¹zÜ,„LÕêÐìÿ¸£x±WÆâ²¤Ôïî•ö!Gæ b ¤"œÓÒg‘[ìÏæ)ˆA’éd&™N Q1þãúg™XŒ,¦ @ðy(˜ GïïRX=Ù~‰Dœ§Ã@Dæ l‚h©w¨nÉ÷õô÷¦sóËÛÒkA ¤oê’÷Û?ò„f8ŽhKòÂÆ‘]À¢¶¬»+ôE(rÆãk‹Æ&ÿfåÖKµ|)ßhÔ¨zÝ©e&­Ó–5emyM§«Íiñ ùí%- endstream endobj 52 0 obj <> stream xÚ]PÁj„0½ç+æ¸K)F í‚к> stream xÚMP_L[u¾·-r×aU Í¥½›1)¡®ÛÒ7‹š˜È6!A+åŽ6¡v¹xÓnÌ1tmï¹—M:tÌ’Zunj\²`¦V}F}Ðè¶D3ã.{‘x~å×%^XŒ>œïœïüËùËX, ˲¶žîþîî-]Oõoó¬g|£üj‚¯º\>WEœ X²ÅD¶šIƒ¥‰aØ–‡ÖqëëøÈƒ2̵ g,㛽þ‹Ÿ,$‚’ËÈðð‘"Ãá 6(Câ¿%922$*‘!ÑãÙÞêñx;ã‰äF§à 5 Ûü~Ÿ[ðz<~ቨ(EBÁ˜Ð”Ãb4(dD艇"¢œ\»Ã²œhokS¥5mKÃÍnA‰Èa¡[¥WÄ!áéxLö£¢pOkë=×&ÆdQºâC¢3d™ÖňFf3l–U™*Ã2æ ÛÄ~oÚB2¶òÇüê‘wøÍSOÜ6—³üêQ;Lþút rcýtÒ\îÃ5   ÄŠ.¼q ë~BëïÈèSº§¹™×à˜ãd!›UÕ®ý{¨‰¨º–ÒÅQºs’îꃊµT©Åtåê^¡Mw=;©©yàÎOÃŒóÿ·ƒ·Íd‰_{ÖÄú"©¥;påIt»±Éõ×Éœª¥€Ÿ„ '¤OŸÒ3Rî:­_¦Nl ËKt *¨t T¬ÔEoÎVþâ¿ÇümÓÇ“›v@Ó^ÜC·¹†vÜôî×Þh,?S 7a.weîú—w°îÇÜMƒ9®¨jcޤñ’ÄQ*Óºãt„¹»/TC'´÷µ½äï<?©ª‚¤¦æNýÚó‡·H}ScÆÈ«ÜݳÕÐþݽ½{\‡·+jZÑ sª–Ö}@~I` }ÁÐq޳‘%²zõâUÈ’™\)¶ >í‡ÄòáB,?’G&Ç&” åDj¼÷åÆÙÔ§_¸ÏÃ¥ÔeåRê£Ô<¼rÅ™ÂLáÍüì7Ÿ5Ú”Â}> stream xÚcd`aa`ddäu ˆòñ‹Ôvö Ž4 ضÿóa5ü¹Œõ‡ ÃYÆrL?䙈³È=ôbùÏÃ$ËÀÀðGDþä‘_@¤:`Þ=‡cN͌ʪêº*¹îÎ)†=í= ý©=u¿•žJ4Ohíoîæ¨ª®)—ï.ŸÕ:¹}_Ù¾²ýª‰ù•Í5-µmÝåå³kæÈMîž3mú䙓×.œ1eÍ‚é“LïªmÏèªoÔ’¨š]7gî¬säº{šžvMèšÖ¾±k_ñâŸöKØ~+Ng—ãbž¦úŸ‡sW÷~®ýÜûðð1ï÷‡"/»‹ endstream endobj 58 0 obj <> stream xÚíXytSÕº?§ÃÙ›Á ÑêÕsPD™¤EAD™¡Œ2–––Ò6MÒ´M“4iš9ç6i“èÀPÊXD¹°÷¡""ˆ#×»XrÝñîòí´•«÷¾?ßzë$g핵¿oÿöoßïûvh*$„¢izøÂeëÖÍ^øìŠ×—/ž8}âDÿoS}/P¾iA¾È`ßC!ü›ü_ ½úß3C£¨ ‡F7}z˜ÿÝ8œ¼©qäõÐáÔcAM ¦Ô£ÔjI½Bͧ–Së©x*•’Sy”ž²Q•”“ÚEí§ŽQ§¨êCê:õ-õL‡ÇnMJš4qâä¨Á”‰Á”À`êÀ`Ú Á´À 20˜>0ˆ ˜G¬"V‘«È€Ud`ÑÈ€yTÀ¼mĸEá£Ãõ#'Ž<%Ì û‰~LTÅÏ’ã·á7ð™Kp /¨¢yÊ…k×h‘ØuV¶9ÛÊj›öUAG`§êì²T…X–Ú˜Þ zªP…µ´†áÅgèRŒ„‹qóÐïºAŽ)}SÁøL ezy&’À´:ÉN—·¦­YÞœÌêQÒ``¾ïUE½ %èÁøfL¤õÒ]—“,×Þ¤p§Uõ¨Ð GÿKÈïz :Ž»Û â“µÉlÊ5æ#(ò]¸4TÂä/V¿»iãú9†%d•p&3µqØù-ØöêkÄr£¥Aµ×HÔ­ÈÙ´D§,R %‚sq³»ÞØÀ⇘ô‘¾mfU¢%ޚ݌g††ýüÔü'å^œëö=í¥OÞöÍû<Ø‡Ï ËÒÚ+,6:ìž Í`GvØÞblcm^fŽ>”O•0Õ¨ÚXàþ6m ‡45*@ùx>ŒÞ2—ÎŽG“»7}š|Zu GÊ>h;ÕÕ{íØg‡¡«£øÁ¦\Ãö*+MŽbËr¨–ÊóØHº,]¼åÝiž¹dÃ+ù©üL~¿?ÉÏéÜet®þèYBh0õFït›„ÊW„"P†ÊåînÑÆsw[ÀæDC+áC^&årLNµvpø%€Ê6‡­ugëÞö&«Ê¡²«w­h_Ó¾º}MMZ„#¿, eCÉVƒ’áb/P 9Ún¯‘tg쎾}eå'šm™ºÁ‰Çß:vøðÁãû{ôòI"à¬Í•s(+'7_­R«T*5¿„Ÿ!Wd*劼üü¼\Ä=àÀ.s'ÛäeHd¨G©ÉF‚Zþp#>ãî‹ Õóªqü°‰V‚ÄÎb2sŠ]œ¯ Ö:[ƒÉmö 7~Žº67>KÜ?qŸº¼÷÷©JbbÒ-û9¬ÂóÁ_­øÁ“E˜á‡œãi;äñ_ ± 4•”5³—’:þY%ÆeHc–jV!¬ÓoKU.Ù^\ƒŸ“¹Â÷]Å ½—Ü‚M8Ì!lví+iCmÈ«¬K­•E(nÓÕÓÑëk’eiñ(¾øWÉ9ö :èõt;âœ["xªùØ ®K²H´ ¢ä¢$¤×€;“º'/ž6ƒ´J«äm¬ËXÕˆQ³¼"à q"ÿ´p,xcݲ×Y ³ÁšØŠºà7˜9ø ÛŸá„ñpEøGw^»(èÙë›#U.Ý&Žo[¤†µäÜS½Y@šfÞÉù†€h¬ ®¥Êå$ÁÅN"7v¦ÉR_ÜГîLý§Ïg4½Üæç¸ ´yŠÖrw ÆŠ ›Y­gzeŒTfiå~ !güæÜ ·Jî›ê Ç!çßèʼnþ ³µV‹W¿ã= .Íð&+‹€ õ¢9Org0b™¥ÃíâáKŸ!xÖ¾€Ì̉â¢d6›é›ÛùoÏÅJ2Û«b±™Œ CKvsÚ¡5¥ëÐR´p‹|%40êžMKÑ´(1}‘ỈÿCi¼ûØ7i8Æëký$¸³o/¥d/e¶îÔ%p¨Àà/Dw³Áühm Á”ç—;þÌ¡c1*6úl6E±Ü¡8Å>Á?õ?¦‹g"¬¹9QJ#Sm´4XË/à…½xQ/^à¨/m°5ï^ˆˆKѦ°¹(§Oøq‡7¤ˆÌû8_ س˶‹%tJý»z(ôª,>ãî{UÚê‚ê‡cï¬Å#Ég ù°ªIS¥³lGÿêLðx,ñLÿz ~­·!ôÖ™[YlbêŠ* ‘ÞíqÉ…‰lò½“îÿÅæ_ˆM>·ïFŠp¯G| ï¾.¸s_LÈLž“½íûÎ^ø]­é,Ù[YÞLF#2Á2•QÍæí(ÈÑMJ£Ÿµâåª' ^0hÀL`ð§ƒ&;úå3X€ ÅðfqØ8Ê?ÈÍEo$o^¦-Ðjôj(¸u‚\Ø >rá ÙÑ‘EÅ3LräVë£ce¢ø¬4½y"÷cC9*+* ×èœx¢+ü‡^¼úÊ’OwZˆ0É@‹«0Žã;Alº~5+Ã%à¯À!œhÞ{¾u‹š€Àç4}Ùb|unum«ÙR½Ù‹àL>Vø#¸óîá¸eœh—­J^‰àFnÖ– ˆç‡àª±TÔ›áiFà;ò®2zöhm Gð¼øá4~”Osù†»hãÁSzƒ±À§x<úDi‘Πƒ ã¥óóø h¿4ÂÍX¢wwy›{L» Q æ:©¯m—˜Äf1iˆvॡéL²ÄŒûÁ~§ù8ëüø»Ã„™; w°üfF§1Ù9䨮t”ž¹nà+ÐYRêd¿dKò38þ$@:¤%K“Zpfø•osâ™.Ú}öc€wñ¦Ìj+Å#^þ¯Çù°ñäË»5 ?Æ]D—ŽÖõÍF ²@»Î¦a·#Cª*'=vx‚ÌÓÆÖÌCʽE]¨Bã9÷åK“¿m‚ŸíœüÒ7–†B9 µð;½x[¯ Ë}Ÿƒ(e@ÐÕW”Œ$ÕÜÊ‹‹6[çñƒÇ¯wÕ558!o¢ü¼ù¿˜É¤Ê,û8Ü9À¯$¤»[ôÛ8ƒZ­Ñj7¯Þ¸:fµ\¦HËL‡Ø ¼¥eç‹¿@v¨uæàuÞž\(Zÿ¼{fÿ/áaês¡¤éÒ R$EiÆ4kUqEj„‚Öæ —D¤Êæü-ûm¢×YÞ‡fà‘5H%™éR)J•µð—Ìÿý¢ Ýs¿}I Òö æÐOô}¨ Ý%b©e/w ×é–’2R!ÚÖÚØ±Æ¦.ÍF¹0K¡Ëõ›áõÄÐf¡å·ç¼½AYŸÕø~ۇߒîâgÈ@‰ÎRH!''K«U«#VÄDÇ­ˆXèÛ÷ïFÈ6çêC§3ýP³›5 $}ÂûÓGÐ…‡ùñ6»0‘+hIá"ÍÍâì§ ”Kê2l¬l¬mÈ©“d(²¤köˆpߣ2<ÑÖk9jê6Euæ*§Þb\%ù2Žïe¿$€ûŒ?"v‡ä]z¹o,äõŸtí@á*Làø @®y(.ݦÜLÄe± lNª}‡3â%IuñUÛÞ3¥crÇ(PZÔ©@&¦ÆTwºÜÛqsÏͽŸ[Ëíå–r#3BЕ ѯ#`z˜q¿’ E(K“23ñåä™ùâÜälÉÆÖýƒ)Mµ¡RŠî9`œÙ'„ýá{ä¾á›MŽùHÿ¾3‰Ô²‡Cv’¤6ˆÅÛøGÒýò½9 Åübò}£·Å­'\~€´ö'û¹((MExËgþjÒ…u¾•Bæ=ûâGÂ'/óàqxú ?È .ã!ð þO¬ KGîª:ÿ-’/!¥@pù?,ÿ¹À Òü»: œöÊf–Ä£ÁŠ:P‡©Ag½.Å/›â?ҙᗓ&/tùF»ý¥¨î†àˆ¿‰úhÚÂÝ•¸T´* êîk³I3; ìNÜ›ÑM„º……˜™‚Cø‘Ü ´.}k<|àF^+,œ±qÔÓ®Yp쇣ilHßß¾tð¯»øA/³¤´Яï§ww}oÃOKÜá„ÿü“fj¶ç!)L¯Îô4Õ×¶°èâ4×T1<䃞ãåþ}ä. ³íî‹&›µ˜$§£ÀR@.¼†4MNú¦1)ƒ<„G\æퟸñ`Ê6#O¡+ß®·éìúŸ r_ñ“ô·“ýçóQ¡nÆØfî®wÖ6ì²’›_ ãªÖ'sü!°!N¿•Ëp—k—líâð!ಗ¶²5Ì~´_U¶Ú&3¥e¤æã¨Pâž]²„ßì’á¾í®pA}½ÿ|+@ªRU&6®ŽpÏóÌsÏÛõr„YãÈGj”“«ÐææI"”›DÑ+ж£,kN©ÓZV‰ê¡`³3«6Uš—®Xw8¥‹ýuâÑîó¾ï¼Ýu»zã‘S~ýŠ”oeF&‡¤ y©²è´èŒèøk Ÿ']×;t䀞VT×ÁÜDêžÀ6a^ĺ‚nÜ×f–‚wÑrŽ_D^Qe<ár(O%ÁöýXÈu"O­Ë 9¨[R ëYA —n¢Ëøyw&C¹ëû3Ÿ°À%ñ(;IÔŒÀÔmò:æ/àâ‘([$‚¸ð¾«–ƒ«‡1¼Í¶¡·͉äžçr D9!ÿ:X¿:~ ;Åü]}úŽ„š¨OŽG0~Õ^r…ÀÑÙí&ýÈwGy8ÃߺhûâëÞ.§Á¬H¶[nß+ÂÌ_·]>¼…Nê^ù½VFpÅ·^Ó‡ò“2w“ßÁQ^-e Z£% „¢ÓåÖ> <þÒø³Ñ=úíÄ+Iò€“þ©ž¦Â­Ü@¤CY¶½9ö„ê :†ŽZ»ê ?ÄeèWý‘ÎÕ·›¸à€é†ÝVÕ³>¯»CeäöUJd£˜Ã>—e@¾xäÕ@[Jv’®_í vß·+Õ‚Cè°±ÓÙ^×Ú† Î”¶ÄÚMÎõ¦µNÆ€PU¼ýÁßš*]™àWJt×Kzכ̉ó) 85é\—¦;ÈkŒÜP_ëïÀÆ;¾î£ITG:¿ð‹Ÿá´‹‚#X‰S…¢Q|ÊÖì숴Ô$Q¬öSò¡dlƒ–É’Ë9TZ]WRæliô:[ê\öb³•\<Ïð£™{Hìo ²ý Ä‘ßÀã“ÀÄ?¥ÕL@/}•zVñ¸:á«Ì‚éæëÚSïÞosÛÜþ¿†1 zk.’Ã0yƒov Ë›~ìààÒYCÙ‡6ò·ÁG‡°SÇ-+žR:ú§‘ÿAK endstream endobj 60 0 obj <> stream xÚUkTSW¾!pïñQT®ÑÌTïU—ãtÙª¨ØQG­hk} ¢Ž/¨õ‰¼!OB$;@È0 ¢.«ë¨¨(PkmÐú§ö±ìèZvMuÌ:?fnÚYóc~ÎZwíçìs÷Þßù¾ïˆ¨èhJ$ß´!iתmoo]›’¿$>>²–~“ O‰ O‡'G“C„L‰ù蟋™JQTï„Hô‹Ä’ñ‘ø–FEÅQb‘(š›?wáꜬ\¹ì`þ´9ægOKQçTæ§ +ÿ³CQ¢7æR ¨eÔ j%µÚO¤SéTVT>%QÔ8Š¥¦R<5ZE½O­¥ÖQë©MÔfj µ•ÚFm§&DQ"*ŠšCD“DQoG]Ï;£Ûc¦Æ|G§Ó7™5ÌIôÛX¿OTŠð.i‘NU r”å/kæð´×WÕÅw1SSŽRmÎáb*Â&¡¿Ùøº¤»½ûXwðéU©·Îçöºœ^'øP£Ö£æJi}y±©¸$ù°4aû¢”„í:£Î…¨œ±e_QÕ·÷}ñÑí}ý‡¥®—©®Ùé&·§‘¿¢¦¨vÃiòÉ?L>]äÔÔijÐj†Gã’ÔìÔÜÔœ„mR¥^¡SꊌJ#(Pa½¦‰³Óu6—ÃUÝJú´ç›Þ§=n§ÛÈÆ”·ïðå4%[{>é\ò)iqu±CoE¥´Z§)äAî37nö¹v¤ÿPƒÑ£÷˜QlÙà…!ì¾0$:?ðä:N¼!sa­D]«¨–š•FÆ-Ÿ™PçïÂÅÁÆ[ŽNëq8pŒ¯"ñdît²€¼Cf='‹ñ2î:ôù»Ï8v'¸P[A¥†Ë‚·od¤I\Ã:<p ÂÔ—x*žÈ•? ‘Yd‡ª*ªÀŽz;¾î¿Ù²hÏöü%¹- d9‹b-C؉c×Åõ„°<”ˆW²gñÊ0#ñZ½6/ ‹wÕ+yB“düüö<àÏð«½=˜qºü /í TvU^K³÷ dàåñÜV7¸áqRÿòze¥ ”€¶-([ãWµvÖ·y¼ŽÌ‘¬`6­S¥ø°é*—¿m>[Óiï¬ì„HGëñL¬Ž»û›‹ƒá%$J7w!7䇄Æ3¹!ø¢-x³ÊYé'ò©kÔ{zx—½èݤÐc®´^¹ÐÑÞ|¼ê fÚÓXaà-Œ=¿IÔæóµ†~_¹‡×Óf(s…PqOÄcHï‰ñ$œ,ÁŸÑÁ:wë«­¯Ét2æ‘7ñè<Š€Ï]Wk\5õàŽp«uÈ! *T2ó ö$Â{}†²Jê‡z{¿„kл¯j9Š%ÊA¼tàÊ-ü‡—kãÚoæ…ð–PçMöµáåyÉÇꬭ° ÏÜÿ”ûð”®Ú gD{¿iJàVÐ¥`±•2Óìφm›§ÍYéušŽº÷}ßkÞÉ”3¶h[ÜöF§ÐØÒ…éýÞ¦Nõ¦Û„à +• ôRK¹¥´Ê ÜVfÓWKÙ熂ڼê<@ K“æñ[“S/«,µ— ê2}¹±¢Œë”×Ë‘‰H$BÛ•`ƒJÔ×ßz‘»G¼4­ZLÞ/¯äSàw͆kHøçgøµÄÉ\ùôÓKÜ_àÌþêÝÈÈìHKÛÉ킟”\D‚õàž!xø“Ò§ŒÃÆû ÃQÒC&0¹z½’«¨©á:Pçnöêëóx˜*Ì€á‡t‡Æ!ãȺ@«W¨ë´~s¸B’cÑÈ@†dÍ9í'|-Ç8öE@ÌâØWePVQ&ðË:Œû‡âÌxÔæ86ò±/pTx¦¤½À¦âÑ*µIöKaOb'=´€‚U(ɾk rU­¶…ÿ‰ö5:þÂ:aP ÏôÕ= ´îÎäˆÂÄÈŠŠe²F£ÿžö5¸›}…nùÿ“ª`nèŸ,å@ªB•©<×p´H¦ø»;qœ!û / OÐ>)³*¹å´BmÊWx Í<{ÿ2éÙA³Ïäú"µP&Àã¥t‹ÇåoÒ7Èùx1 ]öN_[KÇ©fAÑ§Û 7ñD™Îäk~éJH§[þ›žEä}=ƒÛ {Ô‡3~qá!QïWØckDªÑºó,ÓP1CÄIŽãêhãºÿ¼êgä`°x¦É$ŽL&ªˆ+Ù¡ ô<à¬ô\\ãHÎ%î‰_È-ƒÔÇæÛ‘!Saæ†]w ïL ±íX†‰¤“i+®ÏáH,­,,–+ô-<Ûú„ô$Ðì™N«R×ùy¶½ìÖjD?ÝduyÀƒ„r¹hçaD?é}…Çr¹¾Â@À×äX÷Õ®#ܰ-sïÞ_}h9Þ;„Ç äœbUxvxµ$Î×é”Êz½ŸÿŽíXÑ»÷ Ð£Kõš>¶¸6¼Êki¢°3Ühqí{cGÕŒm;æåèKc¸äõ–ÉN‹ô_ÿ ò—<â endstream endobj 62 0 obj <> stream xÚcd`aa`ddðõpqõˆÒv ò5030‰™üfø!ÃôC–ù‡8Ëï´ßWdضÿra•e``h‘-ü ²ADjˆ/B ÌŒŒ,’zÆÎù¹¥%©E ¾ù)©Ey Aù¹‰yh‚ @k ú„˜™2øþ3%}³ïßTVöS·\èû҇¾óþx'šÌ~ {ï¤= 8þLdïNÏë.éÌéÌîÎéæ.H~Â.¼awë÷`6Ⴝ¬›ÙË»‹»Êº9âÓ&¬—ÿqœ}VˤZ¹Êîºêš¦ˆl¿–€n¾²…?œf}Ïï±”íwh7»ó4{ÎI<\=<Üï¹örË9f…‰[ ÿ¢o^¼ endstream endobj 64 0 obj <> stream xÚ]QËnƒ0¼û+ö˜*ÀEI*!$b@âЇJò`/)R1–!‡ü}½6Í¡¬ñ0;»ë‰DS6z\!ú´³lq…aÔÊâ2߬Dèñ:j–pP£\·›?åÔ‰·Î¼wBtæE¥å¬F}}¾œëd ‡ 8ß ßîMÙÞ—§F3dˆ¾œß²Ú;ì 5÷øD܇Uhì.¢õL{3æ'Ô+Ä,Ͻ]&rmq1DÛé+²,ŽsÈê:g¨Õ¿ÇPÑò»³,KöNÉã$ÍY&¨*N“˜0˜>| | øèp4œ4e0ù”AϾÿÖ)ýë»( '"¸ä\9\n#Tލü¯žx¡™êSØŠˆô´™;Ú“òxÄ!oÖº—ò¡ù è¹F\Íl¨Ê¿=•× endstream endobj 22 0 obj <> stream xÚíZko9ý>¿Âß„Òí÷c4B" ™„ Ð>ô&Eh Ò¨»³bþýžkW¹^¨„ÇjW¨ˆ_eß{||}}]´Œ3i˜øóL™ÀÓA3©˜1ŽIˬDÀ¬WL2g Ì[Çg>`„dBYäš ¯9S¹AÝC„†,4qÊ%r#˜ÖL)ÜbH@;)µ†ô3.0£0Tp(g*@.0¨à,0mÐÉb¨³œiÊÎ-°“·è( ,ä`€‰1š!³Ôâ<:# Ôý:#“èìТSî˜/Xë}`³çï‘ «˜Ã? d¹Ö”; ¹£Ä0ç¥cPèBà ]½ yÈ¥ƒ|ǼòxÜ€çÁk@¹·PdÊrAƒ9 JbRŠ <þ9Þ™_­('XÆ£ñޱ @A,Ðäc¦ ŽGS%O“Œ¥@Ó‹%¼ÃÌRQФRQÒ|RQÑTRQÓ,RÑÐRÑv>.æçÇÅêl|¸½3~Y|^÷>N/‹­”m¦lïíÇ¿5¦•!¯CšgØZ£kL¤F_’ññÔj#Ëxn ã¨XίçÅ»5Šzùϧb|ˆHÅÕŠ¶)µo/ªË3Qö‡›Ãõúá~àpמ{/Ñá½Õxv±<‹ü·‰Y$îíø ¸˜M7çŸÏ¿ à]ËRÎÖ¢˜®æ‹{ìeqÊæ×«O×PÌ…q;âæa¥ºO´^\Ÿ‹{ÿž}ºx÷ñ3ûû:q®¤ÿûþý$d6¿Úž®Š{ÛÐxná0˜›\ýÎùï÷“¾¹šZœÄÖt5ý0¿Äë3½´¿ž»=Nñ׊’ÅTÿÚ(mÃÈ·RN^Ÿiáâè”SK5"¾íõ¬Zê>θ·¿ÁnňÖN6É+ó¬¿SÿõÐÊ©—íÇr«¬Hj³®•iì0£›ZR­ê_ÖbÿÔ†ý<"Í1ǺziKF‰‘B‹Ñ+Ò_kxÛGP\‡å•æÆ¥o>M²+Ê-CÃÓ{+DØdz×è§½‡#ùH%yž—Ë8 ‘A—oÓû@ËÎÅ '­¼ù2¥:b»Q VG¶,Ã(ƒ²»¥•Œ6Ï%'G’ŠQåÀìGþ9^Ï8xO\Ô¬Á[õŠcN/}ÉS=®åZú+ƒx߉QTJãë¶~j­$L#¢„æ[Y¶J~Ω\nöó°W_¦ {Æi3¢Û‹YrP°>A¹Wµ]»og÷èNiƒÓcL…‘í¯“ @c…ɯ9s%×ø|Ëžµ![×Ö§kgÊ™ŠtXö?n§1¥nb'2ä¯ÚanÇòTR1%S©%r½'_¦môh~ ›7ú#˜÷æ¯xdåƒë63¸Ël*ÿ7AEž DAJ[7· ò{?q©Îb“Ò#½¡ƒB“Ù¦ò ³ºñ !n%KLµÍ]€{ƒLÑéól¢‡ÕzSÉ›ZËÿà!hû-ò‘q“˜i¦Ñ•RÌh\Érª÷SëMUOãï´¡(³lÇz)BÑ4{•Øëi0.ºx!ßAôÚH´jïæßhÇ7H]§%•›i_BLi_YÕ•Ÿ¾Œ¯ÿµ¢ µˆñëÙÅêý’> Æï!³Årµõ~º“ã§Ó²,µ?¾:Ÿ_Ì®.é‹W¼}ÏO®fh*°/bÃætY$ùÏ7ŽOï'}Tº],ϳO«ù‚>ÆÏ--Põ{Üè?í³Ë÷+,´?ZžÓ× ̘úPyC5ÞõvþèêòCÁøøxU||_?Þù0½\2enÒ7‹ á4ÛP8Õ…Ò–ÞÆ—;³…bªüH„†gÓEzä ÌÉ.s¶Éœ¹s{''›O&I½ä¼Çœý¹ÌaŸm(‰óGKÚã²Åœj3×>Œ9ÝaŽ×Ä©š•É“W/Ž^=Ø:8~Ó7&7œUQÂ3!¼ÅƆÐ#®KJ°Š‰Çœ`›lúêNä8×6&Ó¦¤‰{¶kI¡aIæ6–ôèñ‹Éîs,Çæ©ÐºoI~8mîÛ-IbûaZ&¬‘¸6˜m®M[ú0æ|‡9)ïÊÜþó7_'Cæ˜q—¹ð“÷ ¯ö 6½=ÚÌu bNó/ØÊÉÛÞ9~òl7jç¾ï¼â=éç'¹*‰£ÿ Ê7‰Ó·ß>Œ¸®Û—¢&NÀþ21ožLö_ŸÂì‰>-âÌݤEßìÅœ\ëÅ$Û&~3òtÏlqÓqì-ôØéºuÝðë‚›š™çO'§‡'}´†ù½‰©ìņ5ö‚}PRÂC’ŽcoÂÆH×±{ÙdÄÖŒüut²EìõÎ:§~¬©øu¦"uÉ‹¼ÇKÇs7Áã¥ë¶g6OM^œ>}AŒ÷YÑ?ÊNœ]c'8£K;q}>:þ¸z†ßµ¬dòz÷õþqŒ,ÖlóÃB"¾ÖBB"-„>¶ÎvÓq´-à_æ¤>hLò´IªC’jí%Ѹ‡BÙãÓ5, Ž¥ù×8ªìE»uçíŸH6ôS„ÖntçúÑD<ÌdL—µ!ô£ÃÉÓgo"ï¶ÇÄ ¡ÍÚÄM×1Žó¶Å‡í„‚ ØÃèp]‡¢ïN&›û)&kÂÿsãÀ`)œ¡ß-pDÐʵhó8° }sá ·X!Ü-˜{öô¯Éæ Ô¿|¹–¹á´¨¶5s¡Ö-î8Ùé—TBÑÏv´n2gy›¹ôAÌYñ½"èƒÝíÇ»éÍmŸ8ÿ“#èHEÐŽ~ôÔ!N¶‰ë@O ibÕìÁÖÕ£«å,×·gïÞ‹âê¼Xž!Z.>^L—ïGçÿÀÚ‚OßÍfÅ„ct:W5,bUMš\²LòëðY‡Ï:|Ö᳎uð`²ž¥×ë²ô¥G?úRÿ™ endstream endobj 81 0 obj <<68c068f5945fd50060fa3778c7d1eff4>]/Size 82/W[1 2 2]/Filter/FlateDecode/Length 218>> stream xÚ%λ2C…ὂ$nÉq;HwBÜ/ਵcƘÉèUÚ m:½Fç<…7  ÿ¬æ›íjGD§“‰4òƒ.˜„2LCæ  °+°uØ„-Ø=8P#¨Ðã«[ù— GÉ·g²Ð«RÓ·>ÕÚ®~Õ_]j¤®A\¶\E½»g]Cºxs ëòÙ5¢«¯ÿ¯®?=GuSv©ùâJuûã×ý¯kB­'בW ¦`f¡ ó°˰ ë° ؆]؇Cµ?"þÝ"# endstream endobj startxref 41951 %%EOF glpk-4.52.1/doc/notes/updating.pdf0000666000062000006210000012153112175147600016133 0ustar maomkpasswd%PDF-1.5 %äðíø 16 0 obj <> stream xÚíZÝ$5篨ÇjÑ;Ÿ œÐJpÒˆycx@ËNbvuèNüõ—;Iu§ª»·gaNB«Ù©©rÇ¿ØN¦×“šdü§&“srzõ0½¼›>øLMÊ Pfºûq²&>M%ƒ@7Ýýðí| ïÑØ{´2þŽÏwâ{ƒ÷èpw@•ÿr÷¨M¡Ê¿Uüáw°i´dêôÕ¿42ñJ”†(­:”a6‹?ª¥AÖOœE“»ïîþ16LP"(ZÀ‰h¦ð5–øëô¾òƒô„,¤.ctœÓ˜¢RQ%ɲ„ޤSùk’åƒÏ`RQStk¸é€RdRŠÈ& ¡l{Ô…c““W˜d Î89\âëBzÐuá*åhöƒ“ÂÇéÁ G„u"£ÊÔ ¥g!4qÒ“’"È9)TÂD/Á $²“¬´“ ¹=/©%McºiBH“ÈÂ&îXí¼” ¬°†‰«Kh2X2‘•;#çÎTé=É” kʳs»ƒVn.T™šÍáV$U1~ ð컨Á¢ÀFN2ÍéLYt¸ò-zNüq‡ãIнËDû<Ó¬6…$Šdȼ>d:—®“¦5ðÓX/Û:)Ÿ8ä†2c ™}—‘¤1Ç¥©È˜u-‡yŽ$šÊ³>Z›§ÄYç2÷¬,¹TÓqÜs,óÒhäQ%#9Zž!Cå·éM¢«jb̨<¥œ;°£Ù´K_2¢z³½¦¾Hê˜4.-“µ=2#Y0ÕÍŒÄd óß¿øêóJËâdl×ET‹mÉ6‡óüLFòÍÙÈdR—@ZÑ;ÓËT¤ ,Y>IÀnÁ²½µk¸²k” èe1ËÉfò‚ÂÚöa­­Ð1•ª æïDåz˜ÊQèàšJ»LÞ]ÀË30 .lÂì~è ˜üþB=¾mˆR 6E’°Y”,‹œÛðR¶2fCDu BZ3\šaìÖÒpà"˽^(8YZ¾.P(&R‰ñ ukúÂÝ!¯=ØÛÖ7 oްhé]>,Ý+˜-‹å¯ù/h©C´…æ”i#Y®¤Ž´ô¶äÞôuU+ ñF§Dv¹áw“ t7©ËÇ`³×bâR24L,mB±®(-̸2^°œ–ç¶ßìêâFŸµ˜ÇùÀ7r?·ÂûêcBÛâÂKhMœ$C«UºÔ>Riü‘¹hKN2çY—kd3{^JfÑp¸ñ&^5G°‡®ˆ¬¨°‹]eÁ[òس™ÙÎìÃôõ8E­¥ÁÂu8}åì k"¹b’FÑçDÉ=Rrëç>)æj"-,ËÂ{K{¦ÚÊËl_Íû•,Çt5«…ó™ßvŠ—l¥•-vª[”gÁmC1ƺ’æ¶w‹„¶‰¾ó±Þ—J.ûTVŽû1‘Þ3IŸ…hÜÈkI̲.Uœ€$Æq®]áØ-syǹ<´J€´jxQd:ÝAµâ«µ¬ëª¢Fž+ºÜèKO­–ñ^Ÿuwa|ÞŸƒ°:_…I’² ³Õ›`re›žúê«Dª¤z|ÉšãäØy*ä@説䌌É–ÖôÅjÉMßD3µ²ŸÝ–® [<»µB’Ö]ÚÞù"SsûÊÖ¾ôõuÕuþb FÝ7º Áè¸ÁXfëöÅÞSûˆƒËŠÊsÕãZóÚ’líA’£ËõmÈb¨(}® ‰jVÔ¼Þ*Ð ‘‰†®Û¡áH¬´Ýo3F’ãém ò¸ã–•ëâ›xÜjÛ&ƒÊ´‡húÏ®€ÍŒ^ØeË«mÅWeqe›<ÎâÊÛ­,a3‹«[=Ã=¶¦K¤ÞÚÖ“ä(Þº«áS´,%²­‘’ãÒVþÜ0 öñ<ì)Ä:S¾}ßcYÌ×*½Ïá‰Çº˜^ ib['(—ì/vÑlù忣 Û ÅEÅûêÕ¯éõõP¯±¼ýSôê×ôúzÈCùg«×ÇÁ&Õq·éŸX¯#1`И{–·ËêW»rN@¶Ÿßˆ-s>¶:•QÆl /”£*|4ãiÂÓD„?k9ÿÿ„4èÖ d>rGùî‘èj½?o$ºÖ§G‹âÌ;Eª§Óûã@†H)œ-H¬\kñâ_úª¬´V¸þ|âæÝr)Ï¢ºé:‰¿Ž±ÁµNâRâ©WùS¯Zβ€(vË­|M?‡|MŸEQýFó9½»^ïcò’nýšn·ò9éváÓÃ:&ܨZ|bÕ>W0 ¥ð}çhè¯QÖÃÈoâ×3hB©+¢òáj\:2ÿ ¯Øv×á’€}¡Lä!Í_hx»OÐ0Фð™âaÏAx;éø?]áœaå–¸ìS…Ö}W³öøwغ–FïwôšrõÍó]9ú¶ÚuMkÒrƒ°pZ9.àã£ÂãÜ¡QŸª¼Lõ³|C¾-V2×åxèƒùäº×âp Á§›±ÃæëñYÕòcM×¥ºç.©¾øL§é¢yëF)´ºÅHï ÊÌ*”Ñ¡>nk½–s…Oï¦×“Àà§ÿLé†It+›î½˜é!‚Zꋟ§o¦¯éιŒ…jˆ¡›*Ö|S"Æ0 {|ƒ9b^jàØ²„tŽAF[Ý](”ÅΠÍâ¦tÎs]žd‚¶|veNO3ø½r‘{ž@uaý°~Gè·éd¢6óíé±-‚Åê@ÌŸ_ì"ެˆÃÇõûz¶aÒþ+ù:á=‚äã>b¯ø…(g)Ÿ¾ÿ×ϼa)hÖˆÕsÝÞ>zøþ—O"!ˆ7¯ÿùoñæ·¿ ì¡ÞnÛ8šv³$3üéñ7ñË›ŸF¬¬J>[hÅhcÐq­Ñï!¤;M-?ŠÎúõ{ÿ½´ endstream endobj 22 0 obj <> stream xÚí\Ko$·¾çWtn¢aHVñeÃÉ!‡Ft0åÃÀ ^ :Ùð¯7«øhö »ÙR¬ÉÂXÒL_õøXU]µÓˤ&ÿ©ÉéÉ99ý÷óôíãô׿›IId˜œ¬ÎN'k„3Óãÿ¾{ížÀê'0ö P=ƒûHŸ ¦Oñ©ŒÓO¤42Q;$*©ŒÉcã·6R;[Ç«³q*Q/©L|Š&¯BsaþmÔÿyüG<‹k΢A åã‰ùw™Â6(´ÉÏÉýäDpÌ ¡a:)aü³³‚2~,O÷sÄç@¦xÉ-Çðvªñ8gÇE×c$±Ý¨Ê"¢“'žý¤]`*¦È8MC­ŒCB™Œ§_‘ËÕõ$ê‡BN;4ôâÉg’éo§ÒBq÷‘© ´ˆ ÷ŠìÛÎ Nh?™iDö¿ŽÈø[)*K]àl,­iX¸×î®0°s6BB>\o]#0äǧl!´pf8𬠑$¿T̆¢ŠÁÄ£Ÿhß$r2YÚ+íÛ°¡¶OY^˜NH2åè{mùù‰†ßk—ªk“ÍxASÝé§û¯:"QR Í„¶­®c¬o•ZP}(®³%Ç>‚µ½”ÃÊÑÒV(O_Œ œrúKrÂaãeg›Æ?fTðîFÕî‹ý#]ãø©‹Ðž_Ë'½[ž{^ .÷Þv\D¥CÝu—ºÛ¿Wàл ”äÏ& mä§™€ÆìpM û‚{¡8ñ^Á¸®H4îºçQz­€>6øØûþâëÞ*1€ŸŒ¢—é$¸ò ‘émIËšeÕ¹zD¦ +ÚRMB²¦}õ¸¢Ãæ\}ÎÙc.îâz¢4>§‰¹¼G§œ<—_õ®°ÀÐ-“,íÊR¹­œíœ²ùáB†IÛu(Ì­Ý}ïV.qÄI¡¬Þu"ή˜Üàî†n ÚÜá¢è EÅ Àš”{4Vï-›óþʉÇ,œ½RŽ bþ¼æïðÕ„‡J™ÈÙ+FïY´v-Üfܺ+ã8r ”'ŸU…*h%Žt¥»Au¹fÑÂYÆ14–zÝ”ãÆ©;/^p{²í]°L7Â0׈‹uxGv‚SGGCò pl'¯Ÿ× : 1>ƃéž}‘釔ávÁúKH2îÔ“s)7N0ºí£ ‘9Øè[Tr#}Ó2Í|…3Çó‹øG~q~q_­à¶ÿrôwÊ-JÇ1õ ·¸ºaºMt¬Ÿ¡;Þ†nùpÜqºtû!tûWúÙnÕÍ~kÎïfJgYE?Î*†6i5ŒŸûåo~WBQ½Zcû—ȱl"(.l®šOtÆmÕ×À¯–Þ¬û á[ä÷Ê&^¯|÷mÕЛ(˜c­;³]MéDUš9åœEä,¡Ê5¼vζ}ÜÇFFévt¸•îDÎQš\¡ZGoÕ »¶fØmu’I;Wû6—æ6.àÎéO,iOéÏ6˜{å”åTxÛ*W*‡][9ÌÈyvJ³šZmçîJN ¬3yœÓ­m™u¢¦y\a!ÔñXÖZV5s:˜ÇH¸÷:%ˆ¹Æ¹4¡VJ©m™UÚÚ:ïL–öч2õÜ蛫åMfvÚZf£Éý¦rɽ¶3´p¬(X­Øp^Ù¸?KǵJ(jîR­eûXž])½­æ¢—›’w„¹¶(1Ïíf-2¹j|mÛ~gݬej[k¤4\žÝå{l/ÌÅ,ù¤}¨Í½õSeéúl4¬ì¨ƒ,ÒÍˀƒò|¹BœÖu&§þq¦4,j¸¦Ñ~Uyþ´]V*;5 8X×W"Ó¾‘PA#JÿV±ã‹æ LÅþÚV\Ö,k[®=oy ]]´6Ü?äÑüB'}ÍÌO_šL`Ë{þkó=ŽÅ»å†3,Ô"~ç ™­}ùu]NÓjWfäÜíBåµNÞ¸óçíåÝ|½°ìí¥†ƒ +ÿöœ-õþöhW¶ÕébÑU&•¢~1,µ¼LÒÈr ðè5fƒäwÌÈžÚœÏÎÓwú £dÌ endstream endobj 25 0 obj <> stream xÚµYK7 ¾÷WÌÑF3ª¨%%È%@{è¡@нu{jP ‹ÈžÚŸ_R5[ão²X^K¤(ñãKâô<Á¤é¦`¦ôô×—éÃÃôÓ/~­’NÓÃß“ó*ÚiF¯‚Ÿ>ýqz´è£é­§o¤ßÞÓéç™&‰ÊÓ¬£QÔåÛ»úíWÔ>üJC'tTh_YÚ©R`¿'e|ÿ¯NÇ)¨x•¡ý‚” ~HˆJÓO¡x<_­A\^ÃeŠçJ°Ò‹òyBñFNíô`¿@:”ÖòÊ`žE…p*ŠESUe«âY¥X)´Á¦îªRgz  Î0×>lp¶9ï| }[åÅ"nâiŒr~NwÎA™¸§ïàü:„3à Nçý©œÞãÙ†å m6,Ø D³„ApL…þ3:p6<†þlâ©[ÛN–iÏÜŽ)]áÄ:‹öœÇYf°ýNzÔ²åȘ)2É4ëšYóÙ#[M°a—”5ÀØÛŒíY×U,ÛNðÝlçîbÃÎ0¥Ù°Ö2“%Ô³fýÊzõs9R‹l*2e+¬rï„rû¢ÈLͺÒj2²Ùb¡:lv/ ;Ç ýñÂæñÞfÉ€*‘c¯ö¨­¾òTÏ®<…¦xêó(?€Š~j4ïE!Ñ26e\ïÛB [Žˆ€÷í²ÏËÀÖÆ…¢ž7Û§µbbžGi€În¦¤ ¬ónt6Ú”-Xb fýAÀ[úd§€Ÿó¥ l¤±E«àŪ¾> æ}%¡eW4¤¯z­Gi1©ȶÔ²Zm¿›•: âdµrWíù€2°¥aKZ éöÜ ƒ´Jû×ãêXÙ§IÊb«±Ž¥îÀÚØî„udŸ‘+½Fr—ËжÉ»ó­>=”b4'÷¢(V×¹÷#gêúLAÌŸÞkIP š?…Vô¹¶&d÷5ÈAŠIÍ­`šÓ1¬Ãt¦pK6¡ßEüu`­ëŒJ! xe¿ŸG:CÞé·«ìë° uITu¾ŽücÓl¬fS§À‘#± lyZcKJ§›ºÐÿyèiäÒñ2ô_ˆ³Ê *®—´rFÈiŠöL‘ÑØìŒu`Ë…Í!ù°m¼ *ë„–ø” œÐ÷àXØváfâ‹€a4ŽäÅÏ£e‚rn©½‡iÑ8]sã8H‹)2¹0¹2Û¦¦¨ ò{CÂóÙaË|[¦Ý1LàJMWÕ0d&¾æ4šÄ FÁ‹|à ßË:ùÙ+¤d«’gdBT`ÛÀf¹Y]³‰Žë¯os¥Ä•éU~ÆÍô|@_÷€³Ž,)¿-ˆ²l¿g§éNCÝõ.Ÿ½Q6šïªÓ°©ÒÇUu‚{Ä Â}ÊÅ}Åj÷‰P„é>P¶J¦.™Lz’ º’ ‡%_‡°…Ú´_1ϳ·*¦ñå²Íb½ŒÖ»ðê «ÔPõÚêånõ­GeŠåжh9r™’¸jÍ2¥²Y#ÁäÓK ƒwÁõcã{X‹ÎC!ñJÈú ž²yZªýÔêÄ.›wðÊæ´„Â×­N8Ê7¸:q°‡Bc[PøNÕÉA=_¾Lö¼ãÊøÂ$îztc§)e:r8à0N Y»2°e‘Â4¿Ç:ÄÓÐ"IﻑZÎpXÄÅ­$ÂeÉwäÅ%Iy!°Þ©4)%Il¿·à@Í÷p‚ƒ“Â~ò¼å=Qé¸_¼ $ëb„taækŽÙ3ÌÆv‡an€‰/󺉯`àaS™{eÈKb:%©{(’çW¥=(„mâP2D#„%\>g¸ývCôîu ‘ÄÏ¥-²ÂV%b¸á‡p¬÷«ƒ<ÒKDݹ±cumh”¶„t ï4õu‡(¨»]§¸:Eän5jZÛÈÖÇz½l¡ì¤4Zôª³¡û®ƒ“‡µSákÏ®4 V­ŠA_É×¾’kºŠéRW)Ë×mnXÙ½i„µe’%™EbëqÅØ:dÂj“¦”ôÁE (jÈ|£®Fk®t›Ë› *m»üf—»5Ã~Îñ,ˆÛ®Fß@¼P@×BÄ‹bå×EÝYPMVw:Õ‹=H[±®Û¿>Ýjò.»†½ùBýæR”Çy«ë%À:-u¿´ž½^kÝÙ¥åéò@w&°´«ê+jå[·IÑ4¾|ÖÆ78=U»]´u¥À¨N³×N®LÌM%袭_=¶~ªš‘êS‚•µ?þð?ã«v… endstream endobj 29 0 obj <> stream xÚ¥V TTמÇòîC)I!“NÚdžÉikÛ¤®©`LR«‰ •W6aD6™˜…uöÿ;Ï0lCp €Š(¢hÄD‘³˜hö¦iŽiÓfïô¥'}N“.öôœž{Þ=ÿyçÞÿþ÷û¿û?Á‹‹ãqë¶G6d®Ï¾wëº-KS—¥EþÝ^Ê /‹ / ÿ Ž]þtgüÚ¿nŒ¿‹Ç#üßÌe·Dæ]·r3ïÜ”T™Ì»ƒ æ¥Üù“E©«7nÙYX.iÐY}CGO=wñ?ç‹öí[ºdÉò´ÆŠ_EQcå #uIÔX5–Gû£FtWjjÔˆzNúI‹úI[5¢Ó¢Ó¢Ó¢ñ¤E¦E¦E®\¾dÑòµûË+Å5EÕ 2öUW,ز¿<¿â_~rÈ _ò^á½K¼÷‡„/cX¤$BKè=a €`#a"Ì„…°6ÂN8'á"Ü„‡ð>ÂO´ò1<‚û•w•€˜•1×b3ãÖÆ}¯ HÚÐBdD£öQ_$ìMx~Þ¾ùwÍw%&$v&á§ŽNÜÌÏŦc(雨[~º€éù*±›8}×_ÄõWb±ç«Õü*ä7ãjঈ•AêUúeMéÙÙùâ°2ëŽÌl¾Þð®žÊE%Z‘°¼ û{Êȼ*ÓQúÂw˜ðÚ~À…0#~!ûHúéeÎUF°l`£†YBB¸ . zЯOòÃYȯ 0­ú/•W³€]õwdçl5?ÖH=Îâ…ä¦:ƒÌx·÷á³€ÁÏÌÉ#§ÇžÕN»¨¤oˆ+gŸWÃH“_Ày“OáûR>ùÌ÷8êÅÁG7Ò{Ñ` éŽUuê ¡Z5ýµªga.[§(†d ú F²‘)ׇ-Ýæ!ꕺí¨L“+¦|"ÒOtÓx3‚>CPѽ|k0 ²áÉJñVMƒF ªÚ'ïìð{;;ä~©P ƒÖ@áR–Çÿ9‚ô‚ŒuJMæä žü £Ñ÷é¹}’¯6K“CíÒiÜ{)åú$žáÛ¼Ñþé•Sã¡)×YïQç w`œ17(‹Î¤Ê J^§~´:µ1#wÑF-ûs¸Z…XÞïŠãp⛘ÀqBÀ±ãXY©òAX¹Y¼–cø)WÁn°ƒ^v}ðÆ€Ïê7ûà-ûµ}5#cê ²´‹r”ï­Á*È»Úr™Ò{À£÷PIá6v$ü¾”ó&cqrx-_éAÁ]. iÚÅ¥)÷•î.T(5Jà»N Mnjӽ½ÁÞÃ0Î&Ãd³+ÝZa*7VPR‰×ÅËÈòJÓ1_Bí¶B/b¿÷µ€/VjåBv©f4f°‚Ãã²:.~`Â|ø”j7‚Âß“]`m0J)ö5¨ š:µG½’ðSR"4ƒë§bÿ„ù8D:ÌF矲?bãÙy«¹‰ áž—Øœ¨¦ìäexa¬ý%ÆÄ˜ÀÁV+¬m¥ºAœ—³o;T@©Kܾe\s.SŒŸo¼6òÇwà ô=lÍ46ê ÔÜó锄×p¸§b‡"° óú錉·u‘m0œ=NÃA¦›ûp‰Àµ·µØ[<¼ø™ÅËM-¦z§ÁmÓîþáëG®|hq[]&7Ã~!(–©¶sÒýrT]eŠœ=ØiãRÇCb0ÊTõ¹,¹Íg{o8NPoŒÿ.iöLÞ”4µ¨ºÆÓ«¨Ûê mœd[ ú˜ ´B«¾¼Zcƒ±žbß@eÍ ›o’VN/žì &%¾˜ÄžK±Ãa®¥ð §jsè¯s¨˜h¡D•ú aCÎì‘‘•5¦Íà';wOÕŒÂ%‹Ãq4ü.ÿ·K‡kmµ¦ZNm¯ç^`/«ækÖ² ?*kÓ³ã4NEà2¸ÁMM]>=õáa6y•ð»Ò ƒy˜Ã8Œ?çk™H¢$J™TÒªhooõu¿úàø6y-û½lÂ[÷à[é8?¸h41NLȬetœ>€B×,ÎÎ-Ü RXêÜéÃuoËԵ|Žž„‰Š@Îvdl\8â nbÇHã0sª£«­+dîjìajëhö±FR®“ꤜWN ´þýHT¡Ö%`Úz„ƒä È,l'œMxq¯Ë?«lÿèqþÛy MÀ¤Ú³Žkd*nÚÈÌ>ù¹WX+«rÁ3j(‚½ú" ÔZEXŸÝ{þŸ”áÛsg `!½ ­þÀ´ÐM1f¨bÈu<³o§°J—³rãA½½º|š Êú¡˜ÌV Ñï!sÃñÎâ%¹²ÛûÌ3³§&s§–á]OM¦|òŸolDÌo Ú_£Ž• ŠÚ ;ò™< îÇ·“7JÙv7ÿ:y~º0ý±Íy›èÕ¤:Ûi|2Lò•^”r½;È {•#õ¬<á—¢J±å,×1^ðRÜC÷, x—ÛÚIv· çź~˜`KœÇ$ÎÿxÞÄ|áÒH‘H´÷›ÛþüHÊc endstream endobj 31 0 obj <> stream xÚÅUkPSg>‡KÎA-1Ó¸«9Úmi•E¼€—]Q±VÝ¢xATîV áN !äFòr…BHPÄ *¸‹¢ˆNÝ"ÖÖº;umëXÝ­]§µóú1ãžtatÆß;ßÌ;Ï|ç»<ïó~ÏyIÂÏ Iræ®={·½»ç›â¶-‰÷Î-cì›>ì[¾ìë~x¾?Çßðs´ÿ\‚ C_óÆÀ\$¾Ÿéos!à“b:Iòç,‹\·%nÚa9$g9²$<|Iä$X>"&ÁŠåS jD.›SŸ"WN‚¨©íQSÛ£"ÃÖnÈÎÊ),HÏ›·-;-=O2/.;+Yò«IŽqpNDQÄ5b˜!ßOÈgäsâ'.…ÄkŸ˜MjÉ*RGêI d5YCIi&fú$áC,'®›|¦ù´øò}ægôõOã­ä¥"¨´zúKrÆw5­Eÿ’¶HCø×ЬïEZi äѹ­n·ËÙ!â·¸ ]¹"þµ*Ðé«€æ¶<-º,uŽÿÆi†ôŒ"Û( •އ p\‰+àÏíÀ (Fd硸æj$‡g4¿Í‘ C8ZÄÓ€V¯ó&Bz+ØÀ ·á#ÓíšS¯ëtË©îÖ³@£9•8u1³ž‚õÚ59{Jgd%­æá Z+ZVùx’‡áö¶‡Dìß/Y§Ày»àc ý9r  ¢W¾·aÃ*aQAQ~Q~A®P­Tjáh š%xn´Æ¿§L¬ÙŸÙ ÑesœVñ®\½Þï¯ÿ…4 yûSL„.]½PÙµEgÔtW“«W™#Û¤5¨tS‚œŸÞr¡¯äjë)¾Ì„v Ç=stãŸ4‘´‚‚ùß¿÷¤Š¶ñžÿx0Ð_ø—NËdµ2{™­¬Nn¡«)þØëÖ ó0m£ÆbïÏ_±xwﺞƒK¤ßÄ{üG`Ô›À÷»Õf£ ìàÉo.ï?ò0bèåkÖŠÖBt¿â+š?Öʾ.¸?rþÎGŸ%­AÜÄ$‰V§ÕrÒëy ÈwÊk÷u 3[ÄnÍ. Ÿ/¿Xað $»WJžìHP‚‡ÊIm8Í€Ýl7Ö›nØÚg›¹êÈyõ`¨¨©lÙ!´Xó­5*c%(iÉ~}ŽH‚Ìžª ÇêËë5NMS ŠíŽEñšæ*W”ƒZ¥«P ·áí±xû¼]~@šòGîÜ]¨L€hôÑø¡ÿôŸϸ?W_¦=þ¹oïø:¤‹êêÔf0 Ò«AMOTR[w«’¹+3=ÔÛc`/šdV™Y6û&Äo áÐ> 43J«h¯Œ.cÚȦë»ë»ºí]ÂK¥Új˜‚ÒàM#]¬‹Ê¡Ü Z‚šÕ8È Ç—×$ž>Ò¡ëŒñ}¿0’h’2ª.µ‹ ÎPu4b(Ù9ôtÙµ•[W¥ÿAâ(mkkr¸Ú‹ç‹P*æ Qüþ˜ƒ[cÒ÷v^Á7ï{`o¨nÐ7ÔxöÌzÃàdääþ'Ø ‚âVªÃ­MbðU*½T¹C$EÎl*#ËØÇ [8õí5ô0o®«Mx6ÝÊ«@^Ý™/öOƒRî¼â¨,§”ÊÎ6žeªm6«ÉÒ3 ìê»qé¦Ùj±˜lÜ"+Žm™\(É1^dÐUª§ÙrSäÀYÅÊÓQ•Æè*+•Uêᡸƒ;“ÞW+U*M¥µOZîŠÔÿÈüök šòÃpú·hÑþýÿ#%4íkîÇ$®¨2á(HÌ;ÍïrX\V8I·»rDU¼W~¦«…:}ídâ8Þƒ~ïdµ’?£Æ1ß6Z i¦:;ª’™‰$oz*PÑéYºLQ™ey yÙ¹Æ3ŒmnO,¼ ³QðcD¢@ä‰|q0³ æN¥G(t«šØüu±‡åªR­ èÄ—¯2h5õz;ÔÓ7î^¹õ¼ 7‰¸Þ£Ö«½„ü:žþ·ÞÔQCÐ$vi»Ž¶‰ëÊjeõå´žªPT–)Ê“ã…iû’cõ´­wREÆÊh‚¶¦¦†&‡»µÝáælÞ’é·‰kË›‹¡‚ÖP “*J½ëœ j/H[_Éêɺ >¯±ª­* m >ü°ñ^íÀÑÅ”³®¸”B¹¼\V./—WÈy}J®ã”tº¥n…½ØÉåQÍy×ak6Ð\Q¥-lôq$©nlãáx D¾ukƒ,A† iÿ¼2M‘n2™Ì/gýÄÙž> endstream endobj 32 0 obj <> stream xÚ]PM‹ƒ0½çW̱eY¢J",º‚‡îW,´Ç˜Œ6°&!ƃÿ~M*=ìaæÍ{3ó†–MÕhå~9#zè•–'3;Ðá 4I •ð[³¹%´> stream xÚcd`aa`ddäu qŒÐvö Ž´ Øæþó—aYøs>ëY†rŒ?ä™~(0ÿg‘{èÅòŸ‡I–‘ODròƒHf É $˜˜…Ø€&J)öM^”X\’Z”Yœ›X’‘—šžX’™ŸWœ“Xœa``¬g``äœ_PY”™žQ¢ ‘¬©`hii®£`d``©à˜ Ô—œ˜§à Ô™ Ôää(ç'g¦–T*hØd””Xéë———ë%æëå¥Ûiê(”g–d(¥§•¥¦(¸åç•(ø%æ¦*€½¥&ós JŽRðÍOI-Ê:‰™Á Hµ3v0032²lzÿ£ƒïÇòµ ~HÍgüÞp”ù‡áw Ñ)­}ݺ9fÏœ1W¾{^cÍ$UÅÓ¢æç< 1¹oÞ”É}S'öMížÂ1½u^®ÜoÍ™ß5zçt.É떬쮭é«å¨gŸù[ó·äó¦‰ÝmÝ’Õµu•òÝSÛgµœËYܰ§ü7g˜DsGESsGckGcwGå̺Ùr“»{»—ÌýÎ~[¢æ·)kùœ¦3æL™/×=µ}u×ôöµ;ÖqðuÿÎ^ð‹èZK™ý4<¨¯ŸcZÓôZ¹úîÖæ–ú?ùH4×uwv·s4L©Ÿ)7½{âäIÓ9øŠÿ´_Àö[n:»ó4Õÿ<œ“x¸zx¸wríäÞ9—‡ˆy¿?ÈIÒK endstream endobj 36 0 obj <> stream xÚ]W pSåÚîi1ùX®‰ÑÜ;zŽ‚ÞÑ« ‹ ˆABA,¥h)…î{“&MÒf=IÞlçdk–6i›Ò-] ,BYDdQÄ‹‚Šú»Ì茌_¼çŸßÿ PîÜÎÌ7ïœ9ï9ïú<Ï¡Ò&LH£(jꪬµëWl|âµåëWÌ™½ð™Ô½ç’O¥%g§'çdÐ_®œðÇ”ôäýf ?p—ò_ÿ¸ëÁ´4Ê~Oê,øsê\3•œi'ÇÔÓÓÒI’5ÉŠu›¶WÈ›-\¨+±ïsŸì()™3{ö¼gnÏÞ1ž7æ oógóƧÇq¯ùã^óŒãî ÆÝÌ7æŽã/\0þÂãî ÆÝΟ=kÞKUÕ õEµeVm/ª­|hE}AyIáÿ»KÊ€f¦}˜v-ý:õõúúƒÔänŠ¥,”•²Q@Ù)å¤\”›â(žòP^ÊGù©ÕJ©PÚ}éiTZzÚÜ´«”%ý©ôc¥¿Oè¿«R´Lœ¦ N|uÒ=“'M6LÑþ©ôî§þ<ùnœõõ36K[Ll°È*6rwŠÚÝ=!Æ!öêíFZ(Y€\6t÷é'ÏýKÑ÷ûÌ> ?~%ã÷üäÿH«OgöfÔÂ*Á#è}áqüƒ§žˆÅ°Ìî²»Á…œbgrÁF›Õh’ËÊ„´é3„‰ ¹ñ²}U»ucpºqW¼ÿå$~Oº8?Ü>§ ?þjh²ªmf+y2pžÃg÷½‰‹eÎ ‚ r³.3­­k*I°Ô÷9iúXòÉuý½ üù)W˜¨Ø !|Ã7dwÞŒŠ7¹ ´̬դݪ·ÁÒn !^ ]\'×y ëdNŸËo÷£X³·‰®}«j¬í*$9O}TX$Ü»r`ÎÌÛ0848„ÞÂa©­…m±èŠ…‡d­µÉÔ,ß´.§PME÷YFü{<ÃÑO÷âû>t°#«”!^ Ôw%a^A}sGÞÏÀ ñRh õû::;ÖÿåQü˜bìG¶œˆ7:L´Y¤¥Ncž[.¤·,[µèå*ajÕŒ–m䣌-ú?‚3ðÓøÞK[¾|‚~Öçç›LFk@Ø»]jZS$(Ж»Ï0¼Ø9ìô …NµÛ×ÑÞêtd FÒ1ãzâê(~>6í§sØx¡aDr#9Û¤ž..ìnkK@?:¶.±R˜!H‘0“†ûfá #ò‰$Éïà·±Èp6?‘F³¤†6®\hcîÈ7{ùcí ž,>eÎd€µ±d…ªŸ¥‘«—¾øäÆžƒŠ-³„¿êžeä ´7º]¶]ÉǢأ¾9ŸÏH.Ç¿Hõ»,Šhc[=W È$ž4>-¼ BÒˆùçNd^…/áÜ'£ç':δ  ‡·Ð·ÛñÃÂý«›å&—™£"¯Ãçñ8Ã\ØôUD ^c K™mÈBŠRã¼×„õ´^>vˆ ˆýÞO_ø|ì‹OFƒ|ÄM\NtlÈeÀ†[¥Ûß—›*] /ê°)¦ýp³Ã’+øJ2S*ܯyT˜ ÂC°dàÉŸŒ( ºßì}×ét¸È€º ~m-¬Þl.Ú¸¬`% µ§õ¾ÓƸÀmsº„¸ðŸÉOoåöåÐ’+,˜I‘ðˆ%•üºtæÛé©)ž.̲ýWjàÎìØq;œØ4|ãÂæ%¿üxUïŠô¶«}*Æ,*g›« -ý¸ì=ú|×;ú/Ì·C;r‰­ F·úä¿´½—€“èÃYÑ<ý2 ‡(\‹C‹Œbh4*LªÚ—v,†в±¼èQ õt{<¼×ëIÍ€p¯p;#VIß°¼]@m& †šÅ…ѵ'èËÐ{Ý‚l¸ ˆ3hÚAaúR@ulg½¾]Ξ6]\Ýìâúcæ+ðƒÏâÑ5XPšêho[w÷hI[%-P°Axbq¥·×7HVÓ+f”&¶Z þf`ì&ÎÊA  ÓòŽ´¿? ¨«W3P¡¯0Ve v™Eg!}B¬Ø¡ 0î^~×fâºCŽPª5÷–¯ÖÇäXŠßŒM“ä_= íêõ‡uÁ†Mqey¸d„ù_è<ãétH ŠŒuí vÔ¨j`@a”›w Ȍպj[Ÿíñœ#ôYˆö&8Üà&âÕƒ‘–Ä*Á.<¼DØY§‰“™yk+xS½æ»öáÅ2.æé„4–ןGoƒºªÆŠâ Õk”kËÕ³_.5Z  ¦–`Ù„ô«[¢ÙäÉLELAÂLJ’/IÙQÃF!O¦É®_¶¾Öh1ÒAš&_ŒIíHDÓª*Q—U–ÄŠG˜Ý0”ˆÅ÷÷~/zy¼.v‘³ÌSî. . /ò/rêlÚ0tBüh{ÏÑK‡?;þI -Øæk'±ÕúSM‘ðwÛdn²©È$Ib°e×ŽÃ¦Ï ðUøØÍì]È“B|ØU¬ºy{Ó²í€ͱ0mGÜÝÉu}€»dÎéyõÝ,’¸ÍdZMPÍåZåš¹«çfÍÑi êm¦j1¥Æ’Ä,g»îlX Ö*¨ä‹X-µjY­E«\.³¨-M Fy‰ÂÃô[;Üï–9R¬žjŠÍmrš@ ·htEªå$2•!ÚžÖ~¾÷ÖÊ~—ü¶P‹Wu Wëj#ÔÈ6[µHX'òöxú\½È/+ߟ³¨žÌ¥‘·ºéN€¸3ìn{w"À)dCqóNCI– ‘Y =èAãi Zwƒ«ŸëÞ‹Êœ›¿õ7Ü\¶oÏáÖó„þSP{ŸFH#@+ÈÐ £ó~¥ý"ü@ë üàûÑå-W¥/ H‹k„ ¯d54V©*lh]ɃŒp#?älÿ(qåb¿Ïåsúìèl,;‡¹©fL·ËwÈ“KbÓ’¹§%#8ŠÿWÊî/Þ èù:V§’bHRÝ®0Yµw†…½*ÕÆSmްEf¬Ñ–@-RûšÃtx;]'p,òÁÉï¯òŠO TÀËe‹ë^Ñ×ëk¡Iª7Uì¡?†‘«Ác··Ä!æ UÀ–›•H2¢Î¯Û¸ 4¶•ÀñpÛ08ØíÛÍïâwA:¿i`=‘[‹wnMUí·Œ°°„¤_MÕnZrÃ9I#ÎySjµÔ)6ý:κqaçµ¹Lä—î0ï+é#âf~£0ÓNÔ#ǧ7´ßýà8šª õ…s…ßdf…¥¦¹É`ÐB‹ éDúk~`¬Ë†ZEqåìhœ#¬ÿF- @>·ÇGÀ|y%N&x‡ÇÁ`‰Ìq‡„=¸UjÙ®ßÞRÔ¸t³ñ< ÍÕ'‡—ØNšåð âeþ!®cdo46Ð5ˆí5·n²ßiß-~N.UqÉHÎKN–ÖZTPT!Mx 2ÐCOmîÊ&œ:] „§É2?ÌE¸8tø¤Ëíñ’µsˆ­¼‰7Êgõ¬Y)—mÛºªb-‘ o`übïwÃx žØËß$–t©CäÃO<ñU@ž\£’¹§pö錤ßÚD§7ôæÒ+ `çŽü[C´T3ôÅ6Öj&ÊÈZš°k”“72Ð`–›ä¯q™UO¶C‡šZõAÚ%êrq®ë®“µ}|æk¢v{K*ئݦ+ÌÖ¼ òê€.H?àî>ŽËd‘Ï^ûÔŽ8QÂ[TÀ¾”ˆõLB®m=åûáýÚóiÇM-ÚV¢‹5ÛjWç2‹šæø‰X€(åÛã—ö^‡ èÃ-ƒké,Xµ£jCjeæ~òº°BŽ×wÜâõÓøìþŒ$}LÊíì¯%d Q(„ªÄ°tÇöÜl–5™‰î7¹ÙT柇íyϟ ª ':"î6WÄîvò¤D¥¸X JÐÍ$=Ð鸙è&¸¾Ãøuô@…ô] ¦Z#‘^™væWWbEyêCà |qàjç'ò1¢Ž–öÒ¯À–ù-ÿ¡ ÇÓ¿ Õ¥-7U´”6dÕ¬„Uèå#›?¢ß„¡ÞþÄ’Ä‹c¸‚tz.–Z[,äÒ¬“±j‹š ëæ¡Â1¢´"¿ú‡n#þÈ™Ë."gúýDf¾U2‡Çå/ ƒtèT¦Z©ÆZ‹V®”+«´UPµa¶¹Å°;6 ÃÄ0ï¯ì-„L(I½Áj`‰òA:Þê¡}àr9<\—,°/r–¬lÄ­Ñ2_µ Ñš“u'éAHx{bÿN¢&ŠçÄì„,ÏãSX#µ‰ Z6—4(·6Ï]HÛˆ2ñx[/c#R² P‰º´rÛ®š!æ$9ÚqÔÓæˆù#»žî;â2©,J³²e ©«¶©‘Y\ßx”&¼÷uøè8üÂô•äßŒí°† áñ¾‹¹[–nä1¹ô´äšù–êÍIÎ+É/‚РឺÙÙï—¿Éü•¾(ªÌu¼ÁÀhûž¡v$¹ÖˆCÐYQÝ“wÝ­ˆ&3í¸Â]"a+ˆéIþ¦Lä§L²O™üó¤#“égr3Ϲ?îý?3Ž endstream endobj 38 0 obj <> stream xÚÍy XSgÚvŽÈ9GëJL‹ÎôíŒS»ŠJ‹ÖÚ*nµîÕºo€²!ìdOž•°H !@@QĵVmµÕºÔZmµNÇ®v:miûÆyý¾ùÞqƯәþÿõ×ÿ]zå:Æsî÷Yïç~N(ÁàÁŠ¢F-[?gβyO¬ZðÊÒ)3ž |é_(ð¿4È¿(ÄÿÐ`¼¿÷ëЦ¿F‡>,„F“ÏAº‘ϤQäSð8ù˜x5L0y€< #xXð;ÁdÁtÁÁË‚U‚M‚‚4TP"Ð ¬‡À#Ø%è¼&8-¸(øPð‰àkÁ‚ÿ¤j5–z„z‚ФfQ ¨åÔ:*†J¦$T¥¢Œ”…òRûvˆ·ÇHŸŽ“eÆÄ'%M‰ˆ˜2càbjDðbJð"2xñLðâÙàEð©iSƒÓ‚Á§¦ŸŠ >üæÙ γQÁ‹éÁ‹ rTО¨àQÁ#¢‚GD£‚€QAÀ¨ `TpzpzОéAäéAäéAäéAäéAäéAäéAäéAäAäAäAÀAÀAÀAÀQOO››.ÎÈÎÚ‘9~iúö™iã_IǤý·/j䃂IÔ“ƒ¦ ~N°P°˜Z!8>èÍAgçB®>‹IjCCÃ##a!)!‘àAÁ¯“O žL¡´”ŽÒS@¨2R &ÊLÊÁJÙ¨rÊNUP•TUMÕPª–ª£ê)'墨FÊMy¨&R6ÍT å£Z©6ªÚEuPTµ›Ú#x>P¯ƒÈQ Á7T4µ‚RP J ƒ v„® Ÿ¢ë˜v(›9dêЄf›1ì?†GDx{ä«£D£ŽNýCØÌ°›Âec²DSET?4í¡Þðá¿=Ö;îñqµ¿þjÿ¯­¯xø<·;ÃÇówÆo›ðÈ„ólñ· \/*wQÕÈ'ʹSåbFü’7aYÎ_ ¤.iØ·'…Ð…;rQ¡Z&-.Æ#ñÈ 8ðLÀKOá—ÑD<ʤµ¨-ÀZŒf®’ªß¡aIh É€žkCËÐ(4Êl®´A9+ì2«MjNxA:½ØÓr§QHv2ä49J£ÓkA %ž\{ñ8¬ ¿8ð“É8òqŒfšhñ ´ÿÔUfè!pXà¨1…øÅt@ö ÉqÏæ×‰ JüY–¹2v«V«PŠU˜µ&®ÜõžîêCpÝ#?»–~œ"ËÜ™æ–6ñ¨²Úíì´â$Ut¢WPÝI¦ÿ„†œoC}+J×fA6›åÈhk­÷x8¡«1ߛ õº>ÿo?ö©É+Ϲó”4 e¾+ìúÂÿHÌ„NÛÁ:ö®“‰×&pëha†c„]MÆP4ÍKçƒLŸl\’e7ï)×ZK¹"(Ë·¦­Q¬ ".ûßðQèîB>ö7ˆjÞ>uè °Ÿˆz/bT“—ÍY±hýê «Ö­Î‘„« Ú  륽èÅP ­k7ä—¨ÕÅúbr]¨/$÷°8Š>vìõ×N½ðÖÇçÍfm ñÛK˜õÛŒêô¯Ëåuç¹Ó85¨õê -Rïž°½ßEßBóo¾ô•ðËü—E¾½G ؟dœÏ*X’õÂ’ìŒÒ¥ eåå:WAWB¥¡ Xá§„ö(C4«`¢ÓŸzš{ V´%gËé&oM;î<ÏN#«¢wfd` …®û þö#ÂÃç‘Ï0V˜+MfVxõMß¡Sð.ûù¤C3fMŠ’VŸíu»ëšÛwV§rÏzÎç—„½(ìmF3E¨þ):.I·•“ÑÂ\1Ä{I"Æzé(Ö—›"6ïæo}ë{Ôÿ &ƒ,l…ÖZÂI ~ž$~¦gáÁsñ "iI äÊ 5ëõ‰Æ?$ôîf BMþ‡]ˆ»ê“R·›Qákh¤È¬·èÍÀ6Õ;=î܆Ì9¹âÉ—#~Dþº†û2‚Gñrz³..7%…E1L‹¼EÝçà-÷Ñãf³ÅV¶ŒÑ›ÕF’½1o[Ñ:Ø qåq5ê2•Qm _ªA«Ñ«Y|‰Q”)ì\Øjmö–ö}uû5Ñûô­ Õ Õñe±°æªfΈÍWækóa,>–w† V½N ì?ý骇üÑ?­ü®þÊ¿0PùøÆàÿvKßÿûâŽKêC>ÿ£>êøWþèBüŸ¿#ªÌܵ½X«ÁjáÑ,,z+ñ®ÓSÖËùp‹˜q@Álw‡*†¹^ (6C;{îÆiÜy|ãÍ”“ÊKpþØðõsûwŸl|Ð`x?¢2É´‰N`+ˬå<²0f½]ÎÉAU¬QHò²Š27¼¶¦}¾™-¡ñr…§á­x)ú-^€bøËpÆùÚ;$!ƒ?¿hjRäÜ™à CÜ a×Þ;³DL ‚+€ÝÕ¬ŽãïÖ2$ýJÂ2 Éê®J ¥¤¸Iw3¤»Ý¤¨8/]E~KÉ Ýf2P×⪪ðz<ÍͦR«Â"?2ïà¼Ãs+d d²’tM&@B\ÆÐ¿xé8H7¥v8‹\…®%Ÿ­¸µäQkX«lfóþ½û÷ïßûÚáÝ€õáMbÆU_(ã!3qgnÞ“Óžœ:y2‹®0=­Æý\ƒ3´D:âoƒÄ3ņ–;ƒ½FiŸsöœkgÚ[5 <¨ôŸˆwq)Ä­’~·Ä~+ãEvÂ#¥“å„»SÒUél4-Í77óþ¦{—¹•\¹¾X/-ìòá_3 ýçyÒ—‚‰.zÐOþ:ñ•ðpÏÙ"ñ¿(TRù`1X‰üð×Þ×ÂZ’<ò@úZh´kM™¬–â¢Beé̾€ÙÙ˜}%2\QTZ¬,Ôûµá]­æ@•Þ~@¿÷R·ÍÁyI3„y¿CO¸é†ð(Z0@„U†JŸ:ÏcSâ‘R<´è91~âEHic׬7”ÏÙР·4g7¤¥gK“—ìyåwÚ®×êDCMhd9ÁºØmÚ {Øzc%iÏYt½®Z©ìݽŒðhl¢6–Ëù‡vù÷ÑðÅúäV©çÎt^F4FêWÂ^èWEOäOÏÃC–å·ù,ž†á•(mDcÐR4Ÿ^E ñX²`là„½DÆéU„OÒï‘D#ašCv¢3+Êì¤>‡‹K÷ÌjYe[ËIÄ qDl¡¦@Wøw0=]ˆ„új¨ÑUÿT= 7„½{áX ¨R’Þþ¤Òq;{y¿‡³>à~‹Ã´›CÚ©«Ö@:{wÓ4úþç~aäþ7NæwüoI[ï<‹!þýX´þõåÏ“§×ççàUx5zÏBëùJ…Ûý# _$ºœ“y›Z*™8eö#0´n:¾ò‚ì¸ ·ê¾ºx©gÿ¹–·wq¨ 2ës‰Ä¬ú9‘Lc`‡8Ö„® ˆ¥@.{úÈ¡…énÖÅðøæiD­¾Î]…÷ŒïyYlgâ’µ1\6-ÌéËHÏ/ï쎾Æìéïì¾u‰t^[‹j;5L2W¾Ìm§·;Š»5¤Ö šEÏ2à¶ÔúŒÎ28ïƒèßD䮜N”ìDÓ]a=ï£Øó—ݤ³)?+jjëríöÒî¥ ødÓxæ,œý‰ø"_E6ï¬:ÀhclsÜè]»L=ì{’õŒ°(C“œªìöpPA¬«`Çô]U²_N{}ú’g’žÏ¨Ímr××yeÎLN׿ üèQÒâ0ÓêEVCoŠé:Ä›Ë×?ì¹eX,ånÿS ¨LækÚùj»&üþº*²2ð~ÃõÓGÞ<ôaÙźnÛÞÚÊì…±jŒ "‘rŠòÔiŠ4¹X¹¼paÁ–˜…K q(Y ÑVRÈeãÛ„&¡¡j–Ìß|ƒF£!SägCĺÌyì1.~­·A9ØØë;ŒøKǤ'8x® ñHÙEŸƒ”èì`×Ûƒ ¹ Ű:þ?^}õUá÷-þ¹"iÓܤ!Uq„‰ÍV¿Êå s Ñ5ˆåoE¶o´³Bÿþê«up®÷&Ö¤V¤R€†·‰þL ¿?s fÙÒåq«ø´Ä¨©‹^ŒÆ0Pkt4ÙS´ÐôdÖÊèI¥q<1ãÀ\þ±Nê/çCšÿééJW:³Ó²G'™zs‡;CŸƒcj G„V š˜é“6ëðøôlÚØˆ¦œ_ˆ"CÐÈ¢ƒimÑÆñ*‡çãí8ŠËÇ‹‰„3öOù|MîÝÆ]$¹ô18®s͵¦Åei9-&«Bjš©‡G‡™½ æ×9'ƒ'Þ Iò´yÞ@“ÅÙV°×VÛ*_ªþ3\#=¨§f³»•û”n´—dñø,aÈÀ›¶ÏY¥ÜÒœh¶‹j¹ŽägCˆØ+¡}´Ýl¶³æ<Ÿ†)Ì`êC<ã¯À™îæ ¦2¢‘X‹Ê¬æòA•¤*Ɍٜ¶VÁ†=ÙGóºõ½ÐÜ¢znÝøCÓ£s9ÒøÏoôÖ?êlÈî@˜Sðöê#±Žâö,†zÔ ¥F½}]xܺíË·nÍÉÉUŠÍA¯ºY¾ÕÁCUyµÜÛÙÜÑÜY騮±×:ŠkŠÅve•’ȬG˜duá<’ ±+—IÝiìá¿e á ×ã´çUTæ7'4'z¬òò²ô)r¸>èuíKØŸÞ™Þ•Þ¹ýh¸Æ¬°‚™5º½ÑQydïÛÇOëd–jC'æÑ•‹J¡¨¤@©P(·íXŸ¸%¾D^"/V°h\ÿÒmc÷µ”âœX,u1-^Ívždñc¶·ÆµnoͫέʯQØÂ•¶’¨»Å\i"gô—ÉH¢-p…¡ËW^ú@ør ¹¨·îÓ x—½#,›¹HÒˆ TZ•J€¥ÛBXP¡-Uñ}¯¨´,‘Á ƒ¼\Oø¦ F»ëÌ®7}íJÞüå‹S×ðkh¥R«à +±˜m§…_ž‚+ùåϳræÙÙY˸U0·&ÿM…¥QFdŸV©à!µ6¹!§3å°ò \4²º àÜڶյŦ"S‘í/û`ó ¸ŸëŸ —ŒÉH5ìæ å6›ÅºçHxkwëžÖn§§Þër³¸Ž‰ËÔ®ë»1›Ißi"vd Þq†Ôi<¯—ËjåöõáëoxiÍÕ1»öS\ ˆ÷ÌènMEÂúl~ýÿÅ4ä¦HϤ§jÅ bcZ¥ËZ_^Vxܹ; lRAffôŸd½oÜôœwç¹ùº¼,È‚œêœ&Íý1=û3ý_Rï‘/tËæ†õ³ž°=0ºžikÑÆò0_=·dž|M^ÄJ(„sIy}‰G#Û˜_›‘Y*ÉÛÒ%îáÞÏùÊ£uïY®Ãûl Q·†Z¯•½E{mE¿Ásceª•ÿ4)#*N~mprüO#^ô×ÓÂÞÖ€ N¦¹E³ƒÇù \D^±Kd1e‘‹‰‹¯y‹7 ×lI®Äꤱ»#öDìŽ ºÑ¨0yo +ÀTe*÷] ßýi×g»?±T[kÌ5üÇpaoL"P’¶dôÛ²Ïm:F d “ÚuÁ&LmÃ!°`¢¶¡A›¥®ÑÖdÁ½ôö½Ó59LZ†©›²ƒx‡ù€ÚU€‚Ý&Öoú¹"%$ÔDHÇqh8Óé°öwI`à–zˆ8 Z>$º ù_á1/üp(;á#<=ŒFßú EC§¢P<ŽÃ¿ÂVÑÿÉLÿ¥|4ú$ãµU6sº :˺€õ8ÕI<~›‰ë6ÿl¶£öUzÚåÌMáà¸Òâ‰ûÜ&ÁN&6]¿‘¬ü¾,&Mbê$yž×ûfÎ~‹†ý#z šN´Ë~lΉÛ¾àz¬i^ŒýÍd%+§7.è=Ú÷b¡Š Ó*öõsGNßîÀ¢hÔDÈÌQÂÚþ'ÜÔ.Çÿôeæäï̪Ïv»ëë½d3.½2Õ½ŠÈí‘Sp(‚‡|ŽhÞéjºh´m`eMŒÎ¬)S§±Å’øØì­ÀNؘ›<|ÔŒØï¬¬ÄåPISJð‡—–Ô8Éç…]$´%8’Ȉ²NÃk îú†6s3°­t“)OÊãc dª¤ÉZV˜‘¥ Ð «C^©>B 3ê’˜Ødócœ¦Ú&®•î½%•«Ì’2‰AÒ§k"ºf؉*¼Õå¿#¥êý³Ey6æXd]‘Í/5-j~©}V¸Qa-9äçeªòsÖŠ£_†<È·VÔ.wÔegæçgm< îå.C×妷ÐxôExÃk®›ïXgž642n®ËÉäA®+ÕÊ%Ëw®¬m ×È5r­œL;ES±»Ä³óLú™Ì³›&ðÃYk¸8çdFÖ·}“Íõ^A «”êø)ÞAŠë!¨5°ƒU0{št+y=Þ"kÛ\cñèÉDá°xøŸ~ƒÂø}Ðìô´°o-R=HõˆIõˆ%¦Ýï?Æ“Ö,%røóm4 Ž M"äãasž,EN„ã7îÊEvæF/y›Û“­q,Ö1ÖìØÎ͵ïœ×ÔèºÖ¿W/RÍØ8ái`·nÜ×Ë#cÛw°•4À·‡ð°d¦èµ@øûûÉè¤ æ(ÔIÜ©mÛÚ·íŠ1ªË?Õ4”&9&|˪-ÑÏÒ<ÏÅHKëˆzò66Ô:kjê\Ö"{IyIÔ!­‘Ú‹ëdP²lyžÜ¾ÅU¬Y£¤MâËjÍòÅ"#Bn ,ÊV‹ÑÔÖÞózïÙI²ð<)ãÒ”’§ìH”J”ry©ª”d(»;¶3k·Î¤7 j{¯Sï‰âŘyލœ ÿ¥ö%ÌVÅt4ë7óø“©*HçÈNMÄO<ÄëâÍÌ5·óè Óá´žøU€^p¢÷^ÅìjÑÅò ²ÙÈ첦˜ãòýp™ö;YüPÿë%+Öý,Á62Þ>‚Åì|\µaâXwžéö÷2þÍå÷HpMàoˆwÀko¿×1Í.çNÑOHæ½»Þ`2•E~ÎVT¹yô6Ó鲜øE· Øp_èÿ…þÛ¤©ßT9XÓÿiôÿ›x7ñ0áÚõŸ+‹&æ¢é‹n²Õ\ìžo&r §ÆÙ‹dÙûŒ>y&a1¯`Ôcâ7+ u…Db°¯Ò9z—ƒî ¨Ö&í6%šäN2Uc Ìoñ¨™é¨¨|çÞd¼ß¤ÿƒú§F©-Ú£mCSÝaèÚ5áUt eŠà¹œ©S’Ku¥º`•ôrÓŽ]’ºrm%ù§J­!"ë‘5ûsänuc€~¾D4ôÇÑHü0Ÿ Št™Z«V«ô¬Ž¬R_Y tr%?ðëõl”¿¬™®4˜ÌåžýG¼Ç€½yèÑyz/ìÝ -€Í^¡’hMo«9ð’ój4'„vh«n­ ðÑ-ë"¹»p T*‘Úß_ ¼c¢ÙDýjãô}•¬2”é’2éâ ž±²ˆûžvbæ2ŽA!hðÇD~0‘h(ˇ)Q² :¥V§öÓWE{¸Xuõê.‡ÕatÀØ-óˆ;âL¯À:˜§µ`sNQ–* fÁú³¥7ô÷ÄÈ8ó9Ò‡á.êÂ5”N6] JJ¤Ò¼ì˜5_\¤#ä·ÖÅäfB 5N{eKwG·w¯Íf°Tû6)Þ.ˆK×®'¤ÿ´_ã˜Hü¨ò±Ù?¦äÑD‡hàרy†[ß®øˆï¡êD~„Ôå®AéeÕoµ3ÜЊ‡ ±jöÀ·C<ÀM÷ªD:Øú·1ÿüÃÀ endstream endobj 40 0 obj <> stream xÚE”klSçÆÏÁ¡¼P7еނÚú˜2 hB+-‚±Ò*´4ÐpIhÕ(„à&Nl_b;¾Çñý’¿Oâ[›8qŽíçê” ´.í`‚®R+0uýÐ ³³j;±}ù¿z/~Ï£ç}p¬¨Ãq¼x瞊šwkSQUU¹¹lád[+ÓýÏñGöÅ…—±Â+x¿¨@p ¿*âßÞUôoî¢W0 ñyvb?/_˜_±0ײcÉñ_`‹qœ³Lo!õ’²²7JËÊ^¯P( *I‹X#X׸^°yË–ò ‚×ËʶÞ–‰T’F¡\P%ÔˆE2¡†ÝÔ(%"A°n›X£QnÝ´I§Ó• eêR…ªåÍõ:‰F,¨©E*­¨Ið®B®ìÊD‚'ø¥O– …LÙ®©UŠ&‘JÎ/)Á¶â¸WâzÌÈx°åØsØìl¶ÛUcµXÆ]„áX¾ ߎ{ðŸ qÞàÌé¯X|ù{Á[\¨d„Tá§h);æ“xú³c·îŒ¤ç8t)}‘Çàí¡ê² Ò;&x¾UÐÏ,9êL:AŽ4Ù~HÓÖ°«§Ëïäð9=çZ¾¸23†€Ùæk # ‰Yº°.¬ íM—å`N¿óýÌ”e†| £™Ãda94w¶ {Æa¾Èßüvj =)@™¯`t¸ÁßDX@ mnäøB€x`ȳÜÕawÀi€z/tA³ß#íü¼ ÍÂ?(½žÎñúÙ‡Q˜€ž®·Ãks7€:ÁA¿g†y© }“ì÷×ÍS°ƒ!ŒŠéxˆß~È¡œãåÔi¹\­–ËÓê\.ÎñÙ[æƒ!ú­‡8]Iqè?ïªêx“T§R(“mãü>ˆõôFºI¿ßÈïïê àmñ^©Ôjx‘3à Doݤ—ò‹ ;¬=ñ×i ?ñ -¿Ï) +x&耎“Ùg'RXsÙôô™ƒS;˜—˜•ÌjfÕæùmÿ Wÿ°/è ¹ønðù\Žm뜕…ÞWž¹DÀ‰äWF/Ìœc…b‰+Qq!a¥ )ºyŸ¾Á)Ämçù¡×Â7ûÑçèr¹Á‚:#pt–tÚø^Ý^Æf˜’gÁJf)³‚Y˼¶q®ò/DÎö\ºNJgaR©þ±D>vHÔk/ß]o‡q—aßÇ€”Þá$i2Ô“@»ã<·|fcÃM @µsÇ 8;F/O½xjjÐã[\¸|®.7kÿOhy¿uéä%=õh1/ÙѯQ*Û”ú¸1Ið·ÿ‹ËëËÙ› 'qD§Z§j7Š˜5v[/ü^ð“þìƒé‘ @á´ uj=6GÛ!™ÛÚ,RТƒâÙSôšÈ€×m6¼/Ýó £³7E@&O]f ÜÄ~—Þ;…îÇT–{´üKNa‹5Ø‘Pkd™.nJe³ÃY>Sÿs9O¿½®º\`Cd$tt’¨ß:¨Tɵ-Óí³üëpÿ\æÇ{…E%$Ä¡]NÖ®©~Ê¿?<˜¹|úò ø€GH€ÆkõY`>¥7,؃~û5çSÌsH|Î@VÐ;ž0‘ÍuŸã¾ˆA2jƒŽZE蛡ËC™˜ü˜ø3@4¢Ÿ§_£×>¨¾º¨…ºi“íüá¡f¨}“Ý`Xö²a}j¤?H%n$gó€q‡è)ÌWV^(›=6ptr4JšN‹÷°OÊ,1ˆ$ïÔI›UZ¾ @ÙÝDzWÿŸ}!…*x=Þ “o…ÆF£¼ý|S+ f³œYǬY±êÏÄI8žÎçíb)ó’×îP8<5]Èb]ØbÄØd÷øD~ü:Muu†È A A¿ÌÛë¹™`Ë(G㉙Ño>Ÿ9±´­N6h…×cVÔì®ìOV*v—ÞQxî}퇾CÏñ‚é{×!i²(Ü:¨‘)ªÏRcÓŸï‹KøûAüa§Fuõƒ^9 ÕÕ Oµà†n’ŒL<¼šaƒ78ißOÀã{ÍŒÀT%6°¡Ð€6– PCp eÛÃf™ª­µþ¬îSþUÈ_ïö5ç›.úéÍË,„’°ƒÏãsJ;Õ¬;M¦± ¨ ý”åY¯…)º _Ãé•ßñÎÏç2ùQð_9—Ïÿí>5 = ÓÇw‚×ç¶Ëê´&5Û¢GÍ }ʘ”z«¾TëîvEˆ28xzÞf{yЙrL›£0 -‡Ë+ô¦Íå%;ßW³…ô8a É`459’c+º×ž‘'´¦ çé²l¿9˜]^§f×n½t`jC’˜¹GË6  ì^TÜN*¢Ñ-£ža„Ñ%üeEåIîÒw™Ÿûì貯ŸÍ¹\úö‹ÿ\Ö´Ç endstream endobj 42 0 obj <> stream xÚE”yTSwÇ_HòòT%¾[û’™Ú«"à8ŠKqÔªH]ª(d“} Á–‚†%pAv$bÕ@ ˆ2‚¢"®ã2¶Õ±bµZºê}øãyh{æœwî9÷÷;¿û»¿Ïý¾¯ˆ’H(‘H4qÅ?¶lñ]=ÛÛg£«ËØÂ‚b|“3²WÊO§øDñ¡aê8¡]©„rͦ\Æ-’#'k+$C^Ð:Ø Ùåúªü#ùŒšæuØÈªýÈ`šxZzpÐÏBÛñŽÄXÿf“Iô¬OŒH6 F(L­%“Ñ!7Î\~ —£=N®ª„B02%yÆn¸®úŒÈýˆM&ÃBXVA&ž%Ò~bÿpM90ÅEÆÅÿkcšP¼,Ü͉›Qê‹ö ®î&'//GȯÓýêtžÌÄcYA&‡/2! LNQ^1W¯_@yÚT¢0v#Õã‰6³èžfõÃ0¥+p­´·'|[ff¸¦«s*ß° i×{ÄŽH½æ¹mêcíÑÊöƒºƒœ~ŒqAÃÕÞÖ>`/vWÀ’mK7ûÍ$Ê1+KØMbäüŒ>„ˉåÆfîIÏÖ:&±1r‡n!ƒ3pü‹K‡”üý%.òx%'Çaöþ—}7<÷矛ýW_(sÊa«É|¸{¤sÖSתZ€i?›ìª€Ìü ‰±þ‘u¾ )?ôÙ°‡‘fe•@-×Ißo]5‹L_¨Ø žµŽæZÍpŒiI0Å%Egºüü)ŠÐnpð%'\÷×Ýý°þ_|ÏÊ €»î€Ñý›,vlØ–ë«ÊÕ¼“O=õŽèœåɘOàcËÆ,¦ž!y4±ƒüª¼:Á¶¢H°`„Æš²ËU•%Åw¡J@Bg¥-%¢ä(Wò~QÀGº€“'áD9×#ƒ³Æ³¥½E Õ;/½Ó(þë<Ö ¯îÖtâÁNM·ü¿¸W±ª#y_A-sñjÇ­ÛW¶zs°1Ôß7‚1§³ÿn=u®1Cnç]f.öræ@Wб£"³UmIeä¯6Ä-ØNÌŸ_®Fé“×´dëH©O+_ÛÆÌ bÑ~Ù¡”®XX?ÍËs«ûïKô5]ù¡ë]?-CøccX3„¡áˆñ-#_|¨ÚÀ¥Âç… _1¥‡k­Iû“Ób÷†®î þY´Ãé-LÍDvÝÛ Ûu;‚4AàÉÉ?ÎB '}Ú;ú2é6 TsY× Ý0æW]õ­_v«:* ¤9²6 2ºh¨˜E‘Ïç?ÅimèÜ&:72W<â÷ØýXéèSúwëܯàŸ-ìï&›®ý…NÿÃTí’ͼw-ÆU›i\)³Ž¿1Á\fk{Ãd;‘/Yh²‡§ü*¦æÀ endstream endobj 44 0 obj <> stream xÚ­”{lSçÆÏ‰]çÜt¥x8ÛêãÁºBaàv[K ]•Fë!á–rà7pìØ'Ž;v|?ökßcÇÄiì4vœ:Ðt\Zô2Ôå„€líh'm¨:1º©ªÖs Ûah[Wí¯é“é{õéÓïyôêÁ1¡Ãqüþú꺺]{ÖUÕÔütÓÁÓz޾ucÞ~ûMŒýÎ>\ÂÊìJ¡ìú6áßÅ%cŽäûëwô“¯ÝÑGy)í[Ž qõô{ŠïoP(ž¨Òhûtmí¤|MëZùãO­—?¡PTÈ+Õ*]G«²K^£$ÛUj%É_ŽÈ÷hZ;TdŸ|ÍÓí$©Ý¼qcooï¥Z¿A£kûÑÚõòÞ²]¾[¥Wé ªCòç5]¤¼V©VÉÑ7,j•F­í!U:yæJ×Å³ŠžÃj±:¬WãZÃVc±bÛ°j~ºÛ…íÆ––`8&ÄŽâ?ÆÙ<$üžðóûމêYªlþ$™Ù<3]ÄçËo ˜g>ØU^G% £ŒI!ØRSÁ<À,¹IÀ¯¶¿ûèƒ2y>Bï=w‘[.ã>õYø§ )N‚‰ÏGYP†É,CŦýô (g¾#ú4SÝò¤BÁ­ 8÷±Ä " Dá+LAÊ4‹þ8µ}ÏÚu NL”ÍÿŠìmž©È^•$ÎfÆçh†“awÔF8Tå‹]¼ÊD :,I_Œ˜õ‚À n‰+YØ&å\ì¨#í=”s_¿Ç7FD¡Y÷…i©µ¾»g«¹¬¾>WÈ'‚YzîƒTL¼*˜‚ÑÄ`ÀI´ùÕa8!züÌJvTê1S Š˜üÞ!(ç‡Áà*cÿÆ“~ñsœÝÇ~&‰÷Nz_ôy¢³žë ÏíôÙÁ‹,1*,‚`˜Í1;¥ÃVè“-\éÀ NC-W)õº)¸#âŠòï¡ðÈæ“ f= ×D¿ÏAåéõy8éBFjWQƒ«¶Ñ–"—é ß‹òp…ÊŠò&†AKèÁÝô'Iúƒt•1·my–È3’Oð.¯˜óóBIÆt”ìîÒ«{Žš²“ã÷ÝäNæ6»­Ð_Þ0ÓöÖÍŒ<wÐN™¼NÊFniiidµ†rŒGÒÉ©x.žÊMýVË&¦`k=¶ï1%'·Ø#ž¨, þ0Ïßx#W4wk°ùlj>ÅJî`ž½¾Èd¾ÁsöqjÔ<ªWwkº)ãxa"?!ãT·Ÿ”˜k¶Õ‚ ÌA¯*ÌA ÷% ]Z]§êUÝÙ,0%3Füæ–”N¢Bï4¿¶ëÛ5÷8†ÀOGR…ËçÏŸ4–è$`€â*»õìb4øüæË¡9ÓÄl’Щø ¢ãáñ@<*^<]œž(FùŒ_}©g?z9xÀÙݿե5ïºûjp#rÔ‘”¥!•ˆ$èpt:4–ýXz÷Ÿá·ÁŸ-Ïž9} Ðñ1CuJ®ÔØh릜`D»ÏhN}ú¥˜õ›”* “#ž% ÍÄ_NÍœfJá载ǫdÏÃî¶5Ž«Ó{a?Ԛꪜ¿lÌ7A;è ýú&[¿~÷òF&gÓïž4ÖõÐç6::½óNÏÀ‹ÜcRÙ¥Ïó£²yéÝd؇¾”ÌW;,àËW;ªPúŽ6ÃÞ†.•óæWöAèHÓÞEýÿÃ;Åý¬È¬»ë¤öšàMî~‰ã°×Áoñßwö˜;Dăô¯çÆ"w›`x¬ŽI_-0K’äTÛÛ€ø:\Á¬bùsõÅ-ÄhléR®nÛ?qɃû€úwÜäùô¾^Žz~é=z¯Í™$¡¤Ò3¯ŸÊtn´á/öÈÕ;»_hlnôÓµÀŸæÑ»þ…~Ꚁղ ‰?èC…=Q;ŸlË!“f0£~½·Œ[ÉÜšÕ—vü†8'& >ê·ÜÓoÞ¾í>då+q±÷’ $ýè-ч¦¢€þÓ´BÁ²0‰Ç T¿qom³Ãh?yòMÎä¾Èœžœ={ò @—FžqòÕïuúܨÌ0ÆV҆혈;/•->õ’xID¼Ô/^öÊÒkËòA±˜¹¾âÑ“ endstream endobj 46 0 obj <> stream xÚcd`aa`ddäñ u Ôvö ²ñMÓ÷ý:ô³‰õ‡4ÃÆ²L?䘈³È200¼‘ùAä]© $ÿ 1°02r”T´ë9çTe¦g”(h$k*ZZšë(X*8æ¦e&'æ)ø&–d¤æ&–99 ÁùÉ™©%• 6%%Vúúåååz‰¹ÅzùEévš: å™% A©Å©Ee©) nùy% ~‰¹© 'ëçü܂ҒÔ"ßü”Ô¢< “˜ mÎdbc`ab`d`ah`8ÎÈù£ƒïÇò²å?¹–3nyò}Ñæµß/‹vk8“u:þ±ÕÂîßBݱºµùéNÝáÝž}j»­w:^­8н»ûᬽï6\î{Ò}†ãwÉï3¢™Ýn³Ë¾4é~Ù½¿ûB÷Åi‡|¼9uI÷Úî Uó ¦‡t;t»wtÖ—)¹Õfusíî^ócõšíó¿×ßbþ~î§ è²Îž¹¤ä°bnŽ,öeÝ».ãø3•=­£^G.#‹mKßÃî;uoáQY“Á®Ó1}ƒ<ßÏsßyw~·ÚÉxìg8óÏüïEgÍï^´¨¸»Fþ/'[MqwIÉüîYò?ygˆÎZ ”)ɲՔeeøÊüpžõ=êäl¿§±¯áºÎ½|ÏõÙ<¼r\,æóy8¿m<Ûn endstream endobj 48 0 obj <> stream xÚcd`aa`ddäuòvöñ÷Ôvö Ž4 ضÿóa5ü¹Œõ‡ ÃYÆrL?䙈³È=ôbùÏÃ$ËÀÀðGDþä‘_@¤:`Þ=‡cN͌ʪêº*¹îÎ)†=í= ý©=u¿•žJ4Ohíoîæ¨ª®)—ï.ŸÕ:¹}_Ù¾²ýª‰ù•Í5-µmÝåå³kæÈMîž3mú䙓×.œ1eÍ‚é“LïªmÏèªoÔ’¨š]7gî¬säº{šžvMèšÖ¾±k_ñâŸöKØ~+Ng—ãbž¦úŸ‡sW÷~®ýÜûðð1ï÷‡"ßÍ»a endstream endobj 50 0 obj <> stream xÚÍW{TSW¾>‡ÇÙÛ·rLK{ާ±Ö±âõÑÖÚjë(õ…Vð ˆ@HB€$Ê›²CžPÞä@ òôQQÔ>¬µN‡§µ^«õNÎÌrÕéNïñ®Þ 3}¸zgÍ_w%9k¯¬ßÞûû½¾ßwh*$„¢izòŠÍ«WEG>»qņ5sÏëÿo¾oå‹òÍö="nÿ0=ôÆ/ }œ¢è‹SüOÃ$ÿsÏdò¤f‘+ £¦ÑôXvú“s¾²jö„4U¾ÁvÐÕ~ìÌ…«Ÿã¸=ÉÉÏÏ;oÑè"bn`1t±à?‹…ÅâÑÅ€ñ€ñ€ñÂE`×ÂÀ Û¶/z>°˜XD“N^8yQàÀÅãÅ çΉX.OSde&*g¬‘'$*e36ÈÓâd?ú“Ähò젨ש8*™’ÒïSPÔMêõýùøo(‘úŽp5‘šDý‚zŠZFERk¨µt m Ki#h]F›i m¥m´vÐåtí¤+é*ú}®¦kèZê‰ Š¦‚¨uÔªŒºM«ƒ J jÞ2;‡¦1˜Z°œ€ÇDŒ¹16qÜÔq㧯˜0sBÝ„ÿ™X9I;yêäCSb'~G?.­—ªð9uØmÔ½…—Ö§©eÊ´¦Œ6ލF¬N'œˆ×\¤IÖà–‹`äèF¦ÔômLãi˜’( ª,$‡éõòC‚§¶«EÕ’ÂP)2aÀÞ÷ªºÁ…bð4ß²ÀEƒ¢½Up‘뺛ÕîTr«• ŠùÙSƒN-Xcòà íØã¡ñŒ;8ÖÜóí‰ô08ä1ÄóZ@BŠ.…ËGy¦¥¾›À‹¡r¦`MÑkq;wl[n\Kn c²²P]_tÄP+; 2ÉP:,rãZy@sw®ÕkJÕHƒà블éh05røQf}dèZRdI°&B7#ÇY¡ý–¢PPÁµø9¥vôNºêfw≾pI‹p´¢ u!¦>­Nn’¢T¸,.ZŒVĤ(ÓP<|á/òËÜEtÂÓÚïˆwí9à…–3çù^ù ×%JSJ“«cÀýçûç­™“þÇv*ªU]œ`ªnBM¨Eu Ó q’ø´äðÛ­ëWpZf»5©õÂ/1sâKn$&Ï·aê°î¿6Èñ-—H«Á!A¿“ÛÀn…q 'Åižl H7â}ã@ÖHØ›é%*I„ÌEÊÂÎ4[¶f¸Òþyæ³j‡w}ûŠDZ ºZK·ðL›Š‘ÆÉŒ»8gy”ŒBiéä¿ !u¼ùõ+w¡Ê7_Ã!þv'ù¿¬·sV›Ç°[A|ºq3Ǫ¤€í4‡âçÝ™ŒLiéæñ`H’•¦p9̰­÷_¶ÅbíÑ™ÌL AP›±-§%ýdŒs+Z‡ÞØ­z™¢Èæu(­NÊXmük8AÏCñ›.>RyÄoP‰ªLUv´éøm`W’1‘“KñI“‡òŒy¦¤Y{xü"@•›ÃÖy¨óHw³µÐQh/jßÞÓÝS›î(¨ÌF9P¾Ç¨!é(÷5R¡}ö„ZyfGÔõ¨ëo~¢­ÐU•C8üì¹3§N8{lA˜,®º<²só Š ‹ ‹ÄµâÒp•:K£RçäçB<Ž·›½\³‡!Žtœù’8ÔFã'=¾ÎO‚½Ã¾8‰/•vÒ'ò¨Øè'Œ9`U”.–`Ê÷€¿ãQ…©•›|¶p›º\åP_gžŸzG|²Wd­yU ‚&¦Ædi´V]Áo áÕC8ÒÑàl´5š\ OÕ¥ry(w¸Aq'¤JÍGy_8ÜnkçH8N¿W¯µ¡0[Ì|ð~qµ®¦¸æ±¸û[ðTòÁS+lÖVë-ûÐcÿà„.7¾D¼ùå|á^ð‘ŸÏL2›a9ÆãB¼ üÅŠyáñ3â¸Ë"m‡âjñ @sEe w!쥟åQrI|¦")vv‚ÿÿ»ÞÏ$àí.¦Òjsâ)/ÿñ qâlò'ÝçÑÕÓõ&³É‚,Ю·i¹}ȘV˜›·U¶Áb&¦lGgÖIÍ‘Ò^ä…&—ÄtÙ}íj“£Ìar øé¡y/ŽÆÆÒX¢òýZ»?„÷±½î‡$ŠÕ(Û;ÌpFžfîäMåå›Í{öÄÙãg„úæF­@Z¿êÖYLšÒr”ÇÞÑøˆtw›a/o,*Òêt»¢wDÇF«”êô¬ ˆ­À㬼L¢ød';÷b~ž÷¡ðTÊÿ+ð¾gýoÂÃÔg#H×§HÒMéÖêòPd;[2¹T­P.ÿ[Î[¤Í>®·|Í UÙ¨ge(8¤vjêŠá#ÿ÷A¶»õa~)Òî+æÐOVñ{C(Û-¨€La9ÂßHx¯­¢’°]WÌÉ=1¶"gʃÙj}žÞF6 `)ÚpoÕÇû5 ÙMtýé+2ñ%%¨Ð[JåæfëtEEác£â7ÆB,Èf´#;<ÖŽ7_7„.fF æ´hIû„´Û‹'ùñ6VwI_ ÐÚ’ÕÚµÚ59OG¢\”Gf l:ØTט[/ÏTg+bËŽó_£J<×6d9]Ö_vÕ›«]fx—* ”¼ØXÍ%€‡'Æ_!¹&Á ò=C`y|Á—ÙÞöQBI"/fT`ÊGùpÝ^Í.B.k°+¹îÞ„W$×'Tï}ìpDϼžÈj,E–BBõeLmYý{Užž;‡ïùÌZe¯²T™Ä;álo¢Ü°•€ `fý´J¡lmNê’¤—S–ÈòRrä;¾ÙúM,¦´5ƃ ô½ã¬a")ß¾‡–oIs߈ߙŒ\a9Ì#;iRÄÓñ^q:@:“Ã]É(öÆ­Þ6·Äˆ{1õ¶·GbçŸn߯›ê°¶OqÇ-’A½ïM‰óŸ}‰Sᯮ‰ð,<}ŽáØkxÜÖû•«X!ñöÚGÂûõ­.©L…üŸhCTRœRšˆ–¡Íçó>6V¡ÊÒ*øo Aºß«ÓÀe?ØÂ‘z4ZQê)ëAÐÕ OõÓ¦ìÿâ™Q7Á‡ß|3ÝþQT›íó"ép˜vó” > m'A•‚ê–ŒD˜-IG2û ñÃAw±38DœÊoD[3ö$À÷nu’’—vÌxÁ˜È3Çy¼AF?|ëê‰w¾èǼ̑ÑBÄŒŸßßëð~ïÂOËÝa$þø;'ÉÒîËG ˜Q“ÕÚÜPׯ¡ÁÂÚ2XȈP zNœ.Nüê <•¿‚.u»ËlÖrÒœŽbK1·Óµ¹;ced Št2žrg»?qã±8”kA­%BÝ`ÓÛ 00‡‡Ÿ|(¸›ø_ . u3¦.sƒ«®±ÝêF°–j )¼xl7lçTJÜ+ìeâS¬½<> »³“«eŽ¡c…•Ñ6eYºII`^ä áÖ®w J<Å·Ocüù=ºPuáÁ¤¦èp÷ÊÖ•î•í/‡›µŽT„róÔº¼|y¸f§4jcé>”mÍuº¬•Qdw¹²ëÒùê­§R{¹¯‘Ïtxükï½Þ{5Çšú.øùk¡xffñH‘™˜Ÿ¦ŒJÊŒJ¸™øYò-ƒCï@ØÚ‰ê‡+ ˜ŸK}¯°MM"K±þ6Û‡•šô¸K7ðâV õH&XŽégH±Oüú—XÂ{Qkà†ÔÂÝiÆm›OÊ¥Ÿð2þ;‹!„ÜM†ühÃAÞªñ’ª™‚©{ä1þÉû"Ë' iŽT q?÷ PRnœÂð×…Î%™“È;‹ÿ“k$Ì Å`[tÂnnŠý{Ñuè;k”híøÕl6!¹(o¿›è‘¿žáK~颮¯ï«œF³z´Ùîº}¯H²~,»|48‡.ë_ù9)Ã^{÷5C¨ø|Vãnöpdç(8‚Ö¤G‰(±4Á •õß­þÑøMÐM{5 i‚&ùÖ¡`÷CU œD§L^Ww}g:޼©]Iu;]Ûʶ 8f”Åð¾G~ºU#duþÑŠw˜ó¦FòED)®K%²ù5Fel¨ó+žÙŽ/†iYZO”VØà§8}íÜ&‘&JR÷ää„§§%KãŒp„jÏ‘4?Ó¨c²U¦*9kê+*]mMW[½n/7[ÉKËEq&ŸiØ4JÎ#;Ç?°û~OLH|J§ƒ^ü<í’âYõ’W™ÈÅæ[<:Üà>fsÛ܈4äI¦Ñ`ÍC*8QÕè[V‹e¦ªfFÜ„76عtüûø±¦ñãþ6öô8nþ¬õåΙßMý_ÕUûº endstream endobj 52 0 obj <> stream xÚUiPTW~MÃ{×%¨<[{&úžZŽ“2QQ1£ŽÑ(Žû JÜ ÆÙz¥é…îf=ÝÐÐÝÐÐ@/€ j4EÀŒ1¦Ñ¸Œ³”­25Ѻ=u̼6Sóc~NÕ«óãÞsß9ç»ß÷]I‰D¢ñ6&~´&ùÝmk“’b—ÄÆ†×âBoS¡)¡©âÐäHrˆ)QÿóoQS)ŠêŸ޾qáX4>ߨˆJ,Ersbç.\•™-—̶)ëÀÁÜcÓ’ÔÙ•¹iÂÊÿìP”è­¹Ôjµ‚ZIí£öS©ÃT•‘KÉD5Žb©©OM§VQRk©uÔzj3µ…ÚJm£¶S;¨ ”ˆŠ æP~Ñ$QyÄ»½âybGd[ÔÔ¨ïé4ú³†9…~íSà‰JÞ…'Šq5–H2̹rHCi­ŸrUt{u‹:QgNû~.Ú22 ‹B3‚âÐŒ["§oö}Ñ{}àroÏõªûÈÅ`–DÞ!¢ùD”4-½IhõxZ9¨38¡¾ÝqnäAÊBfjåÖ]é9Ùé9;÷I tªB£L_i‡¤=ÞÊN¾“ñ›³”jsýP2 ýÍÆW%ÝmÝÇ»O/K=µ^—ÇUïð8À‹´n5WLëË M…E‰‡¥q;%ÅíÐu&ÈGeŒõØ%E@}{ß—ßÞ7xXê,ršjË‘nt¹xð)ª j6ž•&žúó©Ä3M­¦ý§fh4¾&I9–’’·]ªÔ+tJ]QiʯÓ4r6ºÖê´;«OKŸö}Ûÿ´ÏåpÙ¡Y™²¶doVc¹µçÎ%ž–VÚõTL«uš|ä^s½áæéà‘+GÕÝz·E—]ÆÞ[†Eç¯?¹Šã¯‰C\H+Q×(ªä€f¥’qËç_$Ôßù»Ð3ÔpÓÞai‡“G)ð*KæN' È{dÖs²/ã®Â€¯û¬Ýns€µæUh¸LødÇF@FšÄԯãG!L}…§â‰ÜY8¡ò¥"2‹$K ²¼l¨ÿÄ7ƒ7šíÙ‘»d·äJºPtÉ0vàèõÃ1}A,Æã•l^b$‹ÇêÔsW½’'4Ù”GÆÏÿqÏþ<Ür¶µÒÏ”ä¡ÝþŠE¥†×Òìý<xx¼€—Å.xœ0¸¼NY¡% í JWgùT-u­¯#s$+˜ÍëTI64^æàâwM]Õ¶ŽŠw´Ïĺ[1w¿f³q ´AB"tsy M{Hh<“†/[7*Np ¯ºZͱg’Á³ì@ï'óp©åÒ…mMí•'5Ñî†r_ÂØr5~@­^oKð÷{x=m†"0— ‡ð¤!,«à“àwM†+HøççøµÄÁ\úì³^î/pvÕndd’SSwr»àÀ§E=H°Ü7 Vz•1Ød_ac(BBúÈ&[¯Wò q4–!¡±Ë82‡ÎÓêêZ­Ç.—d•hd C²¦¬¶“Þæãû¯ drì«R(-/øe¹…‡cÌxÔ–k8:ü±/pDh¦¤-ϪâÑ*µIö¦°»±ÚI- `J²/äƒ\U£m榽 ¿/¿VÁ‡TÇ2µÏ‚§,»38¢01²‚B™¬Áèå ½õ®&o¾Kþÿ¤*˜kú'K¹¢Pe(ÏäÔ§A:-)~ÅîNŒÇ҉Ä>ÃËB“´OÉ,Jn9­P›rnCÏÞ¿Hú’iö™\_ Êøy¼”nv;}úz9ŸŒÓÐiëð¶6Ÿ8Ý$(úLkþfž(Ó˜\Í›®„ôXº¹þ¿é™ôHÎ73¸Ý°G}8ý{Üõ=A1¶„¥©[1¯d*dˆø1‰À1\-£œ÷ŸWþ‚ì /Ã4™Ä‘ÉDv%T¢‘‘œ…ž5öá\üžØ…Ü2Hyl¾2Eb®Ù”1ÇñÎø Û†e˜H:˜Öº,ŽDÓÊüB¹¢^ß̳-OH_Í‘é´*u]gÛªÀf©@ôѧÜH˜!› H€vFô“þWx,—íÍ÷û½ Žu]Þä<Âý ¶gìÝû«-Ç{‡ñ8œ³ƒ¬ Ï­–Äѹ:RY§÷ñß í+ú÷>|ÔûWÉɧBS†ê(b»µ9ÙÚc€¶èººxœ‡×2î G=Ô#Á,ó9²ä[º-ß®ThŒÂ[XrGPè§ð5Š óßÌÀ1뱆¼À‹Ænè‚nçÉ‹ÊeðzJ{œ~¯¦FÅ$HÀoªOç–Òùò’,uMŸ¿DRé?n‘'>Ty…æÙÔÁ½O+ ò\ÙËGÖ„VÙq| M6†-®ù`ì¨ê±£-cǼÝ;†K\_2ÙQ"ý×ÄVë<í endstream endobj 53 0 obj <> stream xÚ]PÁj„0½ç+渥“”–-ˆP\)Ûnë.,½Åd´BMBŒÿ¾&ÊzÈðfòæñÞ$yu¨tï!99#kôÐöZ9Íä$Bƒ]¯ ã zé·.V9K’ü(ì»’ïÓgñVÜçÇâÊèÃå\²gPØ®”óløÖW‡z=•n ¤)H¾ÅÑ»v¯Ê4xfN¡ëu»K^ÇI=Yû‹j”dY”c«'iŽVHtBwHRJ3HË2#¨Õ¿¿Çu£iåp$åI)ßg f+~YðÓ~Áœ356vP ¹o±åäÜâ''& ¦z·ûYcÃV| wqß endstream endobj 55 0 obj <> stream xÚUmlSUÇïéËݵ{QÆš¹ëî&]hJ2”;6?hyS]rÛÞmë ·jÅÍÁÖÞÓ[p/‰Ž’‘l~2ã‹_H5H˜ñ“1! øP0&ÎE£,yNw®‰·!ðáüÏó?¿çyÎ9b,!Twâð‘îw»·wù»ïôTN¼ ~5Î[¯•¿²’×ÒŠÈ6yÝL-M ƒB›*úáËõ¿b(ã0Ä|¹ž©6šñmÞGá»Wâ¢,E¥>Åîï_7r¸`Ýd1ø©¤T jÖá3WAåyP§"Q Ç¢¡p">(¦<ž]n§½+O­gÎ`›°³£ÃëÚ=žáíˆ$‡ƒbTð‹Ê€T) ŠƒÂû±`XRR‚óÍÊuûvìH&“n1’pÇäþÎ6— +ÂQ)!ɧ¥Ð‹*ÂA1" ãqol]±Hü”"É‚?’ä¨1 ³€ÚÍÇ`¥Q©£,ÒÎÄ ÆÂ\BMh?ú ¡+¦V’®+˯ž¼ÊWçf ¯˜Ë~õ¬ç°vab;po@Ãah¦°x Ö0ñaÒù±ÜÍwÁö0ZNÓðEnú<>ç8‡38“QUÿ¡ýÔD}TÝE ½ôF‚î¥{1õbÝVÐëa7]þ…º–iÓ_­S£Y5¹™ <Ýüü[HÜä×Þ³cbû˜ÔÓݰ|\.hr>ùbRÍžÁÜÐ(iÆãÇ´ôŸ”»Oi34ÒÅ›t ë>¬wžÐmÔI¡›ß¢¶vʨ™ô8Ns#“økÇ Ö°¦e³?ýxLàõ1®Ã9Ø3 {1x¹º²›/ Wyv¡ˆ`©h†%ÃÚ‹<{òEZb_àsŸÛàUU´Ôù Þbä_›}Vßb‡R‘æ=/ò§õ}všï’ÑÃà¼už_K?â-ÿ|xË¿Fl‡ZøÕ*³¡Ö–whUäôXÛIúæô¿Yò%ùcbRËáK[åÎOë}åM[Èu^Å¿Men>:³ôÑüÙŸ{öqó,­…+O¬‚U5}AMãÏð0ùæ¿-úŒþdäs<†Õ­ÃSøŠ£.9Ëò45[U°ª¿›¨©1V­ÃfIÅj^‚RÃÿôöš endstream endobj 56 0 obj <> stream xÚ]PÁjÃ0 ½û+tìÃIe()PÒ¥=ôèØJfhl£8‡üý7ô°ƒzzOÒ/ªSeMþMN5 3VŽn"…Ðbo,K÷  [³¤g¼¨¥¿È×Åñr?¿usO“ÛµL ±{R®³GØouujæ1àPÙÎ €ÿ,Ç@3ìŽÚµø¶b_¤‘Œíaw+šˆ4“÷ÐHXžÇqéó&å4Ž^*$i{d"Ire™3´ú_oS´ú•ÄDvX˜I–}FªÕßËžšˆ–½ñ ÑѺÜX|ýÉ;¿ªbü²šmM endstream endobj 58 0 obj <> stream xÚcd`aa`ddäóuvô‹ôÖvö Ž44‰Øäý ùõáçlÖ2 ?dÈ1ýgþ!Î"÷Ћå?“,#³ døÇ"€H5p¾+ÐDÑæÎy©é‰%™ùyÅ9‰ÅÆzFÎù•E™é% Éš †––æ: F– ޹©E™É‰y ¾‰%©¹@ɉ9 ÁùÉ™©%• 6%%Vúúåååz‰¹ÅzùEévš: å™% A©Å©Ee©) nùy% ~‰¹© ŸèA(çü܂ҒÔ"ßü”Ô¢< #™Ì€^ÆØÎÀÌÈÈ¢™ö£ƒïçÜïU›ïýøÎüSý{•蜹ÝóçWvWÉÿÙÈVUÙ]^>·{Ž<_÷øç3~—ÿÑÎü“ë§¥èä™Ý½Ý}“ZgÔÊÕww´¶Ôþ ýûW¢¹¶»³»ƒ£yRý ¹éÝ}'Íäà+^üÓ~!Ûoéiìr\,æóy8'ñpõðpoæÚ̽y6ó~(ÈH‹C endstream endobj 60 0 obj <> stream xÚ]‘Ïnƒ0 Æïy ÛÃaˆnB¢$û£Ñ>ML‡4Bè¡o¿8a=ì@äüð÷Ù±#ÑV­Wˆ>í,;\aµ²¸Ì7+.x5ã ¨Q®ÛÍŸrê ‹Ä[oÞû !:%e­å¬F}}:ŸžÂ!$œî!ÙîmÕÝ—§V3ä9ˆ¾œß²Ú;ìJ5_pOìÃ*´Î vgÑyÒÝŒùÁ õ 1+ oÇCG®,.¦—h{}E–ÇqyÓ µú÷/ ŠË ¿{Ërž¹Ì$æiÁrAª8屋«ÔÇ ñêâƒ÷Û”ÙŸÏVR$.IOÈœÅK’€ $P»¸âÔÔ¾íWž©‹æÞA =nåCAzmà±y³ÖÍÆ¯ÉO4j|lÒ̆TþûŸŸ“8 endstream endobj 18 0 obj <> stream xÚíZio9ý>¿‚ß&A`‰÷1ð9ñøˆ%±×“Z»ãH,C’™¿¯Ènö!Ùédí»„°‹d±ªøøXdw,ãL*&œ`Ò2Å5SLsÇD`Ú¡K3£“Ž™`™dÖz&˜óèñÌ L(Ž'Ù°x&<Œ)³Î0 b5Ó¤Â-ÓŠ)Mut™àá„)«9ÓžžU´¨hާƒªALL[a=ƒçJú¿ž?OF&Ó›­ñ¢x¶õçØ“4Øð\ýÊù¯Ï“¿r5µ8‰Íñbüizî ¿´”?õsþ~Dµ _–‘à§n`ÊQI6‘µTÒ?+mÙ–ÆUíI·´Ì€ø—ž•Fòi¸÷¿\H'’ŽÓxæØ:õŸ?¬¥RåJ-ÿ| …“z {XªÑÅI×à‡Ñä!•Í–J¿Ùƒš°q-õc0€7e~òâ‘øÄý|ªy‚;öª-e^Õö1ÕŒãŒqÑ’ál2Jè^DÌJ=iL’éN–Fãž9¨ò‚±’úâÈv ± ëî¹èu6(oa)•T—Ž"TŠ"HrœYpð}_YÙªõWçÖ,99 ëg=ûàÈÿ'érÞ ÜF  ‚ͼ%©¬ž`r¢IÃZ³EÅå¥Ò8X †$/})¥¶åÒ&Š¥ÑB³—F–­RC/E™ä¦žç-©ä1ò:¼&ÍAn Âjåå“޶M*wñ´ŠˆHÞˆSiM9¶fÓ›áñB »¤6ØØñø¶3¶ÖƤð?å=XJâDsö†÷ûWñ cËrß–ô8ØšG˜XÃþ±âØÅû¬ å샢Äj¤‹ LǨcK‡åCG¦Ç‹4-xèªä %0-t’ïáɽ}6„FRû¶Þ×xW{J’Ç! þwSX †-2wûàUá’ŸŽ2‚6®<¤R}¹´ÞTõ8²ÙG‡©«Ú±ÞŠb‹‘¤þ1úª£Ð` eÊTUÖlÊ­˜Ëöîó¿ûÝgu•—$7Ëe ±ÄŒ\ Iå×bH™g¹| ~­ÓÖuO‚¿rÛ­^ôé‹Èðôîß ªP‹¾›\->Îé{]ü 2™Í›Ç3h¸?.eiÄpûærz5¹¹¦Rñ{úæf‚¦GtlØÏ‹hÿlëÕë?Þ½8Ý99Núèt«˜_Î&·‹éŒ¾ÑÅ,­ ê~¼Çß¾*&×ฮÏ/é† fH:$¯‰ †»xÙŸ\®ß\*ž.ŠÏo‘«‡;ŸÆ×sf£Í úR±&œfk ç«PÚa{†÷±sgò©PL–_Ðp8þ\tCï¹9Å»ÈÙr€±?r£wg–î%çKÈÉ‹RÌš’Ä\I‰M6‘S¢\'ô‡‘«Pé_¥ê@©j$®qÚmŸŸ½Ø<8=_¦—ê’ª@â"ÞÂgMè×%HX×’ã ”°ükï’‚àr®E/¥Û 5ãîÇ-óà®ünívϱ@£]ÁÁ‰.lú±¹ÕÂ.¬…]ÐÁ¸Àmǵ°³mì:ñ÷ƒÏuà“ò{á;<__?ÜJü^ŸùÁ[ÓWÈi³´5}¹Nèý ]ätœŒ˜?7OwÎÁé¬Ë,ö;6£ º ‹¾ŸUN®Ü‘’­Il¸Æû—áMl4ocÓŠ¾2Zt·d ŒµýöíëW°|²÷ذTl±a[0閑ջݜmÇŸªFä|o4:>X/gmÿ´Dñ«ˆ"u‰‹ ÿoëàÒIÝÍàûá²”ºýj¢ì¾Ù|÷æ˜_F%<Oœ]Á¤Ü’'nN:nDÝwÿÑÞàÈÆÞæþëÝxBÚ.Ž?ÕÉnVæ°#hº7â–è¼m¡ÑI±Í°ûÁÑͯZïÉ´s¶¿ûöϘÞyX¾4º|Ý–N&úc.»gºédßNè½3âë¶îÛÛ?9Û¦;ëh´¹þ×mQï>!kä¤ý‘“HBk A å,óZ·ë¤éNè}¯ÛF5¯ÛFw÷dãzä} Ô¿ŽŽ·÷¶Aïí³åÃÌõ¾pó¯mÊ íVáCÙ:Xºó pçZwcÚø´"îŽm¡ÓÍX|õËÈÁæúáù^Üû+ÀÑOö6²òFTµ1‚¾š›F¤Õ <…H“ªöp¸Y¿™Or}kòáC1+n. ú„añùj<ÿ8¸üÛ.ÈáøÃd‚ † ¿ Ò¹*Iò, hø\˺ÒdÉ2ɳEYëfkxé’ÜæZÖU*KÙ.Þ¡¤¨5[ö"KÙ‡Ï>|ö᳟}øìÃg>ûÙGñOUËÖë• ÙzÈÖƒ£?þø‘7V endstream endobj 75 0 obj <<583f00ba5fbb79f7cea6f44186d7272f>]/Size 76/W[1 2 2]/Filter/FlateDecode/Length 213>> stream xÚ%Í;2Ãa…ñ÷D\â–›kBâ–HlÀ&h”)ŒÉŒ"cX€IKÁÐ*t†ÎlÂÔúø?sšß<ç-¾/"†ÃTbÆaaʰ k°›°ÛЀ=8Pd#¨ÐË+ M8RæÒ7Á¨Š ÏŒAF¥žo“ªŸ%¯4ÓžSj»¦ÕþpÍèäÍ5«ó?WVÝ;WN½+W^ýŽ« ëwWQ7¿®9 ¾“îo=çõð•ÌÇSÏ= \=_¸– +Pu¨B ê°»°‡Ð‚¶^?#þ ‚ endstream endobj startxref 41391 %%EOF glpk-4.52.1/examples/0000755000062000006210000000000012175147600013537 5ustar maomkpasswdglpk-4.52.1/examples/assign.mod0000644000062000006210000000404512175147600015527 0ustar maomkpasswd/* ASSIGN, Assignment Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The assignment problem is one of the fundamental combinatorial optimization problems. In its most general form, the problem is as follows: There are a number of agents and a number of tasks. Any agent can be assigned to perform any task, incurring some cost that may vary depending on the agent-task assignment. It is required to perform all tasks by assigning exactly one agent to each task in such a way that the total cost of the assignment is minimized. (From Wikipedia, the free encyclopedia.) */ param m, integer, > 0; /* number of agents */ param n, integer, > 0; /* number of tasks */ set I := 1..m; /* set of agents */ set J := 1..n; /* set of tasks */ param c{i in I, j in J}, >= 0; /* cost of allocating task j to agent i */ var x{i in I, j in J}, >= 0; /* x[i,j] = 1 means task j is assigned to agent i note that variables x[i,j] are binary, however, there is no need to declare them so due to the totally unimodular constraint matrix */ s.t. phi{i in I}: sum{j in J} x[i,j] <= 1; /* each agent can perform at most one task */ s.t. psi{j in J}: sum{i in I} x[i,j] = 1; /* each task must be assigned exactly to one agent */ minimize obj: sum{i in I, j in J} c[i,j] * x[i,j]; /* the objective is to find a cheapest assignment */ solve; printf "\n"; printf "Agent Task Cost\n"; printf{i in I} "%5d %5d %10g\n", i, sum{j in J} j * x[i,j], sum{j in J} c[i,j] * x[i,j]; printf "----------------------\n"; printf " Total: %10g\n", sum{i in I, j in J} c[i,j] * x[i,j]; printf "\n"; data; /* These data correspond to an example from [Christofides]. */ /* Optimal solution is 76 */ param m := 8; param n := 8; param c : 1 2 3 4 5 6 7 8 := 1 13 21 20 12 8 26 22 11 2 12 36 25 41 40 11 4 8 3 35 32 13 36 26 21 13 37 4 34 54 7 8 12 22 11 40 5 21 6 45 18 24 34 12 48 6 42 19 39 15 14 16 28 46 7 16 34 38 3 34 40 22 24 8 26 20 5 17 45 31 37 43 ; end; glpk-4.52.1/examples/bpp.mod0000644000062000006210000000437312175147600015030 0ustar maomkpasswd/* BPP, Bin Packing Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* Given a set of items I = {1,...,m} with weight w[i] > 0, the Bin Packing Problem (BPP) is to pack the items into bins of capacity c in such a way that the number of bins used is minimal. */ param m, integer, > 0; /* number of items */ set I := 1..m; /* set of items */ param w{i in 1..m}, > 0; /* w[i] is weight of item i */ param c, > 0; /* bin capacity */ /* We need to estimate an upper bound of the number of bins sufficient to contain all items. The number of items m can be used, however, it is not a good idea. To obtain a more suitable estimation an easy heuristic is used: we put items into a bin while it is possible, and if the bin is full, we use another bin. The number of bins used in this way gives us a more appropriate estimation. */ param z{i in I, j in 1..m} := /* z[i,j] = 1 if item i is in bin j, otherwise z[i,j] = 0 */ if i = 1 and j = 1 then 1 /* put item 1 into bin 1 */ else if exists{jj in 1..j-1} z[i,jj] then 0 /* if item i is already in some bin, do not put it into bin j */ else if sum{ii in 1..i-1} w[ii] * z[ii,j] + w[i] > c then 0 /* if item i does not fit into bin j, do not put it into bin j */ else 1; /* otherwise put item i into bin j */ check{i in I}: sum{j in 1..m} z[i,j] = 1; /* each item must be exactly in one bin */ check{j in 1..m}: sum{i in I} w[i] * z[i,j] <= c; /* no bin must be overflowed */ param n := sum{j in 1..m} if exists{i in I} z[i,j] then 1; /* determine the number of bins used by the heuristic; obviously it is an upper bound of the optimal solution */ display n; set J := 1..n; /* set of bins */ var x{i in I, j in J}, binary; /* x[i,j] = 1 means item i is in bin j */ var used{j in J}, binary; /* used[j] = 1 means bin j contains at least one item */ s.t. one{i in I}: sum{j in J} x[i,j] = 1; /* each item must be exactly in one bin */ s.t. lim{j in J}: sum{i in I} w[i] * x[i,j] <= c * used[j]; /* if bin j is used, it must not be overflowed */ minimize obj: sum{j in J} used[j]; /* objective is to minimize the number of bins used */ data; /* The optimal solution is 3 bins */ param m := 6; param w := 1 50, 2 60, 3 30, 4 70, 5 50, 6 40; param c := 100; end; glpk-4.52.1/examples/cal.mod0000644000062000006210000000265312175147600015005 0ustar maomkpasswd/* cal.mod - print an ASCII calendar of the given year */ /* Written in GNU MathProg by Andrew Makhorin */ param year, integer, >= 0001, <= 3999, default 2010; param first_day{m in 1..12}, integer, >= 0, <= 6, := time2str(str2time(year & "-" & m & "-01", "%Y-%m-%d"), "%w"); param days_in_month{m in 1..12}, integer, >= 28, <= 31, := (str2time(year + (if m < 12 then 0 else 1) & "-" & (if m < 12 then m+1 else 1) & "-01", "%Y-%m-%d") - str2time(year & "-" & m & "-01", "%Y-%m-%d")) / 86400; param foo{m in 1..12, k in 0..5, d in 0..6}, integer, := 7 * k + d + 1 - first_day[m]; param cal{m in 1..12, k in 0..5, d in 0..6}, integer, := if 1 <= foo[m,k,d] and foo[m,k,d] <= days_in_month[m] then foo[m,k,d]; printf "\n"; printf "%33s%04d\n", "", year; printf "\n"; for {t in 1..12 by 3} { for {m in t..t+2} { printf "%7s%-14s", "", time2str(str2time(m, "%m"), "%B"); printf{0..0: m < t+2} " "; } printf "\n"; for {m in t..t+2} { printf " S M Tu W Th F S"; printf{0..0: m < t+2} " "; } printf "\n"; for {k in 0..5} { for {m in t..t+2} { for {d in 0..6} { printf{0..0: cal[m,k,d] = 0} " "; printf{0..0: cal[m,k,d] != 0} " %2d", cal[m,k,d]; } printf{0..0: m < t+2} " "; } printf "\n"; } } printf "\n"; end; glpk-4.52.1/examples/cf12a.mod0000644000062000006210000000216312175147600015136 0ustar maomkpasswd/* Curve fitting problem 12.11(a) H P Williams "Model Building in Mathematical Programming" Dr. H J Mackenzie HARD software hjm@hardsoftware.com 2006-01-05 */ # set of points set I; # independent variable param x {i in I}; # dependent variable param y {i in I}; # output input values printf {i in I} "x = %.1f; y = %.1f\n", x[i], y[i]; # define equation variables var a; var b; var u {i in I}, >= 0; var v {i in I}, >= 0; # define objective function minimize error: sum {i in I} u[i] + sum {i in I} v[i]; # define equation constraint s.t. equation {i in I} : b * x[i] + a + u[i] - v[i] = y[i]; solve; printf "y = %.4fx + %.4f\n", b, a; /* * * DATA section * */ data; param : I : x y := 1 0 1 2 0.5 0.9 3 1 0.7 4 1.5 1.5 5 1.9 2 6 2.5 2.4 7 3 3.2 8 3.5 2 9 4 2.7 10 4.5 3.5 11 5 1 12 5.5 4 13 6 3.6 14 6.6 2.7 15 7 5.7 16 7.6 4.6 17 8.5 6 18 9 6.8 19 10 7.3 ; end; glpk-4.52.1/examples/cf12b.mod0000644000062000006210000000235112175147600015136 0ustar maomkpasswd/* Curve fitting problem 12.11(b) H P Williams "Model Building in Mathematical Programming" Dr. H J Mackenzie HARD software hjm@hardsoftware.com 2006-01-23 */ # set of points set I; # independent variable param x {i in I}; # dependent variable param y {i in I}; # output input values printf {i in I} "x = %.1f; y = %.1f\n", x[i], y[i]; # define equation variables var a; var b; var u {i in I}, >= 0; var v {i in I}, >= 0; var z; # define objective function minimize deviation: z; # define equation constraint s.t. equation {i in I} : b * x[i] + a + u[i] - v[i] = y[i]; # define deviation constrains s.t. u_deviation {i in I} : z - u[i] >= 0; s.t. v_deviation {i in I} : z - v[i] >= 0; solve; printf "y = %.4fx + %.4f Max deviation = %.4f\n", b, a, z; /* * * DATA section * */ data; param : I : x y := 1 0 1 2 0.5 0.9 3 1 0.7 4 1.5 1.5 5 1.9 2 6 2.5 2.4 7 3 3.2 8 3.5 2 9 4 2.7 10 4.5 3.5 11 5 1 12 5.5 4 13 6 3.6 14 6.6 2.7 15 7 5.7 16 7.6 4.6 17 8.5 6 18 9 6.8 19 10 7.3 ; end; glpk-4.52.1/examples/cflsq.mod0000644000062000006210000000203312175147600015346 0ustar maomkpasswd/*Curve fitting problem by Least Squares Nigel_Galloway@operamail.com October 1st., 2007 */ set Sample; param Sx {z in Sample}; param Sy {z in Sample}; var X; var Y; var Ex{z in Sample}; var Ey{z in Sample}; /* sum of variances is zero for Sx*/ variencesX{z in Sample}: X + Ex[z] = Sx[z]; zumVariancesX: sum{z in Sample} Ex[z] = 0; /* sum of variances is zero for Sy*/ variencesY{z in Sample}: Y + Ey[z] = Sy[z]; zumVariancesY: sum{z in Sample} Ey[z] = 0; solve; param b1 := (sum{z in Sample} Ex[z]*Ey[z])/(sum{z in Sample} Ex[z]*Ex[z]); printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", Y-b1*X, if b1 < 0 then "-" else "+", abs(b1); data; param: Sample: Sx Sy := 1 0 1 2 0.5 0.9 3 1 0.7 4 1.5 1.5 5 1.9 2 6 2.5 2.4 7 3 3.2 8 3.5 2 9 4 2.7 10 4.5 3.5 11 5 1 12 5.5 4 13 6 3.6 14 6.6 2.7 15 7 5.7 16 7.6 4.6 17 8.5 6 18 9 6.8 19 10 7.3 ; end; glpk-4.52.1/examples/color.mod0000644000062000006210000000545012175147600015362 0ustar maomkpasswd/* COLOR, Graph Coloring Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* Given an undirected loopless graph G = (V, E), where V is a set of nodes, E <= V x V is a set of arcs, the Graph Coloring Problem is to find a mapping (coloring) F: V -> C, where C = {1, 2, ... } is a set of colors whose cardinality is as small as possible, such that F(i) != F(j) for every arc (i,j) in E, that is adjacent nodes must be assigned different colors. */ param n, integer, >= 2; /* number of nodes */ set V := {1..n}; /* set of nodes */ set E, within V cross V; /* set of arcs */ check{(i,j) in E}: i != j; /* there must be no loops */ /* We need to estimate an upper bound of the number of colors |C|. The number of nodes |V| can be used, however, for sparse graphs such bound is not very good. To obtain a more suitable estimation we use an easy "greedy" heuristic. Let nodes 1, ..., i-1 are already assigned some colors. To assign a color to node i we see if there is an existing color not used for coloring nodes adjacent to node i. If so, we use this color, otherwise we introduce a new color. */ set EE := setof{(i,j) in E} (i,j) union setof{(i,j) in E} (j,i); /* symmetrisized set of arcs */ param z{i in V, case in 0..1} := /* z[i,0] = color index assigned to node i z[i,1] = maximal color index used for nodes 1, 2, ..., i-1 which are adjacent to node i */ ( if case = 0 then ( /* compute z[i,0] */ min{c in 1..z[i,1]} ( if not exists{j in V: j < i and (i,j) in EE} z[j,0] = c then c else z[i,1] + 1 ) ) else ( /* compute z[i,1] */ if not exists{j in V: j < i} (i,j) in EE then 1 else max{j in V: j < i and (i,j) in EE} z[j,0] ) ); check{(i,j) in E}: z[i,0] != z[j,0]; /* check that all adjacent nodes are assigned distinct colors */ param nc := max{i in V} z[i,0]; /* number of colors used by the heuristic; obviously, it is an upper bound of the optimal solution */ display nc; var x{i in V, c in 1..nc}, binary; /* x[i,c] = 1 means that node i is assigned color c */ var u{c in 1..nc}, binary; /* u[c] = 1 means that color c is used, i.e. assigned to some node */ s.t. map{i in V}: sum{c in 1..nc} x[i,c] = 1; /* each node must be assigned exactly one color */ s.t. arc{(i,j) in E, c in 1..nc}: x[i,c] + x[j,c] <= u[c]; /* adjacent nodes cannot be assigned the same color */ minimize obj: sum{c in 1..nc} u[c]; /* objective is to minimize the number of colors used */ data; /* These data correspond to the instance myciel3.col from: http://mat.gsia.cmu.edu/COLOR/instances.html */ /* The optimal solution is 4 */ param n := 11; set E := 1 2 1 4 1 7 1 9 2 3 2 6 2 8 3 5 3 7 3 10 4 5 4 6 4 10 5 8 5 9 6 11 7 11 8 11 9 11 10 11 ; end; glpk-4.52.1/examples/cplex/0000755000062000006210000000000012175147600014652 5ustar maomkpasswdglpk-4.52.1/examples/cplex/concorde.txt0000644000062000006210000000726312175147600017217 0ustar maomkpasswdSolver: Concorde-03.12.19 (options used: -s 99) http://www.tsp.gatech.edu/concorde.html LP Solver: GLPK 4.34 (CPLEX-like interface module examples/cplex) Computer: Intel Pentium 4 CPU 3GHz, 2GB of RAM Platform: Cygwin 1.5.24 (Windows XP 5.1 Build 2600 Service Pack 4) Compiler: GCC 3.4.4 (options used: -O2) Test set: http://www.iwr.uni-heidelberg.de/groups/comopt/software/ TSPLIB95/ Problem Solution B&B Time, s --------- -------- --- ------- a280 2579 1 3.09 ali535 202339 1 21.88 att48 10628 1 0.20 att532 27686 7 74.31 bayg29 1610 1 0.08 bays29 2020 1 0.08 berlin52 7542 1 0.11 bier127 118282 1 0.62 brazil58 25395 1 0.23 brd14051 brg180 1950 1 0.34 burma14 3323 1 0.06 ch130 6110 1 0.92 ch150 6528 1 1.69 d1291 d15112 d1655 d18512 d198 15780 3 4.92 d2103 d493 35002 5 123.89 d657 48913 11 148.17 dantzig42 699 1 0.08 dsj1000 18660188 13 251.00 eil101 (failed due to CPXgetijdiv) eil51 426 1 0.17 eil76 538 1 0.11 fl1400 fl1577 fl3795 fl417 11861 1 47.20 fnl4461 fri26 937 1 0.05 gil262 2378 3 10.39 gr120 6942 1 0.66 gr137 69853 1 2.09 gr17 2085 1 0.03 gr202 40160 1 3.97 gr21 2707 1 0.03 gr229 134602 7 19.45 gr24 1272 1 0.03 gr431 171414 9 40.67 gr48 5046 1 0.22 gr666 294358 3 40.23 gr96 55209 1 1.22 hk48 11461 1 0.08 kroA100 21282 1 0.41 kroA150 26524 1 2.09 kroA200 29368 1 2.44 kroB100 22141 1 1.20 kroB150 26130 1 1.66 kroB200 29437 1 1.41 kroC100 20749 1 0.42 kroD100 21294 1 0.50 kroE100 22068 1 0.94 lin105 14379 1 0.23 lin318 42029 1 4.28 nrw1379 p654 34643 1 17.08 pa561 2763 15 370.70 pcb1173 56892 11 370.30 pcb3038 pcb442 59778 13 35.86 pla33810 pla7397 pla85900 pr1002 259045 1 23.08 pr107 44303 1 0.38 pr124 59030 1 1.23 pr136 96772 1 2.19 pr144 58537 1 0.89 pr152 73682 1 2.73 pr226 80369 1 2.72 pr2392 pr264 49135 1 1.61 pr299 48191 3 14.52 pr439 107217 15 117.75 pr76 108159 1 0.95 rat195 2323 5 12.91 rat575 6773 19 202.52 rat783 8806 1 37.92 rat99 1211 1 0.50 rd100 7910 1 0.28 rd400 15281 11 74.41 rl11849 rl1304 rl1323 rl1889 rl5915 rl5934 si1032 92650 1 82.09 si175 21407 3 8.97 si535 48450 1 71.28 st70 675 1 0.20 swiss42 1273 1 0.06 ts225 126643 1 21.25 tsp225 3916 1 10.14 u1060 224094 13 507.44 u1432 u159 42080 1 0.41 u1817 u2152 u2319 u574 36905 1 32.84 u724 41910 19 238.42 ulysses16 6859 1 0.19 ulysses22 7013 1 0.47 usa13509 vm1084 239297 9 543.38 vm1748 glpk-4.52.1/examples/cplex/cplex.c0000644000062000006210000017754512175147600016154 0ustar maomkpasswd/* cplex.c (CPLEX-like interface to GLPK API) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include #include #include #include #include #include #include "cplex.h" struct CPXENV { /* environment block */ CPXLP *list; /* linked list of problem objects */ int *intparam; /* int intparam[]; */ /* integer control parameters */ double *dblparam; /* double dblparam[]; */ /* floating-point control parameters */ }; struct CPXLP { /* problem object */ CPXENV *env; /* pointer to environment block */ glp_prob *prob; /* pointer to underlying GLPK problem object */ int rflen; /* length of the array rflag */ char *rflag; /* char rflag[rflen]; */ /* rflag[i], i = 0,...,nrows-1, is a flag of i-th row: */ #define RF_NOT_RANGED 0 /* not ranged */ #define RF_RANGED_POS 1 /* ranged, RHS = lower bound */ #define RF_RANGED_NEG 2 /* ranged, RHS = upper bound */ int stat; /* solution status reported by CPXgetstat; zero means no solution exists */ int meth; /* method indicator reported by CPXgetmethod */ int iwlen; /* length of the working array */ int *iwork; /* int iwork[iwlen] */ /* working array initialized by binary zeros */ CPXLP *link; /* pointer to another problem object */ }; struct intparam { int which; int defv; int minv; int maxv; }; struct dblparam { int which; double defv; double minv; double maxv; }; struct errstring { int code; const char *string; }; #define BIGINT 2100000000 #define BIGDBL 1e75 static const struct intparam intparam[] = { {CPX_PARAM_ADVIND, 0, 0, 2}, {CPX_PARAM_AGGIND, -1, -1, BIGINT}, {CPX_PARAM_DATACHECK, CPX_OFF, CPX_OFF, CPX_ON}, {CPX_PARAM_DPRIIND, CPX_DPRIIND_AUTO, CPX_DPRIIND_AUTO, CPX_DPRIIND_DEVEX}, {CPX_PARAM_FASTMIP, CPX_OFF, CPX_OFF, CPX_ON}, /* ??? */ {CPX_PARAM_ITLIM, BIGINT, 0, BIGINT}, {CPX_PARAM_PERIND, CPX_OFF, CPX_OFF, CPX_ON}, {CPX_PARAM_PPRIIND, CPX_PPRIIND_AUTO, CPX_PPRIIND_PARTIAL, CPX_PPRIIND_FULL}, {CPX_PARAM_PREIND, CPX_ON, CPX_OFF, CPX_ON}, {CPX_PARAM_REINV, 0, 0, 10000}, {CPX_PARAM_SCRIND, CPX_OFF, CPX_OFF, CPX_ON}, {CPX_PARAM_SIMDISPLAY, 1, 0, 2}, }; static const struct dblparam dblparam[] = { {CPX_PARAM_EPOPT, 1e-6, 1e-9, 1e-1}, {CPX_PARAM_EPPER, 1e-6, 1e-8, BIGDBL}, {CPX_PARAM_EPRHS, 1e-6, 1e-9, 1e-1}, {CPX_PARAM_OBJLLIM, -BIGDBL, -BIGDBL, +BIGDBL}, {CPX_PARAM_OBJULIM, +BIGDBL, -BIGDBL, +BIGDBL}, }; static const struct errstring errstring[] = { {CPXERR_ARRAY_NOT_ASCENDING, "Array entry %d not ascending"}, {CPXERR_BAD_ARGUMENT, "Invalid argument"}, {CPXERR_BAD_CTYPE, "Invalid ctype entry %d"}, {CPXERR_BAD_FILETYPE, "Invalid filetype"}, {CPXERR_BAD_LUB, "Invalid bound change indicator entry %d"}, {CPXERR_BAD_PARAM_NUM, "Invalid parameter number"}, {CPXERR_BAD_SENSE, "Invalid sense entry %d"}, {CPXERR_BAD_STATUS, "Invalid status entry %d for basis specificat" "ion"}, {CPXERR_COL_INDEX_RANGE, "Column index %d out of range"}, {CPXERR_COUNT_RANGE, "Count entry %d negative or larger than allo" "wed"}, {CPXERR_DUP_ENTRY, "Duplicate entry"}, {CPXERR_FAIL_OPEN_WRITE, "Could not open file '%s' for writing"}, {CPXERR_INDEX_RANGE, "Index is outside range of valid values"}, {CPXERR_NEGATIVE_SURPLUS, "Insufficient array length"}, {CPXERR_NO_BASIC_SOLN, "No basic solution exists"}, {CPXERR_NO_ENVIRONMENT, "No environment exists"}, {CPXERR_NO_FILENAME, "File name not specified"}, {CPXERR_NO_MEMORY, "Out of memory"}, {CPXERR_NO_PROBLEM, "No problem exists"}, {CPXERR_NO_SOLN, "No solution exists"}, {CPXERR_NOT_FIXED, "Only fixed variables are pivoted out"}, {CPXERR_NULL_NAME, "Null pointer %d in name array"}, {CPXERR_NULL_POINTER, "Null pointer for required data"}, {CPXERR_PARAM_TOO_BIG, "Parameter value too big"}, {CPXERR_PARAM_TOO_SMALL, "Parameter value too small"}, {CPXERR_ROW_INDEX_RANGE, "Row index %d out of range"}, }; /**********************************************************************/ #define xassert glp_assert #define xprintf glp_printf #define xmalloc glp_malloc #define xcalloc glp_calloc #define xfree glp_free /**********************************************************************/ static int findintparam(int whichparam) { int k, card; card = sizeof(intparam) / sizeof(struct intparam); for (k = 0; k < card; k++) if (intparam[k].which == whichparam) return k; return -1; } static int getintparam(CPXENV *env, int whichparam) { int k; xassert(env != NULL); k = findintparam(whichparam); xassert(k >= 0); return env->intparam[k]; } static int finddblparam(int whichparam) { int k, card; card = sizeof(dblparam) / sizeof(struct dblparam); for (k = 0; k < card; k++) if (dblparam[k].which == whichparam) return k; return -1; } static double getdblparam(CPXENV *env, int whichparam) { int k; xassert(env != NULL); k = finddblparam(whichparam); xassert(k >= 0); return env->dblparam[k]; } static const char *finderrstring(int errcode) { int k, card; card = sizeof(errstring) / sizeof(struct errstring); for (k = 0; k < card; k++) { if (errstring[k].code == errcode) return errstring[k].string; } return NULL; } static int error(CPXENV *env, int errcode, ...) { va_list arg; char buffer[510]; xassert(env != NULL); if (getintparam(env, CPX_PARAM_SCRIND) == CPX_ON) { xassert(CPXgeterrorstring(env, errcode, buffer) == buffer); va_start(arg, errcode); vprintf(buffer, arg); va_end(arg); } return errcode; } static int checkenv(CPXENV *env) { int errcode; if (env == NULL) errcode = CPXERR_NO_ENVIRONMENT; else errcode = 0; return errcode; } static checklp(CPXENV *env, CPXLP *lp) { int errcode; errcode = checkenv(env); if (errcode) goto done; if (lp == NULL) errcode = error(env, CPXERR_NO_PROBLEM); done: return errcode; } static void invalidate(CPXLP *lp) { lp->stat = 0; lp->meth = CPX_ALG_NONE; return; } static void enlargerflag(CPXLP *lp) { int m; xassert(lp != NULL); m = glp_get_num_rows(lp->prob); if (lp->rflen < m) { int rflen = lp->rflen; char *rflag = lp->rflag; while (lp->rflen < m) { lp->rflen += lp->rflen; xassert(lp->rflen > 0); } lp->rflag = xcalloc(lp->rflen, sizeof(char)); memcpy(lp->rflag, rflag, rflen); xfree(rflag); } return; } static void enlargeiwork(CPXLP *lp, int len) { xassert(len >= 0); if (lp->iwlen < len) { xfree(lp->iwork); while (lp->iwlen < len) { lp->iwlen += lp->iwlen; xassert(lp->iwlen > 0); } lp->iwork = xcalloc(lp->iwlen, sizeof(int)); memset(lp->iwork, 0, lp->iwlen * sizeof(int)); } return; } /**********************************************************************/ int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt, const double obj[], const int cmatbeg[], const int cmatind[], const double cmatval[], const double lb[], const double ub[], char *colname[]) { int j, k, m, n, beg, end, type, errcode; double lbnd, ubnd; errcode = checklp(env, lp); if (errcode) goto done; if (ccnt < 0 || nzcnt < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (ccnt > 0) { if (cmatbeg == NULL || cmatind == NULL || cmatval == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } } m = glp_get_num_rows(lp->prob); n = glp_get_num_cols(lp->prob); enlargeiwork(lp, m); for (j = 0; j < ccnt; j++) { beg = cmatbeg[j]; if (j > 0 && !(cmatbeg[j-1] <= beg)) { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j); goto done; } if (!(0 <= beg && beg <= nzcnt)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt); for (k = beg; k < end; k++) { if (!(0 <= cmatind[k] && cmatind[k] < m)) { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k); goto done; } } errcode = 0; for (k = beg; k < end; k++) { if (lp->iwork[cmatind[k]]) { errcode = error(env, CPXERR_DUP_ENTRY); break; } lp->iwork[cmatind[k]] = 1; } for (k = beg; k < end; k++) lp->iwork[cmatind[k]] = 0; if (errcode) goto done; if (colname != NULL) { if (colname[j] == NULL) { errcode = error(env, CPXERR_NULL_NAME, j); goto done; } } } errcode = 0; invalidate(lp); if (ccnt > 0) glp_add_cols(lp->prob, ccnt); for (j = 0; j < ccnt; j++) { if (colname != NULL) glp_set_col_name(lp->prob, n+j+1, colname[j]); lbnd = (lb == NULL ? 0.0 : lb[j]); ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]); if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) type = GLP_FR; else if (ubnd >= +CPX_INFBOUND) type = GLP_LO; else if (lbnd <= -CPX_INFBOUND) type = GLP_UP; else if (lbnd != ubnd) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd); if (obj != NULL) glp_set_obj_coef(lp->prob, n+j+1, obj[j]); beg = cmatbeg[j]; end = (j < ccnt-1 ? cmatbeg[j+1] : nzcnt); for (k = beg; k < end; k++) lp->iwork[k-beg] = cmatind[k]+1; glp_set_mat_col(lp->prob, n+j+1, end-beg, lp->iwork-1, cmatval+beg-1); for (k = beg; k < end; k++) lp->iwork[k-beg] = 0; } done: return errcode; } int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt, const double rhs[], const char sense[], const int rmatbeg[], const int rmatind[], const double rmatval[], char *colname[], char *rowname[]) { int i, j, k, m, n, beg, end, type, errcode; double temp; errcode = checklp(env, lp); if (errcode) goto done; if (ccnt < 0 || rcnt < 0 || nzcnt < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (rcnt > 0) { if (rmatbeg == NULL || rmatind == NULL || rmatval == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } } m = glp_get_num_rows(lp->prob); n = glp_get_num_cols(lp->prob); enlargeiwork(lp, n+ccnt); for (i = 0; i < rcnt; i++) { if (sense != NULL) { if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' || sense[i] == 'R')) { errcode = error(env, CPXERR_BAD_SENSE, i); goto done; } } beg = rmatbeg[i]; if (i > 0 && !(rmatbeg[i-1] <= beg)) { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, i); goto done; } if (!(0 <= beg && beg <= nzcnt)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt); for (k = beg; k < end; k++) { if (!(0 <= rmatind[k] && rmatind[k] < n+ccnt)) { errcode = error(env, CPXERR_COL_INDEX_RANGE, k); goto done; } } errcode = 0; for (k = beg; k < end; k++) { if (lp->iwork[rmatind[k]]) { errcode = error(env, CPXERR_DUP_ENTRY); break; } lp->iwork[rmatind[k]] = 1; } for (k = beg; k < end; k++) lp->iwork[rmatind[k]] = 0; if (errcode) goto done; if (rowname != NULL) { if (rowname[i] == NULL) { errcode = error(env, CPXERR_NULL_NAME, i); goto done; } } } for (j = 0; j < ccnt; j++) { if (colname != NULL) { if (colname[j] == NULL) { errcode = error(env, CPXERR_NULL_NAME, j); goto done; } } } errcode = 0; invalidate(lp); if (rcnt > 0) glp_add_rows(lp->prob, rcnt); if (ccnt > 0) glp_add_cols(lp->prob, ccnt); enlargerflag(lp); for (i = 0; i < rcnt; i++) { if (rowname != NULL) glp_set_row_name(lp->prob, m+i+1, rowname[i]); temp = (rhs == NULL ? 0.0 : rhs[i]); if (sense == NULL || sense[i] == 'E') { lp->rflag[m+i] = RF_NOT_RANGED; type = GLP_FX; } else if (sense[i] == 'L') { lp->rflag[m+i] = RF_NOT_RANGED; type = GLP_UP; } else if (sense[i] == 'G') { lp->rflag[m+i] = RF_NOT_RANGED; type = GLP_LO; } else if (sense[i] == 'R') { lp->rflag[m+i] = RF_RANGED_POS; type = GLP_FX; } else xassert(sense != sense); glp_set_row_bnds(lp->prob, m+i+1, type, temp, temp); beg = rmatbeg[i]; end = (i < rcnt-1 ? rmatbeg[i+1] : nzcnt); for (k = beg; k < end; k++) lp->iwork[k-beg] = rmatind[k]+1; glp_set_mat_row(lp->prob, m+i+1, end-beg, lp->iwork-1, rmatval+beg-1); for (k = beg; k < end; k++) lp->iwork[k-beg] = 0; } for (j = 0; j < ccnt; j++) { if (colname != NULL) glp_set_col_name(lp->prob, n+j+1, colname[j]); glp_set_col_bnds(lp->prob, n+j+1, GLP_LO, 0.0, 0.0); } done: return errcode; } int CPXbaropt(CPXENV *env, CPXLP *lp) { xassert(env == env); xassert(lp == lp); xprintf("CPXbaropt: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[]) { xassert(env == env); xassert(lp == lp); xassert(i == i); xassert(y == y); xprintf("CPXbinvrow: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[], const char lu[], const double bd[]) { int j, n, type, errcode; double lbnd, ubnd; errcode = checklp(env, lp); if (errcode) goto done; if (cnt < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (cnt > 0) { if (indices == NULL || lu == NULL || bd == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } } n = glp_get_num_cols(lp->prob); for (j = 0; j < cnt; j++) { if (!(0 <= indices[j] && indices[j] < n)) { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); goto done; } if (!(lu[j] == 'L' || lu[j] == 'U' || lu[j] == 'B')) { errcode = error(env, CPXERR_BAD_LUB, j); goto done; } } errcode = 0; invalidate(lp); for (j = 0; j < cnt; j++) { type = glp_get_col_type(lp->prob, indices[j]+1); lbnd = glp_get_col_lb(lp->prob, indices[j]+1); ubnd = glp_get_col_ub(lp->prob, indices[j]+1); if (type == GLP_FR || type == GLP_UP) lbnd = -CPX_INFBOUND; if (type == GLP_FR || type == GLP_LO) ubnd = +CPX_INFBOUND; if (lu[j] == 'L') lbnd = bd[j]; else if (lu[j] == 'U') ubnd = bd[j]; else if (lu[j] == 'B') lbnd = ubnd = bd[j]; else xassert(lu != lu); if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) type = GLP_FR; else if (ubnd >= +CPX_INFBOUND) type = GLP_LO; else if (lbnd <= -CPX_INFBOUND) type = GLP_UP; else if (lbnd != ubnd) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp->prob, indices[j]+1, type, lbnd, ubnd); } done: return errcode; } int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs, const int rowlist[], const int collist[], const double vallist[]) { int i, j, k, m, n, rcnt, ccnt, len, ptr, errcode; int *head, *next, *ind; double *val; errcode = checklp(env, lp); if (errcode) goto done; if (numcoefs < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (numcoefs == 0) { errcode = 0; goto done; } if (rowlist == NULL || collist == NULL || vallist == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } /* check triplets and determine the number of rows and columns to be changed */ m = glp_get_num_rows(lp->prob); n = glp_get_num_cols(lp->prob); enlargeiwork(lp, m); enlargeiwork(lp, n); rcnt = ccnt = 0; for (k = 0; k < numcoefs; k++) { i = rowlist[k]; if (!(0 <= i && i < m)) { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); goto done; } if (!(lp->iwork[i] & 0x01)) rcnt++, lp->iwork[i] |= 0x01; j = collist[k]; if (!(0 <= j && j < n)) { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); goto done; } if (!(lp->iwork[j] & 0x02)) ccnt++, lp->iwork[j] |= 0x02; } memset(lp->iwork, 0, m * sizeof(int)); memset(lp->iwork, 0, n * sizeof(int)); errcode = 0; invalidate(lp); if (rcnt <= ccnt) { /* change the matrix by rows */ /* build the linked list of triplets: head[i] is a pointer to first triplet for row i next[k] is a pointer to next triplet for the same row */ head = xcalloc(m, sizeof(int)); for (i = 0; i < m; i++) head[i] = -1; next = xcalloc(numcoefs, sizeof(int)); for (k = 0; k < numcoefs; k++) { i = rowlist[k]; next[k] = head[i]; head[i] = k; } /* check duplicate columns */ for (i = 0; i < m; i++) { for (k = head[i]; k >= 0; k = next[k]) { j = collist[k]; if (lp->iwork[j]) { xfree(head); xfree(next); errcode = error(env, CPXERR_DUP_ENTRY); goto done; } lp->iwork[j] = 1; } for (k = head[i]; k >= 0; k = next[k]) lp->iwork[collist[k]] = 0; } /* perform operation */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (i = 0; i < m; i++) { if (head[i] < 0) continue; len = glp_get_mat_row(lp->prob, i+1, ind, val); for (ptr = 1; ptr <= len; ptr++) { j = ind[ptr]-1; xassert(lp->iwork[j] == 0); lp->iwork[j] = ptr; } for (k = head[i]; k >= 0; k = next[k]) { j = collist[k]; if (lp->iwork[j] == 0) lp->iwork[j] = ++len; ptr = lp->iwork[j]; ind[ptr] = j+1, val[ptr] = vallist[k]; } glp_set_mat_row(lp->prob, i+1, len, ind, val); for (ptr = 1; ptr <= len; ptr++) lp->iwork[ind[ptr]-1] = 0; } } else { /* change the matrix by columns */ /* build the linked lists of triplets: head[j] is a pointer to first triplet for column j next[k] is a pointer to next triplet for the same column */ head = xcalloc(n, sizeof(int)); for (j = 0; j < n; j++) head[j] = -1; next = xcalloc(numcoefs, sizeof(int)); for (k = 0; k < numcoefs; k++) { j = collist[k]; next[k] = head[j]; head[j] = k; } /* check duplicate rows */ for (j = 0; j < n; j++) { for (k = head[j]; k >= 0; k = next[k]) { i = rowlist[k]; if (lp->iwork[i]) { xfree(head); xfree(next); errcode = error(env, CPXERR_DUP_ENTRY); goto done; } lp->iwork[i] = 1; } for (k = head[j]; k >= 0; k = next[k]) lp->iwork[rowlist[k]] = 0; } /* perform operation */ ind = xcalloc(1+m, sizeof(int)); val = xcalloc(1+m, sizeof(double)); for (j = 0; j < n; j++) { if (head[j] < 0) continue; len = glp_get_mat_col(lp->prob, j+1, ind, val); for (ptr = 1; ptr <= len; ptr++) { i = ind[ptr]-1; xassert(lp->iwork[i] == 0); lp->iwork[i] = ptr; } for (k = head[j]; k >= 0; k = next[k]) { i = rowlist[k]; if (lp->iwork[i] == 0) lp->iwork[i] = ++len; ptr = lp->iwork[i]; ind[ptr] = i+1, val[ptr] = vallist[k]; } glp_set_mat_col(lp->prob, j+1, len, ind, val); for (ptr = 1; ptr <= len; ptr++) lp->iwork[ind[ptr]-1] = 0; } } xfree(head); xfree(next); xfree(ind); xfree(val); done: return errcode; } void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin) { int errcode; errcode = checklp(env, lp); if (errcode) goto done; if (!(maxormin == CPX_MIN || maxormin == CPX_MAX)) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } errcode = 0; invalidate(lp); if (maxormin == CPX_MIN) glp_set_obj_dir(lp->prob, GLP_MIN); else glp_set_obj_dir(lp->prob, GLP_MAX); done: xassert(errcode == errcode); return; } int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[], const char sense[]) { int i, m, type, errcode; double rhs; errcode = checklp(env, lp); if (errcode) goto done; if (cnt < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (cnt > 0 && (indices == NULL || sense == NULL)) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } m = glp_get_num_rows(lp->prob); for (i = 0; i < cnt; i++) { if (!(0 <= indices[i] && indices[i] < m)) { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); goto done; } if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' || sense[i] == 'R')) { errcode = error(env, CPXERR_BAD_SENSE, i); goto done; } } errcode = 0; invalidate(lp); for (i = 0; i < cnt; i++) { type = glp_get_row_type(lp->prob, indices[i]+1); if (lp->rflag[indices[i]] == RF_NOT_RANGED) { if (type == GLP_LO || type == GLP_FX) rhs = glp_get_row_lb(lp->prob, indices[i]+1); else if (type == GLP_UP) rhs = glp_get_row_ub(lp->prob, indices[i]+1); else xassert(type != type); } else if (lp->rflag[indices[i]] == RF_RANGED_POS) { xassert(type == GLP_DB || type == GLP_FX); rhs = glp_get_row_lb(lp->prob, indices[i]+1); } else if (lp->rflag[indices[i]] == RF_RANGED_NEG) { xassert(type == GLP_DB); rhs = glp_get_row_ub(lp->prob, indices[i]+1); } else xassert(lp != lp); if (sense[i] == 'L') { lp->rflag[indices[i]] = RF_NOT_RANGED; type = GLP_UP; } else if (sense[i] == 'E') { lp->rflag[indices[i]] = RF_NOT_RANGED; type = GLP_FX; } else if (sense[i] == 'G') { lp->rflag[indices[i]] = RF_NOT_RANGED; type = GLP_LO; } else if (sense[i] == 'R') { lp->rflag[indices[i]] = RF_RANGED_POS; type = GLP_FX; } else xassert(sense != sense); glp_set_row_bnds(lp->prob, indices[i]+1, type, rhs, rhs); } done: return errcode; } int CPXcloseCPLEX(CPXENV **_env) { CPXENV *env; CPXLP *lp; int errcode; if (_env == NULL) { errcode = CPXERR_NULL_POINTER; goto done; } env = *_env; errcode = checkenv(env); if (errcode) goto done; while (env->list != NULL) { lp = env->list; errcode = CPXfreeprob(env, &lp); xassert(!errcode); } xfree(env->intparam); xfree(env->dblparam); xfree(env); *_env = NULL; errcode = 0; done: return errcode; } int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[], const int rstat[]) { int i, j, m, n, stat, errcode; errcode = checklp(env, lp); if (errcode) goto done; m = glp_get_num_rows(lp->prob); n = glp_get_num_cols(lp->prob); if (m > 0 && rstat == NULL || n > 0 && cstat == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } for (i = 0; i < m; i++) { if (!(rstat[i] == CPX_AT_LOWER || rstat[i] == CPX_BASIC || rstat[i] == CPX_AT_UPPER)) { errcode = error(env, CPXERR_BAD_STATUS, i); goto done; } } for (j = 0; j < n; j++) { if (!(cstat[j] == CPX_AT_LOWER || cstat[j] == CPX_BASIC || cstat[j] == CPX_AT_UPPER || cstat[j] == CPX_FREE_SUPER)) { errcode = error(env, CPXERR_BAD_STATUS, j); goto done; } } errcode = 0; invalidate(lp); for (i = 0; i < m; i++) { if (rstat[i] == CPX_AT_LOWER) stat = GLP_NL; else if (rstat[i] == CPX_BASIC) stat = GLP_BS; else if (rstat[i] == CPX_AT_UPPER) stat = GLP_NU; else xassert(rstat != rstat); glp_set_row_stat(lp->prob, i+1, stat); } for (j = 0; j < n; j++) { if (cstat[j] == CPX_AT_LOWER) stat = GLP_NL; else if (cstat[j] == CPX_BASIC) stat = GLP_BS; else if (cstat[j] == CPX_AT_UPPER) stat = GLP_NU; else if (cstat[j] == CPX_FREE_SUPER) stat = GLP_NF; else xassert(cstat != cstat); glp_set_col_stat(lp->prob, j+1, stat); } done: return errcode; } int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[], const int rstat[], const double dnorm[]) { int errcode; errcode = CPXcopybase(env, lp, cstat, rstat); xassert(dnorm == dnorm); return errcode; } int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows, int objsen, const double obj[], const double rhs[], const char sense[], const int matbeg[], const int matcnt[], const int matind[], const double matval[], const double lb[], const double ub[], const double rngval[]) { int errcode; errcode = CPXcopylpwnames(env, lp, numcols, numrows, objsen, obj, rhs, sense, matbeg, matcnt, matind, matval, lb, ub, rngval, NULL, NULL); return errcode; } int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows, int objsen, const double obj[], const double rhs[], const char sense[], const int matbeg[], const int matcnt[], const int matind[], const double matval[], const double lb[], const double ub[], const double rngval[], char *colname[], char *rowname[]) { int i, j, k, beg, end, type, errcode; double lbnd, ubnd; char name[255+1]; errcode = checklp(env, lp); if (errcode) goto done; if (numcols < 0 || numrows < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (!(objsen == CPX_MIN || objsen == CPX_MAX)) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (numcols > 0) { if (matbeg == NULL || matcnt == NULL || matind == NULL || matval == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } } for (i = 0; i < numrows; i++) { if (sense != NULL) { if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' || sense[i] == 'R')) { errcode = error(env, CPXERR_BAD_SENSE, i); goto done; } } if (rowname != NULL) { if (rowname[i] == NULL) { errcode = error(env, CPXERR_NULL_NAME, i); goto done; } } } enlargeiwork(lp, numrows); for (j = 0; j < numcols; j++) { beg = matbeg[j]; if (j > 0 && !(matbeg[j-1] <= beg)) { errcode = error(env, CPXERR_ARRAY_NOT_ASCENDING, j); goto done; } if (beg < 0) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } end = beg + matcnt[j]; if (!(beg <= end) || j < numcols-1 && !(end <= matbeg[j+1])) { errcode = error(env, CPXERR_COUNT_RANGE, j); goto done; } for (k = beg; k < end; k++) { if (!(0 <= matind[k] && matind[k] < numrows)) { errcode = error(env, CPXERR_ROW_INDEX_RANGE, k); goto done; } } errcode = 0; for (k = beg; k < end; k++) { if (lp->iwork[matind[k]]) { errcode = error(env, CPXERR_DUP_ENTRY); break; } lp->iwork[matind[k]] = 1; } for (k = beg; k < end; k++) lp->iwork[matind[k]] = 0; if (errcode) goto done; if (colname != NULL) { if (colname[j] != NULL) { errcode = error(env, CPXERR_NULL_NAME, j); goto done; } } } errcode = 0; invalidate(lp); if (glp_get_prob_name(lp->prob) == NULL) name[0] = '\0'; else strcpy(name, glp_get_prob_name(lp->prob)); glp_erase_prob(lp->prob); glp_set_prob_name(lp->prob, name); if (objsen == CPX_MIN) glp_set_obj_dir(lp->prob, GLP_MIN); else if (objsen == CPX_MAX) glp_set_obj_dir(lp->prob, GLP_MAX); else xassert(objsen != objsen); if (numrows > 0) glp_add_rows(lp->prob, numrows); enlargerflag(lp); for (i = 0; i < numrows; i++) { if (rowname != NULL) glp_set_row_name(lp->prob, i+1, rowname[i]); lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]); if (sense == NULL || sense[i] == 'E') { lp->rflag[i] = RF_NOT_RANGED; type = GLP_FX; } else if (sense[i] == 'L') { lp->rflag[i] = RF_NOT_RANGED; type = GLP_UP; } else if (sense[i] == 'G') { lp->rflag[i] = RF_NOT_RANGED; type = GLP_LO; } else if (sense[i] == 'R') { if (rngval == NULL || rngval[i] == 0.0) { lp->rflag[i] = RF_RANGED_POS; type = GLP_FX; } else if (rngval[i] > 0.0) { lp->rflag[i] = RF_RANGED_POS; type = GLP_DB; ubnd += rngval[i]; } else /* rngval[i] < 0.0 */ { lp->rflag[i] = RF_RANGED_NEG; type = GLP_DB; lbnd += rngval[i]; } } else xassert(sense != sense); glp_set_row_bnds(lp->prob, i+1, type, lbnd, ubnd); } if (numcols > 0) glp_add_cols(lp->prob, numcols); for (j = 0; j < numcols; j++) { if (colname != NULL) glp_set_col_name(lp->prob, j+1, colname[j]); lbnd = (lb == NULL ? 0.0 : lb[j]); ubnd = (ub == NULL ? +CPX_INFBOUND : ub[j]); if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) type = GLP_FR; else if (ubnd >= +CPX_INFBOUND) type = GLP_LO; else if (lbnd <= -CPX_INFBOUND) type = GLP_UP; else if (lbnd != ubnd) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp->prob, j+1, type, lbnd, ubnd); if (obj != NULL) glp_set_obj_coef(lp->prob, j+1, obj[j]); beg = matbeg[j]; end = beg + matcnt[j]; for (k = beg; k < end; k++) lp->iwork[k-beg] = matind[k]+1; glp_set_mat_col(lp->prob, j+1, end-beg, lp->iwork-1, matval+beg-1); for (k = beg; k < end; k++) lp->iwork[k-beg] = 0; } done: return errcode; } CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname) { CPXLP *lp = NULL; int errcode; errcode = checkenv(env); if (errcode) goto done; lp = xmalloc(sizeof(struct CPXLP)); lp->env = env; lp->prob = glp_create_prob(); glp_set_prob_name(lp->prob, probname); lp->rflen = 100; lp->rflag = xcalloc(lp->rflen, sizeof(char)); lp->iwlen = 100; lp->iwork = xcalloc(lp->iwlen, sizeof(int)); memset(lp->iwork, 0, lp->iwlen * sizeof(int)); lp->link = env->list; env->list = lp; invalidate(lp); done: if (status != NULL) *status = errcode; return lp; } int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end) { int j, n, errcode; errcode = checklp(env, lp); if (errcode) goto done; n = glp_get_num_cols(lp->prob); if (!(0 <= begin && begin <= end && end < n)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } errcode = 0; invalidate(lp); enlargeiwork(lp, end-begin+1); for (j = begin; j <= end; j++) lp->iwork[j-begin] = j+1; glp_del_cols(lp->prob, end-begin+1, lp->iwork-1); for (j = begin; j <= end; j++) lp->iwork[j-begin] = 0; done: return errcode; } int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end) { int i, m, errcode; errcode = checklp(env, lp); if (errcode) goto done; m = glp_get_num_rows(lp->prob); if (!(0 <= begin && begin <= end && end < m)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } errcode = 0; invalidate(lp); enlargeiwork(lp, end-begin+1); for (i = begin; i <= end; i++) lp->iwork[i-begin] = i+1; glp_del_rows(lp->prob, end-begin+1, lp->iwork-1); for (i = begin; i <= end; i++) lp->iwork[i-begin] = 0; for (i = end+1; i < m; i++) lp->rflag[i-(end-begin+1)] = lp->rflag[i]; done: return errcode; } int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[]) { xassert(env == env); xassert(lp == lp); xassert(delstat == delstat); xprintf("CPXdelsetcols: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[]) { int i, m, cnt, ind, errcode; errcode = checklp(env, lp); if (errcode) goto done; m = glp_get_num_rows(lp->prob); if (m > 0 && delstat == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } errcode = 0; invalidate(lp); enlargeiwork(lp, m); cnt = ind = 0; for (i = 0; i < m; i++) { if (delstat[i] == 1) { delstat[i] = -1; lp->iwork[cnt++] = i+1; } else { delstat[i] = ind; lp->rflag[ind++] = lp->rflag[i]; } } if (cnt > 0) glp_del_rows(lp->prob, cnt, lp->iwork-1); for (i = 0; i < cnt; i++) lp->iwork[i] = 0; done: return errcode; } int CPXdualopt(CPXENV *env, CPXLP *lp); int CPXfreeprob(CPXENV *env, CPXLP **_lp) { CPXLP *lp; int errcode; errcode = checkenv(env); if (errcode) goto done; if (_lp == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } lp = *_lp; errcode = checklp(env, lp); if (errcode) goto done; errcode = 0; env = lp->env; if (env->list == lp) env->list = lp->link; else { CPXLP *pp; for (pp = env->list; pp != NULL; pp = pp->link) if (pp->link == lp) break; xassert(pp != NULL); pp->link = lp->link; } glp_delete_prob(lp->prob); xfree(lp->rflag); xfree(lp->iwork); xfree(lp); *_lp = NULL; done: return errcode; } int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[]) { int i, j, m, n, stat, errcode; errcode = checklp(env, lp); if (errcode) goto done; if (!lp->stat) { errcode = error(env, CPXERR_NO_SOLN); goto done; } if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) ; else { errcode = error(env, CPXERR_NO_BASIC_SOLN); goto done; } errcode = 0; if (rstat != NULL) { m = glp_get_num_rows(lp->prob); for (i = 0; i < m; i++) { stat = glp_get_row_stat(lp->prob, i+1); if (stat == GLP_BS) rstat[i] = CPX_BASIC; else if (lp->rflag[i] == RF_NOT_RANGED || stat != GLP_NU) rstat[i] = CPX_AT_LOWER; else rstat[i] = CPX_AT_UPPER; } } if (cstat != NULL) { n = glp_get_num_cols(lp->prob); for (j = 0; j < n; j++) { stat = glp_get_col_stat(lp->prob, j+1); if (stat == GLP_BS) cstat[j] = CPX_BASIC; else if (stat == GLP_NU) cstat[j] = CPX_AT_UPPER; else if (stat == GLP_NF) cstat[j] = CPX_FREE_SUPER; else cstat[j] = CPX_AT_LOWER; } } done: return errcode; } int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[], double dnorm[]) { int i, m, errcode; errcode = CPXgetbase(env, lp, cstat, rstat); if (errcode) goto done; if (dnorm != NULL) { m = glp_get_num_rows(lp->prob); for (i = 0; i < m; i++) dnorm[i] = 1.0; } done: return errcode; } int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[]) { xassert(env == env); xassert(lp == lp); xassert(head == head); xassert(x == x); xprintf("CPXgetbhead: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXgetdblparam(CPXENV *env, int whichparam, double *value) { int k, errcode; errcode = checkenv(env); if (errcode) goto done; k = finddblparam(whichparam); if (k < 0) { errcode = error(env, CPXERR_BAD_PARAM_NUM); goto done; } errcode = 0; if (value != NULL) *value = env->dblparam[k]; done: return errcode; } int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end) { int j, n, errcode; errcode = checklp(env, lp); if (errcode) goto done; n = glp_get_num_cols(lp->prob); if (!(0 <= begin && begin <= end && end < n)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } if (!lp->stat) { errcode = error(env, CPXERR_NO_SOLN); goto done; } errcode = 0; if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) { if (dj != NULL) { for (j = begin; j <= end; j++) dj[j-begin] = glp_get_col_dual(lp->prob, j+1); } } else xassert(lp != lp); done: return errcode; } char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer) { const char *string; xassert(env == env); string = finderrstring(errcode); if (string == NULL) buffer = NULL; else sprintf(buffer, "CPLEX Error %5d: %s.\n", errcode, string); return buffer; } int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv) { xassert(env == env); xassert(lp == lp); xassert(idiv == idiv); xassert(jdiv == jdiv); xprintf("CPXgetijdiv: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXgetintparam(CPXENV *env, int whichparam, int *value) { int k, errcode; errcode = checkenv(env); if (errcode) goto done; k = findintparam(whichparam); if (k < 0) { errcode = error(env, CPXERR_BAD_PARAM_NUM); goto done; } errcode = 0; if (value != NULL) *value = env->intparam[k]; done: return errcode; } int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end) { xassert(env == env); xassert(lp == lp); xassert(lb == lb); xassert(begin == begin); xassert(end == end); xprintf("CPXgetlb: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXgetmethod(CPXENV *env, CPXLP *lp) { int method; if (checklp(env, lp)) method = CPX_ALG_NONE; else method = lp->meth; return method; } int CPXgetnumcols(CPXENV *env, CPXLP *lp) { int numcols; if (checklp(env, lp)) numcols = 0; else numcols = glp_get_num_cols(lp->prob); return numcols; } int CPXgetnumnz(CPXENV *env, CPXLP *lp) { int numnz; if (checklp(env, lp)) numnz = 0; else numnz = glp_get_num_nz(lp->prob); return numnz; } int CPXgetnumrows(CPXENV *env, CPXLP *lp) { int numrows; if (checklp(env, lp)) numrows = 0; else numrows = glp_get_num_rows(lp->prob); return numrows; } int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval) { int errcode; errcode = checklp(env, lp); if (errcode) goto done; if (!lp->stat) { errcode = error(env, CPXERR_NO_SOLN); goto done; } errcode = 0; if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) { if (objval != NULL) *objval = glp_get_obj_val(lp->prob); } else xassert(lp != lp); done: return errcode; } int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end) { int i, m, errcode; errcode = checklp(env, lp); if (errcode) goto done; m = glp_get_num_rows(lp->prob); if (!(0 <= begin && begin <= end && end < m)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } if (!lp->stat) { errcode = error(env, CPXERR_NO_SOLN); goto done; } errcode = 0; if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) { if (pi != NULL) { for (i = begin; i <= end; i++) pi[i-begin] = glp_get_row_dual(lp->prob, i+1); } } else xassert(lp != lp); done: return errcode; } int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin, int end) { xassert(env == env); xassert(lp == lp); xassert(sense == sense); xassert(begin == begin); xassert(end == end); xprintf("CPXgetsense: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin, int end) { int i, m, type, errcode; double temp; errcode = checklp(env, lp); if (errcode) goto done; m = glp_get_num_rows(lp->prob); if (!(0 <= begin && begin <= end && end < m)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } if (!lp->stat) { errcode = error(env, CPXERR_NO_SOLN); goto done; } errcode = 0; if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) { if (slack != NULL) { for (i = begin; i <= end; i++) { type = glp_get_row_type(lp->prob, i+1); temp = glp_get_row_prim(lp->prob, i+1); if (lp->rflag[i] == RF_NOT_RANGED) { if (type == GLP_LO || type == GLP_FX) slack[i-begin] = glp_get_row_lb(lp->prob, i+1) - temp; else if (type == GLP_UP) slack[i-begin] = glp_get_row_ub(lp->prob, i+1) - temp; else xassert(type != type); } else if (lp->rflag[i] == RF_RANGED_POS) { xassert(type == GLP_DB || type == GLP_FX); slack[i-begin] = temp - glp_get_row_lb(lp->prob, i+1); } else if (lp->rflag[i] == RF_RANGED_NEG) { xassert(type == GLP_DB); slack[i-begin] = temp - glp_get_row_ub(lp->prob, i+1); } else xassert(lp != lp); } } } else xassert(lp != lp); done: return errcode; } int CPXgetstat(CPXENV *env, CPXLP *lp) { int stat; if (checklp(env, lp)) stat = 0; else stat = lp->stat; return stat; } int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end) { xassert(env == env); xassert(lp == lp); xassert(ub == ub); xassert(begin == begin); xassert(end == end); xprintf("CPXgetub: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[], const int rmatind[], const double rmatval[], double weight[], int dpriind) { xassert(env == env); xassert(lp == lp); xassert(rcnt == rcnt); xassert(rmatbeg == rmatbeg); xassert(rmatind == rmatind); xassert(rmatval == rmatval); xassert(weight == weight); xassert(dpriind == dpriind); xprintf("CPXgetweight: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end) { int j, n, errcode; errcode = checklp(env, lp); if (errcode) goto done; n = glp_get_num_cols(lp->prob); if (!(0 <= begin && begin <= end && end < n)) { errcode = error(env, CPXERR_INDEX_RANGE); goto done; } if (!lp->stat) { errcode = error(env, CPXERR_NO_SOLN); goto done; } errcode = 0; if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) { if (x != NULL) { for (j = begin; j <= end; j++) x[j-begin] = glp_get_col_prim(lp->prob, j+1); } } else xassert(lp != lp); done: return errcode; } int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue, double *minvalue, double *maxvalue) { int k, errcode; errcode = checkenv(env); if (errcode) goto done; k = finddblparam(whichparam); if (k < 0) { errcode = error(env, CPXERR_BAD_PARAM_NUM); goto done; } errcode = 0; if (defvalue != NULL) *defvalue = dblparam[k].defv; if (minvalue != NULL) *minvalue = dblparam[k].minv; if (maxvalue != NULL) *maxvalue = dblparam[k].maxv; done: return errcode; } int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue, int *minvalue, int *maxvalue) { int k, errcode; errcode = checkenv(env); if (errcode) goto done; k = findintparam(whichparam); if (k < 0) { errcode = error(env, CPXERR_BAD_PARAM_NUM); goto done; } errcode = 0; if (defvalue != NULL) *defvalue = intparam[k].defv; if (minvalue != NULL) *minvalue = intparam[k].minv; if (maxvalue != NULL) *maxvalue = intparam[k].maxv; done: return errcode; } int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[], int goodlen, double downratio[], double upratio[]) { int k; xassert(env == env); xassert(lp == lp); xassert(goodlist == goodlist); xassert(goodlen >= 0); xassert(downratio != NULL); xassert(upratio != NULL); /* not implemented yet */ for (k = 0; k < goodlen; k++) downratio[k] = upratio[k] = 0.0; return 0; } int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[], const double lb[], const double ub[], const char ctype[], char *colname[]) { int j, n, kind, type, errcode; double lbnd, ubnd; errcode = checklp(env, lp); if (errcode) goto done; if (ccnt < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } for (j = 0; j < ccnt; j++) { if (ctype != NULL) { if (!(ctype[j] == 'C' || ctype[j] == 'B' || ctype[j] == 'I')) { errcode = error(env, CPXERR_BAD_CTYPE, j); goto done; } } if (colname != NULL) { if (colname[j] == NULL) { errcode = error(env, CPXERR_NULL_NAME, j); goto done; } } } errcode = 0; invalidate(lp); n = glp_get_num_cols(lp->prob); if (ccnt > 0) glp_add_cols(lp->prob, ccnt); for (j = 0; j < ccnt; j++) { if (colname != NULL) glp_set_col_name(lp->prob, n+j+1, colname[j]); if (obj != NULL) glp_set_obj_coef(lp->prob, n+j+1, obj[j]); lbnd = (lb == NULL ? 0.0 : lb[j]); ubnd = (ub == NULL ? 0.0 : ub[j]); if (lbnd <= -CPX_INFBOUND && ubnd >= +CPX_INFBOUND) type = GLP_FR; else if (ubnd >= +CPX_INFBOUND) type = GLP_LO; else if (lbnd <= -CPX_INFBOUND) type = GLP_UP; else if (lbnd != ubnd) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp->prob, n+j+1, type, lbnd, ubnd); if (ctype != NULL) { if (ctype[j] == 'C') kind = GLP_CV; else if (ctype[j] == 'B') kind = GLP_BV; else if (ctype[j] == 'I') kind = GLP_IV; else xassert(ctype != ctype); glp_set_col_kind(lp->prob, n+j+1, kind); } } done: return errcode; } int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[], const char sense[], const double rngval[], char *rowname[]) { int i, m, type, errcode; double lbnd, ubnd; errcode = checklp(env, lp); if (errcode) goto done; if (rcnt < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } for (i = 0; i < rcnt; i++) { if (sense != NULL) { if (!(sense[i] == 'L' || sense[i] == 'E' || sense[i] == 'G' || sense[i] == 'R')) { errcode = error(env, CPXERR_BAD_SENSE, i); goto done; } } if (rowname != NULL) { if (rowname[i] == NULL) { errcode = error(env, CPXERR_NULL_NAME, i); goto done; } } } errcode = 0; invalidate(lp); m = glp_get_num_rows(lp->prob); if (rcnt > 0) glp_add_rows(lp->prob, rcnt); enlargerflag(lp); for (i = 0; i < rcnt; i++) { if (rowname != NULL) glp_set_row_name(lp->prob, m+i+1, rowname[i]); lbnd = ubnd = (rhs == NULL ? 0.0 : rhs[i]); if (sense == NULL || sense[i] == 'E') { lp->rflag[m+i] = RF_NOT_RANGED; type = GLP_FX; } else if (sense[i] == 'L') { lp->rflag[m+i] = RF_NOT_RANGED; type = GLP_UP; } else if (sense[i] == 'G') { lp->rflag[m+i] = RF_NOT_RANGED; type = GLP_LO; } else if (sense[i] == 'R') { if (rngval == NULL || rngval[i] == 0.0) { lp->rflag[m+i] = RF_RANGED_POS; type = GLP_FX; } else if (rngval[i] > 0.0) { lp->rflag[m+i] = RF_RANGED_POS; type = GLP_DB; ubnd += rngval[i]; } else /* rngval[i] < 0.0 */ { lp->rflag[m+i] = RF_RANGED_NEG; type = GLP_DB; lbnd += rngval[i]; } } else xassert(sense != sense); glp_set_row_bnds(lp->prob, m+i+1, type, lbnd, ubnd); } done: return errcode; } CPXENV *CPXopenCPLEX(int *status) { CPXENV *env; int k, card; env = xmalloc(sizeof(CPXENV)); env->list = NULL; card = sizeof(intparam) / sizeof(struct intparam); env->intparam = xcalloc(card, sizeof(int)); for (k = 0; k < card; k++) env->intparam[k] = intparam[k].defv; card = sizeof(dblparam) / sizeof(struct dblparam); env->dblparam = xcalloc(card, sizeof(double)); for (k = 0; k < card; k++) env->dblparam[k] = dblparam[k].defv; if (status != NULL) *status = 0; return env; } int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen) { int i, m, errcode; errcode = checklp(env, lp); if (errcode) goto done; if (rlen < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (rlen > 0 && rlist == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } m = glp_get_num_rows(lp->prob); for (i = 0; i < rlen; i++) { if (!(0 <= rlist[i] && rlist[i] < m)) { errcode = error(env, CPXERR_ROW_INDEX_RANGE, i); goto done; } } errcode = 0; for (i = 0; i < rlen; i++) { if (glp_get_row_type(lp->prob, rlist[i]+1) != GLP_FX) { if (glp_get_row_stat(lp->prob, rlist[i]+1) != GLP_BS) { /* not implemented yet */ break; } } } done: return errcode; } int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen) { int j, n, errcode; errcode = checklp(env, lp); if (errcode) goto done; if (clen < 0) { errcode = error(env, CPXERR_BAD_ARGUMENT); goto done; } if (clen > 0 && clist == NULL) { errcode = error(env, CPXERR_NULL_POINTER); goto done; } n = glp_get_num_cols(lp->prob); for (j = 0; j < clen; j++) { if (!(0 <= clist[j] && clist[j] < n)) { errcode = error(env, CPXERR_COL_INDEX_RANGE, j); goto done; } if (glp_get_col_type(lp->prob, clist[j]+1) != GLP_FX) { errcode = error(env, CPXERR_NOT_FIXED); goto done; } } errcode = 0; for (j = 0; j < clen; j++) { if (glp_get_col_stat(lp->prob, clist[j]+1) == GLP_BS) { /* not implemented yet */ break; } } done: return errcode; } int CPXprimopt(CPXENV *env, CPXLP *lp); int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename) { xassert(env == env); xassert(lp == lp); xassert(filename == filename); xprintf("CPXsavwrite: not implemented yet\n"); exit(EXIT_FAILURE); return -1; } int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue) { int k, errcode; errcode = checkenv(env); if (errcode) goto done; k = finddblparam(whichparam); if (k < 0) { errcode = error(env, CPXERR_BAD_PARAM_NUM); goto done; } if (newvalue < dblparam[k].minv) { errcode = error(env, CPXERR_PARAM_TOO_SMALL); goto done; } if (newvalue > dblparam[k].maxv) { errcode = error(env, CPXERR_PARAM_TOO_BIG); goto done; } errcode = 0; env->dblparam[k] = newvalue; done: return errcode; } int CPXsetintparam(CPXENV *env, int whichparam, int newvalue) { int k, errcode; errcode = checkenv(env); if (errcode) goto done; k = findintparam(whichparam); if (k < 0) { errcode = error(env, CPXERR_BAD_PARAM_NUM); goto done; } if (newvalue < intparam[k].minv) { errcode = error(env, CPXERR_PARAM_TOO_SMALL); goto done; } if (newvalue > intparam[k].maxv) { errcode = error(env, CPXERR_PARAM_TOO_BIG); goto done; } errcode = 0; env->intparam[k] = newvalue; done: return errcode; } int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype, int *pfeasind, int *dfeasind) { int type, pfeas, dfeas, errcode; errcode = checklp(env, lp); if (errcode) goto done; errcode = 0; if (!lp->stat) type = CPX_NO_SOLN, pfeas = dfeas = 0; else if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) { type = CPX_BASIC_SOLN; pfeas = (glp_get_prim_stat(lp->prob) == GLP_FEAS); dfeas = (glp_get_dual_stat(lp->prob) == GLP_FEAS); } else xassert(lp != lp); if (solnmethod != NULL) *solnmethod = lp->meth; if (solntype != NULL) *solntype = type; if (pfeasind != NULL) *pfeasind = pfeas; if (dfeasind != NULL) *dfeasind = dfeas; done: return errcode; } int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval, double x[], double pi[], double slack[], double dj[]) { int m, n, errcode; errcode = checklp(env, lp); if (errcode) goto done; if (!lp->stat) { errcode = error(env, CPXERR_NO_SOLN); goto done; } errcode = 0; m = glp_get_num_rows(lp->prob); n = glp_get_num_cols(lp->prob); if (lp->meth == CPX_ALG_PRIMAL || lp->meth == CPX_ALG_DUAL) { if (lpstat != NULL) *lpstat = CPXgetstat(env, lp); if (objval != NULL) xassert(CPXgetobjval(env, lp, objval) == 0); if (x != NULL) xassert(CPXgetx(env, lp, x, 0, n-1) == 0); if (pi != NULL) xassert(CPXgetpi(env, lp, pi, 0, m-1) == 0); if (slack != NULL) xassert(CPXgetslack(env, lp, slack, 0, m-1) == 0); if (dj != NULL) xassert(CPXgetdj(env, lp, dj, 0, n-1) == 0); } else xassert(lp != lp); done: return errcode; } int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[], int goodlen, double downpen[], double uppen[], int itlim) { int k; xassert(env == env); xassert(lp == lp); xassert(goodlist == goodlist); xassert(goodlen >= 0); xassert(downpen != NULL); xassert(uppen != NULL); xassert(itlim == itlim); /* not implemented yet */ for (k = 0; k < goodlen; k++) downpen[k] = uppen[k] = 0.0; return 0; } static int xstrcasecmp(const char *s1, const char *s2) { int c1, c2; for (;;) { c1 = toupper((unsigned char)*s1++); c2 = toupper((unsigned char)*s2++); if (c1 == '\0' || c1 != c2) break; } return c1 - c2; } static void getfiletype(const char *filename, char type[3+1]) { /* determine filetype from filename */ int beg, end; beg = end = strlen(filename); while (beg > 0 && filename[beg-1] != '.' && end - beg < 3) beg--; if (beg > 0 && filename[beg-1] == '.' && xstrcasecmp(&filename[beg], "gz") == 0) { end = --beg; while (beg > 0 && filename[beg-1] != '.' && end - beg < 3) beg--; } if (beg > 0 && filename[beg-1] == '.') { memcpy(type, &filename[beg], end - beg); type[end - beg] = '\0'; } else type[0] = '\0'; return; } int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename, const char *filetype) { glp_prob *copy; int errcode; char type[3+1]; errcode = checklp(env, lp); if (errcode) goto done; if (filename == NULL) { errcode = error(env, CPXERR_NO_FILENAME); goto done; } if (filetype == NULL) getfiletype(filename, type), filetype = type; if (xstrcasecmp(filetype, "MPS") == 0) { glp_term_out(GLP_OFF); errcode = glp_write_mps(lp->prob, GLP_MPS_FILE, NULL, filename) ; glp_term_out(GLP_ON); } else if (xstrcasecmp(filetype, "LP") == 0) { glp_term_out(GLP_OFF); errcode = glp_write_lp(lp->prob, NULL, filename); glp_term_out(GLP_ON); } else if (xstrcasecmp(filetype, "RMP") == 0 || xstrcasecmp(filetype, "REW") == 0) { copy = glp_create_prob(); glp_copy_prob(copy, lp->prob, GLP_OFF); glp_term_out(GLP_OFF); errcode = glp_write_mps(copy, GLP_MPS_DECK, NULL, filename); glp_term_out(GLP_ON); glp_delete_prob(copy); } else if (xstrcasecmp(filetype, "RLP") == 0) { copy = glp_create_prob(); glp_copy_prob(copy, lp->prob, GLP_OFF); glp_term_out(GLP_OFF); errcode = glp_write_lp(copy, NULL, filename); glp_term_out(GLP_ON); glp_delete_prob(copy); } else { errcode = error(env, CPXERR_BAD_FILETYPE); goto done; } if (errcode) errcode = error(env, CPXERR_FAIL_OPEN_WRITE, filename); done: return errcode; } /**********************************************************************/ static int solvelp(CPXENV *env, CPXLP *lp, int meth) { glp_smcp parm; int errcode; errcode = checklp(env, lp); if (errcode) goto done; errcode = 0; invalidate(lp); glp_init_smcp(&parm); switch (meth) { case CPX_ALG_PRIMAL: parm.meth = GLP_PRIMAL; break; case CPX_ALG_DUAL: parm.meth = GLP_DUAL; break; default: xassert(meth != meth); } switch (getintparam(env, CPX_PARAM_SIMDISPLAY)) { case 0: parm.msg_lev = GLP_MSG_OFF; break; case 1: parm.msg_lev = GLP_MSG_ALL; break; case 2: parm.msg_lev = GLP_MSG_ALL; parm.out_frq = 1; break; default: xassert(env != env); } xassert(getdblparam == getdblparam); switch (getintparam(env, CPX_PARAM_ADVIND)) { case 0: glp_term_out(GLP_OFF); glp_adv_basis(lp->prob, 0); glp_term_out(GLP_ON); break; case 1: case 2: break; default: xassert(env != env); } if (!glp_bf_exists(lp->prob)) { if (glp_factorize(lp->prob) != 0) { glp_term_out(GLP_OFF); glp_adv_basis(lp->prob, 0); glp_term_out(GLP_ON); if (glp_factorize(lp->prob) != 0) glp_std_basis(lp->prob); } } xassert(glp_simplex(lp->prob, &parm) == 0); switch (glp_get_status(lp->prob)) { case GLP_OPT: lp->stat = CPX_STAT_OPTIMAL; lp->meth = meth; break; case GLP_NOFEAS: lp->stat = CPX_STAT_INFEASIBLE; lp->meth = meth; break; case GLP_UNBND: lp->stat = CPX_STAT_UNBOUNDED; lp->meth = meth; break; default: xassert(lp != lp); } done: return errcode; } int CPXprimopt(CPXENV *env, CPXLP *lp) { int errcode; errcode = solvelp(env, lp, CPX_ALG_PRIMAL); return errcode; } int CPXdualopt(CPXENV *env, CPXLP *lp) { int errcode; errcode = solvelp(env, lp, CPX_ALG_DUAL); return errcode; } int CPXlpopt(CPXENV *env, CPXLP *lp) { int errcode; errcode = solvelp(env, lp, CPX_ALG_PRIMAL); return errcode; } /* eof */ glpk-4.52.1/examples/cplex/cplex.h0000644000062000006210000002373212175147600016145 0ustar maomkpasswd/* cplex.h (CPLEX-like interface to GLPK API) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef _CPLEX_H #define _CPLEX_H #ifdef __cplusplus extern "C" { #endif typedef struct CPXENV CPXENV, *CPXENVptr; typedef struct CPXLP CPXLP, *CPXLPptr; #define CPX_VERSION 900 #define CPX_OFF 0 #define CPX_ON 1 #define CPX_INFBOUND 1e20 /* error codes: */ #define CPXERR_NO_MEMORY 1001 #define CPXERR_NO_ENVIRONMENT 1002 #define CPXERR_BAD_ARGUMENT 1003 #define CPXERR_NULL_POINTER 1004 #define CPXERR_NO_PROBLEM 1009 #define CPXERR_BAD_PARAM_NUM 1013 #define CPXERR_PARAM_TOO_SMALL 1014 #define CPXERR_PARAM_TOO_BIG 1015 #define CPXERR_INDEX_RANGE 1200 #define CPXERR_COL_INDEX_RANGE 1201 #define CPXERR_ROW_INDEX_RANGE 1203 #define CPXERR_NEGATIVE_SURPLUS 1207 #define CPXERR_BAD_SENSE 1215 #define CPXERR_NO_SOLN 1217 #define CPXERR_NOT_FIXED 1221 #define CPXERR_DUP_ENTRY 1222 #define CPXERR_NULL_NAME 1224 #define CPXERR_ARRAY_NOT_ASCENDING 1226 #define CPXERR_COUNT_RANGE 1227 #define CPXERR_BAD_LUB 1229 #define CPXERR_BAD_STATUS 1253 #define CPXERR_NO_BASIC_SOLN 1261 #define CPXERR_NO_FILENAME 1421 #define CPXERR_FAIL_OPEN_WRITE 1422 #define CPXERR_BAD_FILETYPE 1424 #define CPXERR_BAD_CTYPE 3021 /* control parameters: */ #define CPX_PARAM_ADVIND 1001 #define CPX_PARAM_AGGIND 1003 #define CPX_PARAM_DPRIIND 1009 #define CPX_PARAM_EPOPT 1014 #define CPX_PARAM_EPPER 1015 #define CPX_PARAM_EPRHS 1016 #define CPX_PARAM_FASTMIP 1017 /* ??? */ #define CPX_PARAM_SIMDISPLAY 1019 #define CPX_PARAM_ITLIM 1020 #define CPX_PARAM_OBJLLIM 1025 #define CPX_PARAM_OBJULIM 1026 #define CPX_PARAM_PERIND 1027 #define CPX_PARAM_PPRIIND 1029 #define CPX_PARAM_PREIND 1030 #define CPX_PARAM_REINV 1031 #define CPX_PARAM_SCRIND 1035 #define CPX_PARAM_DATACHECK 1056 /* CPX_PARAM_DPRIIND: */ #define CPX_DPRIIND_AUTO 0 #define CPX_DPRIIND_FULL 1 #define CPX_DPRIIND_STEEP 2 #define CPX_DPRIIND_FULL_STEEP 3 #define CPX_DPRIIND_STEEPQSTART 4 #define CPX_DPRIIND_DEVEX 5 /* CPX_PARAM_PPRIIND: */ #define CPX_PPRIIND_PARTIAL (-1) #define CPX_PPRIIND_AUTO 0 #define CPX_PPRIIND_DEVEX 1 #define CPX_PPRIIND_STEEP 2 #define CPX_PPRIIND_STEEPQSTART 3 #define CPX_PPRIIND_FULL 4 /* CPXgetprobtype: */ #define CPXPROB_LP 0 #define CPXPROB_MIP 1 #define CPXPROB_RELAXED 2 #define CPXPROB_FIXED 3 #define CPXPROB_QP 5 #define CPXPROB_ZEROEDQP 6 /* CPXgetobjsen: */ #define CPX_MIN 1 #define CPX_MAX (-1) /* CPXgetbase: */ #define CPX_AT_LOWER 0 #define CPX_BASIC 1 #define CPX_AT_UPPER 2 #define CPX_FREE_SUPER 3 /* CPXgetstat: */ #define CPX_STAT_OPTIMAL 1 #define CPX_STAT_UNBOUNDED 2 #define CPX_STAT_INFEASIBLE 3 #define CPX_STAT_INForUNBD 4 #define CPX_STAT_OPTIMAL_INFEAS 5 #define CPX_STAT_ABORT_IT_LIM 10 #define CPX_STAT_ABORT_OBJ_LIM 12 /* CPXgetmethod: */ #define CPX_ALG_NONE 0 #define CPX_ALG_PRIMAL 1 #define CPX_ALG_DUAL 2 #define CPX_ALG_BARRIER 4 /* CPXsolninfo: */ #define CPX_NO_SOLN 0 #define CPX_BASIC_SOLN 1 #define CPX_NONBASIC_SOLN 2 #define CPX_PRIMAL_SOLN 3 int CPXaddcols(CPXENV *env, CPXLP *lp, int ccnt, int nzcnt, const double obj[], const int cmatbeg[], const int cmatind[], const double cmatval[], const double lb[], const double ub[], char *colname[]); int CPXaddrows(CPXENV *env, CPXLP *lp, int ccnt, int rcnt, int nzcnt, const double rhs[], const char sense[], const int rmatbeg[], const int rmatind[], const double rmatval[], char *colname[], char *rowname[]); int CPXbaropt(CPXENV *env, CPXLP *lp); int CPXbinvrow(CPXENV *env, CPXLP *lp, int i, double y[]); int CPXchgbds(CPXENV *env, CPXLP *lp, int cnt, const int indices[], const char lu[], const double bd[]); int CPXchgcoeflist(CPXENV *env, CPXLP *lp, int numcoefs, const int rowlist[], const int collist[], const double vallist[]); void CPXchgobjsen(CPXENV *env, CPXLP *lp, int maxormin); int CPXchgsense(CPXENV *env, CPXLP *lp, int cnt, const int indices[], const char sense[]); int CPXcloseCPLEX(CPXENV **env); int CPXcopybase(CPXENV *env, CPXLP *lp, const int cstat[], const int rstat[]); int CPXcopybasednorms(CPXENV *env, CPXLP *lp, const int cstat[], const int rstat[], const double dnorm[]); int CPXcopylp(CPXENV *env, CPXLP *lp, int numcols, int numrows, int objsen, const double obj[], const double rhs[], const char sense[], const int matbeg[], const int matcnt[], const int matind[], const double matval[], const double lb[], const double ub[], const double rngval[]); int CPXcopylpwnames(CPXENV *env, CPXLP *lp, int numcols, int numrows, int objsen, const double obj[], const double rhs[], const char sense[], const int matbeg[], const int matcnt[], const int matind[], const double matval[], const double lb[], const double ub[], const double rngval[], char *colname[], char *rowname[]); CPXLP *CPXcreateprob(CPXENV *env, int *status, const char *probname); int CPXdelcols(CPXENV *env, CPXLP *lp, int begin, int end); int CPXdelrows(CPXENV *env, CPXLP *lp, int begin, int end); int CPXdelsetcols(CPXENV *env, CPXLP *lp, int delstat[]); int CPXdelsetrows(CPXENV *env, CPXLP *lp, int delstat[]); int CPXdualopt(CPXENV *env, CPXLP *lp); int CPXfreeprob(CPXENV *env, CPXLP **lp); int CPXgetbase(CPXENV *env, CPXLP *lp, int cstat[], int rstat[]); int CPXgetbasednorms(CPXENV *env, CPXLP *lp, int cstat[], int rstat[], double dnorm[]); int CPXgetbhead(CPXENV *env, CPXLP *lp, int head[], double x[]); int CPXgetdblparam(CPXENV *env, int whichparam, double *value); int CPXgetdj(CPXENV *env, CPXLP *lp, double dj[], int begin, int end); char *CPXgeterrorstring(CPXENV *env, int errcode, char *buffer); int CPXgetijdiv(CPXENV *env, CPXLP *lp, int *idiv, int *jdiv); int CPXgetintparam(CPXENV *env, int whichparam, int *value); int CPXgetlb(CPXENV *env, CPXLP *lp, double lb[], int begin, int end); int CPXgetmethod(CPXENV *env, CPXLP *lp); int CPXgetnumcols(CPXENV *env, CPXLP *lp); int CPXgetnumnz(CPXENV *env, CPXLP *lp); int CPXgetnumrows(CPXENV *env, CPXLP *lp); int CPXgetobjval(CPXENV *env, CPXLP *lp, double *objval); int CPXgetpi(CPXENV *env, CPXLP *lp, double pi[], int begin, int end); int CPXgetsense(CPXENV *env, CPXLP *lp, char sense[], int begin, int end); int CPXgetslack(CPXENV *env, CPXLP *lp, double slack[], int begin, int end); int CPXgetstat(CPXENV *env, CPXLP *lp); int CPXgetub(CPXENV *env, CPXLP *lp, double ub[], int begin, int end); int CPXgetweight(CPXENV *env, CPXLP *lp, int rcnt, const int rmatbeg[], const int rmatind[], const double rmatval[], double weight[], int dpriind); int CPXgetx(CPXENV *env, CPXLP *lp, double x[], int begin, int end); int CPXinfodblparam(CPXENV *env, int whichparam, double *defvalue, double *minvalue, double *maxvalue); int CPXinfointparam(CPXENV *env, int whichparam, int *defvalue, int *minvalue, int *maxvalue); int CPXlpopt(CPXENV *env, CPXLP *lp); int CPXmdleave(const CPXENV *env, CPXLP *lp, const int goodlist[], int goodlen, double downratio[], double upratio[]); int CPXnewcols(CPXENV *env, CPXLP *lp, int ccnt, const double obj[], const double lb[], const double ub[], const char ctype[], char *colname[]); int CPXnewrows(CPXENV *env, CPXLP *lp, int rcnt, const double rhs[], const char sense[], const double rngval[], char *rowname[]); CPXENV *CPXopenCPLEX(int *status); int CPXpivotin(CPXENV *env, CPXLP *lp, const int rlist[], int rlen); int CPXpivotout(CPXENV *env, CPXLP *lp, const int clist[], int clen); int CPXprimopt(CPXENV *env, CPXLP *lp); int CPXsavwrite(CPXENV *env, CPXLP *lp, const char *filename); int CPXsetdblparam(CPXENV *env, int whichparam, double newvalue); int CPXsetintparam(CPXENV *env, int whichparam, int newvalue); int CPXsolninfo(CPXENV *env, CPXLP *lp, int *solnmethod, int *solntype, int *pfeasind, int *dfeasind); int CPXsolution(CPXENV *env, CPXLP *lp, int *lpstat, double *objval, double x[], double pi[], double slack[], double dj[]); int CPXstrongbranch(CPXENV *env, CPXLP *lp, const int goodlist[], int goodlen, double downpen[], double uppen[], int itlim); int CPXwriteprob(CPXENV *env, CPXLP *lp, const char *filename, const char *filetype); #ifdef __cplusplus } #endif #endif /* eof */ glpk-4.52.1/examples/cplex/README0000644000062000006210000000347612175147600015544 0ustar maomkpasswdThe program module in this subdirectory is a crude implementation of CPLEX-like interface to GLPK API. It consists of two files: cplex.c and cplex.h. NOTE that this module is NOT a clean room implementation of the CPLEX callable library. It only implements a CPLEX-like interface to the GLPK API routines, and its main purpose is to provide possibility to build and run applications which normally use the CPLEX callable library. This module approximately corresponds to CPLEX 9.0. Currently this module can be used as a linear programming solver for Concorde, the state-of-the-art computer code for solving the symmetric traveling salesman problem (TSP) developed by David Applegate, Robert Bixby, Vasek Chvatal, and William Cook. For details about Concorde see its web page at http://www.tsp.gatech.edu/concorde.html. To build Concorde along with GLPK you need to do the following: 1. Configure, build, and install GLPK. 2. Download the Concorde tarball co031219.tgz (version Dec 19, 2003), unpack and unarchive it. 3. Copy files cplex.h and cplex.c to subdirectory concorde/LP/. 4. Create file named lpglpk.c in subdirectory concorde/LP/. This file must contain the following two lines: #include "cplex.c" #include "lpcplex8.c" 5. Configure Concorde in usual way (./configure) and then build it with the following command: make CPPFLAGS=-I. LPSOLVER_INTERFACE=lpglpk.c LPSOLVER_LIB=-lglpk The Concorde executable can be found in subdirectory concorde/TSP/. Please note that currently this GLPK interface module does not support some important features (namely, CPXgetijdiv, CPXmdleave, CPXpivotin, CPXpivotout, and CPXstrongbranch), so large (more than 1000 nodes) TSP instances cannot be solved in a reasonable time, and some instances may cause abnormal termination of Concorde (if CPXgetijdiv is called). glpk-4.52.1/examples/cpp.mod0000644000062000006210000000313612175147600015025 0ustar maomkpasswd/* CPP, Critical Path Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* Note: Reduced costs of auxiliary variables phi[j,k] (see below) can be only zero or one. The critical path is defined by the constraints, whose reduced cost is one. */ set J; /* set of jobs (activities) */ set P{j in J}, in J, default {}; /* P[j] is a subset of jobs that immediately precede job j */ param t{j in J}, >= 0; /* duration required to perform job j */ var x{j in J}, >= 0; /* starting time of job j */ s.t. phi{j in J, k in P[j]}: x[j] >= x[k] + t[k]; /* job j can start only after all immediately preceding jobs have been completely performed */ var z; /* project makespan */ s.t. fin{j in J}: z >= x[j] + t[j]; /* which is the maximum of the completion times of all the jobs */ minimize obj: z; /* the objective is make z as small as possible */ data; /* The optimal solution is 46 */ param : J : t := A 3 /* Excavate */ B 4 /* Lay foundation */ C 3 /* Rough plumbing */ D 10 /* Frame */ E 8 /* Finish exterior */ F 4 /* Install HVAC */ G 6 /* Rough electric */ H 8 /* Sheet rock */ I 5 /* Install cabinets */ J 5 /* Paint */ K 4 /* Final plumbing */ L 2 /* Final electric */ M 4 /* Install flooring */ ; set P[B] := A; set P[C] := B; set P[D] := B; set P[E] := D; set P[F] := D; set P[G] := D; set P[H] := C E F G; set P[I] := H; set P[J] := H; set P[K] := I; set P[L] := J; set P[M] := K L; end; glpk-4.52.1/examples/crypto.mod0000644000062000006210000000470112175147600015562 0ustar maomkpasswd/* CRYPTO, a crypto-arithmetic puzzle */ /* Written in GNU MathProg by Andrew Makhorin */ /* This problem comes from the newsgroup rec.puzzle. The numbers from 1 to 26 are assigned to the letters of the alphabet. The numbers beside each word are the total of the values assigned to the letters in the word (e.g. for LYRE: L, Y, R, E might be to equal 5, 9, 20 and 13, or any other combination that add up to 47). Find the value of each letter under the equations: BALLET 45 GLEE 66 POLKA 59 SONG 61 CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82 CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72 FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100 FUGUE 50 OPERA 65 SOLO 37 WALTZ 34 Solution: A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z 5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18 Reference: Koalog Constraint Solver , Simple problems, the crypto-arithmetic puzzle ALPHACIPHER. */ set LETTERS := { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' }; /* set of letters */ set VALUES := 1..card(LETTERS); /* set of values assigned to the letters */ set WORDS; /* set of words */ param total{word in WORDS}; /* total[word] is the total of the values assigned to the letters in the word */ var x{i in LETTERS, j in VALUES}, binary; /* x[i,j] = 1 means that letter i is assigned value j */ s.t. phi{i in LETTERS}: sum{j in VALUES} x[i,j] = 1; s.t. psi{j in VALUES}: sum{i in LETTERS} x[i,j] = 1; s.t. eqn{word in WORDS}: sum{k in 1..length(word), j in VALUES} j * x[substr(word,k,1), j] = total[word]; solve; printf{i in LETTERS} " %s", i; printf "\n"; printf{i in LETTERS} " %2d", sum{j in VALUES} j * x[i,j]; printf "\n"; data; param : WORDS : total := BALLET 45 CELLO 43 CONCERT 74 FLUTE 30 FUGUE 50 GLEE 66 JAZZ 58 LYRE 47 OBOE 53 OPERA 65 POLKA 59 QUARTET 50 SAXOPHONE 134 SCALE 51 SOLO 37 SONG 61 SOPRANO 82 THEME 72 VIOLIN 100 WALTZ 34 ; end; glpk-4.52.1/examples/csv/0000755000062000006210000000000012175147600014332 5ustar maomkpasswdglpk-4.52.1/examples/csv/distances.csv0000644000062000006210000000025412175147600017025 0ustar maomkpasswdplant,market,distance "Seattle","New York",2.5 "Seattle","Chicago",1.7 "Seattle","Topeka",1.8 "San Diego","New York",2.5 "San Diego","Chicago",1.8 "San Diego","Topeka",1.4 glpk-4.52.1/examples/csv/markets.csv0000644000062000006210000000007312175147600016515 0ustar maomkpasswdmarket,demand "New York",325. "Chicago",300. "Topeka",275. glpk-4.52.1/examples/csv/parameters.csv0000644000062000006210000000004512175147600017211 0ustar maomkpasswdparameter,value "transport cost",90. glpk-4.52.1/examples/csv/plants.csv0000644000062000006210000000005712175147600016352 0ustar maomkpasswdplant,capacity "Seattle",350. "San Diego",600. glpk-4.52.1/examples/csv/transp_csv.mod0000644000062000006210000000307512175147600017222 0ustar maomkpasswd# A TRANSPORTATION PROBLEM # # This problem finds a least cost shipping schedule that meets # requirements at markets and supplies at factories. # # References: # Dantzig G B, "Linear Programming and Extensions." # Princeton University Press, Princeton, New Jersey, 1963, # Chapter 3-3. set I; /* canning plants */ set J; /* markets */ set K dimen 2; /* transportation lane */ set L; /* parameters */ param a{i in I}; /* capacity of plant i in cases */ param b{j in J}; /* demand at market j in cases */ param d{i in I, j in J}; /* distance in thousands of miles */ param e{l in L}; /* parameters */ param f; /* freight in dollars per case per thousand miles */ table tab_plant IN "CSV" "plants.csv" : I <- [plant], a ~ capacity; table tab_market IN "CSV" "markets.csv" : J <- [market], b ~ demand; table tab_distance IN "CSV" "distances.csv" : K <- [plant, market], d ~ distance; table tab_parameter IN "CSV" "parameters.csv" : L <- [parameter], e ~ value ; param c{i in I, j in J} := e['transport cost'] * d[i,j] / 1000; /* transport cost in thousands of dollars per case */ var x{(i,j) in K} >= 0; /* shipment quantities in cases */ minimize cost: sum{(i,j) in K} c[i,j] * x[i,j]; /* total transportation costs in thousands of dollars */ s.t. supply{i in I}: sum{(i,j) in K} x[i,j] <= a[i]; /* observe supply limit at plant i */ s.t. demand{j in J}: sum{(i,j) in K} x[i,j] >= b[j]; /* satisfy demand at market j */ solve; table tab_result{(i,j) in K} OUT "CSV" "result.csv" : i ~ plant, j ~ market, x[i,j] ~ shipment; end; glpk-4.52.1/examples/dbf/0000755000062000006210000000000012175147600014272 5ustar maomkpasswdglpk-4.52.1/examples/dbf/cultural_pres.dbf0000666000062000006210000000014012175147600017632 0ustar maomkpasswdm A CUL_PRESN 1 2 9glpk-4.52.1/examples/dbf/ForestMgt_Model_I_GIS_dbf.mod0000644000062000006210000001645712175147600021627 0ustar maomkpasswd# Model I Forest Estate Modelling using GLPK/MathProg # Reading and writing dbf files # by Noli Sicad --- nsicad@gmail.com # 18 December 2009 # Forest Management 4th Edition # by Lawrence Davis, K. Norman Johnson, Pete Bettinger, Theodore Howard # Chapter 11 - Daniel Pickett # http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm # Model I Formulation /* Note: This is not the full LP model mentioned in the book. Some of the constraints are deliberately omitted in this model for the purpose of clarity. The features of MathProg in this example are: * reading and writing dbf from regular dbf files, * reading dbf file (database of shapefile (stands.shp)) (e.g. area parameter), * using the area data in the constraints and * writing dbf file from result of LP model. Model I - Harvest Scheduling formulation for Sustainable Forest Management (SFM) Features are: * Net Present Value for the objective function (Revenue - Cost) * Harvest Constraints by period - Sustainable Yield per Period * Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha (1-Apha) * Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta (1 +Beta) * Forest / Land Constraint -- Total Area of the forest * Forest Stand Constraint -- Individual stands What is next? -- Forest Mgt Carbon Accounting for Climate Change Note: The model file that the data containing in the dbf files is public domain material (so it is compatible with the GNU GPL) and data can be found in http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm # Noli Sicad --- nsicad@gmail.com */ set G_STAND_TYPE; # A, B, C set I_CULTURAL_PRES; set J_MGT_YEAR; param K_PERIOD; param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR}; # cost param Yield_Table_Vol{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0; param Alpha >= 0; param Beta >= 0; param TCost_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0; param NetRev_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD}; var XForestLand{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} >= 0; #reading dbf tables table tab IN "xBASE" "standtype.dbf": G_STAND_TYPE <- [STAND]; display G_STAND_TYPE; table tab2 IN "xBASE" "cultural_pres.dbf": I_CULTURAL_PRES <- [CUL_PRES]; display I_CULTURAL_PRES; table tab3 IN "xBASE" "mgt_year.dbf": J_MGT_YEAR <- [MGT_YEAR]; display J_MGT_YEAR; /* param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR} default 0; # cost */ set S1, dimen 3; table tab4 IN "xBASE" "Forest_Cost.dbf": S1 <- [STAND, CUL_PRES, MGT_YEAR],Forest_Cost ~FCOST; display Forest_Cost; set S2, dimen 4; table tab5 IN "xBASE" "Yield_Table_Vol.dbf": S2 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],Yield_Table_Vol ~YIELD; display Yield_Table_Vol; set S3, dimen 4; table tab5 IN "xBASE" "TCost_Table.dbf": S3 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],TCost_Table ~TCOST; display TCost_Table; set S4, dimen 4; table tab5 IN "xBASE" "NetRev_Table.dbf": S4 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],NetRev_Table ~NETREV; display NetRev_Table; param MGT; param Area_Stand_Indi{g in G_STAND_TYPE, m in 1..MGT} default 0; set ST, dimen 2; table tab5 IN "xBASE" "stands.dbf": ST <- [VEG_TYPE, MGT], Area_Stand_Indi ~ACRES; display Area_Stand_Indi; param Area_Stand_Type{g in G_STAND_TYPE}:= sum {m in 1..MGT } Area_Stand_Indi[g,m]; display Area_Stand_Type; param Total_Area := sum {g in G_STAND_TYPE, m in 1..MGT } Area_Stand_Indi[g,m]; display Total_Area; param Harvest_Min_Vol_Period; var NetPresentValue; # Objective function maximize Net_Present_Value: NetPresentValue; subject to NPV: NetPresentValue = sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Forest_Cost[g,i,j] * XForestLand[g,i,j]; # Harvest Constraint by Period subject to Harvest_Period_H {k in 1..K_PERIOD}: sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] >= Harvest_Min_Vol_Period; #Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha subject to Even_Flow_Constaints_Alpha {k in 6..K_PERIOD-1}: (1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] <= 0; # Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta subject to Even_Flow_Constaints_Beta {k in 6..K_PERIOD-1}: (1 + Beta) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] >= 0; # Forest / Land Constraints subject to Total_Area_Constraint: sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j] <= Total_Area; display Total_Area; # Forest / Land Constraints for A B C subject to Area {g in G_STAND_TYPE}: sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j] = Area_Stand_Type[g]; solve; #RESULT SECTION printf '#################################\n'; printf 'Forest Management Model I - Noli Sicad\n'; printf '\n'; printf 'Net Present Value = %.2f\n', NetPresentValue; printf '\n'; printf '\n'; printf 'Variables\n'; printf 'Stand_Type Age_Class Mgt_Presc Sign Value \n'; printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR}:'%5s %10s %11s = %10.2f\n', g,i,j, XForestLand[g,i,j]; printf '\n'; printf 'Constraints\n'; printf 'Period Harvest Sign \n'; for {k in 1..K_PERIOD} { printf '%5s %10.2f >= %.3f\n', k, sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j], Harvest_Min_Vol_Period; } # xbase (dbf) output table Harvest{k in 1..K_PERIOD} OUT "xBASE" "HarvestArea1.dbf" "N(5)N(15,2)" : k ~ Period, (sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]) ~ H_Area; # xbase (dbf) read set S, dimen 2; table tab2 IN "xBASE" "HarvestArea1.dbf": S <- [Period, H_Area]; display S; printf '\n'; printf 'Constraint\n'; printf 'Harvest Period\n'; printf 'Type AgeClass PrescMgt Period Value\n'; printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR, k in 1..K_PERIOD}:'%5s %11s %11s %5s %10.2f\n', g,i,j, k, (Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]); printf 'Even_Flow_Constaint_Alpha (1-Alpha)\n'; printf 'Period Sign \n'; for {k in 6..K_PERIOD-1} { printf "%s %10.2f <= %s\n", k, ((1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j]),0; } printf '\n'; # Forest / Land Constraints printf '\n'; printf 'Total Area Constraint\n'; printf 'Type AgeClass PrescMgt Value Sign Total_Area \n'; printf '%5s <= %.3f\n',sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j], Total_Area; printf 'Area\n'; printf 'Area Value Sign Areas_Stand\n'; for {g in G_STAND_TYPE} { printf '%5s %10.2f <= %.3f\n', g, sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j], Area_Stand_Type[g]; } #DATA SECTION data; # Most of the data has been moved to dbf format param MGT:=31; param K_PERIOD:= 7; param Alpha:= 0.20; param Beta:= 0.20; param Harvest_Min_Vol_Period:= 12000; end; glpk-4.52.1/examples/dbf/Forest_Cost.dbf0000666000062000006210000000266212175147600017213 0ustar maomkpasswdF$¡$STANDCCUL_PRESNMGT_YEARC FCOSTN A 1mgt_p1 9491.00 A 1mgt_p2 6508.00 A 1mgt_p3 4552.00 A 1mgt_p4 3160.00 A 2mgt_p1 9317.00 A 2mgt_p2 6549.00 A 2mgt_p3 4570.00 A 2mgt_p4 2965.00 A 9mgt_p1 -71.00 A 9mgt_p2 0.00 A 9mgt_p3 0.00 A 9mgt_p4 0.00 B 1mgt_p1 844.00 B 1mgt_p2 477.00 B 1mgt_p3 288.00 B 1mgt_p4 160.00 B 2mgt_p1 0.00 B 2mgt_p2 0.00 B 2mgt_p3 0.00 B 2mgt_p4 0.00 B 9mgt_p1 -47.00 B 9mgt_p2 0.00 B 9mgt_p3 0.00 B 9mgt_p4 0.00 C 1mgt_p1 720.00 C 1mgt_p2 755.00 C 1mgt_p3 682.00 C 1mgt_p4 525.00 C 2mgt_p1 0.00 C 2mgt_p2 0.00 C 2mgt_p3 0.00 C 2mgt_p4 0.00 C 9mgt_p1 -47.00 C 9mgt_p2 0.00 C 9mgt_p3 0.00 C 9mgt_p4 0.00glpk-4.52.1/examples/dbf/mgt_year.dbf0000666000062000006210000000015212175147600016560 0ustar maomkpasswdm A MGT_YEARC mgt_p1 mgt_p2 mgt_p3 mgt_p4 glpk-4.52.1/examples/dbf/NetRev_Table.dbf0000666000062000006210000002701212175147600017267 0ustar maomkpasswdFüÁ.STANDCCUL_PRESNMGT_YEARC PERIODN NETREVN A 1mgt_p1 1 9970.00 A 1mgt_p1 2 -30.00 A 1mgt_p1 3 -30.00 A 1mgt_p1 4 4020.00 A 1mgt_p1 5 -30.00 A 1mgt_p1 6 -30.00 A 1mgt_p1 7 4020.00 A 1mgt_p2 1 -30.00 A 1mgt_p2 2 10570.00 A 1mgt_p2 3 -30.00 A 1mgt_p2 4 -30.00 A 1mgt_p2 5 4080.00 A 1mgt_p2 6 -30.00 A 1mgt_p2 7 -30.00 A 1mgt_p3 1 -30.00 A 1mgt_p3 2 -30.00 A 1mgt_p3 3 11020.00 A 1mgt_p3 4 -30.00 A 1mgt_p3 5 -30.00 A 1mgt_p3 6 4020.00 A 1mgt_p3 7 -30.00 A 1mgt_p4 1 -30.00 A 1mgt_p4 2 -30.00 A 1mgt_p4 3 -30.00 A 1mgt_p4 4 11470.00 A 1mgt_p4 5 -30.00 A 1mgt_p4 6 -30.00 A 1mgt_p4 7 4020.00 A 2mgt_p1 1 9970.00 A 2mgt_p1 2 -30.00 A 2mgt_p1 3 -30.00 A 2mgt_p1 4 4020.00 A 2mgt_p1 5 -30.00 A 2mgt_p1 6 -30.00 A 2mgt_p1 7 4020.00 A 2mgt_p2 1 -30.00 A 2mgt_p2 2 10570.00 A 2mgt_p2 3 -30.00 A 2mgt_p2 4 -30.00 A 2mgt_p2 5 4080.00 A 2mgt_p2 6 -30.00 A 2mgt_p2 7 -30.00 A 2mgt_p3 1 -30.00 A 2mgt_p3 2 -30.00 A 2mgt_p3 3 11020.00 A 2mgt_p3 4 -30.00 A 2mgt_p3 5 -30.00 A 2mgt_p3 6 4020.00 A 2mgt_p3 7 -30.00 A 2mgt_p4 1 -30.00 A 2mgt_p4 2 -30.00 A 2mgt_p4 3 -30.00 A 2mgt_p4 4 11470.00 A 2mgt_p4 5 -30.00 A 2mgt_p4 6 -30.00 A 2mgt_p4 7 4020.00 A 9mgt_p1 1 -30.00 A 9mgt_p1 2 -30.00 A 9mgt_p1 3 -30.00 A 9mgt_p1 4 -30.00 A 9mgt_p1 5 -30.00 A 9mgt_p1 6 -30.00 A 9mgt_p1 7 -30.00 A 9mgt_p2 1 0.00 A 9mgt_p2 2 0.00 A 9mgt_p2 3 0.00 A 9mgt_p2 4 0.00 A 9mgt_p2 5 0.00 A 9mgt_p2 6 0.00 A 9mgt_p2 7 0.00 A 9mgt_p3 1 0.00 A 9mgt_p3 2 0.00 A 9mgt_p3 3 0.00 A 9mgt_p3 4 0.00 A 9mgt_p3 5 0.00 A 9mgt_p3 6 0.00 A 9mgt_p3 7 0.00 A 9mgt_p4 1 0.00 A 9mgt_p4 2 0.00 A 9mgt_p4 3 0.00 A 9mgt_p4 4 0.00 A 9mgt_p4 5 0.00 A 9mgt_p4 6 0.00 A 9mgt_p4 7 0.00 B 1mgt_p1 1 580.00 B 1mgt_p1 2 -20.00 B 1mgt_p1 3 -20.00 B 1mgt_p1 4 1820.00 B 1mgt_p1 5 -20.00 B 1mgt_p1 6 -20.00 B 1mgt_p1 7 1820.00 B 1mgt_p2 1 -20.00 B 1mgt_p2 2 555.00 B 1mgt_p2 3 -20.00 B 1mgt_p2 4 -20.00 B 1mgt_p2 5 1180.00 B 1mgt_p2 6 -20.00 B 1mgt_p2 7 -20.00 B 1mgt_p3 1 -20.00 B 1mgt_p3 2 -20.00 B 1mgt_p3 3 505.00 B 1mgt_p3 4 -20.00 B 1mgt_p3 5 -20.00 B 1mgt_p3 6 1180.00 B 1mgt_p3 7 -20.00 B 1mgt_p4 1 -20.00 B 1mgt_p4 2 -20.00 B 1mgt_p4 3 -20.00 B 1mgt_p4 4 -20.00 B 1mgt_p4 5 -20.00 B 1mgt_p4 6 -20.00 B 1mgt_p4 7 -20.00 B 2mgt_p1 1 0.00 B 2mgt_p1 2 0.00 B 2mgt_p1 3 0.00 B 2mgt_p1 4 0.00 B 2mgt_p1 5 0.00 B 2mgt_p1 6 0.00 B 2mgt_p1 7 0.00 B 2mgt_p2 1 0.00 B 2mgt_p2 2 0.00 B 2mgt_p2 3 0.00 B 2mgt_p2 4 0.00 B 2mgt_p2 5 0.00 B 2mgt_p2 6 0.00 B 2mgt_p2 7 0.00 B 2mgt_p3 1 0.00 B 2mgt_p3 2 0.00 B 2mgt_p3 3 0.00 B 2mgt_p3 4 0.00 B 2mgt_p3 5 0.00 B 2mgt_p3 6 0.00 B 2mgt_p3 7 0.00 B 2mgt_p4 1 0.00 B 2mgt_p4 2 0.00 B 2mgt_p4 3 0.00 B 2mgt_p4 4 0.00 B 2mgt_p4 5 0.00 B 2mgt_p4 6 0.00 B 2mgt_p4 7 0.00 B 9mgt_p1 1 -20.00 B 9mgt_p1 2 -20.00 B 9mgt_p1 3 -20.00 B 9mgt_p1 4 -20.00 B 9mgt_p1 5 -20.00 B 9mgt_p1 6 -20.00 B 9mgt_p1 7 -20.00 B 9mgt_p2 1 0.00 B 9mgt_p2 2 0.00 B 9mgt_p2 3 0.00 B 9mgt_p2 4 0.00 B 9mgt_p2 5 0.00 B 9mgt_p2 6 0.00 B 9mgt_p2 7 0.00 B 9mgt_p3 1 0.00 B 9mgt_p3 2 0.00 B 9mgt_p3 3 0.00 B 9mgt_p3 4 0.00 B 9mgt_p3 5 0.00 B 9mgt_p3 6 0.00 B 9mgt_p3 7 0.00 B 9mgt_p4 1 0.00 B 9mgt_p4 2 0.00 B 9mgt_p4 3 0.00 B 9mgt_p4 4 0.00 B 9mgt_p4 5 0.00 B 9mgt_p4 6 0.00 B 9mgt_p4 7 0.00 C 1mgt_p1 1 430.00 C 1mgt_p1 2 -20.00 C 1mgt_p1 3 -20.00 C 1mgt_p1 4 -20.00 C 1mgt_p1 5 1180.00 C 1mgt_p1 6 -20.00 C 1mgt_p1 7 1180.00 C 1mgt_p2 1 -20.00 C 1mgt_p2 2 1055.00 C 1mgt_p2 3 -20.00 C 1mgt_p2 4 -20.00 C 1mgt_p2 5 1180.00 C 1mgt_p2 6 20.00 C 1mgt_p2 7 20.00 C 1mgt_p3 1 -20.00 C 1mgt_p3 2 -20.00 C 1mgt_p3 3 2795.00 C 1mgt_p3 4 20.00 C 1mgt_p3 5 20.00 C 1mgt_p3 6 -20.00 C 1mgt_p3 7 -20.00 C 1mgt_p4 1 -20.00 C 1mgt_p4 2 -20.00 C 1mgt_p4 3 -20.00 C 1mgt_p4 4 1867.50 C 1mgt_p4 5 -20.00 C 1mgt_p4 6 -20.00 C 1mgt_p4 7 -20.00 C 2mgt_p1 1 0.00 C 2mgt_p1 2 0.00 C 2mgt_p1 3 0.00 C 2mgt_p1 4 0.00 C 2mgt_p1 5 0.00 C 2mgt_p1 6 0.00 C 2mgt_p1 7 0.00 C 2mgt_p2 1 0.00 C 2mgt_p2 2 0.00 C 2mgt_p2 3 0.00 C 2mgt_p2 4 0.00 C 2mgt_p2 5 0.00 C 2mgt_p2 6 0.00 C 2mgt_p2 7 0.00 C 2mgt_p3 1 0.00 C 2mgt_p3 2 0.00 C 2mgt_p3 3 0.00 C 2mgt_p3 4 0.00 C 2mgt_p3 5 0.00 C 2mgt_p3 6 0.00 C 2mgt_p3 7 0.00 C 2mgt_p4 1 0.00 C 2mgt_p4 2 0.00 C 2mgt_p4 3 0.00 C 2mgt_p4 4 0.00 C 2mgt_p4 5 0.00 C 2mgt_p4 6 0.00 C 2mgt_p4 7 0.00 C 9mgt_p1 1 -20.00 C 9mgt_p1 2 -20.00 C 9mgt_p1 3 -20.00 C 9mgt_p1 4 -20.00 C 9mgt_p1 5 -20.00 C 9mgt_p1 6 -20.00 C 9mgt_p1 7 -20.00 C 9mgt_p2 1 0.00 C 9mgt_p2 2 0.00 C 9mgt_p2 3 0.00 C 9mgt_p2 4 0.00 C 9mgt_p2 5 0.00 C 9mgt_p2 6 0.00 C 9mgt_p2 7 0.00 C 9mgt_p3 1 0.00 C 9mgt_p3 2 0.00 C 9mgt_p3 3 0.00 C 9mgt_p3 4 0.00 C 9mgt_p3 5 0.00 C 9mgt_p3 6 0.00 C 9mgt_p3 7 0.00 C 9mgt_p4 1 0.00 C 9mgt_p4 2 0.00 C 9mgt_p4 3 0.00 C 9mgt_p4 4 0.00 C 9mgt_p4 5 0.00 C 9mgt_p4 6 0.00 C 9mgt_p4 7 0.00glpk-4.52.1/examples/dbf/README0000644000062000006210000000015012175147600015146 0ustar maomkpasswdThis subdirectory contains an example MathProg model that demonstrates using data tables in DBF format. glpk-4.52.1/examples/dbf/stands.dbf0000666000062000006210000001034312175147600016250 0ustar maomkpasswdm AREAN PERIMETERN ACRESN VEG_TYPECCUL_PRESNMGT_YEARCBASAL_AREANAGENMBFNSTANDNMGTN 678347.313 3278.950 16.573A 1mgt_p1 270 75 42.1 8 1 1559350.500 9008.162 35.797A 1mgt_p2 220 55 25.7 6 2 2522098.500 7146.726 57.899A 1mgt_p3 200 50 21.2 1 3 2803427.500 7314.187 64.359A 1mgt_p4 250 65 34.2 4 4 2957964.250 7227.796 67.905A 2mgt_p1 230 60 29.6 14 5 3421375.000 9894.098 78.545A 2mgt_p2 290 90 52.0 12 6 5355937.500 11886.879 122.956A 2mgt_p3 200 50 21.1 28 7 5427447.000 12005.038 124.597A 2mgt_p4 220 55 24.9 13 8 5728451.500 14774.963 131.509A 2 240 65 34.0 19 9 6334165.000 11302.623 145.413A 9mgt_p1 260 70 37.7 24 10 6761519.000 16103.322 155.223A 1 210 55 25.8 3 11 947048.438 3668.863 21.742B 1mgt_p3 10 0 0.1 20 12 983290.750 4240.553 22.573B 1mgt_p4 10 5 0.8 15 13 1417177.250 4942.817 32.535B 1 10 0 0.6 11 14 1750618.250 6395.410 40.189B 1 10 5 0.2 23 15 2005855.000 7811.168 46.048B 1 20 10 1.4 18 16 2277913.250 6446.242 52.294B 1 20 10 1.8 29 17 2558007.500 8362.660 58.724B 1 10 0 0.4 21 18 3039506.500 7666.134 69.777B 1 10 5 0.1 27 19 3194198.250 10899.984 73.329B 1 20 10 1.2 22 20 3601950.500 8392.660 82.688B 9 20 10 1.3 9 21 1018033.125 4197.604 23.369C 1 210 50 21.2 10 22 1020423.875 5466.770 23.425C 1mgt_p1 160 35 9.0 26 23 1893590.750 6982.825 43.471C 1mgt_p2 110 25 4.1 31 24 1897039.375 9009.795 43.549C 1mgt_p3 190 45 17.3 30 25 3144825.500 7770.218 72.196C 1mgt_p4 150 35 8.7 7 26 3150030.000 8650.215 72.314C 1 140 35 8.9 17 27 4222868.000 11840.629 96.942C 1 170 40 13.0 25 28 7130442.000 14321.127 163.692C 1 90 20 3.1 5 29 9389994.000 18714.068 215.566C 1 175 40 12.9 2 30 10706765.000 16504.322 245.795C 9mgt_p2 120 30 5.6 16 31glpk-4.52.1/examples/dbf/standtype.dbf0000666000062000006210000000014012175147600016761 0ustar maomkpasswdm A STANDC A B C glpk-4.52.1/examples/dbf/TCost_Table.dbf0000666000062000006210000002701212175147600017120 0ustar maomkpasswdFüÁ.STANDCCUL_PRESNMGT_YEARC PERIODN TCOSTN A 1mgt_p1 1 4030.00 A 1mgt_p1 2 30.00 A 1mgt_p1 3 30.00 A 1mgt_p1 4 2480.00 A 1mgt_p1 5 30.00 A 1mgt_p1 6 30.00 A 1mgt_p1 7 2480.00 A 1mgt_p2 1 30.00 A 1mgt_p2 2 4230.00 A 1mgt_p2 3 30.00 A 1mgt_p2 4 30.00 A 1mgt_p2 5 2480.00 A 1mgt_p2 6 30.00 A 1mgt_p2 7 30.00 A 1mgt_p3 1 30.00 A 1mgt_p3 2 30.00 A 1mgt_p3 3 4380.00 A 1mgt_p3 4 30.00 A 1mgt_p3 5 30.00 A 1mgt_p3 6 2480.00 A 1mgt_p3 7 30.00 A 1mgt_p4 1 30.00 A 1mgt_p4 2 30.00 A 1mgt_p4 3 30.00 A 1mgt_p4 4 4530.00 A 1mgt_p4 5 30.00 A 1mgt_p4 6 30.00 A 1mgt_p4 7 2480.00 A 2mgt_p1 1 4030.00 A 2mgt_p1 2 30.00 A 2mgt_p1 3 480.00 A 2mgt_p1 4 30.00 A 2mgt_p1 5 2480.00 A 2mgt_p1 6 2480.00 A 2mgt_p1 7 480.00 A 2mgt_p2 1 30.00 A 2mgt_p2 2 4230.00 A 2mgt_p2 3 30.00 A 2mgt_p2 4 480.00 A 2mgt_p2 5 30.00 A 2mgt_p2 6 30.00 A 2mgt_p2 7 30.00 A 2mgt_p3 1 30.00 A 2mgt_p3 2 30.00 A 2mgt_p3 3 4380.00 A 2mgt_p3 4 30.00 A 2mgt_p3 5 480.00 A 2mgt_p3 6 30.00 A 2mgt_p3 7 2480.00 A 2mgt_p4 1 30.00 A 2mgt_p4 2 30.00 A 2mgt_p4 3 30.00 A 2mgt_p4 4 4530.00 A 2mgt_p4 5 30.00 A 2mgt_p4 6 480.00 A 2mgt_p4 7 30.00 A 9mgt_p1 1 30.00 A 9mgt_p1 2 30.00 A 9mgt_p1 3 30.00 A 9mgt_p1 4 30.00 A 9mgt_p1 5 30.00 A 9mgt_p1 6 30.00 A 9mgt_p1 7 30.00 A 9mgt_p2 1 0.00 A 9mgt_p2 2 0.00 A 9mgt_p2 3 0.00 A 9mgt_p2 4 0.00 A 9mgt_p2 5 0.00 A 9mgt_p2 6 0.00 A 9mgt_p2 7 0.00 A 9mgt_p3 1 0.00 A 9mgt_p3 2 0.00 A 9mgt_p3 3 0.00 A 9mgt_p3 4 0.00 A 9mgt_p3 5 0.00 A 9mgt_p3 6 0.00 A 9mgt_p3 7 0.00 A 9mgt_p4 1 0.00 A 9mgt_p4 2 0.00 A 9mgt_p4 3 0.00 A 9mgt_p4 4 0.00 A 9mgt_p4 5 0.00 A 9mgt_p4 6 0.00 A 9mgt_p4 7 0.00 B 1mgt_p1 1 3080.00 B 1mgt_p1 2 20.00 B 1mgt_p1 3 20.00 B 1mgt_p1 4 1820.00 B 1mgt_p1 5 20.00 B 1mgt_p1 6 20.00 B 1mgt_p1 7 1820.00 B 1mgt_p2 1 20.00 B 1mgt_p2 2 2945.00 B 1mgt_p2 3 20.00 B 1mgt_p2 4 20.00 B 1mgt_p2 5 1820.00 B 1mgt_p2 6 20.00 B 1mgt_p2 7 20.00 B 1mgt_p3 1 20.00 B 1mgt_p3 2 20.00 B 1mgt_p3 3 2795.00 B 1mgt_p3 4 20.00 B 1mgt_p3 5 20.00 B 1mgt_p3 6 1820.00 B 1mgt_p3 7 20.00 B 1mgt_p4 1 20.00 B 1mgt_p4 2 20.00 B 1mgt_p4 3 20.00 B 1mgt_p4 4 2570.00 B 1mgt_p4 5 20.00 B 1mgt_p4 6 20.00 B 1mgt_p4 7 1820.00 B 2mgt_p1 1 0.00 B 2mgt_p1 2 0.00 B 2mgt_p1 3 0.00 B 2mgt_p1 4 0.00 B 2mgt_p1 5 0.00 B 2mgt_p1 6 0.00 B 2mgt_p1 7 0.00 B 2mgt_p2 1 0.00 B 2mgt_p2 2 0.00 B 2mgt_p2 3 0.00 B 2mgt_p2 4 0.00 B 2mgt_p2 5 0.00 B 2mgt_p2 6 0.00 B 2mgt_p2 7 0.00 B 2mgt_p3 1 0.00 B 2mgt_p3 2 0.00 B 2mgt_p3 3 0.00 B 2mgt_p3 4 0.00 B 2mgt_p3 5 0.00 B 2mgt_p3 6 0.00 B 2mgt_p3 7 0.00 B 2mgt_p4 1 0.00 B 2mgt_p4 2 0.00 B 2mgt_p4 3 0.00 B 2mgt_p4 4 0.00 B 2mgt_p4 5 0.00 B 2mgt_p4 6 0.00 B 2mgt_p4 7 0.00 B 9mgt_p1 1 20.00 B 9mgt_p1 2 20.00 B 9mgt_p1 3 20.00 B 9mgt_p1 4 20.00 B 9mgt_p1 5 20.00 B 9mgt_p1 6 20.00 B 9mgt_p1 7 20.00 B 9mgt_p2 1 0.00 B 9mgt_p2 2 0.00 B 9mgt_p2 3 0.00 B 9mgt_p2 4 0.00 B 9mgt_p2 5 0.00 B 9mgt_p2 6 0.00 B 9mgt_p2 7 0.00 B 9mgt_p3 1 0.00 B 9mgt_p3 2 0.00 B 9mgt_p3 3 0.00 B 9mgt_p3 4 0.00 B 9mgt_p3 5 0.00 B 9mgt_p3 6 0.00 B 9mgt_p3 7 0.00 B 9mgt_p4 1 0.00 B 9mgt_p4 2 0.00 B 9mgt_p4 3 0.00 B 9mgt_p4 4 0.00 B 9mgt_p4 5 0.00 B 9mgt_p4 6 0.00 B 9mgt_p4 7 0.00 C 1mgt_p1 1 1070.00 C 1mgt_p1 2 20.00 C 1mgt_p1 3 20.00 C 1mgt_p1 4 1820.00 C 1mgt_p1 5 20.00 C 1mgt_p1 6 20.00 C 1mgt_p1 7 1820.00 C 1mgt_p2 1 20.00 C 1mgt_p2 2 2945.00 C 1mgt_p2 3 20.00 C 1mgt_p2 4 20.00 C 1mgt_p2 5 1820.00 C 1mgt_p2 6 20.00 C 1mgt_p2 7 20.00 C 1mgt_p3 1 20.00 C 1mgt_p3 2 20.00 C 1mgt_p3 3 2795.00 C 1mgt_p3 4 20.00 C 1mgt_p3 5 20.00 C 1mgt_p3 6 1820.00 C 1mgt_p3 7 20.00 C 1mgt_p4 1 20.00 C 1mgt_p4 2 20.00 C 1mgt_p4 3 20.00 C 1mgt_p4 4 2570.00 C 1mgt_p4 5 20.00 C 1mgt_p4 6 20.00 C 1mgt_p4 7 1820.00 C 2mgt_p1 1 0.00 C 2mgt_p1 2 0.00 C 2mgt_p1 3 0.00 C 2mgt_p1 4 0.00 C 2mgt_p1 5 0.00 C 2mgt_p1 6 0.00 C 2mgt_p1 7 0.00 C 2mgt_p2 1 0.00 C 2mgt_p2 2 0.00 C 2mgt_p2 3 0.00 C 2mgt_p2 4 0.00 C 2mgt_p2 5 0.00 C 2mgt_p2 6 0.00 C 2mgt_p2 7 0.00 C 2mgt_p3 1 0.00 C 2mgt_p3 2 0.00 C 2mgt_p3 3 0.00 C 2mgt_p3 4 0.00 C 2mgt_p3 5 0.00 C 2mgt_p3 6 0.00 C 2mgt_p3 7 0.00 C 2mgt_p4 1 0.00 C 2mgt_p4 2 0.00 C 2mgt_p4 3 0.00 C 2mgt_p4 4 0.00 C 2mgt_p4 5 0.00 C 2mgt_p4 6 0.00 C 2mgt_p4 7 0.00 C 9mgt_p1 1 20.00 C 9mgt_p1 2 20.00 C 9mgt_p1 3 20.00 C 9mgt_p1 4 20.00 C 9mgt_p1 5 20.00 C 9mgt_p1 6 20.00 C 9mgt_p1 7 20.00 C 9mgt_p2 1 0.00 C 9mgt_p2 2 0.00 C 9mgt_p2 3 0.00 C 9mgt_p2 4 0.00 C 9mgt_p2 5 0.00 C 9mgt_p2 6 0.00 C 9mgt_p2 7 0.00 C 9mgt_p3 1 0.00 C 9mgt_p3 2 0.00 C 9mgt_p3 3 0.00 C 9mgt_p3 4 0.00 C 9mgt_p3 5 0.00 C 9mgt_p3 6 0.00 C 9mgt_p3 7 0.00 C 9mgt_p4 1 0.00 C 9mgt_p4 2 0.00 C 9mgt_p4 3 0.00 C 9mgt_p4 4 0.00 C 9mgt_p4 5 0.00 C 9mgt_p4 6 0.00 C 9mgt_p4 7 0.00glpk-4.52.1/examples/dbf/Yield_Table_Vol.dbf0000666000062000006210000002701212175147600017752 0ustar maomkpasswdFüÁ.STANDCCUL_PRESNMGT_YEARC PERIODN YIELDN A 1mgt_p1 1 35.00 A 1mgt_p1 2 0.00 A 1mgt_p1 3 0.00 A 1mgt_p1 4 26.00 A 1mgt_p1 5 0.00 A 1mgt_p1 6 0.00 A 1mgt_p1 7 26.00 A 1mgt_p2 1 0.00 A 1mgt_p2 2 37.00 A 1mgt_p2 3 0.00 A 1mgt_p2 4 0.00 A 1mgt_p2 5 26.00 A 1mgt_p2 6 0.00 A 1mgt_p2 7 0.00 A 1mgt_p3 1 0.00 A 1mgt_p3 2 0.00 A 1mgt_p3 3 38.50 A 1mgt_p3 4 0.00 A 1mgt_p3 5 0.00 A 1mgt_p3 6 26.00 A 1mgt_p3 7 0.00 A 1mgt_p4 1 0.00 A 1mgt_p4 2 0.00 A 1mgt_p4 3 0.00 A 1mgt_p4 4 40.00 A 1mgt_p4 5 0.00 A 1mgt_p4 6 0.00 A 1mgt_p4 7 26.00 A 2mgt_p1 1 35.00 A 2mgt_p1 2 0.00 A 2mgt_p1 3 6.00 A 2mgt_p1 4 0.00 A 2mgt_p1 5 26.00 A 2mgt_p1 6 0.00 A 2mgt_p1 7 6.00 A 2mgt_p2 1 0.00 A 2mgt_p2 2 37.00 A 2mgt_p2 3 0.00 A 2mgt_p2 4 6.00 A 2mgt_p2 5 0.00 A 2mgt_p2 6 26.00 A 2mgt_p2 7 0.00 A 2mgt_p3 1 0.00 A 2mgt_p3 2 0.00 A 2mgt_p3 3 38.50 A 2mgt_p3 4 0.00 A 2mgt_p3 5 6.00 A 2mgt_p3 6 0.00 A 2mgt_p3 7 26.00 A 2mgt_p4 1 0.00 A 2mgt_p4 2 0.00 A 2mgt_p4 3 0.00 A 2mgt_p4 4 40.00 A 2mgt_p4 5 0.00 A 2mgt_p4 6 6.00 A 2mgt_p4 7 0.00 A 9mgt_p1 1 0.00 A 9mgt_p1 2 0.00 A 9mgt_p1 3 0.00 A 9mgt_p1 4 0.00 A 9mgt_p1 5 0.00 A 9mgt_p1 6 0.00 A 9mgt_p1 7 0.00 A 9mgt_p2 1 0.00 A 9mgt_p2 2 0.00 A 9mgt_p2 3 0.00 A 9mgt_p2 4 0.00 A 9mgt_p2 5 0.00 A 9mgt_p2 6 0.00 A 9mgt_p2 7 0.00 A 9mgt_p3 1 0.00 A 9mgt_p3 2 0.00 A 9mgt_p3 3 0.00 A 9mgt_p3 4 0.00 A 9mgt_p3 5 0.00 A 9mgt_p3 6 0.00 A 9mgt_p3 7 0.00 A 9mgt_p4 1 0.00 A 9mgt_p4 2 0.00 A 9mgt_p4 3 0.00 A 9mgt_p4 4 0.00 A 9mgt_p4 5 0.00 A 9mgt_p4 6 0.00 A 9mgt_p4 7 0.00 B 1mgt_p1 1 18.00 B 1mgt_p1 2 0.00 B 1mgt_p1 3 0.00 B 1mgt_p1 4 12.00 B 1mgt_p1 5 0.00 B 1mgt_p1 6 0.00 B 1mgt_p1 7 12.00 B 1mgt_p2 1 0.00 B 1mgt_p2 2 17.50 B 1mgt_p2 3 0.00 B 1mgt_p2 4 0.00 B 1mgt_p2 5 12.00 B 1mgt_p2 6 0.00 B 1mgt_p2 7 0.00 B 1mgt_p3 1 0.00 B 1mgt_p3 2 0.00 B 1mgt_p3 3 16.50 B 1mgt_p3 4 0.00 B 1mgt_p3 5 0.00 B 1mgt_p3 6 12.00 B 1mgt_p3 7 0.00 B 1mgt_p4 1 0.00 B 1mgt_p4 2 0.00 B 1mgt_p4 3 0.00 B 1mgt_p4 4 15.00 B 1mgt_p4 5 0.00 B 1mgt_p4 6 0.00 B 1mgt_p4 7 12.00 B 2mgt_p1 1 0.00 B 2mgt_p1 2 0.00 B 2mgt_p1 3 0.00 B 2mgt_p1 4 0.00 B 2mgt_p1 5 0.00 B 2mgt_p1 6 0.00 B 2mgt_p1 7 0.00 B 2mgt_p2 1 0.00 B 2mgt_p2 2 0.00 B 2mgt_p2 3 0.00 B 2mgt_p2 4 0.00 B 2mgt_p2 5 0.00 B 2mgt_p2 6 0.00 B 2mgt_p2 7 0.00 B 2mgt_p3 1 0.00 B 2mgt_p3 2 0.00 B 2mgt_p3 3 0.00 B 2mgt_p3 4 0.00 B 2mgt_p3 5 0.00 B 2mgt_p3 6 0.00 B 2mgt_p3 7 0.00 B 2mgt_p4 1 0.00 B 2mgt_p4 2 0.00 B 2mgt_p4 3 0.00 B 2mgt_p4 4 0.00 B 2mgt_p4 5 0.00 B 2mgt_p4 6 0.00 B 2mgt_p4 7 0.00 B 9mgt_p1 1 0.00 B 9mgt_p1 2 0.00 B 9mgt_p1 3 0.00 B 9mgt_p1 4 0.00 B 9mgt_p1 5 0.00 B 9mgt_p1 6 0.00 B 9mgt_p1 7 0.00 B 9mgt_p2 1 0.00 B 9mgt_p2 2 0.00 B 9mgt_p2 3 0.00 B 9mgt_p2 4 0.00 B 9mgt_p2 5 0.00 B 9mgt_p2 6 0.00 B 9mgt_p2 7 0.00 B 9mgt_p3 1 0.00 B 9mgt_p3 2 0.00 B 9mgt_p3 3 0.00 B 9mgt_p3 4 0.00 B 9mgt_p3 5 0.00 B 9mgt_p3 6 0.00 B 9mgt_p3 7 0.00 B 9mgt_p4 1 0.00 B 9mgt_p4 2 0.00 B 9mgt_p4 3 0.00 B 9mgt_p4 4 0.00 B 9mgt_p4 5 0.00 B 9mgt_p4 6 0.00 B 9mgt_p4 7 0.00 C 1mgt_p1 1 6.00 C 1mgt_p1 2 0.00 C 1mgt_p1 3 0.00 C 1mgt_p1 4 12.00 C 1mgt_p1 5 0.00 C 1mgt_p1 6 0.00 C 1mgt_p1 7 12.00 C 1mgt_p2 1 0.00 C 1mgt_p2 2 11.00 C 1mgt_p2 3 0.00 C 1mgt_p2 4 0.00 C 1mgt_p2 5 12.00 C 1mgt_p2 6 0.00 C 1mgt_p2 7 0.00 C 1mgt_p3 1 0.00 C 1mgt_p3 2 0.00 C 1mgt_p3 3 15.00 C 1mgt_p3 4 0.00 C 1mgt_p3 5 0.00 C 1mgt_p3 6 12.00 C 1mgt_p3 7 0.00 C 1mgt_p4 1 0.00 C 1mgt_p4 2 0.00 C 1mgt_p4 3 0.00 C 1mgt_p4 4 17.50 C 1mgt_p4 5 0.00 C 1mgt_p4 6 0.00 C 1mgt_p4 7 12.00 C 2mgt_p1 1 0.00 C 2mgt_p1 2 0.00 C 2mgt_p1 3 0.00 C 2mgt_p1 4 0.00 C 2mgt_p1 5 0.00 C 2mgt_p1 6 0.00 C 2mgt_p1 7 0.00 C 2mgt_p2 1 0.00 C 2mgt_p2 2 0.00 C 2mgt_p2 3 0.00 C 2mgt_p2 4 0.00 C 2mgt_p2 5 0.00 C 2mgt_p2 6 0.00 C 2mgt_p2 7 0.00 C 2mgt_p3 1 0.00 C 2mgt_p3 2 0.00 C 2mgt_p3 3 0.00 C 2mgt_p3 4 0.00 C 2mgt_p3 5 0.00 C 2mgt_p3 6 0.00 C 2mgt_p3 7 0.00 C 2mgt_p4 1 0.00 C 2mgt_p4 2 0.00 C 2mgt_p4 3 0.00 C 2mgt_p4 4 0.00 C 2mgt_p4 5 0.00 C 2mgt_p4 6 0.00 C 2mgt_p4 7 0.00 C 9mgt_p1 1 0.00 C 9mgt_p1 2 0.00 C 9mgt_p1 3 0.00 C 9mgt_p1 4 0.00 C 9mgt_p1 5 0.00 C 9mgt_p1 6 0.00 C 9mgt_p1 7 0.00 C 9mgt_p2 1 0.00 C 9mgt_p2 2 0.00 C 9mgt_p2 3 0.00 C 9mgt_p2 4 0.00 C 9mgt_p2 5 0.00 C 9mgt_p2 6 0.00 C 9mgt_p2 7 0.00 C 9mgt_p3 1 0.00 C 9mgt_p3 2 0.00 C 9mgt_p3 3 0.00 C 9mgt_p3 4 0.00 C 9mgt_p3 5 0.00 C 9mgt_p3 6 0.00 C 9mgt_p3 7 0.00 C 9mgt_p4 1 0.00 C 9mgt_p4 2 0.00 C 9mgt_p4 3 0.00 C 9mgt_p4 4 0.00 C 9mgt_p4 5 0.00 C 9mgt_p4 6 0.00 C 9mgt_p4 7 0.00glpk-4.52.1/examples/dea.mod0000644000062000006210000001152312175147600014773 0ustar maomkpasswd/* Data Envelopment Analysis (DEA) * * DEA quantifies the relative efficiency of decision making units (DMUs) by * finding the efficient frontier in multiple input multiple output data. The * inputs are resources (eg. number of employees, available machines, ...), * the outputs are productive outputs (eg. contracts made, total sales, ...). * The method is non-parametric. More details are available in the paper * below. * * Models according to: Seiford, Threall, "Recent developments in DEA", 1990. * * Implementation: Sebastian Nowozin */ ### SETS ### set dmus; # Decision Making Units (DMU) set inputs; # Input parameters set outputs; # Output parameters ### PARAMETERS ### param input_data{dmus,inputs} >= 0; param output_data{dmus,outputs} >= 0; ### PROGRAM ### var theta{dmus} >= 0; var lambda{dmus,dmus} >= 0; minimize inefficiency: sum{td in dmus} theta[td]; s.t. output_lower_limit{o in outputs, td in dmus}: sum{d in dmus} lambda[d,td]*output_data[d,o] >= output_data[td,o]; s.t. input_upper_limit{i in inputs, td in dmus}: sum{d in dmus} lambda[d,td]*input_data[d,i] <= theta[td]*input_data[td,i]; s.t. PI1{td in dmus}: sum{d in dmus} lambda[d,td] = 1; /* possibilities: i) (no constraint) ii) s.t. PI1{td in dmus}: sum{d in dmus} lambda[d,td] <= 1; iii) s.t. PI1{td in dmus}: sum{d in dmus} lambda[d,td] >= 1; */ ### SOLVE AND PRINT SOLUTION ### solve; printf "DMU\tEfficiency\n"; for {td in dmus} { printf "%s\t%1.4f\n", td, theta[td]; } ### DATA ### data; set dmus := 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 ; set inputs := AvgInventory LaborCost OperatingCost Population ; set outputs := PrescrVol kDollarValue ; param input_data default 0.0 : AvgInventory LaborCost OperatingCost Population := 1 8000 17030 1280 1410 2 9000 25890 2779 1523 3 13694 29076 2372 1354 4 4250 17506 1385 822 5 6500 23208 639 746 6 7000 12946 802 1281 7 4500 18001 1130 1016 8 5000 14473 1097 1070 9 27000 31760 5559 1694 10 21560 50972 15010 1910 11 15000 39523 4799 1745 12 8500 13076 3489 1353 13 35000 35427 1704 500 14 18000 27554 2882 1016 15 59750 53848 14208 2500 16 19200 38253 1480 2293 17 40000 109404 83016 2718 18 8466 18198 1278 2877 19 16000 40891 7599 4150 20 10000 45444 5556 4421 21 25000 35623 2121 3883 22 14000 20192 5515 3519 23 12500 34973 10475 32366 24 17260 32284 14498 3393 25 7000 17920 7585 4489 26 14000 42094 3742 2217 27 16400 35422 14236 4641 28 13000 19100 3529 5968 29 30000 72167 8656 8715 30 12530 19970 1714 5968 31 31500 39183 4919 5607 32 10000 32048 3483 7324 33 22000 68877 12279 8685 34 10000 29812 3332 8685 35 16000 47686 2507 5420 36 10000 33415 4738 7703 37 9000 12359 4603 4665 38 16439 23614 2989 6317 39 14500 36069 1793 31839 40 39000 76307 9539 15619 41 24927 40706 12661 30213 42 13858 39267 4609 34719 43 33375 29509 11323 31839 44 29044 44482 5542 34719 45 32257 61365 20550 32366 46 8800 49671 3306 43561 47 47000 40425 10396 31263 48 12000 33034 4915 31263 49 28000 69163 4688 15173 50 13300 28931 16735 73064 51 13500 29758 4260 62309 52 24000 40927 8285 23166 53 16000 40403 2131 99836 54 17000 38730 2539 60348 55 25000 35978 2502 99836 56 16000 37509 6278 99836 57 20000 46950 10715 85925 58 14000 35966 3144 85925 59 22000 68318 8015 108987 60 21879 69537 7778 108987 61 15000 25425 2812 201404 62 10000 19508 2454 201404 63 20000 28191 3367 201404 64 18000 37073 8624 108987 65 19051 23763 3496 201404 66 15000 28642 3366 201404 67 10000 35919 3868 201404 68 24000 54653 26494 108987 69 1800 6276 3413 60348 ; param output_data default 0.0 : PrescrVol kDollarValue := 1 12293 61.00 2 18400 92.00 3 16789 92.65 4 10700 45.00 5 9800 50.00 6 6500 29.00 7 8200 56.00 8 8680 45.00 9 33800 183.00 10 23710 156.00 11 24000 120.00 12 17500 75.00 13 25000 130.00 14 26000 122.00 15 26830 178.513 16 16600 106.00 17 90000 450.00 18 11140 73.624 19 25868 136.00 20 32700 191.295 21 29117 152.864 22 18000 100.00 23 11100 60.00 24 23030 137.778 25 10656 58.00 26 24682 152.095 27 26908 120.00 28 16464 80.00 29 57000 321.00 30 17532 94.747 31 30035 168.00 32 16000 100.00 33 63700 277.00 34 18000 90.00 35 27339 139.134 36 19500 116.00 37 13000 80.00 38 15370 102.00 39 18446 90.00 40 56000 260.00 41 73845 364.951 42 28600 145.00 43 27000 243.00 44 52423 279.816 45 73759 363.388 46 20500 80.00 47 27100 115.00 48 15000 110.00 49 50895 277.852 50 19707 128.00 51 17994 78.80 52 36135 167.222 53 30000 153.00 54 26195 125.00 55 28000 216.00 56 24658 152.551 57 36850 190.00 58 29250 183.69 59 50000 250.00 60 40078 265.443 61 20200 110.00 62 12500 75.00 63 30890 195.00 64 31000 175.00 65 31277 192.992 66 11500 75.00 67 30000 175.668 68 38383 190.00 69 2075 8.650 ; end; glpk-4.52.1/examples/diet.mod0000644000062000006210000000705512175147600015174 0ustar maomkpasswd# STIGLER'S NUTRITION MODEL # # This model determines a least cost diet which meets the daily # allowances of nutrients for a moderately active man weighing 154 lbs. # # References: # Dantzig G B, "Linear Programming and Extensions." # Princeton University Press, Princeton, New Jersey, 1963, # Chapter 27-1. set N; /* nutrients */ set F; /* foods */ param b{N}; /* required daily allowances of nutrients */ param a{F,N}; /* nutritive value of foods (per dollar spent) */ var x{f in F} >= 0; /* dollars of food f to be purchased daily */ s.t. nb{n in N}: sum{f in F} a[f,n] * x[f] = b[n]; /* nutrient balance (units) */ minimize cost: sum{f in F} x[f]; /* total food bill (dollars) */ data; param : N : b := Calorie 3 /* thousands */ Protein 70 /* grams */ Calcium 0.8 /* grams */ Iron 12 /* milligrams */ Vitamin-A 5 /* thousands IUs */ Vitamin-B1 1.8 /* milligrams */ Vitamin-B2 2.7 /* milligrams */ Niacin 18 /* milligrams */ Vitamin-C 75 /* milligrams */ ; set F := Wheat Cornmeal Cannedmilk Margarine Cheese Peanut-B Lard Liver Porkroast Salmon Greenbeans Cabbage Onions Potatoes Spinach Sweet-Pot Peaches Prunes Limabeans Navybeans; param a default 0 : Calorie Protein Calcium Iron Vitamin-A Vitamin-B1 := # (1000) (g) (g) (mg) (1000IU) (mg) Wheat 44.7 1411 2.0 365 . 55.4 Cornmeal 36 897 1.7 99 30.9 17.4 Cannedmilk 8.4 422 15.1 9 26 3 Margarine 20.6 17 .6 6 55.8 .2 Cheese 7.4 448 16.4 19 28.1 .8 Peanut-B 15.7 661 1 48 . 9.6 Lard 41.7 . . . .2 . Liver 2.2 333 .2 139 169.2 6.4 Porkroast 4.4 249 .3 37 . 18.2 Salmon 5.8 705 6.8 45 3.5 1 Greenbeans 2.4 138 3.7 80 69 4.3 Cabbage 2.6 125 4 36 7.2 9 Onions 5.8 166 3.8 59 16.6 4.7 Potatoes 14.3 336 1.8 118 6.7 29.4 Spinach 1.1 106 . 138 918.4 5.7 Sweet-Pot 9.6 138 2.7 54 290.7 8.4 Peaches 8.5 87 1.7 173 86.8 1.2 Prunes 12.8 99 2.5 154 85.7 3.9 Limabeans 17.4 1055 3.7 459 5.1 26.9 Navybeans 26.9 1691 11.4 792 . 38.4 : Vitamin-B2 Niacin Vitamin-C := # (mg) (mg) (mg) Wheat 33.3 441 . Cornmeal 7.9 106 . Cannedmilk 23.5 11 60 Margarine . . . Cheese 10.3 4 . Peanut-B 8.1 471 . Lard .5 5 . Liver 50.8 316 525 Porkroast 3.6 79 . Salmon 4.9 209 . Greenbeans 5.8 37 862 Cabbage 4.5 26 5369 Onions 5.9 21 1184 Potatoes 7.1 198 2522 Spinach 13.8 33 2755 Sweet-Pot 5.4 83 1912 Peaches 4.3 55 57 Prunes 4.3 65 257 Limabeans 38.2 93 . Navybeans 24.6 217 . ; end; glpk-4.52.1/examples/dist.mod0000644000062000006210000005657112175147600015221 0ustar maomkpasswd# DIST, a product distribution model # # References: # Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language # for Mathematical Programming." Management Science 36 (1990) 519-554. ### SHIPPING SETS AND PARAMETERS ### set whse 'warehouses'; # Locations from which demand is satisfied set dctr 'distribution centers' within whse; # Locations from which product may be shipped param sc 'shipping cost' {dctr,whse} >= 0; # Shipping costs, to whse from dctr, in $ / 100 lb param huge 'largest shipping cost' > 0; # Largest cost allowed for a usable shipping route param msr 'minimum size restriction' {dctr,whse} logical; # True indicates a minimum-size restriction on # direct shipments using this dctr --> whse route param dsr 'direct shipment requirement' {dctr} >= 0; # Minimum total demand, in pallets, needed to # allow shipment on routes subject to the # minimum size restriction ### PLANT SETS AND PARAMETERS ### set fact 'factories' within dctr; # Locations where product is manufactured param rtmin 'regular-time total minimum' >= 0; # Lower limit on (average) total regular-time # crews employed at all factories param rtmax 'regular-time total maximum' >= rtmin; # Upper limit on (average) total regular-time # crews employed at all factories param otmin 'overtime total minimum' >= 0; # Lower limit on total overtime hours at all factories param otmax 'overtime total maximum' >= otmin; # Upper limit on total overtime hours at all factories param rmin 'regular-time minimums' {fact} >= 0; # Lower limits on (average) regular-time crews param rmax 'regular-time maximums' {f in fact} >= rmin[f]; # Upper limits on (average) regular-time crews param omin 'overtime minimums' {fact} >= 0; # Lower limits on overtime hours param omax 'overtime maximums' {f in fact} >= omin[f]; # Upper limits on overtime hours param hd 'hours per day' {fact} >= 0; # Regular-time hours per working day param dp 'days in period' {fact} > 0; # Working days in the current planning period ### PRODUCT SETS AND PARAMETERS ### set prd 'products'; # Elements of the product group param wt 'weight' {prd} > 0; # Weight in 100 lb / 1000 cases param cpp 'cases per pallet' {prd} > 0; # Cases of product per shipping pallet param tc 'transshipment cost' {prd} >= 0; # Transshipment cost in $ / 1000 cases param pt 'production time' {prd,fact} >= 0; # Crew-hours to produce 1000 cases param rpc 'regular-time production cost' {prd,fact} >= 0; # Cost of production on regular time, # in $ / 1000 cases param opc 'overtime production cost' {prd,fact} >= 0; # Cost of production on overtime, in $ / 1000 cases ### DEMAND SETS AND PARAMETERS ### param dt 'total demand' {prd} >= 0; # Total demands for products, in 1000s param ds 'demand shares' {prd,whse} >= 0.0, <= 1.0; # Historical demand data, from which each # warehouse's share of total demand is deduced param dstot {p in prd} := sum {w in whse} ds[p,w]; # Total of demand shares; should be 1, but often isn't param dem 'demand' {p in prd, w in whse} := dt[p] * ds[p,w] / dstot[p]; # Projected demands to be satisfied, in 1000s set rt 'shipping routes available' := {d in dctr, w in whse: d <> w and sc[d,w] < huge and (w in dctr or sum {p in prd} dem[p,w] > 0) and not (msr[d,w] and sum {p in prd} 1000*dem[p,w]/cpp[p] < dsr[d]) }; # List of ordered pairs that represent routes # on which shipments are allowed ### VARIABLES ### var Rprd 'regular-time production' {prd,fact} >= 0; # Regular-time production of each product # at each factory, in 1000s of cases var Oprd 'overtime production' {prd,fact} >= 0; # Overtime production of each product # at each factory, in 1000s of cases var Ship 'shipments' {prd,rt} >= 0; # Shipments of each product on each allowed route, # in 1000s of cases var Trans 'transshipments' {prd,dctr} >= 0; # Transshipments of each product at each # distribution center, in 1000s of cases ### OBJECTIVE ### minimize cost: sum {p in prd, f in fact} rpc[p,f] * Rprd[p,f] + sum {p in prd, f in fact} opc[p,f] * Oprd[p,f] + sum {p in prd, (d,w) in rt} sc[d,w] * wt[p] * Ship[p,d,w] + sum {p in prd, d in dctr} tc[p] * Trans[p,d]; # Total cost: regular production, overtime # production, shipping, and transshipment ### CONSTRAINTS ### rtlim 'regular-time total limits': rtmin <= sum {p in prd, f in fact} (pt[p,f] * Rprd[p,f]) / (dp[f] * hd[f]) <= rtmax; # Total crews must lie between limits otlim 'overtime total limits': otmin <= sum {p in prd, f in fact} pt[p,f] * Oprd[p,f] <= otmax; # Total overtime must lie between limits rlim 'regular-time limits' {f in fact}: rmin[f] <= sum {p in prd} (pt[p,f] * Rprd[p,f]) / (dp[f] * hd[f]) <= rmax[f]; # Crews at each factory must lie between limits olim 'overtime limits' {f in fact}: omin[f] <= sum {p in prd} pt[p,f] * Oprd[p,f] <= omax[f]; # Overtime at each factory must lie between limits noRprd 'no regular production' {p in prd, f in fact: rpc[p,f] = 0}: Rprd[p,f] = 0; noOprd 'no overtime production' {p in prd, f in fact: opc[p,f] = 0}: Oprd[p,f] = 0; # Do not produce where specified cost is zero bal 'material balance' {p in prd, w in whse}: sum {(v,w) in rt} Ship [p,v,w] + (if w in fact then Rprd[p,w] + Oprd[p,w]) = dem[p,w] + (if w in dctr then sum {(w,v) in rt} Ship[p,w,v]); # Demand is satisfied by shipment into warehouse # plus production (if it is a factory) # minus shipment out (if it is a distn. center) trdef 'transshipment definition' {p in prd, d in dctr}: Trans[p,d] >= sum {(d,w) in rt} Ship [p,d,w] - (if d in fact then Rprd[p,d] + Oprd[p,d]); # Transshipment at a distribution center is # shipments out less production (if any) ### DATA -- 3 PRODUCTS ### data; set prd := 18REG 24REG 24PRO ; set whse := w01 w02 w03 w04 w05 w06 w08 w09 w12 w14 w15 w17 w18 w19 w20 w21 w24 w25 w26 w27 w28 w29 w30 w31 w32 w33 w34 w35 w36 w37 w38 w39 w40 w41 w42 w43 w44 w45 w46 w47 w48 w49 w50 w51 w53 w54 w55 w56 w57 w59 w60 w61 w62 w63 w64 w65 w66 w68 w69 w71 w72 w73 w74 w75 w76 w77 w78 w79 w80 w81 w82 w83 w84 w85 w86 w87 w89 w90 w91 w92 w93 w94 w95 w96 w98 x22 x23 ; set dctr := w01 w02 w03 w04 w05 w62 w76 w96 ; set fact := w01 w05 w96 ; param huge := 99. ; param rtmin := 0.0 ; param rtmax := 8.0 ; param otmin := 0.0 ; param otmax := 96.0 ; param rmin := w01 0.00 w05 0.00 w96 0.00 ; param rmax := w01 3.00 w05 2.00 w96 3.00 ; param omin := w01 0.0 w05 0.0 w96 0.0 ; param omax := w01 48.0 w05 0.0 w96 48.0 ; param hd := w01 8.0 w05 8.0 w96 8.0 ; param dp := w01 19.0 w05 19.0 w96 19.0 ; param wt := 18REG 47.3 24REG 63.0 24PRO 63.0 ; param tc := 18REG 40.00 24REG 45.00 24PRO 45.00 ; param dt := 18REG 376.0 24REG 172.4 24PRO 316.3 ; param cpp := 18REG 102. 24REG 91. 24PRO 91. ; param dsr := w01 96. w02 96. w03 96. w04 96. w05 96. w62 96. w76 96. w96 96. ; param pt (tr) : 18REG 24REG 24PRO := w01 1.194 1.429 1.429 w05 1.194 1.509 1.509 w96 0.000 1.600 1.600 ; param rpc (tr) : 18REG 24REG 24PRO := w01 2119. 2653. 2617. w05 2489. 3182. 3176. w96 0. 2925. 2918. ; param opc (tr) : 18REG 24REG 24PRO := w01 2903. 3585. 3579. w05 0. 0. 0. w96 0. 3629. 3622. ; param sc default 99.99 (tr) : w01 w02 w03 w04 w05 w62 w76 w96 := w01 . 2.97 1.14 2.08 2.37 1.26 2.42 1.43 w02 4.74 . 4.17 6.12 7.41 3.78 7.04 5.21 w03 2.45 4.74 . 3.67 2.84 0.90 2.41 2.55 w04 1.74 5.03 2.43 . 3.19 2.45 2.69 0.58 w05 2.70 5.16 2.84 2.85 . 3.26 3.34 2.71 w06 1.99 4.17 2.13 2.19 2.52 2.06 2.00 1.51 w08 0.21 2.92 1.24 2.07 2.29 1.25 2.32 1.55 w09 0.66 3.76 1.41 2.47 1.82 1.66 . 1.87 w12 1.38 3.83 1.68 2.53 2.39 . 1.96 1.94 w14 2.47 1.58 2.40 3.59 3.85 2.25 . 3.05 w15 1.06 4.95 2.48 1.39 3.41 1.96 . 1.02 w17 0.88 3.39 1.46 2.00 2.67 1.45 . 1.46 w18 7.90 6.57 7.79 9.59 10.81 . . 6.70 w19 1.42 4.12 1.96 1.99 3.52 1.88 . 1.26 w20 3.03 1.59 2.34 4.76 3.98 1.88 . 3.73 w24 1.58 2.80 2.27 2.87 3.19 1.31 . 2.05 w25 1.51 5.05 2.74 0.57 2.98 . 2.95 0.27 w26 1.75 3.61 2.70 1.54 4.07 3.52 . 1.03 w27 2.48 6.87 3.17 1.59 2.08 3.45 . 0.99 w28 2.05 6.83 2.97 1.13 2.91 . . 1.26 w29 4.03 3.68 4.46 3.20 5.50 . . 3.20 w30 2.48 5.78 2.99 2.24 1.79 3.10 . 1.39 w31 2.34 5.41 2.87 1.67 1.66 . . 1.39 w32 14.36 . . . . . . . w33 3.87 4.27 5.11 3.48 5.66 4.03 . 3.05 w34 3.26 4.80 3.21 2.70 4.14 . . 1.77 w35 2.34 2.84 2.89 3.35 3.78 2.68 . 2.52 w36 2.43 5.69 2.96 2.95 1.02 2.61 1.07 2.54 w37 2.23 4.64 2.41 1.99 4.30 2.61 . 1.44 w38 4.66 4.36 5.23 3.04 4.46 . . 3.82 w39 1.11 3.51 1.10 2.53 3.07 1.12 . 2.23 w40 2.99 4.78 4.23 1.57 3.92 . . 1.80 w41 4.93 4.00 5.43 4.45 6.31 . . 3.81 w42 3.86 6.55 5.03 2.11 4.41 . . 2.63 w43 4.61 4.45 3.77 1.22 4.31 . . 2.35 w44 2.05 4.48 1.06 3.70 3.46 1.10 . 3.21 w45 0.92 3.42 1.58 3.04 1.82 1.94 . 2.52 w46 1.36 2.44 0.95 3.08 2.78 0.39 2.16 2.37 w47 1.30 3.39 1.60 2.49 4.29 2.04 . 1.68 w48 1.65 3.78 1.03 2.97 2.21 1.31 . 2.74 w49 1.96 3.00 1.50 3.24 3.68 1.00 . 2.99 w50 0.90 4.14 1.60 1.95 3.61 1.61 . 1.52 w51 1.59 3.95 0.25 2.96 2.58 1.00 2.41 2.71 w53 1.59 3.79 1.28 3.12 3.10 0.89 . 2.98 w54 1.72 4.36 1.61 2.92 2.34 1.91 1.97 3.05 w55 2.45 2.73 2.21 4.47 4.30 2.57 . 4.48 w56 1.10 3.73 1.59 2.74 2.33 1.45 . 2.44 w57 0.95 3.39 1.37 2.30 2.47 1.15 . 1.95 w59 3.29 5.35 3.32 3.81 1.52 3.38 1.34 4.08 w60 2.41 6.12 2.46 3.65 2.35 . 1.37 4.06 w61 3.32 5.50 3.41 3.38 1.23 . 0.99 4.28 w62 1.12 3.00 0.82 3.22 2.95 . 3.33 2.53 w63 3.59 6.36 3.25 4.12 1.84 3.59 1.46 4.03 w64 1.85 4.45 2.17 3.43 2.13 2.03 . 4.02 w65 2.78 4.79 2.81 2.94 1.54 2.90 1.07 2.94 w66 3.90 5.79 3.05 3.65 1.36 3.39 1.22 3.57 w68 2.61 5.20 2.90 2.34 1.68 3.19 1.48 2.31 w69 2.94 5.21 2.78 3.43 0.21 3.26 0.68 2.54 w71 2.06 4.98 2.38 2.44 1.59 2.97 1.05 2.55 w72 2.61 5.50 2.83 3.12 1.35 3.23 0.88 2.99 w73 8.52 6.16 8.03 8.83 10.44 7.38 10.26 . w74 6.11 5.46 9.07 9.38 10.80 . . 8.25 w75 2.66 4.94 2.87 3.69 1.52 3.15 1.24 4.00 w76 1.99 5.26 2.23 3.36 0.58 3.17 . 2.50 w77 4.32 3.07 5.05 3.88 6.04 . . 4.15 w78 5.60 2.59 5.78 5.56 7.10 . . 5.60 w79 4.25 2.32 4.93 4.57 6.04 . . 4.58 w80 5.94 4.00 5.60 7.02 9.46 . . 7.51 w81 5.39 2.21 5.10 6.22 6.46 . . 6.58 w82 8.80 5.69 9.29 9.88 11.69 8.63 11.52 . w83 4.40 . 5.24 5.21 5.81 3.91 7.04 5.33 w84 5.87 5.43 6.17 5.70 7.63 . . 5.70 w85 3.90 3.65 3.38 4.57 5.64 3.05 . 5.04 w86 5.48 2.10 5.70 6.37 7.33 . . 6.19 w87 8.88 5.54 9.50 9.71 11.64 8.85 11.68 . w89 4.62 4.01 4.03 6.30 6.30 3.81 . 7.77 w90 4.35 2.72 4.61 4.01 5.60 . . 3.20 w91 7.61 4.42 7.83 6.85 8.79 . . 7.66 w92 7.15 2.69 6.91 7.20 . . . 7.06 w93 3.17 3.95 4.37 3.74 5.05 . . 2.40 w94 1.21 3.07 0.90 2.74 3.17 . 2.63 2.39 w95 5.82 3.29 6.55 7.06 11.47 . . 7.83 w96 1.77 5.20 2.72 0.59 3.47 2.48 . . w98 3.04 1.92 3.64 3.70 4.90 3.05 . 3.88 x22 4.08 6.25 4.15 4.30 1.77 . 1.77 . x23 3.39 5.74 3.55 4.08 1.69 . 1.47 . ; param msr (tr) : w01 w02 w03 w04 w05 w62 w76 w96 := w01 0 0 0 0 0 0 1 0 w02 0 0 0 0 0 0 1 0 w03 0 0 0 0 0 0 1 0 w04 0 0 0 0 0 0 1 0 w05 0 0 0 0 0 0 0 0 w06 0 1 1 1 1 1 1 1 w08 0 1 1 1 1 1 1 1 w09 0 1 1 1 1 1 0 1 w12 0 1 1 1 1 0 1 1 w14 1 1 1 1 1 0 0 1 w15 0 1 1 1 1 1 0 1 w17 0 1 1 1 1 1 0 1 w18 0 1 1 1 1 0 0 1 w19 0 1 1 1 1 0 0 1 w20 1 1 1 1 1 0 0 1 w24 0 1 1 1 1 0 0 1 w25 0 1 1 1 1 0 1 0 w26 1 1 1 0 1 1 0 1 w27 1 1 1 0 1 1 0 1 w28 1 1 1 0 1 0 0 1 w29 0 1 1 1 1 0 0 1 w30 1 1 1 0 1 1 0 1 w31 1 1 1 0 1 0 0 1 w32 0 0 0 0 0 0 0 0 w33 1 0 1 1 1 1 0 1 w34 1 1 1 0 1 0 0 1 w35 1 1 1 1 1 0 0 1 w36 0 1 1 1 0 1 1 1 w37 1 1 1 0 1 1 0 1 w38 1 1 1 0 1 0 0 1 w39 0 1 1 1 1 1 0 1 w40 1 1 1 0 1 0 0 1 w41 1 0 1 1 1 0 0 1 w42 1 1 1 0 1 0 0 1 w43 1 1 1 0 1 0 0 1 w44 1 1 1 1 1 0 0 1 w45 0 1 1 1 1 1 0 1 w46 0 1 1 1 1 0 1 1 w47 0 1 1 1 1 1 0 1 w48 0 1 1 1 1 0 0 1 w49 1 1 1 1 1 0 0 1 w50 0 1 1 1 1 1 0 1 w51 0 1 1 1 1 0 1 1 w53 1 1 1 1 1 0 0 1 w54 0 1 1 1 1 1 1 1 w55 0 1 1 1 1 0 0 1 w56 0 1 1 1 1 1 0 1 w57 0 1 1 1 1 1 0 1 w59 0 1 1 1 0 1 1 1 w60 0 1 1 1 1 0 1 1 w61 0 1 1 1 0 0 1 1 w62 0 0 0 0 0 0 1 0 w63 0 1 1 1 0 1 1 1 w64 0 1 1 1 1 1 0 1 w65 0 1 1 1 0 1 1 1 w66 0 1 1 1 0 1 1 1 w68 0 1 1 1 0 1 1 1 w69 0 1 1 1 0 1 1 1 w71 0 1 1 1 0 1 1 1 w72 0 1 1 1 0 1 1 1 w73 0 1 1 1 0 1 1 0 w74 0 1 1 1 0 0 0 1 w75 0 1 1 1 0 1 1 1 w76 0 0 0 0 0 0 0 0 w77 1 0 1 1 1 0 0 1 w78 1 0 1 1 1 0 0 1 w79 1 0 1 1 1 0 0 1 w80 1 0 1 1 1 0 0 1 w81 1 0 1 1 1 0 0 1 w82 1 0 1 1 1 1 1 0 w83 1 0 1 1 1 0 1 1 w84 1 0 1 1 1 0 0 1 w85 1 1 1 1 1 0 0 1 w86 1 0 1 1 1 0 0 1 w87 1 0 1 1 1 1 1 0 w89 1 0 1 1 1 1 0 1 w90 0 1 1 1 1 0 0 1 w91 1 0 1 1 1 0 0 1 w92 1 0 1 1 1 0 0 1 w93 1 1 1 0 1 0 0 1 w94 0 0 1 1 1 0 1 1 w95 1 0 1 1 1 0 0 1 w96 0 0 0 0 0 0 0 0 w98 1 0 1 1 1 1 0 1 x22 1 1 1 1 0 0 1 0 x23 1 1 1 1 0 0 1 0 ; param ds default 0.000 (tr) : 18REG 24REG 24PRO := w01 0.000 0.000 0.008 w02 0.004 0.000 0.000 w03 0.000 0.000 0.000 w04 0.010 0.002 0.000 w05 0.000 0.000 0.000 w06 0.010 0.008 0.008 w08 0.030 0.024 0.024 w09 0.014 0.018 0.020 w12 0.014 0.012 0.010 w14 0.007 0.007 0.012 w15 0.010 0.019 0.018 w17 0.013 0.010 0.011 w19 0.015 0.012 0.009 w20 0.012 0.021 0.022 w21 0.000 0.000 0.000 w24 0.012 0.022 0.018 w25 0.019 0.025 0.020 w26 0.006 0.015 0.021 w27 0.008 0.010 0.015 w28 0.011 0.016 0.019 w29 0.008 0.020 0.013 w30 0.011 0.013 0.015 w31 0.011 0.013 0.017 w32 0.006 0.000 0.000 w33 0.000 0.015 0.014 w34 0.008 0.007 0.005 w35 0.002 0.006 0.014 w36 0.015 0.013 0.005 w37 0.017 0.016 0.015 w38 0.015 0.009 0.012 w39 0.007 0.017 0.022 w40 0.009 0.014 0.020 w41 0.003 0.014 0.011 w42 0.017 0.011 0.012 w43 0.009 0.013 0.011 w44 0.002 0.012 0.012 w45 0.016 0.025 0.028 w46 0.038 0.062 0.040 w47 0.007 0.010 0.010 w48 0.003 0.015 0.016 w49 0.005 0.016 0.017 w50 0.011 0.008 0.007 w51 0.010 0.022 0.021 w53 0.004 0.026 0.020 w54 0.020 0.017 0.025 w55 0.004 0.019 0.028 w56 0.004 0.010 0.008 w57 0.014 0.020 0.018 w59 0.012 0.006 0.007 w60 0.019 0.010 0.009 w61 0.028 0.010 0.012 w62 0.000 0.000 0.000 w63 0.070 0.027 0.037 w64 0.009 0.004 0.005 w65 0.022 0.015 0.016 w66 0.046 0.017 0.020 w68 0.005 0.012 0.016 w69 0.085 0.036 0.039 w71 0.011 0.013 0.010 w72 0.089 0.031 0.034 w75 0.026 0.012 0.010 w77 0.001 0.004 0.002 w78 0.002 0.004 0.002 w79 0.001 0.004 0.002 w80 0.001 0.001 0.002 w81 0.001 0.003 0.002 w83 0.009 0.010 0.008 w84 0.001 0.002 0.002 w85 0.001 0.004 0.005 w86 0.001 0.002 0.002 w87 0.002 0.003 0.000 w89 0.001 0.001 0.002 w90 0.006 0.017 0.013 w91 0.002 0.010 0.013 w92 0.000 0.003 0.002 w93 0.002 0.006 0.007 w95 0.001 0.007 0.007 w96 0.000 0.000 0.000 w98 0.006 0.005 0.002 ; end; glpk-4.52.1/examples/egypt.mod0000644000062000006210000004460512175147600015401 0ustar maomkpasswd# EGYPT, a static model of fertilizer production # # References: # Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language # for Mathematical Programming." Management Science 36 (1990) 519-554. ### SETS ### set center; # Locations from which final product may be shipped set port within center; # Locations at which imports can be received set plant within center; # Locations of plants set region; # Demand regions set unit; # Productive units set proc; # Processes set nutr; # Nutrients set c_final; # Final products (fertilizers) set c_inter; # Intermediate products set c_ship within c_inter; # Intermediates for shipment set c_raw; # Domestic raw materials and miscellaneous inputs set commod := c_final union c_inter union c_raw; # All commodities ### PARAMETERS ### param cf75 {region,c_final} >= 0; # Consumption of fertilizer 1974-75 (1000 tpy) param fn {c_final,nutr} >= 0; # Nutrient content of fertilizers param cn75 {r in region, n in nutr} := sum {c in c_final} cf75[r,c] * fn[c,n]; # Consumption of nutrients 1974-75 (1000 tpy) param road {region,center} >= 0; # Road distances param rail_half {plant,plant} >= 0; param rail {p1 in plant, p2 in plant} := if rail_half[p1,p2] > 0 then rail_half[p1,p2] else rail_half[p2,p1]; # Interplant rail distances (kms) param impd_barg {plant} >= 0; param impd_road {plant} >= 0; # Import distances (kms) by barge and road param tran_final {pl in plant, r in region} := if road[r,pl] > 0 then .5 + .0144 * road[r,pl] else 0; param tran_import {r in region, po in port} := if road[r,po] > 0 then .5 + .0144 * road[r,po] else 0; param tran_inter {p1 in plant, p2 in plant} := if rail[p1,p2] > 0 then 3.5 + .03 * rail[p1,p2] else 0; param tran_raw {pl in plant} := (if impd_barg[pl] > 0 then 1.0 + .0030 * impd_barg[pl] else 0) + (if impd_road[pl] > 0 then 0.5 + .0144 * impd_road[pl] else 0); # Transport cost (le per ton) for: # final products, imported final products, # interplant shipment, imported raw materials param io {commod,proc}; # Input-output coefficients param util {unit,proc} >= 0; # Capacity utilization coefficients param p_imp {commod} >= 0; # Import Price (cif US$ per ton 1975) param p_r {c_raw} >= 0; param p_pr {plant,c_raw} >= 0; param p_dom {pl in plant, c in c_raw} := if p_r[c] > 0 then p_r[c] else p_pr[pl,c]; # Domestic raw material prices param dcap {plant,unit} >= 0; # Design capacity of plants (t/day) param icap {u in unit, pl in plant} := 0.33 * dcap[pl,u]; # Initial capacity of plants (t/day) param exch := 0.4; # Exchange rate param util_pct := 0.85; # Utilization percent for initial capacity ### DERIVED SETS OF "POSSIBILITIES" ### set m_pos {pl in plant} := {u in unit: icap[u,pl] > 0}; # At each plant, set of units for which there is # initial capacity set p_cap {pl in plant} := {pr in proc: forall {u in unit: util[u,pr] > 0} u in m_pos[pl] }; # At each plant, set of processes for which # all necessary units have some initial capacity set p_except {plant} within proc; # At each plant, list of processes that are # arbitrarily ruled out set p_pos {pl in plant} := p_cap[pl] diff p_except[pl]; # At each plant, set of possible processes set cp_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] > 0}; set cc_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] < 0}; set c_pos {c in commod} := cp_pos[c] union cc_pos[c]; # For each commodity, set of plants that can # produce it (cp_pos) or consume it (cc_pos), # and their union (c_pos) ### VARIABLES ### var Z {pl in plant, p_pos[pl]} >= 0; # Z[pl,pr] is level of process pr at plant pl var Xf {c in c_final, cp_pos[c], region} >= 0; # Xf[c,pl,r] is amount of final product c # shipped from plant pl to region r var Xi {c in c_ship, cp_pos[c], cc_pos[c]} >= 0; # Xi[c,p1,p2] is amount of intermediate c # shipped from plant p1 to plant p2 var Vf {c_final,region,port} >= 0; # Vf[c,r,po] is amount of final product c # imported by region r from port po var Vr {c in c_raw, cc_pos[c]} >= 0; # Vr[c,pl] is amount of raw material c # imported for use at plant pl var U {c in c_raw, cc_pos[c]} >= 0; # U[c,pl] is amount of raw material c # purchased domestically for use at plant pl var Psip; # Domestic recurrent cost var Psil; # Transport cost var Psii; # Import cost ### OBJECTIVE ### minimize Psi: Psip + Psil + Psii; ### CONSTRAINTS ### subject to mbd {n in nutr, r in region}: sum {c in c_final} fn[c,n] * (sum {po in port} Vf[c,r,po] + sum {pl in cp_pos[c]} Xf[c,pl,r]) >= cn75[r,n]; # Total nutrients supplied to a region by all # final products (sum of imports plus internal # shipments from plants) must meet requirements subject to mbdb {c in c_final, r in region: cf75[r,c] > 0}: sum {po in port} Vf[c,r,po] + sum {pl in cp_pos[c]} Xf[c,pl,r] >= cf75[r,c]; # Total of each final product supplied to each # region (as in previous constraint) must meet # requirements subject to mb {c in commod, pl in plant}: sum {pr in p_pos[pl]} io[c,pr] * Z[pl,pr] + ( if c in c_ship then ( if pl in cp_pos[c] then sum {p2 in cc_pos[c]} Xi[c,pl,p2] ) - ( if pl in cc_pos[c] then sum {p2 in cp_pos[c]} Xi[c,p2,pl] )) + ( if (c in c_raw and pl in cc_pos[c]) then (( if p_imp[c] > 0 then Vr[c,pl] ) + ( if p_dom[pl,c] > 0 then U[c,pl] ))) >= if (c in c_final and pl in cp_pos[c]) then sum {r in region} Xf[c,pl,r]; # For each commodity at each plant: sum of # (1) production or consumption at plant, # (2) inter-plant shipments in or out, # (3) import and domestic purchases (raw only) # is >= 0 for raw materials and intermediates; # is >= the total shipped for final products subject to cc {pl in plant, u in m_pos[pl]}: sum {pr in p_pos[pl]} util[u,pr] * Z[pl,pr] <= util_pct * icap[u,pl]; # For each productive unit at each plant, # total utilization by all processes # may not exceed the unit's capacity subject to ap: Psip = sum {c in c_raw, pl in cc_pos[c]} p_dom[pl,c] * U[c,pl]; # Psip is the cost of domestic raw materials, # summed over all plants that consume them subject to al: Psil = sum {c in c_final} ( sum {pl in cp_pos[c], r in region} tran_final[pl,r] * Xf[c,pl,r] + sum {po in port, r in region} tran_import[r,po] * Vf[c,r,po] ) + sum {c in c_ship, p1 in cp_pos[c], p2 in cc_pos[c]} tran_inter[p1,p2] * Xi[c,p1,p2] + sum {c in c_raw, pl in cc_pos[c]: p_imp[c] > 0} tran_raw[pl] * Vr[c,pl]; # Total transport cost is sum of shipping costs for # (1) all final products from all plants, # (2) all imports of final products, # (3) all intermediates shipped between plants, # (4) all imports of raw materials subject to ai: Psii / exch = sum {c in c_final, r in region, po in port} p_imp[c] * Vf[c,r,po] + sum {c in c_raw, pl in cc_pos[c]} p_imp[c] * Vr[c,pl]; # Total import cost -- at exchange rate -- # is sum of import costs for final products # in each region and raw materials at each plant ### DATA ### data; set center := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ABU_KIR TALKHA SUEZ ; set port := ABU_KIR ; set plant := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ; set region := ALEXANDRIA BEHERA GHARBIA KAFR_EL_SH DAKAHLIA DAMIETTA SHARKIA ISMAILIA SUEZ MENOUFIA KALUBIA GIZA BENI_SUEF FAYOUM MINIA ASSIOUT NEW_VALLEY SOHAG QUENA ASWAN ; set unit := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS C_AMM_NITR AMM_SULF SSP ; set proc := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS CAN_310 CAN_335 AMM_SULF SSP_155 ; set nutr := N P205 ; set c_final := UREA CAN_260 CAN_310 CAN_335 AMM_SULF DAP SSP_155 C_250_55 C_300_100 ; set c_inter := AMMONIA NITR_ACID SULF_ACID ; set c_ship := AMMONIA SULF_ACID ; set c_raw := EL_ASWAN COKE_GAS PHOS_ROCK LIMESTONE EL_SULFUR PYRITES ELECTRIC BF_GAS WATER STEAM BAGS ; set p_except[ASWAN] := CAN_335 ; set p_except[HELWAN] := CAN_310 ; set p_except[ASSIOUT] := ; set p_except[KAFR_EL_ZT] := ; set p_except[ABU_ZAABAL] := ; param cf75 default 0.0 : CAN_260 CAN_310 CAN_335 AMM_SULF UREA := ALEXANDRIA . . 5.0 3.0 1.0 ASSIOUT 1.0 20.0 26.0 1.0 27.0 ASWAN . 40.0 . . . BEHERA 1.0 . 25.0 90.0 35.0 BENI_SUEF 1.0 . 15.0 1.0 20.0 DAKAHLIA 1.0 . 26.0 60.0 20.0 DAMIETTA . . 2.0 15.0 8.0 FAYOUM 1.0 . 20.0 6.0 20.0 GHARBIA . . 17.0 60.0 28.0 GIZA . . 40.0 6.0 2.0 ISMAILIA . . 4.0 6.0 2.0 KAFR_EL_SH 1.0 . 10.0 45.0 22.0 KALUBIA . . 25.0 16.0 7.0 MENOUFIA 1.0 . 24.0 21.0 30.0 MINIA 2.0 15.0 35.0 1.0 41.0 NEW_VALLEY . . . . 1.0 QUENA . 95.0 2.0 . 3.0 SHARKIA 1.0 . 31.0 50.0 28.0 SOHAG . 65.0 3.0 . 7.0 SUEZ . . 1.0 . . : SSP_155 C_250_55 C_300_100 DAP := ALEXANDRIA 8.0 . . . ASSIOUT 35.0 5.0 .1 . ASWAN 8.0 . . . BEHERA 64.0 1.0 .1 .1 BENI_SUEF 13.0 3.0 . . DAKAHLIA 52.0 1.0 . . DAMIETTA 5.0 . . . FAYOUM 17.0 1.0 . . GHARBIA 57.0 1.0 .2 .1 GIZA 14.0 1.0 .1 . ISMAILIA 4.0 . . . KAFR_EL_SH 25.0 2.0 .1 . KALUBIA 22.0 1.0 . .1 MENOUFIA 33.0 2.0 .1 .1 MINIA 50.0 3.0 .2 .1 NEW_VALLEY 1.0 . . . QUENA 8.0 . . . SHARKIA 43.0 1.0 .1 . SOHAG 20.0 1.0 . . SUEZ 1.0 . . . ; param fn default 0.0 : N P205 := AMM_SULF .206 . CAN_260 .26 . CAN_310 .31 . CAN_335 .335 . C_250_55 .25 .055 C_300_100 .30 .10 DAP .18 .46 SSP_155 . .15 UREA .46 . ; param road default 0.0 : ABU_KIR ABU_ZAABAL ASSIOUT ASWAN HELWAN KAFR_EL_ZT SUEZ TALKHA := ALEXANDRIA 16 210 607 1135 244 119 362 187 ASSIOUT 616 420 . 518 362 504 527 518 ASWAN 1134 938 518 . 880 1022 1045 1036 BEHERA 76 50 547 1065 184 42 288 120 BENI_SUEF 359 163 257 775 105 248 270 261 DAKAHLIA 208 138 515 1033 152 58 219 3 DAMIETTA 267 216 596 1114 233 131 286 66 FAYOUM 341 145 308 826 88 230 252 243 GHARBIA 150 65 485 1003 122 20 226 55 GIZA 287 48 372 890 .9 133 169 146 ISMAILIA 365 142 536 1054 173 241 89 146 KAFR_EL_SH 145 105 525 1043 162 20 266 35 KALUBIA 190 97 439 957 76 66 180 81 MENOUFIA 157 154 472 990 109 33 213 90 MINIA 384 288 132 650 230 372 394 386 NEW_VALLEY 815 619 199 519 561 703 726 717 QUENA 858 662 242 276 604 746 769 760 SHARKIA 240 60 473 991 110 78 214 58 SOHAG 715 519 99 419 461 603 626 617 SUEZ 370 224 541 1059 178 246 . 298 ; param rail_half default 0 : KAFR_EL_ZT ABU_ZAABAL HELWAN ASSIOUT := ABU_ZAABAL 85 . . . HELWAN 142 57 . . ASSIOUT 504 420 362 . ASWAN 1022 938 880 518 ; param : impd_barg impd_road := ABU_ZAABAL 210 .1 ASSIOUT 583 0 ASWAN 1087 10 HELWAN 183 0 KAFR_EL_ZT 104 6 ; param io default 0.0 := [*,AMM_C_GAS] AMMONIA 1.0 BF_GAS -609. COKE_GAS -2.0 ELECTRIC -1960. STEAM -4. WATER -700. [*,AMM_ELEC] AMMONIA 1.0 EL_ASWAN -12.0 [*,AMM_SULF] AMMONIA -.26 AMM_SULF 1.0 BAGS -22. ELECTRIC -19. SULF_ACID -.76 WATER -17. [*,CAN_310] AMMONIA -.20 BAGS -23. CAN_310 1.0 LIMESTONE -.12 NITR_ACID -.71 STEAM -.4 WATER -49. [*,CAN_335] AMMONIA -.21 BAGS -23. CAN_335 1.0 LIMESTONE -.04 NITR_ACID -.76 STEAM -.4 WATER -49. [*,NITR_ACID] AMMONIA -.292 ELECTRIC -231. NITR_ACID 1.0 WATER -.6 [*,SSP_155] BAGS -22. ELECTRIC -14. PHOS_ROCK -.62 SSP_155 1.0 SULF_ACID -.41 WATER -6. [*,SULF_A_P] ELECTRIC -75. PYRITES -.826 SULF_ACID 1.0 WATER -60. [*,SULF_A_S] ELECTRIC -50. EL_SULFUR -.334 SULF_ACID 1.0 WATER -20. ; param util default 0 := [*,*] SULF_A_S SULF_A_S 1 SULF_A_P SULF_A_P 1 NITR_ACID NITR_ACID 1 AMM_ELEC AMM_ELEC 1 AMM_C_GAS AMM_C_GAS 1 SSP SSP_155 1 C_AMM_NITR CAN_310 1 C_AMM_NITR CAN_335 1 AMM_SULF AMM_SULF 1 ; param p_imp default 0.0 := PYRITES 17.5 AMM_SULF 75. EL_SULFUR 55. DAP 175. UREA 150. SSP_155 80. CAN_260 75. C_250_55 100. CAN_310 90. C_300_100 130. CAN_335 100. ; param p_r default 0.0 := ELECTRIC .007 BF_GAS .007 WATER .031 STEAM 1.25 BAGS .28 ; param p_pr default 0.0 := [HELWAN,COKE_GAS] 16.0 [ASWAN,EL_ASWAN] 1.0 [*,LIMESTONE] ASWAN 1.2 HELWAN 1.2 [*,PHOS_ROCK] ABU_ZAABAL 4.0 ASSIOUT 3.5 KAFR_EL_ZT 5.0 ; param dcap default 0.0 := [ABU_ZAABAL,*] SSP 600 SULF_A_P 227 SULF_A_S 242 [ASSIOUT,*] SSP 600 SULF_A_S 250 [ASWAN,*] AMM_ELEC 450 C_AMM_NITR 1100 NITR_ACID 800 [HELWAN,*] AMM_C_GAS 172 AMM_SULF 24 C_AMM_NITR 364 NITR_ACID 282 [KAFR_EL_ZT,*] SSP 600 SULF_A_P 50 SULF_A_S 200 ; end; glpk-4.52.1/examples/fctp.mod0000644000062000006210000000625112175147600015200 0ustar maomkpasswd/* FCTP, Fixed-Charge Transportation Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Fixed-Charge Transportation Problem (FCTP) is obtained from classical transportation problem by imposing a fixed cost on each transportation link if there is a positive flow on that link. */ param m, integer, > 0; /* number of sources */ param n, integer, > 0; /* number of customers */ set I := 1..m; /* set of sources */ set J := 1..n; /* set of customers */ param supply{i in I}, >= 0; /* supply at source i */ param demand{j in J}, >= 0; /* demand at customer j */ param varcost{i in I, j in J}, >= 0; /* variable cost (a cost per one unit shipped from i to j) */ param fixcost{i in I, j in J}, >= 0; /* fixed cost (a cost for shipping any amount from i to j) */ var x{i in I, j in J}, >= 0; /* amount shipped from source i to customer j */ s.t. f{i in I}: sum{j in J} x[i,j] = supply[i]; /* observe supply at source i */ s.t. g{j in J}: sum{i in I} x[i,j] = demand[j]; /* satisfy demand at customer j */ var y{i in I, j in J}, binary; /* y[i,j] = 1 means some amount is shipped from i to j */ s.t. h{i in I, j in J}: x[i,j] <= min(supply[i], demand[j]) * y[i,j]; /* if y[i,j] is 0, force x[i,j] to be 0 (may note that supply[i] and demand[j] are implicit upper bounds for x[i,j] as follows from the constraints f[i] and g[j]) */ minimize cost: sum{i in I, j in J} varcost[i,j] * x[i,j] + sum{i in I, j in J} fixcost[i,j] * y[i,j]; /* total transportation costs */ data; /* These data correspond to the instance bal8x12 from [Balinski]. */ /* The optimal solution is 471.55 */ param m := 8; param n := 12; param supply := 1 15.00, 2 20.00, 3 45.00, 4 35.00, 5 25.00, 6 35.00, 7 10.00, 8 25.00; param demand := 1 20.00, 2 15.00, 3 20.00, 4 15.00, 5 5.00, 6 20.00, 7 30.00, 8 10.00, 9 35.00, 10 25.00, 11 10.00, 12 5.00; param varcost : 1 2 3 4 5 6 7 8 9 10 11 12 := 1 0.69 0.64 0.71 0.79 1.70 2.83 2.02 5.64 5.94 5.94 5.94 7.68 2 1.01 0.75 0.88 0.59 1.50 2.63 2.26 5.64 5.85 5.62 5.85 4.94 3 1.05 1.06 1.08 0.64 1.22 2.37 1.66 5.64 5.91 5.62 5.91 4.94 4 1.94 1.50 1.56 1.22 1.98 1.98 1.36 6.99 6.99 6.99 6.99 3.68 5 1.61 1.40 1.61 1.33 1.68 2.83 1.54 4.26 4.26 4.26 4.26 2.99 6 5.29 5.94 6.08 5.29 5.96 6.77 5.08 0.31 0.21 0.17 0.31 1.53 7 5.29 5.94 6.08 5.29 5.96 6.77 5.08 0.55 0.35 0.40 0.19 1.53 8 5.29 6.08 6.08 5.29 5.96 6.45 5.08 2.43 2.30 2.33 1.81 2.50 ; param fixcost : 1 2 3 4 5 6 7 8 9 10 11 12 := 1 11.0 16.0 18.0 17.0 10.0 20.0 17.0 13.0 15.0 12.0 14.0 14.0 2 14.0 17.0 17.0 13.0 15.0 13.0 16.0 11.0 20.0 11.0 15.0 10.0 3 12.0 13.0 20.0 17.0 13.0 15.0 16.0 13.0 12.0 13.0 10.0 18.0 4 16.0 19.0 16.0 11.0 15.0 12.0 18.0 12.0 18.0 13.0 13.0 14.0 5 19.0 18.0 15.0 16.0 12.0 14.0 20.0 19.0 11.0 17.0 16.0 18.0 6 13.0 20.0 20.0 17.0 15.0 12.0 14.0 11.0 12.0 19.0 15.0 16.0 7 11.0 12.0 15.0 10.0 17.0 11.0 11.0 16.0 10.0 18.0 17.0 12.0 8 17.0 10.0 20.0 12.0 17.0 20.0 16.0 15.0 10.0 12.0 16.0 18.0 ; end; glpk-4.52.1/examples/food.mod0000644000062000006210000000647212175147600015200 0ustar maomkpasswd/* Food Manufacture 1, section 12.1 in * Williams, "Model Building in Mathematical Programming" * * Sebastian Nowozin */ set oils; set month; /* Buying prices of the raw oils in the next six month. */ param buyingprices{month,oils}; /* Actual amount bought in each month. */ var buys{month,oils} >= 0; /* Stock for each oil. */ var stock{month,oils} >= 0; /* Price of the produced product */ param productprice >= 0; param storagecost; param oilhardness{oils} >= 0; /* Actual amount of output oil produced in each month */ var production{m in month} >= 0; var useoil{m in month, o in oils} >= 0; maximize totalprofit: sum{m in month} productprice*production[m] - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] - sum{m in month, o in oils} storagecost*stock[m,o]; /* Constraints */ /* 1. Starting stock */ s.t. startstock{o in oils}: stock[1,o] = 500; s.t. endstock{o in oils}: stock[6,o] + buys[6,o] - useoil[6,o] >= 500; /* 2. Stock constraints */ s.t. stocklimit{m in month, o in oils}: stock[m,o] <= 1000; s.t. production1{m in month, o in oils}: useoil[m,o] <= stock[m,o] + buys[m,o]; s.t. production2{m1 in month, m2 in month, o in oils : m2 = m1+1}: stock[m2,o] = stock[m1,o] + buys[m1,o] - useoil[m1,o]; s.t. production3a{m in month}: sum{o in oils} oilhardness[o]*useoil[m,o] >= 3*production[m]; s.t. production3b{m in month}: sum{o in oils} oilhardness[o]*useoil[m,o] <= 6*production[m]; s.t. production4{m in month}: production[m] = sum{o in oils} useoil[m,o]; /* 3. Refining constraints */ s.t. refine1{m in month}: useoil[m,"VEG1"]+useoil[m,"VEG2"] <= 200; s.t. refine2{m in month}: useoil[m,"OIL1"]+useoil[m,"OIL2"]+useoil[m,"OIL3"] <= 250; solve; for {m in month} { printf "Month %d\n", m; printf "PRODUCE %4.2f tons, hardness %4.2f\n", production[m], (sum{o in oils} oilhardness[o]*useoil[m,o]) / (sum{o in oils} useoil[m,o]); printf "\tVEG1\tVEG2\tOIL1\tOIL2\tOIL3\n"; printf "STOCK"; printf "%d", m; for {o in oils} { printf "\t%4.2f", stock[m,o]; } printf "\nBUY"; for {o in oils} { printf "\t%4.2f", buys[m,o]; } printf "\nUSE"; printf "%d", m; for {o in oils} { printf "\t%4.2f", useoil[m,o]; } printf "\n"; printf "\n"; } printf "Total profit: %4.2f\n", (sum{m in month} productprice*production[m] - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] - sum{m in month, o in oils} storagecost*stock[m,o]); printf " turnover: %4.2f\n", sum{m in month} productprice*production[m]; printf " buying costs: %4.2f\n", sum{m in month, o in oils} buyingprices[m,o]*buys[m,o]; printf " storage costs: %4.2f\n", sum{m in month, o in oils} storagecost*stock[m,o]; data; param : oils : oilhardness := VEG1 8.8 VEG2 6.1 OIL1 2.0 OIL2 4.2 OIL3 5.0 ; set month := 1 2 3 4 5 6; param buyingprices : VEG1 VEG2 OIL1 OIL2 OIL3 := 1 110 120 130 110 115 2 130 130 110 90 115 3 110 140 130 100 95 4 120 110 120 120 125 5 100 120 150 110 105 6 90 100 140 80 135 ; param productprice := 150; param storagecost := 5; end; glpk-4.52.1/examples/food2.mod0000644000062000006210000001000212175147600015242 0ustar maomkpasswd/* Food Manufacture 2, section 12.2 in * Williams, "Model Building in Mathematical Programming" * * Sebastian Nowozin */ set oils; set month; /* Buying prices of the raw oils in the next six month. */ param buyingprices{month,oils}; /* Actual amount bought in each month. */ var buys{month,oils} >= 0; /* Stock for each oil. */ var stock{month,oils} >= 0; /* Price of the produced product */ param productprice >= 0; param storagecost; param oilhardness{oils} >= 0; param M >= 0; /* Actual amount of output oil produced in each month */ var production{m in month} >= 0; var useoil{m in month, o in oils} >= 0, <= M; var useoilb{m in month, o in oils}, binary; maximize totalprofit: sum{m in month} productprice*production[m] - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] - sum{m in month, o in oils} storagecost*stock[m,o]; /* Constraints */ /* 1. Starting stock */ s.t. startstock{o in oils}: stock[1,o] = 500; s.t. endstock{o in oils}: stock[6,o] + buys[6,o] - useoil[6,o] >= 500; /* 2. Stock constraints */ s.t. stocklimit{m in month, o in oils}: stock[m,o] <= 1000; s.t. production1{m in month, o in oils}: useoil[m,o] <= stock[m,o] + buys[m,o]; s.t. production2{m1 in month, m2 in month, o in oils : m2 = m1+1}: stock[m2,o] = stock[m1,o] + buys[m1,o] - useoil[m1,o]; s.t. production3a{m in month}: sum{o in oils} oilhardness[o]*useoil[m,o] >= 3*production[m]; s.t. production3b{m in month}: sum{o in oils} oilhardness[o]*useoil[m,o] <= 6*production[m]; s.t. production4{m in month}: production[m] = sum{o in oils} useoil[m,o]; /* 3. Refining constraints */ s.t. refine1{m in month}: useoil[m,"VEG1"]+useoil[m,"VEG2"] <= 200; s.t. refine2{m in month}: useoil[m,"OIL1"]+useoil[m,"OIL2"]+useoil[m,"OIL3"] <= 250; /* 4. Additional conditions: * i) The food may never be made up of more than three oils every month */ s.t. useoilb_calc{m in month, o in oils}: M*useoilb[m,o] >= useoil[m,o]; s.t. useoilb_limit{m in month}: sum{o in oils} useoilb[m,o] <= 3; /* ii) If an oil is used in a month, at least 20 tons must be used. */ s.t. useminimum{m in month, o in oils}: 20*useoilb[m,o] <= useoil[m,o]; /* iii) If either of VEG1 or VEG2 is used in a month, OIL2 must also be used */ s.t. use_oil2a{m in month}: useoilb[m,"VEG1"] <= useoilb[m,"OIL3"]; s.t. use_oil2b{m in month}: useoilb[m,"VEG2"] <= useoilb[m,"OIL3"]; solve; for {m in month} { printf "Month %d\n", m; printf "PRODUCE %4.2f tons, hardness %4.2f\n", production[m], (sum{o in oils} oilhardness[o]*useoil[m,o]) / (sum{o in oils} useoil[m,o]); printf "\tVEG1\tVEG2\tOIL1\tOIL2\tOIL3\n"; printf "STOCK"; printf "%d", m; for {o in oils} { printf "\t%4.2f", stock[m,o]; } printf "\nBUY"; for {o in oils} { printf "\t%4.2f", buys[m,o]; } printf "\nUSE"; printf "%d", m; for {o in oils} { printf "\t%4.2f", useoil[m,o]; } printf "\n"; printf "\n"; } printf "Total profit: %4.2f\n", (sum{m in month} productprice*production[m] - sum{m in month, o in oils} buyingprices[m,o]*buys[m,o] - sum{m in month, o in oils} storagecost*stock[m,o]); printf " turnover: %4.2f\n", sum{m in month} productprice*production[m]; printf " buying costs: %4.2f\n", sum{m in month, o in oils} buyingprices[m,o]*buys[m,o]; printf " storage costs: %4.2f\n", sum{m in month, o in oils} storagecost*stock[m,o]; data; param : oils : oilhardness := VEG1 8.8 VEG2 6.1 OIL1 2.0 OIL2 4.2 OIL3 5.0 ; set month := 1 2 3 4 5 6; param buyingprices : VEG1 VEG2 OIL1 OIL2 OIL3 := 1 110 120 130 110 115 2 130 130 110 90 115 3 110 140 130 100 95 4 120 110 120 120 125 5 100 120 150 110 105 6 90 100 140 80 135 ; param productprice := 150; param storagecost := 5; param M := 1000; end; glpk-4.52.1/examples/gap.mod0000644000062000006210000000475712175147600015024 0ustar maomkpasswd/* GAP, Generalized Assignment Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Generalized Assignment Problem (GAP) is to assign a set of jobs to a set of agents subject to the constraints that each job must be assigned exactly to one agent and the total resources consumed by all jobs assigned to an agent must not exceed the agent's capacity. */ param m, integer, > 0; /* number of agents */ param n, integer, > 0; /* number of jobs */ set I := 1..m; /* set of agents */ set J := 1..n; /* set of jobs */ param a{i in I, j in J}, >= 0; /* resource consumed in allocating job j to agent i */ param b{i in I}, >= 0; /* resource capacity of agent i */ param c{i in I, j in J}, >= 0; /* cost of allocating job j to agent i */ var x{i in I, j in J}, binary; /* x[i,j] = 1 means job j is assigned to agent i */ s.t. one{j in J}: sum{i in I} x[i,j] = 1; /* job j must be assigned exactly to one agent */ s.t. lim{i in I}: sum{j in J} a[i,j] * x[i,j] <= b[i]; /* total amount of resources consumed by all jobs assigned to agent i must not exceed the agent's capacity */ minimize obj: sum{i in I, j in J} c[i,j] * x[i,j]; /* the objective is to find cheapest assignment (note that gap can also be formulated as maximization problem) */ data; /* These data correspond to the instance c515-1 (gap1) from: I.H. Osman, "Heuristics for the Generalised Assignment Problem: Simulated Annealing and Tabu Search Approaches", OR Spektrum, Volume 17, 211-225, 1995 D. Cattrysse, M. Salomon and L.N. Van Wassenhove, "A set partitioning heuristic for the generalized assignment problem", European Journal of Operational Research, Volume 72, 167-174, 1994 */ /* The optimal solution is 261 (minimization) or 336 (maximization) */ param m := 5; param n := 15; param a : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 := 1 8 15 14 23 8 16 8 25 9 17 25 15 10 8 24 2 15 7 23 22 11 11 12 10 17 16 7 16 10 18 22 3 21 20 6 22 24 10 24 9 21 14 11 14 11 19 16 4 20 11 8 14 9 5 6 19 19 7 6 6 13 9 18 5 8 13 13 13 10 20 25 16 16 17 10 10 5 12 23 ; param b := 1 36, 2 34, 3 38, 4 27, 5 33; param c : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 := 1 17 21 22 18 24 15 20 18 19 18 16 22 24 24 16 2 23 16 21 16 17 16 19 25 18 21 17 15 25 17 24 3 16 20 16 25 24 16 17 19 19 18 20 16 17 21 24 4 19 19 22 22 20 16 19 17 21 19 25 23 25 25 25 5 18 19 15 15 21 25 16 16 23 15 22 17 19 22 24 ; end; glpk-4.52.1/examples/glpsol.c0000644000062000006210000000024012175147600015177 0ustar maomkpasswd/* glpsol.c */ #include int main(int argc, const char *argv[]) { /* stand-alone LP/MIP solver */ return glp_main(argc, argv); } /* eof */ glpk-4.52.1/examples/graph.mod0000644000062000006210000000450712175147600015347 0ustar maomkpasswd/* graph.mod - graph visualization */ /* Written in GNU MathProg by Andrew Makhorin */ /* This model creates a picture in EPS format to visualize a graph. */ param file, symbolic, default "graph.eps"; /* output file to write the picture */ param R, default 2; /* radius to draw vertices, in mm */ param n, integer, > 0; /* number of vertices */ set V, default 1..n; /* set of vertices */ set E, within V cross V; /* set of edges */ param x{i in V}, default 50 * cos((i - 1) / card(V) * 8 * atan(1)); param y{i in V}, default 50 * sin((i - 1) / card(V) * 8 * atan(1)); /* x[i] and y[i] are coordinates of node i, in mm */ param x0 := (min{i in V} x[i]) - R - 3.0; param y0 := (min{i in V} y[i]) - R - 3.0; param x1 := (max{i in V} x[i]) + R + 3.0; param y1 := (max{i in V} y[i]) + R + 3.0; printf "%%!PS-Adobe-3.0 EPSF-3.0\n" > file; printf "%%%%BoundingBox: 0 0 %d %d\n", (72 / 25.4) * (x1 - x0), (72 / 25.4) * (y1 - y0) >> file; printf "/Helvetica findfont 6 scalefont setfont\n" >> file; printf "/mm { 72 mul 25.4 div } def\n" >> file; for {(i,j) in E} { printf "newpath\n" >> file; printf "%g mm %g mm moveto\n", x[i] - x0, y[i] - y0 >> file; printf "%g mm %g mm lineto\n", x[j] - x0, y[j] - y0 >> file; printf "closepath\n" >> file; printf "stroke\n" >> file; } for {i in V} { printf "newpath\n" >> file; printf "%g mm %g mm %g mm 0 360 arc\n", x[i] - x0, y[i] - y0, R >> file; printf "closepath\n" >> file; printf "gsave 1 1 1 setrgbcolor fill grestore\n" >> file; printf "stroke\n" >> file; printf "%g mm %g mm moveto\n", x[i] - (if i <= 9 then 1.2 else 1.8) - x0, y[i] - 0.8 - y0 >> file; printf "( %d ) show\n", i >> file; } printf "showpage\n" >> file; printf "%%%%EOF\n" >> file; data; param : V : x y := 1 0 40 2 38 12 3 24 -32 4 -24 -32 5 -38 12 6 -19 26 7 19 26 8 31 -10 9 0 -32 10 -31 -10 11 -9 12 12 9 12 13 14 -5 14 0 -15 15 -14 -5 16 0 0 ; set E := (1,*) 6 10 16 12 7 (2,*) 7 6 16 13 8 (3,*) 8 7 16 14 9 (4,*) 9 8 16 15 10 (5,*) 10 9 16 11 6 (6,*) 14 (7,*) 15 (8,*) 11 (9,*) 12 (10,*) 13 (11,*) 12 15 (12,*) 13 (13,*) 14 (14,*) 15 ; end; glpk-4.52.1/examples/hashi.mod0000644000062000006210000001703712175147600015344 0ustar maomkpasswd/* A solver for the Japanese number-puzzle Hashiwokakero * (http://en.wikipedia.org/wiki/Hashiwokakero) * * Sebastian Nowozin , 13th January 2009 */ param n := 25; set rows := 1..n; set cols := 1..n; param givens{rows, cols}, integer, >= 0, <= 8, default 0; /* Set of vertices as (row,col) coordinates */ set V := { (i,j) in { rows, cols }: givens[i,j] != 0 }; /* Set of feasible horizontal edges from (i,j) to (k,l) rightwards */ set Eh := { (i,j,k,l) in { V, V }: i = k and j < l and # Same row and left to right card({ (s,t) in V: s = i and t > j and t < l }) = 0 # No vertex inbetween }; /* Set of feasible vertical edges from (i,j) to (k,l) downwards */ set Ev := { (i,j,k,l) in { V, V }: j = l and i < k and # Same column and top to bottom card({ (s,t) in V: t = j and s > i and s < k }) = 0 # No vertex inbetween }; set E := Eh union Ev; /* Indicators: use edge once/twice */ var xe1{E}, binary; var xe2{E}, binary; /* Constraint: Do not use edge or do use once or do use twice */ s.t. edge_sel{(i,j,k,l) in E}: xe1[i,j,k,l] + xe2[i,j,k,l] <= 1; /* Constraint: There must be as many edges used as the node value */ s.t. satisfy_vertex_demand{(s,t) in V}: sum{(i,j,k,l) in E: (i = s and j = t) or (k = s and l = t)} (xe1[i,j,k,l] + 2.0*xe2[i,j,k,l]) = givens[s,t]; /* Constraint: No crossings */ s.t. no_crossing1{(i,j,k,l) in Eh, (s,t,u,v) in Ev: s < i and u > i and j < t and l > t}: xe1[i,j,k,l] + xe1[s,t,u,v] <= 1; s.t. no_crossing2{(i,j,k,l) in Eh, (s,t,u,v) in Ev: s < i and u > i and j < t and l > t}: xe1[i,j,k,l] + xe2[s,t,u,v] <= 1; s.t. no_crossing3{(i,j,k,l) in Eh, (s,t,u,v) in Ev: s < i and u > i and j < t and l > t}: xe2[i,j,k,l] + xe1[s,t,u,v] <= 1; s.t. no_crossing4{(i,j,k,l) in Eh, (s,t,u,v) in Ev: s < i and u > i and j < t and l > t}: xe2[i,j,k,l] + xe2[s,t,u,v] <= 1; /* Model connectivity by auxiliary network flow problem: * One vertex becomes a target node and all other vertices send a unit flow * to it. The edge selection variables xe1/xe2 are VUB constraints and * therefore xe1/xe2 select the feasible graph for the max-flow problems. */ set node_target := { (s,t) in V: card({ (i,j) in V: i < s or (i = s and j < t) }) = 0}; set node_sources := { (s,t) in V: (s,t) not in node_target }; var flow_forward{ E }, >= 0; var flow_backward{ E }, >= 0; s.t. flow_conservation{ (s,t) in node_target, (p,q) in V }: /* All incoming flows */ - sum{(i,j,k,l) in E: k = p and l = q} flow_forward[i,j,k,l] - sum{(i,j,k,l) in E: i = p and j = q} flow_backward[i,j,k,l] /* All outgoing flows */ + sum{(i,j,k,l) in E: k = p and l = q} flow_backward[i,j,k,l] + sum{(i,j,k,l) in E: i = p and j = q} flow_forward[i,j,k,l] = 0 + (if (p = s and q = t) then card(node_sources) else -1); /* Variable-Upper-Bound (VUB) constraints: xe1/xe2 bound the flows. */ s.t. connectivity_vub1{(i,j,k,l) in E}: flow_forward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]); s.t. connectivity_vub2{(i,j,k,l) in E}: flow_backward[i,j,k,l] <= card(node_sources)*(xe1[i,j,k,l] + xe2[i,j,k,l]); /* A feasible solution is enough */ minimize cost: 0; solve; /* Output solution graphically */ printf "\nSolution:\n"; for { row in rows } { for { col in cols } { /* First print this cell information: givens or space */ printf{0..0: givens[row,col] != 0} "%d", givens[row,col]; printf{0..0: givens[row,col] = 0 and card({(i,j,k,l) in Eh: i = row and col >= j and col < l and xe1[i,j,k,l] = 1}) = 1} "-"; printf{0..0: givens[row,col] = 0 and card({(i,j,k,l) in Eh: i = row and col >= j and col < l and xe2[i,j,k,l] = 1}) = 1} "="; printf{0..0: givens[row,col] = 0 and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and xe1[i,j,k,l] = 1}) = 1} "|"; printf{0..0: givens[row,col] = 0 and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and xe2[i,j,k,l] = 1}) = 1} '"'; printf{0..0: givens[row,col] = 0 and card({(i,j,k,l) in Eh: i = row and col >= j and col < l and (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0 and card({(i,j,k,l) in Ev: j = col and row >= i and row < k and (xe1[i,j,k,l] = 1 or xe2[i,j,k,l] = 1)}) = 0} " "; /* Now print any edges */ printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe1[i,j,k,l] = 1} "-"; printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe2[i,j,k,l] = 1} "="; printf{(i,j,k,l) in Eh: i = row and col >= j and col < l and xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " "; printf{0..0: card({(i,j,k,l) in Eh: i = row and col >= j and col < l}) = 0} " "; } printf "\n"; for { col in cols } { printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe1[i,j,k,l] = 1} "|"; printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe2[i,j,k,l] = 1} '"'; printf{(i,j,k,l) in Ev: j = col and row >= i and row < k and xe1[i,j,k,l] = 0 and xe2[i,j,k,l] = 0} " "; /* No vertical edges: skip also a field */ printf{0..0: card({(i,j,k,l) in Ev: j = col and row >= i and row < k}) = 0} " "; printf " "; } printf "\n"; } data; /* This is a difficult 25x25 Hashiwokakero. */ param givens : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 := 1 2 . 2 . 2 . . 2 . 2 . . 2 . . . . 2 . 2 . 2 . 2 . 2 . 1 . . . . 2 . . . 4 . . 5 . 2 . . 1 . 2 . 2 . 1 3 2 . . 5 . 4 . . 3 . . . . . 1 . . 4 . 5 . 1 . 1 . 4 . . . . . . . . . . . 1 . 3 . . 1 . . . . . . . . 5 2 . . 6 . 6 . . 8 . 5 . 2 . . 3 . 5 . 7 . . 2 . . 6 . 1 . . . . . . . . . 1 . . 2 . . . . . 1 . . . 3 7 2 . . . . 5 . . 6 . 4 . . 2 . . . 2 . 5 . 4 . 2 . 8 . 2 . 2 . . . . . . . . . . . 3 . . 3 . . . 1 . 2 9 . . . . . . . . . . 4 . 2 . 2 . . 1 . . . 3 . 1 . 10 2 . 3 . . 6 . . 2 . . . . . . . . . . 3 . . . . . 11 . . . . 1 . . 2 . . 5 . . 1 . 4 . 3 . . . . 2 . 4 12 . . 2 . . 1 . . . . . . 5 . 4 . . . . 4 . 3 . . . 13 2 . . . 3 . 1 . . . . . . . . 3 . . 5 . 5 . . 2 . 14 . . . . . 2 . 5 . . 7 . 5 . 3 . 1 . . 1 . . 1 . 4 15 2 . 5 . 3 . . . . 1 . 2 . 1 . . . . 2 . 4 . . 2 . 16 . . . . . 1 . . . . . . . . . . 2 . . 2 . 1 . . 3 17 2 . 6 . 6 . . 2 . . 2 . 2 . 5 . . . . . 2 . . . . 18 . . . . . 1 . . . 3 . . . . . 1 . . 1 . . 4 . 3 . 19 . . 4 . 5 . . 2 . . . 2 . . 6 . 6 . . 3 . . . . 3 20 2 . . . . . . . . . 2 . . 1 . . . . . . 1 . . 1 . 21 . . 3 . . 3 . 5 . 5 . . 4 . 6 . 7 . . 4 . 6 . . 4 22 2 . . . 3 . 5 . 2 . 1 . . . . . . . . . . . . . . 23 . . . . . . . . . 1 . . . . . . 3 . 2 . . 5 . . 5 24 2 . 3 . 3 . 5 . 4 . 3 . 3 . 4 . . 2 . 2 . . . 1 . 25 . 1 . 2 . 2 . . . 2 . 2 . . . 2 . . . . 2 . 2 . 2 ; end; glpk-4.52.1/examples/huge.mod0000644000062000006210000000104412175147600015167 0ustar maomkpasswd/*Arithmetic Mean of a large number of Integers - or - solve a very large constraint matrix over 1 million rows and columns Nigel_Galloway@operamail.com March 18th., 2008. */ param e := 20; /* set Sample := {-2**e..2**e-1}; */ set Sample := {1..2**e-1}; var Mean; var E{z in Sample}; /* sum of variances is zero */ zumVariance: sum{z in Sample} E[z] = 0; /* Mean + variance[n] = Sample[n] */ variances{z in Sample}: Mean + E[z] = z; solve; printf "The arithmetic mean of the integers from 1 to %d is %f\n", 2**e-1, Mean; end; glpk-4.52.1/examples/INDEX0000644000062000006210000000447612175147600014344 0ustar maomkpasswdassign.mod Assignment problem bpp.mod Bin packing problem cal.mod Print an ASCII calendar of the given year cf12a.mod Curve fitting problem cf12b.mod Curve fitting problem cflsq.mod Curve fitting problem by least squares color.mod Graph coloring problem cpp.mod Critical path problem crypto.mod A crypto-arithmetic puzzle dea.mod Data envelopment analysis (DEA) diet.mod Stigler's nutrition model dist.mod A product distribution model egypt.mod A static model for fertilizer production fctp.mod Fixed-charge transportation problem food.mod Food manufacture model food2.mod Food manufacture model gap.mod Generalized assignment problem graph.mod Graph visualization hashi.mod A solver for the Japanese number-puzzle Hashiwokakero huge.mod Arithmetic mean of a large number of integers jssp.mod Job-shop scheduling problem magic.mod Magic square maxcut.mod Maximum cut problem maxflow.mod Maximum flow problem mfasp.mod Minimum feedback arc set problem mfvsp.mod Minimum feedback vertex set problem min01ks.mod Finding minimal equivalent 0-1 knapsack inequality misp.mod Maximum independent set problem money.mod A crypto-arithmetic puzzle mvcp.mod Minimum vertex cover problem numbrix.mod Number placement puzzle pbn/*.* Paint-by-numbers puzzle plan.mod A simple LP problem prod.mod A multiperiod production model qfit.mod Quadratic curve fitting solution queens.mod A classic combinatorial optimization problem sat.mod Satisfiability problem shiftcover.mod Workforce shift coverage assignment problem shikaku.mod A solver for the logic puzzle Shikaku sorting.mod How to sort arrays in MathProg spp.mod Shortest path problem stigler.mod Original Stigler's 1939 diet problem sudoku.mod Number placement puzzle tas.mod Tail assignment problem todd.mod A class of hard instances of 0-1 knapsack problems train.mod A model of railroad passenger car allocation transp.mod A transportation problem trick.mod A transportation design problem tsp.mod Traveling salesman problem xyacfs.mod Extended yet another curve fitting solution yacfs.mod Yet another curve fitting solution zebra.mod Who owns the zebra? glpk-4.52.1/examples/iptsamp.c0000644000062000006210000000047512175147600015366 0ustar maomkpasswd/* iptsamp.c */ #include #include #include int main(void) { glp_prob *P; P = glp_create_prob(); glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); glp_interior(P, NULL); glp_print_ipt(P, "25fv47.txt"); glp_delete_prob(P); return 0; } /* eof */ glpk-4.52.1/examples/jssp.mod0000644000062000006210000000634112175147600015223 0ustar maomkpasswd/* JSSP, Job-Shop Scheduling Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Job-Shop Scheduling Problem (JSSP) is to schedule a set of jobs on a set of machines, subject to the constraint that each machine can handle at most one job at a time and the fact that each job has a specified processing order through the machines. The objective is to schedule the jobs so as to minimize the maximum of their completion times. Reference: D. Applegate and W. Cook, "A Computational Study of the Job-Shop Scheduling Problem", ORSA J. On Comput., Vol. 3, No. 2, Spring 1991, pp. 149-156. */ param n, integer, > 0; /* number of jobs */ param m, integer, > 0; /* number of machines */ set J := 1..n; /* set of jobs */ set M := 1..m; /* set of machines */ param sigma{j in J, t in 1..m}, in M; /* permutation of the machines, which represents the processing order of j through the machines: j must be processed first on sigma[j,1], then on sigma[j,2], etc. */ check{j in J, t1 in 1..m, t2 in 1..m: t1 <> t2}: sigma[j,t1] != sigma[j,t2]; /* sigma must be permutation */ param p{j in J, a in M}, >= 0; /* processing time of j on a */ var x{j in J, a in M}, >= 0; /* starting time of j on a */ s.t. ord{j in J, t in 2..m}: x[j, sigma[j,t]] >= x[j, sigma[j,t-1]] + p[j, sigma[j,t-1]]; /* j can be processed on sigma[j,t] only after it has been completely processed on sigma[j,t-1] */ /* The disjunctive condition that each machine can handle at most one job at a time is the following: x[i,a] >= x[j,a] + p[j,a] or x[j,a] >= x[i,a] + p[i,a] for all i, j in J, a in M. This condition is modeled through binary variables Y as shown below. */ var Y{i in J, j in J, a in M}, binary; /* Y[i,j,a] is 1 if i scheduled before j on machine a, and 0 if j is scheduled before i */ param K := sum{j in J, a in M} p[j,a]; /* some large constant */ display K; s.t. phi{i in J, j in J, a in M: i <> j}: x[i,a] >= x[j,a] + p[j,a] - K * Y[i,j,a]; /* x[i,a] >= x[j,a] + p[j,a] iff Y[i,j,a] is 0 */ s.t. psi{i in J, j in J, a in M: i <> j}: x[j,a] >= x[i,a] + p[i,a] - K * (1 - Y[i,j,a]); /* x[j,a] >= x[i,a] + p[i,a] iff Y[i,j,a] is 1 */ var z; /* so-called makespan */ s.t. fin{j in J}: z >= x[j, sigma[j,m]] + p[j, sigma[j,m]]; /* which is the maximum of the completion times of all the jobs */ minimize obj: z; /* the objective is to make z as small as possible */ data; /* These data correspond to the instance ft06 (mt06) from: H. Fisher, G.L. Thompson (1963), Probabilistic learning combinations of local job-shop scheduling rules, J.F. Muth, G.L. Thompson (eds.), Industrial Scheduling, Prentice Hall, Englewood Cliffs, New Jersey, 225-251 */ /* The optimal solution is 55 */ param n := 6; param m := 6; param sigma : 1 2 3 4 5 6 := 1 3 1 2 4 6 5 2 2 3 5 6 1 4 3 3 4 6 1 2 5 4 2 1 3 4 5 6 5 3 2 5 6 1 4 6 2 4 6 1 5 3 ; param p : 1 2 3 4 5 6 := 1 3 6 1 7 6 3 2 10 8 5 4 10 10 3 9 1 5 4 7 8 4 5 5 5 3 8 9 5 3 3 9 1 5 4 6 10 3 1 3 4 9 ; end; glpk-4.52.1/examples/magic.mod0000644000062000006210000000272612175147600015327 0ustar maomkpasswd/* MAGIC, Magic Square */ /* Written in GNU MathProg by Andrew Makhorin */ /* In recreational mathematics, a magic square of order n is an arrangement of n^2 numbers, usually distinct integers, in a square, such that n numbers in all rows, all columns, and both diagonals sum to the same constant. A normal magic square contains the integers from 1 to n^2. (From Wikipedia, the free encyclopedia.) */ param n, integer, > 0, default 4; /* square order */ set N := 1..n^2; /* integers to be placed */ var x{i in 1..n, j in 1..n, k in N}, binary; /* x[i,j,k] = 1 means that cell (i,j) contains integer k */ s.t. a{i in 1..n, j in 1..n}: sum{k in N} x[i,j,k] = 1; /* each cell must be assigned exactly one integer */ s.t. b{k in N}: sum{i in 1..n, j in 1..n} x[i,j,k] = 1; /* each integer must be assigned exactly to one cell */ var s; /* the magic sum */ s.t. r{i in 1..n}: sum{j in 1..n, k in N} k * x[i,j,k] = s; /* the sum in each row must be the magic sum */ s.t. c{j in 1..n}: sum{i in 1..n, k in N} k * x[i,j,k] = s; /* the sum in each column must be the magic sum */ s.t. d: sum{i in 1..n, k in N} k * x[i,i,k] = s; /* the sum in the diagonal must be the magic sum */ s.t. e: sum{i in 1..n, k in N} k * x[i,n-i+1,k] = s; /* the sum in the co-diagonal must be the magic sum */ solve; printf "\n"; printf "Magic sum is %d\n", s; printf "\n"; for{i in 1..n} { printf{j in 1..n} "%3d", sum{k in N} k * x[i,j,k]; printf "\n"; } printf "\n"; end; glpk-4.52.1/examples/Makefile.am0000644000062000006210000000043012175147600015570 0ustar maomkpasswd## Process this file with automake to produce Makefile.in ## AM_CPPFLAGS = -I$(srcdir)/../src LDADD = ../src/libglpk.la bin_PROGRAMS = glpsol glpsol_SOURCES = glpsol.c check: glpsol$(EXEEXT) ./glpsol$(EXEEXT) --version ./glpsol$(EXEEXT) --mps $(srcdir)/plan.mps ## eof ## glpk-4.52.1/examples/Makefile.in0000644000062000006210000004141112175147600015605 0ustar maomkpasswd# Makefile.in generated by automake 1.12.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = glpsol$(EXEEXT) subdir = examples DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_glpsol_OBJECTS = glpsol.$(OBJEXT) glpsol_OBJECTS = $(am_glpsol_OBJECTS) glpsol_LDADD = $(LDADD) glpsol_DEPENDENCIES = ../src/libglpk.la DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(glpsol_SOURCES) DIST_SOURCES = $(glpsol_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(srcdir)/../src LDADD = ../src/libglpk.la glpsol_SOURCES = glpsol.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu examples/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list glpsol$(EXEEXT): $(glpsol_OBJECTS) $(glpsol_DEPENDENCIES) $(EXTRA_glpsol_DEPENDENCIES) @rm -f glpsol$(EXEEXT) $(LINK) $(glpsol_OBJECTS) $(glpsol_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glpsol.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-binPROGRAMS check: glpsol$(EXEEXT) ./glpsol$(EXEEXT) --version ./glpsol$(EXEEXT) --mps $(srcdir)/plan.mps # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glpk-4.52.1/examples/maxcut.mod0000644000062000006210000000534012175147600015543 0ustar maomkpasswd/* MAXCUT, Maximum Cut Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Maximum Cut Problem in a network G = (V, E), where V is a set of nodes, E is a set of edges, is to find the partition of V into disjoint sets V1 and V2, which maximizes the sum of edge weights w(e), where edge e has one endpoint in V1 and other endpoint in V2. Reference: Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: A guide to the theory of NP-completeness [Network design, Cuts and Connectivity, Maximum Cut, ND16]. */ set E, dimen 2; /* set of edges */ param w{(i,j) in E}, >= 0, default 1; /* w[i,j] is weight of edge (i,j) */ set V := (setof{(i,j) in E} i) union (setof{(i,j) in E} j); /* set of nodes */ var x{i in V}, binary; /* x[i] = 0 means that node i is in set V1 x[i] = 1 means that node i is in set V2 */ /* We need to include in the objective function only that edges (i,j) from E, for which x[i] != x[j]. This can be modeled through binary variables s[i,j] as follows: s[i,j] = x[i] xor x[j] = (x[i] + x[j]) mod 2, (1) where s[i,j] = 1 iff x[i] != x[j], that leads to the following objective function: z = sum{(i,j) in E} w[i,j] * s[i,j]. (2) To describe "exclusive or" (1) we could think that s[i,j] is a minor bit of the sum x[i] + x[j]. Then introducing binary variables t[i,j], which represent a major bit of the sum x[i] + x[j], we can write: x[i] + x[j] = s[i,j] + 2 * t[i,j]. (3) An easy check shows that conditions (1) and (3) are equivalent. Note that condition (3) can be simplified by eliminating variables s[i,j]. Indeed, from (3) it follows that: s[i,j] = x[i] + x[j] - 2 * t[i,j]. (4) Since the expression in the right-hand side of (4) is integral, this condition can be rewritten in the equivalent form: 0 <= x[i] + x[j] - 2 * t[i,j] <= 1. (5) (One might note that (5) means t[i,j] = x[i] and x[j].) Substituting s[i,j] from (4) to (2) leads to the following objective function: z = sum{(i,j) in E} w[i,j] * (x[i] + x[j] - 2 * t[i,j]), (6) which does not include variables s[i,j]. */ var t{(i,j) in E}, binary; /* t[i,j] = x[i] and x[j] = (x[i] + x[j]) div 2 */ s.t. xor{(i,j) in E}: 0 <= x[i] + x[j] - 2 * t[i,j] <= 1; /* see (4) */ maximize z: sum{(i,j) in E} w[i,j] * (x[i] + x[j] - 2 * t[i,j]); /* see (6) */ data; /* In this example the network has 15 nodes and 22 edges. */ /* Optimal solution is 20 */ set E := 1 2, 1 5, 2 3, 2 6, 3 4, 3 8, 4 9, 5 6, 5 7, 6 8, 7 8, 7 12, 8 9, 8 12, 9 10, 9 14, 10 11, 10 14, 11 15, 12 13, 13 14, 14 15; end; glpk-4.52.1/examples/maxflow.mod0000644000062000006210000000372712175147600015726 0ustar maomkpasswd/* MAXFLOW, Maximum Flow Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Maximum Flow Problem in a network G = (V, E), where V is a set of nodes, E within V x V is a set of arcs, is to maximize the flow from one given node s (source) to another given node t (sink) subject to conservation of flow constraints at each node and flow capacities on each arc. */ param n, integer, >= 2; /* number of nodes */ set V, default {1..n}; /* set of nodes */ set E, within V cross V; /* set of arcs */ param a{(i,j) in E}, > 0; /* a[i,j] is capacity of arc (i,j) */ param s, symbolic, in V, default 1; /* source node */ param t, symbolic, in V, != s, default n; /* sink node */ var x{(i,j) in E}, >= 0, <= a[i,j]; /* x[i,j] is elementary flow through arc (i,j) to be found */ var flow, >= 0; /* total flow from s to t */ s.t. node{i in V}: /* node[i] is conservation constraint for node i */ sum{(j,i) in E} x[j,i] + (if i = s then flow) /* summary flow into node i through all ingoing arcs */ = /* must be equal to */ sum{(i,j) in E} x[i,j] + (if i = t then flow); /* summary flow from node i through all outgoing arcs */ maximize obj: flow; /* objective is to maximize the total flow through the network */ solve; printf{1..56} "="; printf "\n"; printf "Maximum flow from node %s to node %s is %g\n\n", s, t, flow; printf "Starting node Ending node Arc capacity Flow in arc\n"; printf "------------- ----------- ------------ -----------\n"; printf{(i,j) in E: x[i,j] != 0}: "%13s %11s %12g %11g\n", i, j, a[i,j], x[i,j]; printf{1..56} "="; printf "\n"; data; /* These data correspond to an example from [Christofides]. */ /* Optimal solution is 29 */ param n := 9; param : E : a := 1 2 14 1 4 23 2 3 10 2 4 9 3 5 12 3 8 18 4 5 26 5 2 11 5 6 25 5 7 4 6 7 7 6 8 8 7 9 15 8 9 20; end; glpk-4.52.1/examples/mfasp.mod0000644000062000006210000000356112175147600015353 0ustar maomkpasswd/* MFASP, Minimum Feedback Arc Set Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Minimum Feedback Arc Set Problem for a given directed graph G = (V, E), where V is a set of vertices and E is a set of arcs, is to find a minimal subset of arcs, which being removed from the graph make it acyclic. Reference: Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: A guide to the theory of NP-completeness [Graph Theory, Covering and Partitioning, Minimum Feedback Arc Set, GT9]. */ param n, integer, >= 0; /* number of vertices */ set V, default 1..n; /* set of vertices */ set E, within V cross V, default setof{i in V, j in V: i <> j and Uniform(0,1) <= 0.15} (i,j); /* set of arcs */ printf "Graph has %d vertices and %d arcs\n", card(V), card(E); var x{(i,j) in E}, binary; /* x[i,j] = 1 means that (i->j) is a feedback arc */ /* It is known that a digraph G = (V, E) is acyclic if and only if its vertices can be assigned numbers from 1 to |V| in such a way that k[i] + 1 <= k[j] for every arc (i->j) in E, where k[i] is a number assigned to vertex i. We may use this condition to require that the digraph G = (V, E \ E'), where E' is a subset of feedback arcs, is acyclic. */ var k{i in V}, >= 1, <= card(V); /* k[i] is a number assigned to vertex i */ s.t. r{(i,j) in E}: k[j] - k[i] >= 1 - card(V) * x[i,j]; /* note that x[i,j] = 1 leads to a redundant constraint */ minimize obj: sum{(i,j) in E} x[i,j]; /* the objective is to minimize the cardinality of a subset of feedback arcs */ solve; printf "Minimum feedback arc set:\n"; printf{(i,j) in E: x[i,j]} "%d %d\n", i, j; data; /* The optimal solution is 3 */ param n := 15; set E := 1 2, 2 3, 3 4, 3 8, 4 9, 5 1, 6 5, 7 5, 8 6, 8 7, 8 9, 9 10, 10 11, 10 14, 11 15, 12 7, 12 8, 12 13, 13 8, 13 12, 13 14, 14 9, 15 14; end; glpk-4.52.1/examples/mfvsp.mod0000644000062000006210000000357412175147600015404 0ustar maomkpasswd/* MFVSP, Minimum Feedback Vertex Set Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Minimum Feedback Vertex Set Problem for a given directed graph G = (V, E), where V is a set of vertices and E is a set of arcs, is to find a minimal subset of vertices, which being removed from the graph make it acyclic. Reference: Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: A guide to the theory of NP-completeness [Graph Theory, Covering and Partitioning, Minimum Feedback Vertex Set, GT8]. */ param n, integer, >= 0; /* number of vertices */ set V, default 1..n; /* set of vertices */ set E, within V cross V, default setof{i in V, j in V: i <> j and Uniform(0,1) <= 0.15} (i,j); /* set of arcs */ printf "Graph has %d vertices and %d arcs\n", card(V), card(E); var x{i in V}, binary; /* x[i] = 1 means that i is a feedback vertex */ /* It is known that a digraph G = (V, E) is acyclic if and only if its vertices can be assigned numbers from 1 to |V| in such a way that k[i] + 1 <= k[j] for every arc (i->j) in E, where k[i] is a number assigned to vertex i. We may use this condition to require that the digraph G = (V, E \ E'), where E' is a subset of feedback arcs, is acyclic. */ var k{i in V}, >= 1, <= card(V); /* k[i] is a number assigned to vertex i */ s.t. r{(i,j) in E}: k[j] - k[i] >= 1 - card(V) * (x[i] + x[j]); /* note that x[i] = 1 or x[j] = 1 leads to a redundant constraint */ minimize obj: sum{i in V} x[i]; /* the objective is to minimize the cardinality of a subset of feedback vertices */ solve; printf "Minimum feedback vertex set:\n"; printf{i in V: x[i]} "%d\n", i; data; /* The optimal solution is 3 */ param n := 15; set E := 1 2, 2 3, 3 4, 3 8, 4 9, 5 1, 6 5, 7 5, 8 6, 8 7, 8 9, 9 10, 10 11, 10 14, 11 15, 12 7, 12 8, 12 13, 13 8, 13 12, 13 14, 14 9, 15 14; end; glpk-4.52.1/examples/min01ks.mod0000644000062000006210000000610612175147600015525 0ustar maomkpasswd/* min01ks.mod - finding minimal equivalent 0-1 knapsack inequality */ /* Written in GNU MathProg by Andrew Makhorin */ /* It is obvious that for a given 0-1 knapsack inequality a[1] x[1] + ... + a[n] x[n] <= b, x[j] in {0, 1} (1) there exist infinitely many equivalent inequalities with exactly the same feasible solutions. Given a[j]'s and b this model allows to find an inequality alfa[1] x[1] + ... + alfa[n] x[n] <= beta, x[j] in {0, 1}, (2) which is equivalent to (1) and where alfa[j]'s and beta are smallest non-negative integers. This model has the following formulation: minimize z = |alfa[1]| + ... + |alfa[n]| + |beta| = (3) = alfa[1] + ... + alfa[n] + beta subject to alfa[1] x[1] + ... + alfa[n] x[n] <= beta (4) for all x satisfying to (1) alfa[1] x[1] + ... + alfa[n] x[n] >= beta + 1 (5) for all x not satisfying to (1) alfa[1], ..., alfa[n], beta are non-negative integers. Note that this model has n+1 variables and 2^n constraints. It is interesting, as noticed in [1] and explained in [2], that in most cases LP relaxation of the MIP formulation above has integer optimal solution. References 1. G.H.Bradley, P.L.Hammer, L.Wolsey, "Coefficient Reduction for Inequalities in 0-1 Variables", Math.Prog.7 (1974), 263-282. 2. G.J.Koehler, "A Study on Coefficient Reduction of Binary Knapsack Inequalities", University of Florida, 2001. */ param n, integer, > 0; /* number of variables in the knapsack inequality */ set N := 1..n; /* set of knapsack items */ /* all binary n-vectors are numbered by 0, 1, ..., 2^n-1, where vector 0 is 00...00, vector 1 is 00...01, etc. */ set U := 0..2^n-1; /* set of numbers of all binary n-vectors */ param x{i in U, j in N}, binary, := (i div 2^(j-1)) mod 2; /* x[i,j] is j-th component of i-th binary n-vector */ param a{j in N}, >= 0; /* original coefficients */ param b, >= 0; /* original right-hand side */ set D := setof{i in U: sum{j in N} a[j] * x[i,j] <= b} i; /* set of numbers of binary n-vectors, which (vectors) are feasible, i.e. satisfy to the original knapsack inequality (1) */ var alfa{j in N}, integer, >= 0; /* coefficients to be found */ var beta, integer, >= 0; /* right-hand side to be found */ minimize z: sum{j in N} alfa[j] + beta; /* (3) */ phi{i in D}: sum{j in N} alfa[j] * x[i,j] <= beta; /* (4) */ psi{i in U diff D}: sum{j in N} alfa[j] * x[i,j] >= beta + 1; /* (5) */ solve; printf "\nOriginal 0-1 knapsack inequality:\n"; for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", a[j], j; printf " <= %g\n", b; printf "\nMinimized equivalent inequality:\n"; for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", alfa[j], j; printf " <= %g\n\n", beta; data; /* These data correspond to the very first example from [1]. */ param n := 8; param a := [1]65, [2]64, [3]41, [4]22, [5]13, [6]12, [7]8, [8]2; param b := 80; end; glpk-4.52.1/examples/misp.mod0000644000062000006210000001241312175147600015211 0ustar maomkpasswd/* MISP, Maximum Independent Set Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* Let G = (V,E) be an undirected graph with vertex set V and edge set * E. Vertices u, v in V are non-adjacent if (u,v) not in E. A subset * of the vertices S within V is independent if all vertices in S are * pairwise non-adjacent. The Maximum Independent Set Problem (MISP) is * to find an independent set having the largest cardinality. */ param n, integer, > 0; /* number of vertices */ set V := 1..n; /* set of vertices */ set E within V cross V; /* set of edges */ var x{i in V}, binary; /* x[i] = 1 means vertex i belongs to independent set */ s.t. edge{(i,j) in E}: x[i] + x[j] <= 1; /* if there is edge (i,j), vertices i and j cannot belong to the same independent set */ maximize obj: sum{i in V} x[i]; /* the objective is to maximize the cardinality of independent set */ data; /* These data corresponds to the test instance from: * * M.G.C. Resende, T.A.Feo, S.H.Smith, "Algorithm 787 -- FORTRAN * subroutines for approximate solution of the maximum independent set * problem using GRASP," Trans. on Math. Softw., Vol. 24, No. 4, * December 1998, pp. 386-394. */ /* The optimal solution is 7. */ param n := 50; set E := 1 2 1 3 1 5 1 7 1 8 1 12 1 15 1 16 1 19 1 20 1 21 1 22 1 28 1 30 1 34 1 35 1 37 1 41 1 42 1 47 1 50 2 3 2 5 2 6 2 7 2 8 2 9 2 10 2 13 2 17 2 19 2 20 2 21 2 23 2 25 2 26 2 29 2 31 2 35 2 36 2 44 2 45 2 46 2 50 3 5 3 6 3 8 3 9 3 10 3 11 3 14 3 16 3 23 3 24 3 26 3 27 3 28 3 29 3 30 3 31 3 34 3 35 3 36 3 39 3 41 3 42 3 43 3 44 3 50 4 6 4 7 4 9 4 10 4 11 4 13 4 14 4 15 4 17 4 21 4 22 4 23 4 24 4 25 4 27 4 28 4 30 4 31 4 33 4 34 4 35 4 36 4 37 4 38 4 40 4 41 4 42 4 46 4 49 5 6 5 11 5 14 5 21 5 24 5 25 5 28 5 35 5 38 5 39 5 41 5 44 5 49 5 50 6 8 6 9 6 10 6 13 6 14 6 16 6 17 6 19 6 22 6 23 6 26 6 27 6 30 6 34 6 35 6 38 6 39 6 40 6 41 6 44 6 45 6 47 6 50 7 8 7 9 7 10 7 11 7 13 7 15 7 16 7 18 7 20 7 22 7 23 7 24 7 25 7 33 7 35 7 36 7 38 7 43 7 45 7 46 7 47 8 10 8 11 8 13 8 16 8 17 8 18 8 19 8 20 8 21 8 22 8 23 8 24 8 25 8 26 8 33 8 35 8 36 8 39 8 42 8 44 8 48 8 49 9 12 9 14 9 17 9 19 9 20 9 23 9 28 9 30 9 31 9 32 9 33 9 34 9 38 9 39 9 42 9 44 9 45 9 46 10 11 10 13 10 15 10 16 10 17 10 20 10 21 10 22 10 23 10 25 10 26 10 27 10 28 10 30 10 31 10 32 10 37 10 38 10 41 10 43 10 44 10 45 10 50 11 12 11 14 11 15 11 18 11 21 11 24 11 25 11 26 11 29 11 32 11 33 11 35 11 36 11 37 11 39 11 40 11 42 11 43 11 45 11 47 11 49 11 50 12 13 12 16 12 17 12 19 12 24 12 25 12 26 12 30 12 31 12 32 12 34 12 36 12 37 12 39 12 41 12 44 12 47 12 48 12 49 13 15 13 16 13 18 13 19 13 20 13 22 13 23 13 24 13 27 13 28 13 29 13 31 13 33 13 35 13 36 13 37 13 44 13 47 13 49 13 50 14 15 14 16 14 17 14 18 14 19 14 20 14 21 14 26 14 28 14 29 14 30 14 31 14 32 14 34 14 35 14 36 14 38 14 39 14 41 14 44 14 46 14 47 14 48 15 18 15 21 15 22 15 23 15 25 15 28 15 29 15 30 15 33 15 34 15 36 15 37 15 38 15 39 15 40 15 43 15 44 15 46 15 50 16 17 16 19 16 20 16 25 16 26 16 29 16 35 16 38 16 39 16 40 16 41 16 42 16 44 17 18 17 19 17 21 17 22 17 23 17 25 17 26 17 28 17 29 17 33 17 37 17 44 17 45 17 48 18 20 18 24 18 27 18 28 18 31 18 32 18 34 18 35 18 36 18 37 18 38 18 45 18 48 18 49 18 50 19 22 19 24 19 28 19 29 19 36 19 37 19 39 19 41 19 43 19 45 19 48 19 49 20 21 20 22 20 24 20 25 20 26 20 27 20 29 20 30 20 31 20 33 20 34 20 35 20 38 20 39 20 41 20 42 20 43 20 44 20 45 20 46 20 48 20 49 21 22 21 23 21 29 21 31 21 35 21 38 21 42 21 46 21 47 22 23 22 26 22 27 22 28 22 29 22 30 22 39 22 40 22 41 22 42 22 44 22 45 22 46 22 47 22 49 22 50 23 28 23 31 23 32 23 33 23 34 23 35 23 36 23 39 23 40 23 41 23 42 23 44 23 45 23 48 23 49 23 50 24 25 24 27 24 29 24 30 24 31 24 33 24 34 24 38 24 42 24 43 24 44 24 49 24 50 25 26 25 27 25 29 25 30 25 33 25 34 25 36 25 38 25 40 25 41 25 42 25 44 25 46 25 47 25 48 25 49 26 28 26 31 26 32 26 33 26 37 26 38 26 39 26 40 26 41 26 42 26 45 26 47 26 48 26 49 27 29 27 30 27 33 27 34 27 35 27 39 27 40 27 46 27 48 28 29 28 37 28 40 28 42 28 44 28 46 28 47 28 50 29 35 29 38 29 39 29 41 29 42 29 48 30 31 30 32 30 35 30 37 30 38 30 40 30 43 30 45 30 46 30 47 30 48 31 33 31 35 31 38 31 40 31 41 31 42 31 44 31 46 31 47 31 50 32 33 32 35 32 39 32 40 32 46 32 49 32 50 33 34 33 36 33 37 33 40 33 42 33 43 33 44 33 45 33 50 34 35 34 36 34 37 34 38 34 40 34 43 34 44 34 49 34 50 35 36 35 38 35 41 35 42 35 43 35 45 35 46 35 47 35 49 35 50 36 37 36 39 36 40 36 41 36 42 36 43 36 48 36 50 37 38 37 41 37 43 37 46 37 47 37 48 37 49 37 50 38 41 38 45 38 46 38 48 38 49 38 50 39 43 39 46 39 47 39 48 39 49 40 43 40 45 40 48 40 50 41 42 41 43 41 44 41 45 41 46 41 48 41 49 42 43 42 44 42 46 42 48 42 49 43 45 43 46 43 48 43 50 44 45 44 48 45 46 45 47 45 48 46 49 47 49 47 50 48 49 48 50 49 50 ; end; glpk-4.52.1/examples/misp1.dat0000644000062000006210000002561212175147600015270 0ustar maomkpasswd/* misp1.dat (data for misp.mod to illustrate clique cuts) */ /* These data corresponds to the test instance 1dc.128 (graphs from * single-deletion-correcting codes) from: * * N.J.A.Sloane, "Challenge Problems: Independent Sets In Graphs." * http://neilsloane.com/doc/graphs.html (June 2013). */ /* Optimal solution is 16. */ data; param n := 128; set E := /* 1471 edges */ 1 2 1 3 1 5 1 9 1 17 1 33 1 65 2 3 2 4 2 5 2 6 2 9 2 10 2 17 2 18 2 33 2 34 2 65 2 66 3 4 3 5 3 6 3 7 3 9 3 10 3 11 3 17 3 18 3 19 3 33 3 34 3 35 3 65 3 66 3 67 4 6 4 7 4 8 4 10 4 12 4 18 4 20 4 34 4 36 4 66 4 68 5 6 5 7 5 9 5 10 5 11 5 13 5 17 5 19 5 21 5 33 5 35 5 37 5 65 5 67 5 69 6 7 6 8 6 10 6 11 6 12 6 14 6 18 6 19 6 20 6 22 6 34 6 35 6 36 6 38 6 66 6 67 6 68 6 70 7 8 7 11 7 12 7 13 7 14 7 15 7 19 7 20 7 23 7 35 7 36 7 39 7 67 7 68 7 71 8 12 8 14 8 15 8 16 8 20 8 24 8 36 8 40 8 68 8 72 9 10 9 11 9 13 9 17 9 18 9 19 9 21 9 25 9 33 9 37 9 41 9 65 9 69 9 73 10 11 10 12 10 13 10 14 10 18 10 19 10 20 10 21 10 22 10 26 10 34 10 37 10 38 10 42 10 66 10 69 10 70 10 74 11 12 11 13 11 14 11 15 11 19 11 21 11 22 11 23 11 27 11 35 11 37 11 38 11 39 11 43 11 67 11 69 11 70 11 71 11 75 12 14 12 15 12 16 12 20 12 22 12 23 12 24 12 28 12 36 12 38 12 40 12 44 12 68 12 70 12 72 12 76 13 14 13 15 13 21 13 23 13 25 13 26 13 27 13 29 13 37 13 39 13 45 13 69 13 71 13 77 14 15 14 16 14 22 14 23 14 24 14 26 14 27 14 28 14 30 14 38 14 39 14 40 14 46 14 70 14 71 14 72 14 78 15 16 15 23 15 24 15 27 15 29 15 30 15 31 15 39 15 40 15 47 15 71 15 72 15 79 16 24 16 28 16 30 16 31 16 32 16 40 16 48 16 72 16 80 17 18 17 19 17 21 17 25 17 33 17 34 17 35 17 37 17 41 17 49 17 65 17 73 17 81 18 19 18 20 18 21 18 22 18 25 18 26 18 34 18 35 18 36 18 38 18 41 18 42 18 50 18 66 18 73 18 74 18 82 19 20 19 21 19 22 19 23 19 25 19 26 19 27 19 35 19 37 19 38 19 39 19 41 19 42 19 43 19 51 19 67 19 73 19 74 19 75 19 83 20 22 20 23 20 24 20 26 20 28 20 36 20 38 20 39 20 40 20 42 20 44 20 52 20 68 20 74 20 76 20 84 21 22 21 23 21 25 21 26 21 27 21 29 21 37 21 41 21 42 21 43 21 45 21 53 21 69 21 73 21 75 21 77 21 85 22 23 22 24 22 26 22 27 22 28 22 30 22 38 22 42 22 43 22 44 22 46 22 54 22 70 22 74 22 75 22 76 22 78 22 86 23 24 23 27 23 28 23 29 23 30 23 31 23 39 23 43 23 44 23 45 23 46 23 47 23 55 23 71 23 75 23 76 23 79 23 87 24 28 24 30 24 31 24 32 24 40 24 44 24 46 24 47 24 48 24 56 24 72 24 76 24 80 24 88 25 26 25 27 25 29 25 41 25 45 25 49 25 50 25 51 25 53 25 57 25 73 25 77 25 89 26 27 26 28 26 29 26 30 26 42 26 45 26 46 26 50 26 51 26 52 26 54 26 58 26 74 26 77 26 78 26 90 27 28 27 29 27 30 27 31 27 43 27 45 27 46 27 47 27 51 27 53 27 54 27 55 27 59 27 75 27 77 27 78 27 79 27 91 28 30 28 31 28 32 28 44 28 46 28 48 28 52 28 54 28 55 28 56 28 60 28 76 28 78 28 80 28 92 29 30 29 31 29 45 29 47 29 53 29 57 29 58 29 59 29 61 29 77 29 79 29 93 30 31 30 32 30 46 30 47 30 48 30 54 30 58 30 59 30 60 30 62 30 78 30 79 30 80 30 94 31 32 31 47 31 48 31 55 31 59 31 61 31 62 31 63 31 79 31 80 31 95 32 48 32 56 32 60 32 62 32 63 32 64 32 80 32 96 33 34 33 35 33 37 33 41 33 49 33 65 33 66 33 67 33 69 33 73 33 81 33 97 34 35 34 36 34 37 34 38 34 41 34 42 34 49 34 50 34 66 34 67 34 68 34 70 34 74 34 81 34 82 34 98 35 36 35 37 35 38 35 39 35 41 35 42 35 43 35 49 35 50 35 51 35 67 35 69 35 70 35 71 35 75 35 81 35 82 35 83 35 99 36 38 36 39 36 40 36 42 36 44 36 50 36 52 36 68 36 70 36 71 36 72 36 76 36 82 36 84 36 100 37 38 37 39 37 41 37 42 37 43 37 45 37 49 37 51 37 53 37 69 37 73 37 74 37 75 37 77 37 81 37 83 37 85 37 101 38 39 38 40 38 42 38 43 38 44 38 46 38 50 38 51 38 52 38 54 38 70 38 74 38 75 38 76 38 78 38 82 38 83 38 84 38 86 38 102 39 40 39 43 39 44 39 45 39 46 39 47 39 51 39 52 39 55 39 71 39 75 39 77 39 78 39 79 39 83 39 84 39 87 39 103 40 44 40 46 40 47 40 48 40 52 40 56 40 72 40 76 40 78 40 79 40 80 40 84 40 88 40 104 41 42 41 43 41 45 41 49 41 50 41 51 41 53 41 57 41 73 41 81 41 82 41 83 41 85 41 89 41 105 42 43 42 44 42 45 42 46 42 50 42 51 42 52 42 53 42 54 42 58 42 74 42 82 42 83 42 84 42 85 42 86 42 90 42 106 43 44 43 45 43 46 43 47 43 51 43 53 43 54 43 55 43 59 43 75 43 83 43 85 43 86 43 87 43 91 43 107 44 46 44 47 44 48 44 52 44 54 44 55 44 56 44 60 44 76 44 84 44 86 44 87 44 88 44 92 44 108 45 46 45 47 45 53 45 55 45 57 45 58 45 59 45 61 45 77 45 85 45 87 45 89 45 90 45 91 45 93 45 109 46 47 46 48 46 54 46 55 46 56 46 58 46 59 46 60 46 62 46 78 46 86 46 87 46 88 46 90 46 91 46 92 46 94 46 110 47 48 47 55 47 56 47 59 47 61 47 62 47 63 47 79 47 87 47 88 47 91 47 93 47 94 47 95 47 111 48 56 48 60 48 62 48 63 48 64 48 80 48 88 48 92 48 94 48 95 48 96 48 112 49 50 49 51 49 53 49 57 49 81 49 89 49 97 49 98 49 99 49 101 49 105 49 113 50 51 50 52 50 53 50 54 50 57 50 58 50 82 50 89 50 90 50 98 50 99 50 100 50 102 50 106 50 114 51 52 51 53 51 54 51 55 51 57 51 58 51 59 51 83 51 89 51 90 51 91 51 99 51 101 51 102 51 103 51 107 51 115 52 54 52 55 52 56 52 58 52 60 52 84 52 90 52 92 52 100 52 102 52 103 52 104 52 108 52 116 53 54 53 55 53 57 53 58 53 59 53 61 53 85 53 89 53 91 53 93 53 101 53 105 53 106 53 107 53 109 53 117 54 55 54 56 54 58 54 59 54 60 54 62 54 86 54 90 54 91 54 92 54 94 54 102 54 106 54 107 54 108 54 110 54 118 55 56 55 59 55 60 55 61 55 62 55 63 55 87 55 91 55 92 55 95 55 103 55 107 55 109 55 110 55 111 55 119 56 60 56 62 56 63 56 64 56 88 56 92 56 96 56 104 56 108 56 110 56 111 56 112 56 120 57 58 57 59 57 61 57 89 57 93 57 105 57 113 57 114 57 115 57 117 57 121 58 59 58 60 58 61 58 62 58 90 58 93 58 94 58 106 58 114 58 115 58 116 58 118 58 122 59 60 59 61 59 62 59 63 59 91 59 93 59 94 59 95 59 107 59 115 59 117 59 118 59 119 59 123 60 62 60 63 60 64 60 92 60 94 60 96 60 108 60 116 60 118 60 119 60 120 60 124 61 62 61 63 61 93 61 95 61 109 61 117 61 121 61 122 61 123 61 125 62 63 62 64 62 94 62 95 62 96 62 110 62 118 62 122 62 123 62 124 62 126 63 64 63 95 63 96 63 111 63 119 63 123 63 125 63 126 63 127 64 96 64 112 64 120 64 124 64 126 64 127 64 128 65 66 65 67 65 69 65 73 65 81 65 97 66 67 66 68 66 69 66 70 66 73 66 74 66 81 66 82 66 97 66 98 67 68 67 69 67 70 67 71 67 73 67 74 67 75 67 81 67 82 67 83 67 97 67 98 67 99 68 70 68 71 68 72 68 74 68 76 68 82 68 84 68 98 68 100 69 70 69 71 69 73 69 74 69 75 69 77 69 81 69 83 69 85 69 97 69 99 69 101 70 71 70 72 70 74 70 75 70 76 70 78 70 82 70 83 70 84 70 86 70 98 70 99 70 100 70 102 71 72 71 75 71 76 71 77 71 78 71 79 71 83 71 84 71 87 71 99 71 100 71 103 72 76 72 78 72 79 72 80 72 84 72 88 72 100 72 104 73 74 73 75 73 77 73 81 73 82 73 83 73 85 73 89 73 97 73 101 73 105 74 75 74 76 74 77 74 78 74 82 74 83 74 84 74 85 74 86 74 90 74 98 74 101 74 102 74 106 75 76 75 77 75 78 75 79 75 83 75 85 75 86 75 87 75 91 75 99 75 101 75 102 75 103 75 107 76 78 76 79 76 80 76 84 76 86 76 87 76 88 76 92 76 100 76 102 76 104 76 108 77 78 77 79 77 85 77 87 77 89 77 90 77 91 77 93 77 101 77 103 77 109 78 79 78 80 78 86 78 87 78 88 78 90 78 91 78 92 78 94 78 102 78 103 78 104 78 110 79 80 79 87 79 88 79 91 79 93 79 94 79 95 79 103 79 104 79 111 80 88 80 92 80 94 80 95 80 96 80 104 80 112 81 82 81 83 81 85 81 89 81 97 81 98 81 99 81 101 81 105 81 113 82 83 82 84 82 85 82 86 82 89 82 90 82 98 82 99 82 100 82 102 82 105 82 106 82 114 83 84 83 85 83 86 83 87 83 89 83 90 83 91 83 99 83 101 83 102 83 103 83 105 83 106 83 107 83 115 84 86 84 87 84 88 84 90 84 92 84 100 84 102 84 103 84 104 84 106 84 108 84 116 85 86 85 87 85 89 85 90 85 91 85 93 85 101 85 105 85 106 85 107 85 109 85 117 86 87 86 88 86 90 86 91 86 92 86 94 86 102 86 106 86 107 86 108 86 110 86 118 87 88 87 91 87 92 87 93 87 94 87 95 87 103 87 107 87 108 87 109 87 110 87 111 87 119 88 92 88 94 88 95 88 96 88 104 88 108 88 110 88 111 88 112 88 120 89 90 89 91 89 93 89 105 89 109 89 113 89 114 89 115 89 117 89 121 90 91 90 92 90 93 90 94 90 106 90 109 90 110 90 114 90 115 90 116 90 118 90 122 91 92 91 93 91 94 91 95 91 107 91 109 91 110 91 111 91 115 91 117 91 118 91 119 91 123 92 94 92 95 92 96 92 108 92 110 92 112 92 116 92 118 92 119 92 120 92 124 93 94 93 95 93 109 93 111 93 117 93 121 93 122 93 123 93 125 94 95 94 96 94 110 94 111 94 112 94 118 94 122 94 123 94 124 94 126 95 96 95 111 95 112 95 119 95 123 95 125 95 126 95 127 96 112 96 120 96 124 96 126 96 127 96 128 97 98 97 99 97 101 97 105 97 113 98 99 98 100 98 101 98 102 98 105 98 106 98 113 98 114 99 100 99 101 99 102 99 103 99 105 99 106 99 107 99 113 99 114 99 115 100 102 100 103 100 104 100 106 100 108 100 114 100 116 101 102 101 103 101 105 101 106 101 107 101 109 101 113 101 115 101 117 102 103 102 104 102 106 102 107 102 108 102 110 102 114 102 115 102 116 102 118 103 104 103 107 103 108 103 109 103 110 103 111 103 115 103 116 103 119 104 108 104 110 104 111 104 112 104 116 104 120 105 106 105 107 105 109 105 113 105 114 105 115 105 117 105 121 106 107 106 108 106 109 106 110 106 114 106 115 106 116 106 117 106 118 106 122 107 108 107 109 107 110 107 111 107 115 107 117 107 118 107 119 107 123 108 110 108 111 108 112 108 116 108 118 108 119 108 120 108 124 109 110 109 111 109 117 109 119 109 121 109 122 109 123 109 125 110 111 110 112 110 118 110 119 110 120 110 122 110 123 110 124 110 126 111 112 111 119 111 120 111 123 111 125 111 126 111 127 112 120 112 124 112 126 112 127 112 128 113 114 113 115 113 117 113 121 114 115 114 116 114 117 114 118 114 121 114 122 115 116 115 117 115 118 115 119 115 121 115 122 115 123 116 118 116 119 116 120 116 122 116 124 117 118 117 119 117 121 117 122 117 123 117 125 118 119 118 120 118 122 118 123 118 124 118 126 119 120 119 123 119 124 119 125 119 126 119 127 120 124 120 126 120 127 120 128 121 122 121 123 121 125 122 123 122 124 122 125 122 126 123 124 123 125 123 126 123 127 124 126 124 127 124 128 125 126 125 127 126 127 126 128 127 128 ; end; glpk-4.52.1/examples/misp2.dat0000644000062000006210000007614412175147600015277 0ustar maomkpasswd/* misp2.dat (data for misp.mod to illustrate clique cuts) */ /* These data corresponds to the test instance 1dc.256 (graphs from * single-deletion-correcting codes) from: * * N.J.A.Sloane, "Challenge Problems: Independent Sets In Graphs." * http://neilsloane.com/doc/graphs.html (June 2013). */ /* Optimal solution is 30. */ data; param n := 256; set E := /* 3839 edges */ 1 2 1 3 1 5 1 9 1 17 1 33 1 65 1 129 2 3 2 4 2 5 2 6 2 9 2 10 2 17 2 18 2 33 2 34 2 65 2 66 2 129 2 130 3 4 3 5 3 6 3 7 3 9 3 10 3 11 3 17 3 18 3 19 3 33 3 34 3 35 3 65 3 66 3 67 3 129 3 130 3 131 4 6 4 7 4 8 4 10 4 12 4 18 4 20 4 34 4 36 4 66 4 68 4 130 4 132 5 6 5 7 5 9 5 10 5 11 5 13 5 17 5 19 5 21 5 33 5 35 5 37 5 65 5 67 5 69 5 129 5 131 5 133 6 7 6 8 6 10 6 11 6 12 6 14 6 18 6 19 6 20 6 22 6 34 6 35 6 36 6 38 6 66 6 67 6 68 6 70 6 130 6 131 6 132 6 134 7 8 7 11 7 12 7 13 7 14 7 15 7 19 7 20 7 23 7 35 7 36 7 39 7 67 7 68 7 71 7 131 7 132 7 135 8 12 8 14 8 15 8 16 8 20 8 24 8 36 8 40 8 68 8 72 8 132 8 136 9 10 9 11 9 13 9 17 9 18 9 19 9 21 9 25 9 33 9 37 9 41 9 65 9 69 9 73 9 129 9 133 9 137 10 11 10 12 10 13 10 14 10 18 10 19 10 20 10 21 10 22 10 26 10 34 10 37 10 38 10 42 10 66 10 69 10 70 10 74 10 130 10 133 10 134 10 138 11 12 11 13 11 14 11 15 11 19 11 21 11 22 11 23 11 27 11 35 11 37 11 38 11 39 11 43 11 67 11 69 11 70 11 71 11 75 11 131 11 133 11 134 11 135 11 139 12 14 12 15 12 16 12 20 12 22 12 23 12 24 12 28 12 36 12 38 12 40 12 44 12 68 12 70 12 72 12 76 12 132 12 134 12 136 12 140 13 14 13 15 13 21 13 23 13 25 13 26 13 27 13 29 13 37 13 39 13 45 13 69 13 71 13 77 13 133 13 135 13 141 14 15 14 16 14 22 14 23 14 24 14 26 14 27 14 28 14 30 14 38 14 39 14 40 14 46 14 70 14 71 14 72 14 78 14 134 14 135 14 136 14 142 15 16 15 23 15 24 15 27 15 29 15 30 15 31 15 39 15 40 15 47 15 71 15 72 15 79 15 135 15 136 15 143 16 24 16 28 16 30 16 31 16 32 16 40 16 48 16 72 16 80 16 136 16 144 17 18 17 19 17 21 17 25 17 33 17 34 17 35 17 37 17 41 17 49 17 65 17 73 17 81 17 129 17 137 17 145 18 19 18 20 18 21 18 22 18 25 18 26 18 34 18 35 18 36 18 38 18 41 18 42 18 50 18 66 18 73 18 74 18 82 18 130 18 137 18 138 18 146 19 20 19 21 19 22 19 23 19 25 19 26 19 27 19 35 19 37 19 38 19 39 19 41 19 42 19 43 19 51 19 67 19 73 19 74 19 75 19 83 19 131 19 137 19 138 19 139 19 147 20 22 20 23 20 24 20 26 20 28 20 36 20 38 20 39 20 40 20 42 20 44 20 52 20 68 20 74 20 76 20 84 20 132 20 138 20 140 20 148 21 22 21 23 21 25 21 26 21 27 21 29 21 37 21 41 21 42 21 43 21 45 21 53 21 69 21 73 21 75 21 77 21 85 21 133 21 137 21 139 21 141 21 149 22 23 22 24 22 26 22 27 22 28 22 30 22 38 22 42 22 43 22 44 22 46 22 54 22 70 22 74 22 75 22 76 22 78 22 86 22 134 22 138 22 139 22 140 22 142 22 150 23 24 23 27 23 28 23 29 23 30 23 31 23 39 23 43 23 44 23 45 23 46 23 47 23 55 23 71 23 75 23 76 23 79 23 87 23 135 23 139 23 140 23 143 23 151 24 28 24 30 24 31 24 32 24 40 24 44 24 46 24 47 24 48 24 56 24 72 24 76 24 80 24 88 24 136 24 140 24 144 24 152 25 26 25 27 25 29 25 41 25 45 25 49 25 50 25 51 25 53 25 57 25 73 25 77 25 89 25 137 25 141 25 153 26 27 26 28 26 29 26 30 26 42 26 45 26 46 26 50 26 51 26 52 26 54 26 58 26 74 26 77 26 78 26 90 26 138 26 141 26 142 26 154 27 28 27 29 27 30 27 31 27 43 27 45 27 46 27 47 27 51 27 53 27 54 27 55 27 59 27 75 27 77 27 78 27 79 27 91 27 139 27 141 27 142 27 143 27 155 28 30 28 31 28 32 28 44 28 46 28 48 28 52 28 54 28 55 28 56 28 60 28 76 28 78 28 80 28 92 28 140 28 142 28 144 28 156 29 30 29 31 29 45 29 47 29 53 29 57 29 58 29 59 29 61 29 77 29 79 29 93 29 141 29 143 29 157 30 31 30 32 30 46 30 47 30 48 30 54 30 58 30 59 30 60 30 62 30 78 30 79 30 80 30 94 30 142 30 143 30 144 30 158 31 32 31 47 31 48 31 55 31 59 31 61 31 62 31 63 31 79 31 80 31 95 31 143 31 144 31 159 32 48 32 56 32 60 32 62 32 63 32 64 32 80 32 96 32 144 32 160 33 34 33 35 33 37 33 41 33 49 33 65 33 66 33 67 33 69 33 73 33 81 33 97 33 129 33 145 33 161 34 35 34 36 34 37 34 38 34 41 34 42 34 49 34 50 34 66 34 67 34 68 34 70 34 74 34 81 34 82 34 98 34 130 34 145 34 146 34 162 35 36 35 37 35 38 35 39 35 41 35 42 35 43 35 49 35 50 35 51 35 67 35 69 35 70 35 71 35 75 35 81 35 82 35 83 35 99 35 131 35 145 35 146 35 147 35 163 36 38 36 39 36 40 36 42 36 44 36 50 36 52 36 68 36 70 36 71 36 72 36 76 36 82 36 84 36 100 36 132 36 146 36 148 36 164 37 38 37 39 37 41 37 42 37 43 37 45 37 49 37 51 37 53 37 69 37 73 37 74 37 75 37 77 37 81 37 83 37 85 37 101 37 133 37 145 37 147 37 149 37 165 38 39 38 40 38 42 38 43 38 44 38 46 38 50 38 51 38 52 38 54 38 70 38 74 38 75 38 76 38 78 38 82 38 83 38 84 38 86 38 102 38 134 38 146 38 147 38 148 38 150 38 166 39 40 39 43 39 44 39 45 39 46 39 47 39 51 39 52 39 55 39 71 39 75 39 77 39 78 39 79 39 83 39 84 39 87 39 103 39 135 39 147 39 148 39 151 39 167 40 44 40 46 40 47 40 48 40 52 40 56 40 72 40 76 40 78 40 79 40 80 40 84 40 88 40 104 40 136 40 148 40 152 40 168 41 42 41 43 41 45 41 49 41 50 41 51 41 53 41 57 41 73 41 81 41 82 41 83 41 85 41 89 41 105 41 137 41 145 41 149 41 153 41 169 42 43 42 44 42 45 42 46 42 50 42 51 42 52 42 53 42 54 42 58 42 74 42 82 42 83 42 84 42 85 42 86 42 90 42 106 42 138 42 146 42 149 42 150 42 154 42 170 43 44 43 45 43 46 43 47 43 51 43 53 43 54 43 55 43 59 43 75 43 83 43 85 43 86 43 87 43 91 43 107 43 139 43 147 43 149 43 150 43 151 43 155 43 171 44 46 44 47 44 48 44 52 44 54 44 55 44 56 44 60 44 76 44 84 44 86 44 87 44 88 44 92 44 108 44 140 44 148 44 150 44 152 44 156 44 172 45 46 45 47 45 53 45 55 45 57 45 58 45 59 45 61 45 77 45 85 45 87 45 89 45 90 45 91 45 93 45 109 45 141 45 149 45 151 45 157 45 173 46 47 46 48 46 54 46 55 46 56 46 58 46 59 46 60 46 62 46 78 46 86 46 87 46 88 46 90 46 91 46 92 46 94 46 110 46 142 46 150 46 151 46 152 46 158 46 174 47 48 47 55 47 56 47 59 47 61 47 62 47 63 47 79 47 87 47 88 47 91 47 93 47 94 47 95 47 111 47 143 47 151 47 152 47 159 47 175 48 56 48 60 48 62 48 63 48 64 48 80 48 88 48 92 48 94 48 95 48 96 48 112 48 144 48 152 48 160 48 176 49 50 49 51 49 53 49 57 49 81 49 89 49 97 49 98 49 99 49 101 49 105 49 113 49 145 49 153 49 177 50 51 50 52 50 53 50 54 50 57 50 58 50 82 50 89 50 90 50 98 50 99 50 100 50 102 50 106 50 114 50 146 50 153 50 154 50 178 51 52 51 53 51 54 51 55 51 57 51 58 51 59 51 83 51 89 51 90 51 91 51 99 51 101 51 102 51 103 51 107 51 115 51 147 51 153 51 154 51 155 51 179 52 54 52 55 52 56 52 58 52 60 52 84 52 90 52 92 52 100 52 102 52 103 52 104 52 108 52 116 52 148 52 154 52 156 52 180 53 54 53 55 53 57 53 58 53 59 53 61 53 85 53 89 53 91 53 93 53 101 53 105 53 106 53 107 53 109 53 117 53 149 53 153 53 155 53 157 53 181 54 55 54 56 54 58 54 59 54 60 54 62 54 86 54 90 54 91 54 92 54 94 54 102 54 106 54 107 54 108 54 110 54 118 54 150 54 154 54 155 54 156 54 158 54 182 55 56 55 59 55 60 55 61 55 62 55 63 55 87 55 91 55 92 55 95 55 103 55 107 55 109 55 110 55 111 55 119 55 151 55 155 55 156 55 159 55 183 56 60 56 62 56 63 56 64 56 88 56 92 56 96 56 104 56 108 56 110 56 111 56 112 56 120 56 152 56 156 56 160 56 184 57 58 57 59 57 61 57 89 57 93 57 105 57 113 57 114 57 115 57 117 57 121 57 153 57 157 57 185 58 59 58 60 58 61 58 62 58 90 58 93 58 94 58 106 58 114 58 115 58 116 58 118 58 122 58 154 58 157 58 158 58 186 59 60 59 61 59 62 59 63 59 91 59 93 59 94 59 95 59 107 59 115 59 117 59 118 59 119 59 123 59 155 59 157 59 158 59 159 59 187 60 62 60 63 60 64 60 92 60 94 60 96 60 108 60 116 60 118 60 119 60 120 60 124 60 156 60 158 60 160 60 188 61 62 61 63 61 93 61 95 61 109 61 117 61 121 61 122 61 123 61 125 61 157 61 159 61 189 62 63 62 64 62 94 62 95 62 96 62 110 62 118 62 122 62 123 62 124 62 126 62 158 62 159 62 160 62 190 63 64 63 95 63 96 63 111 63 119 63 123 63 125 63 126 63 127 63 159 63 160 63 191 64 96 64 112 64 120 64 124 64 126 64 127 64 128 64 160 64 192 65 66 65 67 65 69 65 73 65 81 65 97 65 129 65 130 65 131 65 133 65 137 65 145 65 161 65 193 66 67 66 68 66 69 66 70 66 73 66 74 66 81 66 82 66 97 66 98 66 130 66 131 66 132 66 134 66 138 66 146 66 161 66 162 66 194 67 68 67 69 67 70 67 71 67 73 67 74 67 75 67 81 67 82 67 83 67 97 67 98 67 99 67 131 67 133 67 134 67 135 67 139 67 147 67 161 67 162 67 163 67 195 68 70 68 71 68 72 68 74 68 76 68 82 68 84 68 98 68 100 68 132 68 134 68 135 68 136 68 140 68 148 68 162 68 164 68 196 69 70 69 71 69 73 69 74 69 75 69 77 69 81 69 83 69 85 69 97 69 99 69 101 69 133 69 137 69 138 69 139 69 141 69 149 69 161 69 163 69 165 69 197 70 71 70 72 70 74 70 75 70 76 70 78 70 82 70 83 70 84 70 86 70 98 70 99 70 100 70 102 70 134 70 138 70 139 70 140 70 142 70 150 70 162 70 163 70 164 70 166 70 198 71 72 71 75 71 76 71 77 71 78 71 79 71 83 71 84 71 87 71 99 71 100 71 103 71 135 71 139 71 141 71 142 71 143 71 151 71 163 71 164 71 167 71 199 72 76 72 78 72 79 72 80 72 84 72 88 72 100 72 104 72 136 72 140 72 142 72 143 72 144 72 152 72 164 72 168 72 200 73 74 73 75 73 77 73 81 73 82 73 83 73 85 73 89 73 97 73 101 73 105 73 137 73 145 73 146 73 147 73 149 73 153 73 161 73 165 73 169 73 201 74 75 74 76 74 77 74 78 74 82 74 83 74 84 74 85 74 86 74 90 74 98 74 101 74 102 74 106 74 138 74 146 74 147 74 148 74 150 74 154 74 162 74 165 74 166 74 170 74 202 75 76 75 77 75 78 75 79 75 83 75 85 75 86 75 87 75 91 75 99 75 101 75 102 75 103 75 107 75 139 75 147 75 149 75 150 75 151 75 155 75 163 75 165 75 166 75 167 75 171 75 203 76 78 76 79 76 80 76 84 76 86 76 87 76 88 76 92 76 100 76 102 76 104 76 108 76 140 76 148 76 150 76 151 76 152 76 156 76 164 76 166 76 168 76 172 76 204 77 78 77 79 77 85 77 87 77 89 77 90 77 91 77 93 77 101 77 103 77 109 77 141 77 149 77 153 77 154 77 155 77 157 77 165 77 167 77 173 77 205 78 79 78 80 78 86 78 87 78 88 78 90 78 91 78 92 78 94 78 102 78 103 78 104 78 110 78 142 78 150 78 154 78 155 78 156 78 158 78 166 78 167 78 168 78 174 78 206 79 80 79 87 79 88 79 91 79 93 79 94 79 95 79 103 79 104 79 111 79 143 79 151 79 155 79 157 79 158 79 159 79 167 79 168 79 175 79 207 80 88 80 92 80 94 80 95 80 96 80 104 80 112 80 144 80 152 80 156 80 158 80 159 80 160 80 168 80 176 80 208 81 82 81 83 81 85 81 89 81 97 81 98 81 99 81 101 81 105 81 113 81 145 81 161 81 162 81 163 81 165 81 169 81 177 81 209 82 83 82 84 82 85 82 86 82 89 82 90 82 98 82 99 82 100 82 102 82 105 82 106 82 114 82 146 82 162 82 163 82 164 82 166 82 169 82 170 82 178 82 210 83 84 83 85 83 86 83 87 83 89 83 90 83 91 83 99 83 101 83 102 83 103 83 105 83 106 83 107 83 115 83 147 83 163 83 165 83 166 83 167 83 169 83 170 83 171 83 179 83 211 84 86 84 87 84 88 84 90 84 92 84 100 84 102 84 103 84 104 84 106 84 108 84 116 84 148 84 164 84 166 84 167 84 168 84 170 84 172 84 180 84 212 85 86 85 87 85 89 85 90 85 91 85 93 85 101 85 105 85 106 85 107 85 109 85 117 85 149 85 165 85 169 85 170 85 171 85 173 85 181 85 213 86 87 86 88 86 90 86 91 86 92 86 94 86 102 86 106 86 107 86 108 86 110 86 118 86 150 86 166 86 170 86 171 86 172 86 174 86 182 86 214 87 88 87 91 87 92 87 93 87 94 87 95 87 103 87 107 87 108 87 109 87 110 87 111 87 119 87 151 87 167 87 171 87 172 87 173 87 174 87 175 87 183 87 215 88 92 88 94 88 95 88 96 88 104 88 108 88 110 88 111 88 112 88 120 88 152 88 168 88 172 88 174 88 175 88 176 88 184 88 216 89 90 89 91 89 93 89 105 89 109 89 113 89 114 89 115 89 117 89 121 89 153 89 169 89 173 89 177 89 178 89 179 89 181 89 185 89 217 90 91 90 92 90 93 90 94 90 106 90 109 90 110 90 114 90 115 90 116 90 118 90 122 90 154 90 170 90 173 90 174 90 178 90 179 90 180 90 182 90 186 90 218 91 92 91 93 91 94 91 95 91 107 91 109 91 110 91 111 91 115 91 117 91 118 91 119 91 123 91 155 91 171 91 173 91 174 91 175 91 179 91 181 91 182 91 183 91 187 91 219 92 94 92 95 92 96 92 108 92 110 92 112 92 116 92 118 92 119 92 120 92 124 92 156 92 172 92 174 92 176 92 180 92 182 92 183 92 184 92 188 92 220 93 94 93 95 93 109 93 111 93 117 93 121 93 122 93 123 93 125 93 157 93 173 93 175 93 181 93 185 93 186 93 187 93 189 93 221 94 95 94 96 94 110 94 111 94 112 94 118 94 122 94 123 94 124 94 126 94 158 94 174 94 175 94 176 94 182 94 186 94 187 94 188 94 190 94 222 95 96 95 111 95 112 95 119 95 123 95 125 95 126 95 127 95 159 95 175 95 176 95 183 95 187 95 189 95 190 95 191 95 223 96 112 96 120 96 124 96 126 96 127 96 128 96 160 96 176 96 184 96 188 96 190 96 191 96 192 96 224 97 98 97 99 97 101 97 105 97 113 97 161 97 177 97 193 97 194 97 195 97 197 97 201 97 209 97 225 98 99 98 100 98 101 98 102 98 105 98 106 98 113 98 114 98 162 98 177 98 178 98 194 98 195 98 196 98 198 98 202 98 210 98 226 99 100 99 101 99 102 99 103 99 105 99 106 99 107 99 113 99 114 99 115 99 163 99 177 99 178 99 179 99 195 99 197 99 198 99 199 99 203 99 211 99 227 100 102 100 103 100 104 100 106 100 108 100 114 100 116 100 164 100 178 100 180 100 196 100 198 100 199 100 200 100 204 100 212 100 228 101 102 101 103 101 105 101 106 101 107 101 109 101 113 101 115 101 117 101 165 101 177 101 179 101 181 101 197 101 201 101 202 101 203 101 205 101 213 101 229 102 103 102 104 102 106 102 107 102 108 102 110 102 114 102 115 102 116 102 118 102 166 102 178 102 179 102 180 102 182 102 198 102 202 102 203 102 204 102 206 102 214 102 230 103 104 103 107 103 108 103 109 103 110 103 111 103 115 103 116 103 119 103 167 103 179 103 180 103 183 103 199 103 203 103 205 103 206 103 207 103 215 103 231 104 108 104 110 104 111 104 112 104 116 104 120 104 168 104 180 104 184 104 200 104 204 104 206 104 207 104 208 104 216 104 232 105 106 105 107 105 109 105 113 105 114 105 115 105 117 105 121 105 169 105 177 105 181 105 185 105 201 105 209 105 210 105 211 105 213 105 217 105 233 106 107 106 108 106 109 106 110 106 114 106 115 106 116 106 117 106 118 106 122 106 170 106 178 106 181 106 182 106 186 106 202 106 210 106 211 106 212 106 214 106 218 106 234 107 108 107 109 107 110 107 111 107 115 107 117 107 118 107 119 107 123 107 171 107 179 107 181 107 182 107 183 107 187 107 203 107 211 107 213 107 214 107 215 107 219 107 235 108 110 108 111 108 112 108 116 108 118 108 119 108 120 108 124 108 172 108 180 108 182 108 184 108 188 108 204 108 212 108 214 108 215 108 216 108 220 108 236 109 110 109 111 109 117 109 119 109 121 109 122 109 123 109 125 109 173 109 181 109 183 109 189 109 205 109 213 109 217 109 218 109 219 109 221 109 237 110 111 110 112 110 118 110 119 110 120 110 122 110 123 110 124 110 126 110 174 110 182 110 183 110 184 110 190 110 206 110 214 110 218 110 219 110 220 110 222 110 238 111 112 111 119 111 120 111 123 111 125 111 126 111 127 111 175 111 183 111 184 111 191 111 207 111 215 111 219 111 221 111 222 111 223 111 239 112 120 112 124 112 126 112 127 112 128 112 176 112 184 112 192 112 208 112 216 112 220 112 222 112 223 112 224 112 240 113 114 113 115 113 117 113 121 113 177 113 185 113 209 113 225 113 226 113 227 113 229 113 233 113 241 114 115 114 116 114 117 114 118 114 121 114 122 114 178 114 185 114 186 114 210 114 226 114 227 114 228 114 230 114 234 114 242 115 116 115 117 115 118 115 119 115 121 115 122 115 123 115 179 115 185 115 186 115 187 115 211 115 227 115 229 115 230 115 231 115 235 115 243 116 118 116 119 116 120 116 122 116 124 116 180 116 186 116 188 116 212 116 228 116 230 116 231 116 232 116 236 116 244 117 118 117 119 117 121 117 122 117 123 117 125 117 181 117 185 117 187 117 189 117 213 117 229 117 233 117 234 117 235 117 237 117 245 118 119 118 120 118 122 118 123 118 124 118 126 118 182 118 186 118 187 118 188 118 190 118 214 118 230 118 234 118 235 118 236 118 238 118 246 119 120 119 123 119 124 119 125 119 126 119 127 119 183 119 187 119 188 119 191 119 215 119 231 119 235 119 237 119 238 119 239 119 247 120 124 120 126 120 127 120 128 120 184 120 188 120 192 120 216 120 232 120 236 120 238 120 239 120 240 120 248 121 122 121 123 121 125 121 185 121 189 121 217 121 233 121 241 121 242 121 243 121 245 121 249 122 123 122 124 122 125 122 126 122 186 122 189 122 190 122 218 122 234 122 242 122 243 122 244 122 246 122 250 123 124 123 125 123 126 123 127 123 187 123 189 123 190 123 191 123 219 123 235 123 243 123 245 123 246 123 247 123 251 124 126 124 127 124 128 124 188 124 190 124 192 124 220 124 236 124 244 124 246 124 247 124 248 124 252 125 126 125 127 125 189 125 191 125 221 125 237 125 245 125 249 125 250 125 251 125 253 126 127 126 128 126 190 126 191 126 192 126 222 126 238 126 246 126 250 126 251 126 252 126 254 127 128 127 191 127 192 127 223 127 239 127 247 127 251 127 253 127 254 127 255 128 192 128 224 128 240 128 248 128 252 128 254 128 255 128 256 129 130 129 131 129 133 129 137 129 145 129 161 129 193 130 131 130 132 130 133 130 134 130 137 130 138 130 145 130 146 130 161 130 162 130 193 130 194 131 132 131 133 131 134 131 135 131 137 131 138 131 139 131 145 131 146 131 147 131 161 131 162 131 163 131 193 131 194 131 195 132 134 132 135 132 136 132 138 132 140 132 146 132 148 132 162 132 164 132 194 132 196 133 134 133 135 133 137 133 138 133 139 133 141 133 145 133 147 133 149 133 161 133 163 133 165 133 193 133 195 133 197 134 135 134 136 134 138 134 139 134 140 134 142 134 146 134 147 134 148 134 150 134 162 134 163 134 164 134 166 134 194 134 195 134 196 134 198 135 136 135 139 135 140 135 141 135 142 135 143 135 147 135 148 135 151 135 163 135 164 135 167 135 195 135 196 135 199 136 140 136 142 136 143 136 144 136 148 136 152 136 164 136 168 136 196 136 200 137 138 137 139 137 141 137 145 137 146 137 147 137 149 137 153 137 161 137 165 137 169 137 193 137 197 137 201 138 139 138 140 138 141 138 142 138 146 138 147 138 148 138 149 138 150 138 154 138 162 138 165 138 166 138 170 138 194 138 197 138 198 138 202 139 140 139 141 139 142 139 143 139 147 139 149 139 150 139 151 139 155 139 163 139 165 139 166 139 167 139 171 139 195 139 197 139 198 139 199 139 203 140 142 140 143 140 144 140 148 140 150 140 151 140 152 140 156 140 164 140 166 140 168 140 172 140 196 140 198 140 200 140 204 141 142 141 143 141 149 141 151 141 153 141 154 141 155 141 157 141 165 141 167 141 173 141 197 141 199 141 205 142 143 142 144 142 150 142 151 142 152 142 154 142 155 142 156 142 158 142 166 142 167 142 168 142 174 142 198 142 199 142 200 142 206 143 144 143 151 143 152 143 155 143 157 143 158 143 159 143 167 143 168 143 175 143 199 143 200 143 207 144 152 144 156 144 158 144 159 144 160 144 168 144 176 144 200 144 208 145 146 145 147 145 149 145 153 145 161 145 162 145 163 145 165 145 169 145 177 145 193 145 201 145 209 146 147 146 148 146 149 146 150 146 153 146 154 146 162 146 163 146 164 146 166 146 169 146 170 146 178 146 194 146 201 146 202 146 210 147 148 147 149 147 150 147 151 147 153 147 154 147 155 147 163 147 165 147 166 147 167 147 169 147 170 147 171 147 179 147 195 147 201 147 202 147 203 147 211 148 150 148 151 148 152 148 154 148 156 148 164 148 166 148 167 148 168 148 170 148 172 148 180 148 196 148 202 148 204 148 212 149 150 149 151 149 153 149 154 149 155 149 157 149 165 149 169 149 170 149 171 149 173 149 181 149 197 149 201 149 203 149 205 149 213 150 151 150 152 150 154 150 155 150 156 150 158 150 166 150 170 150 171 150 172 150 174 150 182 150 198 150 202 150 203 150 204 150 206 150 214 151 152 151 155 151 156 151 157 151 158 151 159 151 167 151 171 151 172 151 173 151 174 151 175 151 183 151 199 151 203 151 204 151 207 151 215 152 156 152 158 152 159 152 160 152 168 152 172 152 174 152 175 152 176 152 184 152 200 152 204 152 208 152 216 153 154 153 155 153 157 153 169 153 173 153 177 153 178 153 179 153 181 153 185 153 201 153 205 153 217 154 155 154 156 154 157 154 158 154 170 154 173 154 174 154 178 154 179 154 180 154 182 154 186 154 202 154 205 154 206 154 218 155 156 155 157 155 158 155 159 155 171 155 173 155 174 155 175 155 179 155 181 155 182 155 183 155 187 155 203 155 205 155 206 155 207 155 219 156 158 156 159 156 160 156 172 156 174 156 176 156 180 156 182 156 183 156 184 156 188 156 204 156 206 156 208 156 220 157 158 157 159 157 173 157 175 157 181 157 185 157 186 157 187 157 189 157 205 157 207 157 221 158 159 158 160 158 174 158 175 158 176 158 182 158 186 158 187 158 188 158 190 158 206 158 207 158 208 158 222 159 160 159 175 159 176 159 183 159 187 159 189 159 190 159 191 159 207 159 208 159 223 160 176 160 184 160 188 160 190 160 191 160 192 160 208 160 224 161 162 161 163 161 165 161 169 161 177 161 193 161 194 161 195 161 197 161 201 161 209 161 225 162 163 162 164 162 165 162 166 162 169 162 170 162 177 162 178 162 194 162 195 162 196 162 198 162 202 162 209 162 210 162 226 163 164 163 165 163 166 163 167 163 169 163 170 163 171 163 177 163 178 163 179 163 195 163 197 163 198 163 199 163 203 163 209 163 210 163 211 163 227 164 166 164 167 164 168 164 170 164 172 164 178 164 180 164 196 164 198 164 199 164 200 164 204 164 210 164 212 164 228 165 166 165 167 165 169 165 170 165 171 165 173 165 177 165 179 165 181 165 197 165 201 165 202 165 203 165 205 165 209 165 211 165 213 165 229 166 167 166 168 166 170 166 171 166 172 166 174 166 178 166 179 166 180 166 182 166 198 166 202 166 203 166 204 166 206 166 210 166 211 166 212 166 214 166 230 167 168 167 171 167 172 167 173 167 174 167 175 167 179 167 180 167 183 167 199 167 203 167 205 167 206 167 207 167 211 167 212 167 215 167 231 168 172 168 174 168 175 168 176 168 180 168 184 168 200 168 204 168 206 168 207 168 208 168 212 168 216 168 232 169 170 169 171 169 173 169 177 169 178 169 179 169 181 169 185 169 201 169 209 169 210 169 211 169 213 169 217 169 233 170 171 170 172 170 173 170 174 170 178 170 179 170 180 170 181 170 182 170 186 170 202 170 210 170 211 170 212 170 213 170 214 170 218 170 234 171 172 171 173 171 174 171 175 171 179 171 181 171 182 171 183 171 187 171 203 171 211 171 213 171 214 171 215 171 219 171 235 172 174 172 175 172 176 172 180 172 182 172 183 172 184 172 188 172 204 172 212 172 214 172 215 172 216 172 220 172 236 173 174 173 175 173 181 173 183 173 185 173 186 173 187 173 189 173 205 173 213 173 215 173 217 173 218 173 219 173 221 173 237 174 175 174 176 174 182 174 183 174 184 174 186 174 187 174 188 174 190 174 206 174 214 174 215 174 216 174 218 174 219 174 220 174 222 174 238 175 176 175 183 175 184 175 187 175 189 175 190 175 191 175 207 175 215 175 216 175 219 175 221 175 222 175 223 175 239 176 184 176 188 176 190 176 191 176 192 176 208 176 216 176 220 176 222 176 223 176 224 176 240 177 178 177 179 177 181 177 185 177 209 177 217 177 225 177 226 177 227 177 229 177 233 177 241 178 179 178 180 178 181 178 182 178 185 178 186 178 210 178 217 178 218 178 226 178 227 178 228 178 230 178 234 178 242 179 180 179 181 179 182 179 183 179 185 179 186 179 187 179 211 179 217 179 218 179 219 179 227 179 229 179 230 179 231 179 235 179 243 180 182 180 183 180 184 180 186 180 188 180 212 180 218 180 220 180 228 180 230 180 231 180 232 180 236 180 244 181 182 181 183 181 185 181 186 181 187 181 189 181 213 181 217 181 219 181 221 181 229 181 233 181 234 181 235 181 237 181 245 182 183 182 184 182 186 182 187 182 188 182 190 182 214 182 218 182 219 182 220 182 222 182 230 182 234 182 235 182 236 182 238 182 246 183 184 183 187 183 188 183 189 183 190 183 191 183 215 183 219 183 220 183 223 183 231 183 235 183 237 183 238 183 239 183 247 184 188 184 190 184 191 184 192 184 216 184 220 184 224 184 232 184 236 184 238 184 239 184 240 184 248 185 186 185 187 185 189 185 217 185 221 185 233 185 241 185 242 185 243 185 245 185 249 186 187 186 188 186 189 186 190 186 218 186 221 186 222 186 234 186 242 186 243 186 244 186 246 186 250 187 188 187 189 187 190 187 191 187 219 187 221 187 222 187 223 187 235 187 243 187 245 187 246 187 247 187 251 188 190 188 191 188 192 188 220 188 222 188 224 188 236 188 244 188 246 188 247 188 248 188 252 189 190 189 191 189 221 189 223 189 237 189 245 189 249 189 250 189 251 189 253 190 191 190 192 190 222 190 223 190 224 190 238 190 246 190 250 190 251 190 252 190 254 191 192 191 223 191 224 191 239 191 247 191 251 191 253 191 254 191 255 192 224 192 240 192 248 192 252 192 254 192 255 192 256 193 194 193 195 193 197 193 201 193 209 193 225 194 195 194 196 194 197 194 198 194 201 194 202 194 209 194 210 194 225 194 226 195 196 195 197 195 198 195 199 195 201 195 202 195 203 195 209 195 210 195 211 195 225 195 226 195 227 196 198 196 199 196 200 196 202 196 204 196 210 196 212 196 226 196 228 197 198 197 199 197 201 197 202 197 203 197 205 197 209 197 211 197 213 197 225 197 227 197 229 198 199 198 200 198 202 198 203 198 204 198 206 198 210 198 211 198 212 198 214 198 226 198 227 198 228 198 230 199 200 199 203 199 204 199 205 199 206 199 207 199 211 199 212 199 215 199 227 199 228 199 231 200 204 200 206 200 207 200 208 200 212 200 216 200 228 200 232 201 202 201 203 201 205 201 209 201 210 201 211 201 213 201 217 201 225 201 229 201 233 202 203 202 204 202 205 202 206 202 210 202 211 202 212 202 213 202 214 202 218 202 226 202 229 202 230 202 234 203 204 203 205 203 206 203 207 203 211 203 213 203 214 203 215 203 219 203 227 203 229 203 230 203 231 203 235 204 206 204 207 204 208 204 212 204 214 204 215 204 216 204 220 204 228 204 230 204 232 204 236 205 206 205 207 205 213 205 215 205 217 205 218 205 219 205 221 205 229 205 231 205 237 206 207 206 208 206 214 206 215 206 216 206 218 206 219 206 220 206 222 206 230 206 231 206 232 206 238 207 208 207 215 207 216 207 219 207 221 207 222 207 223 207 231 207 232 207 239 208 216 208 220 208 222 208 223 208 224 208 232 208 240 209 210 209 211 209 213 209 217 209 225 209 226 209 227 209 229 209 233 209 241 210 211 210 212 210 213 210 214 210 217 210 218 210 226 210 227 210 228 210 230 210 233 210 234 210 242 211 212 211 213 211 214 211 215 211 217 211 218 211 219 211 227 211 229 211 230 211 231 211 233 211 234 211 235 211 243 212 214 212 215 212 216 212 218 212 220 212 228 212 230 212 231 212 232 212 234 212 236 212 244 213 214 213 215 213 217 213 218 213 219 213 221 213 229 213 233 213 234 213 235 213 237 213 245 214 215 214 216 214 218 214 219 214 220 214 222 214 230 214 234 214 235 214 236 214 238 214 246 215 216 215 219 215 220 215 221 215 222 215 223 215 231 215 235 215 236 215 237 215 238 215 239 215 247 216 220 216 222 216 223 216 224 216 232 216 236 216 238 216 239 216 240 216 248 217 218 217 219 217 221 217 233 217 237 217 241 217 242 217 243 217 245 217 249 218 219 218 220 218 221 218 222 218 234 218 237 218 238 218 242 218 243 218 244 218 246 218 250 219 220 219 221 219 222 219 223 219 235 219 237 219 238 219 239 219 243 219 245 219 246 219 247 219 251 220 222 220 223 220 224 220 236 220 238 220 240 220 244 220 246 220 247 220 248 220 252 221 222 221 223 221 237 221 239 221 245 221 249 221 250 221 251 221 253 222 223 222 224 222 238 222 239 222 240 222 246 222 250 222 251 222 252 222 254 223 224 223 239 223 240 223 247 223 251 223 253 223 254 223 255 224 240 224 248 224 252 224 254 224 255 224 256 225 226 225 227 225 229 225 233 225 241 226 227 226 228 226 229 226 230 226 233 226 234 226 241 226 242 227 228 227 229 227 230 227 231 227 233 227 234 227 235 227 241 227 242 227 243 228 230 228 231 228 232 228 234 228 236 228 242 228 244 229 230 229 231 229 233 229 234 229 235 229 237 229 241 229 243 229 245 230 231 230 232 230 234 230 235 230 236 230 238 230 242 230 243 230 244 230 246 231 232 231 235 231 236 231 237 231 238 231 239 231 243 231 244 231 247 232 236 232 238 232 239 232 240 232 244 232 248 233 234 233 235 233 237 233 241 233 242 233 243 233 245 233 249 234 235 234 236 234 237 234 238 234 242 234 243 234 244 234 245 234 246 234 250 235 236 235 237 235 238 235 239 235 243 235 245 235 246 235 247 235 251 236 238 236 239 236 240 236 244 236 246 236 247 236 248 236 252 237 238 237 239 237 245 237 247 237 249 237 250 237 251 237 253 238 239 238 240 238 246 238 247 238 248 238 250 238 251 238 252 238 254 239 240 239 247 239 248 239 251 239 253 239 254 239 255 240 248 240 252 240 254 240 255 240 256 241 242 241 243 241 245 241 249 242 243 242 244 242 245 242 246 242 249 242 250 243 244 243 245 243 246 243 247 243 249 243 250 243 251 244 246 244 247 244 248 244 250 244 252 245 246 245 247 245 249 245 250 245 251 245 253 246 247 246 248 246 250 246 251 246 252 246 254 247 248 247 251 247 252 247 253 247 254 247 255 248 252 248 254 248 255 248 256 249 250 249 251 249 253 250 251 250 252 250 253 250 254 251 252 251 253 251 254 251 255 252 254 252 255 252 256 253 254 253 255 254 255 254 256 255 256 ; end; glpk-4.52.1/examples/money.mod0000644000062000006210000000341112175147600015366 0ustar maomkpasswd/* MONEY, a crypto-arithmetic puzzle */ /* Written in GNU MathProg by Andrew Makhorin */ /* This is the classic example of a crypto-arithmetic puzzle published in the Strand Magazine by Henry Dudeney: S E N D + M O R E --------- M O N E Y In this puzzle the same letters mean the same digits. The question is: how to replace all the letters with the respective digits that makes the calculation correct? The solution to this puzzle is: O = 0, M = 1, Y = 2, E = 5, N = 6, D = 7, R = 8, and S = 9. References: H. E. Dudeney, in Strand Magazine vol. 68 (July 1924), pp. 97, 214. (From Wikipedia, the free encyclopedia.) */ set LETTERS := { 'D', 'E', 'M', 'N', 'O', 'R', 'S', 'Y' }; /* set of letters */ set DIGITS := 0..9; /* set of digits */ var x{i in LETTERS, d in DIGITS}, binary; /* x[i,d] = 1 means that letter i is digit d */ s.t. one{i in LETTERS}: sum{d in DIGITS} x[i,d] = 1; /* each letter must correspond exactly to one digit */ s.t. alldiff{d in DIGITS}: sum{i in LETTERS} x[i,d] <= 1; /* different letters must correspond to different digits; note that some digits may not correspond to any letters at all */ var dig{i in LETTERS}; /* dig[i] is a digit corresponding to letter i */ s.t. map{i in LETTERS}: dig[i] = sum{d in DIGITS} d * x[i,d]; var carry{1..3}, binary; /* carry bits */ s.t. sum1: dig['D'] + dig['E'] = dig['Y'] + 10 * carry[1]; s.t. sum2: dig['N'] + dig['R'] + carry[1] = dig['E'] + 10 * carry[2]; s.t. sum3: dig['E'] + dig['O'] + carry[2] = dig['N'] + 10 * carry[3]; s.t. sum4: dig['S'] + dig['M'] + carry[3] = dig['O'] + 10 * dig['M']; s.t. note: dig['M'] >= 1; /* M must not be 0 */ solve; /* solve the puzzle */ display dig; /* and display its solution */ end; glpk-4.52.1/examples/mplsamp1.c0000644000062000006210000000142012175147600015432 0ustar maomkpasswd/* mplsamp1.c */ #include #include #include int main(void) { glp_prob *lp; glp_tran *tran; int ret; lp = glp_create_prob(); tran = glp_mpl_alloc_wksp(); ret = glp_mpl_read_model(tran, "egypt.mod", 0); if (ret != 0) { fprintf(stderr, "Error on translating model\n"); goto skip; } ret = glp_mpl_generate(tran, NULL); if (ret != 0) { fprintf(stderr, "Error on generating model\n"); goto skip; } glp_mpl_build_prob(tran, lp); ret = glp_write_mps(lp, GLP_MPS_FILE, NULL, "egypt.mps"); if (ret != 0) fprintf(stderr, "Error on writing MPS file\n"); skip: glp_mpl_free_wksp(tran); glp_delete_prob(lp); return 0; } /* eof */ glpk-4.52.1/examples/mplsamp2.c0000644000062000006210000000174012175147600015440 0ustar maomkpasswd/* mplsamp2.c */ #include #include #include int main(void) { glp_prob *mip; glp_tran *tran; int ret; mip = glp_create_prob(); tran = glp_mpl_alloc_wksp(); ret = glp_mpl_read_model(tran, "sudoku.mod", 1); if (ret != 0) { fprintf(stderr, "Error on translating model\n"); goto skip; } ret = glp_mpl_read_data(tran, "sudoku.dat"); if (ret != 0) { fprintf(stderr, "Error on translating data\n"); goto skip; } ret = glp_mpl_generate(tran, NULL); if (ret != 0) { fprintf(stderr, "Error on generating model\n"); goto skip; } glp_mpl_build_prob(tran, mip); glp_simplex(mip, NULL); glp_intopt(mip, NULL); ret = glp_mpl_postsolve(tran, mip, GLP_MIP); if (ret != 0) fprintf(stderr, "Error on postsolving model\n"); skip: glp_mpl_free_wksp(tran); glp_delete_prob(mip); return 0; } /* eof */ glpk-4.52.1/examples/murtagh.mps0000644000062000006210000003754012175147600015740 0ustar maomkpasswd*NAME: OIL *ROWS: 74 *COLUMNS: 81 *NONZERO: 504 *OPT SOLN: 126.057 *SOURCE: Bruce Murtagh, "Advanced Linear Programming" *APPLICATION: oil refinery model *COMMENTS: problem is maximization * NAME OIL REFINERY EXAMPLE ROWS N PROFIT L MVOLBOL L MVOLCOL E MVOLLNC E MVOLLNB E MVOLSRK E MVOLSRD E MVOLVBB E MVOLVBC E MVOLRCR E MVOLHVO E UBALKWH E UBALH2O E UBALSTM E UBALFUL E MVOLB95 E MVOLB90 E MVOLLHG E MVOLC3S E MVOLNC4 E MVOLLSR E MVOLHSR E MVOLIC4 L VCAPSGP E MVOLRFG E MSCFHYL E MVOLR90 E MVOLR95 E MVOLF90 E MVOLF95 L VCAPRFG E MVOLLCO E MVOLHHG E MVOLHCD L VCAPHVO L VCAPHOL E MVOLC3U E MVOLC4U E MVOLFCG E MVOLSLR L VCAPCCU E MVOLLA3 E MVOLLA4 L VCAPALK L XLPRPRE L XHPRPRE L XTELPRE L XRVPPRE L X200PRE L X230PRE E EVOLPRE L XPSCPRE L XRSCREG L XLPRINT L XHPRINT L XTELINT L XRVPINT L X200INT L X230INT E EVOLINT L XLPRREG L XHPRREG L XTELREG L XRVPREG L X200REG L X230REG E EVOLREG E EVOLLPG E EVOLJP4 L XRVXJP4 L XRVNJP4 E EVOLDSL E EVOLRSD L XVISRSD COLUMNS VCRDBOL MVOLBOL 1.0 VCRDBOL MVOLLNB -.537 VCRDBOL MVOLSRK -.131 VCRDBOL MVOLSRD -.1155 VCRDBOL MVOLVBB -.037 VCRDBOL MVOLRCR -.0365 VCRDBOL MVOLHVO -.143 VCRDBOL UBALKWH .302 VCRDBOL UBALH2O .150 VCRDBOL UBALSTM .003 VCRDBOL UBALFUL .0587 VCRDBOL PROFIT -12.8 VCRDCOL MVOLCOL 1. VCRDCOL MVOLLNC -.2931 VCRDCOL MVOLSRK -.1170 VCRDCOL MVOLSRD -.0649 VCRDCOL MVOLVBC -.18 VCRDCOL MVOLRCR -.1233 VCRDCOL MVOLHVO -.2217 VCRDCOL UBALKWH .384 VCRDCOL UBALH2O .185 VCRDCOL UBALSTM .003 VCRDCOL UBALFUL .1053 VCRDCOL PROFIT -11.48 VSGPLNC MVOLLNC 1. VSGPLNC MVOLC3S -.0112 VSGPLNC MVOLNC4 -.0378 VSGPLNC MVOLLSR -.1502 VSGPLNC MVOLHSR -.7953 VSGPLNC MVOLIC4 -.0099 VSGPLNC UBALKWH .721 VSGPLNC UBALH2O .185 VSGPLNC UBALSTM .013 VSGPLNC UBALFUL .0488 VSGPLNC VCAPSGP 1. VSGPLNB MVOLLNB 1. VSGPLNB MVOLC3S -.0277 VSGPLNB MVOLNC4 -.0563 VSGPLNB MVOLLSR -.199 VSGPLNB MVOLHSR -.6873 VSGPLNB MVOLIC4 -.017 VSGPLNB UBALKWH .495 VSGPLNB UBALH2O .209 VSGPLNB UBALSTM .013 VSGPLNB UBALFUL .0506 VSGPLNB VCAPSGP 1. VSGPLHG MVOLLHG 1.0 VSGPLHG MVOLC3S -.175 VSGPLHG MVOLNC4 -.27 VSGPLHG MVOLLSR -.028 VSGPLHG MVOLIC4 -.455 VSGPLHG UBALKWH .495 VSGPLHG UBALH2O .209 VSGPLHG UBALSTM .013 VSGPLHG UBALFUL .0448 VSGPB95 MVOLB95 1. VSGPB95 MVOLC3S -.2836 VSGPB95 MVOLNC4 -.3285 VSGPB95 MVOLLSR -.0241 VSGPB95 MVOLIC4 -.2502 VSGPB95 UBALKWH .495 VSGPB95 UBALH2O .209 VSGPB95 UBALSTM .013 VSGPB95 UBALFUL .0506 VSGPB90 MVOLB90 1. VSGPB90 MVOLC3S -.271 VSGPB90 MVOLNC4 -.3289 VSGPB90 MVOLLSR -.0255 VSGPB90 MVOLIC4 -.2656 VSGPB90 UBALKWH .495 VSGPB90 UBALH2O .209 VSGPB90 UBALSTM .013 VSGPB90 UBALFUL .0506 VH2RHSR MVOLHSR 1. VH2RHSR MVOLRFG -1. VH2RHSR MSCFHYL .0327 VH2RHSR UBALKWH .793 VH2RHSR UBALH2O .045 VH2RHSR UBALFUL .094 VH2RHSR PROFIT -.0176 VRFFRF1 MVOLRFG 1.0 VRFFRF1 MVOLR90 -1.0 VRFFRF2 MVOLRFG 1.0 VRFFRF2 MVOLR95 -1.0 VRFFHH1 MVOLR90 -1.0 VRFFHH1 MVOLHHG 1.0 VRFFHH2 MVOLR95 -1.0 VRFFHH2 MVOLHHG 1.0 VRFGR90 MVOLR90 1.0 VRFGR90 MVOLB90 -.0404 VRFGR90 MVOLF90 -0.8564 VRFGR90 MSCFHYL -0.8239 VRFGR90 UBALKWH .792 VRFGR90 UBALH2O .297 VRFGR90 UBALSTM 0.0063 VRFGR90 UBALFUL -0.156 VRFGR90 VCAPRFG 1.0 VRFGR90 PROFIT -0.1512 VRFGR95 MVOLR95 1.0 VRFGR95 MVOLB95 -0.0588 VRFGR95 MVOLF95 -0.8145 VRFGR95 MSCFHYL -.7689 VRFGR95 UBALKWH 1.03 VRFGR95 UBALH2O .387 VRFGR95 UBALSTM 0.008 VRFGR95 UBALFUL -.2112 VRFGR95 VCAPRFG 1.3 VRFGR95 PROFIT -0.304 VHOLLCO MVOLLCO 1.0 VHOLLCO MVOLHHG -.6627 VHOLLCO MVOLLHG -0.2414 VHOLLCO MVOLHCD -.2930 VHOLLCO MSCFHYL 2.3 VHOLLCO UBALFUL -.2054 VHOLLCO UBALH2O 0.826 VHOLLCO UBALKWH 14.61 VHOLLCO VCAPHOL 1.0 VHOLLCO PROFIT -0.2112 VHOLSRD MVOLSRD 1.0 VHOLSRD MVOLHHG -.6627 VHOLSRD MVOLLHG -0.2414 VHOLSRD MVOLHCD -.2930 VHOLSRD MSCFHYL 2.3 VHOLSRD UBALFUL -.2054 VHOLSRD UBALH2O 0.826 VHOLSRD UBALKWH 14.61 VHOLSRD VCAPHOL 1.0 VHOLSRD PROFIT -0.2112 VHOLRCR MVOLRCR 1.0 VHOLRCR MVOLHHG -.5875 VHOLRCR MVOLLHG -0.3321 VHOLRCR MVOLHCD -.3620 VHOLRCR MSCFHYL 2.3 VHOLRCR UBALFUL -.2054 VHOLRCR UBALH2O 0.826 VHOLRCR UBALKWH 14.61 VHOLRCR VCAPHOL 1.0 VHOLRCR PROFIT -0.2112 VHOLHVO MVOLHVO 1.0 VHOLHVO MVOLHHG -.5875 VHOLHVO MVOLLHG -0.3321 VHOLHVO MVOLHCD -.3620 VHOLHVO MSCFHYL 2.3 VHOLHVO UBALFUL -.2054 VHOLHVO UBALH2O 0.826 VHOLHVO UBALKWH 14.61 VHOLHVO VCAPHVO 1.0 VHOLHVO VCAPHOL 1.0 VHOLHVO PROFIT -0.2112 VCCUSRK MVOLSRK 1.0 VCCUSRK MVOLNC4 -0.0184 VCCUSRK MVOLC3S -0.0303 VCCUSRK MVOLIC4 -0.0564 VCCUSRK MVOLC3U -0.0655 VCCUSRK MVOLC4U -0.0780 VCCUSRK MVOLFCG -0.4750 VCCUSRK MVOLLCO -0.3050 VCCUSRK UBALSTM -.0654 VCCUSRK UBALFUL -.2703 VCCUSRK UBALH2O .632 VCCUSRK UBALKWH .6807 VCCUSRK VCAPCCU 1. VCCUSRK PROFIT -.2112 VCCUSRD MVOLSRD 1. VCCUSRD MVOLNC4 -.0184 VCCUSRD MVOLC3S -.0303 VCCUSRD MVOLIC4 -.0564 VCCUSRD MVOLC3U -.0655 VCCUSRD MVOLC4U -.0780 VCCUSRD MVOLFCG -.4750 VCCUSRD MVOLLCO -.3050 VCCUSRD UBALSTM -.0654 VCCUSRD UBALFUL -.2703 VCCUSRD UBALH2O 0.632 VCCUSRD UBALKWH .6807 VCCUSRD VCAPCCU 1. VCCUSRD PROFIT -.2112 VCCURCR MVOLRCR 1.0 VCCURCR MVOLNC4 -.0185 VCCURCR MVOLC3S -.0328 VCCURCR MVOLIC4 -.0568 VCCURCR MVOLC3U -.0658 VCCURCR MVOLC4U -.0806 VCCURCR MVOLFCG -.4934 VCCURCR MVOLLCO -.2922 VCCURCR MVOLSLR -.0096 VCCURCR UBALSTM -.0654 VCCURCR UBALFUL -.2703 VCCURCR UBALH2O 0.632 VCCURCR UBALKWH .6807 VCCURCR VCAPCCU 1. VCCURCR PROFIT -.2112 VCCUHVO MVOLHVO 1.0 VCCUHVO MVOLNC4 -.0185 VCCUHVO MVOLC3S -.0328 VCCUHVO MVOLIC4 -.0568 VCCUHVO MVOLC3U -.0658 VCCUHVO MVOLC4U -.0806 VCCUHVO MVOLFCG -.4934 VCCUHVO MVOLLCO -.2922 VCCUHVO MVOLSLR -.0096 VCCUHVO UBALSTM -.0654 VCCUHVO UBALFUL -.2703 VCCUHVO UBALH2O 0.632 VCCUHVO UBALKWH .6807 VCCUHVO VCAPHVO 1. VCCUHVO VCAPCCU 1. VCCUHVO PROFIT -.2112 VALKLA3 MVOLIC4 .7600 VALKLA3 MVOLC3U .5714 VALKLA3 MVOLLA3 -1.0 VALKLA3 UBALSTM .1869 VALKLA3 UBALFUL .2796 VALKLA3 UBALH2O 2.241 VALKLA3 UBALKWH 2.766 VALKLA3 VCAPALK 1.0 VALKLA3 PROFIT -.512 VALKLA4 MVOLIC4 .6571 VALKLA4 MVOLC4U .5714 VALKLA4 MVOLC3S -.0571 VALKLA4 MVOLNC4 -.0114 VALKLA4 MVOLLA4 -1.0 VALKLA4 UBALSTM .1724 VALKLA4 UBALFUL .2579 VALKLA4 UBALH2O 2.067 VALKLA4 UBALKWH 2.552 VALKLA4 VCAPALK 1.0 VALKLA4 PROFIT -.472 VALKIC4 MVOLIC4 1.0 VALKIC4 MVOLNC4 -1.0 VALKC3U MVOLC3U 1.0 VALKC3U MVOLC3S -1.0 VALKC4U MVOLC4U 1.0 VALKC4U MVOLNC4 -1.0 UTILC3S MVOLC3S 1. UTILC3S UBALFUL -3.814 UTILNC4 MVOLNC4 1. UTILNC4 UBALFUL -4.316 UTILIC4 MVOLIC4 1. UTILIC4 UBALFUL -4.153 UTILC3U MVOLC3U 1. UTILC3U UBALFUL -3.808 UTILC4U MVOLC4U 1. UTILC4U UBALFUL -4.44 UTILHYL MSCFHYL 1. UTILHYL UBALFUL -.305 UTILSTM UBALSTM -1. UTILSTM UBALFUL 1.42 UTILSTM PROFIT -.16 PURCPC4 MVOLIC4 -.5 PURCPC4 MVOLNC4 -.5 PURCPC4 PROFIT -12. PURCH2O UBALH2O -1. PURCH2O PROFIT -.0528 PURCKWH UBALKWH -1. PURCKWH PROFIT -.04 PURCFUL UBALFUL -1. PURCFUL PROFIT -1.6 PURCFLR UBALFUL 1. BLPGC3S MVOLC3S 1.0 BLPGC3S EVOLLPG -1.0 BLPGNC4 MVOLNC4 1.0 BLPGNC4 EVOLLPG -1.0 SELLLPG EVOLLPG 1.0 SELLLPG PROFIT 11.0 BUP4LSR MVOLLSR 1.0 BUP4LSR EVOLJP4 -1.0 BUP4LSR XRVXJP4 14.0 BUP4LSR XRVNJP4 -14.0 BUP4HSR MVOLHSR 1.0 BUP4HSR EVOLJP4 -1.0 BUP4HSR XRVXJP4 0.8 BUP4HSR XRVNJP4 -0.8 SELLJP4 EVOLJP4 1.0 SELLJP4 XRVXJP4 -3.0 SELLJP4 XRVNJP4 2.0 SELLJP4 PROFIT 16.8 BDSLSRK MVOLSRK 1.0 BDSLSRK EVOLDSL -1.0 BDSLSRD MVOLSRD 1.0 BDSLSRD EVOLDSL -1.0 SELLDSL EVOLDSL 1.0 SELLDSL PROFIT 14.4 BPRELSR MVOLLSR 1. BPRELSR XLPRPRE -7.95 BPRELSR XHPRPRE -8.70 BPRELSR XTELPRE -3.00 BPRELSR XRVPPRE 14.00 BPRELSR X200PRE 1. BPRELSR X230PRE -1. BPRELSR EVOLPRE -1. BPREHCD MVOLHCD 1.0 BPREHCD XLPRPRE -8.84 BPREHCD XHPRPRE -9.45 BPREHCD XTELPRE -3.00 BPREHCD XRVPPRE 12.00 BPREHCD X200PRE 1. BPREHCD X230PRE -1. BPREHCD EVOLPRE -1. BPREF95 MVOLF95 1.0 BPREF95 XLPRPRE -9.43 BPREF95 XHPRPRE -9.57 BPREF95 XTELPRE -3. BPREF95 XRVPPRE 3.5 BPREF95 X200PRE .233 BPREF95 X230PRE -.358 BPREF95 EVOLPRE -1. BPREF90 MVOLF90 1.0 BPREF90 XLPRPRE -9.03 BPREF90 XHPRPRE -9.32 BPREF90 XTELPRE -3.0 BPREF90 XRVPPRE 3.5 BPREF90 X200PRE .205 BPREF90 X230PRE -.333 BPREF90 EVOLPRE -1. BPREFCG MVOLFCG 1.0 BPREFCG XLPRPRE -9.23 BPREFCG XHPRPRE -9.22 BPREFCG XTELPRE -3. BPREFCG XRVPPRE 6. BPREFCG X200PRE .381 BPREFCG X230PRE -.509 BPREFCG EVOLPRE -1. BPRELA3 MVOLLA3 1.0 BPRELA3 XLPRPRE -9.4 BPRELA3 XHPRPRE -9.85 BPRELA3 XTELPRE -3.0 BPRELA3 XRVPPRE 2.5 BPRELA3 X200PRE 0.39 BPRELA3 X230PRE -0.77 BPRELA3 EVOLPRE -1.0 BPRELA4 MVOLLA4 1.0 BPRELA4 XLPRPRE -9.74 BPRELA4 XHPRPRE -10.1 BPRELA4 XTELPRE -3.0 BPRELA4 XRVPPRE 3.3 BPRELA4 X200PRE 0.233 BPRELA4 X230PRE -0.58 BPRELA4 EVOLPRE -1.0 BPRENC4 MVOLNC4 1.0 BPRENC4 XLPRPRE -9.74 BPRENC4 XHPRPRE -9.9 BPRENC4 XTELPRE -3.0 BPRENC4 XRVPPRE 66.0 BPRENC4 X200PRE 1.0 BPRENC4 X230PRE -1.0 BPRENC4 EVOLPRE -1.0 BPRETEL XLPRPRE -0.493 BPRETEL XHPRPRE -0.165 BPRETEL XTELPRE 1.0 BPRETEL PROFIT -0.3696 SELLPRE XLPRPRE 10.03 SELLPRE XHPRPRE 10.03 SELLPRE XRVPPRE -9.5 SELLPRE X200PRE -0.5 SELLPRE X230PRE 0.5 SELLPRE XPSCPRE 0.64 SELLPRE XRSCREG 0.35 SELLPRE EVOLPRE 1.0 SELLPRE PROFIT 21.44 BINTLSR MVOLLSR 1.0 BINTLSR XLPRINT -7.98 BINTLSR XHPRINT -8.58 BINTLSR XTELINT -3.0 BINTLSR XRVPINT 14.0 BINTLSR X200INT 1.0 BINTLSR X230INT -1.0 BINTLSR EVOLINT -1.0 BINTHCD MVOLHCD 1. BINTHCD XLPRINT -8.87 BINTHCD XHPRINT -9.33 BINTHCD XTELINT -3.0 BINTHCD XRVPINT 12.0 BINTHCD X200INT 1.0 BINTHCD X230INT -1. BINTHCD EVOLINT -1.0 BINTF95 MVOLF95 1. BINTF95 XLPRINT -9.46 BINTF95 XHPRINT -9.45 BINTF95 XTELINT -3.0 BINTF95 XRVPINT 3.5 BINTF95 X200INT .233 BINTF95 X230INT -.358 BINTF95 EVOLINT -1.0 BINTF90 MVOLF90 1. BINTF90 XLPRINT -9.06 BINTF90 XHPRINT -9.20 BINTF90 XTELINT -3.0 BINTF90 XRVPINT 3.5 BINTF90 X200INT .205 BINTF90 X230INT -.333 BINTF90 EVOLINT -1.0 BINTFCG MVOLFCG 1. BINTFCG XLPRINT -9.26 BINTFCG XHPRINT -9.13 BINTFCG XTELINT -3.0 BINTFCG XRVPINT 6. BINTFCG X200INT .318 BINTFCG X230INT -.509 BINTFCG EVOLINT -1.0 BINTNC4 MVOLNC4 1. BINTNC4 XLPRINT -9.77 BINTNC4 XHPRINT -9.78 BINTNC4 XTELINT -3.0 BINTNC4 XRVPINT 66. BINTNC4 X200INT 1.0 BINTNC4 X230INT -1. BINTNC4 EVOLINT -1.0 BINTTEL XLPRINT -.435 BINTTEL XHPRINT -.208 BINTTEL XTELINT 1. BINTTEL PROFIT -.3696 SELLINT XLPRINT 9.65 SELLINT XHPRINT 9.65 SELLINT XRVPINT -9.5 SELLINT X200INT -0.5 SELLINT X230INT 0.5 SELLINT XPSCPRE -.36 SELLINT XRSCREG 0.35 SELLINT EVOLINT 1.0 SELLINT PROFIT 20.32 BREGLSR MVOLLSR 1.0 BREGLSR XLPRREG -7.99 BREGLSR XHPRREG -8.59 BREGLSR XTELREG -3.0 BREGLSR XRVPREG 14.0 BREGLSR X200REG 1.0 BREGLSR X230REG -1.0 BREGLSR EVOLREG -1.0 BREGHCD MVOLHCD 1.0 BREGHCD XLPRREG -8.88 BREGHCD XHPRREG -9.34 BREGHCD XTELREG -3.0 BREGHCD XRVPREG 12.0 BREGHCD X200REG 1.0 BREGHCD X230REG -1.0 BREGHCD EVOLREG -1.0 BREGF95 MVOLF95 1.0 BREGF95 XLPRREG -9.47 BREGF95 XHPRREG -9.46 BREGF95 XTELREG -3.0 BREGF95 XRVPREG 3.5 BREGF95 X200REG .233 BREGF95 X230REG -0.358 BREGF95 EVOLREG -1.0 BREGF90 MVOLF90 1.0 BREGF90 XLPRREG -9.07 BREGF90 XHPRREG -9.21 BREGF90 XTELREG -3.0 BREGF90 XRVPREG 3.5 BREGF90 X200REG .205 BREGF90 X230REG -0.333 BREGF90 EVOLREG -1.0 BREGFCG MVOLFCG 1.0 BREGFCG XLPRREG -9.27 BREGFCG XHPRREG -9.14 BREGFCG XTELREG -3.0 BREGFCG XRVPREG 6.0 BREGFCG X200REG 0.318 BREGFCG X230REG -0.509 BREGFCG EVOLREG -1.0 BREGNC4 MVOLNC4 1.0 BREGNC4 XLPRREG -9.78 BREGNC4 XHPRREG -9.79 BREGNC4 XTELREG -3.0 BREGNC4 XRVPREG 66.0 BREGNC4 X200REG 1.0 BREGNC4 X230REG -1.0 BREGNC4 EVOLREG -1.0 BREGTEL XLPRREG -0.426 BREGTEL XHPRREG -.204 BREGTEL XTELREG 1.0 BREGTEL PROFIT -0.3696 SELLREG XLPRREG 9.05 SELLREG XHPRREG 9.05 SELLREG XRVPREG -9.5 SELLREG X200REG -0.5 SELLREG X230REG 0.5 SELLREG XPSCPRE -0.36 SELLREG XRSCREG -0.65 SELLREG EVOLREG 1.0 SELLREG PROFIT 18.04 BRSDVBB MVOLVBB 1.0 BRSDVBB EVOLRSD -1.0 BRSDVBB XVISRSD 10.1 BRSDVBC MVOLVBC 1.0 BRSDVBC EVOLRSD -1.0 BRSDVBC XVISRSD 12.63 BRSDRCR MVOLRCR 1.0 BRSDRCR EVOLRSD -1.0 BRSDRCR XVISRSD 6.9 BRSDHVO MVOLHVO 1.0 BRSDHVO EVOLRSD -1.0 BRSDHVO XVISRSD 8.05 BRSDHVO VCAPHVO 1.0 BRSDSLR MVOLSLR 1.0 BRSDSLR EVOLRSD -1.0 BRSDSLR XVISRSD 8.05 BRSDLCO MVOLLCO 1.0 BRSDLCO EVOLRSD -1.0 BRSDLCO XVISRSD 4.4 SELLRSD EVOLRSD 1.0 SELLRSD XVISRSD -10.1 SELLRSD PROFIT 8.00 RHS LIMITMAX MVOLBOL 26.316 LIMITMAX MVOLCOL 21.052 LIMITMAX VCAPSGP 23.25 LIMITMAX VCAPHVO 5.25 LIMITMAX VCAPRFG 13.455 LIMITMAX VCAPHOL 3.87 LIMITMAX VCAPCCU 7.26 LIMITMAX VCAPALK 10. ENDATA glpk-4.52.1/examples/mvcp.mod0000644000062000006210000000256512175147600015215 0ustar maomkpasswd/* MVCP, Minimum Vertex Cover Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Minimum Vertex Cover Problem in a network G = (V, E), where V is a set of nodes, E is a set of arcs, is to find a subset V' within V such that each edge (i,j) in E has at least one its endpoint in V' and which minimizes the sum of node weights w(i) over V'. Reference: Garey, M.R., and Johnson, D.S. (1979), Computers and Intractability: A guide to the theory of NP-completeness [Graph Theory, Covering and Partitioning, Minimum Vertex Cover, GT1]. */ set E, dimen 2; /* set of edges */ set V := (setof{(i,j) in E} i) union (setof{(i,j) in E} j); /* set of nodes */ param w{i in V}, >= 0, default 1; /* w[i] is weight of vertex i */ var x{i in V}, binary; /* x[i] = 1 means that node i is included into V' */ s.t. cov{(i,j) in E}: x[i] + x[j] >= 1; /* each edge (i,j) must have node i or j (or both) in V' */ minimize z: sum{i in V} w[i] * x[i]; /* we need to minimize the sum of node weights over V' */ data; /* These data correspond to an example from [Papadimitriou]. */ /* Optimal solution is 6 (greedy heuristic gives 13) */ set E := a1 b1, b1 c1, a1 b2, b2 c2, a2 b3, b3 c3, a2 b4, b4 c4, a3 b5, b5 c5, a3 b6, b6 c6, a4 b1, a4 b2, a4 b3, a5 b4, a5 b5, a5 b6, a6 b1, a6 b2, a6 b3, a6 b4, a7 b2, a7 b3, a7 b4, a7 b5, a7 b6; end; glpk-4.52.1/examples/netgen.c0000644000062000006210000001265512175147600015174 0ustar maomkpasswd/* netgen.c */ /* This main program generates 50 original NETGEN instances of the minimum cost flow problem and writes them in DIMACS format to the current directory. */ #include #include #include #include static int parm[50][15] = { {13502460, 101, 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, },{4281922, 102, 5000, 2500, 2500, 25000, 1, 100, 2500000, 0, 0, 0, 100, 1, 1000, },{44820113, 103, 5000, 2500, 2500, 25000, 1, 100, 6250000, 0, 0, 0, 100, 1, 1000, },{13450451, 104, 5000, 2500, 2500, 25000, -100, -1, 250000, 0, 0, 0, 100, 1, 1000, },{14719436, 105, 5000, 2500, 2500, 25000, 101, 200, 250000, 0, 0, 0, 100, 1, 1000, },{17365786, 106, 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 100, 1, 1000, },{19540113, 107, 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 100, 1, 1000, },{19560313, 108, 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 100, 1, 1000, },{2403509, 109, 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 100, 1, 1000, },{92480414, 110, 5000, 2500, 2500, 12500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, },{4230140, 111, 5000, 2500, 2500, 37500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, },{10032490, 112, 5000, 2500, 2500, 50000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, },{17307474, 113, 5000, 2500, 2500, 75000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, },{4925114, 114, 5000, 500, 4500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, },{19842704, 115, 5000, 1500, 3500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000, },{88392060, 116, 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 0, 1, 1000, },{12904407, 117, 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 0, 1, 1000, },{11811811, 118, 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 0, 1, 1000, },{90023593, 119, 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 0, 1, 1000, },{93028922, 120, 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 0, 1, 1000, },{72707401, 121, 5000, 50, 50, 25000, 1, 100, 250000, 50, 50, 0, 100, 1, 1000, },{93040771, 122, 5000, 250, 250, 25000, 1, 100, 250000, 250, 250, 0, 100, 1, 1000, },{70220611, 123, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{52774811, 124, 5000, 1000, 1000, 25000, 1, 100, 250000, 1000, 1000, 0, 100, 1, 1000, },{22492311, 125, 5000, 1500, 1500, 25000, 1, 100, 250000, 1500, 1500, 0, 100, 1, 1000, },{35269337, 126, 5000, 500, 500, 12500, 1, 100, 125000, 500, 500, 0, 100, 1, 1000, },{30140502, 127, 5000, 500, 500, 37500, 1, 100, 375000, 500, 500, 0, 100, 1, 1000, },{49205455, 128, 5000, 500, 500, 50000, 1, 100, 500000, 500, 500, 0, 100, 1, 1000, },{42958341, 129, 5000, 500, 500, 75000, 1, 100, 750000, 500, 500, 0, 100, 1, 1000, },{25440925, 130, 5000, 500, 500, 12500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{75294924, 131, 5000, 500, 500, 37500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{4463965, 132, 5000, 500, 500, 50000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{13390427, 133, 5000, 500, 500, 75000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{95250971, 134, 1000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{54830522, 135, 2500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{520593, 136, 7500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{52900925, 137, 10000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000, },{22603395, 138, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 50, },{55253099, 139, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 250, },{75357001, 140, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 500, },{10072459, 141, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 2500, },{55728492, 142, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 5000, },{593043, 143, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 0, 1, 1000, },{94236572, 144, 5000, 500, 500, 25000, 1, 10, 250000, 500, 500, 0, 100, 1, 1000, },{94882955, 145, 5000, 500, 500, 25000, 1, 1000, 250000, 500, 500, 0, 100, 1, 1000, },{48489922, 146, 5000, 500, 500, 25000, 1, 10000, 250000, 500, 500, 0, 100, 1, 1000, },{75578374, 147, 5000, 500, 500, 25000, -100, -1, 250000, 500, 500, 0, 100, 1, 1000, },{44821152, 148, 5000, 500, 500, 25000, -50, 49, 250000, 500, 500, 0, 100, 1, 1000, },{45224103, 149, 5000, 500, 500, 25000, 101, 200, 250000, 500, 500, 0, 100, 1, 1000, },{63491741, 150, 5000, 500, 500, 25000, 1001, 1100, 250000, 500, 500, 0, 100, 1, 1000, } }; typedef struct { double rhs; } v_data; typedef struct { double cap, cost; } a_data; int main(void) { glp_graph *G; int k; char fname[100+1]; G = glp_create_graph(sizeof(v_data), sizeof(a_data)); for (k = 1; k <= 50; k++) { sprintf(fname, "netgn%03d.min", parm[k-1][1]); glp_netgen(G, offsetof(v_data, rhs), offsetof(a_data, cap), offsetof(a_data, cost), &parm[k-1][-1]); glp_write_mincost(G, offsetof(v_data, rhs), -1, offsetof(a_data, cap), offsetof(a_data, cost), fname); } glp_delete_graph(G); return 0; } /* eof */ glpk-4.52.1/examples/numbrix.mod0000644000062000006210000000500012175147600015717 0ustar maomkpasswd/* Numbrix, Number Placement Puzzle */ /* Written in GNU MathProg by Robert Wood */ /* Numbrix is a logic-based number-placement puzzle.[1] * The objective is to fill the grid so that each cell contains * digits in sequential order taking a horizontal or vertical * path; diagonal paths are not allowed. The puzzle setter * provides a grid often with the outer most cells completed. * * Completed Numbrix puzzles are usually a square of numbers * in order from 1 to 64 (8x8 grid) or from 1 to 81 (9x9 grid), * following a continuous path in sequence. * * The modern puzzle was invented by Marilyn vos Savant in 2008 * and published by Parade Magazine under the name "Numbrix", * near her weekly Ask Marilyn article. * * http://en.wikipedia.org/wiki/Numbrix */ set I := {1..9}; set J := {1..9}; set VALS := {1..81}; param givens{I, J}, integer, >= 0, <= 81, default 0; /* the "givens" */ param neighbors{i in I,j in J, i2 in I, j2 in J} , binary := (if abs(i - i2) + abs(j -j2) == 1 then 1 else 0 ); /* defines which spots are the boards are neighbors */ var x{i in I, j in J, k in VALS}, binary; /* x[i,j,k] = 1 means cell [i,j] is assigned number k */ s.t. fa{i in I, j in J, k in VALS: givens[i,j] != 0}: x[i,j,k] = (if givens[i,j] = k then 1 else 0); /* assign pre-defined numbers using the "givens" */ s.t. fb{i in I, j in J}: sum{k in VALS} x[i,j,k] = 1; /* each cell must be assigned exactly one number */ s.t. singleNum {k in VALS}: sum{i in I, j in J} x[i,j,k] = 1; /* a value can only occur once */ s.t. neighborContraint {i in I, j in J, k in 1..80}: x[i,j,k] <= sum{i2 in I, j2 in J} x[i2,j2,k+1] * neighbors[i,j,i2,j2]; /* each cell must have a neighbor with the next higher value */ /* there is no need for an objective function here */ solve; for {i in I} { for {0..0: i = 1 or i = 4 or i = 7} printf " +----------+----------+----------+\n"; for {j in J} { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); printf " %2d", sum{k in VALS} x[i,j,k] * k; for {0..0: j = 9} printf(" |\n"); } for {0..0: i = 9} printf " +----------+----------+----------+\n"; } data; param givens : 1 2 3 4 5 6 7 8 9 := 1 . . . . . . . . . 2 . 11 12 15 18 21 62 61 . 3 . 6 . . . . . 60 . 4 . 33 . . . . . 57 . 5 . 32 . . . . . 56 . 6 . 37 . . . . . 73 . 7 . 38 . . . . . 72 . 8 . 43 44 47 48 51 76 77 . 9 . . . . . . . . . ; end; glpk-4.52.1/examples/pbn/0000755000062000006210000000000012175147600014316 5ustar maomkpasswdglpk-4.52.1/examples/pbn/9dom.dat0000644000062000006210000000221712175147600015662 0ustar maomkpasswd/* 9dom.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #8098 from . * Copyright (C) 2010 by Josh Greifer. Used by permission. * * Domino Logic III (Abstract pattern) * * created by Josh Greifer * Apr 5, 2010 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 19; param n := 19; param row : 1 2 := 1 3 . 2 1 . 3 3 1 4 1 . 5 3 1 6 1 . 7 3 1 8 1 . 9 3 1 10 1 . 11 3 1 12 1 . 13 3 1 14 1 . 15 3 1 16 1 . 17 3 1 18 1 . 19 1 . ; param col : 1 2 := 1 1 . 2 1 . 3 1 3 4 1 . 5 1 3 6 1 . 7 1 3 8 1 . 9 1 3 10 1 . 11 1 3 12 1 . 13 1 3 14 1 . 15 1 3 16 1 . 17 1 3 18 1 . 19 3 . ; end; glpk-4.52.1/examples/pbn/bucks.dat0000644000062000006210000000412112175147600016115 0ustar maomkpasswd/* bucks.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #27 from . * Copyright (C) 2004 by Jan Wolter. Used by permission. * * Party at the Right [Political] * * created by Jan Wolter * Apr 6, 2004 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 23; param n := 27; param row : 1 2 3 4 5 6 7 8 := 1 11 . . . . . . . 2 17 . . . . . . . 3 3 5 5 3 . . . . 4 2 2 2 1 . . . . 5 2 1 3 1 3 1 4 . 6 3 3 3 3 . . . . 7 5 1 3 1 3 1 3 . 8 3 2 2 4 . . . . 9 5 5 5 5 . . . . 10 23 . . . . . . . 11 . . . . . . . . 12 23 . . . . . . . 13 1 1 . . . . . . 14 1 1 . . . . . . 15 1 2 1 . . . . . 16 1 1 1 1 . . . . 17 1 1 1 1 . . . . 18 1 10 1 2 1 . . . 19 1 1 1 1 1 1 3 . 20 1 1 1 1 1 1 1 1 21 1 1 1 1 1 1 1 . 22 1 1 1 1 2 2 . . 23 5 5 3 . . . . . ; param col : 1 2 3 4 5 6 := 1 4 12 . . . . 2 6 1 1 . . . 3 8 1 1 . . . 4 3 2 2 1 1 . 5 2 1 1 2 1 6 6 1 1 1 1 . . 7 3 1 1 2 1 1 8 3 2 3 1 1 . 9 10 1 1 . . . 10 4 2 2 1 1 . 11 3 1 1 2 1 1 12 2 1 1 1 . . 13 3 1 1 2 1 1 14 3 2 3 1 6 . 15 10 1 1 . . . 16 4 2 2 1 1 . 17 3 1 1 2 1 1 18 1 1 1 9 . . 19 2 1 1 2 1 1 20 2 2 3 1 3 . 21 8 1 5 . . . 22 6 1 1 . . . 23 4 9 1 . . . 24 1 1 . . . . 25 2 1 . . . . 26 1 1 . . . . 27 4 . . . . . ; end; glpk-4.52.1/examples/pbn/cat.dat0000644000062000006210000000251612175147600015563 0ustar maomkpasswd/* cat.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #6 from . * Copyright (C) 2004 by Jan Wolter. Used by permission. * * Scardy Cat * * created by Jan Wolter * Mar 24, 2004 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 20; param n := 20; param row : 1 2 3 4 := 1 2 . . . 2 2 . . . 3 1 . . . 4 1 . . . 5 1 3 . . 6 2 5 . . 7 1 7 1 1 8 1 8 2 2 9 1 9 5 . 10 2 16 . . 11 1 17 . . 12 7 11 . . 13 5 5 3 . 14 5 4 . . 15 3 3 . . 16 2 2 . . 17 2 1 . . 18 1 1 . . 19 2 2 . . 20 2 2 . . ; param col : 1 2 3 := 1 5 . . 2 5 3 . 3 2 3 4 4 1 7 2 5 8 . . 6 9 . . 7 9 . . 8 8 . . 9 7 . . 10 8 . . 11 9 . . 12 10 . . 13 13 . . 14 6 2 . 15 4 . . 16 6 . . 17 6 . . 18 5 . . 19 6 . . 20 6 . . ; end; glpk-4.52.1/examples/pbn/dancer.dat0000644000062000006210000000145612175147600016252 0ustar maomkpasswd/* dancer.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #1 from . * Copyright (C) 2004 by Jan Wolter. Used by permission. * * Demo Puzzle from Front Page * * created by Jan Wolter * Mar 24, 2004 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 10; param n := 5; param row : 1 2 3 := 1 2 . . 2 2 1 . 3 1 1 . 4 3 . . 5 1 1 . 6 1 1 . 7 2 . . 8 1 1 . 9 1 2 . 10 2 . . ; param col : 1 2 3 := 1 2 1 . 2 2 1 3 3 7 . . 4 1 3 . 5 2 1 . ; end; glpk-4.52.1/examples/pbn/dragon.dat0000644000062000006210000000324012175147600016261 0ustar maomkpasswd/* dragon.dat */ /*********************************************************************** * Hard 20x20 paint-by-numbers puzzle designed by Won Yoon Jo * from the article "Painting by Numbers" by Robert A. Bosch (2000), * . * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 20; param n := 20; param row : 1 2 3 4 5 := 1 7 1 . . . 2 1 1 2 . . 3 2 1 2 . . 4 1 2 2 . . 5 4 2 3 . . 6 3 1 4 . . 7 3 1 3 . . 8 2 1 4 . . 9 2 9 . . . 10 2 1 5 . . 11 2 7 . . . 12 14 . . . . 13 8 2 . . . 14 6 2 2 . . 15 2 8 1 3 . 16 1 5 5 2 . 17 1 3 2 4 1 18 3 1 2 4 1 19 1 1 3 1 3 20 2 1 1 2 . ; param col : 1 2 3 4 5 := 1 1 1 1 2 . 2 3 1 2 1 1 3 1 4 2 1 1 4 1 3 2 4 . 5 1 4 6 1 . 6 1 11 1 . . 7 5 1 6 2 . 8 14 . . . . 9 7 2 . . . 10 7 2 . . . 11 6 1 1 . . 12 9 2 . . . 13 3 1 1 1 . 14 3 1 3 . . 15 2 1 3 . . 16 2 1 5 . . 17 3 2 2 . . 18 3 3 2 . . 19 2 3 2 . . 20 2 6 . . . ; end; glpk-4.52.1/examples/pbn/edge.dat0000644000062000006210000000150112175147600015711 0ustar maomkpasswd/* edge.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #23 from . * Copyright (C) 2004 by Jan Wolter. Used by permission. * * Nonrepresentational Test Pattern * * created by Jan Wolter * Apr 5, 2004 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 11; param n := 10; param row : 1 := 1 1 2 3 3 1 4 2 5 1 6 3 7 3 8 1 9 2 10 2 11 4 ; param col : 1 2 := 1 1 . 2 3 . 3 1 . 4 2 2 5 2 . 6 4 . 7 1 . 8 3 . 9 3 . 10 1 . ; end; glpk-4.52.1/examples/pbn/forever.dat0000644000062000006210000000434312175147600016464 0ustar maomkpasswd/* forever.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #6574 from . * Copyright (C) 2009 by Gator. Used by permission. * * Lasts Forever * * created by Gator * Aug 24, 2009 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 25; param n := 25; param row : 1 2 3 4 5 6 7 8 := 1 1 2 2 2 2 2 1 . 2 1 2 2 2 2 2 1 1 3 1 1 . . . . . . 4 1 1 . . . . . . 5 1 3 1 . . . . . 6 1 13 1 . . . . . 7 1 13 1 . . . . . 8 1 13 1 . . . . . 9 1 4 4 1 . . . . 10 1 4 3 4 1 . . . 11 1 4 5 4 1 . . . 12 1 7 1 . . . . . 13 1 7 1 . . . . . 14 1 7 1 . . . . . 15 1 7 1 . . . . . 16 1 1 5 1 . . . . 17 1 2 6 1 . . . . 18 1 4 6 1 . . . . 19 1 6 6 1 . . . . 20 1 3 1 . . . . . 21 1 1 1 . . . . . 22 1 1 . . . . . . 23 1 1 . . . . . . 24 1 1 2 2 2 2 2 1 25 1 2 2 2 2 2 1 . ; param col : 1 2 3 4 5 6 7 8 := 1 1 2 2 2 2 2 1 . 2 1 1 2 2 2 2 2 1 3 1 1 . . . . . . 4 1 1 . . . . . . 5 1 1 . . . . . . 6 1 2 1 . . . . . 7 1 6 1 1 . . . . 8 1 6 2 1 . . . . 9 1 6 3 1 . . . . 10 1 4 8 1 . . . . 11 1 3 5 2 1 . . . 12 1 4 8 2 1 . . . 13 1 4 9 2 1 . . . 14 1 4 11 1 . . . . 15 1 3 9 1 . . . . 16 1 4 8 1 . . . . 17 1 6 3 1 . . . . 18 1 6 2 1 . . . . 19 1 6 1 1 . . . . 20 1 2 1 . . . . . 21 1 1 . . . . . . 22 1 1 . . . . . . 23 1 1 . . . . . . 24 1 2 2 2 2 2 1 1 25 1 2 2 2 2 2 1 . ; end; glpk-4.52.1/examples/pbn/knot.dat0000644000062000006210000000553312175147600015771 0ustar maomkpasswd/* knot.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #16 from . * Copyright (C) 2004 by Jan Wolter. Used by permission. * * Probably Not * * created by Jan Wolter * Mar 27, 2004 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 34; param n := 34; param row : 1 2 3 4 5 6 7 8 := 1 1 1 . . . . . . 2 2 2 . . . . . . 3 3 3 . . . . . . 4 2 1 1 2 . . . . 5 2 1 1 2 . . . . 6 1 1 1 1 . . . . 7 1 1 1 1 . . . . 8 18 . . . . . . . 9 2 1 1 1 1 2 . . 10 1 1 1 1 1 1 . . 11 1 1 1 1 1 1 . . 12 26 . . . . . . . 13 2 1 1 1 1 1 1 2 14 2 1 1 2 2 1 1 2 15 2 1 1 2 2 1 1 2 16 14 14 . . . . . . 17 1 1 1 1 . . . . 18 1 1 1 1 . . . . 19 14 14 . . . . . . 20 2 1 1 2 2 1 1 2 21 2 1 1 2 2 1 1 2 22 2 1 1 1 1 1 1 2 23 26 . . . . . . . 24 1 1 1 1 1 1 . . 25 1 1 1 1 1 1 . . 26 2 1 1 1 1 2 . . 27 18 . . . . . . . 28 1 1 1 1 . . . . 29 1 1 1 1 . . . . 30 2 1 1 2 . . . . 31 2 1 1 2 . . . . 32 3 3 . . . . . . 33 2 2 . . . . . . 34 1 1 . . . . . . ; param col : 1 2 3 4 5 6 7 8 := 1 1 1 . . . . . . 2 2 2 . . . . . . 3 3 3 . . . . . . 4 2 1 1 2 . . . . 5 2 1 1 2 . . . . 6 1 1 1 1 . . . . 7 1 1 1 1 . . . . 8 18 . . . . . . . 9 2 1 1 1 1 2 . . 10 1 1 1 1 1 1 . . 11 1 1 1 1 1 1 . . 12 26 . . . . . . . 13 2 1 1 1 1 1 1 2 14 2 1 1 2 2 1 1 2 15 2 1 1 2 2 1 1 2 16 14 14 . . . . . . 17 1 1 1 1 . . . . 18 1 1 1 1 . . . . 19 14 14 . . . . . . 20 2 1 1 2 2 1 1 2 21 2 1 1 2 2 1 1 2 22 2 1 1 1 1 1 1 2 23 26 . . . . . . . 24 1 1 1 1 1 1 . . 25 1 1 1 1 1 1 . . 26 2 1 1 1 1 2 . . 27 18 . . . . . . . 28 1 1 1 1 . . . . 29 1 1 1 1 . . . . 30 2 1 1 2 . . . . 31 2 1 1 2 . . . . 32 3 3 . . . . . . 33 2 2 . . . . . . 34 1 1 . . . . . . ; end; glpk-4.52.1/examples/pbn/light.dat0000644000062000006210000000546512175147600016131 0ustar maomkpasswd/* light.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #803 from . * Copyright (C) 2007 by Robert Kummerfeldt. Used by permission. * * You light up my life * * created by Robert Kummerfeldt * Mar 15, 2007 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 45; param n := 50; param row : 1 2 3 4 := 1 . . . . 2 1 . . . 3 1 . . . 4 3 . . . 5 2 2 . . 6 1 1 . . 7 7 . . . 8 1 1 . . 9 1 3 1 . 10 1 3 1 . 11 1 1 . . 12 11 . . . 13 1 1 . . 14 1 1 . . 15 2 2 . . 16 1 1 . . 17 1 1 . . 18 1 1 . . 19 1 1 . . 20 2 2 . . 21 1 1 . . 22 1 1 . . 23 1 1 . . 24 1 1 . . 25 1 1 . . 26 1 1 . . 27 1 1 . . 28 1 1 . . 29 1 1 . . 30 1 1 . . 31 2 2 . . 32 1 1 . . 33 1 1 . . 34 1 1 . . 35 1 1 . . 36 1 1 . . 37 1 4 1 . 38 1 1 1 1 39 1 1 1 1 40 1 1 1 1 41 1 1 1 1 42 25 . . . 43 6 5 . . 44 5 6 . . 45 4 5 . . ; param col : 1 2 3 4 5 := 1 1 . . . . 2 1 . . . . 3 1 . . . . 4 2 . . . . 5 1 . . . . 6 1 . . . . 7 1 . . . . 8 2 . . . . 9 1 . . . . 10 1 . . . . 11 1 . . . . 12 1 . . . . 13 2 . . . . 14 1 . . . . 15 1 . . . . 16 1 . . . . 17 5 . . . . 18 7 1 . . . 19 6 1 . . . 20 6 1 . . . 21 1 6 1 . . 22 4 1 . . . 23 7 1 . . . 24 1 1 1 1 . 25 2 1 2 1 1 26 3 1 2 1 1 27 2 1 2 1 1 28 1 1 1 1 . 29 7 6 . . . 30 4 1 1 . . 31 1 6 1 1 . 32 6 6 . . . 33 6 1 . . . 34 5 1 . . . 35 7 . . . . 36 1 . . . . 37 2 . . . . 38 1 . . . . 39 1 . . . . 40 1 . . . . 41 2 . . . . 42 1 . . . . 43 1 . . . . 44 1 . . . . 45 1 . . . . 46 2 . . . . 47 1 . . . . 48 1 . . . . 49 1 . . . . 50 1 . . . . ; end; glpk-4.52.1/examples/pbn/mum.dat0000644000062000006210000000714712175147600015617 0ustar maomkpasswd/* mum.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #65 from . * Copyright (C) 2004 by Jan Wolter. Used by permission. * * Mum's the Word [has only one solution] * * created by Jan Wolter * Jul 10, 2004 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 40; param n := 34; param row : 1 2 3 4 5 6 7 8 9 := 1 12 . . . . . . . . 2 5 2 5 . . . . . . 3 5 2 2 5 . . . . . 4 1 2 2 2 2 2 1 . . 5 4 2 2 4 2 2 4 . . 6 4 2 2 4 2 2 4 . . 7 1 2 2 2 2 2 1 . . 8 6 2 2 2 2 2 6 . . 9 6 2 2 2 2 2 6 . . 10 1 14 1 . . . . . . 11 10 10 . . . . . . . 12 8 3 3 8 . . . . . 13 1 1 2 1 1 2 1 1 . 14 9 2 2 2 2 9 . . . 15 9 9 . . . . . . . 16 1 1 1 1 1 1 . . . 17 12 2 12 . . . . . . 18 12 12 . . . . . . . 19 1 1 4 1 1 . . . . 20 14 14 . . . . . . . 21 12 12 . . . . . . . 22 2 1 4 1 2 . . . . 23 9 4 9 . . . . . . 24 1 7 4 7 1 . . . . 25 1 1 1 4 1 1 1 . . 26 1 7 4 7 1 . . . . 27 1 7 4 7 1 . . . . 28 1 2 1 2 1 2 1 . . 29 1 7 2 7 1 . . . . 30 1 1 6 2 6 1 1 . . 31 1 1 1 1 2 1 1 1 1 32 1 1 6 2 6 1 1 . . 33 1 1 5 5 1 1 . . . 34 1 1 1 8 1 1 1 . . 35 1 1 4 4 1 1 . . . 36 1 2 6 2 1 . . . . 37 2 4 4 2 . . . . . 38 2 6 2 . . . . . . 39 4 4 . . . . . . . 40 6 . . . . . . . . ; param col : 1 2 3 4 5 6 7 8 9 10 11 12 := 1 5 . . . . . . . . . . . 2 3 2 1 . . . . . . . . . 3 3 2 2 1 . . . . . . . . 4 3 2 2 2 2 . . . . . . . 5 3 2 2 2 2 3 . . . . . . 6 1 2 2 2 2 2 16 . . . . . 7 1 2 2 2 2 2 2 1 2 . . . 8 1 2 2 2 2 2 2 13 1 . . . 9 3 2 2 2 2 2 2 4 1 1 . . 10 6 5 2 2 2 2 6 1 1 . . . 11 1 7 3 2 2 2 2 2 1 1 1 . 12 3 4 1 2 2 2 2 2 2 1 1 1 13 6 1 2 3 2 2 2 2 1 1 1 . 14 1 7 2 16 1 1 . . . . . . 15 1 4 1 1 1 1 1 1 1 1 1 . 16 1 2 1 3 1 1 6 1 1 1 1 . 17 2 7 1 1 11 1 1 1 1 . . . 18 2 7 1 1 11 1 1 1 1 . . . 19 1 2 1 3 1 1 6 1 1 1 1 . 20 1 4 1 1 1 1 1 1 1 1 1 . 21 1 7 2 16 1 1 . . . . . . 22 6 1 2 3 2 2 2 2 1 1 1 . 23 3 4 1 2 2 2 2 2 2 1 1 1 24 1 7 3 2 2 2 2 2 1 1 1 . 25 6 5 2 2 2 2 6 1 1 . . . 26 3 2 2 2 2 2 2 4 1 1 . . 27 1 2 2 2 2 2 2 13 1 . . . 28 1 2 2 2 2 2 2 1 2 . . . 29 1 2 2 2 2 2 16 . . . . . 30 3 2 2 2 2 3 . . . . . . 31 3 2 2 2 2 . . . . . . . 32 3 2 2 1 . . . . . . . . 33 3 2 1 . . . . . . . . . 34 5 . . . . . . . . . . . ; end; glpk-4.52.1/examples/pbn/pbn.mod0000644000062000006210000002226012175147600015600 0ustar maomkpasswd/* PBN, Paint-By-Numbers Puzzle */ /* Written in GNU MathProg by Andrew Makhorin */ /* NOTE: See also the document "Solving Paint-By-Numbers Puzzles with GLPK", which is included in the GLPK distribution. */ /* A paint-by-numbers puzzle consists of an m*n grid of pixels (the canvas) together with m+n cluster-size sequences, one for each row and column. The goal is to paint the canvas with a picture that satisfies the following constraints: 1. Each pixel must be blank or white. 2. If a row or column has cluster-size sequence s1, s2, ..., sk, then it must contain k clusters of black pixels - the first with s1 black pixels, the second with s2 black pixels, and so on. It should be noted that "first" means "leftmost" for rows and "topmost" for columns, and that rows and columns need not begin or end with black pixels. Example: 1 1 1 1 2 1 1 1 1 1 2 3 3 2 1 2 1 2 3 4 8 9 3 6 # # # . # # # # # # 1 4 # . . . . . # # # # 1 1 3 . . # . # . . # # # 2 . . . . . . . . # # 3 3 . . # # # . . # # # 1 4 # . . . . . # # # # 2 5 # # . . . # # # # # 2 5 # # . . . # # # # # 1 1 . . . # . . . . . # 3 . . # # # . . . . . (In Russia such puzzles are known as "Japanese crosswords".) References: Robert A. Bosch, "Painting by Numbers", 2000. */ /*--------------------------------------------------------------------*/ /* Main part based on the formulation proposed by Robert Bosch. */ param m, integer, >= 1; /* the number of rows */ param n, integer, >= 1; /* the number of columns */ param row{i in 1..m, 1..n div 2}, integer, >= 0, default 0; /* the cluster-size sequence for row i (raw data) */ param col{j in 1..n, 1..m div 2}, integer, >= 0, default 0; /* the cluster-size sequence for column j (raw data) */ param kr{i in 1..m} := sum{t in 1..n div 2: row[i,t] > 0} 1; /* the number of clusters in row i */ param kc{j in 1..n} := sum{t in 1..m div 2: col[j,t] > 0} 1; /* the number of clusters in column j */ param sr{i in 1..m, t in 1..kr[i]} := row[i,t], integer, >= 1; /* the cluster-size sequence for row i */ param sc{j in 1..n, t in 1..kc[j]} := col[j,t], integer, >= 1; /* the cluster-size sequence for column j */ check{i in 1..m}: sum{t in 1..kr[i]} sr[i,t] <= n - (kr[i] - 1); /* check that the sum of the cluster sizes in each row is valid */ check{j in 1..n}: sum{t in 1..kc[j]} sc[j,t] <= m - (kc[j] - 1); /* check that the sum of the cluster sizes in each column is valid */ check: sum{i in 1..m, t in 1..kr[i]} sr[i,t] = sum{j in 1..n, t in 1..kc[j]} sc[j,t]; /* check that the sum of the cluster sizes in all rows is equal to the sum of the cluster sizes in all columns */ param er{i in 1..m, t in 1..kr[i]} := if t = 1 then 1 else er[i,t-1] + sr[i,t-1] + 1; /* the smallest value of j such that row i's t-th cluster can be placed in row i with its leftmost pixel occupying pixel j */ param lr{i in 1..m, t in 1..kr[i]} := if t = kr[i] then n + 1 - sr[i,t] else lr[i,t+1] - sr[i,t] - 1; /* the largest value of j such that row i's t-th cluster can be placed in row i with its leftmost pixel occupying pixel j */ param ec{j in 1..n, t in 1..kc[j]} := if t = 1 then 1 else ec[j,t-1] + sc[j,t-1] + 1; /* the smallest value of i such that column j's t-th cluster can be placed in column j with its topmost pixel occupying pixel i */ param lc{j in 1..n, t in 1..kc[j]} := if t = kc[j] then m + 1 - sc[j,t] else lc[j,t+1] - sc[j,t] - 1; /* the largest value of i such that column j's t-th cluster can be placed in column j with its topmost pixel occupying pixel i */ var z{i in 1..m, j in 1..n}, binary; /* z[i,j] = 1, if row i's j-th pixel is painted black z[i,j] = 0, if row i's j-th pixel is painted white */ var y{i in 1..m, t in 1..kr[i], j in er[i,t]..lr[i,t]}, binary; /* y[i,t,j] = 1, if row i's t-th cluster is placed in row i with its leftmost pixel occupying pixel j y[i,t,j] = 0, if not */ var x{j in 1..n, t in 1..kc[j], i in ec[j,t]..lc[j,t]}, binary; /* x[j,t,i] = 1, if column j's t-th cluster is placed in column j with its topmost pixel occupying pixel i x[j,t,i] = 0, if not */ s.t. fa{i in 1..m, t in 1..kr[i]}: sum{j in er[i,t]..lr[i,t]} y[i,t,j] = 1; /* row i's t-th cluster must appear in row i exactly once */ s.t. fb{i in 1..m, t in 1..kr[i]-1, j in er[i,t]..lr[i,t]}: y[i,t,j] <= sum{jp in j+sr[i,t]+1..lr[i,t+1]} y[i,t+1,jp]; /* row i's (t+1)-th cluster must be placed to the right of its t-th cluster */ s.t. fc{j in 1..n, t in 1..kc[j]}: sum{i in ec[j,t]..lc[j,t]} x[j,t,i] = 1; /* column j's t-th cluster must appear in column j exactly once */ s.t. fd{j in 1..n, t in 1..kc[j]-1, i in ec[j,t]..lc[j,t]}: x[j,t,i] <= sum{ip in i+sc[j,t]+1..lc[j,t+1]} x[j,t+1,ip]; /* column j's (t+1)-th cluster must be placed below its t-th cluster */ s.t. fe{i in 1..m, j in 1..n}: z[i,j] <= sum{t in 1..kr[i], jp in er[i,t]..lr[i,t]: j-sr[i,t]+1 <= jp and jp <= j} y[i,t,jp]; /* the double coverage constraint stating that if row i's j-th pixel is painted black, then at least one of row i's clusters must be placed in such a way that it covers row i's j-th pixel */ s.t. ff{i in 1..m, j in 1..n}: z[i,j] <= sum{t in 1..kc[j], ip in ec[j,t]..lc[j,t]: i-sc[j,t]+1 <= ip and ip <= i} x[j,t,ip]; /* the double coverage constraint making sure that if row i's j-th pixel is painted black, then at least one of column j's clusters covers it */ s.t. fg{i in 1..m, j in 1..n, t in 1..kr[i], jp in er[i,t]..lr[i,t]: j-sr[i,t]+1 <= jp and jp <= j}: z[i,j] >= y[i,t,jp]; /* the constraint to prevent white pixels from being covered by the row clusters */ s.t. fh{i in 1..m, j in 1..n, t in 1..kc[j], ip in ec[j,t]..lc[j,t]: i-sc[j,t]+1 <= ip and ip <= i}: z[i,j] >= x[j,t,ip]; /* the constraint to prevent white pixels from being covered by the column clusters */ /* this is a feasibility problem, so no objective is needed */ /*--------------------------------------------------------------------*/ /* The following part is used only to check for multiple solutions. */ param zz{i in 1..m, j in 1..n}, binary, default 0; /* zz[i,j] is z[i,j] for a previously found solution */ s.t. fz{1..1 : sum{i in 1..m, j in 1..n} zz[i,j] > 0}: sum{i in 1..m, j in 1..n} (if zz[i,j] then (1 - z[i,j]) else z[i,j]) >= 1; /* the constraint to forbid finding a solution, which is identical to the previously found one; this constraint is included in the model only if the previously found solution specified by the parameter zz is provided in the data section */ solve; /*--------------------------------------------------------------------*/ /* Print solution to the standard output. */ for {i in 1..m} { printf{j in 1..n} " %s", if z[i,j] then "#" else "."; printf "\n"; } /*--------------------------------------------------------------------*/ /* Write solution to a text file in PostScript format. */ param ps, symbolic, default "solution.ps"; printf "%%!PS-Adobe-3.0\n" > ps; printf "%%%%Creator: GLPK (pbn.mod)\n" >> ps; printf "%%%%BoundingBox: 0 0 %d %d\n", 6 * (n + 2), 6 * (m + 2) >> ps; printf "%%%%EndComments\n" >> ps; printf "<> setpagedevice\n", 6 * (n + 2), 6 * (m + 2) >> ps; printf "0.1 setlinewidth\n" >> ps; printf "/A { 2 copy 2 copy 2 copy newpath moveto exch 6 add exch line" & "to\n" >> ps; printf "exch 6 add exch 6 add lineto 6 add lineto closepath } bind de" & "f\n" >> ps; printf "/W { A stroke } def\n" >> ps; printf "/B { A fill } def\n" >> ps; printf {i in 1..m, j in 1..n} "%d %d %s\n", (j - 1) * 6 + 6, (m - i) * 6 + 6, if z[i,j] then "B" else "W" >> ps; printf "%%%%EOF\n" >> ps; printf "Solution has been written to file %s\n", ps; /*--------------------------------------------------------------------*/ /* Write solution to a text file in the form of MathProg data section, which can be used later to check for multiple solutions. */ param dat, symbolic, default "solution.dat"; printf "data;\n" > dat; printf "\n" >> dat; printf "param zz :" >> dat; printf {j in 1..n} " %d", j >> dat; printf " :=\n" >> dat; for {i in 1..m} { printf " %2d", i >> dat; printf {j in 1..n} " %s", if z[i,j] then "1" else "." >> dat; printf "\n" >> dat; } printf ";\n" >> dat; printf "\n" >> dat; printf "end;\n" >> dat; printf "Solution has also been written to file %s\n", dat; /*--------------------------------------------------------------------*/ /* The following data correspond to the example above. */ data; param m := 10; param n := 10; param row : 1 2 3 := 1 3 6 . 2 1 4 . 3 1 1 3 4 2 . . 5 3 3 . 6 1 4 . 7 2 5 . 8 2 5 . 9 1 1 . 10 3 . . ; param col : 1 2 3 4 := 1 2 3 . . 2 1 2 . . 3 1 1 1 1 4 1 2 . . 5 1 1 1 1 6 1 2 . . 7 2 3 . . 8 3 4 . . 9 8 . . . 10 9 . . . ; end; glpk-4.52.1/examples/pbn/pbn.pdf0000666000062000006210000012514412175147600015603 0ustar maomkpasswd%PDF-1.5 %äðíø 18 0 obj <> stream xÚåXÝoÛ6ß_Aì‰Â*Ž_¢¤a¶ÝÐ}¡EýV÷Aµ[ˆ,¥–Ü´ÁþøÝñ(ÅŽÙ4Íö2  #yÇûݧNfï˜bþË5üK¶Ú±§ öíÏŠ©\h•±Ås¥0†¥Jia ¶X¿æ¯úö}Óm’ÔHÅ_$:ãUÓ%Úñ1}ú1ýó°Cúm’ÂA½M󇛛¶‹ëfÜõËï/~KÞ,~š)%ÊÌëÌ3¡0£¼ÆŸºõ¾¾¸øêrÛïA!‰™#±@k°E¾ßUý›î úý懈ŠÔJá –j+¬#%‡ÍaI‰–J!Ë”y@HYP‘ƒ°C§ ”JÐ5–?ï#ù¸ïÑ0¾>¬Æ¦Ÿ0f¬¥3xƒRFHÍÀ>ĉÅ1%E)KÒBL©.E°¶üˆ ¢&k¯’LaÆôíÇ´;ìÞâ~{¾ R>(ØI¾ê»¡FŒS¼¿ g5™P+–Zè2ܱ å)2­ÂùRJ»C‰‰£‹€ÊN6ûfM'TW͇º H—|ÜÖï¥È‹pÃÊ{§{_ÅüaÔmÒ,Ïš ²BA ŒÀl“±ßÔ hŸ@Þ„>7 JÅê;~q§~ÉÂñ7qŸØ»NÉORÚɤrµÞ§Cs´Zñ¡N2ÉßêΛ[Q·j!M¸â ÊS»šŒºè½u†×Õ*Ñ9ßâJqÈhX\OÕ­‰Xõía× r—–PÇÞZlñNeø¦¯Z¢šžcO˯|ÏÈùˆKíƒè÷W•ß~ŸdŽWA†úRUnVãatŒÛj$j¨ÆfXJeëøÆ ÇEß¶d6.-ñbòû ÑðçPN”Á*Kµ*à2kù3ôCÿ£)‘4s§+쀯â­ºK"ÑÍÆX~½mÆZœƒÑ ÆYÉŸc¶—ÚŒŒƒÃ8˜2§;`“€tÉ·è.¿y’x4Ô>/êHÒico‹uÊ%Y.ÊÏ3¡°„³ŸìWVäÐ…'Ž'%9ö±‡ªÐPᣠ~R.?y¸¨zè£îL¿:ÓŸÓëí2¢?ÃV;s<™³«#7cèªð¯‡Û`¥Di0Ï|†UM¬¯:'Š©¾/ãMÑèÓú÷·Ôá YæK÷’ÔQŸüËWciì ‹ýTSE!2}o°ôgò¡Ä3sD1¡e9·îTç¥(NZÈPƒ³ÖT1Ÿj·RÈ–V…0yéT؈‹µš° }¨â©ùeN¸“WÅó ò¶?´k¤åm/Àƒ®ë5‘Ô»c¹ ÑùšNvuÕ D.—m}1îúùÌwj =ùò’0’ÀØ_¿‡xÔÉ¢¿À@µPÿðFæ“‘°M° Ý ÕÌähÑÕuØˈönšŽÖ“¾š.ȧYg¯ŸuBŠ€˜B«"|º QÏ>T»«¶Ž•L®„qpg.òlž×r­Câ¢:‰Uw~„“¡¶Ççú²RÈö¹Gà4ç:Ì ƒºg8->4/hU†>c…ÄÙUá®Íà…é&W™ã¦Žüv³”ÝegÊ ef*vj?s™eIû©—ªý"¨fVg"Pc§€jÉ«w fbCL23bA|¿s̓]A ³Ó`$®{1>Ô«±Ó/Ms;ï$Àýî´ÿ¶;ÿC¹zUÔì‘àá!þ_A  ™«±?&=Rúæ‘¥ÿåõ·µ?[°wLÀDÌ®Yf4Ó¬ÐB9¶c œqóFË^±—áÇ& £Z‰£µµA¦ùÝ>»>ƒi­t޾à†ÔL,‹-~\«qhô?»øm§W5øù¶èÈÐw!» †è¿Qñøbßïhÿµz#b㎜ʿ­9‚v¿üêo¤M€û endstream endobj 24 0 obj <> stream xÚ•VKoÛ8¾ï¯Ð‘"V¤(JJ±—Ûû(²Xï)ɱäX¨$zõh6ýõáP~Ê­ƒàpøÍpßPþ DÁŸR ÿQ°j‚ËàÝGÅc¥ƒå:Hbž¡Îxª‚eqÏä"B*ö­¿Víó"ŒÓ„Z¶ã·ou¹x\þNt "žG9:‰‚P‚ÇÄyXnJ€‹ˆÝ-dÊLÕ.dƆðÃkøylP~Z„pPv=Á¼W'¯LKb2æµkÛ¡fcm†²]”3ã­ -Q(HÀë4Êç²#àº4}õTÕՀἺè!^ó„âÝvö©.¾•R>ú8ö—¦îÒʶ¤{w?H•×|úóî”{qébX±D§[—‚=±Pì^µ¼±ÅÌ©ˆƒ9d’Ä dâ¢ÔjòrÌ&]Õ®ê±pqh¬®²óÌUQõCW=>yÐP&¢Í~ a³¶cëÉ@QéÞ4çEÕAYm÷:—zšð,ó9•ÿ›f µ|%˜IŸ(¹KŸˆ(S®ÓÃË—n‚ Í:s„ì.ikpÉÙÖtCµ‚¡îH=½>xF¤¦©#ɶõ+ImY½ÇYï«+·nJŽŒíæÅìy˜Ž’¹(±‰-’I‰ê¸‰È(¹›q¥ñH}ø@'DìCƒ£qI‰¾“ùÙ¸øú#"Þ—äug’üµ 3ÿZÙ±'õÁ%0Tß,𬦠³_謮¾LA¿¶†sØ¿ô„~`îe›áI¬&¢43ìI*üwåÁcy˜â0=î­{Ù¾Ft`×ôHw>°zÎM[Ì…%dÄÕDÊ9ÒæõóV¶›¶XÜNw§AÆsí¾Û@þœ§8y)ÏòÝ{÷~ê«<ô¢˜Î@ÿø¨»%a·¿Ò*¢#¸<…·oƒwöÅx<ü”ˆà»"ýûü¡™aËB,–v®~•ÀnÂi¿òWwPé¡Óê24>Š]4P¢‡òP¹óvÑkrk|ª¯5= ¹ Í®‡æ*0`Et˜Ï!6<ëÙ ¾Šê"3’#fȳj_Í+zz‰)ûõÌD½ý–äí·è·ß’¾½bÙ ¥ÕÏM&fegГä˜aùm®bZÙï義æpùô0JúmüýËwžY$Ý endstream endobj 27 0 obj <> stream xÚ­XÝ“œÈ Ï_1LՂ馡!ow—s²‰}µ)Ï=ÝÞ;0»”Ó௿>RKÍ€—;•ÔnU õ—¤–~’f÷a'v1ü‰–ðïŽÝîçÃîÕël'⨈‹Ýá´Óq¤“]˜å‘V»CõGð¦÷¡Ô2Ÿj$DP•cI,[ÇÆôÄ>™¸Ó ìhTuKß³ïâªÓ`:¢®8b,ñ:RÅ[þº#ÞЋ° š#gûvòH%£lå‘/Ë#òH¤ÿU\€8I‘ãPö¶-GxÕ0kxS†Æ²§±ñ®Ý—-rR°ìy¨-»|‰*ð¡ÎypÏüZ–v òN·4äJ58hjGRÇA "ðV¥~Ä’YœêÒ6MÛŒxðZuÌC[w—X§7gg×­÷S:J¼).õÜd©Š”_7Öm»éüRFê»Î&RE²X! ºa_?Ÿ˜ØÐµðºâ 1ŸPÒðËo¯‰e‹îR®¶çñr{LÅW’â¥|€qßàØ[0Ô;Dü˜t Dû#ù“—FFÿü4ߌ‘»CdQ‘,ï¹=ÁÃjl›8 à s£  <§q<•–˜. kyäŸÌÔWq uCqQË›¾jŽ`îÊï%¾ _ÔÜg¥w?nß½¾ýéç7¿n8A&£âGé ¬¼ £y”ç{ŒUüRJ¨¥áËGšNXË¡"¶™Æó4z@•ßÄæ=F=„HÙÞïoè…? Afˆ‘FzõäJÉ"’ KîŒÎvËPb­ÄºÀ]à½ðÊØñÝqhΣϰCWŽ7´’‰ÖV«H£|'¼R’’=W^ÓAÃ~ý­ Ûp«ÁéRé# nDy‰eN4¾-ǧ»Á<Ò¥¤8= j?.ÙÔR)úÞB­#¶,ÒEUdÊQˆ3‘=`¤ë#:Ò{ÚLÌu8‡Ð|võLy­-JÃûŸˆß×G ‘á m¼¿œQÕcÙtº[×Ï‘†Ì’fpÈç‘(Vû~¨ž Fuœ¸ˆà:ñ&ÿý·ë±¨ó(ñ.ÖÕ€Àx|Êp‘¤ú"Ô\ˆCé9ô¼‚óÞ̸Hn±v¿Û©lÛ/h<.Ñtž*©ÎêɼÎ%ãt¦À.‰;‹´s$˜rÕMV\Jq››¯LÝÓ™ïáƒÓ˜Æ Tû ÿHlΔ‡íÔõö~OŸ÷)H34Jª*ŸpÆÖœ°`T蘾r~sêâUz^UU§KèEð’ ݳv•(Vp8-BØ3o2\~·åð¸ªá-}t%#>f¥¡þ05/#o÷å#NwÆÏá ½ð¤ã`ÞkíäÌ6Ç}ý¹ì\(!û"bPl§ ç0¤ Á2RUcÇ¡y˜Â^Š`EvX€ÄŒ•SÏýЇV;ÑŠ ,q ÄðVteI¤3ŽÖþ‚êw ¿¡g”s Fój' Lµ ²b™Íñ‹p5uY ¿ÝÁÈø¬öÁPJDpØç2p°Ÿ ìg+ØOüð(*Bá2~jtŸ »D&íS¼Í¬;ÐNu˜¬?CÇßôΊÈ&·3ÜcÎg8¿ÔjqÖPlÌdùÕ}ÇäÎè«y1³.mø ™æjÉÿ/ùŠùB"|ö{À-zBŠå*Ö´HK»™ÓôG*Jw~̘ë—ñLWI¤P—WUƒâ9„>ÿè“‹}Òù}¥,T$~°~Zbwû £L¾ÔíCá †ÚÑ1XÅ‚K^ ¼ aàá7àŠå,È –à7(Ei͈x.š7-M;á¾p#" £cÐÀeA`ôM «_ â…!Ý*C#àÞCãDÌI¡mAW]´¨óa•=Ð\Xݾ•úšÕãêdþEO- Oé~¨ˆ]ŽcݱáÀ/ú9M±|¼¢7pÕ@ç]ª!Èå©oÎÕµ2neËï–qëzï»ggV3NCkó@ ¾à^â"Cû†íSÓâ/Bºr‘ŽçjÑw^H̰'™‘YÒ@¨Îy[»Ô·R–èÚîœÌ—‰ÙõâRéÜ\~§ …’!_k•)¯U–y­./ M I+ 8lC‹¨X©ÒÖ¥åÎlœ‹7C0[¡s&Mé·b.•+±44€ïÂÿôœ8ö¯‡Ý¿ÿòc1 l endstream endobj 30 0 obj <> stream xÚ•koÛFìû~…Ñ/“‡ø¬“N¯¢mÖ® ²ÖÅ>Ô*Ûçø=\=–8öÛG)Kn´C‚ˆÇãñø&/“o9qáGN"~ÝÉ:Ÿ\,&ó7j"•ðU8Yl'/âÉ,ŒE¤&‹ÍgGMgRzÊùXfmcÊb:ó£ÀiL®ëé—Å;8N¤+7ÁÓîdæ«À]ìôt¦×iÒUfAÏA*NC{Ò)ôcCÐ>½c\½+§^ä<Ôt¼>^mOÚ«O˜¥|,Í÷YÇB3×rÛ_ˆò‚„ÒI¸OM75³ÕԋìÀO›ãßÕt;º‚»|ÏwöíÓS¦íB9ÛªÌ Ý±¿‘C;È0RÁexË«½Ú¯ ±.ó_Gly ˜ô¥Ñ«Ú4Z€ÜÊ#– S@õX[ ?êdY¤xÆ÷œ¶Ö„|Ç ç|E†GDÝVÙÛDúY}aŠ’@Ü}Z1µ^º2\]¬D…vµ¦nLqG«Û‹ÚŸ÷ªVRŠÄʹèIÛfWZ3ÂØâùœ·{àïûª7 ê„^G`—âå$©wghUÐrÞAºÜÔ5†–5æ3·et‰cA¯—h+ür°Ðb[i®ôìS™UÛ '•òÙ¬D«!÷cuB ¬Ì)ÒŒ4Ä “ó$„ÓÙÆ1¸k àèÎÆ4¡ë&mt®‹Ê:J7zƒ¡æ»ÎÛÑ ‹å-ãj{ô¼'O«û©: å3WV0¸$e0g#:7º2õ=­–Î/Ë)ˆ‡!— DºRÙ‹p±.IØF›Š8pó:mv·UyG«MÚ¤DPë5ZY 7ŸÉÆŠ)7ìÃ…U S¬³vƒÎ£~#¾Wïo'èèh*U@d}ƒ[k«5+ ;Zl˶èÙ>“¬n)ª6¦5Êê0VhB_È®xèG› õŠÍHÁšî3©à€‡ºŸÃKÏ3 :0]Õ¢Ù<0Õ$ëgÀï¹,‚1sÑ@úâD@£- Ϲå„EÕÒ(ú,ËÛOtÚ¿úíé í8ÞÕsÜÙ‡ókŒ‹ñìjâ £”CU°V‚â¯!6ÑJFö6%ÁŒUÉíj‰Dc¤M1ŠŒMðÔ8µ…ùÖòÞ`¼‚UYÑ·ó5R§Ei…xî‘ÁQŸÅëÊ2Äzïn¢‹“ Ñ]É娯 »áÓp!¸ð~ÇOŠœ/~^׫´¨3è}XHxÞD o¸ÊK£›®dQ7… ê!õ= x^Äc‘k›Ù«+êÙ°sýö–¶*½¯ôlÄtÜ’muÁ8õ¤½:éUÇ•ÏeÕŵ 7KÞëÕíÏàÎ$luZ›•ÉLs,1tø|Äz<¦\`oÞð€âÖ)³ ™•à|>)€³‹Èrþ ·ÐKŠõèó!*¾ >K˜I×u>”Ü9+ðÎ}/ÊšrïŒÖË¥í:v®Ç¶Ó ¦Çr ¢Þ´6%þ >ë¹®+Ƨy‘DCó¼Ú5Íþå|þðð Ê•®2S½içç]ómº†t?ÌW Û›ñ Ÿ6b×äÙØü" Ÿ6f_%Ø×gž'Lá±)pàx )å%Îõ1z­žˆzŸw­}Háêêæñ1êÅÕÑ%}_;ÑvÉ/Šl–‚ÕÖ­)C;RÂ{°Ûî‡%ZÑ—“/âaÉ‹¾–pS/¢a ~¨† KÏÕÝk†ä‡ÃT÷¸3ô¦\øBFW,§Ý”ä ×'gHr†Ïθ1÷™,弯 Zºž?Å9WcRã8$ù¸”Q4UIeVu]Q a{^0—ÇvŒ¼í‘óiì;‹õdÌ€|ær—f9¾OGö©0Ý ó4¦à÷ï¶Å4!mÃÚeVÞ¦P¤9>ÒÌ·ÑÅ¿äC(T×»\Èa0‡ò j=‹r5uåÐ9­Ôƒ(WlØw);öO”³Ì ¶žQö.—O^®½J'™?£ŒŸÝœ¾æ™’[£ÕÕ6´…àfÿñY?ÇÇ´>Œ+(~§8Zo–„ ø,ˆ}½˜üñÓ?*²ê endstream endobj 33 0 obj <> stream xÚÍXKoÛF¾÷W(P¬Šj³³ï-z²£h¬ uKs $Z&D‰IÙ¨}w¸Ëšz¹Ña"‡»Ão¾yr“o $ÌÿAb¸ÿgÉ|œM“w—:FsÉô&±†:—Œ€jžL_ÈtdIgE6 Á ü>K©ÈuYl›¼Ü T&_g5^JòŸè6 uº¾ »%©³&Ë›ð{·}|,º­7U¹â/òëèëô¯äý4ù–PálòCBãþ7Y'ÂZªMw_$×ÉçCs€9ªÁ/†‚míùÔ¾±Õ®eÆ3‚âëüÑcäÊ)ò±l‘ß«ÑL:õÆým‰âóÛÕ“Ø›u¬*emœ€ÛíR@A´°~†Vµ´Tðˆô"Ý̳êW„ C€µ Þ]ºž­)ÄÕ3ÆãŠ]b¨ë–(´›sr×ÙÞ:g)ï(ú㘠ªGö+‹ñôü~ØÙ?LaìyŸQ¥ ú€„ó´ñ pÃá¯gÀ«sö¦)à£óz•/ÐtÉpuÄtI%¹ñ }( íA~övI0‘„³í|Ä YÕ˜Æg 0êÁYö–‘÷‹e†aÊ×" ØÛ3ZF£%x³¡þu¹BÏc­fLOþïö;{³þýýaS¶@!0Ú+é×<ì”Æíà1Ì7Öÿ¨¸C=蚇|³ló‘k"‡¨LR Q«Èád»F ™c$†Â×à2šÉÖùyz‡ÐÀ5uQ 0I…ÜÍð>6ÖcÌ^๜Ÿ9©Òe>G„~Tlç'öŠgÃW½€o’U«‘R$mÓƒ͆!°ß v`Ê}˜ò$L)tLOmÙjªSÄ)GÄ )Â^‚RcŽ™x¤Ü箄?vš?µPŸ(”ìÜ|/7ÙµJ7Lê#ä™}læ$6ËDôíU¾¼E÷¶š¦ü=Gáw•?Óeò%frYe÷#nIø†@øƒŒ‘\ýÊ®Ç3É"Ê?Ë&ªÊÜ®¯ö0 *ÄÅDýòXÔF¸ñCZ¥ŸAÀ 5L/i­·F“É!F¾‘?“ÎFŒn|Qb¿Éüˆè†Ý \|WJwX¤KŸ*Ž ”*Øâƒg/~‘Ÿ½ŠEn€G¤Wí·Æi†ð³Ùós¿Aæ ?Ý ³6&ð$­Šì½(«nK±]oêðÖÁ$õõ_<è/Ö¨k[4ù]÷¨Žç¡Q(N­/*¨îÍ<>î>ÿô/ÿ*èÔ endstream endobj 38 0 obj <> stream xÚµV{TgŸ1AÓ—©XëLºÕŠU«»ˆ¶ºJEQñX+ „˜ò6$€¥¼%$7 ¯Þ”ÔÖZW[×ÚµÕÚuµ­íZíëú±çì¨{l·{vÿØ=sÎ='“;÷þîï>iÊÅ…¢izüÆeË6‡¬šé´aޝóÅoã°ùÇeC9®ÂdJx–¦Œ8‘0Ñe EÑsž ’~Ì)o>î”Óˆ¯z’r¡i6u§ÞÇg®—ÏKþª$­&6:&E橘!›ãçç;Kö’ŸlI¢R«o—ÉSb”‰òò#A¬RÄ*S´2Ï—cRR’x{§¥¥yÉ“½TšèE3fÉÒbSbd”ÉJÍå6Y€j{ŠlÁcðÓ¹ Sñ+ï£*ò,xï+¹Âõµ˜7e¾ Ør0Ùy”ÃØ ÆÝœ †ü¬_ÍçÖv./ÆÞx&ŽÂr4 ÏF¯òõֶÓ5Q-ªb`‹F;¥Ç;¡aâ‘à*øJÑ´¤sÿÁ–AÓ$“fÐÒ’¶€š bú"-äC¾.[·ßÄŸz Ï˜žr¸DÐo×o„„„°Ý©÷s™VS?´µõC븩& zx´ŒðŠžBëñÑ’K&äLR« “¨¶›ŽÁ¾¦ÃÐèT ƒŒ’Äc¬D¸üÂC¨Dªçyfâ x1°^⦅£L§Éz•kpˆ£ôa•ükH„h’øÀ‡Æê„gêDH>4Wš_n0¦¶žR׊»À^`6°Ã' lYH 5šŽ@só‘QH áx3/t2–Ý ·äÌð·–,32­`®å…·˜f8þá#E/F)NÁ ?¬ ÎYRu½õ袳êΣsWEh3º"EóÄHúÅ'wïzßÂy|V-þ êQ“µŽß}òõ%ó}"V` /,»C³›èc½èƒ^‘°rh¡t¤6b.71ÐC9°¾y5°ÓüLã!ÁÑ!?°uÞG;öæÈ´êN'ï] Á¬ÿ¦Eó8L+É 6ƒ1Ø<ƒ!ÇáŒÖh(á,`*®j3šÁT{ðDà'oö‹èï|ÏÃÉô®l»ü|xEXE¾YÁU¡U)ÍU[N;´³ïž|ÿ&÷=\ø}5~ÂL,Y€-s žgC»lu—¯Ùè®·QTÿÇvFR¸ûå‡ÞØiöå AoìÕ—T6–¶4§—ïäuP`(4Ô¿sʾؾ|³Nÿj^pâêíë dÝNíç ¯­á´)¢EÑ l}Õ5~P»Y“”—'»¹MÒyA!¯o;pŒƒ½•ýgÚ{÷ µ›HéYòlÂK6¤:@ßëC¶ó"ôâÐJ)vÏvU3gËv‡ñÃ_Û™Ö÷[·?“¾¾ =‹&Ìùâ>"â·±¦MR°ƒ¹ªþÐ[ƒÅµÀîýf^7c·ìd>Â+âÏdׂ ìÄÓ‹yv”Z^µÑ{Σü~‘ðÊ’‘­ìƒÐ¿bñs¾/àÇðÓwg~\º¿¯w– —½.+uyHìk ‘MIÝ }p޳Æj©Mý°½ .±UFìB<„ãÈ´µûv R£ëºÊQØÙÞ.¡ÒÚŒ};»€½vñÜ y]‰m-{[¡J ¸PgÈÕÁ.6³,·²ºÔZY›QÏ) &]¥NÜm'yY4Ÿ‡ û¢­9‰1 ¶*;v¼–¥€×Yÿ»‘¹×÷z{Â".Å©bL(ÞÑû¡ jØÏ2¤sQuuDܺ˜JK#b.ïÀßI§ôðÐVÓÚ`k®±’ˆØëH ^!§;ë‚l$E÷ûÑ6BÜ\tZÚ—s»q~ ÌŠc ‰ÍY£Ô¬"}Õdꇣšœ}µJWtˆG!Ìgƒ—Þ»RÆá¼¯'A&âÖýšr~Ð'BÞ°´A[›’š®MIµ§76ÔÚ9<¯';e°”8Å8= ÍgÜ:}I'/ˆ™{CîFŒÍþEý o³£ûQC•#áÆî h> ÿDî'Ø[[¶jCYƒ8ëú:{0¼ Qk2¬á¾˜ÔßCãø@ÆMÚO¹ú×Dýß 9çŠ]˜7ÒT­çE‚?Š“¢ ^_cÓ^ÓÉyòó™ˆFôç_¢'9L:Dº-)‡4=…ƒÐ GL'=uûµ÷AÔ4Å´m@H€múµIaª­‘éJ`%è‡Ñ¨È„`.’ ²¥_¾ý™‘ƒ¥…Ô|urmNuEƒ¥¥=¾.–_ qKrbHUÒbÌþj´ÇÀÑÚ{œQøg‘i/A˜Ì¡ùUts'Êî¡sÂé?~VF¡.7§PßnÜI¶˜H±~=sìhÝýNfƒ®^[™Õ Ѭ<9Ô›› ´· «À˜÷p¢OèÅ`4—–”U7•Xë’ö«½×êÏ<ô%íɬHl‹±ÈKC*–UÁÛ¬£jà>÷”L7Å Š æ‡3ý@¸æȯŽþ[?âÈŸ)xJ‘Ìe(H+ÖO™ó;=»ë/¸ƒIì‚Ø³g®p§µÁL@ÒVùvEÝntâNyØËè¸à¼ÊF ZÉø†/]â—ÿ‡“ºÎàñNêº`,a`D:T•™ÍêËpö].­g^bä^êJº,·¤—G?2!=¯^˜ì ­Â6‘0}.-k°u1±&:é;â ͹°›õUY †\Ðï~“œ`mØõï®$³¸hRÓ>¨9×"@“”©NýƒP hÚ0åQ’a$gYM%Õ¬dÈ{Ô<#®¡»Òº³]¦j#ë<¬È“ ;ß·ék´ |}®>6nö˜†zõ–ÂRâÍѶŸÎ‰dzôœÐׯöÆõžèH•ù¡^²óìH…N½n(/,Cáa¢L31g"Sqõ7hÀã[> stream xÚ­U{Twž!™Z¤VZ;wÝÖ+¨«ÖÖ£+XQÚ¢ÖG• Þ$!BÔ’ÜÂ#¼óà™ðP ¡‚Š´>K[[×Òc[×n·»µµµµßà=g'ØúW÷¿ýcî93çÎw¿ûú.Iøû$INßñÂæˆí‹"cã—,õ}XžŽ+î)&Šø' ~É?ådz"þqÿ§‚|êQÁ¿<â³7gøìŸ3Í:“ð'I:o¿1<|Ùâðð¥‘r…F™žš¦’Ìß·@²dÕª•¡’¥áá«$ë²¥Êô}‰2Il¢*Mš¨^²$[äûÒ¥*dþê4•Jñ\X˜Z­^œ˜»X®L]³ T¢NW¥I⥹Re¾4Y²A.SIâ³¥’)΋§l¤<[‘§’*%±òd©R&pî·Žˆ%‰d2Õ/“‘J‘Z ü(1“˜EüXLD/ˆÄ&"šˆ!^$^"¶[‰mÄ+Äb¶AþD1q‰|Žô‹öû@'êõ¯ x, ULеâ›Ô Ô]z9]÷PoâµùΉ'œäÀ8ªñ[Ñ߸¡ÿ4u<éFdË.xÖËRž•Çèb°°*âèúþµWrOÃ?àÔiϹ£Y¾…s4Þ‹¯1™m/@dчà3¸Öt¾ù½·ºAœS9–×ÇÃjˆ‚°¶(®ûŤ-Dïõ :I$¿"B Ó f5›«Ø™2hÕ §àL=i§R …ËØ,™¸Órz{¿ÎÀyž,j™¡î(çƒùÝ»…<äð-”qCÄÇ ÕLžØ°¿d«î@iqÐ1‹"†ßæ ÚÒß×ÑÒP#¨}À_^Z»;LXf¯  s¦šˆˆ1´oLÄ¿ŒÊø ܪYÿîÊt!þ¾hmmB?ˆ1Wðkƒ']TBDOü(¸=£÷G~s! q(ŽúéÊÙK—vı¸ðwýv‚L]tjâÓ^4ë6‰Ha„"øI¦#¿Už“—¯Èn+hë¶w´°˜ÅqÂ`½SsH¬ößðÜ–“à©=‡§v·ÌÚÏñþT_/Š{P®—üQÀëEvÌ¥Õ`†òË£ÕÕW. š]fÚC©9³TódT³©®ÐjµÆÄâ?â™|>õ»¹úbvu÷ƒ\¦Þ9û fó«Š@¢Ñêó·vË0t³À1Ÿ›²@>@ÿVêÿYç… }¶DM›îŠñœ¡qÛÿ¥Ì‚d´ðK§v¥K8<¯¡ 1 î z:Ïijï,Bb4íö·h&‹3p“ M²aÅé<¼)Ü”‹ÝCîcƒMG ÞÔt&wïH4ˆÍÙ-uOÔw]fÜOïÇË¿\¡ç‘–¹íý×Çl5X ÂTRvà(hYkQ“ÓYßÙ¥pïeW€,ìP0W"1~âwv[Î@W燿Jb„±Öw{4g…ìBš!ú”ž±ƒUÇ–@A^iqV{Ve¦ 8ÓS7må ÒúÒzä‡KŸ)ª7´«íëó@NïU¾ºŒÝ¯öåÝ)³ƒÙd6V”è"Ðk8<‡Ò€ÞÆZÁlnvY«ÀÒØÔ·{šþéô¹ëŒfôפv+*7ÕeWF4ÀºÛuüK‘P¹Ø’e.©‚r kÁjÈΊþ„=ë$9-"´ššAs=x.ŠÉ›þœº(Ü@«oân ‹®©F.÷^ºÊ¾·•Š”%&GÁWÍì}}òÁn¢·ùˆ E­HXÿ×Uú#,ú;…çúJ8†¥^HA,¤ve´å ¾%PïÃOkSúC!îò"^8®Ûu.þIiŸX*â@ÿdZ.Zš}¢4j Kf„m¾ 2Ö) LPZ¦ ÃÁÏ £ú:¡µå!î7ÀÅz(¹1 d™FØâóîƒzcíëÖCuUêØ¼µëë}ƒÒÙÖ‡½r#Äø¼ß[Ym&š‰ï G²´jÀZnmºƒú‚ïà>ë«¡Bj¡¼ª¢–Êwñ‘Hn«v‰qb-å™6ö°³&0p¬)p:;Í¥3ð!t}öª¶ endstream endobj 42 0 obj <> stream xÚ•’LSWÇߣ¥<qêÞs¼W³8¬§8¦&‚PÔ‚&DŠèh‘þ J‘_Â) ­PAlEq¨A‹ËÔR'³Úi4hæÆ6“©s..˼o¹ÿì!KÔlÿ,¹ùÞ{î=÷œÏ9÷’„PH$”’»5"Nš–¶,jjgE®àºÿJòçÜ›$êÇ1îua(AAsy%М)½÷Ê”.äÅ|!$Iª¸ $’å‘ITœNo6¨sUFqXv¸xYtôÊ%â(‰$Z¼N£4¨³Z±TaT)5 #oä‹SuÙj¥Ñ,‹QúÕK—šL¦H…¦0RgÈ]¾DlRUb™²Pi(VæˆãuZ£8E¡QЧ¡#§§8F_dTÄR]ŽÒ åigD1ÄâCBAä?QÄÏ!B –XHÄ D ±‰ØL¤Ûˆ@?‚$üøíBbŒŒ'}~VA˜à `Bø¾°+?‰äÈ_€®¹é½K»Ë`Ø¥é)8>à:ÖÇus]äE.LÀmä*è[k3tRÝfGSßPÓPU5!ø;œSY[[•!`n­µ‚îbe°­În9T{§£›‡¥¥Ê†?G)Á/FLF½´ÃfktVÙjšð]¤ ®Ý_Ó\ T™¹²˜åÃYZjÑ0NÆÃXº§¶ÊæâÎÊv¦Ñj·6B«=$Èâ¹èA'y!‡Ý?¹Ñ:·€ åLtÅB‡¨˜¤XˆgúVß:÷p­½ÈŒ×á`<¿†q ÄÁ(ôáíË®ìaË öT«ó”U* Äï"-B‹ÿñ;Ûg«œ©$|ƒ–gß™üllhtHúÁÊLYË Õž?=¤Û‹J¼. ¢'dßâŠÅ¯?\v„i†FëYh²Z»Öƒ|½N8 †Aè@»¹~KÔ”^š” ¨¾Þô€9ãM_vå}Q(— úú  œ-Scy3µñ* F(Î*Q•fÀ^ 6ï<1tééI4› Âf7Šw{Ü(ËMú¼(Õ{fL€d—éJ9\`áð¾ýûí]åƒ@ý|ýæ,µôô´¹öµ[›óû¬@9ŽÚ.HeÍY§ÈËsªí: $ëcW°PÔ¤ìÍ-ÑíÕ@%¨:töê4i+äP«ž$£ùhþ“ñI´¯‡<&‰èôÌ‘K—FGΖËd;åÛØ>ü„e¡½éÓSNg{ |Ô=äËå±;ÂÙ ð [ò¼QSCÀ¥#7}p9£õnýÇ–ö¢ÓÛ!òµ5Õ 'ŠÁ ”FT^Z­úYì ØUį{ µõð=3B>‹’&ÏôÚU ® (Õó.Çx—›ÿËå¶G^”Æ¿ï{h”~,f6Àei u Ú²™Äi”©ôCØ—õÜBïLÇ™zÁ,”(úÕ7|ÁãÈ“1xwVÀ{‰¦~Ô÷ÒãEÝ|¾ ”O£¹’ß0 Iž‹çÝxúôþ#4ÁÛñ*:N:ñ˃+W¯_¿’!ý0î®ÏC¢/J¾#@ùh fMÞøi‚fhjØ—Û»×”óPÇ‘aÅ¡t6dy*u& ßÒ¢fÞ~Ž>}k_(¤á9â[Ï_h ÷ýìöKmЈ¢7eÆÀ`?ƒ\ÿ>wˆ–~¥»Í\†ÓG»:¨\t0W_jC¥ƒ‹;€Ö:DØl ðÌôÎòzg33…f]à ®õÕ¿A´• endstream endobj 44 0 obj <> stream xÚV TSW~Ï„¼Ç"mѧXëK¨;Zõhuj]P\Q—$Š@„ ˆìK’ŸàYÂ""# q´2eÆÝºµÓjí±Zg,Õ¶Öþ^fÎÜ ¶ÓåÌÌÉÉ}'y÷üË÷÷û.ËÈå ˲î3Ïœ°l„_Àôß1ŽÆ/#ÛßoîÌt’ú3Ò¬4 ‡$ʤÞò Ãú¾FWFzűÞÕ±zÓ¥§Þƒ‘³,¯KŸ±£||ÆøÅlJŠ‹ ˆW [;\å;qâ„‘ª1>>UÓ¢Ââ"×j¢Ušøˆ°(M<ý±Q³62,>I5ìˆøøM“FNLL¥‰Ú<*&.üÝá#U‰‘ñªÅa›ÃâtaëTþ1Ññªš¨0ÕóªG=øÅDmJˆ‹SĬ ‹‹¦Õ:ûÊü˜9ÌbVìUlpŠ“'Ó‚=˜^LoF`1ÞÌXf3™ÁÌdü™YÌlºw.3Ÿ `0 ™@fÄ,a–2˘`&”Ѓa9ÝxŠ]ÆÖôÔcu.YƒÜ[nvrrŠq:¯(Vü“›Á}Äs|¹3ãê|ÙeˆËe××\#]?pë'éÝ¥v°Kö£•,nC'>îä„zl§Í#2H~‹ºBqΘì仪ˆR͵˜¾‡'žA‹Û ;À9"  ^À~­v¶ ûa ö–I&Ü hz]v`JFVödHžŒV4øò£²”}v¥¾âÑEux'ïy#—ÙSªl–ã"´l´lÜ~äø™íàê§„ÉËü´jE=32ÁI|²ô¶#kÚ‘Ã(¢ÇÁ»Ø»ÅÆþ {`zÉpÞPCWƒa”:˜SÚh/*k€ý|st½V­ýd)¾‚?ùò‰§â‘Ñu_Ôýõ|Âßò;O”D>1pÒòÃ[÷Ö¬ Ug4®,li¾fà¢òVmÐÆFÆ iÆDcž!GÙÇ'›¡RìFvi.…ôcdeÒLô:ìÞÒ4E­q{œ˜D›HK!] =Õxˆ(«æêMÁÖøê(¦Þa¥\#À¹wžI³cp%ε ÖΞC/)¿EÖ™Ñ9N¨†‚qª_ÐÉÙ5Ó É"£È`²žhq8ŽôGÝÑewN~Š22À˜žIF!ØæÂØ=Aç#š6œáë²'Ú.ÜzR|nöÔì'3L™EP |5˜j”îÒxÊ;‹ÑS†û:ûRpíŠpÃPÐh†B¸Û 5Ê»:ˆ\ÍÙLO ¥å ؼÓÒ?M³êìxÈŠ6»Â^Ø„^½R¤½øwûÛ¬×á}þÉ›wI€Øå¤~ÖÕá¥VÔ›ž‚Íö=ÔÓ^xˆëu ]Gà@ZUìþHJÆÙô£m<qÇXü·¥víÎ*HUnc¶15wùF] ̃ìËYù^)9g²oÆÊ¯J8£F —Ç‘?(Ý;ÒìÜöܼñ@†…Ò|aX•þ:ìâ[­íbÜ[i!} t`¬ÞÕJ ä* 0E̽13C½Â3βü°7åõÀ)¾„UÂlÛÊ]ÛNïËyÿ$¡ÔP¥Û™Z!¼Z÷‘‹c(÷gáã(H^úx% ä¶@v™XùùÅE%%E;kk?Xu'õ/À£Ï¥gÏ”ð€„­åÝ%{޵u8ÎÊ6¢ µZ©ñ´ðpú9âD\r'h$Õí¯·4‰P‘½'¹ÄZT´ð+Ía•k92†Œ]Cd>È'^U~ §Z*òëAýت°ì€*K&lSÎχr¨æ Û&¼5!ià ­•rÿKd¾þ#ͯϱI}mlºá,t‘Iè,”¦C†¸ŒÆÜ´ì-›f¦PxŽ<Öž}±oa»!WI_ F½>5âxMcr­¥iç‰;„3/%þ3 O8òÆ£Ñ8}/éPr¬ÒëV\ÚÚÉLÛÄ'Ó5w®Ö)Éj.¡bM½?Môæ±DE>ý”gáDÅa+Ì¡¿ÙÉÎdÃa¥$ÑSÔõ@Ð,I §û_ìuI 'àOUM míæjh†£IÖ5´µâÕã»V¶æÌ|(“B0V¨6C­ögßZuBÓ´sá3~0ñ ªï|pŽ8ölwY ä(iÿúœÔعst¡tË`#öoSÖËMÍù‡-¶Š«ìð·üå¼;~E…áG;n¶²èôô>ò2Œ’ T+ˆëwЧ—Ê­b ˜ŒfCJFf2èøµ’öVÙÊŽ6‡·Ìð!²0‹ƒ§©o’ýÕ\µéì«¿ 5ô¤Œs¨!YuÇ<¼uSÙ†;¸ù™ùŽ ûà\ádl”QB‰g?þP ­Ñ¶´âúòší»Mú\}¤òº][öîÝUa©I: Õ Õé’´5ëŠBh7â’wg*ac±¶%2yKR„ƒºz½eëæœ€xXÌ^œóqÒÝ÷o‰ðÅ¢ú¸ÒКy0â` äæ« Óš(wä—•ìäÑÕ,Œƒ«ÇÃÕ{÷ÀÕ*ð§l#¡ÂSƒ#"Qð okºpÊ“ ŽK7(ÓY\íàú>liO‘âX1c[oįdZ–Ó ft}ÐÉuØ·ïTSLü1’CæÓ3Y6OIݯ_sîx‘NCjý9¦!ÃÍ2¡ù½†uÚ‘aa ‘͇­ Í"™AæPöµw³ïÃî W¡nß…nܤùχÚÊ>¥Q>G«€ß–—]…~v.Öëcƒ ž %WZ£ÏRB^NžÁ@æ’!ž’šûm4~ÝÕ=¼Î•—–í¬Úƒ=‰ga5#Ÿ‘ÛD5Wcºu­»º]˜Û ‰ž¿­ ¯ }ßÝ™ÔÑú¼­¨Î¹Âo“\£I®½DâÇÉ݈?‡{Íó¯¬ós ùÃu§©t •³¶nØúù¬²y0‚t¡þ 2ù§¨/ ùüìíÓçU%LþøÿÇkî% ~—~9õÿ«á¿R@j§ªöúós_Šn2©c¨5~L|É„qIÒ÷á[è‹î=F‘˜È"ôt¾Ó-$¶ª#ÇöØáÏ`Û´;¦2‚!”¨ª %#Ëì8Øêͧ´3 ÉÁ—(jŽÆ94~ÀŸáGÝ'ý•’¸vúŒØñËšý¥fáÐÉ3凿ØHOÍ`¿yJ5¨«6ž B¶æ9dOŸ~ç–u˜ X q,:‹ÛÒ³“é½IkM®­µînn Þ*¾‘þÛ4D™‚¼ýk©- ©(«ö³MWpë™ÔSš"tû`¥cJfž>=;WS¾ÞLe6Šx飄7ñÕ„†Üº\kÎv8’y$4ü»> C`~yLGN¥1?ù¥r/-Еå{+XD”y¦).?u‡ã¦ÒmÏîÒ:MÎŽS*Ùo)â=[dîWz„A…qXè°azþ½Û¤óºýæÑ¶›âM07'*zãB¸\ýÂøÿ|&-øÉ}B¸)«LžšW{Vį8âÿ3jÜÐËÑ?ˆ5pì·ùüI œö³É"‘k‘;+eIîBaÙöç·sáh7`±Cêªr³©]‚17ƒ8“bO"`£ÓY»"Þ06E/‚Xºé<‡3º<ж˜r«¡_9ì0U:¬l’+%±4Q&Í—¼…"j"`æ+2`‹Hþ¥H'SZæGUG)hüièâ2Óéì²û%ÑûªäªØ+œ4Š,¯„ â¼Â=­T ,Â5•Å¥ ²ª³» ëÚX俆lµ[OÑE>¡ÒÍ9ßÍ]ríýo‹UŠà endstream endobj 45 0 obj <> stream xÚ]PÁj„0½ç+渥”¨ =‰ÐuWð°¶èn¡Ç˜Œ6°&!ƃß$ÊzÈ03yïñÞв>×J: _Vó R ‹³^,Gèq”ФÉÝ>ÅÊ'f-¯Ì4lB M{ùùn^Ëk›&o÷[•¾ƒÀaCÜVƒís}îÖÙáT«ACžÚzÁÙÙB÷øvŸV •j„ýìâ¦[Œyà„ÊABŠ"Ê¥›%®Άq´LHò$) ¯ª‚ ÿþ²Ñü—Y<äÉ|Ùúcä툠¢>“òÅZï!Þ#¦ F¤ÂçÉŒ6ßùo´ endstream endobj 47 0 obj <> stream xÚ­zX×Úÿ¬ ; *ëÄ%&³XKŒ±Æ˜h j,‰Š½"½Io+–²°»ïîÒ{Y–¶ E…(h¬Ñp£Fݘ‹Ñ›MLÌ<ÜÜï,ˆÞÿssó¿Ïý>ñ™çaæÌ¼¿·ÿÞsP”@ ±vÃGÛ·¬}séš ³fšoÌsú§ŠÞDK~Å¿*à_ÂsB~¬Åk%(M®Ôï#Í×oF™¯¯“Ëä÷­) €‘E©fΜ3cæÌÙKƒ"Cv{y‡ÙNq›j;kÁ‚ùÓmgÏœ¹ÀÖÎß#d·›K€í—0o—0ò‹ŸíÆ@·Ýa‘¶Sz‡…½÷öÛááá3\üCg†x}0uºmøî0oÛ ¡!{<Üm—„Ù®uñ÷°íÇ<£ÿº4Ð?Hæb»&ÐÝ#$€`µ&°¢ÄÔÁcìF¬£6·R;‡8¿ä;2†Š'‡Rþ‚aT,NYP4ÅP/QC©aÔpjeE¤FQ£)kòöŠ¥^¦ÆRʆz…GM &R“¨×©7¨ÉÔj*5z“šN½EÍ Þ¦fQs¨¹Ô<êê]j!µ›ú€²£–PK©eÔGÔrjµ’ZE}L­¦ÖPk){jµžÚ@m¤6Q›©-ÔVjµÚAí¤TTe?„X'»‡8Q _~oÑi9ÜÒÛò¸(@ÔN¡YzD?`æ0¦—V¿T1tëп [;ìÖpÙðºÓGìµzË*gäÐ‘á£ÆŽª…FoÝg½ÞºGì%>7FÍ®d¾<ãåo^þ},Œ­‹$ù6lÔ¯Œ}%ñ•¿»þêöW^[öZ,·€ë”N6Ù¾m[2~ãø‚ñ½¼'J&~>iǤ–I§'ýÎ+­øë`â-M(Ý xÒ<»ï+ä7ñ“XD›ðPĈz>í8Èé  “ãS#ã „ + ¯ª)ÔW4zïÝÈ­'”Ô€¦éAÀLÇÌVLI±h¡ß5|…v”ÃJή×чTMÃ'™è•r8(EWç‹çÍšmuK´ç{h;Un£ס',²¤Ülû‚;Õ`Ôt”*<A¡ ©JTÆA"Ä3˜¦­ø®~ üö#º§Ñ`M´X}ïãnñat‹¨Ñžç*Ååÿ /¤±ub´šüñ-•Z±ÀÕ-Eï´|ÎÕBc‚>ÌU¥„hƧ2®´¼¼¨öä¦6»xØ6,àþei«ÞKÏ!Þ«ï‡èõ e§œÿå?„é®Ü‘š;SmÄ·©ÿ&76¸EÆ„5¸è·ó~‰€þ<äõÿQj•‰Å>Dü£o›OrÐRè®J …påE—¤0V¼’ÏDëÈ­òÃz‡³Ù™Y¹Ç”D–Dr1 —§*ðpü–¤8ÒÒ¼VZ¶ub]†Ë —Ìñïè-þ{*ô ³wdPppqP#§‡‚œŒ V£!!¡…ØT)ø&/]½&>T d’ÓSÓso}†rhËËÿÝ‹ÄYxK:Ù‚f´ SzÁ±^w!_„lX&*(½>b¤ØKDž[¢Å¢Â[±R_4|’ÝnŒ‘BBJ²Z¹išã ç-q…X€^sBôÑS_~ ÝL{ô­ekì6çÀ%ciÃì™Ó$Ž»‚ƒ`33÷æê‡Ü7prSý9û“ÑŸÂ×pæ¸öÓçZÙ ëÊ`bn·Ô5œ‚‰*V½774˜q~Ÿ58úï_SظµÉó“ k’y7ìÁQ)ÜØÛx´‹±BµÏcæN¸ðÈõ¿+^‚ueO7êOÑmœÌ‚´QÅx4²öEë½hÉ>´D£óó@ :&3U§à`ÖŠuX¼ ‰ÇB˜‹rñˆÏ°å)<òÎÇ9Àd¤é2¥/¾¢ÉÇÛŽ…«r4b²´G#ç}‘Œ"5U!%¨J#œrÏìx±'^†Gaë¸°Š´Ô .î~y‰;Ñ<$„Ûæ,C_•íá—â»­§ÈÏ%½õ¼%ÞV.þ*àsÙÃ^—7¦+Ó•:e0E¹…ùRÈMÍŠÊÂã»%HÚ]š– y6ùòÂh.™H ŽÀÂ’Bôea\N\´<>Žƒ„|ÌiexÔ]Il® ÀDËc⤠OK*NBãWI°tUDbj2ÄÛ÷ë9dûS þÀ2&?!¿(7/Ÿƒœ8Ä© ‰ÁwËÐÁÔ®ð–-Bþ-Å¢ºÁœŠ5ýzQ”†‡CD,‡ëq=û< Èo¢XˆÐë¡´€#®Ç›û]_F\ÿR¿ë4ìÙÐV·çž/‚¼Œœ,­V¢Ñ¨c¥ðIàZ'…‚ùÔ~¯ç]»†hò!û‚\T"D5Èž=KÖÓäÛðDpç‰m:ÂÖ„V„†T„ÖÔTTÔ0Q>så1~¬ÿ¸×MÏ7G ÓŸÕ±š LÀû}‰$%ÎìN¦?+ -G—cö•ÌÐ+1šo¡¬[BÞ]dázÊuïK»~XPäö°$Øu†ïò”Eð>|˜6«uñþ÷.†‚£ðuÙïëÎ¥_…k öÂYwXgŒüA~ îÁI8 ÝYGKѰËÙF¨‡îÈÒ)9a1¬†a…ü“˜éüÁ,›´ &Ó„A—„¨£w [Ú0nÍ'sÀ?ZO>ÕUÉôÒ^ÊøYœ¯Ÿ¨A÷-´´| ¤ìûÒ³”¹MRóg® _ýÉd}øWäô]ˆ‘˜^|…}òÍDÜ©£ðȉf]ÇVØÒîíÙƒ®¸!¯µ2²Ò›K2±ºü‹£M'€ùnÿ{ ¤ðþö…›ÖàMØG"—“§¡ŒøWžU£%–!¢ÿd§„˜ä¤U ëG/«¾€4© ýés£u²xçgôþ½ÅŘBûѯìͪç‰ynÎ9öæ‹íû"jLzCÍaˆáL‡ºóiýL6K ñªõÁNþ;w+CÔIêPU2$©“ÕÀˆûäòL(æˆn6­˜Š_]à$u†‹½O6¤˜ °i Ò„úÆ:ͼ¿ ÕwßýÌápsõÕ‰eöE¯˜xbàŽ+ÄÀh;—öRÉí¸=~¢V]´µÖçÛG¦ÉüNböŒh.‘ÄJR<>Õ·[âG##é¬JRò/Yö+ކüˆVÐØ[Ö‡î4¡ˆñoüf´‹EÃ<·œ£½¼´•Ö+ê“ë€A#Ï—Ÿ¡LO–ª‰US”á‰;ÂW‚ìÊt(KÒ©È=&’¢¥ø I\&hui¹EMGo@weEyjÝa;#~ Þ`êêî¼ –À†#Q'uj:˜úbcEE”Ñ'Ö;y×¼sÓ…Tüb~þ‰¥ý˜ù å·¾k!Žº‹Üï}|W܇$è[A£ 4ª±“ð…6…a7ãŽ~1†¢ÚìæSNŸ¾‹Çàq˜ÅÁRñS¬G̲ûHøýßÈ›âÙ?`!'î[žÛÂw2h¾Ì®ÿSŠÂȸ%ÌÕºGwIÊ·ƒiM‰'lƒ°¶GyùÛïJ Ÿ2þ‹+‚cÆïï ù þ ›m®áe Na+På§–2!"ìji銲Ïäçef\…|bJ7‘X ¯Ó9¶·ÃÁ®“†ÏtŸeM+/¸sàóE9ŽŠ‰Ö‡Ã Êa‡ÅÐ|~»«6u/3§¿h»pñìÖ¥lpßiïÍbدšu‘Þyoöñ™“ß³›ÁA¤Ö±Í!7¾)Äň¯˜·¦0ã^ù+²üþÖo4Êz´E”Eç|ÒÂLvaÑÈEÕþ°ÖÆîí æ-ýü'êÎ~Ó1€§ñÞír~’Ù ßCîwIàÑÖ—Æqw­ç¢`³6h/s «¦ØZ(‹öOt_yÔõÄ"+ô*ò%^@L9›Û;"]Ã\àCþëTdÁ‰; ­må'<ê6vß™È&8 æzÕQÖTux_~qHýîbÇ<ß´Õ°‹yw÷´9\}EÏJ,oõ¯5_µø×ºÛ›HÒk»‰_¥ÔõÚ ù ½«Ù”|Uf4&¥H‰Ån}ßK"·¹ÅlV“ZV®Ù¯m4u©êÌ„u{ˆ±R :MŽFÛŽÆJˆŽà·4©Z!Mþ!ˆÜFÝyØ·¿]ÝFÖGÒö›)¯g°Ï!C¾j‰e"«Þm@·5›¬‘ô:ñ`É#RúBø!,RÓõÚÌ=hxgË';æc¡ô»DöAé¹³p‰ùöí›øe®oˆ_…èŠVî%í« Å¿’ºðêÇ¿*B6w{þ&…o\ÆÂö˜÷m u÷þ1ô=‹ÝÐ;xZ‹æÿˆ¤ˆÉÌ8N P'$ቶ °˜µxÛ^Ô)ÿ„ºÐÖ½§9$€ž™zü†6”„€®LŠèbÈ”s©JêÐv;‰gã¶Ão#¾íñ<<;ùi`ꘈ»Ã‹ z³~ô Jƒ ¡…ˆCSÐ:´C³ðb)ów[¶_#~߀¥‰>‡s²Îeû×eσE€…ö^;ƒ6¬ƒäjïBbèS&T¿W€^íA;ŒèM£Î(D¯^e…\µ¡\Ò#BðŒ°%øC2Ù<3™þ.ý ×÷©•„ˆæÉý¦q³P²hÀ=¬ˆ¸ªMEXÊEHfÙwjÐ'V½¶Dh‡ µÝdDBþZïB¶¯ý¹ãʵ$ñ*4·~$^|èéß Eê;ô9ƒ¢ç'ø¼ÉÍCÏD¡i`ÜX„9"Úª×(3%êQˆ‰½ßïôx7ˆcø»gØ|Y‹)®ÙEf%tsZú¡áêM*·wÀ‹Ðð:ú®Nî)ý„w` ,N üïh@Ä·ÛëOq¿Áw³ôxòŸºÖ·nóÑ)Ädkñ;x6vÁ.h.žƒ6HÅ1ázåÞ“Ì@®}nB{MýÆèêò½üÏl£6÷ Way+íÀÃãCð&pžŽÃ](Žþ“/B„ïìÛw¹ŸV„Ò˜{!*D]¸ðÏVX¡¿? ¿W{„Hf†£Ë½ÆUš…-÷…ýÂ*ékºg”ò…\°ùS×`_óµþOÓ •æOñ92à dÁï1 Z‘šzGˆ>CSØ··oÜÂ)`x`ºòj+õ²Ý±Nvì{¤?ÃÅó¹—5Y¤kìeøutkœ!®qRy¨\æ€ÞHÿqÞ$–J^ å'ñóY´Ùee鼡±1ÑÁJ_òÚ»Í3U‹:# !:!!)wã. ºð¿0âRš0¤!h.ËHÌŽ#|ÜßÂIuk0W·†}ýÕÞ {Òü'['»éynÀÉߘÃå²!"ùë±x4^Ì‚œâké½Pð=Woy)g‚«û¢?†Ä—ˆ¬žNy¦ºm5_qCˆ½SÙDƒHÆ‹žç‘’‡If`šCÚúúC*³ô$訒ò)þ>$=.=1lrA—•–‹Ô½#$š¾ ¢Aå›t_Bsó_ é…ò|Å áð"Q0€:9ö’ôó€7ªùÕBÓ;›MÌSk"¤üjD… WªË•5D0}¥­˜NOѨÓüô¾’ìx:˜È,•ò‡è*èxLÂÁ[½Cåã³Ck6ý‚¤}‹éж¯1ÏÔñXˆÂÑ9-¡áˆºñèÇ)ůIñ“êâf%*fQù@!í¡90~‡` Ï!‘&3QG ¨‹t)îR#ËŨ$}<̼¡–GC9ät9ÚÐsY¤â×—‡¾‡§Hű*®ž†«ÌXtOæð_þN£î1ü…þº7uˆ¦Å/‚6hØ½Ï ü`%| n­­^Ÿ)j¹Z|³:r㤤-%ª“˼#C=Kꌽw]yvGý¦RÂUºHs›Ym}¬2ø,úòì–JñEô3/añÓšB÷£pÂæüÑÓW9ô>ð»Ž(ḢôR)Ú5Pà’A­NŽ÷Þ ñ¯qmM¼+œ?g¼Þ=²äjPnjgüy§îW%×&W{–çø€³lûÒù\,NßrhýQåYu£:'‰q&’#¥ØŽ‚ä\BŽ5ÚÌ\ÐètõGL»ÏzõRøÒõÑ©ø"W žËÇ©ÓTnS{*ÍW®  œµ®æõÇ¡ ò¼ I°´ÏÏãådÀÈÝ®½ i)yžÈ¡¯W¢KÔ%äCh3ÓòÑ>]‚Þë˸i3p×¼C„u-O§·ÐÐ!ÊÂ:¶eÚÓéZðk¿ÇÐæ=GîÉxÔ®·FÓ 24ü’ù"þùleT•± …ZeÞfTP&…ºÌ¯Î|ž÷l(%-Eþîb<Ô¾ÂqCIU¥yÓñ¿{ñŸ #Pçô&²ø5·¿OŸæ†^™·º¡~Õ’'Ôù¿I—¢LÈ×PywÖ½vƒuÛ•÷Ðüsbÿ#èÎ×lš[•K0e§ nH…l¤×‡(ä>©Ó9ä@“4oöjroÞ^´“tˆå«üõQ•Õ%z°óRêwiªå’ôÐq÷ÙROZ¼ÿÈ6åGÊÕþîÙ NÌ{BÎpDJ7´·”v0Éè]v2=}énÇ® ‡9ø¬íZa®rƒ¼ŒŸh@žmÖOΡ¢[âô!?‚EçiSÚ¿ -1XWßB‰Ýý›<(Í@So÷ó8s—âÄ=æý;ƒÊn~@8óö$U:p(ÖN4äò8'DC¾fŸªAÓ©­ªìRí}qž³šþå±³gr7oàp,ýGë¶ñêZm¤á˜üc‹}ôëa>8ÙGy0èñ?¦yÆ'nmC#žX_~òQ·ø>úˆ_Ëb[óŠ/²$t ƒ2ê4Gµ 2V¥¦7“I5ßÇÖ…”úÉ‚‚ƒ Á¦jcY)[±Ü&xÒ-|ò\›zâöšÚuËsmÓg?»2¾m#DÚDD¥F5Õš“Ú²šuy'ÈÀ㣵6%ƒdzÚ…S9Yg:Û´eæcez­ÑÆš[N©:GqO(úxl%áÃþEÕ^±²°[ˆ>êý˜ýçUüïOО ¶É Ö"ÿŇ}Àâ2úã¨ÿ ‡Æ~k—ëKÀÁ9p #¾ñ+a f­Ä‡”8r}]|ðÿøqå9ˆƒÏ@(åF~¦A@jTí-!ï‹|X4fò<ž†¤±¿¼IŠõˆŸ~Dbc֜ʂÚCÀih„f8Zq ª½£¬À~Y¥s¥3¬ð‚Í2'™£SÀvóÆaÞb"쀷i 1>kEH+Îv?‹‚ ™ '©øFŸ÷ J{5]ÚʪÎÉa@õ…t6ݶùëýiÚCl!?X.Ná2ÒŸ YJ×tªéæâé9Øøh¾Ô <ôA­¤i€ðL¾âšiFÂÚÄ ~Ôi¯ø÷Òùã2Úc¦¥øA\µë™÷ÍelÂ4ü2ýà Äàç¡u¿¡†Ñ!?§Á72PëäÌ’µ=¤Œ;ëÒõ¶¹[ˆÁÇ zýI÷“;â+è}ô ‹†ÐXú<âÅ_ÄÀ•ãôöž¯Í;ΠU+ÕáñÌ–ÅJŒyuu~5ΜøÊðZëL”åäþRëzcȧ(Òö©¸¹£-¬!õf4,e¶y»-âæƒ×ñˆo”ùê´„AÚ. íé Ñ”–j‰˜’Ò.ÕeÄôtû_¾’ÂÿÚø<Ÿ:÷,—,TsWæÃ ¦¡²õ‡†@ú,­Ÿ&1›À.~˜-RHcŒ‹W¦&$¦*=ª]!†˜ÑÊcåF)xVÉqO]pµâ«X‚ZBzçd= 4¡wõ‚_ΡWŒBdgþ{Љ&<­©øÛNMedßà¼ßx¡úÂYîxÈ&ÚÎßÃs%|WÌ Ò˶ÁüŠàÇ]cgÑhÒ 2p!O~A–Ósw®X2?µ£‹Cß<{r”³¥x½f¢éœ8⨮1oUWzõŠIPÊÇ ù¹è›]^¼¿Û\ûÂTê°Ð]Ú(síkRç†*Ÿ¨JM•¿Ž³$ØÕ)ò;³©l†ÂÎýÕUaAnóò3¦È÷#} I2bµ)ùiÙi9æùh@\‰yçö¨‡-9lÊo0‹“q²Gm„ùýFµ!@ª”¸™8[2Õ¥æ©ISµ©j=‘ Þ¦ õÖEªœ¸tE®fÄ<œ"™Žô)fÊ›6¸º[êMÿsò”y¾Èÿ&IÕ%™±i3Ò ~B’ŸqSšÜ|Ë&týxŸuA¯¢ÏÖîÛw¨¢ÒÔØZØaF¬òWûoÑÆ™¿\¦ÊŠƒhˆNˆKQ¬Y$YôSbA‘a……ÙúþÕêUªè=§èçA£î°ˆYÉ[xØÎõëT{ÀƮԚ4•5mª sÖÊtÉù„öjêOõõdI–üœ~øn¨Å|ýð—Ð1ÿÓÿ6` endstream endobj 49 0 obj <> stream xÚ­V PSg½!ˆ¿e[1»qÝÞ›>ÆB«Ú®–ê¶µ¬í¨‹Q)b…’ÄI  y}ò ‚"!`D„JEX:vÔ>F;ºmék§uw»»Ýuÿ‹·;»hk·™vÚÉÌŸ¹wæÎw¾óCDF'zKÚ–­›w=˜”¼}SBüÌ›õLÍ-zºr½œ ͡I.ýËHòÝÍ‘ÿ]qAp¨;Ù“¸õó™óÆ3çÝì±èƒ%D$‡ƒJÊ!>þ‘Õññ'Ie¥rq~B›'HHL\»Rðp||¢`C±H.ÎJÉBE¨X¨`ö Ò¤¹b‘¢T»¾@¡=þÐCJ¥rµ°øÀj©<ÿ‰¸•¥XQ Ø&: ’—ˆòÏH% ÁVa±H0‡}õÜ_’´XvP!’ ’¥y"¹„E;!Œbb_„,ª”CÑÄÓDñ;âb3‘Ll%RˆTb‘Fl'v;‰tb‘IÄD"’H$Þç”rÞŽØñ÷…Ȭy¿š÷zTI=_3£ð‚ûL-l¢-Ñ8eŒó.vrñyœÂkÔÔÛÎÔ¢úJP“Lz”¬`ÖX«L*0!šÉhÚ­ ÐËýÖÀL\ÂONƼ‰ÿ1Áóîê)é†h úÂͽõã`GI-ØlU+ÒT¿Ú¡F \Ðä긄ƒüÚF°ƒµ–9ôdÅ6ŠPõ5b¸ÌBf%³bÍàÆ+TÌ›ÇátëÉaôvñv3©†¢äǷò݆‰#Œ„ñ‚æ¾àäàÈ)@§ƒéB ¬6“µ EÓÙ,ÒU¼·ƒçŸÇ²‹\<6À«®±»YxuU5Òz›Åkàkm:¨ÎCv£ž‹E¶ØÏ(¾Í¢ÏZÛ÷ì8/Ààûÿ2œBŠ@\".B–Ï¢yòÂÖ+œ®ëîÄQ®6°ûü'{õðl+¢@(cI¶håÙŸ‡9T¸÷Ú@€ƒ#^ÅÂ).ý,ý3^F䀩½êá¶@ïpvÏæ†ÇÜìˆØô>^úöß|ƒ×@šYB ú «6—Ú!§`4ô¯ö¡ã¯Œt€¬¾œÏ‹Èx[%ê26õr±«yGàbÍP˵£ð ¸ÐàÞ[îaî]ÁlLZsã;*lÖ½v‚‚^Ï€+„œ^?~ìÓ “‡eâ»™D(¤¢ñÄËËþ¸/{ñœð­¿ƒïåÍÎ_`5—$²S*ªC´7t5ô\ÀOò=ì ZÐ9Qpï*1gÒ{ÀA6@µ½¶±®«ý£q@^¯IAÁĨ*~Œ¯)Ô²¿ ‘YJ”×–söã.ü@-ó‰Vð‚JwE‰L)•û þŽ–N2³Bæõq>þÞ;sçg¾ÍlRB9Úy|ïÙ þPCðPw㨙¶ ªÀb2ÊùeUBémmûœm(zz|–ΟÄ['ñÎI..ÃI–Ù¸w¸Ø‹O±0ï]6|:À_Q ³Í$Mª½9Üxâìfo!ù äg¨êFóZ Ät€«s–¤•ºÀùëxõ¥‘À’«SÆ1¼äüî7bnaÀ¼Óú=ì@E²u÷‘!Õ¡>sÆ},{-š†…´lÏÖñü×ð½8z„÷~ÛœS‡bnJùnèGm­—®“!èÑ{óŠÌè‘ÎYÖv¨½¾0çÄ&fA΃édÌ-x╊–<ŮDz0Nò³ aý©¾7uÈËRÌ&/µ.ªÇÎÅã²Ùx”ƒ¾Ä\žÇ<Â_UÆŽF[MÔõ¨$æ¤ÍlVCŲŒ®Ü³?óÅÖhl†ÒÒÌܧ¶’A°éóÔeÛïú|/šÄ “\ÚC/çÙÕlô#¯Á§$‹µ"ÃÓÌßT ÖJJ*)δ§òt“]/¹[¬k†³W0±U_qmw8tcÖµ-ûY×ÖË*òöoÜ¿Òѣ㒗ÈQ8v¤íHóŽþª–pQø2Æ98~²q ' si=½˜×­ Kr…‚Ëè4¶í¯)bÍCº›©eæïÐt‘0~ô½ÐëŽ&§ï{£Ý·F™»QüÉ^?ˆÿÓÎÞvJ¡oôú`€¾Ï¯ ,ùdJ2鋹‰§Ûy"&qCV ÌŠ^Ū°ÚUvÔ‡  µª½¥Ú¼ª´ôSâsä?áOŸ?ù+Mò«öoðü"?æÏFInÊs? Ç17!ÜÖÐ0«ó Þ®x/p^¦Wpñ4îãMŒ]…º«æ×nÓ˜ÔP zª]ÛTv˜½zmÈ^¥¬tYÝT=[ÐQït{À͆€¾«Ü >(/«Ô©ÕÌcÌZ~ÚöÌ ¬Ôõuà$½3ø\­¡^€[×,oRúTìVþå%ü‹6,[ÓbÖ”fdгA j—²®¸A[«Àds¹[ƒìÀè$/>`o D1BïüðÂK‹u‹“ #×ú/ÀÓKÿ&ÐÆé endstream endobj 51 0 obj <> stream xÚ¥‘]L[eÇÏië|e•©29=7Sˆ“•™€(ŽIº¹N›(µ-´`)”¥£ô‹R}Zhéé)°;P7>†LDP!‰Ë.t^jBÈŒ.^jÎ’Ì2–“Ýyóó>yŸ<¿ßóâ˜D‚á8žZüîù·Î•?¯P*OæÊw+… ‰¾í«[®G„C˜ð .dŠB,<-!6NIîIE™†Ý{r7ÿ:°›wŸØÍç’!¡ŸÂ$8ŽÚ¬ —¿˜#—S›,&}Ž"³ÔÙdnAAþò˜\^@¾fКôjU#©TQ:­AE%/’gj½–²Y…:ŠjzùèQ³Ùœ£2´äMudzf=¥#Kµ-ZS›VC¾al¤È3*ƒ–ÜcÏÙ;FCS+¥5‘J£FkjÄ0\Rˆ5`¼%‰™‰ÆÎ`ï`eØ>†cìž'zIô·Ø"Щ[£šKÂL ÿUàÅ[ù‚'-‹Xã hè›{çëÄPºÃÓå;ØCÖ#ìÝ~èÄ2 +Ö°w8Þ—ž*Œ88þÆÇ×.àüâ­oóó[Ei>Û Š»š{»¼/XèŠßí$hsâðÎížÎä´î *æaˆAˆ2ÁH€Yâ•Áø ýKœ7ôÐÎ^{¯¨d^½JLÂåaîZüsö𣰠h ÞºÓ\L]¨Ôncge0Ò?Ö?Ü?ý†›§'òØ©Ñéé±ñ•µ/¿„ øÀïôú Ôí÷‚×ߋޣ]°£¶ýòÇÜÜ$uµŠ0Be—â½V£ÖZQê¶ÈÁ /pøÖÑěߥÑÖn <È2äŠ Ä|þÈr0ÎÝIrA.0Ö?šðõG§Ö~» h‰©­—Émì2(Ý\ÔcvéÁ“q¿} ‚ñÐôÐõkü³Ì\ßà/åq@‹¬¾N¥ªÄ>s¹«¥Çfôþ'ºå?’¯B¼öX­å ¯—ºèÉ ÎŒ3ÜG« ¼ÖÑMõ â\¨®-÷Ò3ÆqÓ¥†€ r¡âí‹”g]5Y•ЮqY,:[ ÐÈ?Ÿ/Èü[™4íÒÊ vØÎ£TáϽ ðÛÿcÊŠÄÁŽåÝýχé˜ß¬?[ñ_µ^”Ô¹U3¯ À_ÿ`ªò>¼ÓÒ¡ï,ž‡ÀÇX[ý¿ð:·¶ÉgÝ^N d¬óÙëbá’fôš[¡u2VŽ™[ªù¬(‘^{¸š€W¶Nt¯:WP†š©ü„”è„ã@­}ê‰OÂ4Öik6´U•®«7ø¼9þñ%fÛãöHÓ•Æ@5SRÀšÿ~“ˆÃW¶r‚‚ey·/¡b%R$ù1écÒŸtÿTÊOûãA©”ß8øœ ã endstream endobj 53 0 obj <> stream xÚcd`aa`dd䋊ˆðtuÒvö Ž44‰Øäý ùõáçlÖÒ ?dÈ2ýcþ!Î"÷Ћå?“,ÃGAùŽD¾‘j@‚±^ˆ…‘‘£¬¦ÛÀÀXÏÀÀÈ9¿ ²(3=£DA#YSÁÐÒÒ\GÁÈÀÀRÁ17µ(391OÁ7±$#57±ÈÉQÎOÎL-©TаÉ())°Ò×///×KÌ-ÖË/J·ÓÔQ(Ï,ÉPJ-N-*KMQpËÏ+QðKÌMU€¸]B9çç”–¤)øæ§¤åÅÈtà &FF–Î|?çNYðÃw>ãwõåÌ?$¿¯ýó=º~zgos·dccSƒ|wKoç´†ï1¿c%~‰††ÎÎîɆ©MSå&w÷öNŸþ=ú{´Ä÷äßɽ]“Ú&vKNŸ> stream xÚcd`aa`ddäñóŒõwÒvö ²ñMÓ÷ý:ô³‰õ‡4ÃÆ²L?䘈³È200<‘ùAä]© $W 1°02r”T´ë9çTe¦g”(h$k*ZZšë(X*8æ¦e&'æ)ø&–d¤æ&–99 ÁùÉ™©%• 6%%Vúúåååz‰¹ÅzùEévš: å™% A©Å©Ee©) nùy% ~‰¹© 'ëçü܂ҒÔ"ßü”Ô¢< “ „„˜Y¼÷ÿèàû±¼{ÍÕk¶Ïgü^‹ùû¹Ÿ‚¢Ë:{ 䒒Êuº9²Ø—uì>ºŒãÏTö´Žz¹Œ,¶-}»wìxÔ½…GeM»NÇô ò cî~ÿåíÆ_¾—¼bþ¾î{‚èìY[×ÌžyòȱCÝÏ8¾s«ßø-ø›ÇÆÀ(jSËÌ«fmÜÙ]/·âʹ%{º9^ì¶1—ïVv²ÿÍõ›÷·Ðo1‰ú†îÎî"Žòl+¾»³æ°u”7GÖW´6ÛwWwsüvcã+[ðÃyÖ÷ü©“°ýNœÆ¾†ë:÷ò <<×góðÊq±˜ÏçáüþM ,°Å endstream endobj 57 0 obj <> stream xÚcd`aa`ddäu ˆŒŠÔvöõõ´ Øÿîûõêgëi†2Œ?d™~È1ÿg‘{èÅòŸ‡I–á ˆ|Í"Ÿ €Hu ÁxSˆ…‘‘£´ªÓÀÀXÏÀÀÈ9¿ ²(3=£DA#YSÁÐÒÒ\GÁÈÀÀRÁ17µ(391OÁ7±$#57±ÈÉQÎOÎL-©TаÉ())°Ò×///×KÌ-ÖË/J·ÓÔQ(Ï,ÉPJ-N-*KMQpËÏ+QðKÌMU;]L:çç”–¤)øæ§¤åŘ tž##˳|?ö6.ÿ¾íé¬åßSw0~?rýðkæï;~êˆöôöÍèîá˜Ð>¥^®½;§£¤3¸]¢´³±«»’£vf÷ôÝÝ­MrÝÝm•¿•þœ•h¯éníî⨚Y;Onm÷äÕý3§n]úuÚÖC­ç*ºƒºÛºÛ:;ê:k»Û8¶'•ÛÚ½tÕŒy‹7Ì>Þ=‘cjs_‹\}wgk{e]L¡GL7GaëÂeòÝ3z¦OXÔÓß?»{Z÷]•¹“6,\»vúŒCwlØÝ=£{zÇäÆÐ–î ½¥sj.[¹pËÚâõ‘rÝáñAAAE Õ-|e ~8O6í{Á¶ß SÙå¸XÌçópNâáêáá^Íu“{y?Ï÷‡"¿òÌ” endstream endobj 59 0 obj <> stream xÚ•‘mL[UÇÏ¥åÞ vu´tºõ^ Êx¦âxý@'3¼„ÂVáJ‘—²®£e*™Ìåܨ2 nãeÛ€6®Àôœ²è$1ƨ1&ê>L|Ytb–çâÁÄ‹$~ð›99ÿ'ç<ÿ'Ïï<‡Bj5¢(J›W–SVš[œS‘bÚºyü(éÛ«7:C凑¼—’÷…ÈF•©Þ‡”t„¢hýÁ-]Û¹¥ñŠ¨èš¢Ø¶—±Ét0ÉdJ͵µ¶Ûê­~mŸ’™™‘ȧšL™|v³`o¨µ´ðŇUh¶8”CÔVÛ 8ÚùýOZŽÖCÉÉN§3ÉÒ|2Éf¯ÏŠKä +_*œìmB_`kqð%–fߦNÚ¹¶æÖSÁÎÛê{‹BKç# PÕŠ\ êc( bT‚žE•ˆ AR£cèUE‰!±!—UOÈ=Ún,_‚Á÷)ˆ…G ]RmÔÔÁLŸ"F[*)Æ,Iÿ ýËàñlN‚93Ýy<Þø B" éx2çM²ƒ•è&p‡þE™mÞ!ȼ¡£µò-w Y‚g®À€n² Ò€Ö·Éá_špõÆôè¾4Ñ;¸ã ™µ¼OH\)Ñv<æwM][0â+®ó=Þéq³_ù-Os Œ^Êë!¾NLe`gûgF}Û7Xš_`OCŠ!‘IHî°WÔú¯1 HYîcµò%wŠfáP€šH8û³J~Z ãƒxŠÃWÝ_V.¿(»P ¼8--†D‡~‹‡tH]¼þ‚ wq§±§ËýR[Uic¡b‰î…¨÷¸Yµ÷š¸06; ]Ɔ½d·heµð–äµ X@*plHþÙP3³êÃuÜær™™oxßõÌib¤Fûg©ò÷Vê: •eÙÞú%%ʲªL‹·½o_ûÈ3½UÔ÷K«sãÎ,#™ø¿é!f½b>ÆhÂå•'ª?&÷ 8 —Ö4±úo1äð«~éZ톎”I©•Ú î¾BÔ‘Н¾3à‹¢82œ¿90ŽÙOo•‰Î//ä^Áf\óÁ™a,â‹ìSêEëõWç1 ñ¿ÿD™~"1Üa\Öähgõw—˜g#p›âa­¼®Ìf]¢ÆåÛ*øz »†G|wp”ÄX=å½]öJ¯McfFðgèµn7ötwgØLhP¢Oôyk¼/*–Ï0‘"²›ÄžvÕã*efüÞ›bÿ[zF•vL»«€S°EßëwÚ!dWh™ž?öÎμã™UF ú O£zZ³Ã®ÎÕ„‰­¬ü;Cð] endstream endobj 61 0 obj <> stream xÚcd`aa`ddäóôöðrÓö vô54‰˜Mþ“,Ãjü«žõ‡,Ã9ÆòL?˜ˆ³È200|‘ùAä[© $s„ØÙ…$Û{'–&¥BÉüœÌc=#çü‚Ê¢ÌôŒdMCKKs#KÇÜÔ¢ÌäÄ<ßÄ’ŒÔÜÄ 'G!8?93µ¤RAÃ&£¤¤ÀJ_¿¼¼\/1·X/¿(ÝNSG¡<³$C!(µ8µ¨,5EÁ-?¯DÁ/17Uâ=åZš“Zt#3#c;c3##‹cÁ¾Ÿs»7ÿø¼™ñðæw73ÿLý© ºª£?[îÏs¶œöŽlù?سûÚ×Èýxʶ¦¯oµü_Ö?DÜýóùÏ]6æ?¥æ3þ©K„V¾Ò…?–Ný®8›íwÒtöÍ\›¹—Ìâáb^9.óù<œßŠÓ5Y endstream endobj 63 0 obj <> stream xÚcd`aa`ddäñss‰ rÒvö 2ñÍÊ÷ɰ¬üÙÄúCšá‡ ãY¦rÌ?ÄYdž ‚ÈGü òžˆTŒ¦B ,ŒŒ%íÆzFÎù•E™é% Éš †––æ: F– ޹©E™É‰y ¾‰%©¹‰%@NŽBp~rfjI¥‚†MFII•¾~yy¹^bn±^~Qº¦ŽByfI†BPjqjQYjŠ‚[~^‰‚_bnªÈÍz Â9?· ´$µHÁ7?%µ(è$FC ã„˜Y¼tðýøÞ½éÇüMÛç3~_úùûïŸü¢+Û»så<½U»Ó»9RØ—vŸí>¾œãO/{VwŠ\B Û¡þ›Ý‡ßì>Ä£²)]¥{Æy¾²?œg}ÏŸ:yÛïÄi웸îq¯žÄÃso¯‹ù|Î&"=Gr_ endstream endobj 65 0 obj <> stream xÚTPT×½]xO]—Àòj›Ö·;ŠjèdÄ8*ñ·¨4ˆ®°ÀÊ. ËÂBX‰À²ßBÀá÷ÏvYX@ ÂV ZFS3%-–F“4Sbt¨µ‰­ ÷á³™¾%Õñ“v:óæ›ysï=ß9ç›óH(DAˆö†Ü¿ï­Õ¡aC\ÿ¯Åse-sîìÏû ‚]êÆ2v‰p)BÄË^|E÷tÕ?½äª+ø² À ‚Òe­ ZªIÍÖ*“t2ÿ¸Ù«!!Ákdë‚‚Bd[Ô ­2Nž" “ë’j¹ŽÿQÉÂ5qJ….[æ¿1I§K}}íZ½^(W§j´‰›ÖÈôJ]’ì "]¡ÍTÄ˶kRt²}rµBæ¢è*¡uj†N¡•…iâÚžé‚@ô*Š@GQ4’»'*Ö !Oä^CÑ&´…¢·Ð6´í@»Ðn†ö¡ýè çßB´"ù"%º…f âœÛ7x ´‚O„‘Â>áŒ{›‡¯G±Ç7d9ÍÅx0"î`$À‘WèÎt«Z®MQ·§wuµ·w1b¶ l¿ƒÀú[<>'¡­¦R-¶g-¨€R‘Íð!\±QOêÈc~ “¬òè+û ïBŸÈבLkú¥â¹„ë'ú¸ú.®ræ6Ï…Ðÿ"=ô\†»Ý£‡´tâUÐ PUÒTl> ZêI+©„ÜeL¼ »ÓÉh<¹ ê{¥l+ 6seË{U¥Ðüó–”:.„²{ðš¸2çc?'EN®çÊh§ÿc¿¯Ü²ïrÉçNó§øÓǹܲã_ççœäõ¬ús8ÑÚù—sVoçí£3ø©›vÉQ¾“.—w&:²Þ¨ÿLúkMi€#‰‰p©Á¡$ŒCoÌ`BÏÑú#@o“ïQYrlÍ-6gl¹IÚa»TÙ Ôè¸b½ô$)±¡C%›‹v&‡&e¼ qTÈƒÔ †ïñ \­³S¿£WmVÇ‹í½ÌÀoÇ_© Äì„ÁšgaeVœ0ä=;‰­Ó’¼ ߤyßÌÕ ½Ã# à„óé6¹íxéH†c…‡Óâ2’O¨C (ÚÓûó,`†fª ‚vÄ^Ö\ /ÂnÅK°—ÿCN$ÝÇ’ÒS)É1]|*Ÿ@Zs¶µ£©Ù6 è‰x3äÀJ†#7ª>å>!£ °‹Q‘c¥µæÑóí¦|*ôäVcu¿Oñ£r5™w’ÀÂ)œ0%À{ævÓÏO´á)ÄÅÒfó¥Kµ¦1‚Üe€a)ÞM~ûÇn\«ÚÏp§^x/´`rP8‚„/ SsNgWÔ•¤ §L®ü¹TaFÞŸb´eR2ƒ÷²ûhÎ×Åà£ÊÂ()gyŠ|¡ÔbþUÃŒ¸w—¿/•<,cè®ôvµJ§MIiÓ:¾_E.Ø9bÈåœïý1EÃM#ωçÌ»žgõvù‘èú$#x®¡1º}ùúÕ¦øm?$õ©%ÿõâsž| ö“ý™íq5Ñ QrÍáükq}ÁðD½MI>7ý̓[ñŒ9×òÿå3æ S’ ó´ÿ¿Âñíy~@’[Èÿ™A•ÁήšÏCß´€ÍÂJ/Yþˆóä$~2>^ü±'–<|ˆ=NÏEÒG@nÕ½Ÿ6dƒaè‡që`×èåú>~;&·(ÛäæHCüR«‰ŽÖËϾßS‘³“³wx‰ÛùÐ Vã•Øƒ1‘%&> éTª%§ÍÒVßÕ­îŠaöƒ\® ›WÂxÙ ”¼ b6À`eƒZ‰ÞQüΨ?`_§¡2Ÿ)‚x'¿¤¤  °HÕªªPò«ã§'·FJ!¹.­-£W5pf´`ôt£±5§ê]k(¨õ~Ǭ€´?ç_1V™*òʃw³¥œ™5L˜ÍMÍïUT×–—6ZùEëé¼9!… úŽŒ6eOâÙ-uiå[kaœênºÇ`g7”jÍùPX TœmæÙ.ç—8ð†âÛ)ü²]€oϯŠx¯†4'ù®2RÚ/¹N’~®›8÷Ñ$3®9DnQ%&î„;M î"Å­lh#N©®hõàNÔŽ…S‹¬"ÑTƒh1³PÜ"Z€ïûüúþOÛ endstream endobj 67 0 obj <> stream xÚW TgÚž˜ŒŠA‰ÓÂÖÎЋ—VE´jÕº ^‹+ÖUmDŒ\$CB’rQÈA.á",ˆZ«TÝZk¨œmTê¶ÿ¯nU¶µ­]í¶»ß´{ÎN¸þÿî99“óÍ|ó|ïû>Ï{áéIqDÈÊõCf¬ Ÿäº3ÿ6p­¿¬óâ^ ¸ÉîEŽrÏ{¾H‚ ]W%îOp]_â/Oøž•¢‡  7ƒ‚æ®'iñ±qÊ€é1¯ÌY´èÍ™sƒ‚„È¤Šø˜è}aÑÊ8©,ZÉ/6Écâ¥JmÀô%qJeÒâÙ³Õju`´,9P®ˆ]úÚÌu¼2.`£4YªH‘îX-ß§ X-“ 8ø·B.KR)¥Š€0ùn©bo§x–Çbb ±”¬„ëˆõÄ&h*ÑS!JãM>ÄââE‚%^&^!¦ӈ׉YÄlb1ŸX@,'V+‰UÄjb ñ6J¬%Âx„wˆ Äï‰MD8±™ØBD[‰mÄ»D1݃Äþ•4â´ÀK.px{œ¾&L^ð ô¼íõ¦×1r*YD~-Ú&ê &Q?‰si¬pl˸WÇIÇý÷2ïÛãŽo Å¥>/ú4N‹QÝ5Á%.HÈ-Buti´µÅA:‹¯“éq×¥¬ÐDÚŽ& Ñ—Ýt»¬~¯T‘˜¸§iK‡­¹™/´þ¢¬\æf ¹È_|è"‹ à(U©¯P3*ÈÖç¤á;ÿZí—­3dQÚòÔj¦ŠÊ Ë(0 uƒsžO£ãO<Ÿ>ñ’•‹ª´z§£KŠÊŽBU«)Õ1™k4dâÛ8Æ/3'- 4v4ãX6º‹¥~æÌ|c1P–ªÒZªøûE¸…ú†ÛˆêéâB”e•(Âw‘ÔÏPœkÊJ§IW² áïg£Nê‡ùKF¶ë eUº…)†|“¹˜÷Êñ“9o ¸!rr·è̃)ö2¥x|¿ÕÏJÈÉËÈÉ9i”¬*˜ÉÊ:hjVC,[û“Z@־⫆DYT²?’õÐÄBÙÁcéGròU  ¯àT´‰ìÁN/ìGòg¢Štø~íDzç{N ‡æqgi4‘üª&,a×ÞÐ×ÙWI´YN_­yÿtS½ëoc!ƒSHÃ~%ÚÀÂ6ôHÉÏI¤NÁŸZfIäu¥ïKœïõ,®¢Bq)%(1äWMË#ßݽaë:Wå@Q߇Nô¼óŒs»SòëC-†)g9–<^TÜÂö‰ª &>RÔÌj\-’ô#z^´ tm­PSÅ<z¬ÛÅàçQÊÛBj@ÕÚÖj¦WÔœs,žéCê]ÖºP›\Npý?:Ñdþh!Z†ì4šL>s2J@ùÏÀœè¶ôx¿!Á½Bd¹§$tl„ë4Îà ̇®Àd9ÏIó~г¸Ãm"ú ˜µîµ8Q´šGºDš†7, uÉüñ6þÅö~Ã÷Šób5XyÔ)|sDCp.¡”KB´‘»A§×ç'µ†Ô+x êx^mý…{õ·S Nn"Ѻþܲ8‹±ü›Jó;X®Ð&Ùñ’Û[¿ÜHŠ3ÜQ‡ï…dé‘öH .Ô@Ûsî¨a±sÃFïÄ4D7:e¬4V+÷å"œÅ~"(šø¼/4·tʺ«@!êÆý>®ÆžJ/ÛÕ™TôÛJJòxqet©´ ÎúŸï:wAc¡|Vab¾ª$§(o,òYÀ&c’á`j–lWÛæÒH>„ÁK°ðö¡w’)ɃãC¥9—ŠN½ù;‘ß0q~ÏÁ dBVV»\4òä"òï7DˆFâ†BžPˆ\‡à¦e8…Üf¶‰´Ø ¹i€Ez”Lñ·d@hDÄ–µþÉ o›D¼žµëo$ö¹7ûÑ£{ß Fœãw 9ŽGßœ;ûP˜S’Ây´Ð5‰çŒ@Ùkx ŽdåS(Qt}ó_ð«;§Àr™UWÇ”ƒ½ØÔGM¦êÃfSð%ïÏW²’³xU.öÙ3¨ÕŸ®ý‘‘¤´CwÑÙf*­§ßñ5)e·665²€ ÛÕz‚…®»íhJå2ÈŠy äy¡S¢G‹9?­ŒßrwÑ8Ó_Hª!…Ï¿j#é:}:³…§Zðð;$A>sx‰•è߃Hm|"…·yöŠ>¹|ñÓÏ//Ÿ7cÕÚU¿»Îå<úÂ!èu¢ä>!· hû>Èatp /[“¦ÙÔ‚×¾>gG"ô‚õd²¦¸*CPuÖŠÆÞW ¿ƒ'¿½¿‚|ÛúC;ÐÏìÿÃý¿~HÇ‚¡“é&ÎÀFr…äSþ๤¤+¡q—e'/3ÁŒ™X‚'üõõðn\‚S öF íõ\)Ú¹péÊw®÷}­çÚÕ®MánL¾‚&99Q/’%hm­‚vDþîü7cöÁâÇS¯È³µ¹œdµ•›­QmÝœ)‡`þPw—2]¡Í½Ÿ|t ø¢­(~Õ¥iÔí@ù²Îùðžr$ÄnqbñYòË?As¨xw[u­Å~å-нµtÇiwV$”k( &2t™*AœYQœ k ƒšÿóz4 Mú¹û+ÚµnmH+Š®™Ô*2 Ò ë°r Ýœa6VÃa(8l.8F¡qøSzZðé÷Y¨,ni©¶YŠ¡¨>äó£‚wNhYR±é?n9È77DÎed°+M¾[ß*¯LJrk/È É*jÄÎÚ$_ðhÝå1O¦k÷ÿC”äÌAÒ“j|1¤‡¡Šô±ÙxµÄ¢D~ª üöÄžÓñD,ùn&ò@ß}|çÓ!a7|ÝÓsýÆÕµAaÁ!¬+h¶KuáÃõóZŒ*è§ŠžêùŒŠ9T/%óÌÒ'eiÿ¿¼uÓŠf9Ñê{’3HÁWùo?ùgLÉjP5Õ–†êôS Ù­ð;mø:JòEë ò±‡{`¸…»»WÈ‹íýüÖé¾J°Æ%SRcØÆJ –ÂÛPGé£ýÚB›öZ¡¨Ñ …Oµ§J<¯Ã9‹Ó÷.ã- ª}ºØàbr†3¹—‘hNÂÉcívJ|èºéÔqIBn9ïCÓ(Ƹɱ“X€obºéebÇÈ×D"~PÏ‘à_µPrœ·¢':.CÈípá[y’AËb©MæÑk¡Ší"·áó^FòP}Úé'µŸæ–ÄÁž· Unv f©)#Î{u ~É(A3òº•ÿx¹‚û ”ùúNðï„üâJ‡í¾Éœ_C™È#íxLAVij%”B;ä[ j†rÿ€Š¢N¤ ‰¦{uŽ”‡¼®6dê²Ç^õÃ3øFLëNÅÓñ<ß+Æ}Œ _ÉØ»È§ûxÉUCñៜÃ7BƒkuNßûa_ãÓöäh³ýäÁªLkvU Êö³=›ƒf½Œ)8y`ô‡<Å¢4žðØ<½LGŽBeÓV*’Rµû£[cº˜Gpù”Pb.y¯íñ½‡þ.ùŠ åþL[ô“9³sdòý:ÏEVqZiZ™ÚI ×)SÕú}*ÐRºr…)Â#E…Möz‹ŽÁÑ̲ô²´ê”Vh»¥¶¢º¼±*)qF ·¢-+!±¶HäëçðövzgÆzjåÞc¸šIÿ2º} endstream endobj 69 0 obj <> stream xÚ•V{TeŸawgÄ˨iͬE3„O 4*ã&bXBÅe¹Ã.°ërYˆEx–‹„`a¹è¢\äR ~Š÷r$ ×[©eò•F¦öïï¼þñÍ"N|;{ÞsÞ9ó>Ïóû=¿ù=CR)A’¤}ð–×7ùmY¸Î7(ÈÝzcévœ%tý×O&Ì%„gIá9•³¤Ï¹`ª¸ÿžb]¿s´®óÄe²z!%IZ›Qèââ¶ØÅÅuJž£QÌX Xâî¾|‘ÂÕÅÅ]ᙨL‰KRø†ib”‰aq“ Ø¤ŠˆUjÒóWÆh4jW^Ñét‹ÃS«R¢W-X¤ÐÅjbÊTeÊ6e¤Â[•¤Qø…%*£5/]שÕZ2E᫊T¦$‰µÚ.&\&¿F„6 ÒBCèÄr§S‰iÄtbÁ3‰YÄlâb1—x–`‰µÄz‹ð&| ?Ÿ 6›ˆÍÄb® A6Ä<"è#Éã6ólj%Ó$q’kÒH©Qú@ö²¬‰²¡©³r™¼žžJÒglçÙfO²w4D[Ñt ºñÓ‘`ŽR'ÄG5«[:ÌÍ-¬C/O~fA­‰ Fgäç„fa)–½„çà Øïž…¤HöÍAX‡K™×|Ñ$ô"rúòç¡¡/ñ‹ØÉÛ¾Æ9/Pü#‰ò-4 \cªÀÏf@^îöì¯uÄN}‘¶iÝžÙO «®ÁD?yÅUž™ qñf¨âPUe†–ÖdÈä\)kÀž<ñÚe‘ |Îäåç烞Ž3C5‹~ Z+>nãÊk¡!* ¶©Y¬¥NCÒ»û:Ú‡à&Ï¿Ž±íŠË"Z>ª20b¡.¯|G™±»ûÀq ¿±„.åÀk³D- xÌ“—°õ1»½¶ø,å’auiÌg`(6€aWï6 JéýººäT>Öí^ šŠfÞù×}núž©»|¢ü˜ék«/ažò滯'Ö§ïß_g:ÀBÅÎ=;Ê[Í<ìú«ž¨pTÙá‘)ÉéE!;# uVŠDU¬HÀc^ EF‡ÎK:0¹ÙPÛè¤Ò¬N^ô§²T7ÊÜTe“ÈœôœÿcËøÆ=¢Úò*bØ$*¶eo£±ÛŠAñèž ß“[a7ðh O~gAy¢8á(óÇal¢bsó”Þ'×Aòa¶ÊÊ>Þ}¨½§²èÝ^o­òpç" ¸Z{Ô`˜]¾ÛP\¼wŒ™:SršêC¥ÇÍõH†¦þ:Œ$VŽ`[6Âw| ¥‘Ïhòƒ—ÐRžì»jEΧ¡{Lzæî­a¨€ýP¹=gäÒ£æ ÙT{èXü9'sæøµoNlXçþVàºçµh†A|Ðʓݖ^¬LðæÖ51ÁØ!O‚P:¢;Ú mÕl)Ò"yÿö°¶¦¤ªh+!,¾FåWg@.ÐQ IãÞ“§¦£êÌì¸~ÎZÐ>Ë=t‹9kèAúæòØÛ-_é΂÷@èÙÌ ižAàA/øÑM„<íÇ»#,ÜZÝïSC¯la¼üžêëÿçÕ«ý!ïùàÅá RŸÓ—.œ9ç‡Óþ~oúlòà¬Ù–^BEæ,¨ö¶Dx50ÙxúJWWȆ$ƒ®ª´¬´ ŒtCFC’Z—–Ú€(4MAÓQ0ÊÁÄ•—°Ìi¹X–ìî$e{àä¾Þ#trf ùÅ™Oo ܲjE0?t{ðÔ;mAÆ·‹·¶vІ þŠòúì^°: òwAòW›Ág¤µÌÕ‰FòÇÙÙsÖ牄ÉMU%êówêó!ÖW¥×Öô#ÙugX´ZÃBj¥²¯v@AW®]!;„·%‚aö´CGg$dqx„ÊŠeT;ìáÐc¼ˆ©ì‚ÎŽhÈá°@åDC”² *9‡ÖáGž¦‡mVN{2 mºèŒ÷ è€ðÖO8è}؆ ´5óO~mA ?I„(D2uú -› Y«Í×g„y½Ì{ðÎñæÿ œ*‹JÁTh(2ä–Äš?ªÚl2™¯8AöôÃsݰÃ/óÅN¿Ðü jÔEÙðd›DTk…KLk^E,»zÜ=ºñ"J[Ñð6ÐX²p!žŠ§ ;#‚ë£Æöv:2ްWÇ=å}ÊÍd6¿ç±Æ;àË;wùËçû‚7³ÖTÌEd/xí¾*<ÐFÆTˆÞð3f°Ã"'<;þ6Í@sz†­¹,Q¯¹ÚÔÀ· 6Âò6Ý}Úp‘©½ùE×ø > -_C[瀖'­=A'~¯/£ôj±üPÍ¡™O´xæ„ýñ1"ÞÏ£~ž<~QÖ¿DxbêI]Ù`+„¿SXšvl³Ø¸¼¤ä‚ƒ:H:îi´z8Ìá~yŒvl@ ? ¬…­—ßþôØ'¦}Y¾,Îç&qùõÿõˆµ¶sÄR.Â2b’èö첤?zbšh’Μ;×{aðÜëÿpÝðÆÚõ‘ßž`ÇÚ‡œÅ\äÃ<ølITSþ> êŒMµö¼Ê‚OêÖÍt³ü©:¤”þiÔjîÜ¿b|‡j¨Êƒb±*ëx“ŒòqŽ,ŽØ…–Ñ ZÁ†Anã”a·o©§Ÿ»âUy¦zL ·±žza(æëïÏ['C› ºÂ¢øÂ­ÚX =¡¿Q|÷êÐcž¬r$BˆwÌÄ öÔýé£BñYU`Î> stream xÚµYYoÛF~ï¯Ø·&,í}EËGãºvÛñ‘ÔªÍ:˰ä"ý÷ýf——‡U¶‰ ˜rçøæãììn"ãL&¹bÒ3S‚)Ï™ÒL[Å3Ú2)˜åIˬ“ÐbN¦$sÁ3e™·°1,¨°€w‚ !àÃá®1˜Ð\0ˆÂ Üžžá™kÃ4"Ü °8‹;bx@1±8ž¡GÎ !”X˜â&0+qwŠY»F PÏ@e¯b;¨{øD .š€ gË´ô†!!­´˜6†2,\< bÄýHÊŸ„ò%UÅíÓMñøâö¯ÙÃíŸ_¾²ß_@‰s%ýï/_&'³ùýîtY¼Øý‰ì¹—’Œ…yÅÕœÿø2ŋȫ$c.;ÓåôóüÃ`XŒ(åa?kôH­žÐÅVON„‘fÆQú6¨øÞJ$Gàk£hãG6ÓÒÜŽtë½Ôadãh’ÐDG¢Kz4¦€V6B“äRÃëV!ë¢^zŠQ®ø¨=ù˯ë8p±úú~XÿÊ|ÿýWÇ1ë•2Ñ2½¥7ÒÉÈ›ùZkeƒÕï•·°J2dd„^›E5Þ¾Û¯í¥ÿ9¿6µ¢Dè­Ñ¢}]Û‹¦†Ýzó* ¬\ç [§Xƒ†ó¨‰-jYiEGôV•ÑL ÷é)(WŽÖzTÁ²ŽöºÖˆveDÎ)gOqŒ1‘ ¯T6ÏËZÞynᜃo¯Ê{d“®¤Õ‹I¦±¡É¢1# Už‡7'制9 ñ°9B.Ø2AÛÅùFzÊŠ8'I#¡!>ê<óÒŽæ™%ÍÈHé7Ž .k5üV–R4ÖZSkÊdìD©W•­‘5=‰Ð4^k& àª}%r³Ñ6É隢tžseÚLnîgñ®± §¿ê{ 'î#q1 /\Yë²i'Eì™±¢TLQ‘eåIûH0#7ç6›‘©N|ܰó¬ójëG¾Â@sK ú”t¥'£btå\û_±MX¡p#ÑSq% Æ—óÑ*ßYû,8¯YªpZâwqÊ^–æÉ÷`Ëi™u”øµË(u´*ž¡ã–¡•'I´ª©xN çZ?Iš&ŽÔh5Ç “ Ó#„‘#Ö©ë•ý_Ó´®¼¡ß–yG;×2Ïöø\㹿çôø ËÒºÌyXÄn”ï5GÌVÖEÏx¸^íé@3>}úcIôFŒ/f·ËO úgƒx®™=.–;Ÿ¦¨šñoÓRRŽ'ÓEÍÏ÷ö>œ¾Ú9:.:Ü-7³ìˆéÔÏD€õ8ö­oŠÙݧ% 5Þ^ÜÐîÝ=&’·D0ãlng7Û÷wŸ ÆÇ§ËâË9&ÿxÿóônÁlô9¡ùŽ[kJÐ8‚ëp‡ögŸ ,øå‰ /ާ_Šê¾g mB|Fˆ5!û“½ÃÉEt-;„ˆo'D÷bM!š,xO‹mNˆæMBrԃѢMˆÍ q5!ÇoŽw&ïáú쬇9˜!VŒ@\1"QƒÐ+Ç`LƒÙ$¤z#ªÍHxfÎììmÃ÷䲇5¼FìªÁCI‰´8UòŒ£R¥AÿX×*Ýd¦~=3gó÷÷³›ùmþTTÙUø Uyñœì]Ǻä¦ôÆfSè©L™Ø^°ëëräZÕ“ÁV<~hÃ=<=<þõæA%æ{S²…C×/¾äÅåÅ£LIŒÀ´jšÄ4ÐbÆð3–çÆÔÌL®.Þ¼§Â<êcÆn”'{™‘UÉèN6¢ÉLý0fd‹Y“̇Ë˃½ Ÿ^õÐâþ-|E žÍû‘mKµBÿ¾î-ب&# àÃÑkZ0^ÝV.ß¿%×'¾ÃˆßTWq¶o¶U‰8Þ)Óê*5êattÚ,wÙÜáYŸÝ={wõá*V_—‘°Ù©ÓÛT¤®šŠèòÒê¶9øaÄ´»­m,ÕY¡ìžOÎO¶Ób×™<žol©úÙ¥º*a;ÝÖ´ºmý fl»Ûªš]Óòöêðͯû¯ŽN·zh¼ËåÿÖQx»™dSdz-úïQ¡” 5YåDØVsmàF„\ÓJt¶ß?Þß½:‰“Òvˆ›j%¾ïü#« Šª]¶Õ[3ÔÃèÐk·û¶æã·Ó“·Ç»ä9tøPk­º¯µ†ªµ¢É¶ùhµÖ õ0>ìÚýZÆÇÅöîqœƒ8Ht§ŠÞØñ§w KÇZhÆmƒVKm ƈ_[!ÙŒ¹¸üåôø2úî–ˆÙ!½%bKBpú³Á7iµÒ4àýä7¦p endstream endobj 86 0 obj <]/Size 87/W[1 2 2]/Filter/FlateDecode/Length 226>> stream xÚ%Í»2P…á½D !"!HÄ]ÜÅ-.…‚2Z§P)ŒÉh ¥NcÔJ Òƒ¨Tž#ü³šoþµOq"¢Ýîˆ|ôC$¡ “030 PƒeX…uØ„-Ø=E6‚ ½\]°‡J~û&èVúܳz”ûôL@J¥ªg'ôB2ª”ýUíÌ5 úkPæÿç'ÏœN]Cºøråu•r ëºå*èæÒUTëÉ5¢Û_ר’î®1=|¸ÆõøìšÐKÑU*LÃ,ÌÃ",Á ¬ÁÔav¡p¤·÷ˆ?š¡ ^ endstream endobj startxref 43181 %%EOF glpk-4.52.1/examples/pbn/pbn.tex0000644000062000006210000002324512175147600015625 0ustar maomkpasswd%* pbn.tex *% \documentclass[11pt,draft]{article} \usepackage{amssymb} \begin{document} \title{Solving Paint-By-Numbers Puzzles with GLPK} \author{Andrew Makhorin {\tt}} \date{August 2011} \maketitle \section{Introduction$^1$} \footnotetext[1]{This section is based on the material from [1].} A {\it paint-by-numbers} puzzle consists of an $m\times n$ grid of pixels (the {\it canvas}) together with $m+n$ {\it cluster-size sequences}, one for each row and column. The goal is to paint the canvas with a picture that satisfies the following constraints: 1. Each pixel must be blank or white. 2. If a row or column has cluster-size sequence $s_1$, $s_2$, \dots, $s_k$, then it must contain $k$ clusters of black pixels---the first with $s_1$ black pixels, the second with $s_2$ black pixels, and so on. It should be noted that ``first'' means ``leftmost'' for rows and ``topmost'' for columns, and that rows and columns need not begin or end with black pixels. \subsubsection*{Example} \def\arraystretch{.8} \begin{center} \begin{tabular}{*{3}{@{$\;\;$}c}c*{10}{@{\ }c}@{}} & & && & &1& &1& & & & & \\ & & && & &1& &1& & & & & \\ & & &&2&1&1&1&1&1&2&3& & \\ & & &&3&2&1&2&1&2&3&4&8&9\\ \\ &3&6&&$\blacksquare$&$\blacksquare$&$\blacksquare$&$\square$& $\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& $\blacksquare$&$\blacksquare$\\ &1&4&&$\blacksquare$&$\square$&$\square$&$\square$&$\square$& $\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ 1&1&3&&$\square$&$\square$&$\blacksquare$&$\square$&$\blacksquare$& $\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ & &2&&$\square$&$\square$&$\square$&$\square$&$\square$&$\square$& $\square$&$\square$&$\blacksquare$&$\blacksquare$\\ &3&3&&$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$& $\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ &1&4&&$\blacksquare$&$\square$&$\square$&$\square$&$\square$&$\square$& $\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$\\ &2&5&&$\blacksquare$&$\blacksquare$&$\square$&$\square$&$\square$& $\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& $\blacksquare$\\ &2&5&&$\blacksquare$&$\blacksquare$&$\square$&$\square$&$\square$& $\blacksquare$&$\blacksquare$&$\blacksquare$&$\blacksquare$& $\blacksquare$\\ &1&1&&$\square$&$\square$&$\square$&$\blacksquare$&$\square$&$\square$& $\square$&$\square$&$\square$&$\blacksquare$\\ & &3&&$\square$&$\square$&$\blacksquare$&$\blacksquare$&$\blacksquare$& $\square$&$\square$&$\square$&$\square$&$\square$\\ \end{tabular} \end{center} \def\arraystretch{1} \section{Solving a puzzle} The Paint-By-Numbers puzzle can be formulated as a 0-1 integer feasibility problem. The formulation used in GLPK was proposed in [1]. For solving puzzles there are used two components, which both are coded in the GNU MathProg modeling language [2]: the model section and the data section. The model section is common for all puzzles and placed in file \verb|pbn.mod|. This file is included in the GLPK distribution and can be found in subdirectory \verb|examples/pbn|. To solve a particular puzzle the user only needs to prepare the data section, which defines input data to the puzzle. The data section for the example puzzle from the previous section may look like follows (here \verb|m| is the number of rows, and \verb|n| is the number of columns): \begin{footnotesize} \begin{verbatim} data; param m := 10; param n := 10; param row : 1 2 3 := 1 3 6 . 2 1 4 . 3 1 1 3 4 2 . . 5 3 3 . 6 1 4 . 7 2 5 . 8 2 5 . 9 1 1 . 10 3 . . ; param col : 1 2 3 4 := 1 2 3 . . 2 1 2 . . 3 1 1 1 1 4 1 2 . . 5 1 1 1 1 6 1 2 . . 7 2 3 . . 8 3 4 . . 9 8 . . . 10 9 . . . ; end; \end{verbatim} \end{footnotesize} \newpage Let the data section for a puzzle be placed in file \verb|foo.dat|. Then to solve the puzzle the user should enter the following command: \begin{verbatim} glpsol --minisat -m pbn.mod -d foo.dat \end{verbatim} \noindent This command invokes \verb|glpsol|, the GLPK LP/MIP stand-alone solver, which reads the model section from file \verb|pbn.mod|, the data section from file \verb|foo.dat|, translates them to an internal representation, and solves the resulting 0-1 integer feasibility problem. The option \verb|--minisat| tells \verb|glpsol| to translate the feasibility problem to a CNF satisfiability problem and then use the MiniSat solver [3] to solve it. If a solution to the puzzle has been found, that is indicated by the message \verb|SATISFIABLE|, \verb|glpsol| prints the solution to the standard output (terminal), writes it to file \verb|solution.ps| in the PostScript format, and also writes it to file \verb|solution.dat| in the form of MathProg data section, which can be used later to check for multiple solutions, if necessary (for details see the next section). The message \verb|UNSATISFIABLE| means that the puzzle has no solution. Usually the time taken to solve a puzzle of moderate size (up to 50 rows and columns) varies from several seconds to several minutes. However, hard or large puzzles may require much more time. Data sections for some example puzzles included in the GLPK distribution can be found in subdirectory \verb|examples/pbn|. \section{Checking for multiple solutions} Sometimes the user may be interested to know if the puzzle has exactly one (unique) solution or it has multiple solutions. To check that the user should solve the puzzle as explained above in the previous section and then enter the following command: \begin{verbatim} glpsol --minisat -m pbn.mod -d foo.dat -d solution.dat \end{verbatim} \noindent In this case \verb|glpsol| reads an additional data section from file \verb|solution.dat|, which contains the previously found solution, activates an additional constraint in the model section to forbid finding the solution specified in the additional data section, and attempts to find another solution. The message \verb|UNSATISFIABLE| reported by \verb|glpsol| will mean that the puzzle has a unique solution, while the message \verb|SATISFIABLE| will mean that the puzzle has at least two different solutions. \newpage \section{Solution times} The table on the next page shows solution times on a sample set of the paint-by-numbers puzzles from the \verb|| website. This sample set was used in the survey [4] to compare efficiency of existing PBN solvers. The authors of some puzzles from the sample set have given permission for their puzzles to be freely redistributed as long as the original attribution and copyright statement are retained. In the table these puzzles are marked by an asterisk (*). The files containing the MathProg data sections for these puzzles are included in the GLPK distribution and can be found in subdirectory \verb|examples/pbn|. All runs were performed on Intel Pentium 4 (CPU 3GHz, 2GB of RAM). The C compiler used was GCC 3.4.4 with default optimization options. The column `Sol.Time' shows the time, in seconds, taken by the \verb|glpsol| solver to find a solution to corresponding puzzle. The column `Chk.Time' shows the time, in seconds, taken by \verb|glpsol| to check for multiple solutions, i.e. either to prove that the puzzle has a unique solution or find another solution to the puzzle. Both these times do not include the time used to translate the MathProg model and data sections into an internal MIP representation, but include the time used to translate the 0-1 feasibility problem to a CNF satisfiability problem. \begin{thebibliography}{10} \bibitem{1} Robert A. Bosch, ``Painting by Numbers'', 2000.\\ \verb||. \bibitem{2} GLPK: Modeling Language GNU MathProg. Language Reference. (This document is included in the GLPK distribution and can be found in subdirectory \verb|doc|.) \bibitem{3} Niklas E\'en, Niklas S\"orensson, ``An Extensible SAT-solver'', Chalmers University of Technology, Sweden. \verb||. \bibitem{4} Jan Wolter, ``Survey of Paint-by-Number Puzzle Solvers''.\\ \verb||. \end{thebibliography} \newpage \begin{table} \caption{Solution times on the sample set of puzzles from [4]} \begin{center} \begin{tabular}{@{}lllcrr@{}} \hline \multicolumn{2}{c}{Puzzle}&Size&Notes&Sol.Time, s&Chk.Time, s\\ \hline \#1&Dancer* &$10\times 5$&L&$<1$&$<1$\\ \#6&Cat* &$20\times 20$&L&$<1$&$<1$\\ \#21&Skid* &$25\times 14$&L, B&$<1$&$<1$\\ \#27&Bucks* &$23\times 27$&B&$<1$&$<1$\\ \#23&Edge* &$11\times 10$&&$<1$&$<1$\\ \#2413&Smoke &$20\times 20$&&$<1$&$<1$\\ \#16&Knot* &$34\times 34$&L&1&1\\ \#529&Swing* &$45\times 45$&L&1&1\\ \#65&Mum* &$40\times 34$&&1&1\\ \#7604&DiCap &$55\times 55$&&10&10\\ \#1694&Tragic &$50\times 45$&&3&3\\ \#1611&Merka &$60\times 55$&B&4&4\\ \#436&Petro* &$35\times 40$&&1&1\\ \#4645&M\&M &$70\times 50$&B&5&6\\ \#3541&Signed &$50\times 60$&&7&7\\ \#803&Light* &$45\times 50$&B&1&1\\ \#6574&Forever*&$25\times 25$&&1&1\\ \#2040&Hot &$60\times 55$&&6&6\\ \#6739&Karate &$40\times 40$&M&2&2\\ \#8098&9-Dom* &$19\times 19$&&1&2\\ \#2556&Flag &$45\times 65$&M, B&2&2\\ \#2712&Lion &$47\times 47$&M&11&12\\ \#10088&Marley &$63\times 52$&M&135&226\\ \#9892&Nature &$40\times 50$&M&850&1053\\ \hline \end{tabular} \begin{tabular}{@{}lp{102mm}@{}} *&Puzzle designer has given permission to redistribute the puzzle.\\ L&Puzzle is line solvable. That is, it can be solved one line at a time.\\ B&Puzzle contains blank rows or columns.\\ M&Puzzle has multiple solutions.\\ \end{tabular} \end{center} \end{table} \end{document} glpk-4.52.1/examples/pbn/petro.dat0000644000062000006210000000610712175147600016145 0ustar maomkpasswd/* petro.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #436 from . * Copyright (C) 2006 by Jan Wolter. Used by permission. * * Old Stone Face * * created by Jan Wolter * Jun 17, 2006 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 35; param n := 40; param row : 1 2 3 4 5 6 7 8 9 := 1 2 2 . . . . . . . 2 2 3 2 . . . . . . 3 3 3 3 2 . . . . . 4 3 3 3 3 . . . . . 5 2 3 3 3 3 2 . . . 6 3 3 3 3 3 3 . . . 7 4 2 3 2 2 4 . . . 8 4 2 2 2 2 3 1 . . 9 3 1 2 2 2 3 3 . . 10 3 2 2 2 2 2 4 . . 11 3 2 15 2 4 . . . . 12 5 19 4 . . . . . . 13 6 4 3 3 . . . . . 14 6 4 4 . . . . . . 15 2 4 6 2 . . . . . 16 2 2 3 3 3 2 . . . 17 9 2 2 2 3 9 . . . 18 10 2 2 2 2 2 10 . . 19 4 2 3 3 2 2 3 2 5 20 2 5 2 4 2 . . . . 21 5 3 2 2 5 . . . . 22 6 3 2 3 7 . . . . 23 6 8 9 7 . . . . . 24 4 8 7 5 . . . . . 25 4 . . . . . . . . 26 2 . . . . . . . . 27 2 . . . . . . . . 28 14 . . . . . . . . 29 16 . . . . . . . . 30 3 3 . . . . . . . 31 2 2 . . . . . . . 32 2 2 . . . . . . . 33 4 4 . . . . . . . 34 16 . . . . . . . . 35 12 . . . . . . . . ; param col : 1 2 3 4 5 6 7 := 1 1 . . . . . . 2 3 2 . . . . . 3 2 3 3 . . . . 4 3 3 3 . . . . 5 3 3 3 3 . . . 6 4 2 2 2 . . . 7 3 3 2 3 . . . 8 3 2 2 2 . . . 9 3 2 6 . . . . 10 2 9 . . . . . 11 2 3 3 . . . . 12 4 4 3 2 4 . . 13 7 2 5 2 6 . . 14 12 2 3 2 3 2 . 15 3 1 2 2 2 3 . 16 2 2 3 2 2 2 . 17 6 2 6 2 2 2 . 18 12 4 3 2 2 . . 19 12 2 2 2 . . . 20 2 6 2 . . . . 21 2 6 5 2 . . . 22 10 9 2 2 . . . 23 12 3 3 2 2 . . 24 6 2 2 2 2 2 2 25 2 2 3 2 2 2 . 26 4 3 2 2 2 3 . 27 7 3 3 2 3 2 . 28 5 3 5 2 6 . . 29 4 3 3 3 4 . . 30 3 5 3 . . . . 31 3 9 . . . . . 32 4 2 6 . . . . 33 4 2 2 2 . . . 34 4 2 2 3 . . . 35 3 2 2 3 . . . 36 3 3 3 . . . . 37 3 3 3 . . . . 38 4 3 3 . . . . 39 2 3 3 . . . . 40 2 1 . . . . . ; end; glpk-4.52.1/examples/pbn/README0000644000062000006210000000044012175147600015174 0ustar maomkpasswdThis subdirectory contains examples, which illustrate how to use GLPK and the GNU MathProg modeling language for practical solving the paint-by-numbers puzzle. For details please see the document "Solving Paint-By-Numbers Puzzles with GLPK" included in this subdirectory (file pbn.pdf). glpk-4.52.1/examples/pbn/skid.dat0000644000062000006210000000253712175147600015751 0ustar maomkpasswd/* skid.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #21 from . * Copyright (C) 2004 by Jan Wolter. Used by permission. * * Slippery Conditions * * created by Jan Wolter * Apr 4, 2004 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 25; param n := 14; param row : 1 2 3 := 1 9 . . 2 1 1 . 3 1 1 1 4 1 3 1 5 13 . . 6 13 . . 7 13 . . 8 13 . . 9 2 2 . 10 2 2 . 11 . . . 12 2 2 . 13 2 2 . 14 2 2 . 15 2 2 . 16 2 2 . 17 2 2 . 18 2 2 . 19 2 2 . 20 2 2 . 21 2 2 . 22 2 2 . 23 2 2 . 24 2 2 . 25 2 2 . ; param col : 1 2 3 4 5 := 1 2 . . . . 2 4 6 . . . 3 9 4 4 2 . 4 1 6 2 6 . 5 1 5 2 . . 6 1 6 . . . 7 1 5 . . . 8 1 4 . . . 9 1 4 . . . 10 1 4 2 . . 11 1 4 6 . . 12 1 6 4 4 2 13 9 2 6 . . 14 4 2 . . . ; end; glpk-4.52.1/examples/pbn/swing.dat0000644000062000006210000001232212175147600016137 0ustar maomkpasswd/* swing.dat */ /*********************************************************************** * Web Paint-by-Number Puzzle #529 from . * Copyright (C) 2006 by Jan Wolter. Used by permission. * * Swing * * created by Jan Wolter * Sep 28, 2006 * * Encoded in GNU MathProg by Andrew Makhorin . ***********************************************************************/ data; param m := 45; param n := 45; param row : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 := 1 7 1 1 1 1 1 . . . . . . . . 2 3 1 3 1 4 1 4 1 5 1 5 1 2 . 3 1 1 1 3 1 4 1 4 1 5 1 5 1 2 4 2 1 2 1 1 1 1 6 2 . . . . . 5 3 30 1 5 . . . . . . . . . . 6 1 5 8 1 1 7 1 1 3 . . . . . 7 3 4 8 1 5 1 2 . . . . . . . 8 3 20 6 6 . . . . . . . . . . 9 3 3 7 2 5 1 . . . . . . . . 10 3 3 1 1 9 1 1 5 6 . . . . . 11 2 3 8 1 3 4 2 . . . . . . . 12 5 3 1 10 4 5 2 . . . . . . . 13 1 2 3 8 4 6 . . . . . . . . 14 2 2 3 11 10 . . . . . . . . . 15 2 2 3 10 7 . . . . . . . . . 16 2 3 1 7 12 2 . . . . . . . . 17 2 3 1 4 11 2 . . . . . . . . 18 4 1 2 1 11 2 . . . . . . . . 19 9 1 2 9 . . . . . . . . . . 20 6 2 1 4 11 . . . . . . . . . 21 2 5 1 2 6 6 . . . . . . . . 22 6 2 4 8 4 . . . . . . . . . 23 4 2 16 1 . . . . . . . . . . 24 2 2 15 2 . . . . . . . . . . 25 3 2 15 4 . . . . . . . . . . 26 3 3 13 4 . . . . . . . . . . 27 4 12 9 . . . . . . . . . . . 28 1 9 10 . . . . . . . . . . . 29 2 1 17 7 2 . . . . . . . . . 30 2 2 8 3 8 2 . . . . . . . . 31 2 3 6 3 8 2 . . . . . . . . 32 2 4 5 4 7 2 . . . . . . . . 33 2 5 5 4 6 . . . . . . . . . 34 4 4 5 4 9 . . . . . . . . . 35 1 4 6 4 4 . . . . . . . . . 36 4 3 6 4 3 2 . . . . . . . . 37 2 1 2 7 4 4 2 . . . . . . . 38 2 2 2 9 5 5 2 . . . . . . . 39 2 2 2 10 6 6 . . . . . . . . 40 3 2 1 9 18 . . . . . . . . . 41 8 4 23 . . . . . . . . . . . 42 1 2 1 2 2 1 1 1 2 . . . . . 43 2 1 4 2 1 4 1 5 1 3 1 2 . . 44 2 1 5 4 4 1 5 1 3 1 2 . . . 45 1 10 1 1 1 . . . . . . . . . ; param col : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 := 1 7 1 1 1 1 1 . . . . . . . . 2 2 2 4 1 4 1 5 1 4 1 4 1 2 . 3 3 1 4 1 4 1 14 4 1 2 . . . . 4 1 1 5 1 2 3 4 1 . . . . . . 5 3 13 1 10 . . . . . . . . . . 6 1 9 4 . . . . . . . . . . . 7 6 7 2 2 . . . . . . . . . . 8 8 4 1 4 . . . . . . . . . . 9 2 8 3 2 5 3 . . . . . . . . 10 10 1 3 7 2 . . . . . . . . . 11 8 6 2 8 1 2 . . . . . . . . 12 1 1 2 2 8 1 1 . . . . . . . 13 2 1 1 1 2 1 3 1 3 3 1 . . . 14 2 1 1 1 5 4 2 1 . . . . . . 15 2 1 1 1 1 7 2 1 . . . . . . 16 2 1 1 2 9 1 2 1 . . . . . . 17 4 6 12 1 3 . . . . . . . . . 18 16 13 3 2 . . . . . . . . . . 19 12 21 2 . . . . . . . . . . . 20 2 13 23 . . . . . . . . . . . 21 2 14 19 . . . . . . . . . . . 22 2 14 20 2 . . . . . . . . . . 23 2 13 7 2 8 2 . . . . . . . . 24 12 8 1 7 2 . . . . . . . . . 25 5 1 1 1 2 8 1 5 2 . . . . . 26 2 1 1 1 9 1 1 4 . . . . . . 27 2 1 1 1 6 1 3 5 . . . . . . 28 2 2 1 5 6 2 . . . . . . . . 29 2 1 3 1 3 7 3 2 . . . . . . 30 2 3 2 1 1 2 4 4 2 . . . . . 31 2 2 1 1 2 3 1 8 2 . . . . . 32 9 3 1 7 2 . . . . . . . . . 33 12 4 1 6 2 . . . . . . . . . 34 7 4 1 2 5 . . . . . . . . . 35 2 6 6 5 6 . . . . . . . . . 36 8 8 6 3 . . . . . . . . . . 37 3 10 8 4 2 . . . . . . . . . 38 5 11 9 5 2 . . . . . . . . . 39 3 1 12 16 2 . . . . . . . . . 40 3 1 12 16 . . . . . . . . . . 41 5 2 13 21 . . . . . . . . . . 42 6 1 3 3 1 1 . . . . . . . . 43 5 1 3 1 3 1 1 2 1 4 1 3 1 3 44 5 1 3 1 3 1 4 1 4 1 3 1 3 . 45 1 1 1 1 1 1 . . . . . . . . ; end; glpk-4.52.1/examples/plan.lp0000644000062000006210000000234612175147600015033 0ustar maomkpasswd\* plan.lp *\ Minimize value: .03 bin1 + .08 bin2 + .17 bin3 + .12 bin4 + .15 bin5 + .21 alum + .38 silicon Subject To yield: bin1 + bin2 + bin3 + bin4 + bin5 + alum + silicon = 2000 fe: .15 bin1 + .04 bin2 + .02 bin3 + .04 bin4 + .02 bin5 + .01 alum + .03 silicon <= 60 cu: .03 bin1 + .05 bin2 + .08 bin3 + .02 bin4 + .06 bin5 + .01 alum <= 100 mn: .02 bin1 + .04 bin2 + .01 bin3 + .02 bin4 + .02 bin5 <= 40 mg: .02 bin1 + .03 bin2 + .01 bin5 <= 30 al: .70 bin1 + .75 bin2 + .80 bin3 + .75 bin4 + .80 bin5 + .97 alum >= 1500 si1: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + .01 alum + .97 silicon >= 250 si2: .02 bin1 + .06 bin2 + .08 bin3 + .12 bin4 + .02 bin5 + .01 alum + .97 silicon <= 300 Bounds bin1 <= 200 bin2 <= 2500 400 <= bin3 <= 800 100 <= bin4 <= 700 bin5 <= 1500 End \* eof *\ glpk-4.52.1/examples/plan.mod0000644000062000006210000000164112175147600015174 0ustar maomkpasswd/* plan.mod */ var bin1, >= 0, <= 200; var bin2, >= 0, <= 2500; var bin3, >= 400, <= 800; var bin4, >= 100, <= 700; var bin5, >= 0, <= 1500; var alum, >= 0; var silicon, >= 0; minimize value: .03 * bin1 + .08 * bin2 + .17 * bin3 + .12 * bin4 + .15 * bin5 + .21 * alum + .38 * silicon; subject to yield: bin1 + bin2 + bin3 + bin4 + bin5 + alum + silicon = 2000; fe: .15 * bin1 + .04 * bin2 + .02 * bin3 + .04 * bin4 + .02 * bin5 + .01 * alum + .03 * silicon <= 60; cu: .03 * bin1 + .05 * bin2 + .08 * bin3 + .02 * bin4 + .06 * bin5 + .01 * alum <= 100; mn: .02 * bin1 + .04 * bin2 + .01 * bin3 + .02 * bin4 + .02 * bin5 <= 40; mg: .02 * bin1 + .03 * bin2 + .01 * bin5 <= 30; al: .70 * bin1 + .75 * bin2 + .80 * bin3 + .75 * bin4 + .80 * bin5 + .97 * alum >= 1500; si: 250 <= .02 * bin1 + .06 * bin2 + .08 * bin3 + .12 * bin4 + .02 * bin5 + .01 * alum + .97 * silicon <= 300; end; /* eof */ glpk-4.52.1/examples/plan.mps0000644000062000006210000000432612175147600015217 0ustar maomkpasswd*000000001111111111222222222233333333334444444444555555555566 *234567890123456789012345678901234567890123456789012345678901 NAME PLAN ROWS N VALUE E YIELD L FE L CU L MN L MG G AL L SI COLUMNS BIN1 VALUE .03000 YIELD 1.00000 FE .15000 CU .03000 MN .02000 MG .02000 AL .70000 SI .02000 BIN2 VALUE .08000 YIELD 1.00000 FE .04000 CU .05000 MN .04000 MG .03000 AL .75000 SI .06000 BIN3 VALUE .17000 YIELD 1.00000 FE .02000 CU .08000 MN .01000 AL .80000 SI .08000 BIN4 VALUE .12000 YIELD 1.00000 FE .04000 CU .02000 MN .02000 AL .75000 SI .12000 BIN5 VALUE .15000 YIELD 1.00000 FE .02000 CU .06000 MN .02000 MG .01000 AL .80000 SI .02000 ALUM VALUE .21000 YIELD 1.00000 FE .01000 CU .01000 AL .97000 SI .01000 SILICON VALUE .38000 YIELD 1.00000 FE .03000 SI .97000 RHS RHS1 YIELD 2000.00000 FE 60.00000 CU 100.00000 MN 40.00000 SI 300.00000 MG 30.00000 AL 1500.00000 RANGES RNG1 SI 50.00000 BOUNDS UP BND1 BIN1 200.00000 UP BIN2 2500.00000 LO BIN3 400.00000 UP BIN3 800.00000 LO BIN4 100.00000 UP BIN4 700.00000 UP BIN5 1500.00000 ENDATA glpk-4.52.1/examples/prod.mod0000644000062000006210000002466712175147600015223 0ustar maomkpasswd# PROD, a multiperiod production model # # References: # Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language # for Mathematical Programming." Management Science 36 (1990) 519-554. ### PRODUCTION SETS AND PARAMETERS ### set prd 'products'; # Members of the product group param pt 'production time' {prd} > 0; # Crew-hours to produce 1000 units param pc 'production cost' {prd} > 0; # Nominal production cost per 1000, used # to compute inventory and shortage costs ### TIME PERIOD SETS AND PARAMETERS ### param first > 0 integer; # Index of first production period to be modeled param last > first integer; # Index of last production period to be modeled set time 'planning horizon' := first..last; ### EMPLOYMENT PARAMETERS ### param cs 'crew size' > 0 integer; # Workers per crew param sl 'shift length' > 0; # Regular-time hours per shift param rtr 'regular time rate' > 0; # Wage per hour for regular-time labor param otr 'overtime rate' > rtr; # Wage per hour for overtime labor param iw 'initial workforce' >= 0 integer; # Crews employed at start of first period param dpp 'days per period' {time} > 0; # Regular working days in a production period param ol 'overtime limit' {time} >= 0; # Maximum crew-hours of overtime in a period param cmin 'crew minimum' {time} >= 0; # Lower limit on average employment in a period param cmax 'crew maximum' {t in time} >= cmin[t]; # Upper limit on average employment in a period param hc 'hiring cost' {time} >= 0; # Penalty cost of hiring a crew param lc 'layoff cost' {time} >= 0; # Penalty cost of laying off a crew ### DEMAND PARAMETERS ### param dem 'demand' {prd,first..last+1} >= 0; # Requirements (in 1000s) # to be met from current production and inventory param pro 'promoted' {prd,first..last+1} logical; # true if product will be the subject # of a special promotion in the period ### INVENTORY AND SHORTAGE PARAMETERS ### param rir 'regular inventory ratio' >= 0; # Proportion of non-promoted demand # that must be in inventory the previous period param pir 'promotional inventory ratio' >= 0; # Proportion of promoted demand # that must be in inventory the previous period param life 'inventory lifetime' > 0 integer; # Upper limit on number of periods that # any product may sit in inventory param cri 'inventory cost ratio' {prd} > 0; # Inventory cost per 1000 units is # cri times nominal production cost param crs 'shortage cost ratio' {prd} > 0; # Shortage cost per 1000 units is # crs times nominal production cost param iinv 'initial inventory' {prd} >= 0; # Inventory at start of first period; age unknown param iil 'initial inventory left' {p in prd, t in time} := iinv[p] less sum {v in first..t} dem[p,v]; # Initial inventory still available for allocation # at end of period t param minv 'minimum inventory' {p in prd, t in time} := dem[p,t+1] * (if pro[p,t+1] then pir else rir); # Lower limit on inventory at end of period t ### VARIABLES ### var Crews{first-1..last} >= 0; # Average number of crews employed in each period var Hire{time} >= 0; # Crews hired from previous to current period var Layoff{time} >= 0; # Crews laid off from previous to current period var Rprd 'regular production' {prd,time} >= 0; # Production using regular-time labor, in 1000s var Oprd 'overtime production' {prd,time} >= 0; # Production using overtime labor, in 1000s var Inv 'inventory' {prd,time,1..life} >= 0; # Inv[p,t,a] is the amount of product p that is # a periods old -- produced in period (t+1)-a -- # and still in storage at the end of period t var Short 'shortage' {prd,time} >= 0; # Accumulated unsatisfied demand at the end of period t ### OBJECTIVE ### minimize cost: sum {t in time} rtr * sl * dpp[t] * cs * Crews[t] + sum {t in time} hc[t] * Hire[t] + sum {t in time} lc[t] * Layoff[t] + sum {t in time, p in prd} otr * cs * pt[p] * Oprd[p,t] + sum {t in time, p in prd, a in 1..life} cri[p] * pc[p] * Inv[p,t,a] + sum {t in time, p in prd} crs[p] * pc[p] * Short[p,t]; # Full regular wages for all crews employed, plus # penalties for hiring and layoffs, plus # wages for any overtime worked, plus # inventory and shortage costs # (All other production costs are assumed # to depend on initial inventory and on demands, # and so are not included explicitly.) ### CONSTRAINTS ### rlim 'regular-time limit' {t in time}: sum {p in prd} pt[p] * Rprd[p,t] <= sl * dpp[t] * Crews[t]; # Hours needed to accomplish all regular-time # production in a period must not exceed # hours available on all shifts olim 'overtime limit' {t in time}: sum {p in prd} pt[p] * Oprd[p,t] <= ol[t]; # Hours needed to accomplish all overtime # production in a period must not exceed # the specified overtime limit empl0 'initial crew level': Crews[first-1] = iw; # Use given initial workforce empl 'crew levels' {t in time}: Crews[t] = Crews[t-1] + Hire[t] - Layoff[t]; # Workforce changes by hiring or layoffs emplbnd 'crew limits' {t in time}: cmin[t] <= Crews[t] <= cmax[t]; # Workforce must remain within specified bounds dreq1 'first demand requirement' {p in prd}: Rprd[p,first] + Oprd[p,first] + Short[p,first] - Inv[p,first,1] = dem[p,first] less iinv[p]; dreq 'demand requirements' {p in prd, t in first+1..last}: Rprd[p,t] + Oprd[p,t] + Short[p,t] - Short[p,t-1] + sum {a in 1..life} (Inv[p,t-1,a] - Inv[p,t,a]) = dem[p,t] less iil[p,t-1]; # Production plus increase in shortage plus # decrease in inventory must equal demand ireq 'inventory requirements' {p in prd, t in time}: sum {a in 1..life} Inv[p,t,a] + iil[p,t] >= minv[p,t]; # Inventory in storage at end of period t # must meet specified minimum izero 'impossible inventories' {p in prd, v in 1..life-1, a in v+1..life}: Inv[p,first+v-1,a] = 0; # In the vth period (starting from first) # no inventory may be more than v periods old # (initial inventories are handled separately) ilim1 'new-inventory limits' {p in prd, t in time}: Inv[p,t,1] <= Rprd[p,t] + Oprd[p,t]; # New inventory cannot exceed # production in the most recent period ilim 'inventory limits' {p in prd, t in first+1..last, a in 2..life}: Inv[p,t,a] <= Inv[p,t-1,a-1]; # Inventory left from period (t+1)-p # can only decrease as time goes on ### DATA ### data; set prd := 18REG 24REG 24PRO ; param first := 1 ; param last := 13 ; param life := 2 ; param cs := 18 ; param sl := 8 ; param iw := 8 ; param rtr := 16.00 ; param otr := 43.85 ; param rir := 0.75 ; param pir := 0.80 ; param : pt pc cri crs iinv := 18REG 1.194 2304. 0.015 1.100 82.0 24REG 1.509 2920. 0.015 1.100 792.2 24PRO 1.509 2910. 0.015 1.100 0.0 ; param : dpp ol cmin cmax hc lc := 1 19.5 96.0 0.0 8.0 7500 7500 2 19.0 96.0 0.0 8.0 7500 7500 3 20.0 96.0 0.0 8.0 7500 7500 4 19.0 96.0 0.0 8.0 7500 7500 5 19.5 96.0 0.0 8.0 15000 15000 6 19.0 96.0 0.0 8.0 15000 15000 7 19.0 96.0 0.0 8.0 15000 15000 8 20.0 96.0 0.0 8.0 15000 15000 9 19.0 96.0 0.0 8.0 15000 15000 10 20.0 96.0 0.0 8.0 15000 15000 11 20.0 96.0 0.0 8.0 7500 7500 12 18.0 96.0 0.0 8.0 7500 7500 13 18.0 96.0 0.0 8.0 7500 7500 ; param dem (tr) : 18REG 24REG 24PRO := 1 63.8 1212.0 0.0 2 76.0 306.2 0.0 3 88.4 319.0 0.0 4 913.8 208.4 0.0 5 115.0 298.0 0.0 6 133.8 328.2 0.0 7 79.6 959.6 0.0 8 111.0 257.6 0.0 9 121.6 335.6 0.0 10 470.0 118.0 1102.0 11 78.4 284.8 0.0 12 99.4 970.0 0.0 13 140.4 343.8 0.0 14 63.8 1212.0 0.0 ; param pro (tr) : 18REG 24REG 24PRO := 1 0 1 0 2 0 0 0 3 0 0 0 4 1 0 0 5 0 0 0 6 0 0 0 7 0 1 0 8 0 0 0 9 0 0 0 10 1 0 1 11 0 0 0 12 0 0 0 13 0 1 0 14 0 1 0 ; end; glpk-4.52.1/examples/qfit.mod0000644000062000006210000000226012175147600015203 0ustar maomkpasswd/*Quadratic Curve Fitting Solution Find a plausable quadratic fit to a sample of points Nigel_Galloway@operamail.com February 1st., 2009 */ set Sample; param Sx {z in Sample}; param Sy {z in Sample}; var a; var b; var c; equalz1 :sum{z in Sample} a*Sx[z]*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} c*Sx[z]*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]*Sx[z]; equalz2 :sum{z in Sample} a*Sx[z]*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z]*Sx[z] + sum{z in Sample} c*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; equalz3 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] + sum{z in Sample} c = sum{z in Sample} Sy[z]; solve; printf "\nbest quadratic fit is:\n\ty = %f %s %fx %s %fx^2\n\n", c, if b < 0 then "-" else "+", abs(b), if a < 0 then "-" else "+", abs(a); data; param: Sample: Sx Sy := 1 0 1 2 0.5 0.9 3 1 0.7 4 1.5 1.5 5 1.9 2 6 2.5 2.4 7 3 3.2 8 3.5 2 9 4 2.7 10 4.5 3.5 11 5 1 12 5.5 4 13 6 3.6 14 6.6 2.7 15 7 5.7 16 7.6 4.6 17 8.5 6 18 9 6.8 19 10 7.3 ; end; glpk-4.52.1/examples/queens.mod0000644000062000006210000000246012175147600015542 0ustar maomkpasswd/* QUEENS, a classic combinatorial optimization problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Queens Problem is to place as many queens as possible on the 8x8 (or more generally, nxn) chess board in a way that they do not fight each other. This problem is probably as old as the chess game itself, and thus its origin is not known, but it is known that Gauss studied this problem. */ param n, integer, > 0, default 8; /* size of the chess board */ var x{1..n, 1..n}, binary; /* x[i,j] = 1 means that a queen is placed in square [i,j] */ s.t. a{i in 1..n}: sum{j in 1..n} x[i,j] <= 1; /* at most one queen can be placed in each row */ s.t. b{j in 1..n}: sum{i in 1..n} x[i,j] <= 1; /* at most one queen can be placed in each column */ s.t. c{k in 2-n..n-2}: sum{i in 1..n, j in 1..n: i-j == k} x[i,j] <= 1; /* at most one queen can be placed in each "\"-diagonal */ s.t. d{k in 3..n+n-1}: sum{i in 1..n, j in 1..n: i+j == k} x[i,j] <= 1; /* at most one queen can be placed in each "/"-diagonal */ maximize obj: sum{i in 1..n, j in 1..n} x[i,j]; /* objective is to place as many queens as possible */ /* solve the problem */ solve; /* and print its optimal solution */ for {i in 1..n} { for {j in 1..n} printf " %s", if x[i,j] then "Q" else "."; printf("\n"); } end; glpk-4.52.1/examples/samp1.mps0000644000062000006210000000171012175147600015300 0ustar maomkpasswdNAME SAMP1 ROWS N Z G R1 G R2 G R3 COLUMNS X1 R1 2.0 R2 1.0 X1 R3 5.0 Z 3.0 MARK0001 'MARKER' 'INTORG' X2 R1 -1.0 R2 -1.0 X2 R3 3.0 Z 7.0 X3 R1 1.0 R2 -6.0 X3 Z -1.0 MARK0002 'MARKER' 'INTEND' X4 R1 -1.0 R2 4.0 X4 R3 1.0 Z 1.0 RHS RHS1 R1 1.0 RHS1 R2 8.0 RHS1 R3 5.0 BOUNDS UP BND1 X1 4.0 LO BND1 X2 2.0 UP BND1 X2 5.0 UP BND1 X3 1.0 LO BND1 X4 3.0 UP BND1 X4 8.0 ENDATA glpk-4.52.1/examples/samp2.mps0000644000062000006210000000152512175147600015305 0ustar maomkpasswdNAME SAMP2 ROWS N Z G R1 G R2 G R3 COLUMNS X1 R1 2.0 R2 1.0 X1 R3 5.0 Z 3.0 X2 R1 -1.0 R2 -1.0 X2 R3 3.0 Z 7.0 X3 R1 1.0 R2 -6.0 X3 Z -1.0 X4 R1 -1.0 R2 4.0 X4 R3 1.0 Z 1.0 RHS RHS1 R1 1.0 RHS1 R2 8.0 RHS1 R3 5.0 BOUNDS UP BND1 X1 4.0 LO BND1 X2 2.0 UI BND1 X2 5.0 BV BND1 X3 LO BND1 X4 3.0 UP BND1 X4 8.0 ENDATA glpk-4.52.1/examples/sample.asn0000644000062000006210000000055512175147600015530 0ustar maomkpasswdc sample.asn c c This is an example of the assignment problem data c in DIMACS format. c p asn 17 22 c n 1 n 2 n 3 n 4 n 5 n 6 n 7 n 8 c a 1 9 13 a 1 10 21 a 1 12 20 a 2 10 12 a 2 12 8 a 2 13 26 a 3 11 22 a 3 13 11 a 4 9 12 a 4 12 36 a 4 14 25 a 5 11 41 a 5 12 40 a 5 13 11 a 5 14 4 a 5 15 8 a 5 16 35 a 5 17 32 a 6 9 13 a 7 10 19 a 8 10 39 a 8 11 15 c c eof glpk-4.52.1/examples/sample.c0000644000062000006210000000347712175147600015177 0ustar maomkpasswd/* sample.c */ #include #include #include int main(void) { glp_prob *lp; int ia[1+1000], ja[1+1000]; double ar[1+1000], z, x1, x2, x3; s1: lp = glp_create_prob(); s2: glp_set_prob_name(lp, "sample"); s3: glp_set_obj_dir(lp, GLP_MAX); s4: glp_add_rows(lp, 3); s5: glp_set_row_name(lp, 1, "p"); s6: glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 100.0); s7: glp_set_row_name(lp, 2, "q"); s8: glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 600.0); s9: glp_set_row_name(lp, 3, "r"); s10: glp_set_row_bnds(lp, 3, GLP_UP, 0.0, 300.0); s11: glp_add_cols(lp, 3); s12: glp_set_col_name(lp, 1, "x1"); s13: glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0); s14: glp_set_obj_coef(lp, 1, 10.0); s15: glp_set_col_name(lp, 2, "x2"); s16: glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0); s17: glp_set_obj_coef(lp, 2, 6.0); s18: glp_set_col_name(lp, 3, "x3"); s19: glp_set_col_bnds(lp, 3, GLP_LO, 0.0, 0.0); s20: glp_set_obj_coef(lp, 3, 4.0); s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ s30: glp_load_matrix(lp, 9, ia, ja, ar); s31: glp_simplex(lp, NULL); s32: z = glp_get_obj_val(lp); s33: x1 = glp_get_col_prim(lp, 1); s34: x2 = glp_get_col_prim(lp, 2); s35: x3 = glp_get_col_prim(lp, 3); s36: printf("\nz = %g; x1 = %g; x2 = %g; x3 = %g\n", z, x1, x2, x3); s37: glp_delete_prob(lp); return 0; } /* eof */ glpk-4.52.1/examples/sample.clq0000644000062000006210000000040712175147600015522 0ustar maomkpasswdc sample.clq c c This is an example of the Maximum Weight Clique c Problem in DIMACS clique/coloring format. c p edge 8 16 n 1 3 n 2 4 n 3 8 n 5 5 n 6 2 n 8 3 e 1 4 e 1 5 e 1 6 e 1 8 e 2 3 e 2 6 e 2 7 e 2 8 e 3 4 e 3 6 e 3 7 e 4 5 e 4 8 e 5 7 e 5 8 e 6 7 c c eof glpk-4.52.1/examples/sample.cnf0000644000062000006210000000017712175147600015515 0ustar maomkpasswdc sample.cnf c c This is an example of the CNF-SAT problem data c in DIMACS format. c p cnf 4 3 1 2 0 -4 3 -2 0 -1 4 0 c c eof glpk-4.52.1/examples/sample.col0000644000062000006210000000037112175147600015520 0ustar maomkpasswdc sample.col c c This is an example of the vertex coloring problem data c in DIMACS format. c p edge 10 21 c e 1 2 e 1 6 e 1 7 e 1 10 e 2 3 e 2 7 e 2 8 e 3 4 e 3 8 e 4 5 e 4 8 e 4 9 e 5 6 e 5 9 e 5 10 e 6 10 e 7 8 e 7 10 e 8 9 e 8 10 e 9 10 c c eof glpk-4.52.1/examples/sample.max0000644000062000006210000000037412175147600015533 0ustar maomkpasswdc sample.max c c This is an example of the maximum flow problem data c in DIMACS format. c p max 9 14 c n 1 s n 9 t c a 1 2 14 a 1 4 23 a 2 3 10 a 2 4 9 a 3 5 12 a 3 8 18 a 4 5 26 a 5 2 11 a 5 6 25 a 5 7 4 a 6 7 7 a 6 8 8 a 7 9 15 a 8 9 20 c c eof glpk-4.52.1/examples/sample.min0000644000062000006210000000047412175147600015532 0ustar maomkpasswdc sample.min c c This is an example of the minimum cost flow problem data c in DIMACS format. c p min 9 14 c n 1 20 n 9 -20 c a 1 2 0 14 0 a 1 4 0 23 0 a 2 3 0 10 2 a 2 4 0 9 3 a 3 5 2 12 1 a 3 8 0 18 0 a 4 5 0 26 0 a 5 2 0 11 1 a 5 6 0 25 5 a 5 7 0 4 7 a 6 7 0 7 0 a 6 8 4 8 0 a 7 9 0 15 3 a 8 9 0 20 9 c c eof glpk-4.52.1/examples/sat.mod0000644000062000006210000001211612175147600015030 0ustar maomkpasswd/* SAT, Satisfiability Problem */ /* Written in GNU MathProg by Andrew Makhorin */ param m, integer, > 0; /* number of clauses */ param n, integer, > 0; /* number of variables */ set C{1..m}; /* clauses; each clause C[i], i = 1, ..., m, is disjunction of some variables or their negations; in the data section each clause is coded as a set of indices of corresponding variables, where negative indices mean negation; for example, the clause (x3 or not x7 or x11) is coded as the set { 3, -7, 11 } */ var x{1..n}, binary; /* main variables */ /* To solve the satisfiability problem means to determine all variables x[j] such that conjunction of all clauses C[1] and ... and C[m] takes on the value true, i.e. all clauses are satisfied. Let the clause C[i] be (t or t' or ... or t''), where t, t', ..., t'' are either variables or their negations. The condition of satisfying C[i] can be most naturally written as: t + t' + ... + t'' >= 1, (1) where t, t', t'' have to be replaced by either x[j] or (1 - x[j]). The formulation (1) leads to the mip problem with no objective, i.e. to a feasibility problem. Another, more practical way is to write the condition for C[i] as: t + t' + ... + t'' + y[i] >= 1, (2) where y[i] is an auxiliary binary variable, and minimize the sum of y[i]. If the sum is zero, all y[i] are also zero, and therefore all clauses are satisfied. If the sum is minimal but non-zero, its value shows the number of clauses which cannot be satisfied. */ var y{1..m}, binary, >= 0; /* auxiliary variables */ s.t. c{i in 1..m}: sum{j in C[i]} (if j > 0 then x[j] else (1 - x[-j])) + y[i] >= 1; /* the condition (2) */ minimize unsat: sum{i in 1..m} y[i]; /* number of unsatisfied clauses */ data; /* These data correspond to the instance hole6 (pigeon hole problem for 6 holes) from SATLIB, the Satisfiability Library, which is part of the collection at the Forschungsinstitut fuer anwendungsorientierte Wissensverarbeitung in Ulm Germany */ /* The optimal solution is 1 (one clause cannot be satisfied) */ param m := 133; param n := 42; set C[1] := -1 -7; set C[2] := -1 -13; set C[3] := -1 -19; set C[4] := -1 -25; set C[5] := -1 -31; set C[6] := -1 -37; set C[7] := -7 -13; set C[8] := -7 -19; set C[9] := -7 -25; set C[10] := -7 -31; set C[11] := -7 -37; set C[12] := -13 -19; set C[13] := -13 -25; set C[14] := -13 -31; set C[15] := -13 -37; set C[16] := -19 -25; set C[17] := -19 -31; set C[18] := -19 -37; set C[19] := -25 -31; set C[20] := -25 -37; set C[21] := -31 -37; set C[22] := -2 -8; set C[23] := -2 -14; set C[24] := -2 -20; set C[25] := -2 -26; set C[26] := -2 -32; set C[27] := -2 -38; set C[28] := -8 -14; set C[29] := -8 -20; set C[30] := -8 -26; set C[31] := -8 -32; set C[32] := -8 -38; set C[33] := -14 -20; set C[34] := -14 -26; set C[35] := -14 -32; set C[36] := -14 -38; set C[37] := -20 -26; set C[38] := -20 -32; set C[39] := -20 -38; set C[40] := -26 -32; set C[41] := -26 -38; set C[42] := -32 -38; set C[43] := -3 -9; set C[44] := -3 -15; set C[45] := -3 -21; set C[46] := -3 -27; set C[47] := -3 -33; set C[48] := -3 -39; set C[49] := -9 -15; set C[50] := -9 -21; set C[51] := -9 -27; set C[52] := -9 -33; set C[53] := -9 -39; set C[54] := -15 -21; set C[55] := -15 -27; set C[56] := -15 -33; set C[57] := -15 -39; set C[58] := -21 -27; set C[59] := -21 -33; set C[60] := -21 -39; set C[61] := -27 -33; set C[62] := -27 -39; set C[63] := -33 -39; set C[64] := -4 -10; set C[65] := -4 -16; set C[66] := -4 -22; set C[67] := -4 -28; set C[68] := -4 -34; set C[69] := -4 -40; set C[70] := -10 -16; set C[71] := -10 -22; set C[72] := -10 -28; set C[73] := -10 -34; set C[74] := -10 -40; set C[75] := -16 -22; set C[76] := -16 -28; set C[77] := -16 -34; set C[78] := -16 -40; set C[79] := -22 -28; set C[80] := -22 -34; set C[81] := -22 -40; set C[82] := -28 -34; set C[83] := -28 -40; set C[84] := -34 -40; set C[85] := -5 -11; set C[86] := -5 -17; set C[87] := -5 -23; set C[88] := -5 -29; set C[89] := -5 -35; set C[90] := -5 -41; set C[91] := -11 -17; set C[92] := -11 -23; set C[93] := -11 -29; set C[94] := -11 -35; set C[95] := -11 -41; set C[96] := -17 -23; set C[97] := -17 -29; set C[98] := -17 -35; set C[99] := -17 -41; set C[100] := -23 -29; set C[101] := -23 -35; set C[102] := -23 -41; set C[103] := -29 -35; set C[104] := -29 -41; set C[105] := -35 -41; set C[106] := -6 -12; set C[107] := -6 -18; set C[108] := -6 -24; set C[109] := -6 -30; set C[110] := -6 -36; set C[111] := -6 -42; set C[112] := -12 -18; set C[113] := -12 -24; set C[114] := -12 -30; set C[115] := -12 -36; set C[116] := -12 -42; set C[117] := -18 -24; set C[118] := -18 -30; set C[119] := -18 -36; set C[120] := -18 -42; set C[121] := -24 -30; set C[122] := -24 -36; set C[123] := -24 -42; set C[124] := -30 -36; set C[125] := -30 -42; set C[126] := -36 -42; set C[127] := 6 5 4 3 2 1; set C[128] := 12 11 10 9 8 7; set C[129] := 18 17 16 15 14 13; set C[130] := 24 23 22 21 20 19; set C[131] := 30 29 28 27 26 25; set C[132] := 36 35 34 33 32 31; set C[133] := 42 41 40 39 38 37; end; glpk-4.52.1/examples/shiftcover.mod0000644000062000006210000002463412175147600016425 0ustar maomkpasswd/* File: shiftcover.mod */ /* WORKFORCE SHIFT COVERAGE assignment problem */ /* Written by Larry D'Agostino Maximize Productivity with Industrial Engineer and Operations Research Tools http://industrialengineertools.blogspot.com /* The WORKFORCE SHIFT COVERAGE is an assigment problem that determines the schedule of crew given available time and shifts. The objective is to cover the available time given hourly demand with the minimum number of crew members. This is a set covering problem that is very common among finding crew and shift allocations. Notice in the data section the workforce shift allocation per day of the week.*/ /* ----- Model PARAMTERS and SETS -----*/ param numhrs; /* number of hours of operations in a given day */ param dys; /* number of days in a week */ set S; /* set of crew shifts */ set H := 1..numhrs; /* set of hours of a day*/ set D; /* set of days of a week*/ param dmnd{h in H, d in D}; /* demand for crew members given h hour and d day */ param shifts{d in D, h in H, s in S}; /* shifts to assign to crew members given d day, h hour, and s shift schedule /*----- Model VARIABLES -----*/ var crew{s in S}, integer, >=0; /* number of crew assigned to shift S */ /*----- Model CONSTRAINTS -----*/ s.t. Coverage{h in H, d in D}: sum{s in S} crew[s]*shifts[d,h,s] >= dmnd[h,d]; /* number of crew to cover with a shift given hourly demand and day */ /*----- Model OBJECTIVE -----*/ minimize obj: sum{s in S} crew[s]; /* minimize number of crew to cover demand*/ solve; display crew; printf "\n"; printf "Total Crew: %3d\n\n", sum{s in S} crew[s]; printf "\n\n"; printf "Weekly Crew Schedule\n\n"; printf "Hour "; printf{d in D} " %s ", d; printf "\n"; for {h in H} { printf " %2s ",h; printf{d in D} " %3d ", sum{s in S} crew[s]*shifts[d,h,s]; printf "\n"; } printf"\n"; data; param numhrs := 16; set D := SUN, MON, TUE, WED, THU, FRI, SAT; set S := Sh1, Sh2, Sh3, Sh4, Sh5, Sh6, Sh7, Sh8, Sh9; param dmnd : SUN MON TUE WED THU FRI SAT := 1 0 3 3 4 3 2 0 2 0 14 14 16 14 12 12 3 0 24 24 27 24 20 15 4 0 28 28 32 28 23 15 5 0 33 33 37 33 24 16 6 0 34 34 38 34 24 15 7 0 35 35 39 35 25 11 8 0 35 35 40 35 27 0 9 0 34 34 39 34 25 0 10 0 31 31 35 31 24 0 11 2 24 24 27 24 25 0 12 3 19 19 21 19 21 0 13 2 24 24 27 24 13 0 14 2 16 16 18 16 0 0 15 0 7 7 7 7 0 0 16 0 5 5 5 5 0 0; param shifts := ['SUN',*,*]: Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 5 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 11 0 0 0 0 0 0 0 0 1 12 0 0 0 0 0 0 0 0 1 13 0 0 0 0 0 0 0 0 1 14 0 0 0 0 0 0 0 0 1 15 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 ['MON',*,*]: Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := 1 1 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 0 0 0 3 1 1 1 0 0 0 0 0 0 4 1 1 1 1 0 0 0 0 0 5 0 1 1 1 1 0 0 0 0 6 1 0 1 1 1 1 0 0 1 7 1 1 0 1 1 1 1 0 1 8 1 1 1 0 1 1 1 1 1 9 1 1 1 1 0 1 1 1 1 10 0 1 1 1 1 0 1 1 1 11 0 0 1 1 1 1 0 1 0 12 0 0 0 1 1 1 1 0 1 13 0 0 0 0 1 1 1 1 1 14 0 0 0 0 0 1 1 1 1 15 0 0 0 0 0 0 1 1 1 16 0 0 0 0 0 0 0 1 1 ['TUE',*,*]: Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := 1 1 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 0 0 0 3 1 1 1 0 0 0 0 0 0 4 1 1 1 1 0 0 0 0 0 5 0 1 1 1 1 0 0 0 0 6 1 0 1 1 1 1 0 0 1 7 1 1 0 1 1 1 1 0 1 8 1 1 1 0 1 1 1 1 1 9 1 1 1 1 0 1 1 1 1 10 0 1 1 1 1 0 1 1 1 11 0 0 1 1 1 1 0 1 0 12 0 0 0 1 1 1 1 0 1 13 0 0 0 0 1 1 1 1 1 14 0 0 0 0 0 1 1 1 1 15 0 0 0 0 0 0 1 1 1 16 0 0 0 0 0 0 0 1 1 ['WED',*,*]: Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := 1 1 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 0 0 0 3 1 1 1 0 0 0 0 0 0 4 1 1 1 1 0 0 0 0 0 5 0 1 1 1 1 0 0 0 0 6 1 0 1 1 1 1 0 0 1 7 1 1 0 1 1 1 1 0 1 8 1 1 1 0 1 1 1 1 1 9 1 1 1 1 0 1 1 1 1 10 0 1 1 1 1 0 1 1 1 11 0 0 1 1 1 1 0 1 0 12 0 0 0 1 1 1 1 0 1 13 0 0 0 0 1 1 1 1 1 14 0 0 0 0 0 1 1 1 1 15 0 0 0 0 0 0 1 1 1 16 0 0 0 0 0 0 0 1 1 ['THU',*,*]: Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := 1 1 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 0 0 0 3 1 1 1 0 0 0 0 0 0 4 1 1 1 1 0 0 0 0 0 5 0 1 1 1 1 0 0 0 0 6 1 0 1 1 1 1 0 0 0 7 1 1 0 1 1 1 1 0 0 8 1 1 1 0 1 1 1 1 0 9 1 1 1 1 0 1 1 1 0 10 0 1 1 1 1 0 1 1 0 11 0 0 1 1 1 1 0 1 0 12 0 0 0 1 1 1 1 0 0 13 0 0 0 0 1 1 1 1 0 14 0 0 0 0 0 1 1 1 0 15 0 0 0 0 0 0 1 1 0 16 0 0 0 0 0 0 0 1 0 ['FRI',*,*]: Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := 1 1 0 0 0 0 0 0 0 0 2 1 1 0 0 0 0 0 0 0 3 1 1 1 0 0 0 0 0 0 4 1 1 1 1 0 0 0 0 0 5 0 1 1 1 1 0 0 0 0 6 1 0 1 1 1 1 0 0 0 7 1 1 0 1 1 1 1 0 0 8 1 1 1 0 1 1 1 1 0 9 1 1 1 1 0 1 1 1 0 10 0 1 1 1 1 0 1 1 0 11 0 0 1 1 1 1 0 1 0 12 0 0 0 1 1 1 1 0 0 13 0 0 0 0 1 1 1 1 0 14 0 0 0 0 0 1 1 1 0 15 0 0 0 0 0 0 1 1 0 16 0 0 0 0 0 0 0 1 0 ['SAT',*,*]: Sh1 Sh2 Sh3 Sh4 Sh5 Sh6 Sh7 Sh8 Sh9 := 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 1 3 0 0 0 0 0 0 0 0 1 4 0 0 0 0 0 0 0 0 1 5 0 0 0 0 0 0 0 0 1 6 0 0 0 0 0 0 0 0 1 7 0 0 0 0 0 0 0 0 1 8 0 0 0 0 0 0 0 0 0 9 0 0 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 12 0 0 0 0 0 0 0 0 0 13 0 0 0 0 0 0 0 0 0 14 0 0 0 0 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0; glpk-4.52.1/examples/shikaku.mod0000644000062000006210000000747312175147600015712 0ustar maomkpasswd/* A solver for the Japanese number-puzzle Shikaku * http://en.wikipedia.org/wiki/Shikaku * * Sebastian Nowozin , 27th January 2009 */ param ndim := 10; set rows := 1..ndim; set rows1 := 1..(ndim+1); set cols := 1..ndim; set cols1 := 1..(ndim+1); param givens{rows, cols}, integer, >= 0, default 0; /* Set of vertices as (row,col) coordinates */ set V := { (i,j) in { rows, cols }: givens[i,j] != 0 }; /* Set of all feasible boxes of the right size: only this boxes are possible. * The box contains (i,j) and ranges from (k,l) to (m,n) */ set B := { (i,j,k,l,m,n) in { V, rows, cols, rows1, cols1 }: i >= k and i < m and j >= l and j < n and /* Contains (i,j) */ ((m-k)*(n-l)) = givens[i,j] and /* Right size */ card({ (s,t) in V: s >= k and s < m and t >= l and t < n }) = 1 /* Contains only (i,j), no other number */ }; var x{B}, binary; /* Cover each square exactly once */ s.t. cover_once{ (s,t) in { rows, cols } }: sum{(i,j,k,l,m,n) in B: s >= k and s < m and t >= l and t < n} x[i,j,k,l,m,n] = 1; minimize cost: 0; solve; /* Output solution graphically */ printf "\nSolution:\n"; for { row in rows1 } { for { col in cols1 } { printf{0..0: card({(i,j,k,l,m,n) in B: col >= l and col <= n and (row = k or row = m) and x[i,j,k,l,m,n] = 1}) > 0 and card({(i,j,k,l,m,n) in B: row >= k and row <= m and (col = l or col = n) and x[i,j,k,l,m,n] = 1}) > 0} "+"; printf{0..0: card({(i,j,k,l,m,n) in B: col >= l and col <= n and (row = k or row = m) and x[i,j,k,l,m,n] = 1}) = 0 and card({(i,j,k,l,m,n) in B: row >= k and row <= m and (col = l or col = n) and x[i,j,k,l,m,n] = 1}) > 0} "|"; printf{0..0: card({(i,j,k,l,m,n) in B: row >= k and row <= m and (col = l or col = n) and x[i,j,k,l,m,n] = 1}) = 0 and card({(i,j,k,l,m,n) in B: col >= l and col <= n and (row = k or row = m) and x[i,j,k,l,m,n] = 1}) > 0} "-"; printf{0..0: card({(i,j,k,l,m,n) in B: row >= k and row <= m and (col = l or col = n) and x[i,j,k,l,m,n] = 1}) = 0 and card({(i,j,k,l,m,n) in B: col >= l and col <= n and (row = k or row = m) and x[i,j,k,l,m,n] = 1}) = 0} " "; printf{0..0: card({(i,j,k,l,m,n) in B: col >= l and col < n and (row = k or row = m) and x[i,j,k,l,m,n] = 1}) > 0} "---"; printf{0..0: card({(i,j,k,l,m,n) in B: col >= l and col < n and (row = k or row = m) and x[i,j,k,l,m,n] = 1}) = 0} " "; } printf "\n"; for { (col,p) in { cols, 1 }: card({ s in rows: s = row }) = 1 } { printf{0..0: card({(i,j,k,l,m,n) in B: row >= k and row < m and (col = l or col = n) and x[i,j,k,l,m,n] = 1}) > 0} "|"; printf{0..0: card({(i,j,k,l,m,n) in B: row >= k and row < m and (col = l or col = n) and x[i,j,k,l,m,n] = 1}) = 0} " "; printf{0..0: card({ (i,j) in V: i = row and j = col}) > 0} " %2d", givens[row,col]; printf{0..0: card({ (i,j) in V: i = row and j = col}) = 0} " ."; } printf{0..0: card({ r in rows: r = row }) = 1} "|\n"; } data; /* This Shikaku is from * http://www.emn.fr/x-info/sdemasse/gccat/KShikaku.html#uid5449 */ param givens : 1 2 3 4 5 6 7 8 9 10 := 1 9 . . . 12 . . 5 . . 2 . . . . . . . . . . 3 . . . . . . . . . 6 4 8 . 6 . 8 . . . . . 5 . . . . . . . . . . 6 . . . . . . . . . . 7 . . . . . 6 . 8 . 12 8 4 . . . . . . . . . 9 . . . . . . . . . . 10 . . 3 . . 9 . . . 4 ; end; glpk-4.52.1/examples/sorting.mod0000644000062000006210000000305212175147600015725 0ustar maomkpasswd/* sorting.mod - how to sort arrays in MathProg */ /* Written in GNU MathProg by Andrew Makhorin */ # Sometimes it is necessary to print parameters or variables in the # order of ascending or descending their values. Suppose, for example, # that we have the following subscripted parameter: set I := 1..12; param a{i in I} := Uniform(2, 7); # If we print all its members: printf{i in I} "a[%d] = %g\n", i, a[i]; # the output may look like follows: # # a[1] = 2.64156 # a[2] = 2.04798 # a[3] = 2.14843 # a[4] = 4.76896 # a[5] = 6.09132 # a[6] = 3.27780 # a[7] = 4.06113 # a[8] = 4.05898 # a[9] = 6.63120 # a[10] = 6.50318 # a[11] = 3.46065 # a[12] = 4.69845 # # However, we would like the parameter members to appear in the order # of ascending their values. # # Introduce the following auxiliary parameter: param pos{i in I} := 1 + card({j in I: a[j] < a[i] or a[j] = a[i] and j < i}); # where pos[i] = k means that in the sorted list member a[i] would # have k-th position, 1 <= k <= |I|. Then introduce another auxiliary # parameter: param ind{k in 1..card(I)} := sum{i in I: pos[i] = k} i; # where ind[k] = i iff pos[k] = i. # # Now, the following statement: printf{k in 1..card(I)} "a[%d] = %g\n", ind[k], a[ind[k]]; # prints the parameter members in the desired order: # # a[2] = 2.04798 # a[3] = 2.14843 # a[1] = 2.64156 # a[6] = 3.27780 # a[11] = 3.46065 # a[8] = 4.05898 # a[7] = 4.06113 # a[12] = 4.69845 # a[4] = 4.76896 # a[5] = 6.09132 # a[10] = 6.50318 # a[9] = 6.63120 end; glpk-4.52.1/examples/spp.mod0000644000062000006210000000325312175147600015045 0ustar maomkpasswd/* SPP, Shortest Path Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* Given a directed graph G = (V,E), its edge lengths c(i,j) for all (i,j) in E, and two nodes s, t in V, the Shortest Path Problem (SPP) is to find a directed path from s to t whose length is minimal. */ param n, integer, > 0; /* number of nodes */ set E, within {i in 1..n, j in 1..n}; /* set of edges */ param c{(i,j) in E}; /* c[i,j] is length of edge (i,j); note that edge lengths are allowed to be of any sign (positive, negative, or zero) */ param s, in {1..n}; /* source node */ param t, in {1..n}; /* target node */ var x{(i,j) in E}, >= 0; /* x[i,j] = 1 means that edge (i,j) belong to shortest path; x[i,j] = 0 means that edge (i,j) does not belong to shortest path; note that variables x[i,j] are binary, however, there is no need to declare them so due to the totally unimodular constraint matrix */ s.t. r{i in 1..n}: sum{(j,i) in E} x[j,i] + (if i = s then 1) = sum{(i,j) in E} x[i,j] + (if i = t then 1); /* conservation conditions for unity flow from s to t; every feasible solution is a path from s to t */ minimize Z: sum{(i,j) in E} c[i,j] * x[i,j]; /* objective function is the path length to be minimized */ data; /* Optimal solution is 20 that corresponds to the following shortest path: s = 1 -> 2 -> 4 -> 8 -> 6 = t */ param n := 8; param s := 1; param t := 6; param : E : c := 1 2 1 1 4 8 1 7 6 2 4 2 3 2 14 3 4 10 3 5 6 3 6 19 4 5 8 4 8 13 5 8 12 6 5 7 7 4 5 8 6 4 8 7 10; end; glpk-4.52.1/examples/spxsamp1.c0000644000062000006210000000053012175147600015455 0ustar maomkpasswd/* spxsamp1.c */ #include #include #include int main(void) { glp_prob *P; P = glp_create_prob(); glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); glp_adv_basis(P, 0); glp_simplex(P, NULL); glp_print_sol(P, "25fv47.txt"); glp_delete_prob(P); return 0; } /* eof */ glpk-4.52.1/examples/spxsamp2.c0000644000062000006210000000061312175147600015460 0ustar maomkpasswd/* spxsamp2.c */ #include #include #include int main(void) { glp_prob *P; glp_smcp parm; P = glp_create_prob(); glp_read_mps(P, GLP_MPS_DECK, NULL, "25fv47.mps"); glp_init_smcp(&parm); parm.meth = GLP_DUAL; glp_simplex(P, &parm); glp_print_sol(P, "25fv47.txt"); glp_delete_prob(P); return 0; } /* eof */ glpk-4.52.1/examples/sql/0000755000062000006210000000000012175147600014336 5ustar maomkpasswdglpk-4.52.1/examples/sql/mysql_setup.sh0000777000062000006210000000031712175147600017267 0ustar maomkpasswd#!/bin/sh # This file can be used to create database glpk in MySQL. echo MySQL is called for user root. mysql -f -u root -p < sudoku.sql echo MySQL is called for user root. mysql -f -u root -p < transp.sql glpk-4.52.1/examples/sql/README0000644000062000006210000000035212175147600015216 0ustar maomkpasswdThis subdirectory contains files which demonstrate using data tables in MathProg models for MySQL and iODBC. Script mysql_setup.sh is used to load the data from the *.sql files to a MySQL database. Change the username, if necessary. glpk-4.52.1/examples/sql/sudoku.sql0000644000062000006210000001222212175147600016370 0ustar maomkpasswdCREATE DATABASE glpk; CREATE USER glpk@localhost IDENTIFIED BY 'gnu'; GRANT ALL PRIVILEGES ON glpk.* TO glpk@localhost; USE glpk; DROP TABLE sudoku; CREATE TABLE sudoku ( ID INT , COL INT , LIN INT , VAL INT , PRIMARY KEY ( ID, COL, LIN ) ); DROP TABLE sudoku_solution; CREATE TABLE sudoku_solution ( ID INT , COL INT , LIN INT , VAL INT , PRIMARY KEY ( ID, COL, LIN ) ); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 1, 5); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 2, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 3, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 4, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 5, 4); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 6, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 7, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 8, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 1, 9, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 1, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 2, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 3, 3); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 4, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 5, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 6, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 7, 6); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 8, 2); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 2, 9, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 1, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 2, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 3, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 4, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 5, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 6, 9); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 7, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 8, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 3, 9, 4); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 1, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 2, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 3, 6); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 4, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 5, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 6, 7); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 7, 2); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 8, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 4, 9, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 1, 8); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 2, 1); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 3, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 4, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 5, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 6, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 7, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 8, 4); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 5, 9, 3); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 1, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 2, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 3, 9); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 4, 1); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 5, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 6, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 7, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 8, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 6, 9, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 1, 7); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 2, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 3, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 4, 5); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 5, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 6, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 7, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 8, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 7, 9, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 1, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 2, 9); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 3, 2); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 4, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 5, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 6, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 7, 8); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 8, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 8, 9, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 1, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 2, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 3, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 4, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 5, 3); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 6, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 7, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 8, 0); INSERT INTO sudoku (ID, COL, LIN, VAL) VALUES (1, 9, 9, 6); glpk-4.52.1/examples/sql/sudoku_mysql.mod0000644000062000006210000000660712175147600017607 0ustar maomkpasswd/* SUDOKU, Number Placement Puzzle */ /* Written in GNU MathProg by Andrew Makhorin */ /* This example shows how to use the table statement. The sudoku to be solves is read from file sudoku_in.csv. The solution is written to sudoku_out.csv. The file format is CSV as defined in RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files */ /* Sudoku, also known as Number Place, is a logic-based placement puzzle. The aim of the canonical puzzle is to enter a numerical digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 subgrids (called "regions"), starting with various digits given in some cells (the "givens"). Each row, column, and region must contain only one instance of each numeral. Example: +-------+-------+-------+ | 5 3 . | . 7 . | . . . | | 6 . . | 1 9 5 | . . . | | . 9 8 | . . . | . 6 . | +-------+-------+-------+ | 8 . . | . 6 . | . . 3 | | 4 . . | 8 . 3 | . . 1 | | 7 . . | . 2 . | . . 6 | +-------+-------+-------+ | . 6 . | . . . | 2 8 . | | . . . | 4 1 9 | . . 5 | | . . . | . 8 . | . 7 9 | +-------+-------+-------+ (From Wikipedia, the free encyclopedia.) */ set fields dimen 2; param id; param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; /* the "givens" */ /* table ti IN 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' 'sudoku' : fields <- [COL, LIN], givens ~ VAL; */ table ti IN 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' 'SELECT * FROM sudoku WHERE ID = ' & id : fields <- [COL, LIN], givens ~ VAL; var x{i in 1..9, j in 1..9, k in 1..9}, binary; /* x[i,j,k] = 1 means cell [i,j] is assigned number k */ s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: x[i,j,k] = (if givens[i,j] = k then 1 else 0); /* assign pre-defined numbers using the "givens" */ s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; /* each cell must be assigned exactly one number */ s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; /* cells in the same row must be assigned distinct numbers */ s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; /* cells in the same column must be assigned distinct numbers */ s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; /* cells in the same region must be assigned distinct numbers */ /* there is no need for an objective function here */ solve; table ta{(i,j) in fields} OUT 'MySQL' 'Database=glpk;UID=glpk;PWD=gnu' 'DELETE FROM sudoku_solution' 'WHERE ID = ' & id & ';' 'INSERT INTO sudoku_solution' '(ID, COL, LIN, VAL)' 'VALUES(?, ?, ?, ?);' : id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL; printf "\nSudoku to be solved\n"; for {i in 1..9} { for {0..0: i = 1 or i = 4 or i = 7} printf " +-------+-------+-------+\n"; for {j in 1..9} { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); printf " %d", givens[i,j]; for {0..0: j = 9} printf(" |\n"); } for {0..0: i = 9} printf " +-------+-------+-------+\n"; } printf "\nSolution\n"; for {i in 1..9} { for {0..0: i = 1 or i = 4 or i = 7} printf " +-------+-------+-------+\n"; for {j in 1..9} { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); printf " %d", sum{k in 1..9} x[i,j,k] * k; for {0..0: j = 9} printf(" |\n"); } for {0..0: i = 9} printf " +-------+-------+-------+\n"; } data; param id := 1; end; glpk-4.52.1/examples/sql/sudoku_odbc.mod0000644000062000006210000000646112175147600017347 0ustar maomkpasswd/* SUDOKU, Number Placement Puzzle */ /* Written in GNU MathProg by Andrew Makhorin */ /* This example shows how to use the table statement. The sudoku to be solves is read from file sudoku_in.csv. The solution is written to sudoku_out.csv. The file format is CSV as defined in RFC 4180 - Common Format and MIME Type for Comma-Separated Values (CSV) Files */ /* Sudoku, also known as Number Place, is a logic-based placement puzzle. The aim of the canonical puzzle is to enter a numerical digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 subgrids (called "regions"), starting with various digits given in some cells (the "givens"). Each row, column, and region must contain only one instance of each numeral. Example: +-------+-------+-------+ | 5 3 . | . 7 . | . . . | | 6 . . | 1 9 5 | . . . | | . 9 8 | . . . | . 6 . | +-------+-------+-------+ | 8 . . | . 6 . | . . 3 | | 4 . . | 8 . 3 | . . 1 | | 7 . . | . 2 . | . . 6 | +-------+-------+-------+ | . 6 . | . . . | 2 8 . | | . . . | 4 1 9 | . . 5 | | . . . | . 8 . | . 7 9 | +-------+-------+-------+ (From Wikipedia, the free encyclopedia.) */ set fields dimen 2; param id; param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; /* the "givens" */ table ti IN 'iODBC' 'DSN=glpk;UID=glpk;PWD=gnu' 'SELECT * FROM sudoku' 'WHERE ID = ' & id : fields <- [COL, LIN], givens ~ VAL; var x{i in 1..9, j in 1..9, k in 1..9}, binary; /* x[i,j,k] = 1 means cell [i,j] is assigned number k */ s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: x[i,j,k] = (if givens[i,j] = k then 1 else 0); /* assign pre-defined numbers using the "givens" */ s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; /* each cell must be assigned exactly one number */ s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; /* cells in the same row must be assigned distinct numbers */ s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; /* cells in the same column must be assigned distinct numbers */ s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; /* cells in the same region must be assigned distinct numbers */ /* there is no need for an objective function here */ solve; table ta {(i, j) in {i1 in 1..9} cross {i2 in 1..9}} OUT 'iODBC' 'DSN=glpk;UID=glpk;PWD=gnu' 'DELETE FROM sudoku_solution' 'WHERE ID = ' & id & ';' 'INSERT INTO sudoku_solution' '(ID, COL, LIN, VAL)' 'VALUES(?, ?, ?, ?);' : id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL; printf "\nSudoku to be solved\n"; for {i in 1..9} { for {0..0: i = 1 or i = 4 or i = 7} printf " +-------+-------+-------+\n"; for {j in 1..9} { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); printf " %d", givens[i,j]; for {0..0: j = 9} printf(" |\n"); } for {0..0: i = 9} printf " +-------+-------+-------+\n"; } printf "\nSolution\n"; for {i in 1..9} { for {0..0: i = 1 or i = 4 or i = 7} printf " +-------+-------+-------+\n"; for {j in 1..9} { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); printf " %d", sum{k in 1..9} x[i,j,k] * k; for {0..0: j = 9} printf(" |\n"); } for {0..0: i = 9} printf " +-------+-------+-------+\n"; } data; param id := 1; end; glpk-4.52.1/examples/sql/transp.sql0000644000062000006210000000307012175147600016366 0ustar maomkpasswdCREATE DATABASE glpk; CREATE USER glpk@localhost IDENTIFIED BY 'gnu'; GRANT ALL PRIVILEGES ON glpk.* TO glpk@localhost; USE glpk; # production capacity DROP TABLE transp_capa; CREATE TABLE transp_capa ( PLANT TEXT(127), CAPA REAL, PRIMARY KEY ( PLANT(127) ) ); INSERT INTO transp_capa ( PLANT, CAPA ) VALUES ( 'Seattle', 350 ); INSERT INTO transp_capa ( PLANT, CAPA ) VALUES ( 'San Diego', 600 ); # demand DROP TABLE transp_demand; CREATE TABLE transp_demand ( MARKET TEXT(127), DEMAND REAL, PRIMARY KEY ( MARKET(127) ) ); INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'New York', 325 ); INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'Chicago', 300 ); INSERT INTO transp_demand ( MARKET, DEMAND ) VALUES ( 'Topeka', 275 ); # distance DROP TABLE transp_dist; CREATE TABLE transp_dist ( LOC1 TEXT(127), LOC2 TEXT(127), DIST REAL, PRIMARY KEY ( LOC1(127), LOC2(127) ) ); INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'New York', 2.5 ); INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'Chicago', 1.7 ); INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'Seattle', 'Topeka', 1.8 ); INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'New York', 2.5 ); INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'Chicago', 1.8 ); INSERT INTO transp_dist ( LOC1, LOC2, DIST ) VALUES ( 'San Diego', 'Topeka', 1.4 ); # result DROP TABLE transp_result; CREATE TABLE transp_result ( LOC1 TEXT(127), LOC2 TEXT(127), QUANTITY REAL, PRIMARY KEY ( LOC1(127), LOC2(127) ) ); glpk-4.52.1/examples/sql/transp_mysql.mod0000644000062000006210000000317312175147600017577 0ustar maomkpasswd# A TRANSPORTATION PROBLEM # # This problem finds a least cost shipping schedule that meets # requirements at markets and supplies at factories. # # References: # Dantzig G B, "Linear Programming and Extensions." # Princeton University Press, Princeton, New Jersey, 1963, # Chapter 3-3. set I; /* canning plants */ param a{i in I}; /* capacity of plant i in cases */ table plants IN "MySQL" 'Database=glpk;UID=glpk;PWD=gnu' 'SELECT PLANT, CAPA AS CAPACITY FROM transp_capa' : I <- [ PLANT ], a ~ CAPACITY; set J; /* markets */ param b{j in J}; /* demand at market j in cases */ table markets IN "MySQL" 'Database=glpk;UID=glpk;PWD=gnu' 'transp_demand' : J <- [ MARKET ], b ~ DEMAND; param d{i in I, j in J}; /* distance in thousands of miles */ table dist IN "MySQL" 'Database=glpk;UID=glpk;PWD=gnu' 'transp_dist' : [ LOC1, LOC2 ], d ~ DIST; param f; /* freight in dollars per case per thousand miles */ param c{i in I, j in J} := f * d[i,j] / 1000; /* transport cost in thousands of dollars per case */ var x{i in I, j in J} >= 0; /* shipment quantities in cases */ minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; /* total transportation costs in thousands of dollars */ s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; /* observe supply limit at plant i */ s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; /* satisfy demand at market j */ solve; table result{i in I, j in J: x[i,j]} OUT "MySQL" 'Database=glpk;UID=glpk;PWD=gnu' 'DELETE FROM transp_result;' 'INSERT INTO transp_result VALUES (?,?,?)' : i ~ LOC1, j ~ LOC2, x[i,j] ~ QUANTITY; data; param f := 90; end; glpk-4.52.1/examples/sql/transp_odbc.mod0000644000062000006210000000315312175147600017337 0ustar maomkpasswd# A TRANSPORTATION PROBLEM # # This problem finds a least cost shipping schedule that meets # requirements at markets and supplies at factories. # # References: # Dantzig G B, "Linear Programming and Extensions." # Princeton University Press, Princeton, New Jersey, 1963, # Chapter 3-3. set I; /* canning plants */ param a{i in I}; /* capacity of plant i in cases */ table plants IN "iODBC" 'DSN=glpk;UID=glpk;PWD=gnu' 'SELECT PLANT, CAPA AS CAPACITY' 'FROM transp_capa' : I <- [ PLANT ], a ~ CAPACITY; set J; /* markets */ param b{j in J}; /* demand at market j in cases */ table markets IN "iODBC" 'DSN=glpk;UID=glpk;PWD=gnu' 'transp_demand' : J <- [ MARKET ], b ~ DEMAND; param d{i in I, j in J}; /* distance in thousands of miles */ table dist IN "iODBC" 'DSN=glpk;UID=glpk;PWD=gnu' 'transp_dist' : [ LOC1, LOC2 ], d ~ DIST; param f; /* freight in dollars per case per thousand miles */ param c{i in I, j in J} := f * d[i,j] / 1000; /* transport cost in thousands of dollars per case */ var x{i in I, j in J} >= 0; /* shipment quantities in cases */ minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; /* total transportation costs in thousands of dollars */ s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; /* observe supply limit at plant i */ s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; /* satisfy demand at market j */ solve; table result{i in I, j in J: x[i,j]} OUT "iODBC" 'DSN=glpk;UID=glpk;PWD=gnu' 'DELETE FROM transp_result;' 'INSERT INTO transp_result VALUES (?,?,?)' : i ~ LOC1, j ~ LOC2, x[i,j] ~ QUANTITY; data; param f := 90; end; glpk-4.52.1/examples/stigler.mod0000644000062000006210000004675612175147600015733 0ustar maomkpasswd/* STIGLER, original Stigler's 1939 diet problem */ /* The Stigler Diet is an optimization problem named for George Stigler, a 1982 Nobel Laureate in economics, who posed the following problem: For a moderately active man weighing 154 pounds, how much of each of 77 foods should be eaten on a daily basis so that the man's intake of nine nutrients will be at least equal to the recommended dietary allowances (RDSs) suggested by the National Research Council in 1943, with the cost of the diet being minimal? The nutrient RDAs required to be met in Stigler's experiment were calories, protein, calcium, iron, vitamin A, thiamine, riboflavin, niacin, and ascorbic acid. The result was an annual budget allocated to foods such as evaporated milk, cabbage, dried navy beans, and beef liver at a cost of approximately $0.11 a day in 1939 U.S. dollars. While the name "Stigler Diet" was applied after the experiment by outsiders, according to Stigler, "No one recommends these diets for anyone, let alone everyone." The Stigler diet has been much ridiculed for its lack of variety and palatability, however his methodology has received praise and is considered to be some of the earliest work in linear programming. The Stigler diet question is a linear programming problem. Lacking any sophisticated method of solving such a problem, Stigler was forced to utilize heuristic methods in order to find a solution. The diet question originally asked in which quantities a 154 pound male would have to consume 77 different foods in order to fulfill the recommended intake of 9 different nutrients while keeping expense at a minimum. Through "trial and error, mathematical insight and agility," Stigler was able to eliminate 62 of the foods from the original 77 (these foods were removed based because they lacked nutrients in comparison to the remaining 15). From the reduced list, Stigler calculated the required amounts of each of the remaining 15 foods to arrive at a cost-minimizing solution to his question. According to Stigler's calculations, the annual cost of his solution was $39.93 in 1939 dollars. When corrected for inflation using the consumer price index, the cost of the diet in 2005 dollars is $561.43. The specific combination of foods and quantities is as follows: Stigler's 1939 Diet Food Annual Quantities Annual Cost ---------------- ----------------- ----------- Wheat Flour 370 lb. $13.33 Evaporated Milk 57 cans 3.84 Cabbage 111 lb. 4.11 Spinach 23 lb. 1.85 Dried Navy Beans 285 lb. 16.80 ---------------------------------------------- Total Annual Cost $39.93 The 9 nutrients that Stigler's diet took into consideration and their respective recommended daily amounts were: Table of nutrients considered in Stigler's diet Nutrient Daily Recommended Intake ------------------------- ------------------------ Calories 3,000 Calories Protein 70 grams Calcium .8 grams Iron 12 milligrams Vitamin A 5,000 IU Thiamine (Vitamin B1) 1.8 milligrams Riboflavin (Vitamin B2) 2.7 milligrams Niacin 18 milligrams Ascorbic Acid (Vitamin C) 75 milligrams Seven years after Stigler made his initial estimates, the development of George Dantzig's Simplex algorithm made it possible to solve the problem without relying on heuristic methods. The exact value was determined to be $39.69 (using the original 1939 data). Dantzig's algorithm describes a method of traversing the vertices of a polytope of N+1 dimensions in order to find the optimal solution to a specific situation. (From Wikipedia, the free encyclopedia.) */ /* Translated from GAMS by Andrew Makhorin . For the original GAMS model stigler1939.gms see [3]. References: 1. George J. Stigler, "The Cost of Subsistence," J. Farm Econ. 27, 1945, pp. 303-14. 2. National Research Council, "Recommended Daily Allowances," Reprint and Circular Series No. 115, January, 1943. 3. Erwin Kalvelagen, "Model building with GAMS," Chapter 2, "Building linear programming models," pp. 128-34. */ set C; /* commodities */ check card(C) = 77; /* there must be 77 commodities */ set N; /* nutrients */ param data{c in C, {"price", "weight"} union N}; /* nutritive values per dollar of expenditure */ param allowance{n in N}; /* recommended daily allowance for a moderately active man */ var x{c in C}, >= 0; /* dollars of food to be purchased daily */ s.t. nb{n in N}: sum{c in C} data[c,n] * x[c] >= allowance[n]; /* nutrient balance */ minimize cost: sum{c in C} x[c]; /* total food bill */ solve; param days := 365.25; /* days in a year */ param commodity{c in C}, symbolic; param unit{c in C}, symbolic; printf "\n"; printf "MINIMUM COST ANNUAL DIET\n"; printf "\n"; printf " Commodity Unit Quantity Cost \n"; printf "------------------------- ---------- ---------- ----------\n"; printf{c in C: x[c] != 0} "%-25s %10s %10.2f $%7.2f\n", commodity[c], unit[c], 100 * days * x[c] / data[c,"price"], days * x[c]; printf " -----------------\n"; printf " Total: $%7.2f\n", days * sum{c in C} x[c]; printf "\n"; data; param : C : commodity unit := flour "Wheat Flour (Enriched)" "10 lb." macaroni "Macaroni" "1 lb." cereal "Wheat Cereal (Enriched)" "28 oz." cornflakes "Corn Flakes" "8 oz." cornmeal "Corn Meal" "1 lb." grits "Hominy Grits" "24 oz." rice "Rice" "1 lb." oats "Rolled Oats" "1 lb." whitebread "White Bread (Enriched)" "1 lb." wheatbread "Whole Wheat Bread" "1 lb." ryebread "Rye Bread" "1 lb." poundcake "Pound Cake" "1 lb." crackers "Soda Crackers" "1 lb." milk "Milk" "1 qt." evapmild "Evaporated Milk (can)" "14.5 oz." butter "Butter" "1 lb." margarine "Oleomargarine" "1 lb." eggs "Eggs" "1 doz." cheese "Cheese (Cheddar)" "1 lb." cream "Cream" "1/2 pt." peanutbutter "Peanut Butter" "1 lb." mayonnaise "Mayonnaise" "1/2 pt." crisco "Crisco" "1 lb." lard "Lard" "1 lb." sirloinsteak "Sirloin Steak" "1 lb." roundsteak "Round Steak" "1 lb." ribroast "Rib Roast" "1 lb." chuckroast "Chuck Roast" "1 lb." plate "Plate" "1 lb." liver "Liver (Beef)" "1 lb." lambleg "Leg of Lamb" "1 lb." lambchops "Lamb Chops (Rib)" "1 lb." porkchops "Pork Chops" "1 lb." porkroast "Pork Loin Roast" "1 lb." bacon "Bacon" "1 lb." ham "Ham - smoked" "1 lb." saltpork "Salt Pork" "1 lb." chicken "Roasting Chicken" "1 lb." veal "Veal Cutlets" "1 lb." salmon "Salmon, Pink (can)" "16 oz." apples "Apples" "1 lb." bananas "Bananas" "1 lb." lemons "Lemons" "1 doz." oranges "Oranges" "1 doz." greenbeans "Green Beans" "1 lb." cabbage "Cabbage" "1 lb." carrots "Carrots" "1 bunch" celery "Celery" "1 stalk" lettuce "Lettuce" "1 head" onions "Onions" "1 lb." potatoes "Potatoes" "15 lb." spinach "Spinach" "1 lb." sweetpotato "Sweet Potatoes" "1 lb." peaches "Peaches (can)" "No. 2 1/2" pears "Pears (can)" "No. 2 1/2" pineapple "Pineapple (can)" "No. 2 1/2" asparagus "Asparagus (can)" "No. 2" cannedgrbn "Grean Beans (can)" "No. 2" porkbeans "Pork and Beans (can)" "16 oz." corn "Corn (can)" "No. 2" peas "Peas (can)" "No. 2" tomatoes "Tomatoes (can)" "No. 2" tomatosoup "Tomato Soup (can)" "10 1/2 oz." driedpeach "Peaches, Dried" "1 lb." prunes "Prunes, Dried" "1 lb." raisins "Raisins, Dried" "15 oz." driedpeas "Peas, Dried" "1 lb." limabeans "Lima Beans, Dried" "1 lb." navybeans "Navy Beans, Dried" "1 lb." coffee "Coffee" "1 lb." tea "Tea" "1/4 lb." cocoa "Cocoa" "8 oz." chocolate "Chocolate" "8 oz." sugar "Sugar" "10 lb." cornsirup "Corn Sirup" "24 oz." molasses "Molasses" "18 oz." strawberry "Strawberry Preserve" "1 lb." ; set N := calories /* Calories, unit = 1000 */ protein /* Protein, unit = grams */ calcium /* Calcium, unit = grams */ iron /* Iron, unit = milligrams */ vitaminA /* Vitamin A, unit = 1000 International Units */ thiamine /* Thiamine, Vit. B1, unit = milligrams */ riboflavin /* Riboflavin, Vit. B2, unit = milligrams */ niacin /* Niacin (Nicotinic Acid), unit = milligrams */ ascorbicAcid /* Ascorbic Acid, Vit. C, unit = milligrams */ ; param data : price weight calories protein calcium iron := # aug. 15 edible # 1939 per $1 # (cents) (grams) (1000) (grams) (grams) (mg.) flour 36.0 12600 44.7 1411 2.0 365 macaroni 14.1 3217 11.6 418 .7 54 cereal 24.2 3280 11.8 377 14.4 175 cornflakes 7.1 3194 11.4 252 .1 56 cornmeal 4.6 9861 36.0 897 1.7 99 grits 8.5 8005 28.6 680 .8 80 rice 7.5 6048 21.2 460 .6 41 oats 7.1 6389 25.3 907 5.1 341 whitebread 7.9 5742 15.6 488 2.5 115 wheatbread 9.1 4985 12.2 484 2.7 125 ryebread 9.2 4930 12.4 439 1.1 82 poundcake 24.8 1829 8.0 130 .4 31 crackers 15.1 3004 12.5 288 .5 50 milk 11.0 8867 6.1 310 10.5 18 evapmild 6.7 6035 8.4 422 15.1 9 butter 20.8 1473 10.8 9 .2 3 margarine 16.1 2817 20.6 17 .6 6 eggs 32.6 1857 2.9 238 1.0 52 cheese 24.2 1874 7.4 448 16.4 19 cream 14.1 1689 3.5 49 1.7 3 peanutbutter 17.9 2534 15.7 661 1.0 48 mayonnaise 16.7 1198 8.6 18 .2 8 crisco 20.3 2234 20.1 0 .0 0 lard 9.8 4628 41.7 0 .0 0 sirloinsteak 39.6 1145 2.9 166 .1 34 roundsteak 36.4 1246 2.2 214 .1 32 ribroast 29.2 1553 3.4 213 .1 33 chuckroast 22.6 2007 3.6 309 .2 46 plate 14.6 3107 8.5 404 .2 62 liver 26.8 1692 2.2 333 .2 139 lambleg 27.6 1643 3.1 245 .1 20 lambchops 36.6 1239 3.3 140 .1 15 porkchops 30.7 1477 3.5 196 .2 80 porkroast 24.2 1874 4.4 249 .3 37 bacon 25.6 1772 10.4 152 .2 23 ham 27.4 1655 6.7 212 .2 31 saltpork 16.0 2835 18.8 164 .1 26 chicken 30.3 1497 1.8 184 .1 30 veal 42.3 1072 1.7 156 .1 24 salmon 13.0 3489 5.8 705 6.8 45 apples 4.4 9072 5.8 27 .5 36 bananas 6.1 4982 4.9 60 .4 30 lemons 26.0 2380 1.0 21 .5 14 oranges 30.9 4439 2.2 40 1.1 18 greenbeans 7.1 5750 2.4 138 3.7 80 cabbage 3.7 8949 2.6 125 4.0 36 carrots 4.7 6080 2.7 73 2.8 43 celery 7.3 3915 .9 51 3.0 23 lettuce 8.2 2247 .4 27 1.1 22 onions 3.6 11844 5.8 166 3.8 59 potatoes 34.0 16810 14.3 336 1.8 118 spinach 8.1 4592 1.1 106 .0 138 sweetpotato 5.1 7649 9.6 138 2.7 54 peaches 16.8 4894 3.7 20 .4 10 pears 20.4 4030 3.0 8 .3 8 pineapple 21.3 3993 2.4 16 .4 8 asparagus 27.7 1945 .4 33 .3 12 cannedgrbn 10.0 5386 1.0 54 2.0 65 porkbeans 7.1 6389 7.5 364 4.0 134 corn 10.4 5452 5.2 136 .2 16 peas 13.8 4109 2.3 136 .6 45 tomatoes 8.6 6263 1.3 63 .7 38 tomatosoup 7.6 3917 1.6 71 .6 43 driedpeach 15.7 2889 8.5 87 1.7 173 prunes 9.0 4284 12.8 99 2.5 154 raisins 9.4 4524 13.5 104 2.5 136 driedpeas 7.9 5742 20.0 1367 4.2 345 limabeans 8.9 5097 17.4 1055 3.7 459 navybeans 5.9 7688 26.9 1691 11.4 792 coffee 22.4 2025 .0 0 .0 0 tea 17.4 652 .0 0 .0 0 cocoa 8.6 2637 8.7 237 3.0 72 chocolate 16.2 1400 8.0 77 1.3 39 sugar 51.7 8773 34.9 0 .0 0 cornsirup 13.7 4996 14.7 0 .5 74 molasses 13.6 3752 9.0 0 10.3 244 strawberry 20.5 2213 6.4 11 .4 7 : vitaminA thiamine riboflavin niacin ascorbicAcid := # (1000 IU) (mg.) (mg.) (mg.) (mg.) flour .0 55.4 33.3 441 0 macaroni .0 3.2 1.9 68 0 cereal .0 14.4 8.8 114 0 cornflakes .0 13.5 2.3 68 0 cornmeal 30.9 17.4 7.9 106 0 grits .0 10.6 1.6 110 0 rice .0 2.0 4.8 60 0 oats .0 37.1 8.9 64 0 whitebread .0 13.8 8.5 126 0 wheatbread .0 13.9 6.4 160 0 ryebread .0 9.9 3.0 66 0 poundcake 18.9 2.8 3.0 17 0 crackers .0 .0 .0 0 0 milk 16.8 4.0 16.0 7 177 evapmild 26.0 3.0 23.5 11 60 butter 44.2 .0 .2 2 0 margarine 55.8 .2 .0 0 0 eggs 18.6 2.8 6.5 1 0 cheese 28.1 .8 10.3 4 0 cream 16.9 .6 2.5 0 17 peanutbutter .0 9.6 8.1 471 0 mayonnaise 2.7 .4 .5 0 0 crisco .0 .0 .0 0 0 lard .2 .0 .5 5 0 sirloinsteak .2 2.1 2.9 69 0 roundsteak .4 2.5 2.4 87 0 ribroast .0 .0 2.0 0 0 chuckroast .4 1.0 4.0 120 0 plate .0 .9 .0 0 0 liver 169.2 6.4 50.8 316 525 lambleg .0 2.8 3.0 86 0 lambchops .0 1.7 2.7 54 0 porkchops .0 17.4 2.7 60 0 porkroast .0 18.2 3.6 79 0 bacon .0 1.8 1.8 71 0 ham .0 9.9 3.3 50 0 saltpork .0 1.4 1.8 0 0 chicken .1 .9 1.8 68 46 veal .0 1.4 2.4 57 0 salmon 3.5 1.0 4.9 209 0 apples 7.3 3.6 2.7 5 544 bananas 17.4 2.5 3.5 28 498 lemons .0 .5 .0 4 952 oranges 11.1 3.6 1.3 10 1993 greenbeans 69.0 4.3 5.8 37 862 cabbage 7.2 9.0 4.5 26 5369 carrots 188.5 6.1 4.3 89 608 celery .9 1.4 1.4 9 313 lettuce 112.4 1.8 3.4 11 449 onions 16.6 4.7 5.9 21 1184 potatoes 6.7 29.4 7.1 198 2522 spinach 918.4 5.7 13.8 33 2755 sweetpotato 290.7 8.4 5.4 83 1912 peaches 21.5 .5 1.0 31 196 pears .8 .8 .8 5 81 pineapple 2.0 2.8 .8 7 399 asparagus 16.3 1.4 2.1 17 272 cannedgrbn 53.9 1.6 4.3 32 431 porkbeans 3.5 8.3 7.7 56 0 corn 12.0 1.6 2.7 42 218 peas 34.9 4.9 2.5 37 370 tomatoes 53.2 3.4 2.5 36 1253 tomatosoup 57.9 3.5 2.4 67 862 driedpeach 86.8 1.2 4.3 55 57 prunes 85.7 3.9 4.3 65 257 raisins 4.5 6.3 1.4 24 136 driedpeas 2.9 28.7 18.4 162 0 limabeans 5.1 26.9 38.2 93 0 navybeans .0 38.4 24.6 217 0 coffee .0 4.0 5.1 50 0 tea .0 .0 2.3 42 0 cocoa .0 2.0 11.9 40 0 chocolate .0 .9 3.4 14 0 sugar .0 .0 .0 0 0 cornsirup .0 .0 .0 5 0 molasses .0 1.9 7.5 146 0 strawberry .2 .2 .4 3 0 ; param allowance := calories 3 protein 70 calcium .8 iron 12 vitaminA 5 thiamine 1.8 riboflavin 2.7 niacin 18 ascorbicAcid 75 ; end; glpk-4.52.1/examples/sudoku.dat0000644000062000006210000000063312175147600015545 0ustar maomkpasswd/* sudoku.dat, a hard Sudoku puzzle which causes branching */ data; param givens : 1 2 3 4 5 6 7 8 9 := 1 1 . . . . . 7 . . 2 . 2 . . . . 5 . . 3 6 . . 3 8 . . . . 4 . 7 8 . . . . . . 5 . . . 6 . 9 . . . 6 . . . . . . 1 4 . 7 . . . . 2 5 . . 9 8 . . 3 . . . . 6 . 9 . . 4 . . . . . 2 ; end; glpk-4.52.1/examples/sudoku.mod0000644000062000006210000000505212175147600015554 0ustar maomkpasswd/* SUDOKU, Number Placement Puzzle */ /* Written in GNU MathProg by Andrew Makhorin */ /* Sudoku, also known as Number Place, is a logic-based placement puzzle. The aim of the canonical puzzle is to enter a numerical digit from 1 through 9 in each cell of a 9x9 grid made up of 3x3 subgrids (called "regions"), starting with various digits given in some cells (the "givens"). Each row, column, and region must contain only one instance of each numeral. Example: +-------+-------+-------+ | 5 3 . | . 7 . | . . . | | 6 . . | 1 9 5 | . . . | | . 9 8 | . . . | . 6 . | +-------+-------+-------+ | 8 . . | . 6 . | . . 3 | | 4 . . | 8 . 3 | . . 1 | | 7 . . | . 2 . | . . 6 | +-------+-------+-------+ | . 6 . | . . . | 2 8 . | | . . . | 4 1 9 | . . 5 | | . . . | . 8 . | . 7 9 | +-------+-------+-------+ (From Wikipedia, the free encyclopedia.) */ param givens{1..9, 1..9}, integer, >= 0, <= 9, default 0; /* the "givens" */ var x{i in 1..9, j in 1..9, k in 1..9}, binary; /* x[i,j,k] = 1 means cell [i,j] is assigned number k */ s.t. fa{i in 1..9, j in 1..9, k in 1..9: givens[i,j] != 0}: x[i,j,k] = (if givens[i,j] = k then 1 else 0); /* assign pre-defined numbers using the "givens" */ s.t. fb{i in 1..9, j in 1..9}: sum{k in 1..9} x[i,j,k] = 1; /* each cell must be assigned exactly one number */ s.t. fc{i in 1..9, k in 1..9}: sum{j in 1..9} x[i,j,k] = 1; /* cells in the same row must be assigned distinct numbers */ s.t. fd{j in 1..9, k in 1..9}: sum{i in 1..9} x[i,j,k] = 1; /* cells in the same column must be assigned distinct numbers */ s.t. fe{I in 1..9 by 3, J in 1..9 by 3, k in 1..9}: sum{i in I..I+2, j in J..J+2} x[i,j,k] = 1; /* cells in the same region must be assigned distinct numbers */ /* there is no need for an objective function here */ solve; for {i in 1..9} { for {0..0: i = 1 or i = 4 or i = 7} printf " +-------+-------+-------+\n"; for {j in 1..9} { for {0..0: j = 1 or j = 4 or j = 7} printf(" |"); printf " %d", sum{k in 1..9} x[i,j,k] * k; for {0..0: j = 9} printf(" |\n"); } for {0..0: i = 9} printf " +-------+-------+-------+\n"; } data; /* These data correspond to the example above. */ param givens : 1 2 3 4 5 6 7 8 9 := 1 5 3 . . 7 . . . . 2 6 . . 1 9 5 . . . 3 . 9 8 . . . . 6 . 4 8 . . . 6 . . . 3 5 4 . . 8 . 3 . . 1 6 7 . . . 2 . . . 6 7 . 6 . . . . 2 8 . 8 . . . 4 1 9 . . 5 9 . . . . 8 . . 7 9 ; end; glpk-4.52.1/examples/t1.cs0000644000062000006210000000666712175147600014431 0ustar maomkpasswd/*Find the minimum value which satisfies the linear inequality: a*x + b*y >= 1 {a,b,x,y Integers} {a,b > 0} {a,b entered on command line} Nigel_Galloway@operamail.com February 2008 */ using System; using System.Runtime.InteropServices; unsafe class GLPK{ double *lp; public int a; public int b; const string glpkLibrary = "libglpk.so"; readonly int GLP_FR = 1; readonly int GLP_IV = 2; readonly int GLP_DB = 4; struct ConstraintMatrix{ public fixed int ia[3]; public fixed int ja[3]; public fixed double ar[3]; } [DllImport(glpkLibrary, SetLastError=true)] static extern double* glp_create_prob(); [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_add_rows(double* lp, int rows); [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_add_cols(double* lp, int cols); [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_set_col_bnds(double* lp, int col, int bound_type, double lower_bound, double upper_bound); [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_set_col_kind(double* lp, int col, int kind); [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_load_matrix(double* lp, int elements, int* ia, int* ja, double* ar); public GLPK(int a, int b){ this.a = a; this.b = b; lp = glp_create_prob(); //Col 1 is x, Col 2 is y glp_add_rows(lp, 1); glp_add_cols(lp, 2); glp_set_col_bnds(lp, 1, GLP_FR, 0.0, 0.0); glp_set_col_bnds(lp, 2, GLP_FR, 0.0, 0.0); glp_set_col_kind(lp, 1, GLP_IV); glp_set_col_kind(lp, 2, GLP_IV); //Row 1 is a*x + b*y ConstraintMatrix CM = new ConstraintMatrix(); CM.ia[1]=1; CM.ja[1]=1; CM.ar[1]=a; CM.ia[2]=1; CM.ja[2]=2; CM.ar[2]=b; glp_load_matrix(lp, 2, CM.ia, CM.ja, CM.ar); Console.WriteLine("Hello Nigel"); } [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_set_row_bnds(double* lp, int row, int bound_type, double lower_bound, double upper_bound); [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_simplex(double* lp, void* options); [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_intopt(double* lp, void* options); [DllImport(glpkLibrary, SetLastError=true)] static extern double glp_mip_col_val(double* lp, int col); public int betterGuess(int upper_bound){ //Find a new guess less than the old guess: 1 <= (a*x + b*y) <= (old guess - 1) glp_set_row_bnds(lp, 1, GLP_DB, 1.0, ((double)upper_bound)-0.5); glp_simplex(lp, null); glp_intopt(lp, null); int x = (int)glp_mip_col_val(lp, 1); int y = (int)glp_mip_col_val(lp, 2); int nextGuess = a*x + b*y; Console.WriteLine("x = {0}, y = {1}, a*x + b*y = {2}",x,y,nextGuess); return nextGuess; } [DllImport(glpkLibrary, SetLastError=true)] static extern void glp_delete_prob(double* lp); ~GLPK(){ glp_delete_prob(lp); Console.WriteLine("Goodbye Nigel"); } } class test{ static bool isMinimum(int a, int b, int guess){ Console.WriteLine("Trying {0}",guess); if (a%guess > 0) return false; if (b%guess > 0) return false; Console.WriteLine("Solution is {0}",guess); return true; } public static void Main(string[] args){ Console.WriteLine("a = {0}, b = {1}",args[0], args[1]); GLPK lp = new GLPK(Int32.Parse(args[0]),Int32.Parse(args[1])); int guess = (lp.a > lp.b) ? lp.b : lp.a; while (!isMinimum(lp.a,lp.b,guess)) guess = lp.betterGuess(guess); } } glpk-4.52.1/examples/tas.mod0000644000062000006210000005005012175147600015027 0ustar maomkpasswd/* TAS, Tail Assignment Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Tail Assignment Problem (TAS) is to construct rosters for a set of aircrafts (tails), which cover all flights for a given scheduling period. This model includes only flight connection constraints while other constraints (for example, maintenance constraints) are ignored. Such simplification allows using a single commodity network to model the problem, where commodity corresponds to the set of aircrafts. Nodes of the network are activities. They include all flights plus two dummy nodes (activities): source node, s, corresponding to initial activity of each aircraft, and sink node t, corresponding to final activity of each aircraft. Arc v->v' exists in the network if and only if the same aircraft is able to operate activity v and then immediately activity v'. In partucular, arcs s->f and f->t exist for all flights f. Arcs f->f', where f and f' are some flights, exist only if the connection time (which is the difference between the departure time of f' and the arrival time of f) is not less than a given minimal connection time. Reference: M. Groenkvist, "The Tail Assignment Problem," Dept. of Comp. Sci. and Eng., Chalmers University of Technology and Goeteborg University, Goeteborg, Sweden, August 2005. */ ######################################################################## param nf, integer, > 0; /* number of flights */ set F := 1..nf; /* set of flights (for a given period from timetable) */ param hub{f in F}, in {1, 2}; /* hub[f] = 1: Sheremetyevo-1 hub[f] = 2: Sheremetyevo-2 */ param dest{f in F}, symbolic; /* destination airport (IATA code) */ param fno1{f in F}, integer; /* first leg flight number */ param dep1{f in F}, integer, >= 0; /* departure time from Sheremetyevo airport, in minutes */ check{f in F: f < nf}: dep1[f] <= dep1[f+1]; /* all flights must be ordered by ascending of the departure time */ param arr1{f in F}, integer, >= 0; /* arrival time to destination airport, in minutes */ param fno2{f in F}, integer; /* second leg flight number */ param dep2{f in F}, integer, >= 0; /* departure time from destination airport, in minutes */ param arr2{f in F}, integer, >= 0; /* arrival time to Sheremetyevo airport, in minutes */ param mct1, integer, >= 0, default 80; /* minimal connection time (within SVO1 or SVO2), in minutes */ param mct2, integer, >= 0, default 150; /* minimal connection time (between SVO1 and SVO2), in minutes */ set E := setof{f in F, ff in F: arr2[f] + (if hub[f] = hub[ff] then mct1 else mct2) <= dep1[ff]} (f, ff); /* connection network; arc f->ff is in E, iff the same aircraft can be assigned to flight f and then immediately to flight ff */ var s{f in F}, >= 0; /* s[f] is a flow from source node to node f */ var x{(f,ff) in E}, >= 0; /* x[f,ff] is a flow from node f to node ff */ var t{f in F}, >= 0; /* t[f] is a flow from node f to sink node */ s.t. into{f in F}: s[f] + sum{(ff,f) in E} x[ff,f] = 1; /* exactly one aircraft must come into each node f */ s.t. from{f in F}: t[f] + sum{(f,ff) in E} x[f,ff] = 1; /* exactly one aircraft must come from each node f */ minimize obj: sum{f in F} s[f]; /* minimize the number aircrafts sufficient to cover all flights */ solve; ######################################################################## param na := floor(sum{f in F} s[f] + .5); /* minimal number of aircrafts found */ printf "At least %d aircrafts needed\n", na; set A := 1..na; /* set of aircrafts */ printf "Building rosters...\n"; param tail{f in F}, in A, := /* tail[f] is the number of an aircraft assigned to flight f */ if f = 1 then 1 /* assign aircraft 1 to the earliest flight */ else if s[f] >= 0.9 then (max{ff in 1..f-1} tail[ff]) + 1 /* if f is the first flight in a roster, assign to it a next aircraft */ else sum{(ff,f) in E} tail[ff] * (if x[ff,f] >= 0.9 then 1); /* otherwise, assign to flight f the same aircraft, which is assigned to a preceding flight in the roster */ ######################################################################## param file, symbolic, default "tas.ps"; /* file to output the assignment chart in postscript format */ param title, symbolic, default "(no title)"; /* chart title */ param left, default 25; /* left margin, in mm */ param top, default 25; /* top margin, in mm */ param right, default 20; /* right margin, in mm */ param bottom, default 15; /* bottom margin, in mm */ param sx := 297 - left - right; /* chart area horizontal size, in mm */ param sy := 210 - top - bottom; /* chart area vertical size, in mm */ param gap, default sy / (na - 1); /* gap between rosters, in mm */ printf "Writing assignment chart to %s...\n", file; printf "%%!PS-Adobe-3.0\n" > file; printf "%%%%Title: Tail Assignment Chart\n" >> file; printf "%%%%Creator: GLPK MathProg\n" >> file; printf "%%%%BoundingBox: 0 0 595 842\n" >> file; printf "%%%%EndComments\n" >> file; printf "<> setpagedevice\n" >> file; printf "72 25.4 div dup scale\n" >> file; printf "210 %.3f sub %.3f translate\n", bottom, left >> file; printf "90 rotate\n" >> file; printf "/HelveticaBold findfont 5 scalefont setfont\n" >> file; printf "%.3f %.3f moveto (%s) dup show\n", 0, sy + 5, title >> file; param period := floor((max{f in F} arr2[f]) / 60. + .5); /* period duration, in hours */ /* vertical bars */ printf ".8 .8 .8 setrgbcolor\n" >> file; for {tt in 0..period} { printf "%s setlinewidth\n", if tt mod 24 = 0 then ".5" else "0" >> file; printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", tt * (sx / period), 0, tt * (sx / period), sy + (if tt mod 24 = 0 then 2) >> file; } /* rosters */ for {a in A} { printf "0 0 0 setrgbcolor\n" >> file; printf "0 setlinewidth\n" >> file; printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", 0, sy - gap * (a - 1), sx, sy - gap * (a - 1) >> file; printf "/Dingbats findfont 4 scalefont setfont\n" >> file; printf "%.3f %.3f moveto <28> dup show\n", -4, sy - gap * (a - 1) - 1.4, a >> file; printf "/Helvetica findfont 3 scalefont setfont\n" >> file; printf "%.3f %.3f moveto (%2d) dup show\n", -9, sy - gap * (a - 1) - 1.2, a >> file; for {f in F: tail[f] == a} { printf "0 0 %s setrgbcolor\n", if hub[f] = 1 then "0" else ".8" >> file; printf "1 setlinewidth\n" >> file; printf "newpath %.3f %.3f moveto %.3f %.3f lineto stroke\n", dep1[f] / 60 * (sx / period), sy - gap * (a - 1), arr2[f] / 60 * (sx / period), sy - gap * (a - 1) >> file; printf "/Helvetica findfont 1.8 scalefont setfont\n" >> file; printf "%.3f %.3f moveto (%02d:%02d %s) dup show\n", dep1[f] / 60 * (sx / period), sy - gap * (a - 1) + .8, (dep1[f] mod 1440) div 60, (dep1[f] mod 1440) mod 60, dest[f] >> file; printf "%.3f %.3f moveto (%d %02d:%02d) dup show\n", dep1[f] / 60 * (sx / period), sy - gap * (a - 1) - 2.1, fno1[f], (arr2[f] mod 1440) div 60, (arr2[f] mod 1440) mod 60 >> file; } } printf "showpage\n" >> file; printf "%%%%EOF\n" >> file; ######################################################################## data; param title := "Tu-154 [from 2008-08-18 to 2008-08-24]"; param nf := 261; param : hub dest fno1 dep1 arr1 fno2 dep2 arr2 := 1 1 IKT 743 195 520 744 610 970 2 1 OMS 815 205 405 816 485 700 3 1 CEK 897 205 360 898 430 595 4 1 KRR 763 260 400 764 480 610 5 2 SIP 133 280 420 134 500 620 6 2 BUD 131 290 450 132 520 675 7 1 AAQ 701 305 440 702 510 640 8 1 MRV 785 310 440 786 520 650 9 2 WAW 101 355 475 102 540 660 10 2 GYD 147 370 550 148 675 860 11 1 AER 869 385 530 870 655 795 12 1 KRR 765 430 560 766 630 760 13 1 AAQ 703 520 660 704 740 850 14 1 LED 845 530 620 846 690 775 15 1 KRR 767 540 675 768 765 895 16 2 KBP 183 665 760 184 850 940 17 1 MRV 787 755 905 788 985 1135 18 1 KRR 771 810 940 772 1030 1165 19 1 LED 849 825 900 850 960 1095 20 2 IST 209 880 1050 210 1120 1280 21 1 AER 873 885 1030 874 1760 1900 22 1 ASF 711 995 1145 712 1640 1795 23 2 ULN 563 995 1335 564 1415 1815 24 2 OTP 151 1020 1175 152 1800 1940 25 2 BEY 509 1025 1265 510 1350 1580 26 2 OSL 211 1060 1220 212 1860 2015 27 1 IKT 739 1085 1420 740 1510 1870 28 1 KRR 773 1095 1240 774 1620 1765 29 1 SGC 877 1120 1315 878 1395 1625 30 1 LED 857 1150 1230 858 1610 1690 31 1 CEK 899 1230 1385 900 1455 1620 32 1 PEE 821 1235 1390 822 1450 1600 33 2 TBS 197 1240 1405 198 1560 1715 34 1 UFA 891 1275 1405 892 1475 1610 35 1 KJA 781 1300 1570 782 1680 1990 36 1 IKT 743 1635 1960 744 2050 2410 37 1 OMS 815 1645 1845 816 1925 2140 38 1 CEK 897 1645 1800 898 1870 2035 39 1 KRR 763 1700 1840 764 1920 2050 40 2 SIP 133 1720 1860 134 1940 2060 41 2 BUD 131 1730 1890 132 1960 2115 42 1 AAQ 701 1745 1880 702 1950 2080 43 1 MRV 785 1750 1880 786 1960 2090 44 2 WAW 101 1795 1915 102 1980 2100 45 2 GYD 147 1810 1990 148 2115 2300 46 1 AER 869 1825 1970 870 2095 2235 47 2 EVN 193 1850 2030 194 2105 2275 48 1 KRR 765 1870 2000 766 2070 2200 49 1 AAQ 703 1960 2100 704 2180 2290 50 1 LED 845 1970 2060 846 2130 2215 51 1 KRR 767 1980 2115 768 2205 2335 52 2 KBP 183 2105 2200 184 2290 2380 53 1 MRV 787 2195 2345 788 2425 2575 54 1 KRR 771 2250 2380 772 2470 2605 55 1 LED 849 2265 2340 850 2400 2535 56 2 IST 209 2320 2490 210 2560 2720 57 1 AER 873 2325 2470 874 3200 3340 58 2 ULN 563 2435 2775 564 2855 3255 59 1 ASF 711 2435 2585 712 3080 3235 60 2 DAM 517 2465 2705 518 2790 3020 61 2 OSL 211 2500 2660 212 3300 3455 62 2 KBP 185 2510 2610 186 3160 3250 63 1 IKT 739 2525 2860 740 2950 3310 64 1 KRR 773 2535 2680 774 3060 3205 65 1 SGC 877 2560 2755 878 2835 3065 66 1 LED 857 2590 2670 858 3050 3130 67 1 CEK 899 2670 2825 900 2895 3060 68 1 PEE 821 2675 2830 822 2890 3040 69 2 TBS 197 2680 2845 198 3000 3155 70 1 UFA 891 2715 2845 892 2915 3050 71 1 KJA 781 2740 3010 782 3120 3430 72 1 IKT 743 3075 3400 744 3490 3850 73 1 CEK 897 3085 3240 898 3310 3475 74 1 OMS 815 3085 3285 816 3365 3580 75 1 KRR 763 3140 3280 764 3360 3490 76 2 SIP 133 3160 3300 134 3380 3500 77 2 BUD 131 3170 3330 132 3400 3555 78 1 AAQ 701 3185 3320 702 3390 3520 79 1 MRV 785 3190 3320 786 3400 3530 80 2 WAW 101 3235 3355 102 3420 3540 81 2 FRU 181 3245 3495 182 3590 3860 82 2 GYD 147 3250 3430 148 3555 3740 83 1 AER 869 3265 3410 870 3535 3675 84 1 KRR 765 3310 3440 766 3510 3640 85 1 AAQ 703 3400 3540 704 3620 3730 86 1 LED 845 3410 3500 846 3570 3655 87 1 KRR 767 3420 3555 768 3645 3775 88 2 KBP 183 3545 3640 184 3730 3820 89 1 MRV 787 3635 3785 788 3865 4015 90 1 KRR 771 3690 3820 772 3910 4045 91 1 LED 849 3705 3780 850 3840 3975 92 2 IST 209 3760 3930 210 4000 4160 93 1 AER 873 3765 3910 874 4640 4780 94 2 ULN 563 3875 4215 564 4295 4695 95 1 ASF 711 3875 4025 712 4520 4675 96 2 OTP 151 3900 4055 152 4680 4820 97 2 BEY 509 3905 4145 510 4230 4460 98 2 OSL 211 3940 4100 212 4740 4895 99 2 KBP 185 3950 4050 186 4600 4690 100 1 IKT 739 3965 4300 740 4390 4750 101 1 KRR 773 3975 4120 774 4500 4645 102 1 SGC 877 4000 4195 878 4275 4505 103 1 LED 857 4030 4110 858 4490 4570 104 1 CEK 899 4110 4265 900 4335 4500 105 1 PEE 821 4115 4270 822 4330 4480 106 2 TBS 197 4120 4285 198 4440 4595 107 1 UFA 891 4155 4285 892 4355 4490 108 1 KJA 781 4180 4450 782 4560 4870 109 1 IKT 743 4515 4840 744 4930 5290 110 1 OMS 815 4525 4725 816 4805 5020 111 1 CEK 897 4525 4680 898 4750 4915 112 1 KRR 763 4580 4720 764 4800 4930 113 2 SIP 133 4600 4740 134 4820 4940 114 2 BUD 131 4610 4770 132 4840 4995 115 1 AAQ 701 4625 4760 702 4830 4960 116 1 MRV 785 4630 4760 786 4840 4970 117 2 WAW 101 4675 4795 102 4860 4980 118 2 GYD 147 4690 4870 148 4995 5180 119 1 AER 869 4705 4850 870 4975 5115 120 2 EVN 193 4730 4910 194 4985 5155 121 1 KRR 765 4750 4880 766 4950 5080 122 1 AAQ 703 4840 4980 704 5060 5170 123 1 LED 845 4850 4940 846 5010 5095 124 1 KRR 767 4860 4995 768 5085 5215 125 2 KBP 183 4985 5080 184 5170 5260 126 1 MRV 787 5075 5225 788 5305 5455 127 1 KRR 771 5130 5260 772 5350 5485 128 1 LED 849 5145 5220 850 5280 5415 129 2 IST 209 5200 5370 210 5440 5600 130 1 AER 873 5205 5350 874 6080 6220 131 1 ASF 711 5315 5465 712 5960 6115 132 2 ULN 563 5315 5655 564 5735 6135 133 2 DAM 517 5345 5585 518 5670 5900 134 2 OSL 211 5380 5540 212 6180 6335 135 2 KBP 185 5390 5490 186 6040 6130 136 1 IKT 739 5405 5740 740 5830 6190 137 1 KRR 773 5415 5560 774 5940 6085 138 1 SGC 877 5440 5635 878 5715 5945 139 1 LED 857 5470 5550 858 5930 6010 140 1 CEK 899 5550 5705 900 5775 5940 141 1 PEE 821 5555 5710 822 5770 5920 142 2 TBS 197 5560 5725 198 5880 6035 143 1 UFA 891 5595 5725 892 5795 5930 144 1 KJA 781 5620 5890 782 6000 6310 145 1 IKT 743 5955 6280 744 6370 6730 146 1 OMS 815 5965 6165 816 6245 6460 147 1 CEK 897 5965 6120 898 6190 6355 148 1 KRR 763 6020 6160 764 6240 6370 149 2 SIP 133 6040 6180 134 6260 6380 150 2 BUD 131 6050 6210 132 6280 6435 151 1 AAQ 701 6065 6200 702 6270 6400 152 1 MRV 785 6070 6200 786 6280 6410 153 2 WAW 101 6115 6235 102 6300 6420 154 2 FRU 181 6125 6375 182 6470 6740 155 2 GYD 147 6130 6310 148 6435 6620 156 1 AER 869 6145 6290 870 6415 6555 157 2 EVN 193 6170 6350 194 6425 6595 158 1 KRR 765 6190 6320 766 6390 6520 159 1 AAQ 703 6280 6420 704 6500 6610 160 1 LED 845 6290 6380 846 6450 6535 161 1 KRR 767 6300 6435 768 6525 6655 162 2 KBP 183 6425 6520 184 6610 6700 163 2 AYT 223 6500 6690 224 6750 6940 164 1 AER 867 6510 6660 868 6730 6880 165 1 MRV 787 6515 6665 788 6745 6895 166 1 KRR 771 6570 6700 772 6790 6925 167 1 LED 849 6585 6660 850 6720 6855 168 2 IST 209 6640 6810 210 6880 7040 169 1 AER 873 6645 6790 874 7520 7660 170 1 ASF 711 6755 6905 712 7400 7555 171 2 ULN 563 6755 7095 564 7175 7575 172 2 OTP 151 6780 6935 152 7560 7700 173 2 BEY 509 6785 7025 510 7110 7340 174 2 OSL 211 6820 6980 212 7620 7775 175 2 KBP 185 6830 6930 186 7480 7570 176 1 IKT 739 6845 7180 740 7270 7630 177 1 KRR 773 6855 7000 774 7380 7525 178 1 SGC 877 6880 7075 878 7155 7385 179 1 LED 857 6910 6990 858 7370 7450 180 1 CEK 899 6990 7145 900 7215 7380 181 1 PEE 821 6995 7150 822 7210 7360 182 2 TBS 197 7000 7165 198 7320 7475 183 1 UFA 891 7035 7165 892 7235 7370 184 1 KJA 781 7060 7330 782 7440 7750 185 1 IKT 743 7395 7720 744 7810 8170 186 1 CEK 897 7405 7560 898 7630 7795 187 1 KRR 763 7460 7600 764 7680 7810 188 2 SIP 133 7480 7620 134 7700 7820 189 2 BUD 131 7490 7650 132 7720 7875 190 1 AAQ 701 7505 7640 702 7710 7840 191 1 MRV 785 7510 7640 786 7720 7850 192 2 IST 207 7545 7720 208 7795 7985 193 2 WAW 101 7555 7675 102 7740 7860 194 2 GYD 147 7570 7750 148 7875 8060 195 1 AER 869 7585 7730 870 7855 7995 196 2 AYT 221 7610 7800 222 7895 8085 197 2 EVN 193 7610 7790 194 7865 8035 198 1 KRR 765 7630 7760 766 7830 7960 199 1 AAQ 703 7720 7860 704 7940 8050 200 1 LED 845 7730 7820 846 7890 7975 201 1 KRR 767 7740 7875 768 7965 8095 202 2 KBP 183 7865 7960 184 8050 8140 203 2 AYT 223 7940 8130 224 8190 8380 204 1 MRV 787 7955 8105 788 8185 8335 205 1 KRR 771 8010 8140 772 8230 8365 206 1 LED 849 8025 8100 850 8160 8295 207 2 IST 209 8080 8250 210 8320 8480 208 1 AER 873 8085 8230 874 8960 9100 209 1 ASF 711 8195 8345 712 8840 8995 210 2 ULN 563 8195 8535 564 8615 9015 211 1 KJA 779 8230 8500 780 8575 8870 212 2 OSL 211 8260 8420 212 9060 9215 213 2 KBP 185 8270 8370 186 8920 9010 214 1 IKT 739 8285 8620 740 8710 9070 215 1 KRR 773 8295 8440 774 8820 8965 216 1 SGC 877 8320 8515 878 8595 8825 217 1 LED 857 8350 8430 858 8810 8890 218 1 CEK 899 8430 8585 900 8655 8820 219 1 PEE 821 8435 8590 822 8650 8800 220 2 TBS 197 8440 8605 198 8760 8915 221 1 UFA 891 8475 8605 892 8675 8810 222 1 KJA 781 8500 8770 782 8880 9190 223 1 IKT 743 8835 9160 744 9250 9610 224 1 OMS 815 8845 9045 816 9125 9340 225 1 CEK 897 8845 9000 898 9070 9235 226 1 KRR 763 8900 9040 764 9120 9250 227 2 SIP 133 8920 9060 134 9140 9260 228 2 BUD 131 8930 9090 132 9160 9315 229 1 AAQ 701 8945 9080 702 9150 9280 230 1 MRV 785 8950 9080 786 9160 9290 231 2 IST 207 8985 9160 208 9235 9425 232 2 WAW 101 8995 9115 102 9180 9300 233 2 FRU 181 9005 9255 182 9350 9620 234 2 GYD 147 9010 9190 148 9315 9500 235 1 AER 869 9025 9170 870 9295 9435 236 2 EVN 193 9050 9230 194 9305 9475 237 1 KRR 765 9070 9200 766 9270 9400 238 1 AAQ 703 9160 9300 704 9380 9490 239 1 LED 845 9170 9260 846 9330 9415 240 1 KRR 767 9180 9315 768 9405 9535 241 2 KBP 183 9305 9400 184 9490 9580 242 2 AYT 223 9380 9570 224 9630 9820 243 1 MRV 787 9395 9545 788 9625 9775 244 1 KRR 771 9450 9580 772 9670 9805 245 1 LED 849 9465 9540 850 9600 9735 246 2 IST 209 9520 9690 210 9760 9920 247 1 AER 873 9525 9670 874 10400 10540 248 1 ASF 711 9635 9785 712 10280 10435 249 2 ULN 563 9635 9975 564 10055 10455 250 2 OTP 151 9660 9815 152 10440 10580 251 2 DAM 517 9665 9905 518 9990 10220 252 2 OSL 211 9700 9860 212 10500 10655 253 2 KBP 185 9710 9810 186 10360 10450 254 1 IKT 739 9725 10060 740 10150 10510 255 1 KRR 773 9735 9880 774 10260 10405 256 1 SGC 877 9760 9955 878 10035 10265 257 1 LED 857 9790 9870 858 10250 10330 258 1 CEK 899 9870 10025 900 10095 10260 259 1 PEE 821 9875 10030 822 10090 10240 260 1 UFA 891 9915 10045 892 10115 10250 261 1 KJA 781 9940 10210 782 10320 10630 ; end; glpk-4.52.1/examples/todd.mod0000644000062000006210000000202512175147600015171 0ustar maomkpasswd/* TODD, a class of hard instances of zero-one knapsack problems */ /* Written in GNU MathProg by Andrew Makhorin */ /* Chvatal describes a class of instances of zero-one knapsack problems due to Todd. He shows that a wide class of algorithms - including all based on branch and bound or dynamic programming - find it difficult to solve problems in the Todd class. More exactly, the time required by these algorithms to solve instances of problems that belong to the Todd class grows as an exponential function of the problem size. Reference: Chvatal V. (1980), Hard knapsack problems, Op. Res. 28, 1402-1411. */ param n > 0 integer; param log2_n := log(n) / log(2); param k := floor(log2_n); param a{j in 1..n} := 2 ** (k + n + 1) + 2 ** (k + n + 1 - j) + 1; param b := 0.5 * floor(sum{j in 1..n} a[j]); var x{1..n} binary; maximize obj: sum{j in 1..n} a[j] * x[j]; s.t. cap: sum{j in 1..n} a[j] * x[j] <= b; data; param n := 15; /* change this parameter to choose a particular instance */ end; glpk-4.52.1/examples/train.mod0000644000062000006210000002623312175147600015363 0ustar maomkpasswd# TRAIN, a model of railroad passenger car allocation # # References: # Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language # for Mathematical Programming." Management Science 36 (1990) 519-554. ### SCHEDULE SETS AND PARAMETERS ### set cities; set links within {c1 in cities, c2 in cities: c1 <> c2}; # Set of cities, and set of intercity links param last > 0 integer; # Number of time intervals in a day set times := 1..last; # Set of time intervals in a day set schedule within {c1 in cities, t1 in times, c2 in cities, t2 in times: (c1,c2) in links}; # Member (c1,t1,c2,t2) of this set represents # a train that leaves city c1 at time t1 # and arrives in city c2 at time t2 ### DEMAND PARAMETERS ### param section > 0 integer; # Maximum number of cars in one section of a train param demand {schedule} > 0; # For each scheduled train: # the smallest number of cars that # can meet demand for the train param low {(c1,t1,c2,t2) in schedule} := ceil(demand[c1,t1,c2,t2]); # Minimum number of cars needed to meet demand param high {(c1,t1,c2,t2) in schedule} := max (2, min (ceil(2*demand[c1,t1,c2,t2]), section*ceil(demand[c1,t1,c2,t2]/section) )); # Maximum number of cars allowed on a train: # 2 if demand is for less than one car; # otherwise, lesser of # number of cars needed to hold twice the demand, and # number of cars in minimum number of sections needed ### DISTANCE PARAMETERS ### param dist_table {links} >= 0 default 0.0; param distance {(c1,c2) in links} > 0 := if dist_table[c1,c2] > 0 then dist_table[c1,c2] else dist_table[c2,c1]; # Inter-city distances: distance[c1,c2] is miles # between city c1 and city c2 ### VARIABLES ### var U 'cars stored' {cities,times} >= 0; # u[c,t] is the number of unused cars stored # at city c in the interval beginning at time t var X 'cars in train' {schedule} >= 0; # x[c1,t1,c2,t2] is the number of cars assigned to # the scheduled train that leaves c1 at t1 and # arrives in c2 at t2 ### OBJECTIVES ### minimize cars: sum {c in cities} U[c,last] + sum {(c1,t1,c2,t2) in schedule: t2 < t1} X[c1,t1,c2,t2]; # Number of cars in the system: # sum of unused cars and cars in trains during # the last time interval of the day minimize miles: sum {(c1,t1,c2,t2) in schedule} distance[c1,c2] * X[c1,t1,c2,t2]; # Total car-miles run by all scheduled trains in a day ### CONSTRAINTS ### account {c in cities, t in times}: U[c,t] = U[c, if t > 1 then t-1 else last] + sum {(c1,t1,c,t) in schedule} X[c1,t1,c,t] - sum {(c,t,c2,t2) in schedule} X[c,t,c2,t2]; # For every city and time: # unused cars in the present interval must equal # unused cars in the previous interval, # plus cars just arriving in trains, # minus cars just leaving in trains satisfy {(c1,t1,c2,t2) in schedule}: low[c1,t1,c2,t2] <= X[c1,t1,c2,t2] <= high[c1,t1,c2,t2]; # For each scheduled train: # number of cars must meet demand, # but must not be so great that unnecessary # sections are run ### DATA ### data; set cities := BO NY PH WA ; set links := (BO,NY) (NY,PH) (PH,WA) (NY,BO) (PH,NY) (WA,PH) ; param dist_table := [*,*] BO NY 232 NY PH 90 PH WA 135 ; param last := 48 ; param section := 14 ; set schedule := (WA,*,PH,*) 2 5 6 9 8 11 10 13 12 15 13 16 14 17 15 18 16 19 17 20 18 21 19 22 20 23 21 24 22 25 23 26 24 27 25 28 26 29 27 30 28 31 29 32 30 33 31 34 32 35 33 36 34 37 35 38 36 39 37 40 38 41 39 42 40 43 41 44 42 45 44 47 46 1 (PH,*,NY,*) 1 3 5 7 9 11 11 13 13 15 14 16 15 17 16 18 17 19 18 20 19 21 20 22 21 23 22 24 23 25 24 26 25 27 26 28 27 29 28 30 29 31 30 32 31 33 32 34 33 35 34 36 35 37 36 38 37 39 38 40 39 41 40 42 41 43 42 44 43 45 44 46 45 47 47 1 (NY,*,BO,*) 10 16 12 18 14 20 15 21 16 22 17 23 18 24 19 25 20 26 21 27 22 28 23 29 24 30 25 31 26 32 27 33 28 34 29 35 30 36 31 37 32 38 33 39 34 40 35 41 36 42 37 43 38 44 39 45 40 46 41 47 42 48 43 1 44 2 45 3 46 4 48 6 (BO,*,NY,*) 7 13 9 15 11 17 12 18 13 19 14 20 15 21 16 22 17 23 18 24 19 25 20 26 21 27 22 28 23 29 24 30 25 31 26 32 27 33 28 34 29 35 30 36 31 37 32 38 33 39 34 40 35 41 36 42 37 43 38 44 39 45 40 46 41 47 43 1 45 3 47 5 (NY,*,PH,*) 1 3 12 14 13 15 14 16 15 17 16 18 17 19 18 20 19 21 20 22 21 23 22 24 23 25 24 26 25 27 26 28 27 29 28 30 29 31 30 32 31 33 32 34 33 35 34 36 35 37 36 38 37 39 38 40 39 41 40 42 41 43 42 44 43 45 44 46 45 47 46 48 47 1 (PH,*,WA,*) 1 4 14 17 15 18 16 19 17 20 18 21 19 22 20 23 21 24 22 25 23 26 24 27 25 28 26 29 27 30 28 31 29 32 30 33 31 34 32 35 33 36 34 37 35 38 36 39 37 40 38 41 39 42 40 43 41 44 42 45 43 46 44 47 45 48 46 1 47 2 ; param demand := [WA,*,PH,*] 2 5 .55 6 9 .01 8 11 .01 10 13 .13 12 15 1.59 13 16 1.69 14 17 5.19 15 18 3.55 16 19 6.29 17 20 4.00 18 21 5.80 19 22 3.40 20 23 4.88 21 24 2.92 22 25 4.37 23 26 2.80 24 27 4.23 25 28 2.88 26 29 4.33 27 30 3.11 28 31 4.64 29 32 3.44 30 33 4.95 31 34 3.73 32 35 5.27 33 36 3.77 34 37 4.80 35 38 3.31 36 39 3.89 37 40 2.65 38 41 3.01 39 42 2.04 40 43 2.31 41 44 1.52 42 45 1.75 44 47 1.88 46 1 1.05 [PH,*,NY,*] 1 3 1.05 5 7 .43 9 11 .20 11 13 .21 13 15 .40 14 16 6.49 15 17 16.40 16 18 9.48 17 19 17.15 18 20 9.31 19 21 15.20 20 22 8.21 21 23 13.32 22 24 7.35 23 25 11.83 24 26 6.61 25 27 10.61 26 28 6.05 27 29 9.65 28 30 5.61 29 31 9.25 30 32 5.40 31 33 8.24 32 34 4.84 33 35 7.44 34 36 4.44 35 37 6.80 36 38 4.11 37 39 6.25 38 40 3.69 39 41 5.55 40 42 3.29 41 43 4.77 42 44 2.91 43 45 4.19 44 46 2.53 45 47 4.00 47 1 1.65 [NY,*,BO,*] 10 16 1.23 12 18 3.84 14 20 4.08 15 21 1.47 16 22 2.96 17 23 1.60 18 24 2.95 19 25 1.71 20 26 2.81 21 27 1.77 22 28 2.87 23 29 1.84 24 30 2.95 25 31 1.91 26 32 3.12 27 33 1.93 28 34 3.31 29 35 2.00 30 36 3.40 31 37 2.08 32 38 3.41 33 39 2.69 34 40 4.45 35 41 2.32 36 42 3.40 37 43 1.80 38 44 2.63 39 45 1.52 40 46 2.23 41 47 1.25 42 48 1.79 43 1 .97 44 2 1.28 45 3 .48 46 4 .68 48 6 .08 [BO,*,NY,*] 7 13 .03 9 15 1.29 11 17 4.59 12 18 2.56 13 19 3.92 14 20 2.37 15 21 3.81 16 22 2.24 17 23 3.51 18 24 2.13 19 25 3.28 20 26 2.05 21 27 3.15 22 28 1.99 23 29 3.09 24 30 1.93 25 31 3.19 26 32 1.91 27 33 3.21 28 34 1.85 29 35 3.21 30 36 1.71 31 37 3.04 32 38 2.08 33 39 3.13 34 40 1.96 35 41 2.53 36 42 1.43 37 43 2.04 38 44 1.12 39 45 1.71 40 46 .91 41 47 1.32 43 1 1.80 45 3 1.13 47 5 .23 [NY,*,PH,*] 1 3 .04 12 14 4.68 13 15 5.61 14 16 3.56 15 17 5.81 16 18 3.81 17 19 6.31 18 20 4.07 19 21 7.33 20 22 4.55 21 23 7.37 22 24 4.73 23 25 7.61 24 26 4.92 25 27 7.91 26 28 5.19 27 29 8.40 28 30 5.53 29 31 9.32 30 32 5.51 31 33 10.33 32 34 9.21 33 35 18.95 34 36 11.23 35 37 16.85 36 38 7.29 37 39 10.89 38 40 5.41 39 41 8.21 40 42 4.52 41 43 6.99 42 44 3.92 43 45 6.21 44 46 3.44 45 47 5.17 46 48 2.55 47 1 1.24 [PH,*,WA,*] 1 4 .20 14 17 4.49 15 18 3.53 16 19 2.67 17 20 3.83 18 21 3.01 19 22 4.12 20 23 3.15 21 24 4.67 22 25 3.20 23 26 4.23 24 27 2.87 25 28 3.84 26 29 2.60 27 30 3.80 28 31 2.77 29 32 4.31 30 33 3.16 31 34 4.88 32 35 3.45 33 36 5.55 34 37 3.52 35 38 6.11 36 39 3.32 37 40 5.53 38 41 3.03 39 42 4.51 40 43 2.53 41 44 3.39 42 45 1.93 43 46 2.52 44 47 1.20 45 48 1.75 46 1 .88 47 2 .87 ; end; glpk-4.52.1/examples/transp.mod0000644000062000006210000000264112175147600015552 0ustar maomkpasswd# A TRANSPORTATION PROBLEM # # This problem finds a least cost shipping schedule that meets # requirements at markets and supplies at factories. # # References: # Dantzig G B, "Linear Programming and Extensions." # Princeton University Press, Princeton, New Jersey, 1963, # Chapter 3-3. set I; /* canning plants */ set J; /* markets */ param a{i in I}; /* capacity of plant i in cases */ param b{j in J}; /* demand at market j in cases */ param d{i in I, j in J}; /* distance in thousands of miles */ param f; /* freight in dollars per case per thousand miles */ param c{i in I, j in J} := f * d[i,j] / 1000; /* transport cost in thousands of dollars per case */ var x{i in I, j in J} >= 0; /* shipment quantities in cases */ minimize cost: sum{i in I, j in J} c[i,j] * x[i,j]; /* total transportation costs in thousands of dollars */ s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i]; /* observe supply limit at plant i */ s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j]; /* satisfy demand at market j */ data; set I := Seattle San-Diego; set J := New-York Chicago Topeka; param a := Seattle 350 San-Diego 600; param b := New-York 325 Chicago 300 Topeka 275; param d : New-York Chicago Topeka := Seattle 2.5 1.7 1.8 San-Diego 2.5 1.8 1.4 ; param f := 90; end; glpk-4.52.1/examples/trick.mod0000644000062000006210000000433512175147600015361 0ustar maomkpasswd/* TRICK, A Transportation Design Problem */ /* Translated from the Mosel modeling language to GNU MathProg by Andrew Makhorin */ /* This example model is described in the article "Formulations and Reformulations in Integer Programming" by Michael Trick (it is publicly available at http://mat.gsia.cmu.edu/trick/formul04.pdf). This model demonstrates an amazing effect when including in the formulation an additional constraint, which is redundant even for LP relaxation, makes the model easy for solving with the B&B. */ set TRUCKS := 1..10; set PACKAGES := 1..20; param capacity{TRUCKS}; param size{PACKAGES}; param cost{TRUCKS}; param can_use{PACKAGES, TRUCKS}; var x{PACKAGES, TRUCKS}, binary; var y{TRUCKS}, binary; minimize total: sum{i in TRUCKS} cost[i] * y[i]; f1{i in TRUCKS}: sum{j in PACKAGES} size[j] * x[j,i] <= capacity[i] * y[i]; f2{i in TRUCKS, j in PACKAGES}: x[j,i] <= y[i]; f3{j in PACKAGES}: sum{i in TRUCKS} can_use[j,i] * x[j,i] = 1; redundant_constraint: sum{i in TRUCKS} capacity[i] * y[i] >= sum{j in PACKAGES} size[j]; data; param capacity := [1] 100 [2] 200 [3] 100 [4] 200 [5] 100 [6] 200 [7] 100 [8] 200 [9] 100 [10] 200; param size := [1] 17 [2] 21 [3] 54 [4] 45 [5] 87 [6] 34 [7] 23 [8] 45 [9] 12 [10] 43 [11] 54 [12] 39 [13] 31 [14] 26 [15] 75 [16] 48 [17] 16 [18] 32 [19] 45 [20] 55; param cost := [1] 1 [2] 1.8 [3] 1 [4] 1.8 [5] 1 [6] 1.8 [7] 1 [8] 1.8 [9] 1 [10] 1.8; param can_use (tr): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 := 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0 0 0 2 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 0 3 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 4 0 0 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 5 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 0 6 0 0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 7 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 8 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 9 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 10 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1; end; glpk-4.52.1/examples/tsp.mod0000644000062000006210000001501012175147600015043 0ustar maomkpasswd/* TSP, Traveling Salesman Problem */ /* Written in GNU MathProg by Andrew Makhorin */ /* The Traveling Salesman Problem (TSP) is stated as follows. Let a directed graph G = (V, E) be given, where V = {1, ..., n} is a set of nodes, E <= V x V is a set of arcs. Let also each arc e = (i,j) be assigned a number c[i,j], which is the length of the arc e. The problem is to find a closed path of minimal length going through each node of G exactly once. */ param n, integer, >= 3; /* number of nodes */ set V := 1..n; /* set of nodes */ set E, within V cross V; /* set of arcs */ param c{(i,j) in E}; /* distance from node i to node j */ var x{(i,j) in E}, binary; /* x[i,j] = 1 means that the salesman goes from node i to node j */ minimize total: sum{(i,j) in E} c[i,j] * x[i,j]; /* the objective is to make the path length as small as possible */ s.t. leave{i in V}: sum{(i,j) in E} x[i,j] = 1; /* the salesman leaves each node i exactly once */ s.t. enter{j in V}: sum{(i,j) in E} x[i,j] = 1; /* the salesman enters each node j exactly once */ /* Constraints above are not sufficient to describe valid tours, so we need to add constraints to eliminate subtours, i.e. tours which have disconnected components. Although there are many known ways to do that, I invented yet another way. The general idea is the following. Let the salesman sells, say, cars, starting the travel from node 1, where he has n cars. If we require the salesman to sell exactly one car in each node, he will need to go through all nodes to satisfy this requirement, thus, all subtours will be eliminated. */ var y{(i,j) in E}, >= 0; /* y[i,j] is the number of cars, which the salesman has after leaving node i and before entering node j; in terms of the network analysis, y[i,j] is a flow through arc (i,j) */ s.t. cap{(i,j) in E}: y[i,j] <= (n-1) * x[i,j]; /* if arc (i,j) does not belong to the salesman's tour, its capacity must be zero; it is obvious that on leaving a node, it is sufficient to have not more than n-1 cars */ s.t. node{i in V}: /* node[i] is a conservation constraint for node i */ sum{(j,i) in E} y[j,i] /* summary flow into node i through all ingoing arcs */ + (if i = 1 then n) /* plus n cars which the salesman has at starting node */ = /* must be equal to */ sum{(i,j) in E} y[i,j] /* summary flow from node i through all outgoing arcs */ + 1; /* plus one car which the salesman sells at node i */ solve; printf "Optimal tour has length %d\n", sum{(i,j) in E} c[i,j] * x[i,j]; printf("From node To node Distance\n"); printf{(i,j) in E: x[i,j]} " %3d %3d %8g\n", i, j, c[i,j]; data; /* These data correspond to the symmetric instance ulysses16 from: Reinelt, G.: TSPLIB - A travelling salesman problem library. ORSA-Journal of the Computing 3 (1991) 376-84; http://elib.zib.de/pub/Packages/mp-testdata/tsp/tsplib */ /* The optimal solution is 6859 */ param n := 16; param : E : c := 1 2 509 1 3 501 1 4 312 1 5 1019 1 6 736 1 7 656 1 8 60 1 9 1039 1 10 726 1 11 2314 1 12 479 1 13 448 1 14 479 1 15 619 1 16 150 2 1 509 2 3 126 2 4 474 2 5 1526 2 6 1226 2 7 1133 2 8 532 2 9 1449 2 10 1122 2 11 2789 2 12 958 2 13 941 2 14 978 2 15 1127 2 16 542 3 1 501 3 2 126 3 4 541 3 5 1516 3 6 1184 3 7 1084 3 8 536 3 9 1371 3 10 1045 3 11 2728 3 12 913 3 13 904 3 14 946 3 15 1115 3 16 499 4 1 312 4 2 474 4 3 541 4 5 1157 4 6 980 4 7 919 4 8 271 4 9 1333 4 10 1029 4 11 2553 4 12 751 4 13 704 4 14 720 4 15 783 4 16 455 5 1 1019 5 2 1526 5 3 1516 5 4 1157 5 6 478 5 7 583 5 8 996 5 9 858 5 10 855 5 11 1504 5 12 677 5 13 651 5 14 600 5 15 401 5 16 1033 6 1 736 6 2 1226 6 3 1184 6 4 980 6 5 478 6 7 115 6 8 740 6 9 470 6 10 379 6 11 1581 6 12 271 6 13 289 6 14 261 6 15 308 6 16 687 7 1 656 7 2 1133 7 3 1084 7 4 919 7 5 583 7 6 115 7 8 667 7 9 455 7 10 288 7 11 1661 7 12 177 7 13 216 7 14 207 7 15 343 7 16 592 8 1 60 8 2 532 8 3 536 8 4 271 8 5 996 8 6 740 8 7 667 8 9 1066 8 10 759 8 11 2320 8 12 493 8 13 454 8 14 479 8 15 598 8 16 206 9 1 1039 9 2 1449 9 3 1371 9 4 1333 9 5 858 9 6 470 9 7 455 9 8 1066 9 10 328 9 11 1387 9 12 591 9 13 650 9 14 656 9 15 776 9 16 933 10 1 726 10 2 1122 10 3 1045 10 4 1029 10 5 855 10 6 379 10 7 288 10 8 759 10 9 328 10 11 1697 10 12 333 10 13 400 10 14 427 10 15 622 10 16 610 11 1 2314 11 2 2789 11 3 2728 11 4 2553 11 5 1504 11 6 1581 11 7 1661 11 8 2320 11 9 1387 11 10 1697 11 12 1838 11 13 1868 11 14 1841 11 15 1789 11 16 2248 12 1 479 12 2 958 12 3 913 12 4 751 12 5 677 12 6 271 12 7 177 12 8 493 12 9 591 12 10 333 12 11 1838 12 13 68 12 14 105 12 15 336 12 16 417 13 1 448 13 2 941 13 3 904 13 4 704 13 5 651 13 6 289 13 7 216 13 8 454 13 9 650 13 10 400 13 11 1868 13 12 68 13 14 52 13 15 287 13 16 406 14 1 479 14 2 978 14 3 946 14 4 720 14 5 600 14 6 261 14 7 207 14 8 479 14 9 656 14 10 427 14 11 1841 14 12 105 14 13 52 14 15 237 14 16 449 15 1 619 15 2 1127 15 3 1115 15 4 783 15 5 401 15 6 308 15 7 343 15 8 598 15 9 776 15 10 622 15 11 1789 15 12 336 15 13 287 15 14 237 15 16 636 16 1 150 16 2 542 16 3 499 16 4 455 16 5 1033 16 6 687 16 7 592 16 8 206 16 9 933 16 10 610 16 11 2248 16 12 417 16 13 406 16 14 449 16 15 636 ; end; glpk-4.52.1/examples/xyacfs.mod0000644000062000006210000000302712175147600015537 0ustar maomkpasswd/*Extended Yet Another Curve Fitting Solution (The poor man's RMA) An extension of yacfs.mod adding a Weight parameter: When set to 1 the model produces best fit by least squares with all error in y and none in x (YonX); When set to zero the model produces best fit by least squares with all error in x and none in y (XonY); When set to 0.5 the model assumes equal error in x and y producing results similar to fitting by Reduced Major Axis Analysis. Nigel_Galloway@operamail.com November 5th., 2009 */ set Sample; param Sx {z in Sample}; param Sy {z in Sample}; param Weight := 0.5; var a; var b; var p; var q; XonY1 :sum{z in Sample} q*Sy[z]*Sy[z] + sum{z in Sample} p*Sy[z] = sum{z in Sample} Sy[z]*Sx[z]; XonY2 :sum{z in Sample} q*Sy[z] + sum{z in Sample} p = sum{z in Sample} Sx[z]; YonX1 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; YonX2 :sum{z in Sample} a*Sx[z] + sum{z in Sample} b = sum{z in Sample} Sy[z]; solve; param W := Weight*a + (1-Weight)*(1/q); printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", b*Weight - (1-Weight)*(p/q), if W < 0 then "-" else "+", abs(W); data; param: Sample: Sx Sy := 1 0 1 2 0.5 0.9 3 1 0.7 4 1.5 1.5 5 1.9 2 6 2.5 2.4 7 3 3.2 8 3.5 2 9 4 2.7 10 4.5 3.5 11 5 1 12 5.5 4 13 6 3.6 14 6.6 2.7 15 7 5.7 16 7.6 4.6 17 8.5 6 18 9 6.8 19 10 7.3 ; end; glpk-4.52.1/examples/yacfs.mod0000644000062000006210000000164512175147600015353 0ustar maomkpasswd/*Yet Another Curve Fitting Solution Obviously this solution produces the same answer as examples/cflsq.mod Nigel_Galloway@operamail.com February 1st., 2009 */ set Sample; param Sx {z in Sample}; param Sy {z in Sample}; var a; var b; equalz1 :sum{z in Sample} a*Sx[z]*Sx[z] + sum{z in Sample} b*Sx[z] = sum{z in Sample} Sy[z]*Sx[z]; equalz2 :sum{z in Sample} a*Sx[z] + sum{z in Sample} b = sum{z in Sample} Sy[z]; solve; printf "\nbest linear fit is:\n\ty = %f %s %fx\n\n", b, if a < 0 then "-" else "+", abs(a); data; param: Sample: Sx Sy := 1 0 1 2 0.5 0.9 3 1 0.7 4 1.5 1.5 5 1.9 2 6 2.5 2.4 7 3 3.2 8 3.5 2 9 4 2.7 10 4.5 3.5 11 5 1 12 5.5 4 13 6 3.6 14 6.6 2.7 15 7 5.7 16 7.6 4.6 17 8.5 6 18 9 6.8 19 10 7.3 ; end; glpk-4.52.1/examples/zebra.mod0000644000062000006210000001222012175147600015340 0ustar maomkpasswd/* ZEBRA, Who Owns the Zebra? */ /* Written in GNU MathProg by Andrew Makhorin */ ######################################################################## # The Zebra Puzzle is a well-known logic puzzle. # # It is often called "Einstein's Puzzle" or "Einstein's Riddle" # because it is said to have been invented by Albert Einstein as a boy, # with the common claim that Einstein said "only 2 percent of the # world's population can solve". It is also sometimes attributed to # Lewis Carroll. However, there is no known evidence for Einstein's or # Carroll's authorship. # # There are several versions of this puzzle. The version below is # quoted from the first known publication in Life International # magazine on December 17, 1962. # # 1. There are five houses. # 2. The Englishman lives in the red house. # 3. The Spaniard owns the dog. # 4. Coffee is drunk in the green house. # 5. The Ukrainian drinks tea. # 6. The green house is immediately to the right of the ivory house. # 7. The Old Gold smoker owns snails. # 8. Kools are smoked in the yellow house. # 9. Milk is drunk in the middle house. # 10. The Norwegian lives in the first house. # 11. The man who smokes Chesterfields lives in the house next to the # man with the fox. # 12. Kools are smoked in the house next to the house where the horse # is kept. # 13. The Lucky Strike smoker drinks orange juice. # 14. The Japanese smokes Parliaments. # 15. The Norwegian lives next to the blue house. # # Now, who drinks water? Who owns the zebra? # # In the interest of clarity, it must be added that each of the five # houses is painted a different color, and their inhabitants are of # different national extractions, own different pets, drink different # beverages and smoke different brands of American cigarettes. One # other thing: In statement 6, right means your right. # # (From Wikipedia, the free encyclopedia.) ######################################################################## set HOUSE := { 1..5 }; set COLOR := { "blue", "green", "ivory", "red", "yellow" }; set NATIONALITY := { "Englishman", "Japanese", "Norwegian", "Spaniard", "Ukranian" }; set DRINK := { "coffee", "milk", "orange_juice", "tea", "water" }; set SMOKE := { "Chesterfield", "Kools", "Lucky_Strike", "Old_Gold", "Parliament" }; set PET := { "dog", "fox", "horse", "snails", "zebra" }; var color{HOUSE, COLOR}, binary; c1{h in HOUSE}: sum{c in COLOR} color[h,c] = 1; c2{c in COLOR}: sum{h in HOUSE} color[h,c] = 1; var nationality{HOUSE, NATIONALITY}, binary; n1{h in HOUSE}: sum{n in NATIONALITY} nationality[h,n] = 1; n2{n in NATIONALITY}: sum{h in HOUSE} nationality[h,n] = 1; var drink{HOUSE, DRINK}, binary; d1{h in HOUSE}: sum{d in DRINK} drink[h,d] = 1; d2{d in DRINK}: sum{h in HOUSE} drink[h,d] = 1; var smoke{HOUSE, SMOKE}, binary; s1{h in HOUSE}: sum{s in SMOKE} smoke[h,s] = 1; s2{s in SMOKE}: sum{h in HOUSE} smoke[h,s] = 1; var pet{HOUSE, PET}, binary; p1{h in HOUSE}: sum{p in PET} pet[h,p] = 1; p2{p in PET}: sum{h in HOUSE} pet[h,p] = 1; /* the Englishman lives in the red house */ f2{h in HOUSE}: nationality[h,"Englishman"] = color[h,"red"]; /* the Spaniard owns the dog */ f3{h in HOUSE}: nationality[h,"Spaniard"] = pet[h,"dog"]; /* coffee is drunk in the green house */ f4{h in HOUSE}: drink[h,"coffee"] = color[h,"green"]; /* the Ukrainian drinks tea */ f5{h in HOUSE}: nationality[h,"Ukranian"] = drink[h,"tea"]; /* the green house is immediately to the right of the ivory house */ f6{h in HOUSE}: color[h,"green"] = if h = 1 then 0 else color[h-1,"ivory"]; /* the Old Gold smoker owns snails */ f7{h in HOUSE}: smoke[h,"Old_Gold"] = pet[h,"snails"]; /* Kools are smoked in the yellow house */ f8{h in HOUSE}: smoke[h,"Kools"] = color[h,"yellow"]; /* milk is drunk in the middle house */ f9: drink[3,"milk"] = 1; /* the Norwegian lives in the first house */ f10: nationality[1,"Norwegian"] = 1; /* the man who smokes Chesterfields lives in the house next to the man with the fox */ f11{h in HOUSE}: (1 - smoke[h,"Chesterfield"]) + (if h = 1 then 0 else pet[h-1,"fox"]) + (if h = 5 then 0 else pet[h+1,"fox"]) >= 1; /* Kools are smoked in the house next to the house where the horse is kept */ f12{h in HOUSE}: (1 - smoke[h,"Kools"]) + (if h = 1 then 0 else pet[h-1,"horse"]) + (if h = 5 then 0 else pet[h+1,"horse"]) >= 1; /* the Lucky Strike smoker drinks orange juice */ f13{h in HOUSE}: smoke[h,"Lucky_Strike"] = drink[h,"orange_juice"]; /* the Japanese smokes Parliaments */ f14{h in HOUSE}: nationality[h,"Japanese"] = smoke[h,"Parliament"]; /* the Norwegian lives next to the blue house */ f15{h in HOUSE}: (1 - nationality[h,"Norwegian"]) + (if h = 1 then 0 else color[h-1,"blue"]) + (if h = 5 then 0 else color[h+1,"blue"]) >= 1; solve; printf "\n"; printf "HOUSE COLOR NATIONALITY DRINK SMOKE PET\n"; for {h in HOUSE} { printf "%5d", h; printf{c in COLOR: color[h,c]} " %-6s", c; printf{n in NATIONALITY: nationality[h,n]} " %-11s", n; printf{d in DRINK: drink[h,d]} " %-12s", d; printf{s in SMOKE: smoke[h,s]} " %-12s", s; printf{p in PET: pet[h,p]} " %-6s", p; printf "\n"; } printf "\n"; end; glpk-4.52.1/INSTALL0000644000062000006210000001755412175147600012766 0ustar maomkpasswdINSTALLING GLPK ON YOUR COMPUTER ******************************** Unpacking the distribution file ------------------------------- The GLPK package (like all other GNU software) is distributed in the form of a packed archive. It is one file named `glpk-X.Y.tar.gz', where `X' is the major version number and `Y' is the minor version number; for example, the archive name might be `glpk-4.15.tar.gz'. In order to prepare the distribution for installation you should: 1. Copy the GLPK distribution file to a working directory. 2. Unpack the distribution file with the following command: gzip -d glpk-X.Y.tar.gz After unpacking the distribution file is automatically renamed to `glpk-X.Y.tar'. 3. Unarchive the distribution file with the following command: tar -x < glpk-X.Y.tar It automatically creates the subdirectory `glpk-X.Y' containing the GLPK distribution. Configuring the package ----------------------- After unpacking and unarchiving the GLPK distribution you should configure the package, i.e. automatically tune it for your platform. Normally, you should just `cd' to the directory `glpk-X.Y' and run the `configure' script, e.g. ./configure The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It also creates file `config.h' containing platform-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, a file `config.cache' that saves the results of its tests to speed up reconfiguring, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). Running `configure' takes about a few seconds. While it is running, it displays some messages that tell you what it is doing. If you don't want to see the messages, run `configure' with its standard output redirected to `dev/null'; for example, `./configure > /dev/null'. By default both static and shared versions of the GLPK library will be compiled. Compilation of the shared librariy can be turned off by specifying the `--disable-shared' option to `configure', e.g. ./configure --disable-shared If you encounter problems building the library try using the above option, because some platforms do not support shared libraries. The GLPK package has some optional features listed below. By default all these features are disabled. To enable a feature the corresponding option should be passed to the configure script. --with-gmp Enable using the GNU MP bignum library This feature allows the exact simplex solver to use the GNU MP bignum library. If it is disabled, the exact simplex solver uses the GLPK bignum module, which provides the same functionality as GNU MP, however, it is much less efficient. For details about the GNU MP bignum library see its web page at . --with-zlib Enable using the zlib data compression library This feature allows GLPK API routines and the stand-alone solver to read and write compressed data files performing compression and decompression "on the fly" (compressed data files are recognized by suffix `.gz' in the file name). It may be useful in case of large MPS files to save the disk space. For details about the zlib compression library see its web page at . --enable-dl The same as --enable-dl=ltdl --enable-dl=ltdl Enable shared library support (GNU) --enable-dl=dlfcn Enable shared library support (POSIX) Currently this feature is only needed to provide dynamic linking to ODBC and MySQL shared libraries (see below). For details about the GNU shared library support see the manual at . --enable-odbc Enable using ODBC table driver (libiodbc) --enable-odbc=unix Enable using ODBC table driver (libodbc) This feature allows transmitting data between MathProg model objects and relational databases accessed through ODBC. For more details about this feature see the supplement "Using Data Tables in the GNU MathProg Modeling Language" (doc/tables.*). --enable-mysql Enable using MySQL table driver (libmysql) This feature allows transmitting data between MathProg model objects and MySQL relational databases. For more details about this feature see the supplement "Using Data Tables in the GNU MathProg Modeling Language" (doc/tables.*). Compiling the package --------------------- Normally, you can compile (build) the package by typing the command: make It reads `Makefile' generated by `configure' and performs all necessary jobs. If you want, you can override the `make' variables CFLAGS and LDFLAGS like this: make CFLAGS=-O2 LDFLAGS=-s To compile the package in a different directory from the one containing the source code, you must use a version of `make' that supports `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If for some reason `configure' is not in the source code directory that you are configuring, then it will report that it can't find the source code. In that case, run `configure' with the option `--srcdir=DIR', where DIR is the directory that contains the source code. Some systems require unusual options for compilation or linking that the `configure' script does not know about. You can give `configure' initial values for variables by setting them in the environment. Using a Bourne-compatible shell, you can do that on the command line like this: CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure Or on systems that have the `env' program, you can do it like this: env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure Here are the `make' variables that you might want to override with environment variables when running `configure'. For these variables, any value given in the environment overrides the value that `configure' would choose: CC: C compiler program. The default is `cc'. INSTALL: Program used to install files. The default value is `install' if you have it, otherwise `cp'. For these variables, any value given in the environment is added to the value that `configure' chooses: DEFS: Configuration options, in the form `-Dfoo -Dbar ...'. LIBS: Libraries to link with, in the form `-lfoo -lbar ...'. Checking the package -------------------- To check the package, i.e. to run some tests included in the package, you can use the following command: make check Installing the package ---------------------- Normally, to install the GLPK package you should type the following command: make install By default, `make install' will install the package's files in `usr/local/bin', `usr/local/lib', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. Alternately, you can do so by consistently giving a value for the `prefix' variable when you run `make', e.g. make prefix=/usr/gnu make prefix=/usr/gnu install After installing you can remove the program binaries and object files from the source directory by typing `make clean'. To remove all files that `configure' created (`Makefile', `config.status', etc.), just type `make distclean'. The file `configure.ac' is used to create `configure' by a program called `autoconf'. You only need it if you want to remake `configure' using a newer version of `autoconf'. Uninstalling the package ------------------------ To uninstall the GLPK package, i.e. to remove all the package's files from the system places, you can use the following command: make uninstall ======================================================================== glpk-4.52.1/install-sh0000755000062000006210000003325512175147600013735 0ustar maomkpasswd#!/bin/sh # install - install a program, script, or datafile scriptversion=2011-11-20.07; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # 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 # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: glpk-4.52.1/ltmain.sh0000755000062000006210000105377412175147600013565 0ustar maomkpasswd # libtool (GNU libtool) 2.4 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, # 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --no-quiet, --no-silent # print informational messages (default) # --tag=TAG use configuration variables from tag TAG # -v, --verbose print more informational messages than default # --no-verbose don't print the extra informational messages # --version print version information # -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. When passed as first option, # `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.4 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . # GNU libtool home page: . # General help using GNU software: . PROGRAM=libtool PACKAGE=libtool VERSION=2.4 TIMESTAMP="" package_revision=1.3294 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # NLS nuisances: We save the old values to restore during execute mode. lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done LC_ALL=C LANGUAGE=C export LANGUAGE LC_ALL $lt_unset CDPATH # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" : ${CP="cp -f"} test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} : ${EGREP="/usr/bin/grep -E"} : ${FGREP="/usr/bin/grep -F"} : ${GREP="/usr/bin/grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="/usr/bin/sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_dirname may be replaced by extended shell implementation # func_basename file func_basename () { func_basename_result=`$ECHO "${1}" | $SED "$basename"` } # func_basename may be replaced by extended shell implementation # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # func_dirname_and_basename may be replaced by extended shell implementation # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname may be replaced by extended shell implementation # These SED scripts presuppose an absolute path with a trailing slash. pathcar='s,^/\([^/]*\).*$,\1,' pathcdr='s,^/[^/]*,,' removedotparts=':dotsl s@/\./@/@g t dotsl s,/\.$,/,' collapseslashes='s@/\{1,\}@/@g' finalslash='s,/*$,/,' # func_normal_abspath PATH # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. # value returned in "$func_normal_abspath_result" func_normal_abspath () { # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` while :; do # Processed it all yet? if test "$func_normal_abspath_tpath" = / ; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result" ; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_relative_path SRCDIR DSTDIR # generates a relative path from SRCDIR to DSTDIR, with a trailing # slash if non-empty, suitable for immediately appending a filename # without needing to append a separator. # value returned in "$func_relative_path_result" func_relative_path () { func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=${func_dirname_result} if test "x$func_relative_path_tlibdir" = x ; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test "x$func_stripname_result" != x ; then func_relative_path_result=${func_relative_path_result}/${func_stripname_result} fi # Normalisation. If bindir is libdir, return empty string, # else relative path ending with a slash; either way, target # file name can be directly appended. if test ! -z "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result/" func_relative_path_result=$func_stripname_result fi } # The name of this program: func_dirname_and_basename "$progpath" progname=$func_basename_result # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' # Sed substitution that converts a w32 file name or path # which contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname: ${opt_mode+$opt_mode: }$*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "$my_tmpdir" } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_tr_sh # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_version # Echo version message to standard output and exit. func_version () { $opt_debug $SED -n '/(C)/!b go :more /\./!{ N s/\n# / / b more } :go /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $opt_debug $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" echo $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help [NOEXIT] # Echo long help message to standard output and exit, # unless 'noexit' is passed as argument. func_help () { $opt_debug $SED -n '/^# Usage:/,/# Report bugs to/ { :print s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p d } /^# .* home page:/b print /^# General help using/b print ' < "$progpath" ret=$? if test -z "$1"; then exit $ret fi } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $opt_debug func_error "missing argument for $1." exit_cmd=exit } # func_split_short_opt shortopt # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. func_split_short_opt () { my_sed_short_opt='1s/^\(..\).*$/\1/;q' my_sed_short_rest='1s/^..\(.*\)$/\1/;q' func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` } # func_split_short_opt may be replaced by extended shell implementation # func_split_long_opt longopt # Set func_split_long_opt_name and func_split_long_opt_arg shell # variables after splitting LONGOPT at the `=' sign. func_split_long_opt () { my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^--[^=]*=//' func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` } # func_split_long_opt may be replaced by extended shell implementation exit_cmd=: magic="%%%MAGIC variable%%%" magic_exe="%%%MAGIC EXE variable%%%" # Global variables. nonopt= preserve_args= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "${1}=\$${1}\${2}" } # func_append may be replaced by extended shell implementation # func_append_quoted var value # Quote VALUE and append to the end of shell variable VAR, separated # by a space. func_append_quoted () { func_quote_for_eval "${2}" eval "${1}=\$${1}\\ \$func_quote_for_eval_result" } # func_append_quoted may be replaced by extended shell implementation # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "${@}"` } # func_arith may be replaced by extended shell implementation # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` } # func_len may be replaced by extended shell implementation # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_lo2o may be replaced by extended shell implementation # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_xform may be replaced by extended shell implementation # func_fatal_configuration arg... # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func_error ${1+"$@"} func_error "See the $PACKAGE documentation for more information." func_fatal_error "Fatal configuration error." } # func_config # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # Display the features supported by this script. func_features () { echo "host: $host" if test "$build_libtool_libs" = yes; then echo "enable shared libraries" else echo "disable shared libraries" fi if test "$build_old_libs" = yes; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag tagname # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname="$1" re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf="/$re_begincf/,/$re_endcf/p" # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Option defaults: opt_debug=: opt_dry_run=false opt_config=false opt_preserve_dup_deps=false opt_features=false opt_finish=false opt_help=false opt_help_all=false opt_silent=: opt_verbose=: opt_silent=false opt_verbose=false # Parse options once, thoroughly. This comes as soon as possible in the # script to make things like `--version' happen as quickly as we can. { # this just eases exit handling while test $# -gt 0; do opt="$1" shift case $opt in --debug|-x) opt_debug='set -x' func_echo "enabling shell trace mode" $opt_debug ;; --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) opt_config=: func_config ;; --dlopen|-dlopen) optarg="$1" opt_dlopen="${opt_dlopen+$opt_dlopen }$optarg" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) opt_features=: func_features ;; --finish) opt_finish=: set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help_all=: opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_mode="$optarg" case $optarg in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_silent=false func_append preserve_args " $opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $opt" ;; --silent|--quiet) opt_silent=: func_append preserve_args " $opt" opt_verbose=false ;; --verbose|-v) opt_verbose=: func_append preserve_args " $opt" opt_silent=false ;; --tag) test $# = 0 && func_missing_arg $opt && break optarg="$1" opt_tag="$optarg" func_append preserve_args " $opt $optarg" func_enable_tag "$optarg" shift ;; -\?|-h) func_usage ;; --help) func_help ;; --version) func_version ;; # Separate optargs to long options: --*=*) func_split_long_opt "$opt" set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-n*|-v*) func_split_short_opt "$opt" set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) set dummy "$opt" ${1+"$@"}; shift; break ;; esac done # Validate options: # save first non-option argument if test "$#" -gt 0; then nonopt="$opt" shift fi # preserve --debug test "$opt_debug" = : || func_append preserve_args " --debug" case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test "$opt_mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$opt_mode' for more information." } # Bail if the options were screwed $exit_cmd $EXIT_FAILURE } ## ----------- ## ## Main. ## ## ----------- ## # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case "$lt_sysroot:$1" in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result="=$func_stripname_result" ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$lt_sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $opt_debug # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result="" if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result" ; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $opt_debug if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $opt_debug # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $opt_debug if test -z "$2" && test -n "$1" ; then func_error "Could not determine host file name corresponding to" func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result="$1" fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $opt_debug if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " \`$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result="$3" fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $opt_debug case $4 in $1 ) func_to_host_path_result="$3$func_to_host_path_result" ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via `$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $opt_debug $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $opt_debug case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result="$1" } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result="$func_convert_core_msys_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $opt_debug func_to_host_file_result="$1" if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result="$func_cygpath_result" fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via `$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $opt_debug if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd="func_convert_path_${func_stripname_result}" fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $opt_debug func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result="$1" } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_msys_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $opt_debug func_to_host_path_result="$1" if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result="$func_cygpath_result" func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_mode_compile arg... func_mode_compile () { $opt_debug # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify \`-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" func_append_quoted lastarg "$arg" done IFS="$save_ifs" func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with \`-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj="$func_basename_result" } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from \`$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$opt_mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$opt_mode'" ;; esac echo $ECHO "Try \`$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test "$opt_help" = :; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | sed -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | sed '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$opt_mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "\`$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument \`$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and \`=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the \`-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the \`$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the \`$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test "$opt_mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test "x$prev" = x-m && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$opt_mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename="" if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname" ; then func_basename "$dlprefile_dlname" dlprefile_dlbasename="$func_basename_result" else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename" ; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $opt_debug sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $opt_debug match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive which possess that section. Heuristic: eliminate # all those which have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $opt_debug func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $opt_debug if func_cygming_gnu_implib_p "$1" ; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1" ; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result="" fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" if test "$lock_old_archive_extraction" = yes; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test "$lock_old_archive_extraction" = yes; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ which is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options which match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include /* declarations of non-ANSI functions */ #if defined(__MINGW32__) # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined(__CYGWIN__) # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined (other platforms) ... */ #endif /* portability defines, excluding path handling macros */ #if defined(_MSC_VER) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC # ifndef _INTPTR_T_DEFINED # define _INTPTR_T_DEFINED # define intptr_t int # endif #elif defined(__MINGW32__) # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined(__CYGWIN__) # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined (other platforms) ... */ #endif #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #if defined(LT_DEBUGWRAPPER) static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_emit_exe_manifest # emit a Win32 UAC manifest for executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_exe_manifest () { cat < EOF } # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $opt_debug case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir="$arg" prev= continue ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -{shared,static}-libgcc, -static-{libgfortran|libstdc++} # link against specified runtime library # -fstack-protector* stack protector flags for GCC -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-flto*|-fwhopr*|-fuse-linker-plugin| \ -shared-libgcc|-static-libgcc|-static-libgfortran|-static-libstdc++| \ -fstack-protector*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test "$prev" = dlfiles; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps ; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." else echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test "$prefer_static_libs" = yes || test "$prefer_static_libs,$installed" = "built,no"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib="$l" done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$lt_sysroot$libdir" absdir="$lt_sysroot$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later func_append notinst_path " $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi case "$host" in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test "$installed" = no; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$opt_mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$opt_mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system can not link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs="$temp_deplibs" fi func_append newlib_search_path " $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps ; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path="$deplib" ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. func_append verstring ":${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" func_append libobjs " $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$opt_mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test "X$deplibs_check_method" = "Xnone"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using \`nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$opt_mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_apped perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd1 in $cmds; do IFS="$save_ifs" # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test "$try_normal_branch" = yes \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=${output_objdir}/${output_la}.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$opt_mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$opt_mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " ${wl}-bind_at_load" func_append finalize_command " ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs="$new_libs" func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=no ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper $cwrapper.manifest; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then # Create the UAC manifests first if necessary (but the # manifest files must have executable permission regardless). case $output_name in *instal*|*patch*|*setup*|*update*) func_emit_exe_manifest > $cwrapper.manifest func_emit_exe_manifest > $output_path/$objdir/$output_name.exe.manifest chmod +x $cwrapper.manifest chmod +x $output_path/$objdir/$output_name.exe.manifest ;; esac $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then func_append oldobjs " $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test "x$bindir" != x ; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$opt_mode" = link || test "$opt_mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) func_append RM " $arg"; rmforce=yes ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then odir="$objdir" else odir="$dir/$objdir" fi func_basename "$file" name="$func_basename_result" test "$opt_mode" = uninstall && odir="$dir" # Remember odir for removal later, being careful to avoid duplicates if test "$opt_mode" = clean; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case "$opt_mode" in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test "$opt_mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.${objext}" func_append rmfiles " ${name}.manifest $objdir/${name}.manifest" if test "$fast_install" = yes && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name $objdir/lt-${name}.manifest" fi if test "X$noexename" != "X$name" ; then func_append rmfiles " $odir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$opt_mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 glpk-4.52.1/m4/0000755000062000006210000000000012175147600012241 5ustar maomkpasswdglpk-4.52.1/m4/libtool.m40000644000062000006210000104472712175147600014166 0ustar maomkpasswd# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, # Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, # Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 57 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # `#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test $lt_write_fail = 0 && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2010 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_REPLACE_SHELLFNS mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES # -------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test "$lt_cv_ld_force_load" = "yes"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script which will find a shell with a builtin # printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case "$ECHO" in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified).], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([${with_sysroot}]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and in which our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; haiku*) version_type=linux need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ F* | *Sun*Fortran*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global defined # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS="$save_LDFLAGS"]) if test "$lt_cv_irix_exported_symbol" = yes; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], [[If ld is used when linking, flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ func_to_tool_file "$lt_outputfile"~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case ${2} in .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case ${prev}${p} in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test "$pre_test_object_deps_done" = no; then case ${prev} in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" CFLAGS="$lt_save_CFLAGS" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) # ------------------------------------------------------ # In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and # '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. m4_defun([_LT_PROG_FUNCTION_REPLACE], [dnl { sed -e '/^$1 ()$/,/^} # $1 /c\ $1 ()\ {\ m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) } # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: ]) # _LT_PROG_REPLACE_SHELLFNS # ------------------------- # Replace existing portable implementations of several shell functions with # equivalent extended shell implementations where those features are available.. m4_defun([_LT_PROG_REPLACE_SHELLFNS], [if test x"$xsi_shell" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}"]) _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"}]) _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl func_split_long_opt_name=${1%%=*} func_split_long_opt_arg=${1#*=}]) _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac]) _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) fi if test x"$lt_shell_append" = xyes; then _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl func_quote_for_eval "${2}" dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) fi ]) # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine which file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS glpk-4.52.1/m4/ltoptions.m40000644000062000006210000002725612175147600014552 0ustar maomkpasswd# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, # Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) glpk-4.52.1/m4/ltsugar.m40000644000062000006210000001042412175147600014165 0ustar maomkpasswd# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) glpk-4.52.1/m4/ltversion.m40000644000062000006210000000125612175147600014534 0ustar maomkpasswd# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 3294 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4]) m4_define([LT_PACKAGE_REVISION], [1.3294]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4' macro_revision='1.3294' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) glpk-4.52.1/m4/lt~obsolete.m40000644000062000006210000001375612175147600015071 0ustar maomkpasswd# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) glpk-4.52.1/Makefile.am0000644000062000006210000000016712175147600013761 0ustar maomkpasswd## Process this file with automake to produce Makefile.in ## ACLOCAL_AMFLAGS=-I m4 SUBDIRS = src examples ## eof ## glpk-4.52.1/Makefile.in0000644000062000006210000005661112175147600013777 0ustar maomkpasswd# Makefile.in generated by automake 1.12.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ THANKS config.guess config.sub install-sh ltmain.sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ cscope distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src examples all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then rm -f stamp-h1; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done cscopelist-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist-recursive cscopelist cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ cscopelist-recursive ctags-recursive install-am install-strip \ tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-cscope \ clean-generic clean-libtool cscope cscopelist \ cscopelist-recursive ctags ctags-recursive dist dist-all \ dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-generic distclean-hdr \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-recursive uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glpk-4.52.1/missing0000755000062000006210000002370312175147600013325 0ustar maomkpasswd#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2012-01-06.18; # UTC # Copyright (C) 1996-2012 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, 'missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle 'PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file 'aclocal.m4' autoconf touch file 'configure' autoheader touch file 'config.h.in' autom4te touch the output file, or create a stub one automake touch all 'Makefile.in' files bison create 'y.tab.[ch]', if possible, from existing .[ch] flex create 'lex.yy.c', if possible, from existing .c help2man touch the output file lex create 'lex.yy.c', if possible, from existing .c makeinfo touch the output file yacc create 'y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running '$TOOL --version' or '$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified 'acinclude.m4' or '${configure_ac}'. You might want to install the Automake and Perl packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified '${configure_ac}'. You might want to install the Autoconf and GNU m4 packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified 'acconfig.h' or '${configure_ac}'. You might want to install the Autoconf and GNU m4 packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified 'Makefile.am', 'acinclude.m4' or '${configure_ac}'. You might want to install the Automake and Perl packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: '$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get '$1' as part of Autoconf from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: '$1' $msg. You should only need it if you modified a '.y' file. You may need the Bison package in order for those modifications to take effect. You can get Bison from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified a '.l' file. You may need the Flex package in order for those modifications to take effect. You can get Flex from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG=\${$#} case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the Help2man package in order for those modifications to take effect. You can get Help2man from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: '$1' is $msg. You should only need it if you modified a '.texi' or '.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy 'make' (AIX, DU, IRIX). You might want to install the Texinfo package or the GNU make package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; *) echo 1>&2 "\ WARNING: '$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the 'README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing '$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: glpk-4.52.1/NEWS0000644000062000006210000023005412175147600012424 0ustar maomkpasswdGLPK 4.52.1 (release date: Jul 28, 2013) This is a bug-fix release. A version information bug in Makefile.am was fixed. Thanks to Sebastien Villemot for bug report. GLPK 4.52 (release date: Jul 18, 2013) The clique cut generator was essentially reimplemented, and now it is able to process very large and/or dense conflict graphs. A simple rounding heuristic was added to the MIP optimizer. Some bugs were fixed in the proximity search heuristic routine. Thanks to Giorgio Sartor <0gioker0@gmail.com>. New command-line option '--proxy [nnn]' was added to glpsol to enable using the proximity search heuristic. A bug (incorrect processing of LI column indicator) was fixed in the mps format reading routine. Thanks to Charles Brixko for bug report. GLPK 4.51 (release date: Jun 19, 2013) Singleton and dense phases were implemented on computing LU-factorization with Gaussian elimination. The singleton phase is a feature that allows processing row and column singletons on initial elimination steps more efficiently. The dense phase is a feature used on final elimination steps when the active submatrix becomes relatively dense. It significantly reduces the time needed, especially if the active submatrix fits in CPU cache, and improves numerical accuracy due to full pivoting. The API routine glp_adv_basis that constructs advanced initial LP basis was replaced by an improved version, which (unlike the old version) takes into account numerical values of constraint coefficients. The proximity search heuristic for MIP was included in the GLPK integer optimizer glp_intopt. On API level the heuristic can be enabled by setting the parameter ps_heur in glp_iocp to GLP_ON. This feature is also available in the solver glpsol through command-line option '--proxy'. Many thanks to Giorgio Sartor <0gioker0@gmail.com> for contribution. A bug was fixed that caused numerical instability in the FPUMP heuristic. GLPK 4.50 (release date: May 24, 2013) A new version of LU-factorization routines were added. Currently this version provides the same functionality as the old one, however, the new version allows further improving. Old routines for FHV-factorization used to update the basis factorization were replaced by a new version conforming to the new version of LU-factorization. Some clarifications about using the name index routines were added. Thanks to Xypron for suggestion. Some typos were corrected in the MathProg language reference. Thanks to Jeffrey Kantor for report. A serious bug (out-of-range indexing error) was *tentatively* fixed in the routine glp_relax4. Unfortunatly, this bug is inherited from the original Fortran version of the RELAX-IV code (for details please see ChangeLog), and since the code is very intricate, the bug is still under investigation. Thanks to Sylvain Fournier for bug report. GLPK 4.49 (release date: Apr 16, 2013) The new API routine glp_mincost_relax4, which is a driver to relaxation method of Bertsekas and Tseng (RELAX-IV), was added to the package. RELAX-IV is a code for solving minimum cost flow problems. On large instances it is 100-1000 times faster than the standard primal simplex method. Prof. Bertsekas, the author of the original RELAX-IV Fortran code, kindly permitted to include a C translation of his code in GLPK under GPLv3. A bug (wrong dual feasibility test) was fixed in API routine glp_warm_up. Thanks to David T. Price for bug report. Obsolete API routine lpx_check_kkt was replaced by new routine glp_check_kkt. IMPORTANT: All old API routines whose names begin with 'lpx_' were removed from API level and NO MORE AVAILABLE. GLPK 4.48 (release date: Jan 28, 2013) This is a maintainer release. Some minor changes in API (glpk.h) were made. For details please see ChangeLog. Some bugs/typos were fixed. Thanks to Raniere Gaia Costa da Silva, Heinrich Schuchardt , and Robbie Morrison for reports. GLPK 4.47 (release date: Sep 09, 2011) The new API routine glp_intfeas1 was added to the package. This routine is a tentative implementation of the integer (0-1) feasibility solver based on the CNF-SAT solver (which currently is MiniSat). It may be used in the same way as glp_intopt to find either any integer feasible solution or a solution, for which the objective function is not worse than the specified value. Detailed description of this routine can be found in the document "CNF Satisfiability Problem", which is included in the distribution (see doc/cnfsat.pdf). The following two options were added to glpsol: --minisat translate 0-1 feasibility problem to CNF-SAT problem and solve it with glp_intfeas1/MiniSat (if the problem instance is already in CNF-SAT format, no translation is performed) --objbnd bound add inequality obj <= bound (minimization) or obj >= bound (maximization) to 0-1 feasibility problem (this option assumes --minisat) The paint-by-numbers puzzle model (pbn.mod) included in the distribution is a nice example of the 0-1 feasibility problem, which can be efficiently solved with glp_intfeas1/MiniSat. This model along with a brief instruction (pbn.pdf) and benchmark examples from encoded in GNU MathProg (*.dat) can be found in subdirectory examples/pbn/. The glpsol lp/mip solver was modified to bypass postprocessing of MathProg models if the solution reported is neither optimal nor feasible. A minor bug in examples/Makefile.am was fixed to correctly build glpk in a separate directory. Thanks to Marco Atzeri for bug report and patch. GLPK 4.46 (release date: Aug 09, 2011) The following new API routines were added: glp_read_cnfsat read CNF-SAT problem data in DIMACS format glp_check_cnfsat check for CNF-SAT problem instance glp_write_cnfsat write CNF-SAT problem data in DIMACS format glp_minisat1 solve CNF-SAT problem instance with MiniSat The routine glp_minisat1 is a driver to MiniSat, a CNF-SAT solver developed by Niklas Een and Niklas Sorensson, Chalmers University of Technology, Sweden. This routine is similar to the routine glp_intopt, however, it is intended to solve a 0-1 programming problem instance, which is the MIP translation of a CNF-SAT problem instance. Detailed description of these new API routines can be found in the document "CNF Satisfiability Problem", which is included in the distribution (see files doc/cnfsat.tex and doc/cnfsat.pdf). The following new glpsol command-line options were added: --cnf filename read CNF-SAT problem instance in DIMACS format from filename and translate it to MIP --wcnf filename write CNF-SAT problem instance in DIMACS format to filename --minisat solve CNF-SAT problem instance with MiniSat solver The zlib compression library (version 1.2.5) was ANSIfied, modified according to GLPK requirements and included in the distribution as an external software module. Thus, now this feature is platform independent. Some bugs were fixed in the SQL table driver. Thanks to Xypron . GLPK 4.45 (release date: Dec 05, 2010) This is a bug-fix release. Several bugs/typos were fixed. Thanks to Xypron , Robbie Morrison , and Ali Baharev for reports. Some glpk documents was re-formatted and merged into a single document. Now the glpk documentation consists of the following three main documents (all included in the distribution): GLPK: Reference Manual GLPK: Graph and Network Routines Modeling Language GNU MathProg: Language Reference GLPK 4.44 (release date: Jun 03, 2010) The following suffixes for variables and constraints were implemented in the MathProg language: .lb (lower bound), .ub (upper bound), .status (status in the solution), .val (primal value), and .dual (dual value). Thanks to Xypron for draft implementation and testing. Now the MathProg language allows comment records (marked by '#' in the very first position) in CSV data files read with the table statements. Note that the comment records may appear only in the beginning of a CSV data file. The API routine glp_cpp to solve the Critical Path Problem was added and documented. GLPK 4.43 (release date: Feb 20, 2010) This is a maintainer release. `configure.ac' was changed to allow building the package under Mac OS and Darwin with ODBC support. Thanks to Xypron for suggestions and Noli Sicad for testing. The SQL table driver was improved to process NULL data. Thanks to Xypron . Some bugs were fixed in the LP/MIP preprocessor. GLPK 4.42 (release date: Jan 13, 2010) The following new API routines were added: glp_check_dup check for duplicate elements in sparse matrix glp_sort_matrix sort elements of the constraint matrix glp_read_prob read problem data in GLPK format glp_write_prob write problem data in GLPK format glp_analyze_bound analyze active bound of non-basic variable glp_analyze_coef analyze objective coefficient at basic variable glp_print_ranges print sensitivity analysis report (this routine replaces lpx_print_sens_bnds and makes it deprecated) For description of these new routines and the GLPK LP/MIP format see a new edition of the reference manual included in the distribution. (Chapter "Graph and network API routines" was carried out from the main reference manual and included in the distribution as a separate document.) The following new command-line options were added to the stand- alone solver glpsol: --glp filename read problem data in GLPK format --wglp filename write problem data in GLPK format --ranges filename print sensitivity analysis report (this option replaces --bounds) Now all GLPK routines performing file I/O support special filenames "/dev/stdin", "/dev/stdout", and "/dev/stderr", which can be specified in the same way as regular filenames. This feature is plaform-independent. GLPK 4.41 (release date: Dec 21, 2009) The following new API routies were added: glp_transform_row transform explicitly specified row glp_transform_col transform explicitly specified column glp_prim_rtest perform primal ratio test glp_dual_rtest perform dual ratio test For description of these new routines see a new edition of the reference manual included in the distribution. The following API routines are deprecated: lpx_transform_row, lpx_transform_col, lpx_prim_ratio_test, lpx_dual_ratio_test. Some improvements were made in the MIP solver (glp_intopt). The SQL table driver used to read/write data in MathProg models was changed to allow multiple arguments separated by semicolon in SQL statements. Thanks to Xypron . Two new options were added to the glpsol stand-alone solver: --seed value (to initialize the pseudo-random number generator used in MathProg models with specified value), and --ini filename (to use a basis previously saved with -w option as an initial basis on solving similar LP's). Two new MathProg example models were included. Thanks to Nigel Galloway and Noli Sicad for contribution. Scripts to build GLPK with Microsoft Visual Studio 2010 for both 32-bit and 64-bit Windows were included. Thanks to Xypron for contribution and testing. GLPK 4.40 (release date: Nov 03, 2009) The following new API routines were added: glp_del_vertices remove vertices from graph glp_del_arc remove arc from graph glp_wclique_exact find maximum weight clique with the exact algorithm developed by Prof. P. Ostergard glp_read_ccdata read graph in DIMACS clique/coloring format glp_write_ccdata write graph in DIMACS clique/coloring format For description of these new routines see a new edition of the reference manual included in the distribution. The hybrid pseudocost branching heuristic was included in the MIP solver. It is available on API level (iocp.br_tech should be set to GLP_BR_PCH) and in the stand-alone solver glpsol (via the command-line option --pcost). This heuristic may be useful on solving hard MIP instances. The branching heuristic by Driebeck and Tomlin (used in the MIP solver by default) was changed to switch to branching on most fractional variable if an lower bound of degradation of the objective is close to zero for all branching candidates. A bug was fixed in the LP preprocessor (routine npp_empty_col). Thanks to Stefan Vigerske for the bug report. A bug was fixed and some improvements were made in the FPUMP heuristic module. Thanks to Xypron . A bug was fixed in the API routine glp_warm_up (dual feasibility test was incorrect in maximization case). Thanks to Uday Venkatadri for the bug report. GLPK 4.39 (release date: Jul 26, 2009) The following new API routines were added: glp_warm_up "warm up" LP basis glp_set_vertex_name assign (change) vertex name glp_create_v_index create vertex name index glp_find_vertex find vertex by its name glp_delete_v_index delete vertex name index glp_read_asnprob read assignment problem data in DIMACS format glp_write_asnprob write assignment problem data in DIMACS format glp_check_asnprob check correctness of assignment problem data glp_asnprob_lp convert assignment problem to LP glp_asnprob_okalg solve assignment problem with the out-of-kilter algorithm glp_asnprob_hall find bipartite matching of maxumum cardinality with Hall's algorithm Also were added some API routines to read plain data files. The API routines glp_read_lp and glp_write_lp to read/write files in CPLEX LP format were re-implemented. Now glp_write_lp correctly writes double-bounded (ranged) rows by introducing slack variables rather than by duplicating the rows. For description of these new routines see a new edition of the reference manual included in the distribution. The 'xfree(NULL)' bug was fixed in the AMD routines. Thanks to Niels Klitgord for bug report. The message "Crashing..." was changed to "Constructing initial basis..." due to suggestion by Thomas Kahle . Some typos were corrected in glpsol output messages. Thanks to Xypron for patch. GLPK 4.38 (release date: May 02, 2009) API routines glp_read_mps and glp_write_mps were improved. Some improvements were made in the dual simplex routines. Two external software modules AMD and COLAMD were included in the distribution (for more details please see src/amd/README and src/colamd/README). Now they are used in the interior-point solver to reorder the matrix prior to Cholesky factorization. API routine glp_ipt_status may return two new statuses due to changes in the routine glp_interior. For details please see the reference manual included in the distribution. A minor bug was fixed in the graph/network routines. Thanks to Nelson H. F. Beebe for bug report. GLPK 4.37 (release date: Mar 29, 2009) The 0-1 Feasibility Pump heuristic was included in the GLPK integer optimizer glp_intopt. On API level the heuristic can be enabled by setting the parameter fp_heur in glp_iocp to GLP_ON. This feature is also available in the solver glpsol through command-line option '--fpump'. For more details please see the reference manual included in the distribution. The following new API routines were added: glp_print_sol write basic solution in printable format glp_print_ipt write interior-point solution in printable format glp_print_mip write MIP solution in printable format glp_read_graph read (di)graph from plain text file glp_write_graph write (di)graph to plain text file glp_weak_comp find all weakly connected components glp_strong_comp find all strongly connected components The following API routines are deprecated: lpx_print_sol, lpx_print_ips, lpx_print_mip, lpx_print_prob (the latter is equivalent to glp_write_lp). A bug was fixed in the interior-point solver (glp_interior) to correctly compute dual solution components when the problem is scaled. The files configure.ac and Makefile.am were changed: (a) to allow using autoreconf/autoheader; (b) to allow building the package in a directory other than its source directory. Thanks to Marco Atzeri for bug report. An example model in the GNU MathProg language was added. Thanks to Larry D'Agostino for contribution. GLPK 4.36 (release date: Feb 06, 2009) The following new API routines were added to the package: glp_mincost_okalg find minimum-cost flow with out-of-kilter algorithm glp_maxflow_ffalg find maximal flow with Ford-Fulkerson algorithm For detailed description of these new routines and related data structures see chapter "Graph and Network API Routines" in a new edition of the reference manual included in the distribution. The following two new command-line options were added to the solver glpsol: --mincost read min-cost flow data in DIMACS format --maxflow read maximum flow data in DIMACS format Duplicate symbols in the header glpk.h were removed to allow using swig. Thanks to Kelly Westbrooks and Nigel Galloway for suggestion. A minor defect was fixed in the routine glp_write_lp. Thanks to Sebastien Briais for bug report. A minor bug was fixed in the SQL module. Thanks to Xypron for patch. Some new example models in the GNU MathProg modeling language were added. Thanks to Sebastian Nowozin and Nigel Galloway for contribution. GLPK 4.35 (release date: Jan 09, 2009) The following new API routines were added to the package: glp_create_graph create graph glp_set_graph_name assign (change) graph name glp_add_vertices add new vertices to graph glp_add_arc add new arc to graph glp_erase_graph erase graph content glp_delete_graph delete graph glp_read_mincost read minimum cost flow problem data in DIMACS format glp_write_mincost write minimum cost flow problem data in DIMACS format glp_mincost_lp convert minimum cost flow problem to LP glp_netgen Klingman's network problem generator glp_gridgen grid-like network problem generator glp_read_maxflow read maximum flow problem data in DIMACS format glp_write_maxflow write maximum flow problem data in DIMACS format glp_maxflow_lp convert maximum flow problem to LP glp_rmfgen Goldfarb's maximum flow problem generator For detailed description of these new routines and related data structures see chapter "Graph and Network API Routines" in a new edition of the reference manual included in the distribution. A minor change were made in the internal routine xputc. Thanks to Luiz Bettoni for suggestion. A minor bug was fixed in the internal routine mpl_fn_time2str. Thanks to Stefan Vigerske for bug report. GLPK 4.34 (release date: Dec 04, 2008) The GNU MathProg modeling language was supplemented with three new built-in functions: gmtime obtaining current calendar time str2time converting character string to calendar time time2str converting calendar time to character string (Thanks to Xypron .) For detailed description of these functions see Appendix A in the document "Modeling Language GNU MathProg", a new edition of which was included in the distribution. A bug was fixed in the MIP solver. Thanks to Nigel Galloway for bug report. A new makefile was added to build the GLPK DLL with Microsoft Visual Studio Express 2008 for 64-bit Windows. Thanks to Xypron for contribution and testing. GLPK 4.33 (release date: Oct 30, 2008) The following new API routines were added to the package: glp_copy_prob copy problem object content glp_exact solve LP in exact arithmetic (makes lpx_exact deprecated) glp_get_unbnd_ray determine variable causing unboundedness (makes lpx_get_ray_info deprecated) glp_interior solve LP with interior-point method (makes lpx_interior deprecated) The following new API routines for processing models written in the GNU Mathprog language were added to the package: glp_mpl_alloc_wksp allocate the translator workspace glp_mpl_read_model read and translate model section glp_mpl_read_data read and translate data section glp_mpl_generate generate the model glp_mpl_build_prob build LP/MIP instance from the model glp_mpl_postsolve postsolve the model glp_mpl_free_wksp deallocate the translator workspace (These routines make lpx_read_model deprecated.) For description of all these new API routines see the reference manual included in the distribution. A crude implementation of CPLEX-like interface to GLPK API was added to the package. Currently it allows using GLPK as a core LP solver for Concorde, a well known computer code for solving the symmetric TSP. For details see examples/cplex/README. Some bugs were fixed in the SQL table driver. Thanks to Xypron . GLPK 4.32 (release date: Oct 03, 2008) The following new features were included in the MIP solver (the API routine glp_intopt): * MIP presolver * mixed cover cut generator * clique cut generator * Euclidean reduction of the objective value Due to changes the routine glp_intopt may additionally return GLP_ENOPFS, GLP_ENODFS, and GLP_EMIPGAP. The API routines lpx_integer are lpx_intopt are deprecated, since they are completely superseded by glp_intopt. The following new branch-and-cut API routines were added: glp_ios_row_attr determine additional row attributes glp_ios_pool_size determine current size of the cut pool glp_ios_add_row add constraint to the cut pool glp_ios_del_row delete constraint from the cut pool glp_ios_clear_pool delete all constraints from the cut pool For description of these new routines see the reference manual included in the distribution. The stand-alone solver glpsol was changed to allow multiple data files. A new edition of the supplement "Using Data Tables in the GNU MathProg Modeling Language" was included. As usual, some bugs were fixed (in the MathProg translator). Thanks to Xypron . GLPK 4.31 (release date: Sep 02, 2008) The core LP solver based on the dual simplex method was re-implemented and now it provides both phases I and II. The following new API routines were added: glp_scale_prob automatic scaling of problem data glp_std_basis construct standard initial LP basis glp_adv_basis construct advanced initial LP basis glp_cpx_basis construct Bixby's initial LP basis For description of these new routines see the reference manual included in the distribution. The following API routines are deprecated: lpx_scale_prob, lpx_std_basis, lpx_adv_basis, lpx_cpx_basis. Necessary changes were made in memory allocation routines to resolve portability issues for 64-bit platforms. New version of the routine lpx_write_pb to write problem data in OPB (pseudo boolean format) was added to the package. Thanks to Oscar Gustafsson for the contribution. Two new makefiles were added to build the package for 32- and 64-bit Windows with Microsoft Visual Studio Express 2008. Thanks to Heinrich Schuchardt (aka Xypron) for the contribution and testing. Two new makefiles were added to build the package with Digital Mars C/C++ 8.50 and Open Watcom C/C++ 1.6 (for 32-bit Windows). GLPK 4.30 (release date: Aug 13, 2008) The core LP solver based on the primal simplex method was re-implemented to allow its further improvements. Currently the new version provides the same features as the old one, however, it is a bit faster and more numerically stable. Some changes were made in the MathProg translator to allow <, <=, >=, and > on comparing symbolic values. Thanks to Heinrich Schuchardt for patches. Internal routine set_d_eps in the exact LP solver was changed to prevent approximation errors in case of integral data. Thanks to Markus Pilz for bug report. GLPK 4.29 (release date: Jul 06, 2008) The configure script was changed to disable all optional features by default. For details please see file INSTALL. The following new API routines were added: glp_erase_prob erase problem object content glp_read_mps read problem data in MPS format glp_write_mps write problem data in MPS format glp_read_lp read problem data in CPLEX LP format glp_write_lp write problem data in CPLEX LP format For description of these new routines see the reference manual included in the distribution. The following API routines are deprecated: lpx_read_mps, lpx_read_freemps, lpx_write_mps, lpx_write_freemps, lpx_read_cpxlp, and lpx_write_cpxlp. Two bugs were fixed. Thanks to Anne-Laurence Putz and Xypron for bug report. GLPK 4.28 (release date: Mar 25, 2008) The iODBC and MySQL table drivers, which allows transmitting data between MathProg model objects and relational databases, were re-implemented to replace a static linking by a dynamic linking to corresponding shared libraries. Many thanks to Heinrich Schuchardt for the contribution, Rafael Laboissiere for useful advices concerning the shared library support under GNU/Linux, and Vijay Patil for testing this feature under Windows XP. A new optional feature was added to the package. This feature is based on the zlib data compression library and allows GLPK API routines and the stand-alone solver to read and write compressed data files performing compression/decompression "on the fly" (compressed data files are recognized by suffix `.gz' in the file name). It may be useful in case of large MPS files to save the disk space (up to ten times). The `configure' script was re-implemented. Now it supports the following specific options: --with-gmp Enable using the GNU MP bignum library --without-gmp Disable using the GNU MP bignum library --with-zlib Enable using the zlib data compression library --without-zlib Disable using the zlib data compression library --enable-dl Enable shared library support (auto check) --enable-dl=ltdl Enable shared library support (GNU) --enable-dl=dlfcn Enable shared library support (POSIX) --disable-dl Disable shared library support --enable-odbc Enable using ODBC table driver --disable-odbc Disable using ODBC table driver --enable-mysql Enable using MySQL table driver --disable-mysql Disable using MySQL table driver For more details please see file INSTALL. GLPK 4.27 (release date: Mar 02, 2008) Three new table drivers were added to the MathProg translator: xBASE built-in table driver, which allows reading and writing data in .dbf format (only C and N fields are supported); MySQL table driver, which provides connection to a MySQL database; iODBC table driver, which provides connection to a database through ODBC. The MySQL and iODBC table drivers were contributed to GLPK by Heinrich Schuchardt . The table driver is a program module which allows transmitting data between MathProg model objects and external data tables. For detailed description of the table statement and table drivers see the document "Using Data Tables in the GNU MathProg Modeling Language" (file doc/tables.txt) included in the distribution. Some examples which demonstrate using MySQL and iODBC table drivers can be found in subdirectory examples/sql. GLPK 4.26 (release date: Feb 17, 2008) The table statement was implemented in the GNU MathProg modeling language. This new feature allows reading data from external tables into model objects such as sets and parameters as well as writing results of computations to external tables. A table is a (unordered) set of records, where each record consists of the same number of fields, and each field is provided with a unique symbolic name called the field name. Currently the GLPK package has the only built-in table driver, which supports tables in the CSV (comma-separated values) file format. This format is very simple and supported by almost all spreadsheets and database management systems. Detailed description of the table statement and CSV format can be found in file doc/tables.txt, included in the distribution. GLPK 4.25 (release date: Dec 19, 2007) A tentative implementation of Gomory's mixed integer cuts was included in the branch-and-cut solver. To enable generating Gomory's cuts the control parameter gmi_cuts passed to the routine glp_intopt should be set to GLP_ON. This feature is also available in the solver glpsol through command-line option '--gomory'. For more details please see the reference manual included in the distribution. GLPK 4.24 (release date: Nov 21, 2007) A tentative implementation of MIR (mixed integer rounding) cuts was included in the MIP solver. To enable generating MIR cuts the control parameter mir_cuts passed to the routine glp_intopt should be set to GLP_ON. This feature is also available in the stand-alone solver glpsol via command-line option '--mir'. For more details please see the reference manual included in the distribution. The implementation is mainly based on the following two papers: 1. H. Marchand and L. A. Wolsey. Aggregation and mixed integer rounding to solve MIPs. CORE discussion paper 9839, CORE, Universite catholique de Louvain, June 1998. 2. G. Andreello, A. Caprara, and M. Fischetti. Embedding cuts in a Branch&Cut framework. Preliminary draft, October 2003. MIR cuts can be generated on any level of the search tree that makes the GLPK MIP solver to be a real branch-and-cut solver. A bug was fixed in the routine lpx_write_cpxlp. If a variable x has upper bound and no lower bound, it should appear in the bounds section as "-inf <= x <= u", not as "x <= u". Thanks to Enric Rodriguez for the bug report. GLPK 4.23 (release date: Oct 28, 2007) The following new API routines were added: glp_read_sol read basic solution from text file glp_write_sol write basic solution to text file glp_read_ipt read interior-point solution from text file glp_write_ipt write interior-point solution to text file glp_read_mip read MIP solution from text file glp_write_mip write MIP solution to text file For description of these routines and corresponding file formats see Chapter "API Routines", Section "Utility routines" in the reference manual included in the distribution. Advanced API routine glp_free_env was added. It may be used by the application program to free all resources allocated by GLPK routines. The following three new command-line options were added to the solver glpsol: --mipgap tol set relative MIP gap tolerance -r filename read solution from filename -w filename write solution to filename GLPK 4.22 (release date: Sep 19, 2007) This is a maintainer release. A bug was fixed in the MIP preprocessor (ios_preprocess_node). Thanks to Roberto Bagnara (Department of Mathematics, University of Parma, Italy) for the bug report. A bug was fixed in the MIP preprocessor (col_implied_bounds), due to which constraint coefficients with small magnitude could lead to wrong implied bounds of structural variables. A similar bug was fixed in the routine reduce_bounds. A bug was fixed in the routines glp_set_mat_row and glp_set_mat_col. (The bug appeared due to incorrect removing zero elements from the row/column lists.) A bug was fixed in the API routines lpx_read_mps and lpx_read_freemps, due to which bounds of type LI specified in BOUNDS section were incorrectly processed. A call to standard function vsprintf was replaced by a call to vsnprintf for security reasons. Many thanks to Peter T. Breuer and Rafael Laboissiere . GLPK 4.21 (release date: Aug 28, 2007) Additional reasons for calling the callback routine used in the MIP solver (glp_intopt) were introduced. Currently the following reasons are supported: * request for subproblem selection * request for preprocessing * request for row generation * request for heuristic solution * request for cut generation * request for branching * better integer solution found A basic preprocessing component used to improve subproblem formulations by tightening bounds of variables was included in the MIP solver. Depending on the control parameter pp_tech passed to the routine glp_intopt the preprocessing can be performed either on the root level or on all levels (default) or can be disabled. Backtracking heuristic used by default in the MIP solver was changed to the "best local bound". For more details see Chapter "Advanced API routines", Section "Branch-and-bound interface routines" in a new edition of the reference manual included in the distribution. GLPK 4.20 (release date: Jul 26, 2007) API routine lpx_integer was replaced by API routine glp_intopt, which provides equivalent functionality and additionally allows the application to control the solution process by means of the user-written callback routine, which is called by the solver at various points of the branch-and-bound algorithm. Besides, the new MIP solver allows generating "lazy" constraints and cutting planes on all levels of the branch-and-bound tree, not only on the root level. The routine lpx_integer is also still available for the backward compatibility. The following new advanced API routines, which may be called from the B&B callback routine, were included in the package: glp_ios_reason determine reason for calling callback routine glp_ios_get_prob access the problem object glp_ios_tree_size determine size of the branch-and-bound tree glp_ios_curr_node determine current active subproblem glp_ios_next_node determine next active subproblem glp_ios_prev_node determine previous active subproblem glp_ios_up_node determine parent subproblem glp_ios_node_level determine subproblem level glp_ios_node_bound determine subproblem local bound glp_ios_mip_gap compute relative MIP gap glp_ios_heur_sol provide solution found by heuristic glp_ios_terminate terminate the solution process For description of these routines see Chapter "Advanced API routines", Section "Branch-and-bound interface routines" in a new edition of the reference manual, which was included in the distribution. Old version of the integer optimization suite (IOS) as well as TSP solver tspsol based on it are no longer supported and were removed from the package. A minor error in the MIP presolver was fixed; thanks to Graham Rockwell for the bug report. GLPK 4.19 (release date: Jul 05, 2007) The principal change is upgrading to GPLv3. A serious bug in the routine glp_del_cols was fixed; thanks to Cedric[FR] for the bug report. The bug appeared because on deleting non-basic columns the basis header remained valid, however, contained invalid (old) column ordinal numbers. A new advanced API routine glp_mem_limit was added. The case GLP_EBOUND was added to the routine lpx_simplex. Thanks to Cameron Kellough for the bug report. An API routine lpx_write_pb to write the problem instance in OPB (pseudo boolean) format format was added. Thanks to Oscar Gustafsson for the contribution. Two new options --wpb and --wnpb were added to glpsol to write the problem instance in OPB format. GLPK 4.18 (release date: Jun 25, 2007) The following new API routines were added: glp_set_rii set (change) row scale factor glp_set_sjj set (change) column scale factor glp_get_rii retrieve row scale factor glp_get_sjj retrieve column scale factor glp_simplex solve LP problem with the simplex method (this routine replaces lpx_simplex, which is also available for backward compatibility) glp_init_smcp initialize simplex method control params glp_bf_exists check if the basis factorization exists glp_factorize compute the basis factorization glp_bf_updated check if the basis factorization has been updated glp_get_bfcp retrieve basis factorization control params glp_set_bfcp change basis factorization control params glp_get_bhead retrieve the basis header information glp_get_row_bind retrieve row index in the basis header glp_get_col_bind retrieve column index in the basis header glp_ftran perform forward transformation glp_btran perform backward transformation For description of all these routines see a new edition of the reference manual included in the distribution. Type names ulong_t and uldiv_t were changed to glp_ulong and glp_uldiv to avoid conflicts with standard type names on some platforms. Thanks to Boris Wirtz for the bug report. Some new examples in the MathProg language were added. Thanks to Sebastian Nowozin . GLPK 4.17 (release date: May 26, 2007) API routines glp_set_mat_row, glp_set_mat_col, and glp_load_mat were modified to allow zero constraint coefficients (which are not stored in the constraint matrix). Note that constraint coefficients with duplicate row/column indices are not allowed. Another form of LP basis factorization was implemented in the package. It is based on LU-factorization of an initial basis and Schur complement to reflect changes in the basis. Currently the implementation is incomplete and provides only updating the factorization on replacing a column of the basis matrix. On API level the user can set the control parameter LPX_K_BFTYPE to choose between the folloiwng forms of LP basis factorization to be used in the simplex method routines: 1) LU + Forrest-Tomlin update; 2) LU + Schur complement + Bartels-Golub update; 3) LU + Schur complement + Givens rotation update. The GLPK implementation is similar to LUSOL/LUMOD developed by Michael A. Saunders. The user can choose the form of LP basis factorzation used by the simplex method routines by specifying the folloiwng options of glpsol: --luf, --cbg, --cgr. GLPK 4.16 (release date: May 05, 2007) A number of basic GLPK API routines, which now are in the stable stable, were renamed to be prefixed with 'glp_'. Note that all these routines are available via their old names prefixed with 'lpx_' that keeps the downward compatibility with older versions of the package. Three new GLPK API routines were added to the package: glp_version, glp_term_hook, and glp_mem_usage; for more details see a new edition of the GLPK reference manual included in the distribution. The routine glp_version reports the actual version of the GLPK library and also can be used (along with the header glpk.h) in Autotools specification files to check if the GLPK library has been installed. The header glpk.h was changed to conform to C++ environment. GLPK 4.15 (release date: Feb 18, 2007) Autotools specification files (configure.ac, Makefile.am) were changed to use GNU Libtool. This allows building the static as well as shared GLPK library. GLPK 4.14 (release date: Feb 05, 2007) Now GLPK conforms to ILP32, LLP64, and LP64 programming models (the latter seems to be the ultimate choice regarding 64-bit architectures). Note that GLPK itself is a 32-bit application, and the conformity only means that the package works correctly on all these arenae. Nevertheless, on 64-bit platforms it is possible to use more than 4GB of memory, if necessary. GLPK 4.13 (release date: Nov 13, 2006) A tentative implementation of the "exact" simplex method based on bignum (rational) arithmetic was included in the package. On API level this new feature is available through the routine lpx_exact, which is similar to the routine lpx_simplex. In the solver glpsol this feature is available through two new command-line options: --exact and --xcheck. If the '--exact' option is specified, glpsol solves LP instance using the exact simplex method; in case of MIP it is used to obtain optimal solution of LP relaxation. If the --xcheck option is specified, LP instance (or LP relaxation) is solved using the standard (floating-point) simplex method, however, then glpsol calls the exact simplex routine to make sure that the final LP basis is exactly optimal, and if it is not, to perform some additional simplex iterations in exact arithmetic. GLPK 4.12 (release date: Nov 08, 2006) A tentative implementation of some simplex method routines based on exact (bignum) arithmetic was included in the package. Currently these routines provide computing LU-factorization of the basis matrix and computing components of basic solution. These routines were used to implement a routine, which checks primal and dual feasibility of basic solution exactly, i.e. in rational numbers, without round-off errors. In glpsol this feature is available through the command-line option --xcheck. GLPK has its own low-level routines implementing operations on integer and rational numbers that makes it independent on other software packages. However, to attain a much better performance it is highly recommended to install (before configuring GLPK) the GNU Multiple Precision Arithmetic Library (GMP). Using GMP makes computations 100-200 times faster. GLPK 4.11 (release date: Jul 25, 2006) Three new built-in functions in the modeling language were implemented: card (cardinality of set), length (length of character string), and substr (substring of character string). Another improvement concerns the printf statement which now allows redirecting its output to a specified file. These new features are illustrated in example models crypto.mod and graph.mod included in the distribution. For more details see the document "Modeling Language GNU MathProg". Four batch files (along with corresponding makefiles) were included in the distribution to simplify building GLPK under MS Windows; see them in subdirectory 'w32'. GLPK 4.10 (release date: May 11, 2006) Cutting planes of two new classes were implemented: mixed cover cuts and clique cuts. On API level this feature can be enabled by setting control parameter LPX_K_USECUTS passed to the routine lpx_intopt. In glpsol this feature is available through the command-line options --cover and --clique. For more details see the reference manual. Now the routines lpx_read_mps and lpx_read_freemps support LI bound type. It is similar to LO, however, indicates the column as of integer kind. GLPK 4.9 (release date: Jan 17, 2006) An advanced MIP solver was implemented. It includes: - basic presolving technique (removing free, singleton and redundant rows, improving bounds of columns, removing fixed columns, reducing constraint coefficents); - generating cutting planes to improve LP relaxation (currently only Gomory's mixed integer cuts are implemented); - using the branch-and-bound method to solve resultant MIP; - recovering solution of the original MIP. The solver is available on API level via the routine lpx_intopt (see the reference manual). It is similar to the routine lpx_integer, however, does not require initial solution of LP relaxation. The solver is also available in the command-line utility glpsol via two options: --intopt (only presolving) and --cuts (assumes --intopt plus generating cuts). Note that efficiency of the MIP solver strongly depends on the internal structure of the problem to be solved. For some hard instances it is very efficient, but for other instances it may be significantly worse than the standard branch-and-bound. For some comparative benchmarks see doc/bench1.txt. Well, what else... Three built-in functions were added to MathProg: sin, cos, and atan (the latter allows one or two arguments). Some bugs were fixed. Several new examples in MathProg were included: color.mod (graph coloring problem), tsp.mod (traveling salesman problem), and pbn.mod (paint-by-numbers puzzle). GLPK 4.8 (release date: Jan 12, 2005) Core simplex method and interior-point method routines were re-implemented and now they use a new, "storage-by-rows" sparse matrix format (unlike previous versions where linked lists were used to represent sparse matrices). For details see ChangeLog. Also a minor bug was fixed in API routine lpx_read_cpxlp. GLPK 4.7 (release date: Aug 23, 2004) Now GLPK supports free MPS format. Two new API routines lpx_read_freemps (to read problem data in free MPS format) and lpx_write_freemps (to write problem data in free MPS format) were added. This feature is also available in the solver glpsol via new command-line options --freemps and --wfreemps. For more details see the GLPK reference manual. API routines lpx_read_cpxlp and lpx_write_cpxlp for reading and writing problem data in CPLEX LP format were re-implemented to allow long symbolic names (up to 255 characters). The following three modules were temporarily removed from the GLPK distribution due to licensing problems: DELI (an interface module to Delphi), GLPKMEX (an interface module to Matlab), and JNI (an interface module to Java). GLPK 4.6 (release date: Aug 04, 2004) Three new statements were implemented in the GNU MathProg language: solve, printf, and for. Their detailed description can be found in the GLPK documentation included in the distribution. (See also a sample model, examples/queens.mod, which illustrates using these new statements.) Two new API routines were added to the package: lpx_read_prob and lpx_write_prob. They allow reading/writing problem data in GNU LP low-level text format. Three new command-line options were implemented in the LP/MIP solver glpsol: --glp (to read problem data in GNU LP format), --wglp (to write problem data in GNU LP format), and --name (to change problem name). Now glpsol also supports processing models where the new statements (see above) are used. A new version of GLPKMEX, a Matlab MEX interface to GLPK, was included. For more details see contrib/glpkmex/ChangeLog. GLPK 4.5 (release date: Jul 19, 2004) The branch-and-bound solver was completely re-implemented. Some modifications were made in memory allocation routines that allows using the package on 64-bit platforms. For more details see ChangeLog. GLPK 4.4 (release date: Jan 17, 2004) All API routines were re-implemented using new data structures. The new implementation provides the same specifications and functionality of API routines as the old one, however, it has some important advantages, in particular: * linked lists are used everywhere that allows creating and modifying the problem object as efficiently as possible * all data stored in the problem object are non-scaled (even if the internal scaling is used) that prevents distortion of the original problem data * solution components obtained by the solver remain available even if the problem object has been modified * no solver-specific data are used in the new data structures that allows attaching any external lp/mip solver using GLPK API as an uniform interface Note that some API routines became obsolete being replaced by new, more convenient routines. These obsolete routines are kept for backward compatibility, however, they will be removed in the future. For more details please see ChangeLog and the GLPK Reference Manual. New edition of the GLPK Reference Manual was included in the distribution. GLPKMEX, a Matlab MEX interface to GLPK package, contributed by Nicolo Giorgetti was included in the distribution. GLPK FAQ contributed by Harley Mackenzie was included in the distribution. GLPK 4.3 (release date: Dec 12, 2003) The bug, due to which the standard math library is not linked on building the package on some platforms, was fixed. The following new built-in functions were added to the MathProg language: round, trunc, Irand224, Uniform01, Uniform, Normal01, Normal. For details see the language description. The MathProg syntax was changed to allow writing 'subj to' that means 'subject to'. The new api routine lpx_get_ray_info was added. It is intended to determine which (non-basic) variable causes unboundness. For details see the reference manual. The module glpmps.c was changed to avoid compilation errors on building the package on Mac OS X. Several typos was fixed and some new material was added to the GLPK documentation. GLPK 4.2 (release date: Nov 14, 2003) A preliminary implementation of the Integer Optimization Suite (IOS) was included in the package. The Branch-and-Cut Framework being completely superseded by IOS was removed from the package. New API routine lpx_print_sens_bnds intended for bounds sensitivity analysis was contributed to GLPK by Brady Hunsaker . This function is also available in the solver glpsol (via command-line option --bounds). An improved version of GLPK JNI (Java Native Interface) was contributed by Chris Rosebrugh . GLPK DELI (Delphi Interface) was contributed by Ivo van Baren . Several makefiles were added to allow compiling GLPK on some non-GNU 32-bit platforms: * Windows single-threaded static library, Visual C++ 6.0 * Windows multi-threaded dynamic library, Visual C++ 6.0 * Windows single-threaded static library, Borland C++ 5.2 * DOS single-threaded static library, Digital Mars C++ 7.50 And, of course, some bugs were fixed. For more details see ChangeLog. GLPK 4.1 (release date: Aug 23, 2003) Some improvements were made in the lp/mip solver routines and several bugs were fixed in the model translator. For more details see ChangeLog. GLPK 4.0 (release date: May 06, 2003) Now GLPK supports the GNU MathProg modeling language, which is a subset of the AMPL modeling language. The document "GLPK: Modeling Language GNU MathProg" included in the distribution is a complete description of GNU MathProg. (See the files lang.latex, lang.dvi, and lang.ps in the subdirectory 'doc'. See also some examples in the subdirectory 'sample'.) New version of the solver glpsol, which supports models written in GNU MathProg, was implemented. (Brief instructions how to use glpsol can be found in the GNU MathProg documentation.) The GLPK/L modeling language is no more supported. The reason is that GNU MathProg being much more powerful completely supersedes all features of GLPK/L. GLPK 3.3 (release date: Mar 25, 2003) LP PRESOLVER ------------ Now the routine lpx_simplex (which is a driver to the simplex method for solving LP) is provided with the built-in LP presolver, which is a program that transforms the original LP problem to an equivalent LP problem, which may be easier for solving with the simplex method than the original one. Once the transformed LP has been solver, the presolver transforms its basic solution back to a corresponding basic solution of the original problem. For details about this feature please see the GLPK reference manual. Currently the LP presolver implements the following features: * removing empty rows; * removing empty columns; * removing free rows; * removing fixed columns; * removing row singletons, which have the form of equations; * removing row singletons, which have the form of inequalities; * removing column singletons, which are implied slack variables; * fixing and removing column singletons, which are implied free variables; * removing forcing rows that involves fixing and removing the corresponding columns; * checking for primal and dual infeasibilities. The LP presolver is also used by default in the stand-alone program glpsol. In order *not* to use it, the option --nopresol should be specified in the command-line. CHANGES IN GLPK/L ----------------- The syntax and semantics of the GLPK/L modeling language was changed to allow declaration of "interval" sets. This means that now the user can declare a set, for example, as: set task = [8:11]; that is exactly equivalent to the following declaration: set task = (task_8, task_9, task_10, task_11); For details see the language description. JAVA INTERFACE -------------- Now GLPK includes the package GLPK JNI (Java Native Interface) that implements Java binding for GLPK. It allows Java programs to utilize GLPK in solving LP and MIP problems. For details see a brief user's guide in the subdirectory contrib/java-binding. This package was developed and programmed by Yuri Victorovich , who contributed it to GLPK. GLPK 3.2.4 (release date: Feb 18, 2003) This is a bug-fix release. For details see ChangeLog. GLPK 3.2.3 (release date: Nov 11, 2002) A new implementation of the api routine lpx_integer which now is based on the b&b driver (which is based on the implicit enumeration suite) was included in the package. This new implementation has exactly the same functionality as the old version, so all changes are transparent to the api user. Four new api routines were included in the package: lpx_check_kkt checks Karush-Kuhn-Tucker optmality conditions; lpx_read_bas reads predifined basis in MPS format; lpx_write_bas writes current basis in MPS format; lpx_write_lpt writes problem data in CPLEX LP format. Also other minor improvements were made (for details see the file 'ChangeLog'). GLPK 3.2.2 (release date: Oct 14, 2002) The api routine lpx_read_lpt was included in the package. It is similar to the routine lpx_read_mps and intended to read LP/MIP data prepared in CPLEX LP format. Description of this format is given in the GLPK reference manual, a new edition of which was also included in the distribution (see the files 'refman.latex', 'refman.dvi', 'refman.ps' in the subdirectory 'doc'). In order to use data files in CPLEX LP format with the solver glpsol the option '--lpt' should be specified in the command line. Several bugs were fixed and some minor improvements were made (for details see the file 'ChangeLog'). GLPK 3.2.1 (release date: Aug 12, 2002) Now GLPK includes a preliminary implementation of the branch-and-cut framework, which is a set of data structures and routines intended for developing branch-and-cut methods for solving mixed-integer and combinatorial optimization problems. Detailed decsription of the branch-and-cut framework is given in the document "GLPK: A Preliminary Implementation of the Branch-And-Cut Framework" included in the distribution (see the file 'brcut.txt' in the subdirectory 'doc'). In order to illustrate how the GLPK branch-and-cut framework can be used for solving a particular optimization problem there is an example included in the package. This is a stand-alone program, TSPSOL, which is intended for solving to optimality the symmetric Traveling Salesman Problem (TSP), a classical problem of the combinatorial optimization (see the file 'tspsol.c' in the subdirectory 'sample'). GLPK 3.2 (release date: Jul 15, 2002) New edition of the document "GLPK: Reference Manual" was included (see the files 'refman.latex', 'refman.dvi', and 'refman.ps' in the subdirectory 'doc'). New edition of the document "GLPK: Modeling Language GLPK/L" was included (see the files 'lang.latex', 'lang.dvi', and 'lang.ps' in the subdirectory 'doc'). The following new API routines were added to the package: lpx_transform_row (transform explicitly specified row); lpx_transform_col (transform explicitly specified column); lpx_prim_ratio_test (perform primal ratio test); lpx_dual_ratio_test (perform dual ratio test); lpx_interior (solve LP problem using interior point method); lpx_get_ips_stat (query status of interior point solution); lpx_get_ips_row (obtain row interior point solution); lpx_get_ips_col (obtain column interior point solution); lpx_get_ips_obj (obtain interior point value of obj.func.); lpx_read_lpm (read LP/MIP model written in GLPK/L); lpx_write_mps (write problem data using MPS format); lpx_print_ips (print interior point solution). Detailed description of all these new API routines are given in the new edition of the reference manual. New version of the stand-alone solver glpsol (which is based on the new API) was implemented. So long as the new API (introduced in glpk 3.0) now provides all the functions, which were provided by the old API, the old API routines were removed from the package at all. GLPK 3.1 (release date: May 27, 2002) A preliminary implementation of new API routines was completed and included in the package. These new API routines provide much more flexible interaction between the application program, LP/MIP problem instances, and solver routines. Based on completely changed data structures they are, however, similar to the API routines and provide the same functionality. Please note that three routines, namely, solving LPs using interior point method, reading model written in the GLPK/L modeling language, and writing problem data in the MPS format, are not implemented in the new API, however, these routines are planned to be implemented in the next version of the package. A description of the new API routines is given in the document "GLPK Reference Manual", a draft edition of which is included in the package (see the files 'refman.latex', 'refman.dvi', and 'refman.ps' in the subdirectory 'doc'). Although the old API routines are kept in the package, they are no longer supported and will be removed in the future. GLPK 3.0.8 (release date: May 13, 2002) A preliminary implementation of new API routines was included in the package. These new API routines are intended to provide much more flexible interaction between the application program, LP/MIP problem and solver routines. See the document "New GLPK API Routines" (the file 'newapi.txt' in the subdirectory 'doc') also included in the package. The api routines glp_simplex2, glp_call_ipm1, glp_call_bbm1 were renamed, respectively, to glp_simplex, glp_interior, glp_integer in order to reflect changes in implementation. The api routines glp_call_rsm1, glp_simplex1, glp_pivot_in, glp_pivout_out were removed from the package since they are completely supreseded by the new API routines (however, these routines still can be found in the subdirectory 'oldsrc'). Please consult a new edition of the document "GLPK User's Guide" about all these changes in the existing api routines. The document "GLPK Library Reference" was removed from the package (into the subdirectory 'oldsrc') since it describes the obsolete library routines, most of which are no longer used. GLPK 3.0.7 (release date: Apr 22, 2002) A new, more efficient implementation of the primal/dual simplex method was included in the package. Due to some improvements the simplex-based solver allows solving many LP problems faster and provides more reliable results. Note that the new implementation is currently incomplete and available only via the api routine glp_simplex2. All the changes are transparent on API level. GLPK 3.0.6 (release date: Mar 28, 2002) New version of LU-factorization and basis maintenance routines (based on Forrest-Tomlin updating technique) was implemented. Since these new routines functionally supersede some routines (which implement other forms of the basis matrix) and make them obsolete, the latter were removed from the package (they still can be found in the subdirectory 'oldsrc'). All the changes are transparent on API level. GLPK 3.0.5 (release date: Jan 29, 2002) New edition of the document "GLPK User's Guide" was included in the distribution. Now it describes all additional API routines, which were recently added to the package. Structure of the package was re-organized in order to make its maintenance easier (all small files in the subdurectory 'source' were merged in bigger units). These changes are transparent for the user. GLPK 3.0.4 (release date: Dec 10, 2001) A new, more efficient implementation of the two-phase primal simplex method was included in the package. Due to some new features (an advanced initial basis, projected steepest edge, recursive updating values and reduced costs) the new LP solver is faster and numerically more stable than the old one. The new LP solver is available as API routine glp_simplex2 and has the same purpose as API routine glp_call_rsm1. For detailed specification see the file 'newapi.txt' in the directory 'doc'. Now the new LP solver is also used by default to solve an initial LP problem in the branch-and-bound routine glp_call_bbm1 instead the routine rsm1_driver. Note that the branch-and-bound procedure itself is still based on rsm1_driver. The new LP solver is also used as default solver in GLPSOL for solving LP and MIP problems. In order to choose the old solver the option '--old-sim' can be specified in the command line. GLPK 3.0.3 (release date: Oct 03, 2001) Some minor changes were made in the simplex method routines in order to improve numerical stability of the method. GLPK 3.0.2 (release date: Sep 24, 2001) A new implementation of the basis maintaining routines was included in the package. These routines, which are based on so called FHV-factorization (a variety of LU-factorization) of the basis matrix and Gustavson's data structures, allows performing the main operations faster at the expense of some worsening numerical accuracy. AFI (Advanced Form of the Inverse), which is the form of the basis matrix based on FHV-factorization, is available via the parameter form = 3 (on API level) or via the option --afi (in GLPSOL solver). GLPK 3.0.1 (release date: Aug 01, 2001) Old GLPK API routines have been removed from the package. New GLPK API routines were added: - scaling routines; - a routine for writing problem data in MPS format; - a comprehensive driver to the simplex method; - basis maintaining routines. A description of the new API routines is given in the document "Additional GLPK API Routines". This document is included into the distribution in plain text format (see the file 'newapi.txt' in the subdirectory 'doc'). Now the distribution includes a non-trivial example of using GLPK as a base LP solver for Concorde, a well known program that solves Traveling Salesman Problem (TSP). For further details see comments in the file 'sample/lpglpk30.c'. GLPK 3.0 (release date: Jul 19, 2001) Now GLPK is provided with new API, which being more flexible can be used in more complex algorithmic schemes. New edition of the document "GLPK User's Guide" is included in the distribution. Now it completely corresponds to the new GLPK API routines. Old API routines are not removed yet from the package, however they became obsolete and therefore should not be used. Since now the header glpk.h corresponds to new API, in order to compile existing programs that use old GLPK API routines the statement #define GLP_OLD_API should be inserted before the statement #include "glpk.h" GLPK 2.4.1 (release date: Jun 14, 2001) The document "Modeling language GLPK/L" is included into the distribution in texinfo format. New edition of the document "GLPK User's Guide" is included in the distribution. Now it describes all additional API routines which were recently added to the package. GLPK 2.4 (release date: May 10, 2001) Now GLPK includes an implementation of a preliminary version of the GLPK/L modeling language. This language is intended for writing mathematcal programming models. The name GLPK/L is derived from GNU Linear Programming Kit Language. A brief description of the GLPK/L language is given in the document "GLPK/L Modeling Language: A Brief Description". This document is included into the distribution in plain text format (see the file 'language.txt' in the subdirectory 'doc'). The language processor (which is a program that analyzes model description written in GLPK/L and translates it to internal data structures) is available as the GLPK API routine. The stand-alone solver GLPSOL now is able: a) to process model descriptions written in the GLPK/L language; b) to solve pure LP problems using the interior point method (therefore the program GLPIPM was removed from the package). GLPK 2.3 (release date: Apr 09, 2001) New edition of the document "GLPK User's Guide" is included in the distribution. Now it describes all additional API routines which were recently added to the package. The MIP solver was fully re-programmed in order to improve its robustness and performance. In particular, a basis recovering procedure was implemented (this procedure allows switching to the primal simplex method in case when the dual simplex method fails). GLPK 2.2 (release date: Mar 15, 2001) Now GLPK includes a tentative implementation of the branch-and-bound procedure based on the dual simplex method for mixed integer linear programming (MIP). Complete description of this new feature of the package is given in the preliminary document "Mixed Integer Linear Programming Using GLPK Version 2.2 (Supplement to GLPK User's Guide)". This document is included into the distribution in plain text format (see the file 'mip.txt' in the subdirectory 'doc'). The MIP solver (glp_integer) can be used as GLPK API routine in the same way as the pure LP solver (glp_simplex). The stand-alone program 'glpsol' is now able to solve LP as well as MIP problems. Note that the current version of GLPK MIP solver is based on easiest heuristics for branching and backtrackng. Therefore the solver is fit mainly for MIP problems which are not very hard and have few integer variables. GLPK 2.1 (release date: Feb 19, 2001) The document "GLPK Implementation of the Revised Simplex Method" is included into the distribution. This document describes most of routines related to the revised simplex method. GLPK 2.0 (release date: Jan 25, 2001) Now GLPK includes a tentative implementation of the primal-dual interior point method for large-scale linear programming. The interior point solver can be used as GLPK API routine in the same manner as the simplex method solver (glp_simplex): ret = glp_interior(); Note that currently the interior point solver implemented in GLPK doesn't include many important features, in particular: * it can't process dense columns; therefore if the problem has dense columns, the solving will be extremely inefficient; * it has no special features against numerical unstability; some problems may cause premature termination of the solving when the matrix A*D*A' becomes ill-conditioned; * it computes only values of primal (auxiliary and structural) variables and doesn't compute values of dual variables (i.e. reduced costs) which are just set to zero; * it doesn't identify optimal basis corresponding to the found interior point solution; all variables in the found solution are just marked as basic variables. GLPK also includes a stand-alone program 'glpipm' which is a demo based on the interior point method. It may be used in the same way as the program 'glpsol' that is based on the simplex method. glpk-4.52.1/README0000644000062000006210000000302312175147600012577 0ustar maomkpasswd Olga K. gewidmet GLPK (GNU Linear Programming Kit) Version 4.52.1 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied Informatics, Moscow Aviation Institute, Moscow, Russia. All rights reserved. E-mail: . GLPK is part of the GNU Project released under the aegis of GNU. GLPK is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. See the file COPYING for the GNU General Public License. See the file INSTALL for compilation and installation instructions. The GLPK package is a set of routines written in ANSI C and organized in the form of a callable library. This package is intended for solving large-scale linear programming (LP), mixed integer linear programming (MIP), and other related problems. The GLPK package includes the following main components: * implementation of the simplex method; * implementation of the exact simplex method based on bignum (rational) arithmetic; * implementation of the primal-dual interior-point method; * implementation of the branch-and-cut method; * application program interface (API); * GNU MathProg modeling language (a subset of AMPL); * GLPSOL, a stand-alone LP/MIP solver. See GLPK webpage . Please report bugs to . glpk-4.52.1/src/0000755000062000006210000000000012175147600012510 5ustar maomkpasswdglpk-4.52.1/src/amd/0000755000062000006210000000000012175147600013251 5ustar maomkpasswdglpk-4.52.1/src/amd/amd.h0000644000062000006210000000327612175147600014173 0ustar maomkpasswd/* amd.h */ /* Written by Andrew Makhorin . */ #ifndef GLPAMD_H #define GLPAMD_H #define AMD_DATE "May 31, 2007" #define AMD_VERSION_CODE(main, sub) ((main) * 1000 + (sub)) #define AMD_MAIN_VERSION 2 #define AMD_SUB_VERSION 2 #define AMD_SUBSUB_VERSION 0 #define AMD_VERSION AMD_VERSION_CODE(AMD_MAIN_VERSION, AMD_SUB_VERSION) #define AMD_CONTROL 5 #define AMD_INFO 20 #define AMD_DENSE 0 #define AMD_AGGRESSIVE 1 #define AMD_DEFAULT_DENSE 10.0 #define AMD_DEFAULT_AGGRESSIVE 1 #define AMD_STATUS 0 #define AMD_N 1 #define AMD_NZ 2 #define AMD_SYMMETRY 3 #define AMD_NZDIAG 4 #define AMD_NZ_A_PLUS_AT 5 #define AMD_NDENSE 6 #define AMD_MEMORY 7 #define AMD_NCMPA 8 #define AMD_LNZ 9 #define AMD_NDIV 10 #define AMD_NMULTSUBS_LDL 11 #define AMD_NMULTSUBS_LU 12 #define AMD_DMAX 13 #define AMD_OK 0 #define AMD_OUT_OF_MEMORY (-1) #define AMD_INVALID (-2) #define AMD_OK_BUT_JUMBLED 1 #define amd_order _glp_amd_order int amd_order(int n, const int Ap[], const int Ai[], int P[], double Control[], double Info[]); #define amd_2 _glp_amd_2 void amd_2(int n, int Pe[], int Iw[], int Len[], int iwlen, int pfree, int Nv[], int Next[], int Last[], int Head[], int Elen[], int Degree[], int W[], double Control[], double Info[]); #define amd_valid _glp_amd_valid int amd_valid(int n_row, int n_col, const int Ap[], const int Ai[]); #define amd_defaults _glp_amd_defaults void amd_defaults(double Control[]); #define amd_control _glp_amd_control void amd_control(double Control[]); #define amd_info _glp_amd_info void amd_info(double Info[]); #endif /* eof */ glpk-4.52.1/src/amd/amd_1.c0000644000062000006210000001504312175147600014401 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_1 =============================================================== */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* AMD_1: Construct A+A' for a sparse matrix A and perform the AMD ordering. * * The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style * compressed-column form, with sorted row indices in each column, and no * duplicate entries. Diagonal entries may be present, but they are ignored. * Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1]. * Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The * size of the matrix, n, must be greater than or equal to zero. * * This routine must be preceded by a call to AMD_aat, which computes the * number of entries in each row/column in A+A', excluding the diagonal. * Len [j], on input, is the number of entries in row/column j of A+A'. This * routine constructs the matrix A+A' and then calls AMD_2. No error checking * is performed (this was done in AMD_valid). */ #include "amd_internal.h" GLOBAL void AMD_1 ( Int n, /* n > 0 */ const Int Ap [ ], /* input of size n+1, not modified */ const Int Ai [ ], /* input of size nz = Ap [n], not modified */ Int P [ ], /* size n output permutation */ Int Pinv [ ], /* size n output inverse permutation */ Int Len [ ], /* size n input, undefined on output */ Int slen, /* slen >= sum (Len [0..n-1]) + 7n, * ideally slen = 1.2 * sum (Len) + 8n */ Int S [ ], /* size slen workspace */ double Control [ ], /* input array of size AMD_CONTROL */ double Info [ ] /* output array of size AMD_INFO */ ) { Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head, *Elen, *Degree, *s, *W, *Sp, *Tp ; /* --------------------------------------------------------------------- */ /* construct the matrix for AMD_2 */ /* --------------------------------------------------------------------- */ ASSERT (n > 0) ; iwlen = slen - 6*n ; s = S ; Pe = s ; s += n ; Nv = s ; s += n ; Head = s ; s += n ; Elen = s ; s += n ; Degree = s ; s += n ; W = s ; s += n ; Iw = s ; s += iwlen ; ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ; /* construct the pointers for A+A' */ Sp = Nv ; /* use Nv and W as workspace for Sp and Tp [ */ Tp = W ; pfree = 0 ; for (j = 0 ; j < n ; j++) { Pe [j] = pfree ; Sp [j] = pfree ; pfree += Len [j] ; } /* Note that this restriction on iwlen is slightly more restrictive than * what is strictly required in AMD_2. AMD_2 can operate with no elbow * room at all, but it will be very slow. For better performance, at * least size-n elbow room is enforced. */ ASSERT (iwlen >= pfree + n) ; #ifndef NDEBUG for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ; #endif for (k = 0 ; k < n ; k++) { AMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k)) ; p1 = Ap [k] ; p2 = Ap [k+1] ; /* construct A+A' */ for (p = p1 ; p < p2 ; ) { /* scan the upper triangular part of A */ j = Ai [p] ; ASSERT (j >= 0 && j < n) ; if (j < k) { /* entry A (j,k) in the strictly upper triangular part */ ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ; Iw [Sp [j]++] = k ; Iw [Sp [k]++] = j ; p++ ; } else if (j == k) { /* skip the diagonal */ p++ ; break ; } else /* j > k */ { /* first entry below the diagonal */ break ; } /* scan lower triangular part of A, in column j until reaching * row k. Start where last scan left off. */ ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; pj2 = Ap [j+1] ; for (pj = Tp [j] ; pj < pj2 ; ) { i = Ai [pj] ; ASSERT (i >= 0 && i < n) ; if (i < k) { /* A (i,j) is only in the lower part, not in upper */ ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; Iw [Sp [i]++] = j ; Iw [Sp [j]++] = i ; pj++ ; } else if (i == k) { /* entry A (k,j) in lower part and A (j,k) in upper */ pj++ ; break ; } else /* i > k */ { /* consider this entry later, when k advances to i */ break ; } } Tp [j] = pj ; } Tp [k] = p ; } /* clean up, for remaining mismatched entries */ for (j = 0 ; j < n ; j++) { for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) { i = Ai [pj] ; ASSERT (i >= 0 && i < n) ; /* A (i,j) is only in the lower part, not in upper */ ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ; ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ; Iw [Sp [i]++] = j ; Iw [Sp [j]++] = i ; } } #ifndef NDEBUG for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ; ASSERT (Sp [n-1] == pfree) ; #endif /* Tp and Sp no longer needed ] */ /* --------------------------------------------------------------------- */ /* order the matrix */ /* --------------------------------------------------------------------- */ AMD_2 (n, Pe, Iw, Len, iwlen, pfree, Nv, Pinv, P, Head, Elen, Degree, W, Control, Info) ; } glpk-4.52.1/src/amd/amd_2.c0000644000062000006210000023050112175147600014400 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_2 =============================================================== */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* AMD_2: performs the AMD ordering on a symmetric sparse matrix A, followed * by a postordering (via depth-first search) of the assembly tree using the * AMD_postorder routine. */ #include "amd_internal.h" /* ========================================================================= */ /* === clear_flag ========================================================== */ /* ========================================================================= */ static Int clear_flag (Int wflg, Int wbig, Int W [ ], Int n) { Int x ; if (wflg < 2 || wflg >= wbig) { for (x = 0 ; x < n ; x++) { if (W [x] != 0) W [x] = 1 ; } wflg = 2 ; } /* at this point, W [0..n-1] < wflg holds */ return (wflg) ; } /* ========================================================================= */ /* === AMD_2 =============================================================== */ /* ========================================================================= */ GLOBAL void AMD_2 ( Int n, /* A is n-by-n, where n > 0 */ Int Pe [ ], /* Pe [0..n-1]: index in Iw of row i on input */ Int Iw [ ], /* workspace of size iwlen. Iw [0..pfree-1] * holds the matrix on input */ Int Len [ ], /* Len [0..n-1]: length for row/column i on input */ Int iwlen, /* length of Iw. iwlen >= pfree + n */ Int pfree, /* Iw [pfree ... iwlen-1] is empty on input */ /* 7 size-n workspaces, not defined on input: */ Int Nv [ ], /* the size of each supernode on output */ Int Next [ ], /* the output inverse permutation */ Int Last [ ], /* the output permutation */ Int Head [ ], Int Elen [ ], /* the size columns of L for each supernode */ Int Degree [ ], Int W [ ], /* control parameters and output statistics */ double Control [ ], /* array of size AMD_CONTROL */ double Info [ ] /* array of size AMD_INFO */ ) { /* * Given a representation of the nonzero pattern of a symmetric matrix, A, * (excluding the diagonal) perform an approximate minimum (UMFPACK/MA38-style) * degree ordering to compute a pivot order such that the introduction of * nonzeros (fill-in) in the Cholesky factors A = LL' is kept low. At each * step, the pivot selected is the one with the minimum UMFAPACK/MA38-style * upper-bound on the external degree. This routine can optionally perform * aggresive absorption (as done by MC47B in the Harwell Subroutine * Library). * * The approximate degree algorithm implemented here is the symmetric analog of * the degree update algorithm in MA38 and UMFPACK (the Unsymmetric-pattern * MultiFrontal PACKage, both by Davis and Duff). The routine is based on the * MA27 minimum degree ordering algorithm by Iain Duff and John Reid. * * This routine is a translation of the original AMDBAR and MC47B routines, * in Fortran, with the following modifications: * * (1) dense rows/columns are removed prior to ordering the matrix, and placed * last in the output order. The presence of a dense row/column can * increase the ordering time by up to O(n^2), unless they are removed * prior to ordering. * * (2) the minimum degree ordering is followed by a postordering (depth-first * search) of the assembly tree. Note that mass elimination (discussed * below) combined with the approximate degree update can lead to the mass * elimination of nodes with lower exact degree than the current pivot * element. No additional fill-in is caused in the representation of the * Schur complement. The mass-eliminated nodes merge with the current * pivot element. They are ordered prior to the current pivot element. * Because they can have lower exact degree than the current element, the * merger of two or more of these nodes in the current pivot element can * lead to a single element that is not a "fundamental supernode". The * diagonal block can have zeros in it. Thus, the assembly tree used here * is not guaranteed to be the precise supernodal elemination tree (with * "funadmental" supernodes), and the postordering performed by this * routine is not guaranteed to be a precise postordering of the * elimination tree. * * (3) input parameters are added, to control aggressive absorption and the * detection of "dense" rows/columns of A. * * (4) additional statistical information is returned, such as the number of * nonzeros in L, and the flop counts for subsequent LDL' and LU * factorizations. These are slight upper bounds, because of the mass * elimination issue discussed above. * * (5) additional routines are added to interface this routine to MATLAB * to provide a simple C-callable user-interface, to check inputs for * errors, compute the symmetry of the pattern of A and the number of * nonzeros in each row/column of A+A', to compute the pattern of A+A', * to perform the assembly tree postordering, and to provide debugging * ouput. Many of these functions are also provided by the Fortran * Harwell Subroutine Library routine MC47A. * * (6) both int and UF_long versions are provided. In the descriptions below * and integer is and int or UF_long depending on which version is * being used. ********************************************************************** ***** CAUTION: ARGUMENTS ARE NOT CHECKED FOR ERRORS ON INPUT. ****** ********************************************************************** ** If you want error checking, a more versatile input format, and a ** ** simpler user interface, use amd_order or amd_l_order instead. ** ** This routine is not meant to be user-callable. ** ********************************************************************** * ---------------------------------------------------------------------------- * References: * ---------------------------------------------------------------------------- * * [1] Timothy A. Davis and Iain Duff, "An unsymmetric-pattern multifrontal * method for sparse LU factorization", SIAM J. Matrix Analysis and * Applications, vol. 18, no. 1, pp. 140-158. Discusses UMFPACK / MA38, * which first introduced the approximate minimum degree used by this * routine. * * [2] Patrick Amestoy, Timothy A. Davis, and Iain S. Duff, "An approximate * minimum degree ordering algorithm," SIAM J. Matrix Analysis and * Applications, vol. 17, no. 4, pp. 886-905, 1996. Discusses AMDBAR and * MC47B, which are the Fortran versions of this routine. * * [3] Alan George and Joseph Liu, "The evolution of the minimum degree * ordering algorithm," SIAM Review, vol. 31, no. 1, pp. 1-19, 1989. * We list below the features mentioned in that paper that this code * includes: * * mass elimination: * Yes. MA27 relied on supervariable detection for mass elimination. * * indistinguishable nodes: * Yes (we call these "supervariables"). This was also in the MA27 * code - although we modified the method of detecting them (the * previous hash was the true degree, which we no longer keep track * of). A supervariable is a set of rows with identical nonzero * pattern. All variables in a supervariable are eliminated together. * Each supervariable has as its numerical name that of one of its * variables (its principal variable). * * quotient graph representation: * Yes. We use the term "element" for the cliques formed during * elimination. This was also in the MA27 code. The algorithm can * operate in place, but it will work more efficiently if given some * "elbow room." * * element absorption: * Yes. This was also in the MA27 code. * * external degree: * Yes. The MA27 code was based on the true degree. * * incomplete degree update and multiple elimination: * No. This was not in MA27, either. Our method of degree update * within MC47B is element-based, not variable-based. It is thus * not well-suited for use with incomplete degree update or multiple * elimination. * * Authors, and Copyright (C) 2004 by: * Timothy A. Davis, Patrick Amestoy, Iain S. Duff, John K. Reid. * * Acknowledgements: This work (and the UMFPACK package) was supported by the * National Science Foundation (ASC-9111263, DMS-9223088, and CCR-0203270). * The UMFPACK/MA38 approximate degree update algorithm, the unsymmetric analog * which forms the basis of AMD, was developed while Tim Davis was supported by * CERFACS (Toulouse, France) in a post-doctoral position. This C version, and * the etree postorder, were written while Tim Davis was on sabbatical at * Stanford University and Lawrence Berkeley National Laboratory. * ---------------------------------------------------------------------------- * INPUT ARGUMENTS (unaltered): * ---------------------------------------------------------------------------- * n: The matrix order. Restriction: n >= 1. * * iwlen: The size of the Iw array. On input, the matrix is stored in * Iw [0..pfree-1]. However, Iw [0..iwlen-1] should be slightly larger * than what is required to hold the matrix, at least iwlen >= pfree + n. * Otherwise, excessive compressions will take place. The recommended * value of iwlen is 1.2 * pfree + n, which is the value used in the * user-callable interface to this routine (amd_order.c). The algorithm * will not run at all if iwlen < pfree. Restriction: iwlen >= pfree + n. * Note that this is slightly more restrictive than the actual minimum * (iwlen >= pfree), but AMD_2 will be very slow with no elbow room. * Thus, this routine enforces a bare minimum elbow room of size n. * * pfree: On input the tail end of the array, Iw [pfree..iwlen-1], is empty, * and the matrix is stored in Iw [0..pfree-1]. During execution, * additional data is placed in Iw, and pfree is modified so that * Iw [pfree..iwlen-1] is always the unused part of Iw. * * Control: A double array of size AMD_CONTROL containing input parameters * that affect how the ordering is computed. If NULL, then default * settings are used. * * Control [AMD_DENSE] is used to determine whether or not a given input * row is "dense". A row is "dense" if the number of entries in the row * exceeds Control [AMD_DENSE] times sqrt (n), except that rows with 16 or * fewer entries are never considered "dense". To turn off the detection * of dense rows, set Control [AMD_DENSE] to a negative number, or to a * number larger than sqrt (n). The default value of Control [AMD_DENSE] * is AMD_DEFAULT_DENSE, which is defined in amd.h as 10. * * Control [AMD_AGGRESSIVE] is used to determine whether or not aggressive * absorption is to be performed. If nonzero, then aggressive absorption * is performed (this is the default). * ---------------------------------------------------------------------------- * INPUT/OUPUT ARGUMENTS: * ---------------------------------------------------------------------------- * * Pe: An integer array of size n. On input, Pe [i] is the index in Iw of * the start of row i. Pe [i] is ignored if row i has no off-diagonal * entries. Thus Pe [i] must be in the range 0 to pfree-1 for non-empty * rows. * * During execution, it is used for both supervariables and elements: * * Principal supervariable i: index into Iw of the description of * supervariable i. A supervariable represents one or more rows of * the matrix with identical nonzero pattern. In this case, * Pe [i] >= 0. * * Non-principal supervariable i: if i has been absorbed into another * supervariable j, then Pe [i] = FLIP (j), where FLIP (j) is defined * as (-(j)-2). Row j has the same pattern as row i. Note that j * might later be absorbed into another supervariable j2, in which * case Pe [i] is still FLIP (j), and Pe [j] = FLIP (j2) which is * < EMPTY, where EMPTY is defined as (-1) in amd_internal.h. * * Unabsorbed element e: the index into Iw of the description of element * e, if e has not yet been absorbed by a subsequent element. Element * e is created when the supervariable of the same name is selected as * the pivot. In this case, Pe [i] >= 0. * * Absorbed element e: if element e is absorbed into element e2, then * Pe [e] = FLIP (e2). This occurs when the pattern of e (which we * refer to as Le) is found to be a subset of the pattern of e2 (that * is, Le2). In this case, Pe [i] < EMPTY. If element e is "null" * (it has no nonzeros outside its pivot block), then Pe [e] = EMPTY, * and e is the root of an assembly subtree (or the whole tree if * there is just one such root). * * Dense variable i: if i is "dense", then Pe [i] = EMPTY. * * On output, Pe holds the assembly tree/forest, which implicitly * represents a pivot order with identical fill-in as the actual order * (via a depth-first search of the tree), as follows. If Nv [i] > 0, * then i represents a node in the assembly tree, and the parent of i is * Pe [i], or EMPTY if i is a root. If Nv [i] = 0, then (i, Pe [i]) * represents an edge in a subtree, the root of which is a node in the * assembly tree. Note that i refers to a row/column in the original * matrix, not the permuted matrix. * * Info: A double array of size AMD_INFO. If present, (that is, not NULL), * then statistics about the ordering are returned in the Info array. * See amd.h for a description. * ---------------------------------------------------------------------------- * INPUT/MODIFIED (undefined on output): * ---------------------------------------------------------------------------- * * Len: An integer array of size n. On input, Len [i] holds the number of * entries in row i of the matrix, excluding the diagonal. The contents * of Len are undefined on output. * * Iw: An integer array of size iwlen. On input, Iw [0..pfree-1] holds the * description of each row i in the matrix. The matrix must be symmetric, * and both upper and lower triangular parts must be present. The * diagonal must not be present. Row i is held as follows: * * Len [i]: the length of the row i data structure in the Iw array. * Iw [Pe [i] ... Pe [i] + Len [i] - 1]: * the list of column indices for nonzeros in row i (simple * supervariables), excluding the diagonal. All supervariables * start with one row/column each (supervariable i is just row i). * If Len [i] is zero on input, then Pe [i] is ignored on input. * * Note that the rows need not be in any particular order, and there * may be empty space between the rows. * * During execution, the supervariable i experiences fill-in. This is * represented by placing in i a list of the elements that cause fill-in * in supervariable i: * * Len [i]: the length of supervariable i in the Iw array. * Iw [Pe [i] ... Pe [i] + Elen [i] - 1]: * the list of elements that contain i. This list is kept short * by removing absorbed elements. * Iw [Pe [i] + Elen [i] ... Pe [i] + Len [i] - 1]: * the list of supervariables in i. This list is kept short by * removing nonprincipal variables, and any entry j that is also * contained in at least one of the elements (j in Le) in the list * for i (e in row i). * * When supervariable i is selected as pivot, we create an element e of * the same name (e=i): * * Len [e]: the length of element e in the Iw array. * Iw [Pe [e] ... Pe [e] + Len [e] - 1]: * the list of supervariables in element e. * * An element represents the fill-in that occurs when supervariable i is * selected as pivot (which represents the selection of row i and all * non-principal variables whose principal variable is i). We use the * term Le to denote the set of all supervariables in element e. Absorbed * supervariables and elements are pruned from these lists when * computationally convenient. * * CAUTION: THE INPUT MATRIX IS OVERWRITTEN DURING COMPUTATION. * The contents of Iw are undefined on output. * ---------------------------------------------------------------------------- * OUTPUT (need not be set on input): * ---------------------------------------------------------------------------- * * Nv: An integer array of size n. During execution, ABS (Nv [i]) is equal to * the number of rows that are represented by the principal supervariable * i. If i is a nonprincipal or dense variable, then Nv [i] = 0. * Initially, Nv [i] = 1 for all i. Nv [i] < 0 signifies that i is a * principal variable in the pattern Lme of the current pivot element me. * After element me is constructed, Nv [i] is set back to a positive * value. * * On output, Nv [i] holds the number of pivots represented by super * row/column i of the original matrix, or Nv [i] = 0 for non-principal * rows/columns. Note that i refers to a row/column in the original * matrix, not the permuted matrix. * * Elen: An integer array of size n. See the description of Iw above. At the * start of execution, Elen [i] is set to zero for all rows i. During * execution, Elen [i] is the number of elements in the list for * supervariable i. When e becomes an element, Elen [e] = FLIP (esize) is * set, where esize is the size of the element (the number of pivots, plus * the number of nonpivotal entries). Thus Elen [e] < EMPTY. * Elen (i) = EMPTY set when variable i becomes nonprincipal. * * For variables, Elen (i) >= EMPTY holds until just before the * postordering and permutation vectors are computed. For elements, * Elen [e] < EMPTY holds. * * On output, Elen [i] is the degree of the row/column in the Cholesky * factorization of the permuted matrix, corresponding to the original row * i, if i is a super row/column. It is equal to EMPTY if i is * non-principal. Note that i refers to a row/column in the original * matrix, not the permuted matrix. * * Note that the contents of Elen on output differ from the Fortran * version (Elen holds the inverse permutation in the Fortran version, * which is instead returned in the Next array in this C version, * described below). * * Last: In a degree list, Last [i] is the supervariable preceding i, or EMPTY * if i is the head of the list. In a hash bucket, Last [i] is the hash * key for i. * * Last [Head [hash]] is also used as the head of a hash bucket if * Head [hash] contains a degree list (see the description of Head, * below). * * On output, Last [0..n-1] holds the permutation. That is, if * i = Last [k], then row i is the kth pivot row (where k ranges from 0 to * n-1). Row Last [k] of A is the kth row in the permuted matrix, PAP'. * * Next: Next [i] is the supervariable following i in a link list, or EMPTY if * i is the last in the list. Used for two kinds of lists: degree lists * and hash buckets (a supervariable can be in only one kind of list at a * time). * * On output Next [0..n-1] holds the inverse permutation. That is, if * k = Next [i], then row i is the kth pivot row. Row i of A appears as * the (Next[i])-th row in the permuted matrix, PAP'. * * Note that the contents of Next on output differ from the Fortran * version (Next is undefined on output in the Fortran version). * ---------------------------------------------------------------------------- * LOCAL WORKSPACE (not input or output - used only during execution): * ---------------------------------------------------------------------------- * * Degree: An integer array of size n. If i is a supervariable, then * Degree [i] holds the current approximation of the external degree of * row i (an upper bound). The external degree is the number of nonzeros * in row i, minus ABS (Nv [i]), the diagonal part. The bound is equal to * the exact external degree if Elen [i] is less than or equal to two. * * We also use the term "external degree" for elements e to refer to * |Le \ Lme|. If e is an element, then Degree [e] is |Le|, which is the * degree of the off-diagonal part of the element e (not including the * diagonal part). * * Head: An integer array of size n. Head is used for degree lists. * Head [deg] is the first supervariable in a degree list. All * supervariables i in a degree list Head [deg] have the same approximate * degree, namely, deg = Degree [i]. If the list Head [deg] is empty then * Head [deg] = EMPTY. * * During supervariable detection Head [hash] also serves as a pointer to * a hash bucket. If Head [hash] >= 0, there is a degree list of degree * hash. The hash bucket head pointer is Last [Head [hash]]. If * Head [hash] = EMPTY, then the degree list and hash bucket are both * empty. If Head [hash] < EMPTY, then the degree list is empty, and * FLIP (Head [hash]) is the head of the hash bucket. After supervariable * detection is complete, all hash buckets are empty, and the * (Last [Head [hash]] = EMPTY) condition is restored for the non-empty * degree lists. * * W: An integer array of size n. The flag array W determines the status of * elements and variables, and the external degree of elements. * * for elements: * if W [e] = 0, then the element e is absorbed. * if W [e] >= wflg, then W [e] - wflg is the size of the set * |Le \ Lme|, in terms of nonzeros (the sum of ABS (Nv [i]) for * each principal variable i that is both in the pattern of * element e and NOT in the pattern of the current pivot element, * me). * if wflg > W [e] > 0, then e is not absorbed and has not yet been * seen in the scan of the element lists in the computation of * |Le\Lme| in Scan 1 below. * * for variables: * during supervariable detection, if W [j] != wflg then j is * not in the pattern of variable i. * * The W array is initialized by setting W [i] = 1 for all i, and by * setting wflg = 2. It is reinitialized if wflg becomes too large (to * ensure that wflg+n does not cause integer overflow). * ---------------------------------------------------------------------------- * LOCAL INTEGERS: * ---------------------------------------------------------------------------- */ Int deg, degme, dext, lemax, e, elenme, eln, i, ilast, inext, j, jlast, jnext, k, knt1, knt2, knt3, lenj, ln, me, mindeg, nel, nleft, nvi, nvj, nvpiv, slenme, wbig, we, wflg, wnvi, ok, ndense, ncmpa, dense, aggressive ; unsigned Int hash ; /* unsigned, so that hash % n is well defined.*/ /* * deg: the degree of a variable or element * degme: size, |Lme|, of the current element, me (= Degree [me]) * dext: external degree, |Le \ Lme|, of some element e * lemax: largest |Le| seen so far (called dmax in Fortran version) * e: an element * elenme: the length, Elen [me], of element list of pivotal variable * eln: the length, Elen [...], of an element list * hash: the computed value of the hash function * i: a supervariable * ilast: the entry in a link list preceding i * inext: the entry in a link list following i * j: a supervariable * jlast: the entry in a link list preceding j * jnext: the entry in a link list, or path, following j * k: the pivot order of an element or variable * knt1: loop counter used during element construction * knt2: loop counter used during element construction * knt3: loop counter used during compression * lenj: Len [j] * ln: length of a supervariable list * me: current supervariable being eliminated, and the current * element created by eliminating that supervariable * mindeg: current minimum degree * nel: number of pivots selected so far * nleft: n - nel, the number of nonpivotal rows/columns remaining * nvi: the number of variables in a supervariable i (= Nv [i]) * nvj: the number of variables in a supervariable j (= Nv [j]) * nvpiv: number of pivots in current element * slenme: number of variables in variable list of pivotal variable * wbig: = INT_MAX - n for the int version, UF_long_max - n for the * UF_long version. wflg is not allowed to be >= wbig. * we: W [e] * wflg: used for flagging the W array. See description of Iw. * wnvi: wflg - Nv [i] * x: either a supervariable or an element * * ok: true if supervariable j can be absorbed into i * ndense: number of "dense" rows/columns * dense: rows/columns with initial degree > dense are considered "dense" * aggressive: true if aggressive absorption is being performed * ncmpa: number of garbage collections * ---------------------------------------------------------------------------- * LOCAL DOUBLES, used for statistical output only (except for alpha): * ---------------------------------------------------------------------------- */ double f, r, ndiv, s, nms_lu, nms_ldl, dmax, alpha, lnz, lnzme ; /* * f: nvpiv * r: degme + nvpiv * ndiv: number of divisions for LU or LDL' factorizations * s: number of multiply-subtract pairs for LU factorization, for the * current element me * nms_lu number of multiply-subtract pairs for LU factorization * nms_ldl number of multiply-subtract pairs for LDL' factorization * dmax: the largest number of entries in any column of L, including the * diagonal * alpha: "dense" degree ratio * lnz: the number of nonzeros in L (excluding the diagonal) * lnzme: the number of nonzeros in L (excl. the diagonal) for the * current element me * ---------------------------------------------------------------------------- * LOCAL "POINTERS" (indices into the Iw array) * ---------------------------------------------------------------------------- */ Int p, p1, p2, p3, p4, pdst, pend, pj, pme, pme1, pme2, pn, psrc ; /* * Any parameter (Pe [...] or pfree) or local variable starting with "p" (for * Pointer) is an index into Iw, and all indices into Iw use variables starting * with "p." The only exception to this rule is the iwlen input argument. * * p: pointer into lots of things * p1: Pe [i] for some variable i (start of element list) * p2: Pe [i] + Elen [i] - 1 for some variable i * p3: index of first supervariable in clean list * p4: * pdst: destination pointer, for compression * pend: end of memory to compress * pj: pointer into an element or variable * pme: pointer into the current element (pme1...pme2) * pme1: the current element, me, is stored in Iw [pme1...pme2] * pme2: the end of the current element * pn: pointer into a "clean" variable, also used to compress * psrc: source pointer, for compression */ /* ========================================================================= */ /* INITIALIZATIONS */ /* ========================================================================= */ /* Note that this restriction on iwlen is slightly more restrictive than * what is actually required in AMD_2. AMD_2 can operate with no elbow * room at all, but it will be slow. For better performance, at least * size-n elbow room is enforced. */ ASSERT (iwlen >= pfree + n) ; ASSERT (n > 0) ; /* initialize output statistics */ lnz = 0 ; ndiv = 0 ; nms_lu = 0 ; nms_ldl = 0 ; dmax = 1 ; me = EMPTY ; mindeg = 0 ; ncmpa = 0 ; nel = 0 ; lemax = 0 ; /* get control parameters */ if (Control != (double *) NULL) { alpha = Control [AMD_DENSE] ; aggressive = (Control [AMD_AGGRESSIVE] != 0) ; } else { alpha = AMD_DEFAULT_DENSE ; aggressive = AMD_DEFAULT_AGGRESSIVE ; } /* Note: if alpha is NaN, this is undefined: */ if (alpha < 0) { /* only remove completely dense rows/columns */ dense = n-2 ; } else { dense = alpha * sqrt ((double) n) ; } dense = MAX (16, dense) ; dense = MIN (n, dense) ; AMD_DEBUG1 (("\n\nAMD (debug), alpha %g, aggr. "ID"\n", alpha, aggressive)) ; for (i = 0 ; i < n ; i++) { Last [i] = EMPTY ; Head [i] = EMPTY ; Next [i] = EMPTY ; /* if separate Hhead array is used for hash buckets: * Hhead [i] = EMPTY ; */ Nv [i] = 1 ; W [i] = 1 ; Elen [i] = 0 ; Degree [i] = Len [i] ; } #ifndef NDEBUG AMD_DEBUG1 (("\n======Nel "ID" initial\n", nel)) ; AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, Head, Elen, Degree, W, -1) ; #endif /* initialize wflg */ wbig = Int_MAX - n ; wflg = clear_flag (0, wbig, W, n) ; /* --------------------------------------------------------------------- */ /* initialize degree lists and eliminate dense and empty rows */ /* --------------------------------------------------------------------- */ ndense = 0 ; for (i = 0 ; i < n ; i++) { deg = Degree [i] ; ASSERT (deg >= 0 && deg < n) ; if (deg == 0) { /* ------------------------------------------------------------- * we have a variable that can be eliminated at once because * there is no off-diagonal non-zero in its row. Note that * Nv [i] = 1 for an empty variable i. It is treated just * the same as an eliminated element i. * ------------------------------------------------------------- */ Elen [i] = FLIP (1) ; nel++ ; Pe [i] = EMPTY ; W [i] = 0 ; } else if (deg > dense) { /* ------------------------------------------------------------- * Dense variables are not treated as elements, but as unordered, * non-principal variables that have no parent. They do not take * part in the postorder, since Nv [i] = 0. Note that the Fortran * version does not have this option. * ------------------------------------------------------------- */ AMD_DEBUG1 (("Dense node "ID" degree "ID"\n", i, deg)) ; ndense++ ; Nv [i] = 0 ; /* do not postorder this node */ Elen [i] = EMPTY ; nel++ ; Pe [i] = EMPTY ; } else { /* ------------------------------------------------------------- * place i in the degree list corresponding to its degree * ------------------------------------------------------------- */ inext = Head [deg] ; ASSERT (inext >= EMPTY && inext < n) ; if (inext != EMPTY) Last [inext] = i ; Next [i] = inext ; Head [deg] = i ; } } /* ========================================================================= */ /* WHILE (selecting pivots) DO */ /* ========================================================================= */ while (nel < n) { #ifndef NDEBUG AMD_DEBUG1 (("\n======Nel "ID"\n", nel)) ; if (AMD_debug >= 2) { AMD_dump (n, Pe, Iw, Len, iwlen, pfree, Nv, Next, Last, Head, Elen, Degree, W, nel) ; } #endif /* ========================================================================= */ /* GET PIVOT OF MINIMUM DEGREE */ /* ========================================================================= */ /* ----------------------------------------------------------------- */ /* find next supervariable for elimination */ /* ----------------------------------------------------------------- */ ASSERT (mindeg >= 0 && mindeg < n) ; for (deg = mindeg ; deg < n ; deg++) { me = Head [deg] ; if (me != EMPTY) break ; } mindeg = deg ; ASSERT (me >= 0 && me < n) ; AMD_DEBUG1 (("=================me: "ID"\n", me)) ; /* ----------------------------------------------------------------- */ /* remove chosen variable from link list */ /* ----------------------------------------------------------------- */ inext = Next [me] ; ASSERT (inext >= EMPTY && inext < n) ; if (inext != EMPTY) Last [inext] = EMPTY ; Head [deg] = inext ; /* ----------------------------------------------------------------- */ /* me represents the elimination of pivots nel to nel+Nv[me]-1. */ /* place me itself as the first in this set. */ /* ----------------------------------------------------------------- */ elenme = Elen [me] ; nvpiv = Nv [me] ; ASSERT (nvpiv > 0) ; nel += nvpiv ; /* ========================================================================= */ /* CONSTRUCT NEW ELEMENT */ /* ========================================================================= */ /* ----------------------------------------------------------------- * At this point, me is the pivotal supervariable. It will be * converted into the current element. Scan list of the pivotal * supervariable, me, setting tree pointers and constructing new list * of supervariables for the new element, me. p is a pointer to the * current position in the old list. * ----------------------------------------------------------------- */ /* flag the variable "me" as being in Lme by negating Nv [me] */ Nv [me] = -nvpiv ; degme = 0 ; ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; if (elenme == 0) { /* ------------------------------------------------------------- */ /* construct the new element in place */ /* ------------------------------------------------------------- */ pme1 = Pe [me] ; pme2 = pme1 - 1 ; for (p = pme1 ; p <= pme1 + Len [me] - 1 ; p++) { i = Iw [p] ; ASSERT (i >= 0 && i < n && Nv [i] >= 0) ; nvi = Nv [i] ; if (nvi > 0) { /* ----------------------------------------------------- */ /* i is a principal variable not yet placed in Lme. */ /* store i in new list */ /* ----------------------------------------------------- */ /* flag i as being in Lme by negating Nv [i] */ degme += nvi ; Nv [i] = -nvi ; Iw [++pme2] = i ; /* ----------------------------------------------------- */ /* remove variable i from degree list. */ /* ----------------------------------------------------- */ ilast = Last [i] ; inext = Next [i] ; ASSERT (ilast >= EMPTY && ilast < n) ; ASSERT (inext >= EMPTY && inext < n) ; if (inext != EMPTY) Last [inext] = ilast ; if (ilast != EMPTY) { Next [ilast] = inext ; } else { /* i is at the head of the degree list */ ASSERT (Degree [i] >= 0 && Degree [i] < n) ; Head [Degree [i]] = inext ; } } } } else { /* ------------------------------------------------------------- */ /* construct the new element in empty space, Iw [pfree ...] */ /* ------------------------------------------------------------- */ p = Pe [me] ; pme1 = pfree ; slenme = Len [me] - elenme ; for (knt1 = 1 ; knt1 <= elenme + 1 ; knt1++) { if (knt1 > elenme) { /* search the supervariables in me. */ e = me ; pj = p ; ln = slenme ; AMD_DEBUG2 (("Search sv: "ID" "ID" "ID"\n", me,pj,ln)) ; } else { /* search the elements in me. */ e = Iw [p++] ; ASSERT (e >= 0 && e < n) ; pj = Pe [e] ; ln = Len [e] ; AMD_DEBUG2 (("Search element e "ID" in me "ID"\n", e,me)) ; ASSERT (Elen [e] < EMPTY && W [e] > 0 && pj >= 0) ; } ASSERT (ln >= 0 && (ln == 0 || (pj >= 0 && pj < iwlen))) ; /* --------------------------------------------------------- * search for different supervariables and add them to the * new list, compressing when necessary. this loop is * executed once for each element in the list and once for * all the supervariables in the list. * --------------------------------------------------------- */ for (knt2 = 1 ; knt2 <= ln ; knt2++) { i = Iw [pj++] ; ASSERT (i >= 0 && i < n && (i == me || Elen [i] >= EMPTY)); nvi = Nv [i] ; AMD_DEBUG2 ((": "ID" "ID" "ID" "ID"\n", i, Elen [i], Nv [i], wflg)) ; if (nvi > 0) { /* ------------------------------------------------- */ /* compress Iw, if necessary */ /* ------------------------------------------------- */ if (pfree >= iwlen) { AMD_DEBUG1 (("GARBAGE COLLECTION\n")) ; /* prepare for compressing Iw by adjusting pointers * and lengths so that the lists being searched in * the inner and outer loops contain only the * remaining entries. */ Pe [me] = p ; Len [me] -= knt1 ; /* check if nothing left of supervariable me */ if (Len [me] == 0) Pe [me] = EMPTY ; Pe [e] = pj ; Len [e] = ln - knt2 ; /* nothing left of element e */ if (Len [e] == 0) Pe [e] = EMPTY ; ncmpa++ ; /* one more garbage collection */ /* store first entry of each object in Pe */ /* FLIP the first entry in each object */ for (j = 0 ; j < n ; j++) { pn = Pe [j] ; if (pn >= 0) { ASSERT (pn >= 0 && pn < iwlen) ; Pe [j] = Iw [pn] ; Iw [pn] = FLIP (j) ; } } /* psrc/pdst point to source/destination */ psrc = 0 ; pdst = 0 ; pend = pme1 - 1 ; while (psrc <= pend) { /* search for next FLIP'd entry */ j = FLIP (Iw [psrc++]) ; if (j >= 0) { AMD_DEBUG2 (("Got object j: "ID"\n", j)) ; Iw [pdst] = Pe [j] ; Pe [j] = pdst++ ; lenj = Len [j] ; /* copy from source to destination */ for (knt3 = 0 ; knt3 <= lenj - 2 ; knt3++) { Iw [pdst++] = Iw [psrc++] ; } } } /* move the new partially-constructed element */ p1 = pdst ; for (psrc = pme1 ; psrc <= pfree-1 ; psrc++) { Iw [pdst++] = Iw [psrc] ; } pme1 = p1 ; pfree = pdst ; pj = Pe [e] ; p = Pe [me] ; } /* ------------------------------------------------- */ /* i is a principal variable not yet placed in Lme */ /* store i in new list */ /* ------------------------------------------------- */ /* flag i as being in Lme by negating Nv [i] */ degme += nvi ; Nv [i] = -nvi ; Iw [pfree++] = i ; AMD_DEBUG2 ((" s: "ID" nv "ID"\n", i, Nv [i])); /* ------------------------------------------------- */ /* remove variable i from degree link list */ /* ------------------------------------------------- */ ilast = Last [i] ; inext = Next [i] ; ASSERT (ilast >= EMPTY && ilast < n) ; ASSERT (inext >= EMPTY && inext < n) ; if (inext != EMPTY) Last [inext] = ilast ; if (ilast != EMPTY) { Next [ilast] = inext ; } else { /* i is at the head of the degree list */ ASSERT (Degree [i] >= 0 && Degree [i] < n) ; Head [Degree [i]] = inext ; } } } if (e != me) { /* set tree pointer and flag to indicate element e is * absorbed into new element me (the parent of e is me) */ AMD_DEBUG1 ((" Element "ID" => "ID"\n", e, me)) ; Pe [e] = FLIP (me) ; W [e] = 0 ; } } pme2 = pfree - 1 ; } /* ----------------------------------------------------------------- */ /* me has now been converted into an element in Iw [pme1..pme2] */ /* ----------------------------------------------------------------- */ /* degme holds the external degree of new element */ Degree [me] = degme ; Pe [me] = pme1 ; Len [me] = pme2 - pme1 + 1 ; ASSERT (Pe [me] >= 0 && Pe [me] < iwlen) ; Elen [me] = FLIP (nvpiv + degme) ; /* FLIP (Elen (me)) is now the degree of pivot (including * diagonal part). */ #ifndef NDEBUG AMD_DEBUG2 (("New element structure: length= "ID"\n", pme2-pme1+1)) ; for (pme = pme1 ; pme <= pme2 ; pme++) AMD_DEBUG3 ((" "ID"", Iw[pme])); AMD_DEBUG3 (("\n")) ; #endif /* ----------------------------------------------------------------- */ /* make sure that wflg is not too large. */ /* ----------------------------------------------------------------- */ /* With the current value of wflg, wflg+n must not cause integer * overflow */ wflg = clear_flag (wflg, wbig, W, n) ; /* ========================================================================= */ /* COMPUTE (W [e] - wflg) = |Le\Lme| FOR ALL ELEMENTS */ /* ========================================================================= */ /* ----------------------------------------------------------------- * Scan 1: compute the external degrees of previous elements with * respect to the current element. That is: * (W [e] - wflg) = |Le \ Lme| * for each element e that appears in any supervariable in Lme. The * notation Le refers to the pattern (list of supervariables) of a * previous element e, where e is not yet absorbed, stored in * Iw [Pe [e] + 1 ... Pe [e] + Len [e]]. The notation Lme * refers to the pattern of the current element (stored in * Iw [pme1..pme2]). If aggressive absorption is enabled, and * (W [e] - wflg) becomes zero, then the element e will be absorbed * in Scan 2. * ----------------------------------------------------------------- */ AMD_DEBUG2 (("me: ")) ; for (pme = pme1 ; pme <= pme2 ; pme++) { i = Iw [pme] ; ASSERT (i >= 0 && i < n) ; eln = Elen [i] ; AMD_DEBUG3 ((""ID" Elen "ID": \n", i, eln)) ; if (eln > 0) { /* note that Nv [i] has been negated to denote i in Lme: */ nvi = -Nv [i] ; ASSERT (nvi > 0 && Pe [i] >= 0 && Pe [i] < iwlen) ; wnvi = wflg - nvi ; for (p = Pe [i] ; p <= Pe [i] + eln - 1 ; p++) { e = Iw [p] ; ASSERT (e >= 0 && e < n) ; we = W [e] ; AMD_DEBUG4 ((" e "ID" we "ID" ", e, we)) ; if (we >= wflg) { /* unabsorbed element e has been seen in this loop */ AMD_DEBUG4 ((" unabsorbed, first time seen")) ; we -= nvi ; } else if (we != 0) { /* e is an unabsorbed element */ /* this is the first we have seen e in all of Scan 1 */ AMD_DEBUG4 ((" unabsorbed")) ; we = Degree [e] + wnvi ; } AMD_DEBUG4 (("\n")) ; W [e] = we ; } } } AMD_DEBUG2 (("\n")) ; /* ========================================================================= */ /* DEGREE UPDATE AND ELEMENT ABSORPTION */ /* ========================================================================= */ /* ----------------------------------------------------------------- * Scan 2: for each i in Lme, sum up the degree of Lme (which is * degme), plus the sum of the external degrees of each Le for the * elements e appearing within i, plus the supervariables in i. * Place i in hash list. * ----------------------------------------------------------------- */ for (pme = pme1 ; pme <= pme2 ; pme++) { i = Iw [pme] ; ASSERT (i >= 0 && i < n && Nv [i] < 0 && Elen [i] >= 0) ; AMD_DEBUG2 (("Updating: i "ID" "ID" "ID"\n", i, Elen[i], Len [i])); p1 = Pe [i] ; p2 = p1 + Elen [i] - 1 ; pn = p1 ; hash = 0 ; deg = 0 ; ASSERT (p1 >= 0 && p1 < iwlen && p2 >= -1 && p2 < iwlen) ; /* ------------------------------------------------------------- */ /* scan the element list associated with supervariable i */ /* ------------------------------------------------------------- */ /* UMFPACK/MA38-style approximate degree: */ if (aggressive) { for (p = p1 ; p <= p2 ; p++) { e = Iw [p] ; ASSERT (e >= 0 && e < n) ; we = W [e] ; if (we != 0) { /* e is an unabsorbed element */ /* dext = | Le \ Lme | */ dext = we - wflg ; if (dext > 0) { deg += dext ; Iw [pn++] = e ; hash += e ; AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; } else { /* external degree of e is zero, absorb e into me*/ AMD_DEBUG1 ((" Element "ID" =>"ID" (aggressive)\n", e, me)) ; ASSERT (dext == 0) ; Pe [e] = FLIP (me) ; W [e] = 0 ; } } } } else { for (p = p1 ; p <= p2 ; p++) { e = Iw [p] ; ASSERT (e >= 0 && e < n) ; we = W [e] ; if (we != 0) { /* e is an unabsorbed element */ dext = we - wflg ; ASSERT (dext >= 0) ; deg += dext ; Iw [pn++] = e ; hash += e ; AMD_DEBUG4 ((" e: "ID" hash = "ID"\n",e,hash)) ; } } } /* count the number of elements in i (including me): */ Elen [i] = pn - p1 + 1 ; /* ------------------------------------------------------------- */ /* scan the supervariables in the list associated with i */ /* ------------------------------------------------------------- */ /* The bulk of the AMD run time is typically spent in this loop, * particularly if the matrix has many dense rows that are not * removed prior to ordering. */ p3 = pn ; p4 = p1 + Len [i] ; for (p = p2 + 1 ; p < p4 ; p++) { j = Iw [p] ; ASSERT (j >= 0 && j < n) ; nvj = Nv [j] ; if (nvj > 0) { /* j is unabsorbed, and not in Lme. */ /* add to degree and add to new list */ deg += nvj ; Iw [pn++] = j ; hash += j ; AMD_DEBUG4 ((" s: "ID" hash "ID" Nv[j]= "ID"\n", j, hash, nvj)) ; } } /* ------------------------------------------------------------- */ /* update the degree and check for mass elimination */ /* ------------------------------------------------------------- */ /* with aggressive absorption, deg==0 is identical to the * Elen [i] == 1 && p3 == pn test, below. */ ASSERT (IMPLIES (aggressive, (deg==0) == (Elen[i]==1 && p3==pn))) ; if (Elen [i] == 1 && p3 == pn) { /* --------------------------------------------------------- */ /* mass elimination */ /* --------------------------------------------------------- */ /* There is nothing left of this node except for an edge to * the current pivot element. Elen [i] is 1, and there are * no variables adjacent to node i. Absorb i into the * current pivot element, me. Note that if there are two or * more mass eliminations, fillin due to mass elimination is * possible within the nvpiv-by-nvpiv pivot block. It is this * step that causes AMD's analysis to be an upper bound. * * The reason is that the selected pivot has a lower * approximate degree than the true degree of the two mass * eliminated nodes. There is no edge between the two mass * eliminated nodes. They are merged with the current pivot * anyway. * * No fillin occurs in the Schur complement, in any case, * and this effect does not decrease the quality of the * ordering itself, just the quality of the nonzero and * flop count analysis. It also means that the post-ordering * is not an exact elimination tree post-ordering. */ AMD_DEBUG1 ((" MASS i "ID" => parent e "ID"\n", i, me)) ; Pe [i] = FLIP (me) ; nvi = -Nv [i] ; degme -= nvi ; nvpiv += nvi ; nel += nvi ; Nv [i] = 0 ; Elen [i] = EMPTY ; } else { /* --------------------------------------------------------- */ /* update the upper-bound degree of i */ /* --------------------------------------------------------- */ /* the following degree does not yet include the size * of the current element, which is added later: */ Degree [i] = MIN (Degree [i], deg) ; /* --------------------------------------------------------- */ /* add me to the list for i */ /* --------------------------------------------------------- */ /* move first supervariable to end of list */ Iw [pn] = Iw [p3] ; /* move first element to end of element part of list */ Iw [p3] = Iw [p1] ; /* add new element, me, to front of list. */ Iw [p1] = me ; /* store the new length of the list in Len [i] */ Len [i] = pn - p1 + 1 ; /* --------------------------------------------------------- */ /* place in hash bucket. Save hash key of i in Last [i]. */ /* --------------------------------------------------------- */ /* NOTE: this can fail if hash is negative, because the ANSI C * standard does not define a % b when a and/or b are negative. * That's why hash is defined as an unsigned Int, to avoid this * problem. */ hash = hash % n ; ASSERT (((Int) hash) >= 0 && ((Int) hash) < n) ; /* if the Hhead array is not used: */ j = Head [hash] ; if (j <= EMPTY) { /* degree list is empty, hash head is FLIP (j) */ Next [i] = FLIP (j) ; Head [hash] = FLIP (i) ; } else { /* degree list is not empty, use Last [Head [hash]] as * hash head. */ Next [i] = Last [j] ; Last [j] = i ; } /* if a separate Hhead array is used: * Next [i] = Hhead [hash] ; Hhead [hash] = i ; */ Last [i] = hash ; } } Degree [me] = degme ; /* ----------------------------------------------------------------- */ /* Clear the counter array, W [...], by incrementing wflg. */ /* ----------------------------------------------------------------- */ /* make sure that wflg+n does not cause integer overflow */ lemax = MAX (lemax, degme) ; wflg += lemax ; wflg = clear_flag (wflg, wbig, W, n) ; /* at this point, W [0..n-1] < wflg holds */ /* ========================================================================= */ /* SUPERVARIABLE DETECTION */ /* ========================================================================= */ AMD_DEBUG1 (("Detecting supervariables:\n")) ; for (pme = pme1 ; pme <= pme2 ; pme++) { i = Iw [pme] ; ASSERT (i >= 0 && i < n) ; AMD_DEBUG2 (("Consider i "ID" nv "ID"\n", i, Nv [i])) ; if (Nv [i] < 0) { /* i is a principal variable in Lme */ /* --------------------------------------------------------- * examine all hash buckets with 2 or more variables. We do * this by examing all unique hash keys for supervariables in * the pattern Lme of the current element, me * --------------------------------------------------------- */ /* let i = head of hash bucket, and empty the hash bucket */ ASSERT (Last [i] >= 0 && Last [i] < n) ; hash = Last [i] ; /* if Hhead array is not used: */ j = Head [hash] ; if (j == EMPTY) { /* hash bucket and degree list are both empty */ i = EMPTY ; } else if (j < EMPTY) { /* degree list is empty */ i = FLIP (j) ; Head [hash] = EMPTY ; } else { /* degree list is not empty, restore Last [j] of head j */ i = Last [j] ; Last [j] = EMPTY ; } /* if separate Hhead array is used: * i = Hhead [hash] ; Hhead [hash] = EMPTY ; */ ASSERT (i >= EMPTY && i < n) ; AMD_DEBUG2 (("----i "ID" hash "ID"\n", i, hash)) ; while (i != EMPTY && Next [i] != EMPTY) { /* ----------------------------------------------------- * this bucket has one or more variables following i. * scan all of them to see if i can absorb any entries * that follow i in hash bucket. Scatter i into w. * ----------------------------------------------------- */ ln = Len [i] ; eln = Elen [i] ; ASSERT (ln >= 0 && eln >= 0) ; ASSERT (Pe [i] >= 0 && Pe [i] < iwlen) ; /* do not flag the first element in the list (me) */ for (p = Pe [i] + 1 ; p <= Pe [i] + ln - 1 ; p++) { ASSERT (Iw [p] >= 0 && Iw [p] < n) ; W [Iw [p]] = wflg ; } /* ----------------------------------------------------- */ /* scan every other entry j following i in bucket */ /* ----------------------------------------------------- */ jlast = i ; j = Next [i] ; ASSERT (j >= EMPTY && j < n) ; while (j != EMPTY) { /* ------------------------------------------------- */ /* check if j and i have identical nonzero pattern */ /* ------------------------------------------------- */ AMD_DEBUG3 (("compare i "ID" and j "ID"\n", i,j)) ; /* check if i and j have the same Len and Elen */ ASSERT (Len [j] >= 0 && Elen [j] >= 0) ; ASSERT (Pe [j] >= 0 && Pe [j] < iwlen) ; ok = (Len [j] == ln) && (Elen [j] == eln) ; /* skip the first element in the list (me) */ for (p = Pe [j] + 1 ; ok && p <= Pe [j] + ln - 1 ; p++) { ASSERT (Iw [p] >= 0 && Iw [p] < n) ; if (W [Iw [p]] != wflg) ok = 0 ; } if (ok) { /* --------------------------------------------- */ /* found it! j can be absorbed into i */ /* --------------------------------------------- */ AMD_DEBUG1 (("found it! j "ID" => i "ID"\n", j,i)); Pe [j] = FLIP (i) ; /* both Nv [i] and Nv [j] are negated since they */ /* are in Lme, and the absolute values of each */ /* are the number of variables in i and j: */ Nv [i] += Nv [j] ; Nv [j] = 0 ; Elen [j] = EMPTY ; /* delete j from hash bucket */ ASSERT (j != Next [j]) ; j = Next [j] ; Next [jlast] = j ; } else { /* j cannot be absorbed into i */ jlast = j ; ASSERT (j != Next [j]) ; j = Next [j] ; } ASSERT (j >= EMPTY && j < n) ; } /* ----------------------------------------------------- * no more variables can be absorbed into i * go to next i in bucket and clear flag array * ----------------------------------------------------- */ wflg++ ; i = Next [i] ; ASSERT (i >= EMPTY && i < n) ; } } } AMD_DEBUG2 (("detect done\n")) ; /* ========================================================================= */ /* RESTORE DEGREE LISTS AND REMOVE NONPRINCIPAL SUPERVARIABLES FROM ELEMENT */ /* ========================================================================= */ p = pme1 ; nleft = n - nel ; for (pme = pme1 ; pme <= pme2 ; pme++) { i = Iw [pme] ; ASSERT (i >= 0 && i < n) ; nvi = -Nv [i] ; AMD_DEBUG3 (("Restore i "ID" "ID"\n", i, nvi)) ; if (nvi > 0) { /* i is a principal variable in Lme */ /* restore Nv [i] to signify that i is principal */ Nv [i] = nvi ; /* --------------------------------------------------------- */ /* compute the external degree (add size of current element) */ /* --------------------------------------------------------- */ deg = Degree [i] + degme - nvi ; deg = MIN (deg, nleft - nvi) ; ASSERT (IMPLIES (aggressive, deg > 0) && deg >= 0 && deg < n) ; /* --------------------------------------------------------- */ /* place the supervariable at the head of the degree list */ /* --------------------------------------------------------- */ inext = Head [deg] ; ASSERT (inext >= EMPTY && inext < n) ; if (inext != EMPTY) Last [inext] = i ; Next [i] = inext ; Last [i] = EMPTY ; Head [deg] = i ; /* --------------------------------------------------------- */ /* save the new degree, and find the minimum degree */ /* --------------------------------------------------------- */ mindeg = MIN (mindeg, deg) ; Degree [i] = deg ; /* --------------------------------------------------------- */ /* place the supervariable in the element pattern */ /* --------------------------------------------------------- */ Iw [p++] = i ; } } AMD_DEBUG2 (("restore done\n")) ; /* ========================================================================= */ /* FINALIZE THE NEW ELEMENT */ /* ========================================================================= */ AMD_DEBUG2 (("ME = "ID" DONE\n", me)) ; Nv [me] = nvpiv ; /* save the length of the list for the new element me */ Len [me] = p - pme1 ; if (Len [me] == 0) { /* there is nothing left of the current pivot element */ /* it is a root of the assembly tree */ Pe [me] = EMPTY ; W [me] = 0 ; } if (elenme != 0) { /* element was not constructed in place: deallocate part of */ /* it since newly nonprincipal variables may have been removed */ pfree = p ; } /* The new element has nvpiv pivots and the size of the contribution * block for a multifrontal method is degme-by-degme, not including * the "dense" rows/columns. If the "dense" rows/columns are included, * the frontal matrix is no larger than * (degme+ndense)-by-(degme+ndense). */ if (Info != (double *) NULL) { f = nvpiv ; r = degme + ndense ; dmax = MAX (dmax, f + r) ; /* number of nonzeros in L (excluding the diagonal) */ lnzme = f*r + (f-1)*f/2 ; lnz += lnzme ; /* number of divide operations for LDL' and for LU */ ndiv += lnzme ; /* number of multiply-subtract pairs for LU */ s = f*r*r + r*(f-1)*f + (f-1)*f*(2*f-1)/6 ; nms_lu += s ; /* number of multiply-subtract pairs for LDL' */ nms_ldl += (s + lnzme)/2 ; } #ifndef NDEBUG AMD_DEBUG2 (("finalize done nel "ID" n "ID"\n ::::\n", nel, n)) ; for (pme = Pe [me] ; pme <= Pe [me] + Len [me] - 1 ; pme++) { AMD_DEBUG3 ((" "ID"", Iw [pme])) ; } AMD_DEBUG3 (("\n")) ; #endif } /* ========================================================================= */ /* DONE SELECTING PIVOTS */ /* ========================================================================= */ if (Info != (double *) NULL) { /* count the work to factorize the ndense-by-ndense submatrix */ f = ndense ; dmax = MAX (dmax, (double) ndense) ; /* number of nonzeros in L (excluding the diagonal) */ lnzme = (f-1)*f/2 ; lnz += lnzme ; /* number of divide operations for LDL' and for LU */ ndiv += lnzme ; /* number of multiply-subtract pairs for LU */ s = (f-1)*f*(2*f-1)/6 ; nms_lu += s ; /* number of multiply-subtract pairs for LDL' */ nms_ldl += (s + lnzme)/2 ; /* number of nz's in L (excl. diagonal) */ Info [AMD_LNZ] = lnz ; /* number of divide ops for LU and LDL' */ Info [AMD_NDIV] = ndiv ; /* number of multiply-subtract pairs for LDL' */ Info [AMD_NMULTSUBS_LDL] = nms_ldl ; /* number of multiply-subtract pairs for LU */ Info [AMD_NMULTSUBS_LU] = nms_lu ; /* number of "dense" rows/columns */ Info [AMD_NDENSE] = ndense ; /* largest front is dmax-by-dmax */ Info [AMD_DMAX] = dmax ; /* number of garbage collections in AMD */ Info [AMD_NCMPA] = ncmpa ; /* successful ordering */ Info [AMD_STATUS] = AMD_OK ; } /* ========================================================================= */ /* POST-ORDERING */ /* ========================================================================= */ /* ------------------------------------------------------------------------- * Variables at this point: * * Pe: holds the elimination tree. The parent of j is FLIP (Pe [j]), * or EMPTY if j is a root. The tree holds both elements and * non-principal (unordered) variables absorbed into them. * Dense variables are non-principal and unordered. * * Elen: holds the size of each element, including the diagonal part. * FLIP (Elen [e]) > 0 if e is an element. For unordered * variables i, Elen [i] is EMPTY. * * Nv: Nv [e] > 0 is the number of pivots represented by the element e. * For unordered variables i, Nv [i] is zero. * * Contents no longer needed: * W, Iw, Len, Degree, Head, Next, Last. * * The matrix itself has been destroyed. * * n: the size of the matrix. * No other scalars needed (pfree, iwlen, etc.) * ------------------------------------------------------------------------- */ /* restore Pe */ for (i = 0 ; i < n ; i++) { Pe [i] = FLIP (Pe [i]) ; } /* restore Elen, for output information, and for postordering */ for (i = 0 ; i < n ; i++) { Elen [i] = FLIP (Elen [i]) ; } /* Now the parent of j is Pe [j], or EMPTY if j is a root. Elen [e] > 0 * is the size of element e. Elen [i] is EMPTY for unordered variable i. */ #ifndef NDEBUG AMD_DEBUG2 (("\nTree:\n")) ; for (i = 0 ; i < n ; i++) { AMD_DEBUG2 ((" "ID" parent: "ID" ", i, Pe [i])) ; ASSERT (Pe [i] >= EMPTY && Pe [i] < n) ; if (Nv [i] > 0) { /* this is an element */ e = i ; AMD_DEBUG2 ((" element, size is "ID"\n", Elen [i])) ; ASSERT (Elen [e] > 0) ; } AMD_DEBUG2 (("\n")) ; } AMD_DEBUG2 (("\nelements:\n")) ; for (e = 0 ; e < n ; e++) { if (Nv [e] > 0) { AMD_DEBUG3 (("Element e= "ID" size "ID" nv "ID" \n", e, Elen [e], Nv [e])) ; } } AMD_DEBUG2 (("\nvariables:\n")) ; for (i = 0 ; i < n ; i++) { Int cnt ; if (Nv [i] == 0) { AMD_DEBUG3 (("i unordered: "ID"\n", i)) ; j = Pe [i] ; cnt = 0 ; AMD_DEBUG3 ((" j: "ID"\n", j)) ; if (j == EMPTY) { AMD_DEBUG3 ((" i is a dense variable\n")) ; } else { ASSERT (j >= 0 && j < n) ; while (Nv [j] == 0) { AMD_DEBUG3 ((" j : "ID"\n", j)) ; j = Pe [j] ; AMD_DEBUG3 ((" j:: "ID"\n", j)) ; cnt++ ; if (cnt > n) break ; } e = j ; AMD_DEBUG3 ((" got to e: "ID"\n", e)) ; } } } #endif /* ========================================================================= */ /* compress the paths of the variables */ /* ========================================================================= */ for (i = 0 ; i < n ; i++) { if (Nv [i] == 0) { /* ------------------------------------------------------------- * i is an un-ordered row. Traverse the tree from i until * reaching an element, e. The element, e, was the principal * supervariable of i and all nodes in the path from i to when e * was selected as pivot. * ------------------------------------------------------------- */ AMD_DEBUG1 (("Path compression, i unordered: "ID"\n", i)) ; j = Pe [i] ; ASSERT (j >= EMPTY && j < n) ; AMD_DEBUG3 ((" j: "ID"\n", j)) ; if (j == EMPTY) { /* Skip a dense variable. It has no parent. */ AMD_DEBUG3 ((" i is a dense variable\n")) ; continue ; } /* while (j is a variable) */ while (Nv [j] == 0) { AMD_DEBUG3 ((" j : "ID"\n", j)) ; j = Pe [j] ; AMD_DEBUG3 ((" j:: "ID"\n", j)) ; ASSERT (j >= 0 && j < n) ; } /* got to an element e */ e = j ; AMD_DEBUG3 (("got to e: "ID"\n", e)) ; /* ------------------------------------------------------------- * traverse the path again from i to e, and compress the path * (all nodes point to e). Path compression allows this code to * compute in O(n) time. * ------------------------------------------------------------- */ j = i ; /* while (j is a variable) */ while (Nv [j] == 0) { jnext = Pe [j] ; AMD_DEBUG3 (("j "ID" jnext "ID"\n", j, jnext)) ; Pe [j] = e ; j = jnext ; ASSERT (j >= 0 && j < n) ; } } } /* ========================================================================= */ /* postorder the assembly tree */ /* ========================================================================= */ AMD_postorder (n, Pe, Nv, Elen, W, /* output order */ Head, Next, Last) ; /* workspace */ /* ========================================================================= */ /* compute output permutation and inverse permutation */ /* ========================================================================= */ /* W [e] = k means that element e is the kth element in the new * order. e is in the range 0 to n-1, and k is in the range 0 to * the number of elements. Use Head for inverse order. */ for (k = 0 ; k < n ; k++) { Head [k] = EMPTY ; Next [k] = EMPTY ; } for (e = 0 ; e < n ; e++) { k = W [e] ; ASSERT ((k == EMPTY) == (Nv [e] == 0)) ; if (k != EMPTY) { ASSERT (k >= 0 && k < n) ; Head [k] = e ; } } /* construct output inverse permutation in Next, * and permutation in Last */ nel = 0 ; for (k = 0 ; k < n ; k++) { e = Head [k] ; if (e == EMPTY) break ; ASSERT (e >= 0 && e < n && Nv [e] > 0) ; Next [e] = nel ; nel += Nv [e] ; } ASSERT (nel == n - ndense) ; /* order non-principal variables (dense, & those merged into supervar's) */ for (i = 0 ; i < n ; i++) { if (Nv [i] == 0) { e = Pe [i] ; ASSERT (e >= EMPTY && e < n) ; if (e != EMPTY) { /* This is an unordered variable that was merged * into element e via supernode detection or mass * elimination of i when e became the pivot element. * Place i in order just before e. */ ASSERT (Next [i] == EMPTY && Nv [e] > 0) ; Next [i] = Next [e] ; Next [e]++ ; } else { /* This is a dense unordered variable, with no parent. * Place it last in the output order. */ Next [i] = nel++ ; } } } ASSERT (nel == n) ; AMD_DEBUG2 (("\n\nPerm:\n")) ; for (i = 0 ; i < n ; i++) { k = Next [i] ; ASSERT (k >= 0 && k < n) ; Last [k] = i ; AMD_DEBUG2 ((" perm ["ID"] = "ID"\n", k, i)) ; } } glpk-4.52.1/src/amd/amd_aat.c0000644000062000006210000001340112175147600015002 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_aat ============================================================= */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* AMD_aat: compute the symmetry of the pattern of A, and count the number of * nonzeros each column of A+A' (excluding the diagonal). Assumes the input * matrix has no errors, with sorted columns and no duplicates * (AMD_valid (n, n, Ap, Ai) must be AMD_OK, but this condition is not * checked). */ #include "amd_internal.h" GLOBAL size_t AMD_aat /* returns nz in A+A' */ ( Int n, const Int Ap [ ], const Int Ai [ ], Int Len [ ], /* Len [j]: length of column j of A+A', excl diagonal*/ Int Tp [ ], /* workspace of size n */ double Info [ ] ) { Int p1, p2, p, i, j, pj, pj2, k, nzdiag, nzboth, nz ; double sym ; size_t nzaat ; #ifndef NDEBUG AMD_debug_init ("AMD AAT") ; for (k = 0 ; k < n ; k++) Tp [k] = EMPTY ; ASSERT (AMD_valid (n, n, Ap, Ai) == AMD_OK) ; #endif if (Info != (double *) NULL) { /* clear the Info array, if it exists */ for (i = 0 ; i < AMD_INFO ; i++) { Info [i] = EMPTY ; } Info [AMD_STATUS] = AMD_OK ; } for (k = 0 ; k < n ; k++) { Len [k] = 0 ; } nzdiag = 0 ; nzboth = 0 ; nz = Ap [n] ; for (k = 0 ; k < n ; k++) { p1 = Ap [k] ; p2 = Ap [k+1] ; AMD_DEBUG2 (("\nAAT Column: "ID" p1: "ID" p2: "ID"\n", k, p1, p2)) ; /* construct A+A' */ for (p = p1 ; p < p2 ; ) { /* scan the upper triangular part of A */ j = Ai [p] ; if (j < k) { /* entry A (j,k) is in the strictly upper triangular part, * add both A (j,k) and A (k,j) to the matrix A+A' */ Len [j]++ ; Len [k]++ ; AMD_DEBUG3 ((" upper ("ID","ID") ("ID","ID")\n", j,k, k,j)); p++ ; } else if (j == k) { /* skip the diagonal */ p++ ; nzdiag++ ; break ; } else /* j > k */ { /* first entry below the diagonal */ break ; } /* scan lower triangular part of A, in column j until reaching * row k. Start where last scan left off. */ ASSERT (Tp [j] != EMPTY) ; ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ; pj2 = Ap [j+1] ; for (pj = Tp [j] ; pj < pj2 ; ) { i = Ai [pj] ; if (i < k) { /* A (i,j) is only in the lower part, not in upper. * add both A (i,j) and A (j,i) to the matrix A+A' */ Len [i]++ ; Len [j]++ ; AMD_DEBUG3 ((" lower ("ID","ID") ("ID","ID")\n", i,j, j,i)) ; pj++ ; } else if (i == k) { /* entry A (k,j) in lower part and A (j,k) in upper */ pj++ ; nzboth++ ; break ; } else /* i > k */ { /* consider this entry later, when k advances to i */ break ; } } Tp [j] = pj ; } /* Tp [k] points to the entry just below the diagonal in column k */ Tp [k] = p ; } /* clean up, for remaining mismatched entries */ for (j = 0 ; j < n ; j++) { for (pj = Tp [j] ; pj < Ap [j+1] ; pj++) { i = Ai [pj] ; /* A (i,j) is only in the lower part, not in upper. * add both A (i,j) and A (j,i) to the matrix A+A' */ Len [i]++ ; Len [j]++ ; AMD_DEBUG3 ((" lower cleanup ("ID","ID") ("ID","ID")\n", i,j, j,i)) ; } } /* --------------------------------------------------------------------- */ /* compute the symmetry of the nonzero pattern of A */ /* --------------------------------------------------------------------- */ /* Given a matrix A, the symmetry of A is: * B = tril (spones (A), -1) + triu (spones (A), 1) ; * sym = nnz (B & B') / nnz (B) ; * or 1 if nnz (B) is zero. */ if (nz == nzdiag) { sym = 1 ; } else { sym = (2 * (double) nzboth) / ((double) (nz - nzdiag)) ; } nzaat = 0 ; for (k = 0 ; k < n ; k++) { nzaat += Len [k] ; } AMD_DEBUG1 (("AMD nz in A+A', excluding diagonal (nzaat) = %g\n", (double) nzaat)) ; AMD_DEBUG1 ((" nzboth: "ID" nz: "ID" nzdiag: "ID" symmetry: %g\n", nzboth, nz, nzdiag, sym)) ; if (Info != (double *) NULL) { Info [AMD_STATUS] = AMD_OK ; Info [AMD_N] = n ; Info [AMD_NZ] = nz ; Info [AMD_SYMMETRY] = sym ; /* symmetry of pattern of A */ Info [AMD_NZDIAG] = nzdiag ; /* nonzeros on diagonal of A */ Info [AMD_NZ_A_PLUS_AT] = nzaat ; /* nonzeros in A+A' */ } return (nzaat) ; } glpk-4.52.1/src/amd/amd_control.c0000644000062000006210000000370112175147600015717 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_control ========================================================= */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* User-callable. Prints the control parameters for AMD. See amd.h * for details. If the Control array is not present, the defaults are * printed instead. */ #include "amd_internal.h" GLOBAL void AMD_control ( double Control [ ] ) { double alpha ; Int aggressive ; if (Control != (double *) NULL) { alpha = Control [AMD_DENSE] ; aggressive = Control [AMD_AGGRESSIVE] != 0 ; } else { alpha = AMD_DEFAULT_DENSE ; aggressive = AMD_DEFAULT_AGGRESSIVE ; } PRINTF (("\nAMD version %d.%d.%d, %s: approximate minimum degree ordering\n" " dense row parameter: %g\n", AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE, alpha)) ; if (alpha < 0) { PRINTF ((" no rows treated as dense\n")) ; } else { PRINTF (( " (rows with more than max (%g * sqrt (n), 16) entries are\n" " considered \"dense\", and placed last in output permutation)\n", alpha)) ; } if (aggressive) { PRINTF ((" aggressive absorption: yes\n")) ; } else { PRINTF ((" aggressive absorption: no\n")) ; } PRINTF ((" size of AMD integer: %d\n\n", sizeof (Int))) ; } glpk-4.52.1/src/amd/amd_defaults.c0000644000062000006210000000257312175147600016054 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_defaults ======================================================== */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* User-callable. Sets default control parameters for AMD. See amd.h * for details. */ #include "amd_internal.h" /* ========================================================================= */ /* === AMD defaults ======================================================== */ /* ========================================================================= */ GLOBAL void AMD_defaults ( double Control [ ] ) { Int i ; if (Control != (double *) NULL) { for (i = 0 ; i < AMD_CONTROL ; i++) { Control [i] = 0 ; } Control [AMD_DENSE] = AMD_DEFAULT_DENSE ; Control [AMD_AGGRESSIVE] = AMD_DEFAULT_AGGRESSIVE ; } } glpk-4.52.1/src/amd/amd_dump.c0000644000062000006210000001400112175147600015177 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_dump ============================================================ */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* Debugging routines for AMD. Not used if NDEBUG is not defined at compile- * time (the default). See comments in amd_internal.h on how to enable * debugging. Not user-callable. */ #include "amd_internal.h" #ifndef NDEBUG /* This global variable is present only when debugging */ GLOBAL Int AMD_debug = -999 ; /* default is no debug printing */ /* ========================================================================= */ /* === AMD_debug_init ====================================================== */ /* ========================================================================= */ /* Sets the debug print level, by reading the file debug.amd (if it exists) */ GLOBAL void AMD_debug_init ( char *s ) { FILE *f ; f = fopen ("debug.amd", "r") ; if (f == (FILE *) NULL) { AMD_debug = -999 ; } else { fscanf (f, ID, &AMD_debug) ; fclose (f) ; } if (AMD_debug >= 0) { printf ("%s: AMD_debug_init, D= "ID"\n", s, AMD_debug) ; } } /* ========================================================================= */ /* === AMD_dump ============================================================ */ /* ========================================================================= */ /* Dump AMD's data structure, except for the hash buckets. This routine * cannot be called when the hash buckets are non-empty. */ GLOBAL void AMD_dump ( Int n, /* A is n-by-n */ Int Pe [ ], /* pe [0..n-1]: index in iw of start of row i */ Int Iw [ ], /* workspace of size iwlen, iwlen [0..pfree-1] * holds the matrix on input */ Int Len [ ], /* len [0..n-1]: length for row i */ Int iwlen, /* length of iw */ Int pfree, /* iw [pfree ... iwlen-1] is empty on input */ Int Nv [ ], /* nv [0..n-1] */ Int Next [ ], /* next [0..n-1] */ Int Last [ ], /* last [0..n-1] */ Int Head [ ], /* head [0..n-1] */ Int Elen [ ], /* size n */ Int Degree [ ], /* size n */ Int W [ ], /* size n */ Int nel ) { Int i, pe, elen, nv, len, e, p, k, j, deg, w, cnt, ilast ; if (AMD_debug < 0) return ; ASSERT (pfree <= iwlen) ; AMD_DEBUG3 (("\nAMD dump, pfree: "ID"\n", pfree)) ; for (i = 0 ; i < n ; i++) { pe = Pe [i] ; elen = Elen [i] ; nv = Nv [i] ; len = Len [i] ; w = W [i] ; if (elen >= EMPTY) { if (nv == 0) { AMD_DEBUG3 (("\nI "ID": nonprincipal: ", i)) ; ASSERT (elen == EMPTY) ; if (pe == EMPTY) { AMD_DEBUG3 ((" dense node\n")) ; ASSERT (w == 1) ; } else { ASSERT (pe < EMPTY) ; AMD_DEBUG3 ((" i "ID" -> parent "ID"\n", i, FLIP (Pe[i]))); } } else { AMD_DEBUG3 (("\nI "ID": active principal supervariable:\n",i)); AMD_DEBUG3 ((" nv(i): "ID" Flag: %d\n", nv, (nv < 0))) ; ASSERT (elen >= 0) ; ASSERT (nv > 0 && pe >= 0) ; p = pe ; AMD_DEBUG3 ((" e/s: ")) ; if (elen == 0) AMD_DEBUG3 ((" : ")) ; ASSERT (pe + len <= pfree) ; for (k = 0 ; k < len ; k++) { j = Iw [p] ; AMD_DEBUG3 ((" "ID"", j)) ; ASSERT (j >= 0 && j < n) ; if (k == elen-1) AMD_DEBUG3 ((" : ")) ; p++ ; } AMD_DEBUG3 (("\n")) ; } } else { e = i ; if (w == 0) { AMD_DEBUG3 (("\nE "ID": absorbed element: w "ID"\n", e, w)) ; ASSERT (nv > 0 && pe < 0) ; AMD_DEBUG3 ((" e "ID" -> parent "ID"\n", e, FLIP (Pe [e]))) ; } else { AMD_DEBUG3 (("\nE "ID": unabsorbed element: w "ID"\n", e, w)) ; ASSERT (nv > 0 && pe >= 0) ; p = pe ; AMD_DEBUG3 ((" : ")) ; ASSERT (pe + len <= pfree) ; for (k = 0 ; k < len ; k++) { j = Iw [p] ; AMD_DEBUG3 ((" "ID"", j)) ; ASSERT (j >= 0 && j < n) ; p++ ; } AMD_DEBUG3 (("\n")) ; } } } /* this routine cannot be called when the hash buckets are non-empty */ AMD_DEBUG3 (("\nDegree lists:\n")) ; if (nel >= 0) { cnt = 0 ; for (deg = 0 ; deg < n ; deg++) { if (Head [deg] == EMPTY) continue ; ilast = EMPTY ; AMD_DEBUG3 ((ID": \n", deg)) ; for (i = Head [deg] ; i != EMPTY ; i = Next [i]) { AMD_DEBUG3 ((" "ID" : next "ID" last "ID" deg "ID"\n", i, Next [i], Last [i], Degree [i])) ; ASSERT (i >= 0 && i < n && ilast == Last [i] && deg == Degree [i]) ; cnt += Nv [i] ; ilast = i ; } AMD_DEBUG3 (("\n")) ; } ASSERT (cnt == n - nel) ; } } #endif glpk-4.52.1/src/amd/amd_info.c0000644000062000006210000001065612175147600015201 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_info ============================================================ */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* User-callable. Prints the output statistics for AMD. See amd.h * for details. If the Info array is not present, nothing is printed. */ #include "amd_internal.h" #define PRI(format,x) { if (x >= 0) { PRINTF ((format, x)) ; }} GLOBAL void AMD_info ( double Info [ ] ) { double n, ndiv, nmultsubs_ldl, nmultsubs_lu, lnz, lnzd ; PRINTF (("\nAMD version %d.%d.%d, %s, results:\n", AMD_MAIN_VERSION, AMD_SUB_VERSION, AMD_SUBSUB_VERSION, AMD_DATE)) ; if (!Info) { return ; } n = Info [AMD_N] ; ndiv = Info [AMD_NDIV] ; nmultsubs_ldl = Info [AMD_NMULTSUBS_LDL] ; nmultsubs_lu = Info [AMD_NMULTSUBS_LU] ; lnz = Info [AMD_LNZ] ; lnzd = (n >= 0 && lnz >= 0) ? (n + lnz) : (-1) ; /* AMD return status */ PRINTF ((" status: ")) ; if (Info [AMD_STATUS] == AMD_OK) { PRINTF (("OK\n")) ; } else if (Info [AMD_STATUS] == AMD_OUT_OF_MEMORY) { PRINTF (("out of memory\n")) ; } else if (Info [AMD_STATUS] == AMD_INVALID) { PRINTF (("invalid matrix\n")) ; } else if (Info [AMD_STATUS] == AMD_OK_BUT_JUMBLED) { PRINTF (("OK, but jumbled\n")) ; } else { PRINTF (("unknown\n")) ; } /* statistics about the input matrix */ PRI (" n, dimension of A: %.20g\n", n); PRI (" nz, number of nonzeros in A: %.20g\n", Info [AMD_NZ]) ; PRI (" symmetry of A: %.4f\n", Info [AMD_SYMMETRY]) ; PRI (" number of nonzeros on diagonal: %.20g\n", Info [AMD_NZDIAG]) ; PRI (" nonzeros in pattern of A+A' (excl. diagonal): %.20g\n", Info [AMD_NZ_A_PLUS_AT]) ; PRI (" # dense rows/columns of A+A': %.20g\n", Info [AMD_NDENSE]) ; /* statistics about AMD's behavior */ PRI (" memory used, in bytes: %.20g\n", Info [AMD_MEMORY]) ; PRI (" # of memory compactions: %.20g\n", Info [AMD_NCMPA]) ; /* statistics about the ordering quality */ PRINTF (("\n" " The following approximate statistics are for a subsequent\n" " factorization of A(P,P) + A(P,P)'. They are slight upper\n" " bounds if there are no dense rows/columns in A+A', and become\n" " looser if dense rows/columns exist.\n\n")) ; PRI (" nonzeros in L (excluding diagonal): %.20g\n", lnz) ; PRI (" nonzeros in L (including diagonal): %.20g\n", lnzd) ; PRI (" # divide operations for LDL' or LU: %.20g\n", ndiv) ; PRI (" # multiply-subtract operations for LDL': %.20g\n", nmultsubs_ldl) ; PRI (" # multiply-subtract operations for LU: %.20g\n", nmultsubs_lu) ; PRI (" max nz. in any column of L (incl. diagonal): %.20g\n", Info [AMD_DMAX]) ; /* total flop counts for various factorizations */ if (n >= 0 && ndiv >= 0 && nmultsubs_ldl >= 0 && nmultsubs_lu >= 0) { PRINTF (("\n" " chol flop count for real A, sqrt counted as 1 flop: %.20g\n" " LDL' flop count for real A: %.20g\n" " LDL' flop count for complex A: %.20g\n" " LU flop count for real A (with no pivoting): %.20g\n" " LU flop count for complex A (with no pivoting): %.20g\n\n", n + ndiv + 2*nmultsubs_ldl, ndiv + 2*nmultsubs_ldl, 9*ndiv + 8*nmultsubs_ldl, ndiv + 2*nmultsubs_lu, 9*ndiv + 8*nmultsubs_lu)) ; } } glpk-4.52.1/src/amd/amd_internal.h0000644000062000006210000000616412175147600016066 0ustar maomkpasswd/* amd_internal.h */ /* Written by Andrew Makhorin . */ #ifndef AMD_INTERNAL_H #define AMD_INTERNAL_H /* AMD will be exceedingly slow when running in debug mode. */ #if 1 #define NDEBUG #endif #include "amd.h" #define _GLPSTD_STDIO #include "env.h" #define Int int #define ID "%d" #define Int_MAX INT_MAX #if 0 /* 15/II-2012 */ /* now this macro is defined in glpenv.h; besides, the definiton below depends on implementation, because size_t is an unsigned type */ #define SIZE_T_MAX ((size_t)(-1)) #endif #define EMPTY (-1) #define FLIP(i) (-(i)-2) #define UNFLIP(i) ((i < EMPTY) ? FLIP (i) : (i)) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define IMPLIES(p, q) (!(p) || (q)) #define GLOBAL #define AMD_order amd_order #define AMD_defaults amd_defaults #define AMD_control amd_control #define AMD_info amd_info #define AMD_1 amd_1 #define AMD_2 amd_2 #define AMD_valid amd_valid #define AMD_aat amd_aat #define AMD_postorder amd_postorder #define AMD_post_tree amd_post_tree #define AMD_dump amd_dump #define AMD_debug amd_debug #define AMD_debug_init amd_debug_init #define AMD_preprocess amd_preprocess #define amd_malloc xmalloc #if 0 /* 24/V-2009 */ #define amd_free xfree #else #define amd_free(ptr) { if ((ptr) != NULL) xfree(ptr); } #endif #define amd_printf xprintf #define PRINTF(params) { amd_printf params; } #ifndef NDEBUG #define ASSERT(expr) xassert(expr) #define AMD_DEBUG0(params) { PRINTF(params); } #define AMD_DEBUG1(params) { if (AMD_debug >= 1) PRINTF(params); } #define AMD_DEBUG2(params) { if (AMD_debug >= 2) PRINTF(params); } #define AMD_DEBUG3(params) { if (AMD_debug >= 3) PRINTF(params); } #define AMD_DEBUG4(params) { if (AMD_debug >= 4) PRINTF(params); } #else #define ASSERT(expression) #define AMD_DEBUG0(params) #define AMD_DEBUG1(params) #define AMD_DEBUG2(params) #define AMD_DEBUG3(params) #define AMD_DEBUG4(params) #endif #define amd_aat _glp_amd_aat size_t AMD_aat(Int n, const Int Ap[], const Int Ai[], Int Len[], Int Tp[], double Info[]); #define amd_1 _glp_amd_1 void AMD_1(Int n, const Int Ap[], const Int Ai[], Int P[], Int Pinv[], Int Len[], Int slen, Int S[], double Control[], double Info[]); #define amd_postorder _glp_amd_postorder void AMD_postorder(Int nn, Int Parent[], Int Npiv[], Int Fsize[], Int Order[], Int Child[], Int Sibling[], Int Stack[]); #define amd_post_tree _glp_amd_post_tree #ifndef NDEBUG Int AMD_post_tree(Int root, Int k, Int Child[], const Int Sibling[], Int Order[], Int Stack[], Int nn); #else Int AMD_post_tree(Int root, Int k, Int Child[], const Int Sibling[], Int Order[], Int Stack[]); #endif #define amd_preprocess _glp_amd_preprocess void AMD_preprocess(Int n, const Int Ap[], const Int Ai[], Int Rp[], Int Ri[], Int W[], Int Flag[]); #define amd_debug _glp_amd_debug extern Int AMD_debug; #define amd_debug_init _glp_amd_debug_init void AMD_debug_init(char *s); #define amd_dump _glp_amd_dump void AMD_dump(Int n, Int Pe[], Int Iw[], Int Len[], Int iwlen, Int pfree, Int Nv[], Int Next[], Int Last[], Int Head[], Int Elen[], Int Degree[], Int W[], Int nel); #endif /* eof */ glpk-4.52.1/src/amd/amd_order.c0000644000062000006210000001451612175147600015360 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_order =========================================================== */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* User-callable AMD minimum degree ordering routine. See amd.h for * documentation. */ #include "amd_internal.h" /* ========================================================================= */ /* === AMD_order =========================================================== */ /* ========================================================================= */ GLOBAL Int AMD_order ( Int n, const Int Ap [ ], const Int Ai [ ], Int P [ ], double Control [ ], double Info [ ] ) { Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ; size_t nzaat, slen ; double mem = 0 ; #ifndef NDEBUG AMD_debug_init ("amd") ; #endif /* clear the Info array, if it exists */ info = Info != (double *) NULL ; if (info) { for (i = 0 ; i < AMD_INFO ; i++) { Info [i] = EMPTY ; } Info [AMD_N] = n ; Info [AMD_STATUS] = AMD_OK ; } /* make sure inputs exist and n is >= 0 */ if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0) { if (info) Info [AMD_STATUS] = AMD_INVALID ; return (AMD_INVALID) ; /* arguments are invalid */ } if (n == 0) { return (AMD_OK) ; /* n is 0 so there's nothing to do */ } nz = Ap [n] ; if (info) { Info [AMD_NZ] = nz ; } if (nz < 0) { if (info) Info [AMD_STATUS] = AMD_INVALID ; return (AMD_INVALID) ; } /* check if n or nz will cause size_t overflow */ if (((size_t) n) >= SIZE_T_MAX / sizeof (Int) || ((size_t) nz) >= SIZE_T_MAX / sizeof (Int)) { if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; /* problem too large */ } /* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */ status = AMD_valid (n, n, Ap, Ai) ; if (status == AMD_INVALID) { if (info) Info [AMD_STATUS] = AMD_INVALID ; return (AMD_INVALID) ; /* matrix is invalid */ } /* allocate two size-n integer workspaces */ Len = amd_malloc (n * sizeof (Int)) ; Pinv = amd_malloc (n * sizeof (Int)) ; mem += n ; mem += n ; if (!Len || !Pinv) { /* :: out of memory :: */ amd_free (Len) ; amd_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } if (status == AMD_OK_BUT_JUMBLED) { /* sort the input matrix and remove duplicate entries */ AMD_DEBUG1 (("Matrix is jumbled\n")) ; Rp = amd_malloc ((n+1) * sizeof (Int)) ; Ri = amd_malloc (MAX (nz,1) * sizeof (Int)) ; mem += (n+1) ; mem += MAX (nz,1) ; if (!Rp || !Ri) { /* :: out of memory :: */ amd_free (Rp) ; amd_free (Ri) ; amd_free (Len) ; amd_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } /* use Len and Pinv as workspace to create R = A' */ AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ; Cp = Rp ; Ci = Ri ; } else { /* order the input matrix as-is. No need to compute R = A' first */ Rp = NULL ; Ri = NULL ; Cp = (Int *) Ap ; Ci = (Int *) Ai ; } /* --------------------------------------------------------------------- */ /* determine the symmetry and count off-diagonal nonzeros in A+A' */ /* --------------------------------------------------------------------- */ nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ; AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ; ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ; /* --------------------------------------------------------------------- */ /* allocate workspace for matrix, elbow room, and 6 size-n vectors */ /* --------------------------------------------------------------------- */ S = NULL ; slen = nzaat ; /* space for matrix */ ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */ slen += nzaat/5 ; /* add elbow room */ for (i = 0 ; ok && i < 7 ; i++) { ok = ((slen + n) > slen) ; /* check for size_t overflow */ slen += n ; /* size-n elbow room, 6 size-n work */ } mem += slen ; ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */ ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */ if (ok) { S = amd_malloc (slen * sizeof (Int)) ; } AMD_DEBUG1 (("slen %g\n", (double) slen)) ; if (!S) { /* :: out of memory :: (or problem too large) */ amd_free (Rp) ; amd_free (Ri) ; amd_free (Len) ; amd_free (Pinv) ; if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ; return (AMD_OUT_OF_MEMORY) ; } if (info) { /* memory usage, in bytes. */ Info [AMD_MEMORY] = mem * sizeof (Int) ; } /* --------------------------------------------------------------------- */ /* order the matrix */ /* --------------------------------------------------------------------- */ AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ; /* --------------------------------------------------------------------- */ /* free the workspace */ /* --------------------------------------------------------------------- */ amd_free (Rp) ; amd_free (Ri) ; amd_free (Len) ; amd_free (Pinv) ; amd_free (S) ; if (info) Info [AMD_STATUS] = status ; return (status) ; /* successful ordering */ } glpk-4.52.1/src/amd/amd_postorder.c0000644000062000006210000001543112175147600016263 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_postorder ======================================================= */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* Perform a postordering (via depth-first search) of an assembly tree. */ #include "amd_internal.h" GLOBAL void AMD_postorder ( /* inputs, not modified on output: */ Int nn, /* nodes are in the range 0..nn-1 */ Int Parent [ ], /* Parent [j] is the parent of j, or EMPTY if root */ Int Nv [ ], /* Nv [j] > 0 number of pivots represented by node j, * or zero if j is not a node. */ Int Fsize [ ], /* Fsize [j]: size of node j */ /* output, not defined on input: */ Int Order [ ], /* output post-order */ /* workspaces of size nn: */ Int Child [ ], Int Sibling [ ], Int Stack [ ] ) { Int i, j, k, parent, frsize, f, fprev, maxfrsize, bigfprev, bigf, fnext ; for (j = 0 ; j < nn ; j++) { Child [j] = EMPTY ; Sibling [j] = EMPTY ; } /* --------------------------------------------------------------------- */ /* place the children in link lists - bigger elements tend to be last */ /* --------------------------------------------------------------------- */ for (j = nn-1 ; j >= 0 ; j--) { if (Nv [j] > 0) { /* this is an element */ parent = Parent [j] ; if (parent != EMPTY) { /* place the element in link list of the children its parent */ /* bigger elements will tend to be at the end of the list */ Sibling [j] = Child [parent] ; Child [parent] = j ; } } } #ifndef NDEBUG { Int nels, ff, nchild ; AMD_DEBUG1 (("\n\n================================ AMD_postorder:\n")); nels = 0 ; for (j = 0 ; j < nn ; j++) { if (Nv [j] > 0) { AMD_DEBUG1 (( ""ID" : nels "ID" npiv "ID" size "ID " parent "ID" maxfr "ID"\n", j, nels, Nv [j], Fsize [j], Parent [j], Fsize [j])) ; /* this is an element */ /* dump the link list of children */ nchild = 0 ; AMD_DEBUG1 ((" Children: ")) ; for (ff = Child [j] ; ff != EMPTY ; ff = Sibling [ff]) { AMD_DEBUG1 ((ID" ", ff)) ; ASSERT (Parent [ff] == j) ; nchild++ ; ASSERT (nchild < nn) ; } AMD_DEBUG1 (("\n")) ; parent = Parent [j] ; if (parent != EMPTY) { ASSERT (Nv [parent] > 0) ; } nels++ ; } } } AMD_DEBUG1 (("\n\nGo through the children of each node, and put\n" "the biggest child last in each list:\n")) ; #endif /* --------------------------------------------------------------------- */ /* place the largest child last in the list of children for each node */ /* --------------------------------------------------------------------- */ for (i = 0 ; i < nn ; i++) { if (Nv [i] > 0 && Child [i] != EMPTY) { #ifndef NDEBUG Int nchild ; AMD_DEBUG1 (("Before partial sort, element "ID"\n", i)) ; nchild = 0 ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { ASSERT (f >= 0 && f < nn) ; AMD_DEBUG1 ((" f: "ID" size: "ID"\n", f, Fsize [f])) ; nchild++ ; ASSERT (nchild <= nn) ; } #endif /* find the biggest element in the child list */ fprev = EMPTY ; maxfrsize = EMPTY ; bigfprev = EMPTY ; bigf = EMPTY ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { ASSERT (f >= 0 && f < nn) ; frsize = Fsize [f] ; if (frsize >= maxfrsize) { /* this is the biggest seen so far */ maxfrsize = frsize ; bigfprev = fprev ; bigf = f ; } fprev = f ; } ASSERT (bigf != EMPTY) ; fnext = Sibling [bigf] ; AMD_DEBUG1 (("bigf "ID" maxfrsize "ID" bigfprev "ID" fnext "ID " fprev " ID"\n", bigf, maxfrsize, bigfprev, fnext, fprev)) ; if (fnext != EMPTY) { /* if fnext is EMPTY then bigf is already at the end of list */ if (bigfprev == EMPTY) { /* delete bigf from the element of the list */ Child [i] = fnext ; } else { /* delete bigf from the middle of the list */ Sibling [bigfprev] = fnext ; } /* put bigf at the end of the list */ Sibling [bigf] = EMPTY ; ASSERT (Child [i] != EMPTY) ; ASSERT (fprev != bigf) ; ASSERT (fprev != EMPTY) ; Sibling [fprev] = bigf ; } #ifndef NDEBUG AMD_DEBUG1 (("After partial sort, element "ID"\n", i)) ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { ASSERT (f >= 0 && f < nn) ; AMD_DEBUG1 ((" "ID" "ID"\n", f, Fsize [f])) ; ASSERT (Nv [f] > 0) ; nchild-- ; } ASSERT (nchild == 0) ; #endif } } /* --------------------------------------------------------------------- */ /* postorder the assembly tree */ /* --------------------------------------------------------------------- */ for (i = 0 ; i < nn ; i++) { Order [i] = EMPTY ; } k = 0 ; for (i = 0 ; i < nn ; i++) { if (Parent [i] == EMPTY && Nv [i] > 0) { AMD_DEBUG1 (("Root of assembly tree "ID"\n", i)) ; k = AMD_post_tree (i, k, Child, Sibling, Order, Stack #ifndef NDEBUG , nn #endif ) ; } } } glpk-4.52.1/src/amd/amd_post_tree.c0000644000062000006210000001070512175147600016245 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_post_tree ======================================================= */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* Post-ordering of a supernodal elimination tree. */ #include "amd_internal.h" GLOBAL Int AMD_post_tree ( Int root, /* root of the tree */ Int k, /* start numbering at k */ Int Child [ ], /* input argument of size nn, undefined on * output. Child [i] is the head of a link * list of all nodes that are children of node * i in the tree. */ const Int Sibling [ ], /* input argument of size nn, not modified. * If f is a node in the link list of the * children of node i, then Sibling [f] is the * next child of node i. */ Int Order [ ], /* output order, of size nn. Order [i] = k * if node i is the kth node of the reordered * tree. */ Int Stack [ ] /* workspace of size nn */ #ifndef NDEBUG , Int nn /* nodes are in the range 0..nn-1. */ #endif ) { Int f, head, h, i ; #if 0 /* --------------------------------------------------------------------- */ /* recursive version (Stack [ ] is not used): */ /* --------------------------------------------------------------------- */ /* this is simple, but can caouse stack overflow if nn is large */ i = root ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { k = AMD_post_tree (f, k, Child, Sibling, Order, Stack, nn) ; } Order [i] = k++ ; return (k) ; #endif /* --------------------------------------------------------------------- */ /* non-recursive version, using an explicit stack */ /* --------------------------------------------------------------------- */ /* push root on the stack */ head = 0 ; Stack [0] = root ; while (head >= 0) { /* get head of stack */ ASSERT (head < nn) ; i = Stack [head] ; AMD_DEBUG1 (("head of stack "ID" \n", i)) ; ASSERT (i >= 0 && i < nn) ; if (Child [i] != EMPTY) { /* the children of i are not yet ordered */ /* push each child onto the stack in reverse order */ /* so that small ones at the head of the list get popped first */ /* and the biggest one at the end of the list gets popped last */ for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { head++ ; ASSERT (head < nn) ; ASSERT (f >= 0 && f < nn) ; } h = head ; ASSERT (head < nn) ; for (f = Child [i] ; f != EMPTY ; f = Sibling [f]) { ASSERT (h > 0) ; Stack [h--] = f ; AMD_DEBUG1 (("push "ID" on stack\n", f)) ; ASSERT (f >= 0 && f < nn) ; } ASSERT (Stack [h] == i) ; /* delete child list so that i gets ordered next time we see it */ Child [i] = EMPTY ; } else { /* the children of i (if there were any) are already ordered */ /* remove i from the stack and order it. Front i is kth front */ head-- ; AMD_DEBUG1 (("pop "ID" order "ID"\n", i, k)) ; Order [i] = k++ ; ASSERT (k <= nn) ; } #ifndef NDEBUG AMD_DEBUG1 (("\nStack:")) ; for (h = head ; h >= 0 ; h--) { Int j = Stack [h] ; AMD_DEBUG1 ((" "ID, j)) ; ASSERT (j >= 0 && j < nn) ; } AMD_DEBUG1 (("\n\n")) ; ASSERT (head < nn) ; #endif } return (k) ; } glpk-4.52.1/src/amd/amd_preprocess.c0000644000062000006210000001017712175147600016431 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_preprocess ====================================================== */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* Sorts, removes duplicate entries, and transposes from the nonzero pattern of * a column-form matrix A, to obtain the matrix R. The input matrix can have * duplicate entries and/or unsorted columns (AMD_valid (n,Ap,Ai) must not be * AMD_INVALID). * * This input condition is NOT checked. This routine is not user-callable. */ #include "amd_internal.h" /* ========================================================================= */ /* === AMD_preprocess ====================================================== */ /* ========================================================================= */ /* AMD_preprocess does not check its input for errors or allocate workspace. * On input, the condition (AMD_valid (n,n,Ap,Ai) != AMD_INVALID) must hold. */ GLOBAL void AMD_preprocess ( Int n, /* input matrix: A is n-by-n */ const Int Ap [ ], /* size n+1 */ const Int Ai [ ], /* size nz = Ap [n] */ /* output matrix R: */ Int Rp [ ], /* size n+1 */ Int Ri [ ], /* size nz (or less, if duplicates present) */ Int W [ ], /* workspace of size n */ Int Flag [ ] /* workspace of size n */ ) { /* --------------------------------------------------------------------- */ /* local variables */ /* --------------------------------------------------------------------- */ Int i, j, p, p2 ; ASSERT (AMD_valid (n, n, Ap, Ai) != AMD_INVALID) ; /* --------------------------------------------------------------------- */ /* count the entries in each row of A (excluding duplicates) */ /* --------------------------------------------------------------------- */ for (i = 0 ; i < n ; i++) { W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */ Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */ } for (j = 0 ; j < n ; j++) { p2 = Ap [j+1] ; for (p = Ap [j] ; p < p2 ; p++) { i = Ai [p] ; if (Flag [i] != j) { /* row index i has not yet appeared in column j */ W [i]++ ; /* one more entry in row i */ Flag [i] = j ; /* flag row index i as appearing in col j*/ } } } /* --------------------------------------------------------------------- */ /* compute the row pointers for R */ /* --------------------------------------------------------------------- */ Rp [0] = 0 ; for (i = 0 ; i < n ; i++) { Rp [i+1] = Rp [i] + W [i] ; } for (i = 0 ; i < n ; i++) { W [i] = Rp [i] ; Flag [i] = EMPTY ; } /* --------------------------------------------------------------------- */ /* construct the row form matrix R */ /* --------------------------------------------------------------------- */ /* R = row form of pattern of A */ for (j = 0 ; j < n ; j++) { p2 = Ap [j+1] ; for (p = Ap [j] ; p < p2 ; p++) { i = Ai [p] ; if (Flag [i] != j) { /* row index i has not yet appeared in column j */ Ri [W [i]++] = j ; /* put col j in row i */ Flag [i] = j ; /* flag row index i as appearing in col j*/ } } } #ifndef NDEBUG ASSERT (AMD_valid (n, n, Rp, Ri) == AMD_OK) ; for (j = 0 ; j < n ; j++) { ASSERT (W [j] == Rp [j+1]) ; } #endif } glpk-4.52.1/src/amd/amd_valid.c0000644000062000006210000000651512175147600015344 0ustar maomkpasswd/* ========================================================================= */ /* === AMD_valid =========================================================== */ /* ========================================================================= */ /* ------------------------------------------------------------------------- */ /* AMD, Copyright (c) Timothy A. Davis, */ /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */ /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */ /* web: http://www.cise.ufl.edu/research/sparse/amd */ /* ------------------------------------------------------------------------- */ /* Check if a column-form matrix is valid or not. The matrix A is * n_row-by-n_col. The row indices of entries in column j are in * Ai [Ap [j] ... Ap [j+1]-1]. Required conditions are: * * n_row >= 0 * n_col >= 0 * nz = Ap [n_col] >= 0 number of entries in the matrix * Ap [0] == 0 * Ap [j] <= Ap [j+1] for all j in the range 0 to n_col. * Ai [0 ... nz-1] must be in the range 0 to n_row-1. * * If any of the above conditions hold, AMD_INVALID is returned. If the * following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning, * not an error): * * row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending * order, and/or duplicate entries exist. * * Otherwise, AMD_OK is returned. * * In v1.2 and earlier, this function returned TRUE if the matrix was valid * (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or * AMD_OK_BUT_JUMBLED). */ #include "amd_internal.h" GLOBAL Int AMD_valid ( /* inputs, not modified on output: */ Int n_row, /* A is n_row-by-n_col */ Int n_col, const Int Ap [ ], /* column pointers of A, of size n_col+1 */ const Int Ai [ ] /* row indices of A, of size nz = Ap [n_col] */ ) { Int nz, j, p1, p2, ilast, i, p, result = AMD_OK ; if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL) { return (AMD_INVALID) ; } nz = Ap [n_col] ; if (Ap [0] != 0 || nz < 0) { /* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */ AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ; return (AMD_INVALID) ; } for (j = 0 ; j < n_col ; j++) { p1 = Ap [j] ; p2 = Ap [j+1] ; AMD_DEBUG2 (("\nColumn: "ID" p1: "ID" p2: "ID"\n", j, p1, p2)) ; if (p1 > p2) { /* column pointers must be ascending */ AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ; return (AMD_INVALID) ; } ilast = EMPTY ; for (p = p1 ; p < p2 ; p++) { i = Ai [p] ; AMD_DEBUG3 (("row: "ID"\n", i)) ; if (i < 0 || i >= n_row) { /* row index out of range */ AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)); return (AMD_INVALID) ; } if (i <= ilast) { /* row index unsorted, or duplicate entry present */ AMD_DEBUG1 (("index unsorted/dupl col "ID" row "ID"\n", j, i)); result = AMD_OK_BUT_JUMBLED ; } ilast = i ; } } return (result) ; } glpk-4.52.1/src/amd/COPYING0000644000062000006210000006362512175147600014320 0ustar maomkpasswd GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is 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. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! glpk-4.52.1/src/amd/README0000644000062000006210000000461712175147600014141 0ustar maomkpasswdNOTE: Files in this subdirectory are NOT part of the GLPK package, but are used with GLPK. The original code was modified according to GLPK requirements by Andrew Makhorin . ************************************************************************ AMD Version 2.2, Copyright (C) 2007 by Timothy A. Davis, Patrick R. Amestoy, and Iain S. Duff. All Rights Reserved. Description: AMD is a set of routines for pre-ordering sparse matrices prior to Cholesky or LU factorization, using the approximate minimum degree ordering algorithm. Written in ANSI/ISO C with a MATLAB interface, and in Fortran 77. Authors: Timothy A. Davis (davis at cise.ufl.edu), University of Florida. Patrick R. Amestoy, ENSEEIHT, Toulouse, France. Iain S. Duff, Rutherford Appleton Laboratory, UK. AMD License: Your use or distribution of AMD or any modified version of AMD implies that you agree to this License. This library is 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. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 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. AMD is available under alternate licences; contact T. Davis for details. Availability: http://www.cise.ufl.edu/research/sparse/amd glpk-4.52.1/src/bflib/0000755000062000006210000000000012175147600013566 5ustar maomkpasswdglpk-4.52.1/src/bflib/fhv.c0000644000062000006210000005476312175147600014534 0ustar maomkpasswd/* fhv.c (sparse updatable FHV-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "fhv.h" /*********************************************************************** * fhv_ft_update - update FHV-factorization (Forrest-Tomlin) * * This routine updates FHV-factorization of the original matrix A * after replacing its j-th column by a new one. The routine is based * on the method proposed by Forrest and Tomlin [1]. * * The parameter q specifies the number of column of A, which has been * replaced, 1 <= q <= n, where n is the order of A. * * Row indices and numerical values of non-zero elements of the new * j-th column of A should be placed in locations aq_ind[1], ..., * aq_ind[aq_len] and aq_val[1], ..., aq_val[aq_len], respectively, * where aq_len is the number of non-zeros. Neither zero nor duplicate * elements are allowed. * * The working arrays ind, val, and work should have at least 1+n * elements (0-th elements are not used). * * RETURNS * * 0 The factorization has been successfully updated. * * 1 New matrix U = P'* V * Q' is upper triangular with zero diagonal * element u[s,s]. (Elimination was not performed.) * * 2 New matrix U = P'* V * Q' is upper triangular, and its diagonal * element u[s,s] or u[t,t] is too small in magnitude. (Elimination * was not performed.) * * 3 The same as 2, but after performing elimination. * * 4 The factorization has not been updated, because maximal number of * updates has been reached. * * 5 Accuracy test failed for the updated factorization. * * BACKGROUND * * The routine is based on the updating method proposed by Forrest and * Tomlin [1]. * * Let q-th column of the original matrix A have been replaced by new * column A[q]. Then, to keep the equality A = F * H * V, q-th column * of matrix V should be replaced by column V[q] = inv(F * H) * A[q]. * From the standpoint of matrix U = P'* V * Q' such replacement is * equivalent to replacement of s-th column of matrix U, where s is * determined from q by permutation matrix Q. Thus, matrix U loses its * upper triangular form and becomes the following: * * 1 s t n * 1 x x * x x x x x x * . x * x x x x x x * s . . * x x x x x x * . . * x x x x x x * . . * . x x x x x * . . * . . x x x x * t . . * . . . x x x * . . . . . . . x x * n . . . . . . . . x * * where t is largest row index of a non-zero element in s-th column. * * The routine makes matrix U upper triangular as follows. First, it * moves rows and columns s+1, ..., t by one position to the left and * upwards, resp., and moves s-th row and s-th column to position t. * Due to such symmetric permutations matrix U becomes the following * (note that all diagonal elements remain on the diagonal, and element * u[s,s] becomes u[t,t]): * * 1 s t n * 1 x x x x x x * x x * . x x x x x * x x * s . . x x x x * x x * . . . x x x * x x * . . . . x x * x x * . . . . . x * x x * t . . x x x x * x x * . . . . . . . x x * n . . . . . . . . x * * Then the routine performs gaussian elimination to eliminate * subdiagonal elements u[t,s], ..., u[t,t-1] using diagonal elements * u[s,s], ..., u[t-1,t-1] as pivots. During the elimination process * the routine permutes neither rows nor columns, so only t-th row is * changed. Should note that actually all operations are performed on * matrix V = P * U * Q, since matrix U is not stored. * * To keep the equality A = F * H * V, the routine appends new row-like * factor H[k] to matrix H, and every time it applies elementary * gaussian transformation to eliminate u[t,j'] = v[p,j] using pivot * u[j',j'] = v[i,j], it also adds new element f[p,j] = v[p,j] / v[i,j] * (gaussian multiplier) to factor H[k], which initially is a unity * matrix. At the end of elimination process the row-like factor H[k] * may look as follows: * * 1 n 1 s t n * 1 1 . . . . . . . . 1 1 . . . . . . . . * . 1 . . . . . . . . 1 . . . . . . . * . . 1 . . . . . . s . . 1 . . . . . . * p . x x 1 . x . x . . . . 1 . . . . . * . . . . 1 . . . . . . . . 1 . . . . * . . . . . 1 . . . . . . . . 1 . . . * . . . . . . 1 . . t . . x x x x 1 . . * . . . . . . . 1 . . . . . . . . 1 . * n . . . . . . . . 1 n . . . . . . . . 1 * * H[k] inv(P) * H[k] * P * * If, however, s = t, no elimination is needed, in which case no new * row-like factor is created. * * REFERENCES * * 1. J.J.H.Forrest and J.A.Tomlin, "Updated triangular factors of the * basis to maintain sparsity in the product form simplex method," * Math. Prog. 2 (1972), pp. 263-78. */ int fhv_ft_update(FHV *fhv, int q, int aq_len, const int aq_ind[], const double aq_val[], int ind[/*1+n*/], double val[/*1+n*/], double work[/*1+n*/]) { LUF *luf = fhv->luf; int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int *vr_cap = &sva->cap[vr_ref-1]; double *vr_piv = luf->vr_piv; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *vc_cap = &sva->cap[vc_ref-1]; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; int *qq_ind = luf->qq_ind; int *qq_inv = luf->qq_inv; int *hh_ind = fhv->hh_ind; int hh_ref = fhv->hh_ref; int *hh_ptr = &sva->ptr[hh_ref-1]; int *hh_len = &sva->len[hh_ref-1]; #if 1 /* FIXME */ const double eps_tol = DBL_EPSILON; const double vpq_tol = 1e-5; const double err_tol = 1e-10; #endif int end, i, i_end, i_ptr, j, j_end, j_ptr, k, len, nnz, p, p_end, p_ptr, ptr, q_end, q_ptr, s, t; double f, vpq, temp; /*--------------------------------------------------------------*/ /* replace current q-th column of matrix V by new one */ /*--------------------------------------------------------------*/ xassert(1 <= q && q <= n); /* convert new q-th column of matrix A to dense format */ for (i = 1; i <= n; i++) val[i] = 0.0; xassert(0 <= aq_len && aq_len <= n); for (k = 1; k <= aq_len; k++) { i = aq_ind[k]; xassert(1 <= i && i <= n); xassert(val[i] == 0.0); xassert(aq_val[k] != 0.0); val[i] = aq_val[k]; } /* compute new q-th column of matrix V: * new V[q] = inv(F * H) * (new A[q]) */ luf->pp_ind = fhv->p0_ind; luf->pp_inv = fhv->p0_inv; luf_f_solve(luf, val); luf->pp_ind = pp_ind; luf->pp_inv = pp_inv; fhv_h_solve(fhv, val); /* q-th column of V = s-th column of U */ s = qq_inv[q]; /* determine row number of element v[p,q] that corresponds to * diagonal element u[s,s] */ p = pp_inv[s]; /* convert new q-th column of V to sparse format; * element v[p,q] = u[s,s] is not included in the element list * and stored separately */ vpq = 0.0; len = 0; for (i = 1; i <= n; i++) { temp = val[i]; #if 1 /* FIXME */ if (-eps_tol < temp && temp < +eps_tol) #endif /* nop */; else if (i == p) vpq = temp; else { ind[++len] = i; val[len] = temp; } } /* clear q-th column of matrix V */ for (q_end = (q_ptr = vc_ptr[q]) + vc_len[q]; q_ptr < q_end; q_ptr++) { /* get row index of v[i,q] */ i = sv_ind[q_ptr]; /* find and remove v[i,q] from i-th row */ for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; sv_ind[i_ptr] != q; i_ptr++) /* nop */; xassert(i_ptr < i_end); sv_ind[i_ptr] = sv_ind[i_end-1]; sv_val[i_ptr] = sv_val[i_end-1]; vr_len[i]--; } /* now q-th column of matrix V is empty */ vc_len[q] = 0; /* put new q-th column of V (except element v[p,q] = u[s,s]) in * column-wise format */ if (len > 0) { if (vc_cap[q] < len) { if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_enlarge_cap(sva, vc_ref-1+q, len, 0); } ptr = vc_ptr[q]; memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); vc_len[q] = len; } /* put new q-th column of V (except element v[p,q] = u[s,s]) in * row-wise format, and determine largest row number t such that * u[s,t] != 0 */ t = (vpq == 0.0 ? 0 : s); for (k = 1; k <= len; k++) { /* get row index of v[i,q] */ i = ind[k]; /* put v[i,q] to i-th row */ if (vr_cap[i] == vr_len[i]) { /* reserve extra locations in i-th row to reduce further * relocations of that row */ #if 1 /* FIXME */ int need = vr_len[i] + 5; #endif if (sva->r_ptr - sva->m_ptr < need) { sva_more_space(sva, need); sv_ind = sva->ind; sv_val = sva->val; } sva_enlarge_cap(sva, vr_ref-1+i, need, 0); } sv_ind[ptr = vr_ptr[i] + (vr_len[i]++)] = q; sv_val[ptr] = val[k]; /* v[i,q] is non-zero; increase t */ if (t < pp_ind[i]) t = pp_ind[i]; } /*--------------------------------------------------------------*/ /* check if matrix U is already upper triangular */ /*--------------------------------------------------------------*/ /* check if there is a spike in s-th column of matrix U, which * is q-th column of matrix V */ if (s >= t) { /* no spike; matrix U is already upper triangular */ /* store its diagonal element u[s,s] = v[p,q] */ vr_piv[p] = vpq; if (s > t) { /* matrix U is structurally singular, because its diagonal * element u[s,s] = v[p,q] is exact zero */ xassert(vpq == 0.0); return 1; } #if 1 /* FIXME */ else if (-vpq_tol < vpq && vpq < +vpq_tol) #endif { /* matrix U is not well conditioned, because its diagonal * element u[s,s] = v[p,q] is too small in magnitude */ return 2; } else { /* normal case */ return 0; } } /*--------------------------------------------------------------*/ /* perform implicit symmetric permutations of rows and columns */ /* of matrix U */ /*--------------------------------------------------------------*/ /* currently v[p,q] = u[s,s] */ xassert(p == pp_inv[s] && q == qq_ind[s]); for (k = s; k < t; k++) { pp_ind[pp_inv[k] = pp_inv[k+1]] = k; qq_inv[qq_ind[k] = qq_ind[k+1]] = k; } /* now v[p,q] = u[t,t] */ pp_ind[pp_inv[t] = p] = qq_inv[qq_ind[t] = q] = t; /*--------------------------------------------------------------*/ /* check if matrix U is already upper triangular */ /*--------------------------------------------------------------*/ /* check if there is a spike in t-th row of matrix U, which is * p-th row of matrix V */ for (p_end = (p_ptr = vr_ptr[p]) + vr_len[p]; p_ptr < p_end; p_ptr++) { if (qq_inv[sv_ind[p_ptr]] < t) break; /* spike detected */ } if (p_ptr == p_end) { /* no spike; matrix U is already upper triangular */ /* store its diagonal element u[t,t] = v[p,q] */ vr_piv[p] = vpq; #if 1 /* FIXME */ if (-vpq_tol < vpq && vpq < +vpq_tol) #endif { /* matrix U is not well conditioned, because its diagonal * element u[t,t] = v[p,q] is too small in magnitude */ return 2; } else { /* normal case */ return 0; } } /*--------------------------------------------------------------*/ /* copy p-th row of matrix V, which is t-th row of matrix U, to */ /* working array */ /*--------------------------------------------------------------*/ /* copy p-th row of matrix V, including element v[p,q] = u[t,t], * to the working array in dense format and remove these elements * from matrix V; since no pivoting is used, only this row will * change during elimination */ for (j = 1; j <= n; j++) work[j] = 0.0; work[q] = vpq; for (p_end = (p_ptr = vr_ptr[p]) + vr_len[p]; p_ptr < p_end; p_ptr++) { /* get column index of v[p,j] and store this element to the * working array */ work[j = sv_ind[p_ptr]] = sv_val[p_ptr]; /* find and remove v[p,j] from j-th column */ for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; sv_ind[j_ptr] != p; j_ptr++) /* nop */; xassert(j_ptr < j_end); sv_ind[j_ptr] = sv_ind[j_end-1]; sv_val[j_ptr] = sv_val[j_end-1]; vc_len[j]--; } /* now p-th row of matrix V is temporarily empty */ vr_len[p] = 0; /*--------------------------------------------------------------*/ /* perform gaussian elimination */ /*--------------------------------------------------------------*/ /* transform p-th row of matrix V stored in working array, which * is t-th row of matrix U, to eliminate subdiagonal elements * u[t,s], ..., u[t,t-1]; corresponding gaussian multipliers will * form non-trivial row of new row-like factor */ nnz = 0; /* number of non-zero gaussian multipliers */ for (k = s; k < t; k++) { /* diagonal element u[k,k] = v[i,j] is used as pivot */ i = pp_inv[k], j = qq_ind[k]; /* take subdiagonal element u[t,k] = v[p,j] */ temp = work[j]; #if 1 /* FIXME */ if (-eps_tol < temp && temp < +eps_tol) continue; #endif /* compute and save gaussian multiplier: * f := u[t,k] / u[k,k] = v[p,j] / v[i,j] */ ind[++nnz] = i; val[nnz] = f = work[j] / vr_piv[i]; /* gaussian transformation to eliminate u[t,k] = v[p,j]: * (p-th row of V) := (p-th row of V) - f * (i-th row of V) */ for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; i_ptr < i_end; i_ptr++) work[sv_ind[i_ptr]] -= f * sv_val[i_ptr]; } /* now matrix U is again upper triangular */ #if 1 /* FIXME */ if (-vpq_tol < work[q] && work[q] < +vpq_tol) #endif { /* however, its new diagonal element u[t,t] = v[p,q] is too * small in magnitude */ return 3; } /*--------------------------------------------------------------*/ /* create new row-like factor H[k] and add to eta file H */ /*--------------------------------------------------------------*/ /* (nnz = 0 means that all subdiagonal elements were too small * in magnitude) */ if (nnz > 0) { if (fhv->nfs == fhv->nfs_max) { /* maximal number of row-like factors has been reached */ return 4; } k = ++(fhv->nfs); hh_ind[k] = p; /* store non-trivial row of H[k] in right (dynamic) part of * SVA (diagonal unity element is not stored) */ if (sva->r_ptr - sva->m_ptr < nnz) { sva_more_space(sva, nnz); sv_ind = sva->ind; sv_val = sva->val; } sva_reserve_cap(sva, fhv->hh_ref-1+k, nnz); ptr = hh_ptr[k]; memcpy(&sv_ind[ptr], &ind[1], nnz * sizeof(int)); memcpy(&sv_val[ptr], &val[1], nnz * sizeof(double)); hh_len[k] = nnz; } /*--------------------------------------------------------------*/ /* copy transformed p-th row of matrix V, which is t-th row of */ /* matrix U, from working array back to matrix V */ /*--------------------------------------------------------------*/ /* copy elements of transformed p-th row of matrix V, which are * non-diagonal elements u[t,t+1], ..., u[t,n] of matrix U, from * working array to corresponding columns of matrix V (note that * diagonal element u[t,t] = v[p,q] not copied); also transform * p-th row of matrix V to sparse format */ len = 0; for (k = t+1; k <= n; k++) { /* j-th column of V = k-th column of U */ j = qq_ind[k]; /* take non-diagonal element v[p,j] = u[t,k] */ temp = work[j]; #if 1 /* FIXME */ if (-eps_tol < temp && temp < +eps_tol) continue; #endif /* add v[p,j] to j-th column of matrix V */ if (vc_cap[j] == vc_len[j]) { /* reserve extra locations in j-th column to reduce further * relocations of that column */ #if 1 /* FIXME */ int need = vc_len[j] + 5; #endif if (sva->r_ptr - sva->m_ptr < need) { sva_more_space(sva, need); sv_ind = sva->ind; sv_val = sva->val; } sva_enlarge_cap(sva, vc_ref-1+j, need, 0); } sv_ind[ptr = vc_ptr[j] + (vc_len[j]++)] = p; sv_val[ptr] = temp; /* store element v[p,j] = u[t,k] to working sparse vector */ ind[++len] = j; val[len] = temp; } /* copy elements from working sparse vector to p-th row of matrix * V (this row is currently empty) */ if (vr_cap[p] < len) { if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_enlarge_cap(sva, vr_ref-1+p, len, 0); } ptr = vr_ptr[p]; memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); vr_len[p] = len; /* store new diagonal element u[t,t] = v[p,q] */ vr_piv[p] = work[q]; /*--------------------------------------------------------------*/ /* perform accuracy test (only if new H[k] was added) */ /*--------------------------------------------------------------*/ if (nnz > 0) { /* copy p-th (non-trivial) row of row-like factor H[k] (except * unity diagonal element) to working array in dense format */ for (j = 1; j <= n; j++) work[j] = 0.0; k = fhv->nfs; for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) work[sv_ind[ptr]] = sv_val[ptr]; /* compute inner product of p-th (non-trivial) row of matrix * H[k] and q-th column of matrix V */ temp = vr_piv[p]; /* 1 * v[p,q] */ ptr = vc_ptr[q]; end = ptr + vc_len[q]; for (; ptr < end; ptr++) temp += work[sv_ind[ptr]] * sv_val[ptr]; /* inner product should be equal to element v[p,q] *before* * matrix V was transformed */ /* compute relative error */ temp = fabs(vpq - temp) / (1.0 + fabs(vpq)); #if 1 /* FIXME */ if (temp > err_tol) #endif { /* relative error is too large */ return 5; } } /* factorization has been successfully updated */ return 0; } /*********************************************************************** * fhv_h_solve - solve system H * x = b * * This routine solves the system H * x = b, where the matrix H is the * middle factor of the sparse updatable FHV-factorization. * * On entry the array x should contain elements of the right-hand side * vector b in locations x[1], ..., x[n], where n is the order of the * matrix F. On exit this array will contain elements of the solution * vector x in the same locations. */ void fhv_h_solve(FHV *fhv, double x[/*1+n*/]) { SVA *sva = fhv->luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int nfs = fhv->nfs; int *hh_ind = fhv->hh_ind; int hh_ref = fhv->hh_ref; int *hh_ptr = &sva->ptr[hh_ref-1]; int *hh_len = &sva->len[hh_ref-1]; int i, k, end, ptr; double x_i; for (k = 1; k <= nfs; k++) { x_i = x[i = hh_ind[k]]; for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) x_i -= sv_val[ptr] * x[sv_ind[ptr]]; x[i] = x_i; } return; } /*********************************************************************** * fhv_ht_solve - solve system H' * x = b * * This routine solves the system H' * x = b, where H' is a matrix * transposed to the matrix H, which is the middle factor of the sparse * updatable FHV-factorization. * * On entry the array x should contain elements of the right-hand side * vector b in locations x[1], ..., x[n], where n is the order of the * matrix F. On exit this array will contain elements of the solution * vector x in the same locations. */ void fhv_ht_solve(FHV *fhv, double x[/*1+n*/]) { SVA *sva = fhv->luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int nfs = fhv->nfs; int *hh_ind = fhv->hh_ind; int hh_ref = fhv->hh_ref; int *hh_ptr = &sva->ptr[hh_ref-1]; int *hh_len = &sva->len[hh_ref-1]; int k, end, ptr; double x_j; for (k = nfs; k >= 1; k--) { if ((x_j = x[hh_ind[k]]) == 0.0) continue; for (end = (ptr = hh_ptr[k]) + hh_len[k]; ptr < end; ptr++) x[sv_ind[ptr]] -= sv_val[ptr] * x_j; } return; } /* eof */ glpk-4.52.1/src/bflib/fhv.h0000644000062000006210000001037112175147600014524 0ustar maomkpasswd/* fhv.h (sparse updatable FHV-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef FHV_H #define FHV_H #include "luf.h" /*********************************************************************** * The structure FHV describes sparse updatable FHV-factorization. * * The FHV-factorization has the following format: * * A = F * H * V, (1) * * F = P0 * L * P0', (2) * * H = H[1] * H[2] * ... * H[nfs], (3) * * V = P * U * Q, (4) * * where: A is a given (unsymmetric) square matrix; F, H, V are matrix * factors actually computed; L is a lower triangular matrix with unity * diagonal; U is an upper tringular matrix; H[k], k = 1, 2, ..., nfs, * is a row-like factor, which differs from unity matrix only in one * row called a non-trivial row; P0, P, Q are permutation matrices; and * P0' is a matrix transposed to P0. * * Matrices F, V, P, Q are stored in the underlying LUF object. * * Non-trivial rows of factors H[k] are stored as sparse vectors in the * right (static) part of the sparse vector area (SVA). Note that unity * diagonal elements of non-trivial rows are not stored. * * Matrix P0 is stored in the same way as matrix P. * * Matrices L and U are completely defined by matrices F, V, P, and Q, * and therefore not stored explicitly. */ typedef struct FHV FHV; struct FHV { /* FHV-factorization */ LUF *luf; /* LU-factorization (contains matrices F, V, P, Q) */ /*--------------------------------------------------------------*/ /* matrix H in the form of eta file */ int nfs_max; /* maximal number of row-like factors (this limits the number of * updates of the factorization) */ int nfs; /* current number of row-like factors, 0 <= nfs <= nfs_max */ int *hh_ind; /* int hh_ind[1+nfs_max]; */ /* hh_ind[0] is not used; * hh_ind[k], 1 <= k <= nfs, is number of non-trivial row of * factor H[k] */ int hh_ref; /* reference number of sparse vector in SVA, which is non-trivial * row of factor H[1] */ #if 0 + 0 int *hh_ptr = &sva->ptr[hh_ref-1]; /* hh_ptr[0] is not used; * hh_ptr[k], 1 <= k <= nfs, is pointer to non-trivial row of * factor H[k] */ int *hh_len = &sva->len[hh_ref-1]; /* hh_len[0] is not used; * hh_len[k], 1 <= k <= nfs, is number of non-zero elements in * non-trivial row of factor H[k] */ #endif /*--------------------------------------------------------------*/ /* matrix P0 */ int *p0_ind; /* int p0_ind[1+n]; */ /* p0_ind[i] = j means that P0[i,j] = 1 */ int *p0_inv; /* int p0_inv[1+n]; */ /* p0_inv[j] = i means that P0[i,j] = 1 */ }; #define fhv_ft_update _glp_fhv_ft_update int fhv_ft_update(FHV *fhv, int q, int aq_len, const int aq_ind[], const double aq_val[], int ind[/*1+n*/], double val[/*1+n*/], double work[/*1+n*/]); /* update FHV-factorization (Forrest-Tomlin) */ #define fhv_h_solve _glp_fhv_h_solve void fhv_h_solve(FHV *fhv, double x[/*1+n*/]); /* solve system H * x = b */ #define fhv_ht_solve _glp_fhv_ht_solve void fhv_ht_solve(FHV *fhv, double x[/*1+n*/]); /* solve system H' * x = b */ #endif /* eof */ glpk-4.52.1/src/bflib/fhvint.c0000644000062000006210000001307312175147600015234 0ustar maomkpasswd/* fhvint.c (interface to FHV-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "fhvint.h" FHVINT *fhvint_create(void) { /* create interface to FHV-factorization */ FHVINT *fi; fi = talloc(1, FHVINT); fi->valid = 0; fi->fhv = NULL; fi->lufint = NULL; fi->nfs_max = 0; return fi; } int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, int ind[], double val[]), void *info) { /* compute FHV-factorization of specified matrix A */ FHV *fhv; LUFINT *lufint; int nfs_max, old_n_max, n_max, k, ret; xassert(n > 0); fi->valid = 0; /* get required value of nfs_max */ nfs_max = fi->nfs_max; if (nfs_max == 0) nfs_max = 100; xassert(nfs_max > 0); /* create interface to LU-factorization, if necessary */ lufint = fi->lufint; if (lufint == NULL) { lufint = fi->lufint = lufint_create(); lufint->sva_n_max = 4 * n + nfs_max; lufint->sva_size = 10 * n; lufint->delta_n0 = 0; lufint->delta_n = 100; lufint->sgf_updat = 1; } /* compute LU-factorization of specified matrix A */ old_n_max = lufint->n_max; ret = lufint_factorize(lufint, n, col, info); n_max = lufint->n_max; /* create FHV-factorization, if necessary */ fhv = fi->fhv; if (fhv == NULL) { fhv = fi->fhv = talloc(1, FHV); fhv->luf = lufint->luf; fhv->nfs_max = 0; fhv->hh_ind = NULL; fhv->p0_ind = NULL; fhv->p0_inv = NULL; } /* allocate/reallocate FHV-factorization, if necessary */ if (fhv->nfs_max != nfs_max) { fhv->nfs_max = nfs_max; if (fhv->hh_ind != NULL) tfree(fhv->hh_ind); fhv->hh_ind = talloc(1+nfs_max, int); } if (old_n_max < n_max) { if (fhv->p0_ind != NULL) tfree(fhv->p0_ind); if (fhv->p0_inv != NULL) tfree(fhv->p0_inv); fhv->p0_ind = talloc(1+n_max, int); fhv->p0_inv = talloc(1+n_max, int); } /* H := I */ fhv->nfs = 0; fhv->hh_ref = sva_alloc_vecs(fi->lufint->sva, nfs_max); /* P0 := P */ for (k = 1; k <= n; k++) { fhv->p0_ind[k] = fi->lufint->luf->pp_ind[k]; fhv->p0_inv[k] = fi->lufint->luf->pp_inv[k]; } /* set validation flag */ if (ret == 0) fi->valid = 1; return ret; } int fhvint_update(FHVINT *fi, int j, int len, const int ind[], const double val[]) { /* update FHV-factorization after replacing j-th column of A */ SGF *sgf = fi->lufint->sgf; int *ind1 = sgf->rs_next; double *val1 = sgf->vr_max; double *work = sgf->work; int ret; xassert(fi->valid); ret = fhv_ft_update(fi->fhv, j, len, ind, val, ind1, val1, work); if (ret != 0) fi->valid = 0; return ret; } void fhvint_ftran(FHVINT *fi, double x[]) { /* solve system A * x = b */ FHV *fhv = fi->fhv; LUF *luf = fhv->luf; int n = luf->n; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; SGF *sgf = fi->lufint->sgf; double *work = sgf->work; xassert(fi->valid); /* A = F * H * V */ /* x = inv(A) * b = inv(V) * inv(H) * inv(F) * b */ luf->pp_ind = fhv->p0_ind; luf->pp_inv = fhv->p0_inv; luf_f_solve(luf, x); luf->pp_ind = pp_ind; luf->pp_inv = pp_inv; fhv_h_solve(fhv, x); luf_v_solve(luf, x, work); memcpy(&x[1], &work[1], n * sizeof(double)); return; } void fhvint_btran(FHVINT *fi, double x[]) { /* solve system A'* x = b */ FHV *fhv = fi->fhv; LUF *luf = fhv->luf; int n = luf->n; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; SGF *sgf = fi->lufint->sgf; double *work = sgf->work; xassert(fi->valid); /* A' = (F * H * V)' = V'* H'* F' */ /* x = inv(A') * b = inv(F') * inv(H') * inv(V') * b */ luf_vt_solve(luf, x, work); fhv_ht_solve(fhv, work); luf->pp_ind = fhv->p0_ind; luf->pp_inv = fhv->p0_inv; luf_ft_solve(luf, work); luf->pp_ind = pp_ind; luf->pp_inv = pp_inv; memcpy(&x[1], &work[1], n * sizeof(double)); return; } void fhvint_delete(FHVINT *fi) { /* delete interface to FHV-factorization */ FHV *fhv = fi->fhv; LUFINT *lufint = fi->lufint; if (fhv != NULL) { tfree(fhv->hh_ind); tfree(fhv->p0_ind); tfree(fhv->p0_inv); tfree(fhv); } if (lufint != NULL) lufint_delete(fi->lufint); tfree(fi); return; } /* eof */ glpk-4.52.1/src/bflib/fhvint.h0000644000062000006210000000466112175147600015244 0ustar maomkpasswd/* fhvint.h (interface to FHV-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef FHVINT_H #define FHVINT_H #include "fhv.h" #include "lufint.h" typedef struct FHVINT FHVINT; struct FHVINT { /* interface to FHV-factorization */ int valid; /* factorization is valid only if this flag is set */ FHV *fhv; /* FHV-factorization */ LUFINT *lufint; /* interface to underlying LU-factorization */ /*--------------------------------------------------------------*/ /* control parameters */ int nfs_max; /* required maximal number of row-like factors */ }; #define fhvint_create _glp_fhvint_create FHVINT *fhvint_create(void); /* create interface to FHV-factorization */ #define fhvint_factorize _glp_fhvint_factorize int fhvint_factorize(FHVINT *fi, int n, int (*col)(void *info, int j, int ind[], double val[]), void *info); /* compute FHV-factorization of specified matrix A */ #define fhvint_update _glp_fhvint_update int fhvint_update(FHVINT *fi, int j, int len, const int ind[], const double val[]); /* update FHV-factorization after replacing j-th column of A */ #define fhvint_ftran _glp_fhvint_ftran void fhvint_ftran(FHVINT *fi, double x[]); /* solve system A * x = b */ #define fhvint_btran _glp_fhvint_btran void fhvint_btran(FHVINT *fi, double x[]); /* solve system A'* x = b */ #define fhvint_delete _glp_fhvint_delete void fhvint_delete(FHVINT *fi); /* delete interface to FHV-factorization */ #endif /* eof */ glpk-4.52.1/src/bflib/luf.c0000644000062000006210000004717512175147600014536 0ustar maomkpasswd/* luf.c (sparse LU-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "luf.h" /*********************************************************************** * luf_check_all - check LU-factorization before k-th elimination step * * This routine checks that before performing k-th elimination step, * 1 <= k <= n+1, all components of the LU-factorization are correct. * * In case of k = n+1, i.e. after last elimination step, it is assumed * that rows of F and columns of V are *not* built yet. * * NOTE: For testing/debugging only. */ void luf_check_all(LUF *luf, int k) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fr_ref = luf->fr_ref; int *fr_len = &sva->len[fr_ref-1]; int fc_ref = luf->fc_ref; int *fc_ptr = &sva->ptr[fc_ref-1]; int *fc_len = &sva->len[fc_ref-1]; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; int *qq_ind = luf->qq_ind; int *qq_inv = luf->qq_inv; int i, ii, i_ptr, i_end, j, jj, j_ptr, j_end; xassert(n > 0); xassert(1 <= k && k <= n+1); /* check permutation matrix P */ for (i = 1; i <= n; i++) { ii = pp_ind[i]; xassert(1 <= ii && ii <= n); xassert(pp_inv[ii] == i); } /* check permutation matrix Q */ for (j = 1; j <= n; j++) { jj = qq_inv[j]; xassert(1 <= jj && jj <= n); xassert(qq_ind[jj] == j); } /* check row-wise representation of matrix F */ for (i = 1; i <= n; i++) xassert(fr_len[i] == 0); /* check column-wise representation of matrix F */ for (j = 1; j <= n; j++) { /* j-th column of F = jj-th column of L */ jj = pp_ind[j]; if (jj < k) { j_ptr = fc_ptr[j]; j_end = j_ptr + fc_len[j]; for (; j_ptr < j_end; j_ptr++) { i = sv_ind[j_ptr]; xassert(1 <= i && i <= n); ii = pp_ind[i]; /* f[i,j] = l[ii,jj] */ xassert(ii > jj); xassert(sv_val[j_ptr] != 0.0); } } else /* jj >= k */ xassert(fc_len[j] == 0); } /* check row-wise representation of matrix V */ for (i = 1; i <= n; i++) { /* i-th row of V = ii-th row of U */ ii = pp_ind[i]; i_ptr = vr_ptr[i]; i_end = i_ptr + vr_len[i]; for (; i_ptr < i_end; i_ptr++) { j = sv_ind[i_ptr]; xassert(1 <= j && j <= n); jj = qq_inv[j]; /* v[i,j] = u[ii,jj] */ if (ii < k) xassert(jj > ii); else /* ii >= k */ { xassert(jj >= k); /* find v[i,j] in j-th column */ j_ptr = vc_ptr[j]; j_end = j_ptr + vc_len[j]; for (; sv_ind[j_ptr] != i; j_ptr++) /* nop */; xassert(j_ptr < j_end); } xassert(sv_val[i_ptr] != 0.0); } } /* check column-wise representation of matrix V */ for (j = 1; j <= n; j++) { /* j-th column of V = jj-th column of U */ jj = qq_inv[j]; if (jj < k) xassert(vc_len[j] == 0); else /* jj >= k */ { j_ptr = vc_ptr[j]; j_end = j_ptr + vc_len[j]; for (; j_ptr < j_end; j_ptr++) { i = sv_ind[j_ptr]; ii = pp_ind[i]; /* v[i,j] = u[ii,jj] */ xassert(ii >= k); /* find v[i,j] in i-th row */ i_ptr = vr_ptr[i]; i_end = i_ptr + vr_len[i]; for (; sv_ind[i_ptr] != j; i_ptr++) /* nop */; xassert(i_ptr < i_end); } } } return; } /*********************************************************************** * luf_build_v_rows - build matrix V in row-wise format * * This routine builds the row-wise representation of matrix V in the * left part of SVA using its column-wise representation. * * NOTE: On entry to the routine all rows of matrix V should have zero * capacity. * * The working array len should have at least 1+n elements (len[0] is * not used). */ void luf_build_v_rows(LUF *luf, int len[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int i, j, end, nnz, ptr, ptr1; /* calculate the number of non-zeros in each row of matrix V and * the total number of non-zeros */ nnz = 0; for (i = 1; i <= n; i++) len[i] = 0; for (j = 1; j <= n; j++) { nnz += vc_len[j]; for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) len[sv_ind[ptr]]++; } /* we need at least nnz free locations in SVA */ if (sva->r_ptr - sva->m_ptr < nnz) { sva_more_space(sva, nnz); sv_ind = sva->ind; sv_val = sva->val; } /* reserve locations for rows of matrix V */ for (i = 1; i <= n; i++) { if (len[i] > 0) sva_enlarge_cap(sva, vr_ref-1+i, len[i], 0); vr_len[i] = len[i]; } /* walk thru column of matrix V and build its rows */ for (j = 1; j <= n; j++) { for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) { i = sv_ind[ptr]; sv_ind[ptr1 = vr_ptr[i] + (--len[i])] = j; sv_val[ptr1] = sv_val[ptr]; } } return; } /*********************************************************************** * luf_build_f_rows - build matrix F in row-wise format * * This routine builds the row-wise representation of matrix F in the * right part of SVA using its column-wise representation. * * NOTE: On entry to the routine all rows of matrix F should have zero * capacity. * * The working array len should have at least 1+n elements (len[0] is * not used). */ void luf_build_f_rows(LUF *luf, int len[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fr_ref = luf->fr_ref; int *fr_ptr = &sva->ptr[fr_ref-1]; int *fr_len = &sva->len[fr_ref-1]; int fc_ref = luf->fc_ref; int *fc_ptr = &sva->ptr[fc_ref-1]; int *fc_len = &sva->len[fc_ref-1]; int i, j, end, nnz, ptr, ptr1; /* calculate the number of non-zeros in each row of matrix F and * the total number of non-zeros (except diagonal elements) */ nnz = 0; for (i = 1; i <= n; i++) len[i] = 0; for (j = 1; j <= n; j++) { nnz += fc_len[j]; for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) len[sv_ind[ptr]]++; } /* we need at least nnz free locations in SVA */ if (sva->r_ptr - sva->m_ptr < nnz) { sva_more_space(sva, nnz); sv_ind = sva->ind; sv_val = sva->val; } /* reserve locations for rows of matrix F */ for (i = 1; i <= n; i++) { if (len[i] > 0) sva_reserve_cap(sva, fr_ref-1+i, len[i]); fr_len[i] = len[i]; } /* walk through columns of matrix F and build its rows */ for (j = 1; j <= n; j++) { for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) { i = sv_ind[ptr]; sv_ind[ptr1 = fr_ptr[i] + (--len[i])] = j; sv_val[ptr1] = sv_val[ptr]; } } return; } /*********************************************************************** * luf_build_v_cols - build matrix V in column-wise format * * This routine builds the column-wise representation of matrix V in * the left (if the flag updat is set) or right (if the flag updat is * clear) part of SVA using its row-wise representation. * * NOTE: On entry to the routine all columns of matrix V should have * zero capacity. * * The working array len should have at least 1+n elements (len[0] is * not used). */ void luf_build_v_cols(LUF *luf, int updat, int len[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int i, j, end, nnz, ptr, ptr1; /* calculate the number of non-zeros in each column of matrix V * and the total number of non-zeros (except pivot elements) */ nnz = 0; for (j = 1; j <= n; j++) len[j] = 0; for (i = 1; i <= n; i++) { nnz += vr_len[i]; for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) len[sv_ind[ptr]]++; } /* we need at least nnz free locations in SVA */ if (sva->r_ptr - sva->m_ptr < nnz) { sva_more_space(sva, nnz); sv_ind = sva->ind; sv_val = sva->val; } /* reserve locations for columns of matrix V */ for (j = 1; j <= n; j++) { if (len[j] > 0) { if (updat) sva_enlarge_cap(sva, vc_ref-1+j, len[j], 0); else sva_reserve_cap(sva, vc_ref-1+j, len[j]); } vc_len[j] = len[j]; } /* walk through rows of matrix V and build its columns */ for (i = 1; i <= n; i++) { for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) { j = sv_ind[ptr]; sv_ind[ptr1 = vc_ptr[j] + (--len[j])] = i; sv_val[ptr1] = sv_val[ptr]; } } return; } /*********************************************************************** * luf_check_f_rc - check rows and columns of matrix F * * This routine checks that the row- and column-wise representations * of matrix F are identical. * * NOTE: For testing/debugging only. */ void luf_check_f_rc(LUF *luf) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fr_ref = luf->fr_ref; int *fr_ptr = &sva->ptr[fr_ref-1]; int *fr_len = &sva->len[fr_ref-1]; int fc_ref = luf->fc_ref; int *fc_ptr = &sva->ptr[fc_ref-1]; int *fc_len = &sva->len[fc_ref-1]; int i, i_end, i_ptr, j, j_end, j_ptr; /* walk thru rows of matrix F */ for (i = 1; i <= n; i++) { for (i_end = (i_ptr = fr_ptr[i]) + fr_len[i]; i_ptr < i_end; i_ptr++) { j = sv_ind[i_ptr]; /* find element f[i,j] in j-th column of matrix F */ for (j_end = (j_ptr = fc_ptr[j]) + fc_len[j]; sv_ind[j_ptr] != i; j_ptr++) /* nop */; xassert(j_ptr < j_end); xassert(sv_val[i_ptr] == sv_val[j_ptr]); /* mark element f[i,j] */ sv_ind[j_ptr] = -i; } } /* walk thru column of matix F and check that all elements has been marked */ for (j = 1; j <= n; j++) { for (j_end = (j_ptr = fc_ptr[j]) + fc_len[j]; j_ptr < j_end; j_ptr++) { xassert((i = sv_ind[j_ptr]) < 0); /* unmark element f[i,j] */ sv_ind[j_ptr] = -i; } } return; } /*********************************************************************** * luf_check_v_rc - check rows and columns of matrix V * * This routine checks that the row- and column-wise representations * of matrix V are identical. * * NOTE: For testing/debugging only. */ void luf_check_v_rc(LUF *luf) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int i, i_end, i_ptr, j, j_end, j_ptr; /* walk thru rows of matrix V */ for (i = 1; i <= n; i++) { for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; i_ptr < i_end; i_ptr++) { j = sv_ind[i_ptr]; /* find element v[i,j] in j-th column of matrix V */ for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; sv_ind[j_ptr] != i; j_ptr++) /* nop */; xassert(j_ptr < j_end); xassert(sv_val[i_ptr] == sv_val[j_ptr]); /* mark element v[i,j] */ sv_ind[j_ptr] = -i; } } /* walk thru column of matix V and check that all elements has been marked */ for (j = 1; j <= n; j++) { for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; j_ptr < j_end; j_ptr++) { xassert((i = sv_ind[j_ptr]) < 0); /* unmark element v[i,j] */ sv_ind[j_ptr] = -i; } } return; } /*********************************************************************** * luf_f_solve - solve system F * x = b * * This routine solves the system F * x = b, where the matrix F is the * left factor of the sparse LU-factorization. * * On entry the array x should contain elements of the right-hand side * vector b in locations x[1], ..., x[n], where n is the order of the * matrix F. On exit this array will contain elements of the solution * vector x in the same locations. */ void luf_f_solve(LUF *luf, double x[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fc_ref = luf->fc_ref; int *fc_ptr = &sva->ptr[fc_ref-1]; int *fc_len = &sva->len[fc_ref-1]; int *pp_inv = luf->pp_inv; int j, k, ptr, end; double x_j; for (k = 1; k <= n; k++) { /* k-th column of L = j-th column of F */ j = pp_inv[k]; /* x[j] is already computed */ /* walk thru j-th column of matrix F and substitute x[j] into * other equations */ if ((x_j = x[j]) != 0.0) { for (end = (ptr = fc_ptr[j]) + fc_len[j]; ptr < end; ptr++) x[sv_ind[ptr]] -= sv_val[ptr] * x_j; } } return; } /*********************************************************************** * luf_ft_solve - solve system F' * x = b * * This routine solves the system F' * x = b, where F' is a matrix * transposed to the matrix F, which is the left factor of the sparse * LU-factorization. * * On entry the array x should contain elements of the right-hand side * vector b in locations x[1], ..., x[n], where n is the order of the * matrix F. On exit this array will contain elements of the solution * vector x in the same locations. */ void luf_ft_solve(LUF *luf, double x[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fr_ref = luf->fr_ref; int *fr_ptr = &sva->ptr[fr_ref-1]; int *fr_len = &sva->len[fr_ref-1]; int *pp_inv = luf->pp_inv; int i, k, ptr, end; double x_i; for (k = n; k >= 1; k--) { /* k-th column of L' = i-th row of F */ i = pp_inv[k]; /* x[i] is already computed */ /* walk thru i-th row of matrix F and substitute x[i] into * other equations */ if ((x_i = x[i]) != 0.0) { for (end = (ptr = fr_ptr[i]) + fr_len[i]; ptr < end; ptr++) x[sv_ind[ptr]] -= sv_val[ptr] * x_i; } } return; } /*********************************************************************** * luf_v_solve - solve system V * x = b * * This routine solves the system V * x = b, where the matrix V is the * right factor of the sparse LU-factorization. * * On entry the array b should contain elements of the right-hand side * vector b in locations b[1], ..., b[n], where n is the order of the * matrix V. On exit the array x will contain elements of the solution * vector x in locations x[1], ..., x[n]. Note that the array b will be * clobbered on exit. */ void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; double *vr_piv = luf->vr_piv; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *pp_inv = luf->pp_inv; int *qq_ind = luf->qq_ind; int i, j, k, ptr, end; double x_j; for (k = n; k >= 1; k--) { /* k-th row of U = i-th row of V */ /* k-th column of U = j-th column of V */ i = pp_inv[k]; j = qq_ind[k]; /* compute x[j] = b[i] / u[k,k], where u[k,k] = v[i,j]; * walk through j-th column of matrix V and substitute x[j] * into other equations */ if ((x_j = x[j] = b[i] / vr_piv[i]) != 0.0) { for (end = (ptr = vc_ptr[j]) + vc_len[j]; ptr < end; ptr++) b[sv_ind[ptr]] -= sv_val[ptr] * x_j; } } return; } /*********************************************************************** * luf_vt_solve - solve system V' * x = b * * This routine solves the system V' * x = b, where V' is a matrix * transposed to the matrix V, which is the right factor of the sparse * LU-factorization. * * On entry the array b should contain elements of the right-hand side * vector b in locations b[1], ..., b[n], where n is the order of the * matrix V. On exit the array x will contain elements of the solution * vector x in locations x[1], ..., x[n]. Note that the array b will be * clobbered on exit. */ void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; double *vr_piv = luf->vr_piv; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int *pp_inv = luf->pp_inv; int *qq_ind = luf->qq_ind; int i, j, k, ptr, end; double x_i; for (k = 1; k <= n; k++) { /* k-th row of U' = j-th column of V */ /* k-th column of U' = i-th row of V */ i = pp_inv[k]; j = qq_ind[k]; /* compute x[i] = b[j] / u'[k,k], where u'[k,k] = v[i,j]; * walk through i-th row of matrix V and substitute x[i] into * other equations */ if ((x_i = x[i] = b[j] / vr_piv[i]) != 0.0) { for (end = (ptr = vr_ptr[i]) + vr_len[i]; ptr < end; ptr++) b[sv_ind[ptr]] -= sv_val[ptr] * x_i; } } return; } /* eof */ glpk-4.52.1/src/bflib/luf.h0000644000062000006210000001775712175147600014546 0ustar maomkpasswd/* luf.h (sparse LU-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef LUF_H #define LUF_H #include "sva.h" /*********************************************************************** * The structure LUF describes sparse LU-factorization. * * The LU-factorization has the following format: * * A = F * V = P * L * U * Q, (1) * * F = P * L * P', (2) * * V = P * U * Q, (3) * * where A is a given (unsymmetric) square matrix, F and V are matrix * factors actually computed, L is a lower triangular matrix with unity * diagonal, U is an upper triangular matrix, P and Q are permutation * matrices, P' is a matrix transposed to P. All the matrices have the * same order n. * * Matrices F and V are stored in both row- and column-wise sparse * formats in the associated sparse vector area (SVA). Unity diagonal * elements of matrix F are not stored. Pivot elements of matrix V * (which correspond to diagonal elements of matrix U) are stored in * a separate ordinary array. * * Permutation matrices P and Q are stored in ordinary arrays in both * row- and column-like formats. * * Matrices L and U are completely defined by matrices F, V, P, and Q, * and therefore not stored explicitly. */ typedef struct LUF LUF; struct LUF { /* sparse LU-factorization */ int n; /* order of matrices A, F, V, P, Q */ SVA *sva; /* associated sparse vector area (SVA) used to store rows and * columns of matrices F and V; note that different objects may * share the same SVA */ /*--------------------------------------------------------------*/ /* matrix F in row-wise format */ /* during the factorization process this object is not used */ int fr_ref; /* reference number of sparse vector in SVA, which is the first * row of matrix F */ #if 0 + 0 int *fr_ptr = &sva->ptr[fr_ref-1]; /* fr_ptr[0] is not used; * fr_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ int *fr_len = &sva->len[fr_ref-1]; /* fr_len[0] is not used; * fr_len[i], 1 <= i <= n, is length of i-th row */ #endif /*--------------------------------------------------------------*/ /* matrix F in column-wise format */ /* during the factorization process this object is constructed by columns */ int fc_ref; /* reference number of sparse vector in SVA, which is the first * column of matrix F */ #if 0 + 0 int *fc_ptr = &sva->ptr[fc_ref-1]; /* fc_ptr[0] is not used; * fc_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ int *fc_len = &sva->len[fc_ref-1]; /* fc_len[0] is not used; * fc_len[j], 1 <= j <= n, is length of j-th column */ #endif /*--------------------------------------------------------------*/ /* matrix V in row-wise format */ int vr_ref; /* reference number of sparse vector in SVA, which is the first * row of matrix V */ #if 0 + 0 int *vr_ptr = &sva->ptr[vr_ref-1]; /* vr_ptr[0] is not used; * vr_ptr[i], 1 <= i <= n, is pointer to i-th row in SVA */ int *vr_len = &sva->len[vr_ref-1]; /* vr_len[0] is not used; * vr_len[i], 1 <= i <= n, is length of i-th row */ int *vr_cap = &sva->cap[vr_ref-1]; /* vr_cap[0] is not used; * vr_cap[i], 1 <= i <= n, is capacity of i-th row */ #endif double *vr_piv; /* double vr_piv[1+n]; */ /* vr_piv[0] is not used; * vr_piv[i], 1 <= i <= n, is pivot element of i-th row */ /*--------------------------------------------------------------*/ /* matrix V in column-wise format */ /* during the factorization process this object contains only the * patterns (row indices) of columns of the active submatrix */ int vc_ref; /* reference number of sparse vector in SVA, which is the first * column of matrix V */ #if 0 + 0 int *vc_ptr = &sva->ptr[vc_ref-1]; /* vc_ptr[0] is not used; * vc_ptr[j], 1 <= j <= n, is pointer to j-th column in SVA */ int *vc_len = &sva->len[vc_ref-1]; /* vc_len[0] is not used; * vc_len[j], 1 <= j <= n, is length of j-th column */ int *vc_cap = &sva->cap[vc_ref-1]; /* vc_cap[0] is not used; * vc_cap[j], 1 <= j <= n, is capacity of j-th column */ #endif /*--------------------------------------------------------------*/ /* matrix P */ int *pp_ind; /* int pp_ind[1+n]; */ /* pp_ind[i] = j means that P[i,j] = 1 */ int *pp_inv; /* int pp_inv[1+n]; */ /* pp_inv[j] = i means that P[i,j] = 1 */ /* if i-th row or column of matrix F is i'-th row or column of * matrix L, or if i-th row of matrix V is i'-th row of matrix U, * then pp_ind[i] = i' and pp_inv[i'] = i */ /*--------------------------------------------------------------*/ /* matrix Q */ int *qq_ind; /* int qq_ind[1+n]; */ /* qq_ind[i] = j means that Q[i,j] = 1 */ int *qq_inv; /* int qq_inv[1+n]; */ /* qq_inv[j] = i means that Q[i,j] = 1 */ /* if j-th column of matrix V is j'-th column of matrix U, then * qq_ind[j'] = j and qq_inv[j] = j' */ }; #define luf_swap_u_rows(i1, i2) \ do \ { int j1, j2; \ j1 = pp_inv[i1], j2 = pp_inv[i2]; \ pp_ind[j1] = i2, pp_inv[i2] = j1; \ pp_ind[j2] = i1, pp_inv[i1] = j2; \ } while (0) /* swap rows i1 and i2 of matrix U = P'* V * Q' */ #define luf_swap_u_cols(j1, j2) \ do \ { int i1, i2; \ i1 = qq_ind[j1], i2 = qq_ind[j2]; \ qq_ind[j1] = i2, qq_inv[i2] = j1; \ qq_ind[j2] = i1, qq_inv[i1] = j2; \ } while (0) /* swap columns j1 and j2 of matrix U = P'* V * Q' */ #define luf_check_all _glp_luf_check_all void luf_check_all(LUF *luf, int k); /* check LU-factorization before k-th elimination step */ #define luf_build_v_rows _glp_luf_build_v_rows void luf_build_v_rows(LUF *luf, int len[/*1+n*/]); /* build matrix V in row-wise format */ #define luf_build_f_rows _glp_luf_build_f_rows void luf_build_f_rows(LUF *luf, int len[/*1+n*/]); /* build matrix F in row-wise format */ #define luf_build_v_cols _glp_luf_build_v_cols void luf_build_v_cols(LUF *luf, int updat, int len[/*1+n*/]); /* build matrix V in column-wise format */ #define luf_check_f_rc _glp_luf_check_f_rc void luf_check_f_rc(LUF *luf); /* check rows and columns of matrix F */ #define luf_check_v_rc _glp_luf_check_v_rc void luf_check_v_rc(LUF *luf); /* check rows and columns of matrix V */ #define luf_f_solve _glp_luf_f_solve1 void luf_f_solve(LUF *luf, double x[/*1+n*/]); /* solve system F * x = b */ #define luf_ft_solve _glp_luf_ft_solve1 void luf_ft_solve(LUF *luf, double x[/*1+n*/]); /* solve system F' * x = b */ #define luf_v_solve _glp_luf_v_solve1 void luf_v_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); /* solve system V * x = b */ #define luf_vt_solve _glp_luf_vt_solve1 void luf_vt_solve(LUF *luf, double b[/*1+n*/], double x[/*1+n*/]); /* solve system V' * x = b */ #endif /* eof */ glpk-4.52.1/src/bflib/lufint.c0000644000062000006210000001555412175147600015245 0ustar maomkpasswd/* lufint.c (interface to LU-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "lufint.h" LUFINT *lufint_create(void) { /* create interface to LU-factorization */ LUFINT *fi; fi = talloc(1, LUFINT); fi->n_max = 0; fi->valid = 0; fi->sva = NULL; fi->luf = NULL; fi->sgf = NULL; fi->sva_n_max = fi->sva_size = 0; fi->delta_n0 = fi->delta_n = 0; fi->sgf_updat = 0; fi->sgf_piv_tol = 0.10; fi->sgf_piv_lim = 4; fi->sgf_suhl = 1; fi->sgf_eps_tol = DBL_EPSILON; return fi; } static int setup_v_cols(LUF *luf, int (*col)(void *info, int j, int ind[], double val[]), void *info, int ind[], double val[]) { /* setup matrix V = A in column-wise format */ int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *vc_cap = &sva->cap[vc_ref-1]; int j, len, ptr, nnz; nnz = 0; for (j = 1; j <= n; j++) { /* get j-th column */ len = col(info, j, ind, val); xassert(0 <= len && len <= n); /* enlarge j-th column capacity */ if (vc_cap[j] < len) { if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_enlarge_cap(sva, vc_ref-1+j, len, 0); } /* store j-th column */ ptr = vc_ptr[j]; memcpy(&sv_ind[ptr], &ind[1], len * sizeof(int)); memcpy(&sv_val[ptr], &val[1], len * sizeof(double)); vc_len[j] = len; nnz += len; } return nnz; } int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, int ind[], double val[]), void *info) { /* compute LU-factorization of specified matrix A */ SVA *sva; LUF *luf; SGF *sgf; int k; xassert(n > 0); fi->valid = 0; /* create sparse vector area (SVA), if necessary */ sva = fi->sva; if (sva == NULL) { int sva_n_max = fi->sva_n_max; int sva_size = fi->sva_size; if (sva_n_max == 0) sva_n_max = 4 * n; if (sva_size == 0) sva_size = 10 * n; sva = fi->sva = sva_create_area(sva_n_max, sva_size); } /* allocate/reallocate underlying objects, if necessary */ if (fi->n_max < n) { int n_max = fi->n_max; if (n_max == 0) n_max = fi->n_max = n + fi->delta_n0; else n_max = fi->n_max = n + fi->delta_n; xassert(n_max >= n); /* allocate/reallocate LU-factorization (LUF) */ luf = fi->luf; if (luf == NULL) { luf = fi->luf = talloc(1, LUF); memset(luf, 0, sizeof(LUF)); luf->sva = sva; } else { tfree(luf->vr_piv); tfree(luf->pp_ind); tfree(luf->pp_inv); tfree(luf->qq_ind); tfree(luf->qq_inv); } luf->vr_piv = talloc(1+n_max, double); luf->pp_ind = talloc(1+n_max, int); luf->pp_inv = talloc(1+n_max, int); luf->qq_ind = talloc(1+n_max, int); luf->qq_inv = talloc(1+n_max, int); /* allocate/reallocate factorizer workspace (SGF) */ sgf = fi->sgf; if (sgf == NULL) { sgf = fi->sgf = talloc(1, SGF); memset(sgf, 0, sizeof(SGF)); sgf->luf = luf; } else { tfree(sgf->rs_head); tfree(sgf->rs_prev); tfree(sgf->rs_next); tfree(sgf->cs_head); tfree(sgf->cs_prev); tfree(sgf->cs_next); tfree(sgf->vr_max); tfree(sgf->flag); tfree(sgf->work); } sgf->rs_head = talloc(1+n_max, int); sgf->rs_prev = talloc(1+n_max, int); sgf->rs_next = talloc(1+n_max, int); sgf->cs_head = talloc(1+n_max, int); sgf->cs_prev = talloc(1+n_max, int); sgf->cs_next = talloc(1+n_max, int); sgf->vr_max = talloc(1+n_max, double); sgf->flag = talloc(1+n_max, char); sgf->work = talloc(1+n_max, double); } luf = fi->luf; sgf = fi->sgf; #if 1 /* FIXME */ /* initialize SVA */ sva->n = 0; sva->m_ptr = 1; sva->r_ptr = sva->size + 1; sva->head = sva->tail = 0; #endif /* allocate sparse vectors in SVA */ luf->n = n; luf->fr_ref = sva_alloc_vecs(sva, n); luf->fc_ref = sva_alloc_vecs(sva, n); luf->vr_ref = sva_alloc_vecs(sva, n); luf->vc_ref = sva_alloc_vecs(sva, n); /* setup matrix V = A in column-wise format */ setup_v_cols(luf, col, info, sgf->rs_prev, sgf->work); /* setup factorizer control parameters */ sgf->updat = fi->sgf_updat; sgf->piv_tol = fi->sgf_piv_tol; sgf->piv_lim = fi->sgf_piv_lim; sgf->suhl = fi->sgf_suhl; sgf->eps_tol = fi->sgf_eps_tol; /* compute LU-factorization of specified matrix A */ k = sgf_factorize(sgf, 1); if (k == 0) fi->valid = 1; return k; } void lufint_delete(LUFINT *fi) { /* delete interface to LU-factorization */ SVA *sva = fi->sva; LUF *luf = fi->luf; SGF *sgf = fi->sgf; if (sva != NULL) sva_delete_area(sva); if (luf != NULL) { tfree(luf->vr_piv); tfree(luf->pp_ind); tfree(luf->pp_inv); tfree(luf->qq_ind); tfree(luf->qq_inv); tfree(luf); } if (sgf != NULL) { tfree(sgf->rs_head); tfree(sgf->rs_prev); tfree(sgf->rs_next); tfree(sgf->cs_head); tfree(sgf->cs_prev); tfree(sgf->cs_next); tfree(sgf->vr_max); tfree(sgf->flag); tfree(sgf->work); tfree(sgf); } tfree(fi); return; } /* eof */ glpk-4.52.1/src/bflib/lufint.h0000644000062000006210000000462112175147600015243 0ustar maomkpasswd/* lufint.h (interface to LU-factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef LUFINT_H #define LUFINT_H #include "sgf.h" typedef struct LUFINT LUFINT; struct LUFINT { /* interface to LU-factorization */ int n_max; /* maximal value of n (increased automatically) */ int valid; /* factorization is valid only if this flag is set */ SVA *sva; /* sparse vector area (SVA) */ LUF *luf; /* sparse LU-factorization */ SGF *sgf; /* sparse Gaussian factorizer workspace */ /*--------------------------------------------------------------*/ /* control parameters */ int sva_n_max, sva_size; /* parameters passed to sva_create_area */ int delta_n0, delta_n; /* if n_max = 0, set n_max = n + delta_n0 * if n_max < n, set n_max = n + delta_n */ int sgf_updat; double sgf_piv_tol; int sgf_piv_lim; int sgf_suhl; double sgf_eps_tol; /* factorizer control parameters */ }; #define lufint_create _glp_lufint_create LUFINT *lufint_create(void); /* create interface to LU-factorization */ #define lufint_factorize _glp_lufint_factorize int lufint_factorize(LUFINT *fi, int n, int (*col)(void *info, int j, int ind[], double val[]), void *info); /* compute LU-factorization of specified matrix A */ #define lufint_delete _glp_lufint_delete void lufint_delete(LUFINT *fi); /* delete interface to LU-factorization */ #endif /* eof */ glpk-4.52.1/src/bflib/sgf.c0000644000062000006210000015452112175147600014521 0ustar maomkpasswd/* sgf.c (sparse Gaussian factorizer) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "sgf.h" /*********************************************************************** * sgf_reduce_nuc - initial reordering to minimize nucleus size * * On entry to this routine it is assumed that V = A and F = P = Q = I, * where A is the original matrix to be factorized. It is also assumed * that matrix V = A is stored in both row- and column-wise formats. * * This routine performs (implicit) non-symmetric permutations of rows * and columns of matrix U = P'* V * Q' to reduce it to the form: * * 1 k1 k2 n * 1 x x x x x x x x x x * . x x x x x x x x x * . . x x x x x x x x * k1 . . . * * * * x x x * . . . * * * * x x x * . . . * * * * x x x * k2 . . . * * * * x x x * . . . . . . . x x x * . . . . . . . . x x * n . . . . . . . . . x * * where non-zeros in rows and columns k1, k1+1, ..., k2 constitute so * called nucleus ('*'), whose size is minimized by the routine. * * The numbers k1 and k2 are returned by the routine on exit. Usually, * if the nucleus exists, 1 <= k1 < k2 <= n. However, if the resultant * matrix U is upper triangular (has no nucleus), k1 = n+1 and k2 = n. * * Note that the routines sgf_choose_pivot and sgf_eliminate perform * exactly the same transformations (by processing row and columns * singletons), so preliminary minimization of the nucleus may not be * used. However, processing row and column singletons by the routines * sgf_minimize_nuc and sgf_singl_phase is more efficient. */ void sgf_reduce_nuc(LUF *luf, int *k1_, int *k2_, int cnt[/*1+n*/], int list[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; int *qq_ind = luf->qq_ind; int *qq_inv = luf->qq_inv; int i, ii, j, jj, k1, k2, ns, ptr, end; /* initial nucleus is U = V = A */ k1 = 1, k2 = n; /*--------------------------------------------------------------*/ /* process column singletons */ /*--------------------------------------------------------------*/ /* determine initial counts of columns of V and initialize list * of active column singletons */ ns = 0; /* number of active column singletons */ for (j = 1; j <= n; j++) { if ((cnt[j] = vc_len[j]) == 1) list[++ns] = j; } /* process active column singletons */ while (ns > 0) { /* column singleton is in j-th column of V */ j = list[ns--]; /* find i-th row of V containing column singleton */ ptr = vc_ptr[j]; end = ptr + vc_len[j]; for (; pp_ind[i = sv_ind[ptr]] < k1; ptr++) /* nop */; xassert(ptr < end); /* permute rows and columns of U to move column singleton to * position u[k1,k1] */ ii = pp_ind[i]; luf_swap_u_rows(k1, ii); jj = qq_inv[j]; luf_swap_u_cols(k1, jj); /* nucleus size decreased */ k1++; /* walk thru i-th row of V and decrease column counts; this * may cause new column singletons to appear */ ptr = vr_ptr[i]; end = ptr + vr_len[i]; for (; ptr < end; ptr++) { if (--(cnt[j = sv_ind[ptr]]) == 1) list[++ns] = j; } } /* nucleus begins at k1-th row/column of U */ if (k1 > n) { /* U is upper triangular; no nucleus exist */ goto done; } /*--------------------------------------------------------------*/ /* process row singletons */ /*--------------------------------------------------------------*/ /* determine initial counts of rows of V and initialize list of * active row singletons */ ns = 0; /* number of active row singletons */ for (i = 1; i <= n; i++) { if (pp_ind[i] < k1) { /* corresponding row of U is above its k1-th row; set its * count to zero to prevent including it in active list */ cnt[i] = 0; } else if ((cnt[i] = vr_len[i]) == 1) list[++ns] = i; } /* process active row singletons */ while (ns > 0) { /* row singleton is in i-th row of V */ i = list[ns--]; /* find j-th column of V containing row singleton */ ptr = vr_ptr[i]; end = ptr + vr_len[i]; for (; qq_inv[j = sv_ind[ptr]] > k2; ptr++) /* nop */; xassert(ptr < end); /* permute rows and columns of U to move row singleton to * position u[k2,k2] */ ii = pp_ind[i]; luf_swap_u_rows(k2, ii); jj = qq_inv[j]; luf_swap_u_cols(k2, jj); /* nucleus size decreased */ k2--; /* walk thru j-th column of V and decrease row counts; this * may cause new row singletons to appear */ ptr = vc_ptr[j]; end = ptr + vc_len[j]; for (; ptr < end; ptr++) { if (--(cnt[i = sv_ind[ptr]]) == 1) list[++ns] = i; } } /* nucleus ends at k2-th row/column of U */ xassert(k1 < k2); done: *k1_ = k1, *k2_ = k2; return; } /*********************************************************************** * sgf_singl_phase - compute LU-factorization (singleton phase) * * It is assumed that on entry to the routine L = P'* F * P = F = I * and matrix U = P'* V * Q' has the following structure (provided by * the routine sgf_reduce_nuc): * * 1 k1 k2 n * 1 a a a b b b b c c c * . a a b b b b c c c * . . a b b b b c c c * k1 . . . * * * * d d d * . . . * * * * d d d * . . . * * * * d d d * k2 . . . * * * * d d d * . . . . . . . e e e * . . . . . . . . e e * n . . . . . . . . . e * * First, the routine performs (implicit) symmetric permutations of * rows and columns of matrix U to place them in the following order: * * 1, 2, ..., k1-1; n, n-1, ..., k2+1; k1, k1+1, ..., k2 * * This changes the structure of matrix U as follows: * * 1 k1 k2' n * 1 a a a c c c b b b b * . a a c c c b b b b * . . a c c c b b b b * k1 . . . e . . . . . . * . . . e e . . . . . * . . . e e e . . . . * k2'. . . d d d * * * * * . . . d d d * * * * * . . . d d d * * * * * n . . . d d d * * * * * * where k2' = n - k2 + k1. * * Then the routine performs elementary gaussian transformations to * eliminate subdiagonal elements in columns k1, ..., k2'-1 of U. The * effect is the same as if the routine sgf_eliminate would be called * for k = 1, ..., k2'-1 using diagonal elements u[k,k] as pivots. * * After elimination matrices L and U becomes the following: * * 1 k1 k2' n 1 k1 k2' n * 1 1 . . . . . . . . . 1 a a a c c c b b b b * . 1 . . . . . . . . . a a c c c b b b b * . . 1 . . . . . . . . . a c c c b b b b * k1 . . . 1 . . . . . . k1 . . . e . . . . . . * . . . e'1 . . . . . . . . . e . . . . . * . . . e'e'1 . . . . . . . . . e . . . . * k2'. . . d'd'd'1 . . . k2'. . . . . . * * * * * . . . d'd'd'. 1 . . . . . . . . * * * * * . . . d'd'd'. . 1 . . . . . . . * * * * * n . . . d'd'd'. . . 1 n . . . . . . * * * * * * matrix L matrix U * * where columns k1, ..., k2'-1 of L consist of subdiagonal elements * of initial matrix U divided by pivots u[k,k]. * * On exit the routine returns k2', the elimination step number, from * which computing of the factorization should be continued. Note that * k2' = n+1 means that matrix U is already upper triangular. */ int sgf_singl_phase(LUF *luf, int k1, int k2, int updat, int ind[/*1+n*/], double val[/*1+n*/]) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fc_ref = luf->fc_ref; int *fc_ptr = &sva->ptr[fc_ref-1]; int *fc_len = &sva->len[fc_ref-1]; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; double *vr_piv = luf->vr_piv; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; int *qq_ind = luf->qq_ind; int *qq_inv = luf->qq_inv; int i, j, k, ptr, ptr1, end, len; double piv; /* (see routine sgf_reduce_nuc) */ xassert((1 <= k1 && k1 < k2 && k2 <= n) || (k1 == n+1 && k2 == n)); /* perform symmetric permutations of rows/columns of U */ for (k = k1; k <= k2; k++) pp_ind[pp_inv[k]] = qq_inv[qq_ind[k]] = k - k2 + n; for (k = k2+1; k <= n; k++) pp_ind[pp_inv[k]] = qq_inv[qq_ind[k]] = n - k + k1; for (k = 1; k <= n; k++) pp_inv[pp_ind[k]] = qq_ind[qq_inv[k]] = k; /* determine k2' */ k2 = n - k2 + k1; /* process rows and columns of V corresponding to rows and * columns 1, ..., k1-1 of U */ for (k = 1; k < k1; k++) { /* k-th row of U = i-th row of V */ i = pp_inv[k]; /* find pivot u[k,k] = v[i,j] in i-th row of V */ ptr = vr_ptr[i]; end = ptr + vr_len[i]; for (; qq_inv[sv_ind[ptr]] != k; ptr++) /* nop */; xassert(ptr < end); /* store pivot */ vr_piv[i] = sv_val[ptr]; /* and remove it from i-th row of V */ sv_ind[ptr] = sv_ind[end-1]; sv_val[ptr] = sv_val[end-1]; vr_len[i]--; /* clear column of V corresponding to k-th column of U */ vc_len[qq_ind[k]] = 0; } /* clear rows of V corresponding to rows k1, ..., k2'-1 of U */ for (k = k1; k < k2; k++) vr_len[pp_inv[k]] = 0; /* process rows and columns of V corresponding to rows and * columns k2', ..., n of U */ for (k = k2; k <= n; k++) { /* k-th row of U = i-th row of V */ i = pp_inv[k]; /* remove elements from i-th row of V that correspond to * elements u[k,k1], ..., u[k,k2'-1] */ ptr = ptr1 = vr_ptr[i]; end = ptr + vr_len[i]; for (; ptr < end; ptr++) { if (qq_inv[sv_ind[ptr]] >= k2) { sv_ind[ptr1] = sv_ind[ptr]; sv_val[ptr1] = sv_val[ptr]; ptr1++; } } vr_len[i] = ptr1 - vr_ptr[i]; /* k-th column of U = j-th column of V */ j = qq_ind[k]; /* remove elements from j-th column of V that correspond to * elements u[1,k], ..., u[k1-1,k] */ ptr = ptr1 = vc_ptr[j]; end = ptr + vc_len[j]; for (; ptr < end; ptr++) { if (pp_ind[sv_ind[ptr]] >= k2) /* element value is not needed in this case */ sv_ind[ptr1++] = sv_ind[ptr]; } vc_len[j] = ptr1 - vc_ptr[j]; } /* process columns of V corresponding to columns k1, ..., k2'-1 * of U, build columns of F */ for (k = k1; k < k2; k++) { /* k-th column of U = j-th column of V */ j = qq_ind[k]; /* remove elements from j-th column of V that correspond to * pivot (diagonal) element u[k,k] and subdiagonal elements * u[k+1,k], ..., u[n,k]; subdiagonal elements are stored for * further addition to matrix F */ len = 0; piv = 0.0; ptr = vc_ptr[j]; end = ptr + vc_len[j]; for (; ptr < end; ptr++) { i = sv_ind[ptr]; /* v[i,j] */ if (pp_ind[i] == k) { /* store pivot v[i,j] = u[k,k] */ piv = vr_piv[i] = sv_val[ptr]; } else if (pp_ind[i] > k) { /* store subdiagonal element v[i,j] = u[i',k] */ len++; ind[len] = i; val[len] = sv_val[ptr]; } } /* clear j-th column of V = k-th column of U */ vc_len[j] = 0; /* build k-th column of L = j-th column of F */ j = pp_inv[k]; xassert(piv != 0.0); if (len > 0) { if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_reserve_cap(sva, fc_ref-1+j, len); for (ptr = fc_ptr[j], ptr1 = 1; ptr1 <= len; ptr++, ptr1++) { sv_ind[ptr] = ind[ptr1]; sv_val[ptr] = val[ptr1] / piv; } fc_len[j] = len; } } /* if it is not planned to update matrix V, relocate all its * non-active rows corresponding to rows 1, ..., k2'-1 of U to * the right (static) part of SVA */ if (!updat) { for (k = 1; k < k2; k++) { i = pp_inv[k]; len = vr_len[i]; if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_make_static(sva, vr_ref-1+i); } } /* elimination steps 1, ..., k2'-1 have been performed */ return k2; } /*********************************************************************** * sgf_choose_pivot - choose pivot element v[p,q] * * This routine chooses pivot element v[p,q], k <= p, q <= n, in the * active submatrix of matrix V = P * U * Q, where k is the number of * current elimination step, 1 <= k <= n. * * It is assumed that on entry to the routine matrix U = P'* V * Q' has * the following partially triangularized form: * * 1 k n * 1 x x x x x x x x x x * . x x x x x x x x x * . . x x x x x x x x * . . . x x x x x x x * k . . . . * * * * * * * . . . . * * * * * * * . . . . * * * * * * * . . . . * * * * * * * . . . . * * * * * * * n . . . . * * * * * * * * where rows and columns k, k+1, ..., n belong to the active submatrix * (its elements are marked by '*'). * * Since the matrix U is not stored, the routine works with the matrix * V = P * U * Q. It is assumed that the row-wise representation * corresponds to the matrix V, but the column-wise representation * corresponds to the active submatrix of the matrix V, i.e. elements, * which are not in the active submatrix, are not included in column * vectors. It is also assumed that each active row of the matrix V is * in the set R[len], where len is the number of non-zeros in the row, * and each active column of the matrix V is in the set C[len], where * len is the number of non-zeros in the column (in the latter case * only elements of the active submatrix are counted; such elements are * marked by '*' on the figure above). * * For the reason of numerical stability the routine applies so called * threshold pivoting proposed by J.Reid. It is assumed that an element * v[i,j] can be selected as a pivot candidate if it is not very small * (in magnitude) among other elements in the same row, i.e. if it * satisfies to the stability condition |v[i,j]| >= tol * max|v[i,*]|, * where 0 < tol < 1 is a given tolerance. * * In order to keep sparsity of the matrix V the routine uses Markowitz * strategy, trying to choose such element v[p,q], which satisfies to * the stability condition (see above) and has smallest Markowitz cost * (nr[p]-1) * (nc[q]-1), where nr[p] and nc[q] are, resp., numbers of * non-zeros in p-th row and q-th column of the active submatrix. * * In order to reduce the search, i.e. not to walk through all elements * of the active submatrix, the routine uses a technique proposed by * I.Duff. This technique is based on using the sets R[len] and C[len] * of active rows and columns. * * If the pivot element v[p,q] has been chosen, the routine stores its * indices to locations *p and *q and returns zero. Otherwise, non-zero * is returned. */ int sgf_choose_pivot(SGF *sgf, int *p_, int *q_) { LUF *luf = sgf->luf; int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *rs_head = sgf->rs_head; int *rs_next = sgf->rs_next; int *cs_head = sgf->cs_head; int *cs_prev = sgf->cs_prev; int *cs_next = sgf->cs_next; double *vr_max = sgf->vr_max; double piv_tol = sgf->piv_tol; int piv_lim = sgf->piv_lim; int suhl = sgf->suhl; int i, i_ptr, i_end, j, j_ptr, j_end, len, min_i, min_j, min_len, ncand, next_j, p, q; double best, big, cost, temp; /* no pivot candidate has been chosen so far */ p = q = 0, best = DBL_MAX, ncand = 0; /* if the active submatrix contains a column having the only * non-zero element (column singleton), choose it as the pivot */ j = cs_head[1]; if (j != 0) { xassert(vc_len[j] == 1); p = sv_ind[vc_ptr[j]], q = j; goto done; } /* if the active submatrix contains a row having the only * non-zero element (row singleton), choose it as the pivot */ i = rs_head[1]; if (i != 0) { xassert(vr_len[i] == 1); p = i, q = sv_ind[vr_ptr[i]]; goto done; } /* the active submatrix contains no singletons; walk thru its * other non-empty rows and columns */ for (len = 2; len <= n; len++) { /* consider active columns containing len non-zeros */ for (j = cs_head[len]; j != 0; j = next_j) { /* save the number of next column of the same length */ next_j = cs_next[j]; /* find an element in j-th column, which is placed in the * row with minimal number of non-zeros and satisfies to * the stability condition (such element may not exist) */ min_i = min_j = 0, min_len = INT_MAX; for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; j_ptr < j_end; j_ptr++) { /* get row index of v[i,j] */ i = sv_ind[j_ptr]; /* if i-th row is not shorter, skip v[i,j] */ if (vr_len[i] >= min_len) continue; /* big := max|v[i,*]| */ if ((big = vr_max[i]) < 0.0) { /* largest magnitude is unknown; compute it */ for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; i_ptr < i_end; i_ptr++) { if ((temp = sv_val[i_ptr]) < 0.0) temp = -temp; if (big < temp) big = temp; } xassert(big > 0.0); vr_max[i] = big; } /* find v[i,j] in i-th row */ for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; sv_ind[i_ptr] != j; i_ptr++) /* nop */; xassert(i_ptr < i_end); /* if |v[i,j]| < piv_tol * max|v[i,*]|, skip v[i,j] */ if ((temp = sv_val[i_ptr]) < 0.0) temp = -temp; if (temp < piv_tol * big) continue; /* v[i,j] is a better candidate */ min_i = i, min_j = j, min_len = vr_len[i]; /* if Markowitz cost of v[i,j] is not greater than * (len-1)**2, v[i,j] can be chosen as the pivot right * now; this heuristic reduces the search and works well * in many cases */ if (min_len <= len) { p = min_i, q = min_j; goto done; } } /* j-th column has been scanned */ if (min_i != 0) { /* element v[min_i,min_j] is a next pivot candidate */ ncand++; /* compute its Markowitz cost */ cost = (double)(min_len - 1) * (double)(len - 1); /* if this element is better, choose it as the pivot */ if (cost < best) p = min_i, q = min_j, best = cost; /* if piv_lim candidates were considered, terminate * the search, because it is doubtful that a much better * candidate will be found */ if (ncand == piv_lim) goto done; } else if (suhl) { /* j-th column has no eligible elements that satisfy to * the stability criterion; Uwe Suhl suggests to exclude * such column from further considerations until it * becomes a column singleton; in hard cases this may * significantly reduce the time needed to choose the * pivot element */ sgf_deactivate_col(j); cs_prev[j] = cs_next[j] = j; } } /* consider active rows containing len non-zeros */ for (i = rs_head[len]; i != 0; i = rs_next[i]) { /* big := max|v[i,*]| */ if ((big = vr_max[i]) < 0.0) { /* largest magnitude is unknown; compute it */ for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; i_ptr < i_end; i_ptr++) { if ((temp = sv_val[i_ptr]) < 0.0) temp = -temp; if (big < temp) big = temp; } xassert(big > 0.0); vr_max[i] = big; } /* find an element in i-th row, which is placed in the * column with minimal number of non-zeros and satisfies to * the stability condition (such element always exists) */ min_i = min_j = 0, min_len = INT_MAX; for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; i_ptr < i_end; i_ptr++) { /* get column index of v[i,j] */ j = sv_ind[i_ptr]; /* if j-th column is not shorter, skip v[i,j] */ if (vc_len[j] >= min_len) continue; /* if |v[i,j]| < piv_tol * max|v[i,*]|, skip v[i,j] */ if ((temp = sv_val[i_ptr]) < 0.0) temp = -temp; if (temp < piv_tol * big) continue; /* v[i,j] is a better candidate */ min_i = i, min_j = j, min_len = vc_len[j]; /* if Markowitz cost of v[i,j] is not greater than * (len-1)**2, v[i,j] can be chosen as the pivot right * now; this heuristic reduces the search and works well * in many cases */ if (min_len <= len) { p = min_i, q = min_j; goto done; } } /* i-th row has been scanned */ if (min_i != 0) { /* element v[min_i,min_j] is a next pivot candidate */ ncand++; /* compute its Markowitz cost */ cost = (double)(len - 1) * (double)(min_len - 1); /* if this element is better, choose it as the pivot */ if (cost < best) p = min_i, q = min_j, best = cost; /* if piv_lim candidates were considered, terminate * the search, because it is doubtful that a much better * candidate will be found */ if (ncand == piv_lim) goto done; } else { /* this can never be */ xassert(min_i != min_i); } } } done: /* report the pivot to the factorization routine */ *p_ = p, *q_ = q; return (p == 0); } /*********************************************************************** * sgf_eliminate - perform gaussian elimination * * This routine performs elementary gaussian transformations in order * to eliminate subdiagonal elements in k-th column of matrix * U = P'* V * Q' using pivot element u[k,k], where k is the number of * current elimination step, 1 <= k <= n. * * The parameters p and q specify, resp., row and column indices of the * pivot element v[p,q] = u[k,k]. * * On entry the routine assumes that partially triangularized matrices * L = P'* F * P and U = P'* V * Q' have the following structure: * * 1 k n 1 k n * 1 1 . . . . . . . . . 1 x x x x x x x x x x * x 1 . . . . . . . . . x x x x x x x x x * x x 1 . . . . . . . . . x x x x x x x x * x x x 1 . . . . . . . . . x x x x x x x * k x x x x 1 . . . . . k . . . . * * * * * * * x x x x _ 1 . . . . . . . . # * * * * * * x x x x _ . 1 . . . . . . . # * * * * * * x x x x _ . . 1 . . . . . . # * * * * * * x x x x _ . . . 1 . . . . . # * * * * * * n x x x x _ . . . . 1 n . . . . # * * * * * * * matrix L matrix U * * where rows and columns k, k+1, ..., n of matrix U constitute the * active submatrix. Elements to be eliminated are marked by '#', and * other elements of the active submatrix are marked by '*'. May note * that each eliminated non-zero element u[i,k] of matrix U gives * corresponding non-zero element l[i,k] of matrix L (marked by '_'). * * Actually all operations are performed on matrix V. It is assumed * that the row-wise representation corresponds to matrix V, but the * column-wise representation corresponds to the active submatrix of * matrix V (or, more precisely, to its pattern, because only row * indices for columns of the active submatrix are used on this stage). * * Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal * elements u[i',k] = v[i,q], i'= k+1, k+2, ..., n, the routine applies * the following elementary gaussian transformations: * * (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V), * * where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier stored to * p-th column of matrix F to keep the main equality A = F * V * (corresponding elements l[i',k] of matrix L are marked by '_' on the * figure above). * * NOTE: On entry to the routine the working arrays flag and work * should contain zeros. This status is retained by the routine * on exit. */ int sgf_eliminate(SGF *sgf, int p, int q) { LUF *luf = sgf->luf; int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fc_ref = luf->fc_ref; int *fc_ptr = &sva->ptr[fc_ref-1]; int *fc_len = &sva->len[fc_ref-1]; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int *vr_cap = &sva->cap[vr_ref-1]; double *vr_piv = luf->vr_piv; int vc_ref = luf->vc_ref; int *vc_ptr = &sva->ptr[vc_ref-1]; int *vc_len = &sva->len[vc_ref-1]; int *vc_cap = &sva->cap[vc_ref-1]; int *rs_head = sgf->rs_head; int *rs_prev = sgf->rs_prev; int *rs_next = sgf->rs_next; int *cs_head = sgf->cs_head; int *cs_prev = sgf->cs_prev; int *cs_next = sgf->cs_next; double *vr_max = sgf->vr_max; char *flag = sgf->flag; double *work = sgf->work; double eps_tol = sgf->eps_tol; int nnz_diff = 0; int fill, i, i_ptr, i_end, j, j_ptr, j_end, ptr, len, loc, loc1; double vpq, fip, vij; xassert(1 <= p && p <= n); xassert(1 <= q && q <= n); /* remove p-th row from the active set; this row will never * return there */ sgf_deactivate_row(p); /* process p-th (pivot) row */ ptr = 0; for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; i_ptr < i_end; i_ptr++) { /* get column index of v[p,j] */ j = sv_ind[i_ptr]; if (j == q) { /* save pointer to pivot v[p,q] */ ptr = i_ptr; } else { /* store v[p,j], j != q, to working array */ flag[j] = 1; work[j] = sv_val[i_ptr]; } /* remove j-th column from the active set; q-th column will * never return there while other columns will return to the * active set with new length */ if (cs_next[j] == j) { /* j-th column was marked by the pivoting routine according * to Uwe Suhl's suggestion and is already inactive */ xassert(cs_prev[j] == j); } else sgf_deactivate_col(j); nnz_diff -= vc_len[j]; /* find and remove v[p,j] from j-th column */ for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; sv_ind[j_ptr] != p; j_ptr++) /* nop */; xassert(j_ptr < j_end); sv_ind[j_ptr] = sv_ind[j_end-1]; vc_len[j]--; } /* save pivot v[p,q] and remove it from p-th row */ xassert(ptr > 0); vpq = vr_piv[p] = sv_val[ptr]; sv_ind[ptr] = sv_ind[i_end-1]; sv_val[ptr] = sv_val[i_end-1]; vr_len[p]--; /* if it is not planned to update matrix V, relocate p-th row to * the right (static) part of SVA */ if (!sgf->updat) { len = vr_len[p]; if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_make_static(sva, vr_ref-1+p); } /* copy the pattern (row indices) of q-th column of the active * submatrix (from which v[p,q] has been just removed) to p-th * column of matrix F (without unity diagonal element) */ len = vc_len[q]; if (len > 0) { if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_reserve_cap(sva, fc_ref-1+p, len); memcpy(&sv_ind[fc_ptr[p]], &sv_ind[vc_ptr[q]], len * sizeof(int)); fc_len[p] = len; } /* make q-th column of the active submatrix empty */ vc_len[q] = 0; /* transform non-pivot rows of the active submatrix */ for (loc = fc_len[p]-1; loc >= 0; loc--) { /* get row index of v[i,q] = row index of f[i,p] */ i = sv_ind[fc_ptr[p] + loc]; xassert(i != p); /* v[p,q] was removed */ /* remove i-th row from the active set; this row will return * there with new length */ sgf_deactivate_row(i); /* find v[i,q] in i-th row */ for (i_end = (i_ptr = vr_ptr[i]) + vr_len[i]; sv_ind[i_ptr] != q; i_ptr++) /* nop */; xassert(i_ptr < i_end); /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] */ fip = sv_val[fc_ptr[p] + loc] = sv_val[i_ptr] / vpq; /* remove v[i,q] from i-th row */ sv_ind[i_ptr] = sv_ind[i_end-1]; sv_val[i_ptr] = sv_val[i_end-1]; vr_len[i]--; /* perform elementary gaussian transformation: * (i-th row) := (i-th row) - f[i,p] * (p-th row) * note that p-th row of V, which is in the working array, * doesn't contain pivot v[p,q], and i-th row of V doesn't * contain v[i,q] to be eliminated */ /* walk thru i-th row and transform existing elements */ fill = vr_len[p]; for (i_end = (i_ptr = ptr = vr_ptr[i]) + vr_len[i]; i_ptr < i_end; i_ptr++) { /* get column index and value of v[i,j] */ j = sv_ind[i_ptr]; vij = sv_val[i_ptr]; if (flag[j]) { /* v[p,j] != 0 */ flag[j] = 0, fill--; /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */ vij -= fip * work[j]; if (-eps_tol < vij && vij < +eps_tol) { /* new v[i,j] is close to zero; remove it from the * active submatrix, i.e. replace it by exact zero */ /* find and remove v[i,j] from j-th column */ for (j_end = (j_ptr = vc_ptr[j]) + vc_len[j]; sv_ind[j_ptr] != i; j_ptr++) /* nop */; xassert(j_ptr < j_end); sv_ind[j_ptr] = sv_ind[j_end-1]; vc_len[j]--; continue; } } /* keep new v[i,j] in i-th row */ sv_ind[ptr] = j; sv_val[ptr] = vij; ptr++; } /* (new length of i-th row may decrease because of numerical * cancellation) */ vr_len[i] = len = ptr - vr_ptr[i]; /* now flag[*] is the pattern of the set v[p,*] \ v[i,*], and * fill is the number of non-zeros in this set */ if (fill == 0) { /* no fill-in occurs */ /* walk thru p-th row and restore the column flags */ for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; i_ptr < i_end; i_ptr++) flag[sv_ind[i_ptr]] = 1; /* v[p,j] != 0 */ goto skip; } /* up to fill new non-zero elements may appear in i-th row due * to fill-in; reserve locations for these elements (note that * actual length of i-th row is currently stored in len) */ if (vr_cap[i] < len + fill) { if (sva->r_ptr - sva->m_ptr < len + fill) { sva_more_space(sva, len + fill); sv_ind = sva->ind; sv_val = sva->val; } sva_enlarge_cap(sva, vr_ref-1+i, len + fill, 0); } vr_len[i] += fill; /* walk thru p-th row and add new elements to i-th row */ for (loc1 = vr_len[p]-1; loc1 >= 0; loc1--) { /* get column index of v[p,j] */ j = sv_ind[vr_ptr[p] + loc1]; if (!flag[j]) { /* restore j-th column flag */ flag[j] = 1; /* v[i,j] was computed earlier on transforming existing * elements of i-th row */ continue; } /* v[i,j] := 0 - f[i,p] * v[p,j] */ vij = - fip * work[j]; if (-eps_tol < vij && vij < +eps_tol) { /* new v[i,j] is close to zero; do not add it to the * active submatrix, i.e. replace it by exact zero */ continue; } /* add new v[i,j] to i-th row */ sv_ind[ptr = vr_ptr[i] + (len++)] = j; sv_val[ptr] = vij; /* add new v[i,j] to j-th column */ if (vc_cap[j] == vc_len[j]) { /* we reserve extra locations in j-th column to reduce * further relocations of that column */ #if 1 /* FIXME */ /* use control parameter to specify the number of extra * locations reserved */ int need = vc_len[j] + 10; #endif if (sva->r_ptr - sva->m_ptr < need) { sva_more_space(sva, need); sv_ind = sva->ind; sv_val = sva->val; } sva_enlarge_cap(sva, vc_ref-1+j, need, 1); } sv_ind[vc_ptr[j] + (vc_len[j]++)] = i; } /* set final length of i-th row just transformed */ xassert(len <= vr_len[i]); vr_len[i] = len; skip: /* return i-th row to the active set with new length */ sgf_activate_row(i); /* since i-th row has been changed, largest magnitude of its * elements becomes unknown */ vr_max[i] = -1.0; } /* walk thru p-th (pivot) row */ for (i_end = (i_ptr = vr_ptr[p]) + vr_len[p]; i_ptr < i_end; i_ptr++) { /* get column index of v[p,j] */ j = sv_ind[i_ptr]; xassert(j != q); /* v[p,q] was removed */ /* return j-th column to the active set with new length */ if (cs_next[j] == j && vc_len[j] != 1) { /* j-th column was marked by the pivoting routine and it is * still not a column singleton, so leave it incative */ xassert(cs_prev[j] == j); } else sgf_activate_col(j); nnz_diff += vc_len[j]; /* restore zero content of the working arrays */ flag[j] = 0; work[j] = 0.0; } /* return the difference between the numbers of non-zeros in the * active submatrix on entry and on exit, resp. */ return nnz_diff; } /*********************************************************************** * sgf_dense_lu - compute dense LU-factorization with full pivoting * * This routine performs Gaussian elimination with full pivoting to * compute dense LU-factorization of the specified matrix A of order n * in the form: * * A = P * L * U * Q, (1) * * where L is lower triangular matrix with unit diagonal, U is upper * triangular matrix, P and Q are permutation matrices. * * On entry to the routine elements of matrix A = (a[i,j]) should be * placed in the array elements a[0], ..., a[n^2-1] in dense row-wise * format. On exit from the routine matrix A is replaced by factors L * and U as follows: * * u[1,1] u[1,2] ... u[1,n-1] u[1,n] * l[2,1] u[2,2] ... u[2,n-1] u[2,n] * . . . . . . . . . . . . . . * l[n-1,1] l[n-1,2] u[n-1,n-1] u[n-1,n] * l[n,1] l[n,2] ... l[n,n-1] u[n,n] * * The unit diagonal elements of L are not stored. * * Information on permutations of rows and columns of active submatrix * during factorization is accumulated by the routine as follows. Every * time the routine permutes rows i and i' or columns j and j', it also * permutes elements r[i-1] and r[i'-1] or c[j-1] and c[j'-1], resp. * Thus, on entry to the routine elements r[0], r[1], ..., r[n-1] and * c[0], c[1], ..., c[n-1] should be initialized by some integers that * identify rows and columns of the original matrix A. * * If the factorization has been successfully computed, the routine * returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, * all elements of the active submatrix are close to zero, the routine * returns k, in which case a partial factorization is stored in the * array a. */ int sgf_dense_lu(int n, double a_[], int r[], int c[], double eps) { /* non-optimized version */ int i, j, k, p, q, ref; double akk, big, temp; # define a(i,j) a_[(i)*n+(j)] /* initially U = A, L = P = Q = I */ /* main elimination loop */ for (k = 0; k < n; k++) { /* choose pivot u[p,q], k <= p, q <= n */ p = q = -1, big = eps; for (i = k; i < n; i++) { for (j = k; j < n; j++) { /* temp = |u[i,j]| */ if ((temp = a(i,j)) < 0.0) temp = -temp; if (big < temp) p = i, q = j, big = temp; } } if (p < 0) { /* k-th elimination step failed */ return k+1; } /* permute rows k and p */ if (k != p) { for (j = 0; j < n; j++) temp = a(k,j), a(k,j) = a(p,j), a(p,j) = temp; ref = r[k], r[k] = r[p], r[p] = ref; } /* permute columns k and q */ if (k != q) { for (i = 0; i < n; i++) temp = a(i,k), a(i,k) = a(i,q), a(i,q) = temp; ref = c[k], c[k] = c[q], c[q] = ref; } /* now pivot is in position u[k,k] */ akk = a(k,k); /* eliminate subdiagonal elements u[k+1,k], ..., u[n,k] */ for (i = k+1; i < n; i++) { if (a(i,k) != 0.0) { /* gaussian multiplier l[i,k] := u[i,k] / u[k,k] */ temp = (a(i,k) /= akk); /* (i-th row) := (i-th row) - l[i,k] * (k-th row) */ for (j = k+1; j < n; j++) a(i,j) -= temp * a(k,j); } } } # undef a return 0; } /*********************************************************************** * sgf_dense_phase - compute LU-factorization (dense phase) * * This routine performs dense phase of computing LU-factorization. * * The aim is two-fold. First, the main factorization routine switches * to dense phase when the active submatrix is relatively dense, so * using dense format allows significantly reduces overheads needed to * maintain sparse data structures. And second, that is more important, * on dense phase full pivoting is used (rather than partial pivoting) * that allows improving numerical stability, since round-off errors * tend to increase on last steps of the elimination process. * * On entry the routine assumes that elimination steps 1, 2, ..., k-1 * have been performed, so partially transformed matrices L = P'* F * P * and U = P'* V * Q' have the following structure: * * 1 k n 1 k n * 1 1 . . . . . . . . . 1 x x x x x x x x x x * x 1 . . . . . . . . . x x x x x x x x x * x x 1 . . . . . . . . . x x x x x x x x * x x x 1 . . . . . . . . . x x x x x x x * k x x x x 1 . . . . . k . . . . * * * * * * * x x x x . 1 . . . . . . . . * * * * * * * x x x x . . 1 . . . . . . . * * * * * * * x x x x . . . 1 . . . . . . * * * * * * * x x x x . . . . 1 . . . . . * * * * * * * n x x x x . . . . . 1 n . . . . * * * * * * * * matrix L matrix U * * where rows and columns k, k+1, ..., n of matrix U constitute the * active submatrix A~, whose elements are marked by '*'. * * The routine copies the active submatrix A~ to a working array in * dense format, compute dense factorization A~ = P~* L~* U~* Q~ using * full pivoting, and then copies non-zero elements of factors L~ and * U~ back to factors L and U (more precisely, to factors F and V). * * If the factorization has been successfully computed, the routine * returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, * all elements of the active submatrix are close to zero, the routine * returns k (information on linearly dependent rows/columns in this * case is provided by matrices P and Q). */ int sgf_dense_phase(LUF *luf, int k, int updat) { int n = luf->n; SVA *sva = luf->sva; int *sv_ind = sva->ind; double *sv_val = sva->val; int fc_ref = luf->fc_ref; int *fc_ptr = &sva->ptr[fc_ref-1]; int *fc_len = &sva->len[fc_ref-1]; int *fc_cap = &sva->cap[fc_ref-1]; int vr_ref = luf->vr_ref; int *vr_ptr = &sva->ptr[vr_ref-1]; int *vr_len = &sva->len[vr_ref-1]; int *vr_cap = &sva->cap[vr_ref-1]; double *vr_piv = luf->vr_piv; int vc_ref = luf->vc_ref; int *vc_len = &sva->len[vc_ref-1]; int *pp_inv = luf->pp_inv; int *pp_ind = luf->pp_ind; int *qq_ind = luf->qq_ind; int *qq_inv = luf->qq_inv; int a_end, a_ptr, end, i, ia, ii, j, ja, jj, ka, len, na, ne, need, ptr; double *a_; xassert(1 <= k && k <= n); /* active columns of V are not longer needed; make them empty */ for (jj = k; jj <= n; jj++) { /* jj is number of active column of U = P'* V * Q' */ vc_len[qq_ind[jj]] = 0; } /* determine order of active submatrix A~ of matrix U */ na = n - k + 1; xassert(1 <= na && na <= n); /* determine number of elements in dense triangular factor (L~ or * U~), except diagonal elements */ ne = na * (na - 1) / 2; /* we allocate active submatrix A~ in free (middle) part of SVA; * to avoid defragmentation that could destroy A~ we also should * reserve ne locations to build rows of V from rows of U~ and ne * locations to build columns of F from columns of L~ */ need = na * na + ne + ne; if (sva->r_ptr - sva->m_ptr < need) { sva_more_space(sva, need); sv_ind = sva->ind; sv_val = sva->val; } /* free (middle) part of SVA is structured as follows: * end of left (dynamic) part * ne free locations for new rows of V * na free locations for active submatrix A~ * unused locations, if any * ne free locations for new columns of F * beginning of right (static) part */ a_ptr = sva->m_ptr + ne; a_end = a_ptr + na * na; /* copy active submatrix A~ from matrix V to working array in * dense row-wise format */ a_ = &sva->val[a_ptr]; # define a(ia, ja) a_[((ia) - 1) * na + ((ja) - 1)] for (ia = 1; ia <= na; ia++) { /* clear ia-th row of A~ */ for (ja = 1; ja <= na; ja++) a(ia, ja) = 0.0; /* ia-th row of A~ = (k-1+ia)-th row of U = i-th row of V */ i = pp_inv[k-1+ia]; ptr = vr_ptr[i]; end = ptr + vr_len[i]; for (; ptr < end; ptr++) a(ia, qq_inv[sv_ind[ptr]]-k+1) = sv_val[ptr]; /* i-th row of V is no longer needed; make it empty */ vr_len[i] = 0; } /* compute dense factorization A~ = P~* L~* U~* Q~ */ #if 1 /* FIXME: epsilon tolerance */ ka = sgf_dense_lu(na, &a(1, 1), &pp_inv[k], &qq_ind[k], 1e-20); #endif /* rows of U with numbers pp_inv[k, k+1, ..., n] were permuted * due to row permutations of A~; update matrix P using P~ */ for (ii = k; ii <= n; ii++) pp_ind[pp_inv[ii]] = ii; /* columns of U with numbers qq_ind[k, k+1, ..., n] were permuted * due to column permutations of A~; update matrix Q using Q~ */ for (jj = k; jj <= n; jj++) qq_inv[qq_ind[jj]] = jj; /* check if dense factorization is complete */ if (ka != 0) { /* A~ is singular to working precision */ /* information on linearly dependent rows/columns is provided * by matrices P and Q */ xassert(1 <= ka && ka <= na); return k - 1 + ka; } /* build new rows of V from rows of U~ */ for (ia = 1; ia <= na; ia++) { /* ia-th row of U~ = (k-1+ia)-th row of U = i-th row of V */ i = pp_inv[k-1+ia]; xassert(vr_len[i] == 0); /* store diagonal element u~[ia,ia] */ vr_piv[i] = a(ia, ia); /* determine number of non-zero non-diagonal elements in ia-th row of U~ */ len = 0; for (ja = ia+1; ja <= na; ja++) { if (a(ia, ja) != 0.0) len++; } /* reserve len locations for i-th row of matrix V in left * (dynamic) part of SVA */ if (vr_cap[i] < len) { /* there should be enough room in free part of SVA */ xassert(sva->r_ptr - sva->m_ptr >= len); sva_enlarge_cap(sva, vr_ref-1+i, len, 0); /* left part of SVA should not overlap matrix A~ */ xassert(sva->m_ptr <= a_ptr); } /* copy non-zero non-diaginal elements of ia-th row of U~ to * i-th row of V */ ptr = vr_ptr[i]; for (ja = ia+1; ja <= na; ja++) { if (a(ia, ja) != 0.0) { sv_ind[ptr] = qq_ind[k-1+ja]; sv_val[ptr] = a(ia, ja); ptr++; } } xassert(ptr - vr_ptr[i] == len); vr_len[i] = len; } /* build new columns of F from columns of L~ */ for (ja = 1; ja <= na; ja++) { /* ja-th column of L~ = (k-1+ja)-th column of L = j-th column * of F */ j = pp_inv[k-1+ja]; xassert(fc_len[j] == 0); xassert(fc_cap[j] == 0); /* determine number of non-zero non-diagonal elements in ja-th * column of L~ */ len = 0; for (ia = ja+1; ia <= na; ia++) { if (a(ia, ja) != 0.0) len++; } /* reserve len locations for j-th column of matrix F in right * (static) part of SVA */ /* there should be enough room in free part of SVA */ xassert(sva->r_ptr - sva->m_ptr >= len); if (len > 0) sva_reserve_cap(sva, fc_ref-1+j, len); /* right part of SVA should not overlap matrix A~ */ xassert(a_end <= sva->r_ptr); /* copy non-zero non-diagonal elements of ja-th column of L~ * to j-th column of F */ ptr = fc_ptr[j]; for (ia = ja+1; ia <= na; ia++) { if (a(ia, ja) != 0.0) { sv_ind[ptr] = pp_inv[k-1+ia]; sv_val[ptr] = a(ia, ja); ptr++; } } xassert(ptr - fc_ptr[j] == len); fc_len[j] = len; } /* factors L~ and U~ are no longer needed */ # undef a /* if it is not planned to update matrix V, relocate all its new * rows to the right (static) part of SVA */ if (!updat) { for (ia = 1; ia <= na; ia++) { i = pp_inv[k-1+ia]; len = vr_len[i]; if (sva->r_ptr - sva->m_ptr < len) { sva_more_space(sva, len); sv_ind = sva->ind; sv_val = sva->val; } sva_make_static(sva, vr_ref-1+i); } } return 0; } /*********************************************************************** * sgf_factorize - compute LU-factorization (main routine) * * This routine computes sparse LU-factorization of specified matrix A * using Gaussian elimination. * * On entry to the routine matrix V = A should be stored in column-wise * format. * * If the factorization has been successfully computed, the routine * returns zero. Otherwise, if on k-th elimination step, 1 <= k <= n, * all elements of the active submatrix are close to zero, the routine * returns k (information on linearly dependent rows/columns in this * case is provided by matrices P and Q). */ int sgf_factorize(SGF *sgf, int singl) { LUF *luf = sgf->luf; int n = luf->n; SVA *sva = luf->sva; int vr_ref = luf->vr_ref; int *vr_len = &sva->len[vr_ref-1]; double *vr_piv = luf->vr_piv; int vc_ref = luf->vc_ref; int *vc_len = &sva->len[vc_ref-1]; int *pp_ind = luf->pp_ind; int *pp_inv = luf->pp_inv; int *qq_ind = luf->qq_ind; int *qq_inv = luf->qq_inv; int *rs_head = sgf->rs_head; int *rs_prev = sgf->rs_prev; int *rs_next = sgf->rs_next; int *cs_head = sgf->cs_head; int *cs_prev = sgf->cs_prev; int *cs_next = sgf->cs_next; double *vr_max = sgf->vr_max; char *flag = sgf->flag; double *work = sgf->work; int i, j, k, k1, k2, p, q, nnz; /* build matrix V = A in row-wise format */ luf_build_v_rows(luf, rs_prev); /* P := Q := I, so V = U = A, F = L = I */ for (k = 1; k <= n; k++) { vr_piv[k] = 0.0; pp_ind[k] = pp_inv[k] = qq_ind[k] = qq_inv[k] = k; } #ifdef GLP_DEBUG sva_check_area(sva); luf_check_all(luf, 1); #endif /* perform singleton phase, if required */ if (!singl) { /* assume that nucleus is entire matrix U */ k2 = 1; } else { /* minimize nucleus size */ sgf_reduce_nuc(luf, &k1, &k2, rs_prev, rs_next); #ifdef GLP_DEBUG xprintf("n = %d; k1 = %d; k2 = %d\n", n, k1, k2); #endif /* perform singleton phase */ k2 = sgf_singl_phase(luf, k1, k2, sgf->updat, rs_prev, work); } #ifdef GLP_DEBUG sva_check_area(sva); luf_check_all(luf, k2); #endif /* initialize working arrays */ rs_head[0] = cs_head[0] = 0; for (k = 1; k <= n; k++) { rs_head[k] = cs_head[k] = 0; vr_max[k] = -1.0; flag[k] = 0; work[k] = 0.0; } /* build lists of active rows and columns of matrix V; determine * number of non-zeros in initial active submatrix */ nnz = 0; for (k = k2; k <= n; k++) { i = pp_inv[k]; sgf_activate_row(i); nnz += vr_len[i]; j = qq_ind[k]; sgf_activate_col(j); } /* main factorization loop */ for (k = k2; k <= n; k++) { int na; double den; /* calculate density of active submatrix */ na = n - k + 1; /* order of active submatrix */ den = (double)nnz / (double)(na * na); /* if active submatrix is relatively dense, switch to dense * phase */ #if 1 /* FIXME */ if (na >= 5 && den >= 0.71) { #ifdef GLP_DEBUG xprintf("na = %d; nnz = %d; den = %g\n", na, nnz, den); #endif break; } #endif /* choose pivot v[p,q] */ if (sgf_choose_pivot(sgf, &p, &q) != 0) return k; /* failure */ /* u[i,j] = v[p,q], k <= i, j <= n */ i = pp_ind[p]; xassert(k <= i && i <= n); j = qq_inv[q]; xassert(k <= j && j <= n); /* move u[i,j] to position u[k,k] by implicit permutations of * rows and columns of matrix U */ luf_swap_u_rows(k, i); luf_swap_u_cols(k, j); /* perform gaussian elimination */ nnz += sgf_eliminate(sgf, p, q); } #if 1 /* FIXME */ if (k <= n) { /* continue computing factorization in dense mode */ #ifdef GLP_DEBUG sva_check_area(sva); luf_check_all(luf, k); #endif k = sgf_dense_phase(luf, k, sgf->updat); if (k != 0) return k; /* failure */ } #endif #ifdef GLP_DEBUG sva_check_area(sva); luf_check_all(luf, n+1); #endif /* defragment SVA; currently all columns of V are empty, so they * will have zero capacity as required by luf_build_v_cols */ sva_defrag_area(sva); /* build matrix F in row-wise format */ luf_build_f_rows(luf, rs_head); /* build matrix V in column-wise format */ luf_build_v_cols(luf, sgf->updat, rs_head); return 0; } /* eof */ glpk-4.52.1/src/bflib/sgf.h0000644000062000006210000002030612175147600014517 0ustar maomkpasswd/* sgf.h (sparse Gaussian factorizer) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef SGF_H #define SGF_H #include "luf.h" typedef struct SGF SGF; struct SGF { /* sparse Gaussian factorizer workspace */ LUF *luf; /* LU-factorization being computed */ /*--------------------------------------------------------------*/ /* to efficiently choose pivot elements according to Markowitz * strategy, the search technique proposed by Iain Duff is used; * it is based on using two families of sets {R[0], ..., R[n]} * and {C[0], ..., C[n]}, where R[k] and C[k], 0 <= k <= n, are, * respectively, sets of rows and columns of the active submatrix * of matrix V having k non-zeros (i.e. whose length is k); each * set R[k] and C[k] is implemented as a doubly linked list */ int *rs_head; /* int rs_head[1+n]; */ /* rs_head[k], 0 <= k <= n, is the number of first row, which * has k non-zeros in the active submatrix */ int *rs_prev; /* int rs_prev[1+n]; */ /* rs_prev[0] is not used; * rs_prev[i], 1 <= i <= n, is the number of previous row, which * has the same number of non-zeros as i-th row; * rs_prev[i] < 0 means that i-th row is inactive */ int *rs_next; /* int rs_next[1+n]; */ /* rs_next[0] is not used; * rs_next[i], 1 <= i <= n, is the number of next row, which has * the same number of non-zeros as i-th row; * rs_next[i] < 0 means that i-th row is inactive */ int *cs_head; /* int cs_head[1+n]; */ /* cs_head[k], 0 <= k <= n, is the number of first column, which * has k non-zeros in the active submatrix */ int *cs_prev; /* int cs_prev[1+n]; */ /* cs_prev[0] is not used; * cs_prev[j], 1 <= j <= n, is the number of previous column, * which has the same number of non-zeros as j-th column; * cs_prev[j] < 0 means that j-th column is inactive */ int *cs_next; /* int cs_next[1+n]; */ /* cs_next[0] is not used; * cs_next[j], 1 <= j <= n, is the number of next column, which * has the same number of non-zeros as j-th column; * cs_next[j] < 0 means that j-th column is inactive */ /* NOTE: cs_prev[j] = cs_next[j] = j means that j-th column was * temporarily removed from corresponding set C[k] by the * pivoting routine according to Uwe Suhl's heuristic */ /*--------------------------------------------------------------*/ /* working arrays */ double *vr_max; /* int vr_max[1+n]; */ /* vr_max[0] is not used; * vr_max[i], 1 <= i <= n, is used only if i-th row of matrix V * is active (i.e. belongs to the active submatrix), and is the * largest magnitude of elements in that row; if vr_max[i] < 0, * the largest magnitude is unknown yet */ char *flag; /* char flag[1+n]; */ /* boolean working array */ double *work; /* double work[1+n]; */ /* floating-point working array */ /*--------------------------------------------------------------*/ /* control parameters */ int updat; /* if this flag is set, the matrix V is assumed to be updatable; * in this case factorized (non-active) part of V is stored in * the left part of SVA rather than in its right part */ double piv_tol; /* threshold pivoting tolerance, 0 < piv_tol < 1; element v[i,j] * of the active submatrix fits to be pivot if it satisfies to * the stability criterion |v[i,j]| >= piv_tol * max |v[i,*]|, * i.e. if it is not very small in the magnitude among other * elements in the same row; decreasing this parameter gives * better sparsity at the expense of numerical accuracy and vice * versa */ int piv_lim; /* maximal allowable number of pivot candidates to be considered; * if piv_lim pivot candidates have been considered, the pivoting * routine terminates the search with the best candidate found */ int suhl; /* if this flag is set, the pivoting routine applies a heuristic * proposed by Uwe Suhl: if a column of the active submatrix has * no eligible pivot candidates (i.e. all its elements do not * satisfy to the stability criterion), the routine excludes it * from futher consideration until it becomes column singleton; * in many cases this allows reducing the time needed to choose * the pivot */ double eps_tol; /* epsilon tolerance; each element of the active submatrix, whose * magnitude is less than eps_tol, is replaced by exact zero */ #if 0 /* FIXME */ double den_lim; /* density limit; if the density of the active submatrix reaches * this limit, the factorization routine switches from sparse to * dense mode */ #endif }; #define sgf_activate_row(i) \ do \ { int len = vr_len[i]; \ rs_prev[i] = 0; \ rs_next[i] = rs_head[len]; \ if (rs_next[i] != 0) \ rs_prev[rs_next[i]] = i; \ rs_head[len] = i; \ } while (0) /* include i-th row of matrix V in active set R[len] */ #define sgf_deactivate_row(i) \ do \ { if (rs_prev[i] == 0) \ rs_head[vr_len[i]] = rs_next[i]; \ else \ rs_next[rs_prev[i]] = rs_next[i]; \ if (rs_next[i] == 0) \ ; \ else \ rs_prev[rs_next[i]] = rs_prev[i]; \ rs_prev[i] = rs_next[i] = -1; \ } while (0) /* remove i-th row of matrix V from active set R[len] */ #define sgf_activate_col(j) \ do \ { int len = vc_len[j]; \ cs_prev[j] = 0; \ cs_next[j] = cs_head[len]; \ if (cs_next[j] != 0) \ cs_prev[cs_next[j]] = j; \ cs_head[len] = j; \ } while (0) /* include j-th column of matrix V in active set C[len] */ #define sgf_deactivate_col(j) \ do \ { if (cs_prev[j] == 0) \ cs_head[vc_len[j]] = cs_next[j]; \ else \ cs_next[cs_prev[j]] = cs_next[j]; \ if (cs_next[j] == 0) \ ; \ else \ cs_prev[cs_next[j]] = cs_prev[j]; \ cs_prev[j] = cs_next[j] = -1; \ } while (0) /* remove j-th column of matrix V from active set C[len] */ #define sgf_reduce_nuc _glp_sgf_reduce_nuc void sgf_reduce_nuc(LUF *luf, int *k1, int *k2, int cnt[/*1+n*/], int list[/*1+n*/]); /* initial reordering to minimize nucleus size */ #define sgf_singl_phase _glp_sgf_singl_phase int sgf_singl_phase(LUF *luf, int k1, int k2, int updat, int ind[/*1+n*/], double val[/*1+n*/]); /* compute LU-factorization (singleton phase) */ #define sgf_choose_pivot _glp_sgf_choose_pivot int sgf_choose_pivot(SGF *sgf, int *p, int *q); /* choose pivot element v[p,q] */ #define sgf_eliminate _glp_sgf_eliminate int sgf_eliminate(SGF *sgf, int p, int q); /* perform gaussian elimination */ #define sgf_dense_lu _glp_sgf_dense_lu int sgf_dense_lu(int n, double a[], int r[], int c[], double eps); /* compute dense LU-factorization with full pivoting */ #define sgf_dense_phase _glp_sgf_dense_phase int sgf_dense_phase(LUF *luf, int k, int updat); /* compute LU-factorization (dense phase) */ #define sgf_factorize _glp_sgf_factorize int sgf_factorize(SGF *sgf, int singl); /* compute LU-factorization (main routine) */ #endif /* eof */ glpk-4.52.1/src/bflib/sva.c0000644000062000006210000004553612175147600014540 0ustar maomkpasswd/* sva.c (sparse vector area) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "sva.h" /*********************************************************************** * sva_create_area - create sparse vector area (SVA) * * This routine creates the sparse vector area (SVA), which initially * is empty. * * The parameter n_max specifies the initial number of vectors that can * be allocated in the SVA, n_max > 0. * * The parameter size specifies the initial number of free locations in * the SVA, size > 0. * * On exit the routine returns a pointer to the SVA created. */ SVA *sva_create_area(int n_max, int size) { SVA *sva; xassert(0 < n_max && n_max < INT_MAX); xassert(0 < size && size < INT_MAX); sva = talloc(1, SVA); sva->n_max = n_max; sva->n = 0; sva->ptr = talloc(1+n_max, int); sva->len = talloc(1+n_max, int); sva->cap = talloc(1+n_max, int); sva->size = size; sva->m_ptr = 1; sva->r_ptr = size+1; sva->head = sva->tail = 0; sva->prev = talloc(1+n_max, int); sva->next = talloc(1+n_max, int); sva->ind = talloc(1+size, int); sva->val = talloc(1+size, double); sva->talky = 0; return sva; } /*********************************************************************** * sva_alloc_vecs - allocate new vectors in SVA * * This routine allocates nnn new empty vectors, nnn > 0, in the sparse * vector area (SVA). * * The new vectors are assigned reference numbers k, k+1, ..., k+nnn-1, * where k is a reference number assigned to the very first new vector, * which is returned by the routine on exit. */ int sva_alloc_vecs(SVA *sva, int nnn) { int n = sva->n; int n_max = sva->n_max; int *ptr = sva->ptr; int *len = sva->len; int *cap = sva->cap; int *prev = sva->prev; int *next = sva->next; int k, new_n; #if 1 if (sva->talky) xprintf("sva_alloc_vecs: nnn = %d\n", nnn); #endif xassert(nnn > 0); /* determine new number of vectors in SVA */ new_n = n + nnn; xassert(new_n > n); if (n_max < new_n) { /* enlarge the SVA arrays */ while (n_max < new_n) { n_max += n_max; xassert(n_max > 0); } sva->n_max = n_max; sva->ptr = ptr = trealloc(ptr, 1+n_max, int); sva->len = len = trealloc(len, 1+n_max, int); sva->cap = cap = trealloc(cap, 1+n_max, int); sva->prev = prev = trealloc(prev, 1+n_max, int); sva->next = next = trealloc(next, 1+n_max, int); } /* initialize new vectors */ sva->n = new_n; for (k = n+1; k <= new_n; k++) { ptr[k] = len[k] = cap[k] = 0; prev[k] = next[k] = -1; } #if 1 if (sva->talky) xprintf("now sva->n_max = %d, sva->n = %d\n", sva->n_max, sva->n); #endif /* return reference number of very first new vector */ return n+1; } /*********************************************************************** * sva_resize_area - change size of SVA storage * * This routine increases or decrases the size of the SVA storage by * reallocating it. * * The parameter delta specifies the number of location by which the * current size of the SVA storage should be increased (if delta > 0) * or decreased (if delta < 0). Note that if delta is negative, it * should not be less than the current size of the middle part. * * As a result of this operation the size of the middle part of SVA is * increased/decreased by delta locations. * * NOTE: This operation changes ptr[k] for all vectors stored in the * right part of SVA. */ void sva_resize_area(SVA *sva, int delta) { int n = sva->n; int *ptr = sva->ptr; int size = sva->size; int m_ptr = sva->m_ptr; int r_ptr = sva->r_ptr; int k, r_size; #if 1 if (sva->talky) xprintf("sva_resize_area: delta = %d\n", delta); #endif xassert(delta != 0); /* determine size of the right part, in locations */ r_size = size - r_ptr + 1; /* relocate the right part in case of negative delta */ if (delta < 0) { xassert(delta >= m_ptr - r_ptr); sva->r_ptr += delta; memmove(&sva->ind[sva->r_ptr], &sva->ind[r_ptr], r_size * sizeof(int)); memmove(&sva->val[sva->r_ptr], &sva->val[r_ptr], r_size * sizeof(double)); } /* reallocate the storage arrays */ xassert(delta < INT_MAX - sva->size); sva->size += delta; sva->ind = trealloc(sva->ind, 1+sva->size, int); sva->val = trealloc(sva->val, 1+sva->size, double); /* relocate the right part in case of positive delta */ if (delta > 0) { sva->r_ptr += delta; memmove(&sva->ind[sva->r_ptr], &sva->ind[r_ptr], r_size * sizeof(int)); memmove(&sva->val[sva->r_ptr], &sva->val[r_ptr], r_size * sizeof(double)); } /* update pointers to vectors stored in the right part */ for (k = 1; k <= n; k++) { if (ptr[k] >= r_ptr) ptr[k] += delta; } #if 1 if (sva->talky) xprintf("now sva->size = %d\n", sva->size); #endif return; } /*********************************************************************** * sva_defrag_area - defragment left part of SVA * * This routine performs "garbage" collection to defragment the left * part of SVA. * * NOTE: This operation may change ptr[k] and cap[k] for all vectors * stored in the left part of SVA. */ void sva_defrag_area(SVA *sva) { int *ptr = sva->ptr; int *len = sva->len; int *cap = sva->cap; int *prev = sva->prev; int *next = sva->next; int *ind = sva->ind; double *val = sva->val; int k, next_k, ptr_k, len_k, m_ptr, head, tail; #if 1 if (sva->talky) { xprintf("sva_defrag_area:\n"); xprintf("before defragmenting = %d %d %d\n", sva->m_ptr - 1, sva->r_ptr - sva->m_ptr, sva->size + 1 - sva->r_ptr); } #endif m_ptr = 1; head = tail = 0; /* walk through the linked list of vectors stored in the left * part of SVA */ for (k = sva->head; k != 0; k = next_k) { /* save number of next vector in the list */ next_k = next[k]; /* determine length of k-th vector */ len_k = len[k]; if (len_k == 0) { /* k-th vector is empty; remove it from the left part */ ptr[k] = cap[k] = 0; prev[k] = next[k] = -1; } else { /* determine pointer to first location of k-th vector */ ptr_k = ptr[k]; xassert(m_ptr <= ptr_k); /* relocate k-th vector to the beginning of the left part, * if necessary */ if (m_ptr < ptr_k) { memmove(&ind[m_ptr], &ind[ptr_k], len_k * sizeof(int)); memmove(&val[m_ptr], &val[ptr_k], len_k * sizeof(double)); ptr[k] = m_ptr; } /* remove unused locations from k-th vector */ cap[k] = len_k; /* the left part of SVA has been enlarged */ m_ptr += len_k; /* add k-th vector to the end of the new linked list */ prev[k] = tail; next[k] = 0; if (head == 0) head = k; else next[tail] = k; tail = k; } } /* set new pointer to the middle part of SVA */ xassert(m_ptr <= sva->r_ptr); sva->m_ptr = m_ptr; /* set new head and tail of the linked list */ sva->head = head; sva->tail = tail; #if 1 if (sva->talky) xprintf("after defragmenting = %d %d %d\n", sva->m_ptr - 1, sva->r_ptr - sva->m_ptr, sva->size + 1 - sva->r_ptr); #endif return; } /*********************************************************************** * sva_more_space - increase size of middle (free) part of SVA * * This routine increases the size of the middle (free) part of the * sparse vector area (SVA). * * The parameter m_size specifies the minimal size, in locations, of * the middle part to be provided. This new size should be greater than * the current size of the middle part. * * First, the routine defragments the left part of SVA. Then, if the * size of the left part has not sufficiently increased, the routine * increases the total size of the SVA storage by reallocating it. */ void sva_more_space(SVA *sva, int m_size) { int size, delta; #if 1 if (sva->talky) xprintf("sva_more_space: m_size = %d\n", m_size); #endif xassert(m_size > sva->r_ptr - sva->m_ptr); /* defragment the left part */ sva_defrag_area(sva); /* set, heuristically, the minimal size of the middle part to be * not less than the size of the defragmented left part */ if (m_size < sva->m_ptr - 1) m_size = sva->m_ptr - 1; /* if there is still not enough room, increase the total size of * the SVA storage */ if (sva->r_ptr - sva->m_ptr < m_size) { size = sva->size; /* new sva size */ for (;;) { delta = size - sva->size; if (sva->r_ptr - sva->m_ptr + delta >= m_size) break; size += size; xassert(size > 0); } sva_resize_area(sva, delta); xassert(sva->r_ptr - sva->m_ptr >= m_size); } return; } /*********************************************************************** * sva_enlarge_cap - enlarge capacity of specified vector * * This routine enlarges the current capacity of the specified vector * by relocating its content. * * The parameter k specifies the reference number of the vector whose * capacity should be enlarged, 1 <= k <= n. This vector should either * have zero capacity or be stored in the left (dynamic) part of SVA. * * The parameter new_cap specifies the new capacity of the vector, * in locations. This new capacity should be greater than the current * capacity of the vector. * * The parameter skip is a flag. If this flag is set, the routine does * *not* copy numerical values of elements of the vector on relocating * its content, i.e. only element indices are copied. * * NOTE: On entry to the routine the middle part of SVA should have at * least new_cap free locations. */ void sva_enlarge_cap(SVA *sva, int k, int new_cap, int skip) { int *ptr = sva->ptr; int *len = sva->len; int *cap = sva->cap; int *prev = sva->prev; int *next = sva->next; int *ind = sva->ind; double *val = sva->val; xassert(1 <= k && k <= sva->n); xassert(new_cap > cap[k]); /* there should be at least new_cap free locations */ xassert(sva->r_ptr - sva->m_ptr >= new_cap); /* relocate the vector */ if (cap[k] == 0) { /* the vector is empty */ xassert(ptr[k] == 0); xassert(len[k] == 0); } else { /* the vector has non-zero capacity */ xassert(ptr[k] + len[k] <= sva->m_ptr); /* copy the current vector content to the beginning of the * middle part */ if (len[k] > 0) { memcpy(&ind[sva->m_ptr], &ind[ptr[k]], len[k] * sizeof(int)); if (!skip) memcpy(&val[sva->m_ptr], &val[ptr[k]], len[k] * sizeof(double)); } /* remove the vector from the linked list */ if (prev[k] == 0) sva->head = next[k]; else { /* preceding vector exists; increase its capacity */ cap[prev[k]] += cap[k]; next[prev[k]] = next[k]; } if (next[k] == 0) sva->tail = prev[k]; else prev[next[k]] = prev[k]; } /* set new pointer and capacity of the vector */ ptr[k] = sva->m_ptr; cap[k] = new_cap; /* add the vector to the end of the linked list */ prev[k] = sva->tail; next[k] = 0; if (sva->head == 0) sva->head = k; else next[sva->tail] = k; sva->tail = k; /* new_cap free locations have been consumed */ sva->m_ptr += new_cap; xassert(sva->m_ptr <= sva->r_ptr); return; } /*********************************************************************** * sva_reserve_cap - reserve locations for specified vector * * This routine reserves locations for the specified vector in the * right (static) part of SVA. * * The parameter k specifies the reference number of the vector (this * vector should have zero capacity), 1 <= k <= n. * * The parameter new_cap specifies a non-zero capacity of the vector, * in locations. * * NOTE: On entry to the routine the middle part of SVA should have at * least new_cap free locations. */ void sva_reserve_cap(SVA *sva, int k, int new_cap) { int *ptr = sva->ptr; int *len = sva->len; int *cap = sva->cap; xassert(1 <= k && k <= sva->n); xassert(new_cap > 0); xassert(ptr[k] == 0 && len[k] == 0 && cap[k] == 0); /* there should be at least new_cap free locations */ xassert(sva->r_ptr - sva->m_ptr >= new_cap); /* set the pointer and capacity of the vector */ ptr[k] = sva->r_ptr - new_cap; cap[k] = new_cap; /* new_cap free locations have been consumed */ sva->r_ptr -= new_cap; return; } /*********************************************************************** * sva_make_static - relocate specified vector to right part of SVA * * Assuming that the specified vector is stored in the left (dynamic) * part of SVA, this routine makes the vector static by relocating its * content to the right (static) part of SVA. However, if the specified * vector has zero capacity, the routine does nothing. * * The parameter k specifies the reference number of the vector to be * relocated, 1 <= k <= n. * * NOTE: On entry to the routine the middle part of SVA should have at * least len[k] free locations, where len[k] is the length of the * vector to be relocated. */ void sva_make_static(SVA *sva, int k) { int *ptr = sva->ptr; int *len = sva->len; int *cap = sva->cap; int *prev = sva->prev; int *next = sva->next; int *ind = sva->ind; double *val = sva->val; int ptr_k, len_k; xassert(1 <= k && k <= sva->n); /* if the vector has zero capacity, do nothing */ if (cap[k] == 0) { xassert(ptr[k] == 0); xassert(len[k] == 0); goto done; } /* there should be at least len[k] free locations */ len_k = len[k]; xassert(sva->r_ptr - sva->m_ptr >= len_k); /* remove the vector from the linked list */ if (prev[k] == 0) sva->head = next[k]; else { /* preceding vector exists; increase its capacity */ cap[prev[k]] += cap[k]; next[prev[k]] = next[k]; } if (next[k] == 0) sva->tail = prev[k]; else prev[next[k]] = prev[k]; /* if the vector has zero length, make it empty */ if (len_k == 0) { ptr[k] = cap[k] = 0; goto done; } /* copy the vector content to the beginning of the right part */ ptr_k = sva->r_ptr - len_k; memcpy(&ind[ptr_k], &ind[ptr[k]], len_k * sizeof(int)); memcpy(&val[ptr_k], &val[ptr[k]], len_k * sizeof(double)); /* set new pointer and capacity of the vector */ ptr[k] = ptr_k; cap[k] = len_k; /* len[k] free locations have been consumed */ sva->r_ptr -= len_k; done: return; } /*********************************************************************** * sva_check_area - check sparse vector area (SVA) * * This routine checks the SVA data structures for correctness. * * NOTE: For testing/debugging only. */ void sva_check_area(SVA *sva) { int n_max = sva->n_max; int n = sva->n; int *ptr = sva->ptr; int *len = sva->len; int *cap = sva->cap; int size = sva->size; int m_ptr = sva->m_ptr; int r_ptr = sva->r_ptr; int head = sva->head; int tail = sva->tail; int *prev = sva->prev; int *next = sva->next; int k; xassert(1 <= n && n <= n_max); xassert(1 <= m_ptr && m_ptr <= r_ptr && r_ptr <= size+1); /* all vectors included the linked list should have non-zero * capacity and be stored in the left part */ for (k = head; k != 0; k = next[k]) { xassert(1 <= k && k <= n); xassert(cap[k] > 0); xassert(0 <= len[k] && len[k] <= cap[k]); if (prev[k] == 0) xassert(k == head); else { xassert(1 <= prev[k] && prev[k] <= n); xassert(next[prev[k]] == k); } if (next[k] == 0) { xassert(k == tail); xassert(ptr[k] + cap[k] <= m_ptr); } else { xassert(1 <= next[k] && next[k] <= n); xassert(prev[next[k]] == k); xassert(ptr[k] + cap[k] <= ptr[next[k]]); } cap[k] = -cap[k]; } /* all other vectors should either have zero capacity or be * stored in the right part */ for (k = 1; k <= n; k++) { if (cap[k] < 0) { /* k-th vector is stored in the left part */ cap[k] = -cap[k]; } else if (cap[k] == 0) { /* k-th vector has zero capacity */ xassert(ptr[k] == 0); xassert(len[k] == 0); } else /* cap[k] > 0 */ { /* k-th vector is stored in the right part */ xassert(0 <= len[k] && len[k] <= cap[k]); xassert(r_ptr <= ptr[k] && ptr[k] + cap[k] <= size+1); } } return; } /*********************************************************************** * sva_delete_area - delete sparse vector area (SVA) * * This routine deletes the sparse vector area (SVA) freeing all the * memory allocated to it. */ void sva_delete_area(SVA *sva) { tfree(sva->ptr); tfree(sva->len); tfree(sva->cap); tfree(sva->prev); tfree(sva->next); tfree(sva->ind); tfree(sva->val); tfree(sva); return; } /* eof */ glpk-4.52.1/src/bflib/sva.h0000644000062000006210000001474012175147600014536 0ustar maomkpasswd/* sva.h (sparse vector area) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef SVA_H #define SVA_H /*********************************************************************** * Sparse Vector Area (SVA) is a container for sparse vectors. This * program object is used mainly on computing factorization, where the * sparse vectors are rows and columns of sparse matrices. * * The SVA storage is a set of locations numbered 1, 2, ..., size, * where size is the size of SVA, which is the total number of * locations currently allocated. Each location is identified by its * pointer p, 1 <= p <= size, and is the pair (ind[p], val[p]), where * ind[p] and val[p] are, respectively, the index and value fields used * to store the index and numeric value of a particular vector element. * * Each sparse vector is identified by its reference number k, * 1 <= k <= n, where n is the total number of vectors currently stored * in SVA, and defined by the triplet (ptr[k], len[k], cap[k]), where: * ptr[k] is a pointer to the first location of the vector; len[k] is * the vector length, which is the number of its non-zero elements, * len[k] >= 0; and cap[k] is the capacity of the vector, which is the * total number of adjacent locations allocated to that vector, * cap[k] >= len[k]. Thus, non-zero elements of k-th vector are stored * in locations ptr[k], ptr[k]+1, ..., ptr[k]+len[k]-1, and locations * ptr[k]+len[k], ptr[k]+len[k]+1, ..., ptr[k]+cap[k]-1 are reserved. * * The SVA storage is divided into three parts as follows: * * Locations 1, 2, ..., m_ptr-1 constitute the left (dynamic) part of * SVA. This part is used to store vectors, whose capacity may change. * Note that all vectors stored in the left part are also included in * a doubly linked list, where they are ordered by increasing their * pointers ptr[k] (this list is needed for efficient implementation * of the garbage collector used to defragment the left part of SVA); * * Locations m_ptr, m_ptr+1, ..., r_ptr-1 are free and constitute the * middle (free) part of SVA. * * Locations r_ptr, r_ptr+1, ..., size constitute the right (static) * part of SVA. This part is used to store vectors, whose capacity is * not changed. */ typedef struct SVA SVA; struct SVA { /* sparse vector area */ int n_max; /* maximal value of n (enlarged automatically) */ int n; /* number of currently allocated vectors, 0 <= n <= n_max */ int *ptr; /* int ptr[1+n_max]; */ /* ptr[0] is not used; * ptr[k], 1 <= i <= n, is pointer to first location of k-th * vector in the arrays ind and val */ int *len; /* int len[1+n_max]; */ /* len[0] is not used; * len[k], 1 <= k <= n, is length of k-th vector, len[k] >= 0 */ int *cap; /* int cap[1+n_max]; */ /* cap[0] is not used; * cap[k], 1 <= k <= n, is capacity of k-th vector (the number * of adjacent locations allocated to it), cap[k] >= len[k] */ /* NOTE: if cap[k] = 0, then ptr[k] = 0 and len[k] = 0 */ int size; /* total number of locations in SVA */ int m_ptr, r_ptr; /* partitioning pointers that define the left, middle, and right * parts of SVA (see above); 1 <= m_ptr <= r_ptr <= size+1 */ int head; /* number of first (leftmost) vector in the linked list */ int tail; /* number of last (rightmost) vector in the linked list */ int *prev; /* int prev[1+n_max]; */ /* prev[0] is not used; * prev[k] is number of vector which precedes k-th vector in the * linked list; * prev[k] < 0 means that k-th vector is not in the list */ int *next; /* int next[1+n_max]; */ /* next[0] is not used; * next[k] is number of vector which succedes k-th vector in the * linked list; * next[k] < 0 means that k-th vector is not in the list */ /* NOTE: only vectors having non-zero capacity and stored in the * left part of SVA are included in this linked list */ int *ind; /* int ind[1+size]; */ /* ind[0] is not used; * ind[p], 1 <= p <= size, is index field of location p */ double *val; /* double val[1+size]; */ /* val[0] is not used; * val[p], 1 <= p <= size, is value field of location p */ #if 1 int talky; /* option to enable talky mode */ #endif }; #define sva_create_area _glp_sva_create_area SVA *sva_create_area(int n_max, int size); /* create sparse vector area (SVA) */ #define sva_alloc_vecs _glp_sva_alloc_vecs int sva_alloc_vecs(SVA *sva, int nnn); /* allocate new vectors in SVA */ #define sva_resize_area _glp_sva_resize_area void sva_resize_area(SVA *sva, int delta); /* change size of SVA storage */ #define sva_defrag_area _glp_sva_defrag_area void sva_defrag_area(SVA *sva); /* defragment left part of SVA */ #define sva_more_space _glp_sva_more_space void sva_more_space(SVA *sva, int m_size); /* increase size of middle (free) part of SVA */ #define sva_enlarge_cap _glp_sva_enlarge_cap void sva_enlarge_cap(SVA *sva, int k, int new_cap, int skip); /* enlarge capacity of specified vector */ #define sva_reserve_cap _glp_sva_reserve_cap void sva_reserve_cap(SVA *sva, int k, int new_cap); /* reserve locations for specified vector */ #define sva_make_static _glp_sva_make_static void sva_make_static(SVA *sva, int k); /* relocate specified vector to right part of SVA */ #define sva_check_area _glp_sva_check_area void sva_check_area(SVA *sva); /* check sparse vector area (SVA) */ #define sva_delete_area _glp_sva_delete_area void sva_delete_area(SVA *sva); /* delete sparse vector area (SVA) */ #endif /* eof */ glpk-4.52.1/src/cglib/0000755000062000006210000000000012175147600013570 5ustar maomkpasswdglpk-4.52.1/src/cglib/cfg.c0000644000062000006210000003261212175147600014477 0ustar maomkpasswd/* cfg.c (conflict graph) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "cfg.h" #include "env.h" /*********************************************************************** * cfg_create_graph - create conflict graph * * This routine creates the conflict graph, which initially is empty, * and returns a pointer to the graph descriptor. * * The parameter n specifies the number of *all* variables in MIP, for * which the conflict graph will be built. * * The parameter nv_max specifies maximal number of vertices in the * conflict graph. It should be the double number of binary variables * in corresponding MIP. */ CFG *cfg_create_graph(int n, int nv_max) { CFG *G; xassert(n >= 0); xassert(0 <= nv_max && nv_max <= n + n); G = talloc(1, CFG); G->n = n; G->pos = talloc(1+n, int); memset(&G->pos[1], 0, n * sizeof(int)); G->neg = talloc(1+n, int); memset(&G->neg[1], 0, n * sizeof(int)); G->pool = dmp_create_pool(); G->nv_max = nv_max; G->nv = 0; G->ref = talloc(1+nv_max, int); G->vptr = talloc(1+nv_max, CFGVLE *); G->cptr = talloc(1+nv_max, CFGCLE *); return G; } /*********************************************************************** * cfg_add_clique - add clique to conflict graph * * This routine adds a clique to the conflict graph. * * The parameter size specifies the clique size, size >= 2. Note that * any edge can be considered as a clique of size 2. * * The array ind specifies vertices constituting the clique in elements * ind[k], 1 <= k <= size: * * ind[k] = +j means a vertex of the conflict graph that corresponds to * original binary variable x[j], 1 <= j <= n. * * ind[k] = -j means a vertex of the conflict graph that corresponds to * complement of original binary variable x[j], 1 <= j <= n. * * Note that if both vertices for x[j] and (1 - x[j]) have appeared in * the conflict graph, the routine automatically adds an edge incident * to these vertices. */ static void add_edge(CFG *G, int v, int w) { /* add clique of size 2 */ DMP *pool = G->pool; int nv = G->nv; CFGVLE **vptr = G->vptr; CFGVLE *vle; xassert(1 <= v && v <= nv); xassert(1 <= w && w <= nv); xassert(v != w); vle = dmp_talloc(pool, CFGVLE); vle->v = w; vle->next = vptr[v]; vptr[v] = vle; vle = dmp_talloc(pool, CFGVLE); vle->v = v; vle->next = vptr[w]; vptr[w] = vle; return; } void cfg_add_clique(CFG *G, int size, const int ind[]) { int n = G->n; int *pos = G->pos; int *neg = G->neg; DMP *pool = G->pool; int nv_max = G->nv_max; int *ref = G->ref; CFGVLE **vptr = G->vptr; CFGCLE **cptr = G->cptr; int j, k, v; xassert(2 <= size && size <= nv_max); /* add new vertices to the conflict graph */ for (k = 1; k <= size; k++) { j = ind[k]; if (j > 0) { /* vertex corresponds to x[j] */ xassert(1 <= j && j <= n); if (pos[j] == 0) { /* no such vertex exists; add it */ v = pos[j] = ++(G->nv); xassert(v <= nv_max); ref[v] = j; vptr[v] = NULL; cptr[v] = NULL; if (neg[j] != 0) { /* now both vertices for x[j] and (1 - x[j]) exist */ add_edge(G, v, neg[j]); } } } else { /* vertex corresponds to (1 - x[j]) */ j = -j; xassert(1 <= j && j <= n); if (neg[j] == 0) { /* no such vertex exists; add it */ v = neg[j] = ++(G->nv); xassert(v <= nv_max); ref[v] = j; vptr[v] = NULL; cptr[v] = NULL; if (pos[j] != 0) { /* now both vertices for x[j] and (1 - x[j]) exist */ add_edge(G, v, pos[j]); } } } } /* add specified clique to the conflict graph */ if (size == 2) add_edge(G, ind[1] > 0 ? pos[+ind[1]] : neg[-ind[1]], ind[2] > 0 ? pos[+ind[2]] : neg[-ind[2]]); else { CFGVLE *vp, *vle; CFGCLE *cle; /* build list of clique vertices */ vp = NULL; for (k = 1; k <= size; k++) { vle = dmp_talloc(pool, CFGVLE); vle->v = ind[k] > 0 ? pos[+ind[k]] : neg[-ind[k]]; vle->next = vp; vp = vle; } /* attach the clique to all its vertices */ for (k = 1; k <= size; k++) { cle = dmp_talloc(pool, CFGCLE); cle->vptr = vp; v = ind[k] > 0 ? pos[+ind[k]] : neg[-ind[k]]; cle->next = cptr[v]; cptr[v] = cle; } } return; } /*********************************************************************** * cfg_get_adjacent - get vertices adjacent to specified vertex * * This routine stores numbers of all vertices adjacent to specified * vertex v of the conflict graph in locations ind[1], ..., ind[len], * and returns len, 1 <= len <= nv-1, where nv is the total number of * vertices in the conflict graph. * * Note that the conflict graph defined by this routine has neither * self-loops nor multiple edges. */ int cfg_get_adjacent(CFG *G, int v, int ind[]) { int nv = G->nv; int *ref = G->ref; CFGVLE **vptr = G->vptr; CFGCLE **cptr = G->cptr; CFGVLE *vle; CFGCLE *cle; int k, w, len; xassert(1 <= v && v <= nv); len = 0; /* walk thru the list of adjacent vertices */ for (vle = vptr[v]; vle != NULL; vle = vle->next) { w = vle->v; xassert(1 <= w && w <= nv); xassert(w != v); if (ref[w] > 0) { ind[++len] = w; ref[w] = -ref[w]; } } /* walk thru the list of incident cliques */ for (cle = cptr[v]; cle != NULL; cle = cle->next) { /* walk thru the list of clique vertices */ for (vle = cle->vptr; vle != NULL; vle = vle->next) { w = vle->v; xassert(1 <= w && w <= nv); if (w != v && ref[w] > 0) { ind[++len] = w; ref[w] = -ref[w]; } } } xassert(1 <= len && len < nv); /* unmark vertices included in the resultant adjacency list */ for (k = 1; k <= len; k++) { w = ind[k]; ref[w] = -ref[w]; } return len; } /*********************************************************************** * cfg_expand_clique - expand specified clique to maximal clique * * Given some clique in the conflict graph this routine expands it to * a maximal clique by including in it new vertices. * * On entry vertex indices constituting the initial clique should be * stored in locations c_ind[1], ..., c_ind[c_len], where c_len is the * initial clique size. On exit the routine stores new vertex indices * to locations c_ind[c_len+1], ..., c_ind[c_len'], where c_len' is the * size of the maximal clique found, and returns c_len'. * * ALGORITHM * * Let G = (V, E) be a graph, C within V be a current clique to be * expanded, and D within V \ C be a subset of vertices adjacent to all * vertices from C. On every iteration the routine chooses some vertex * v in D, includes it into C, and removes from D the vertex v as well * as all vertices not adjacent to v. Initially C is empty and D = V. * Iterations repeat until D becomes an empty set. Obviously, the final * set C is a maximal clique in G. * * Now let C0 be an initial clique, and we want C0 to be a subset of * the final maximal clique C. To provide this condition the routine * starts constructing C by choosing only such vertices v in D, which * are in C0, until all vertices from C0 have been included in C. May * note that if on some iteration C0 \ C is non-empty (i.e. if not all * vertices from C0 have been included in C), C0 \ C is a subset of D, * because C0 is a clique. */ static int intersection(int d_len, int d_ind[], int d_pos[], int len, const int ind[]) { /* compute intersection D := D inter W, where W is some specified * set of vertices */ int k, t, v, new_len; /* walk thru vertices in W and mark vertices in D */ for (t = 1; t <= len; t++) { /* v in W */ v = ind[t]; /* determine position of v in D */ k = d_pos[v]; if (k != 0) { /* v in D */ xassert(d_ind[k] == v); /* mark v to keep it in D */ d_ind[k] = -v; } } /* remove all unmarked vertices from D */ new_len = 0; for (k = 1; k <= d_len; k++) { /* v in D */ v = d_ind[k]; if (v < 0) { /* v is marked; keep it */ v = -v; new_len++; d_ind[new_len] = v; d_pos[v] = new_len; } else { /* v is not marked; remove it */ d_pos[v] = 0; } } return new_len; } int cfg_expand_clique(CFG *G, int c_len, int c_ind[]) { int nv = G->nv; int d_len, *d_ind, *d_pos, len, *ind; int k, v; xassert(0 <= c_len && c_len <= nv); /* allocate working arrays */ d_ind = talloc(1+nv, int); d_pos = talloc(1+nv, int); ind = talloc(1+nv, int); /* initialize C := 0, D := V */ d_len = nv; for (k = 1; k <= nv; k++) d_ind[k] = d_pos[k] = k; /* expand C by vertices of specified initial clique C0 */ for (k = 1; k <= c_len; k++) { /* v in C0 */ v = c_ind[k]; xassert(1 <= v && v <= nv); /* since C0 is clique, v should be in D */ xassert(d_pos[v] != 0); /* W := set of vertices adjacent to v */ len = cfg_get_adjacent(G, v, ind); /* D := D inter W */ d_len = intersection(d_len, d_ind, d_pos, len, ind); /* since v not in W, now v should be not in D */ xassert(d_pos[v] == 0); } /* expand C by some other vertices until D is empty */ while (d_len > 0) { /* v in D */ v = d_ind[1]; xassert(1 <= v && v <= nv); /* note that v is adjacent to all vertices in C (by design), * so add v to C */ c_ind[++c_len] = v; /* W := set of vertices adjacent to v */ len = cfg_get_adjacent(G, v, ind); /* D := D inter W */ d_len = intersection(d_len, d_ind, d_pos, len, ind); /* since v not in W, now v should be not in D */ xassert(d_pos[v] == 0); } /* free working arrays */ tfree(d_ind); tfree(d_pos); tfree(ind); /* bring maximal clique to calling routine */ return c_len; } /*********************************************************************** * cfg_check_clique - check clique in conflict graph * * This routine checks that vertices of the conflict graph specified * in locations c_ind[1], ..., c_ind[c_len] constitute a clique. * * NOTE: for testing/debugging only. */ void cfg_check_clique(CFG *G, int c_len, const int c_ind[]) { int nv = G->nv; int k, kk, v, w, len, *ind; char *flag; ind = talloc(1+nv, int); flag = talloc(1+nv, char); memset(&flag[1], 0, nv); /* walk thru clique vertices */ xassert(c_len >= 0); for (k = 1; k <= c_len; k++) { /* get clique vertex v */ v = c_ind[k]; xassert(1 <= v && v <= nv); /* get vertices adjacent to vertex v */ len = cfg_get_adjacent(G, v, ind); for (kk = 1; kk <= len; kk++) { w = ind[kk]; xassert(1 <= w && w <= nv); xassert(w != v); flag[w] = 1; } /* check that all clique vertices other than v are adjacent to v */ for (kk = 1; kk <= c_len; kk++) { w = c_ind[kk]; xassert(1 <= w && w <= nv); if (w != v) xassert(flag[w]); } /* reset vertex flags */ for (kk = 1; kk <= len; kk++) flag[ind[kk]] = 0; } tfree(ind); tfree(flag); return; } /*********************************************************************** * cfg_delete_graph - delete conflict graph * * This routine deletes the conflict graph by freeing all the memory * allocated to this program object. */ void cfg_delete_graph(CFG *G) { tfree(G->pos); tfree(G->neg); dmp_delete_pool(G->pool); tfree(G->ref); tfree(G->vptr); tfree(G->cptr); tfree(G); return; } /* eof */ glpk-4.52.1/src/cglib/cfg.h0000644000062000006210000001127612175147600014507 0ustar maomkpasswd/* cfg.h (conflict graph) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef CFG_H #define CFG_H #include "dmp.h" /*********************************************************************** * The structure CFG describes the conflict graph. * * Conflict graph is an undirected graph G = (V, E), where V is a set * of vertices, E <= V x V is a set of edges. Each vertex v in V of the * conflict graph corresponds to a binary variable z[v], which is * either an original binary variable x[j] or its complement 1 - x[j]. * Edge (v,w) in E means that z[v] and z[w] cannot take the value 1 at * the same time, i.e. it defines an inequality z[v] + z[w] <= 1, which * is assumed to be valid for original MIP. * * Since the conflict graph may be dense, it is stored as an union of * its cliques rather than explicitly. */ typedef struct CFG CFG; typedef struct CFGVLE CFGVLE; typedef struct CFGCLE CFGCLE; struct CFG { /* conflict graph descriptor */ int n; /* number of *all* variables (columns) in corresponding MIP */ int *pos; /* int pos[1+n]; */ /* pos[0] is not used; * pos[j] = v, 1 <= j <= n, means that vertex v corresponds to * original binary variable x[j], and pos[j] = 0 means that the * conflict graph has no such vertex */ int *neg; /* int neg[1+n]; */ /* neg[0] is not used; * neg[j] = v, 1 <= j <= n, means that vertex v corresponds to * complement of original binary variable x[j], and neg[j] = 0 * means that the conflict graph has no such vertex */ DMP *pool; /* memory pool to allocate elements of the conflict graph */ int nv_max; /* maximal number of vertices in the conflict graph */ int nv; /* current number of vertices in the conflict graph */ int *ref; /* int ref[1+nv_max]; */ /* ref[v] = j, 1 <= v <= nv, means that vertex v corresponds * either to original binary variable x[j] or to its complement, * i.e. either pos[j] = v or neg[j] = v */ CFGVLE **vptr; /* CFGVLE *vptr[1+nv_max]; */ /* vptr[v], 1 <= v <= nv, is an initial pointer to the list of * vertices adjacent to vertex v */ CFGCLE **cptr; /* CFGCLE *cptr[1+nv_max]; */ /* cptr[v], 1 <= v <= nv, is an initial pointer to the list of * cliques that contain vertex v */ }; struct CFGVLE { /* vertex list element */ int v; /* vertex number, 1 <= v <= nv */ CFGVLE *next; /* pointer to next vertex list element */ }; struct CFGCLE { /* clique list element */ CFGVLE *vptr; /* initial pointer to the list of clique vertices */ CFGCLE *next; /* pointer to next clique list element */ }; #define cfg_create_graph _glp_cfg_create_graph CFG *cfg_create_graph(int n, int nv_max); /* create conflict graph */ #define cfg_add_clique _glp_cfg_add_clique void cfg_add_clique(CFG *G, int size, const int ind[]); /* add clique to conflict graph */ #define cfg_get_adjacent _glp_cfg_get_adjacent int cfg_get_adjacent(CFG *G, int v, int ind[]); /* get vertices adjacent to specified vertex */ #define cfg_expand_clique _glp_cfg_expand_clique int cfg_expand_clique(CFG *G, int c_len, int c_ind[]); /* expand specified clique to maximal clique */ #define cfg_check_clique _glp_cfg_check_clique void cfg_check_clique(CFG *G, int c_len, const int c_ind[]); /* check clique in conflict graph */ #define cfg_delete_graph _glp_cfg_delete_graph void cfg_delete_graph(CFG *G); /* delete conflict graph */ #define cfg_build_graph _glp_cfg_build_graph CFG *cfg_build_graph(void /* glp_prob */ *P); /* build conflict graph */ #define cfg_find_clique _glp_cfg_find_clique int cfg_find_clique(void /* glp_prob */ *P, CFG *G, int ind[], double *sum); /* find maximum weight clique in conflict graph */ #endif /* eof */ glpk-4.52.1/src/cglib/cfg1.c0000644000062000006210000006034512175147600014564 0ustar maomkpasswd/* cfg1.c (conflict graph) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "cfg.h" #include "glpapi.h" #include "wclique.h" #include "wclique1.h" /*********************************************************************** * cfg_build_graph - build conflict graph * * This routine builds the conflict graph. It analyzes the specified * problem object to discover original and implied packing inequalities * and adds corresponding cliques to the conflict graph. * * Packing inequality has the form: * * sum z[j] <= 1, (1) * j in J * * where z[j] = x[j] or z[j] = 1 - x[j], x[j] is an original binary * variable. Every packing inequality (1) is equivalent to a set of * edge inequalities: * * z[i] + z[j] <= 1 for all i, j in J, i != j, (2) * * and since every edge inequality (2) defines an edge in the conflict * graph, corresponding packing inequality (1) defines a clique. * * To discover packing inequalities the routine analyzes constraints * of the specified MIP. To simplify the analysis each constraint is * analyzed separately. The analysis is performed as follows. * * Let some original constraint be the following: * * L <= sum a[j] x[j] <= U. (3) * * To analyze it the routine analyzes two constraints of "not greater * than" type: * * sum (-a[j]) x[j] <= -L, (4) * * sum (+a[j]) x[j] <= +U, (5) * * which are relaxations of the original constraint (3). (If, however, * L = -oo, or U = +oo, corresponding constraint being redundant is not * analyzed.) * * Let a constraint of "not greater than" type be the following: * * sum a[j] x[j] + sum a[j] x[j] <= b, (6) * j in J j in J' * * where J is a subset of binary variables, J' is a subset of other * (continues and non-binary integer) variables. The constraint (6) is * is relaxed as follows, to eliminate non-binary variables: * * sum a[j] x[j] <= b - sum a[j] x[j] <= b', (7) * j in J j in J' * * b' = sup(b - sum a[j] x[j]) = * j in J' * * = b - inf(sum a[j] x[j]) = * * = b - sum inf(a[j] x[j]) = (8) * * = b - sum a[j] inf(x[j]) - sum a[j] sup(x[j]) = * a[j]>0 a[j]<0 * * = b - sum a[j] l[j] - sum a[j] u[j], * a[j]>0 a[j]<0 * * where l[j] and u[j] are, resp., lower and upper bounds of x[j]. * * Then the routine transforms the relaxed constraint containing only * binary variables: * * sum a[j] x[j] <= b (9) * * to an equivalent 0-1 knapsack constraint as follows: * * sum a[j] x[j] + sum a[j] x[j] <= b ==> * a[j]>0 a[j]<0 * * sum a[j] x[j] + sum a[j] (1 - x[j]) <= b ==> * a[j]>0 a[j]<0 (10) * * sum (+a[j]) x[j] + sum (-a[j]) x[j] <= b + sum (-a[j]) ==> * a[j]>0 a[j]<0 a[j]<0 * * sum a'[j] z[j] <= b', * * where a'[j] = |a[j]| > 0, and * * ( x[j] if a[j] > 0 * z[j] = < * ( 1 - x[j] if a[j] < 0 * * is a binary variable, which is either original binary variable x[j] * or its complement. * * Finally, the routine analyzes the resultant 0-1 knapsack inequality: * * sum a[j] z[j] <= b, (11) * j in J * * where all a[j] are positive, to discover clique inequalities (1), * which are valid for (11) and therefore valid for (3). (It is assumed * that the original MIP has been preprocessed, so it is not checked, * for example, that b > 0 or that a[j] <= b.) * * In principle, to discover any edge inequalities valid for (11) it * is sufficient to check whether a[i] + a[j] > b for all i, j in J, * i < j. However, this way requires O(|J|^2) checks, so the routine * analyses (11) in the following way, which is much more efficient in * many practical cases. * * 1. Let a[p] and a[q] be two minimal coefficients: * * a[p] = min a[j], (12) * * a[q] = min a[j], j != p, (13) * * such that * * a[p] + a[q] > b. (14) * * This means that a[i] + a[j] > b for any i, j in J, i != j, so * * z[i] + z[j] <= 1 (15) * * are valid for (11) for any i, j in J, i != j. This case means that * J define a clique in the conflict graph. * * 2. Otherwise, let a[p] and [q] be two maximal coefficients: * * a[p] = max a[j], (16) * * a[q] = max a[j], j != p, (17) * * such that * * a[p] + a[q] <= b. (18) * * This means that a[i] + a[j] <= b for any i, j in J, i != j, so in * this case no valid edge inequalities for (11) exist. * * 3. Otherwise, let all a[j] be ordered by descending their values: * * a[1] >= a[2] >= ... >= a[p-1] >= a[p] >= a[p+1] >= ... (19) * * where p is such that * * a[p-1] + a[p] > b, (20) * * a[p] + a[p+1] <= b. (21) * * (May note that due to the former two cases in this case we always * have 2 <= p <= |J|-1.) * * Since a[p] and a[p-1] are two minimal coefficients in the set * J' = {1, ..., p}, J' define a clique in the conflict graph for the * same reason as in the first case. Similarly, since a[p] and a[p+1] * are two maximal coefficients in the set J" = {p, ..., |J|}, no edge * inequalities exist for all i, j in J" for the same reason as in the * second case. Thus, to discover other edge inequalities (15) valid * for (11), the routine checks if a[i] + a[j] > b for all i in J', * j in J", i != j. */ #define is_binary(j) \ (P->col[j]->kind == GLP_IV && P->col[j]->type == GLP_DB && \ P->col[j]->lb == 0.0 && P->col[j]->ub == 1.0) /* check if x[j] is binary variable */ struct term { int ind; double val; }; /* term a[j] * z[j] used to sort a[j]'s */ static int fcmp(const void *e1, const void *e2) { /* auxiliary routine called from qsort */ const struct term *t1 = e1, *t2 = e2; if (t1->val > t2->val) return -1; else if (t1->val < t2->val) return +1; else return 0; } static void analyze_ineq(glp_prob *P, CFG *G, int len, int ind[], double val[], double rhs, struct term t[]) { /* analyze inequality constraint (6) */ /* P is the original MIP * G is the conflict graph to be built * len is the number of terms in the constraint * ind[1], ..., ind[len] are indices of variables x[j] * val[1], ..., val[len] are constraint coefficients a[j] * rhs is the right-hand side b * t[1+len] is a working array */ int j, k, kk, p, q, type, new_len; /* eliminate non-binary variables; see (7) and (8) */ new_len = 0; for (k = 1; k <= len; k++) { /* get index of variable x[j] */ j = ind[k]; if (is_binary(j)) { /* x[j] remains in relaxed constraint */ new_len++; ind[new_len] = j; val[new_len] = val[k]; } else if (val[k] > 0.0) { /* eliminate non-binary x[j] in case a[j] > 0 */ /* b := b - a[j] * l[j]; see (8) */ type = P->col[j]->type; if (type == GLP_FR || type == GLP_UP) { /* x[j] has no lower bound */ goto done; } rhs -= val[k] * P->col[j]->lb; } else /* val[j] < 0.0 */ { /* eliminate non-binary x[j] in case a[j] < 0 */ /* b := b - a[j] * u[j]; see (8) */ type = P->col[j]->type; if (type == GLP_FR || type == GLP_LO) { /* x[j] has no upper bound */ goto done; } rhs -= val[k] * P->col[j]->ub; } } len = new_len; /* now we have the constraint (9) */ if (len <= 1) { /* at least two terms are needed */ goto done; } /* make all constraint coefficients positive; see (10) */ for (k = 1; k <= len; k++) { if (val[k] < 0.0) { /* a[j] < 0; substitute x[j] = 1 - x'[j], where x'[j] is * a complement binary variable */ ind[k] = -ind[k]; val[k] = -val[k]; rhs += val[k]; } } /* now we have 0-1 knapsack inequality (11) */ /* increase the right-hand side a bit to avoid false checks due * to rounding errors */ rhs += 0.001 * (1.0 + fabs(rhs)); /*** first case ***/ /* find two minimal coefficients a[p] and a[q] */ p = 0; for (k = 1; k <= len; k++) { if (p == 0 || val[p] > val[k]) p = k; } q = 0; for (k = 1; k <= len; k++) { if (k != p && (q == 0 || val[q] > val[k])) q = k; } xassert(p != 0 && q != 0 && p != q); /* check condition (14) */ if (val[p] + val[q] > rhs) { /* all z[j] define a clique in the conflict graph */ cfg_add_clique(G, len, ind); goto done; } /*** second case ***/ /* find two maximal coefficients a[p] and a[q] */ p = 0; for (k = 1; k <= len; k++) { if (p == 0 || val[p] < val[k]) p = k; } q = 0; for (k = 1; k <= len; k++) { if (k != p && (q == 0 || val[q] < val[k])) q = k; } xassert(p != 0 && q != 0 && p != q); /* check condition (18) */ if (val[p] + val[q] <= rhs) { /* no valid edge inequalities exist */ goto done; } /*** third case ***/ xassert(len >= 3); /* sort terms in descending order of coefficient values */ for (k = 1; k <= len; k++) { t[k].ind = ind[k]; t[k].val = val[k]; } qsort(&t[1], len, sizeof(struct term), fcmp); for (k = 1; k <= len; k++) { ind[k] = t[k].ind; val[k] = t[k].val; } /* now a[1] >= a[2] >= ... >= a[len-1] >= a[len] */ /* note that a[1] + a[2] > b and a[len-1] + a[len] <= b due two * the former two cases */ xassert(val[1] + val[2] > rhs); xassert(val[len-1] + val[len] <= rhs); /* find p according to conditions (20) and (21) */ for (p = 2; p < len; p++) { if (val[p] + val[p+1] <= rhs) break; } xassert(p < len); /* z[1], ..., z[p] define a clique in the conflict graph */ cfg_add_clique(G, p, ind); /* discover other edge inequalities */ for (k = 1; k <= p; k++) { for (kk = p; kk <= len; kk++) { if (k != kk && val[k] + val[kk] > rhs) { int iii[1+2]; iii[1] = ind[k]; iii[2] = ind[kk]; cfg_add_clique(G, 2, iii); } } } done: return; } CFG *cfg_build_graph(void *P_) { glp_prob *P = P_; int m = P->m; int n = P->n; CFG *G; int i, k, type, len, *ind; double *val; struct term *t; /* create the conflict graph (number of its vertices cannot be * greater than double number of binary variables) */ G = cfg_create_graph(n, 2 * glp_get_num_bin(P)); /* allocate working arrays */ ind = talloc(1+n, int); val = talloc(1+n, double); t = talloc(1+n, struct term); /* analyze constraints to discover edge inequalities */ for (i = 1; i <= m; i++) { type = P->row[i]->type; if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { /* i-th row has lower bound */ /* analyze inequality sum (-a[j]) * x[j] <= -lb */ len = glp_get_mat_row(P, i, ind, val); for (k = 1; k <= len; k++) val[k] = -val[k]; analyze_ineq(P, G, len, ind, val, -P->row[i]->lb, t); } if (type == GLP_UP || type == GLP_DB || type == GLP_FX) { /* i-th row has upper bound */ /* analyze inequality sum (+a[j]) * x[j] <= +ub */ len = glp_get_mat_row(P, i, ind, val); analyze_ineq(P, G, len, ind, val, +P->row[i]->ub, t); } } /* free working arrays */ tfree(ind); tfree(val); tfree(t); return G; } /*********************************************************************** * cfg_find_clique - find maximum weight clique in conflict graph * * This routine finds a maximum weight clique in the conflict graph * G = (V, E), where the weight of vertex v in V is the value of * corresponding binary variable z (which is either an original binary * variable or its complement) in the optimal solution to LP relaxation * provided in the problem object. The goal is to find a clique in G, * whose weight is greater than 1, in which case corresponding packing * inequality is violated at the optimal point. * * On exit the routine stores vertex indices of the conflict graph * included in the clique found to locations ind[1], ..., ind[len], and * returns len, which is the clique size. The clique weight is stored * in location pointed to by the parameter sum. If no clique has been * found, the routine returns 0. * * Since the conflict graph may have a big number of vertices and be * quite dense, the routine uses an induced subgraph G' = (V', E'), * which is constructed as follows: * * 1. If the weight of some vertex v in V is zero (close to zero), it * is not included in V'. Obviously, including in a clique * zero-weight vertices does not change its weight, so if in G there * exist a clique of a non-zero weight, in G' exists a clique of the * same weight. This point is extremely important, because dropping * out zero-weight vertices can be done without retrieving lists of * adjacent vertices whose size may be very large. * * 2. Cumulative weight of vertex v in V is the sum of the weight of v * and weights of all vertices in V adjacent to v. Obviously, if * a clique includes a vertex v, the clique weight cannot be greater * than the cumulative weight of v. Since we are interested only in * cliques whose weight is greater than 1, vertices of V, whose * cumulative weight is not greater than 1, are not included in V'. * * May note that in many practical cases the size of the induced * subgraph G' is much less than the size of the original conflict * graph G due to many binary variables, whose optimal values are zero * or close to zero. For example, it may happen that |V| = 100,000 and * |E| = 1e9 while |V'| = 50 and |E'| = 1000. */ struct csa { /* common storage area */ glp_prob *P; /* original MIP */ CFG *G; /* original conflict graph G = (V, E), |V| = nv */ int *ind; /* int ind[1+nv]; */ /* working array */ /*--------------------------------------------------------------*/ /* induced subgraph G' = (V', E') of original conflict graph */ int nn; /* number of vertices in V' */ int *vtoi; /* int vtoi[1+nv]; */ /* vtoi[v] = i, 1 <= v <= nv, means that vertex v in V is vertex * i in V'; vtoi[v] = 0 means that vertex v is not included in * the subgraph */ int *itov; /* int itov[1+nv]; */ /* itov[i] = v, 1 <= i <= nn, means that vertex i in V' is vertex * v in V */ double *wgt; /* double wgt[1+nv]; */ /* wgt[i], 1 <= i <= nn, is a weight of vertex i in V', which is * the value of corresponding binary variable in optimal solution * to LP relaxation */ }; static void build_subgraph(struct csa *csa) { /* build induced subgraph */ glp_prob *P = csa->P; int n = P->n; CFG *G = csa->G; int *ind = csa->ind; int *pos = G->pos; int *neg = G->neg; int nv = G->nv; int *ref = G->ref; int *vtoi = csa->vtoi; int *itov = csa->itov; double *wgt = csa->wgt; int j, k, v, w, nn, len; double z, sum; /* initially induced subgraph is empty */ nn = 0; /* walk thru vertices of original conflict graph */ for (v = 1; v <= nv; v++) { /* determine value of binary variable z[j] that corresponds to * vertex v */ j = ref[v]; xassert(1 <= j && j <= n); if (pos[j] == v) { /* z[j] = x[j], where x[j] is original variable */ z = P->col[j]->prim; } else if (neg[j] == v) { /* z[j] = 1 - x[j], where x[j] is original variable */ z = 1.0 - P->col[j]->prim; } else xassert(v != v); /* if z[j] is close to zero, do not include v in the induced * subgraph */ if (z < 0.001) { vtoi[v] = 0; continue; } /* calculate cumulative weight of vertex v */ sum = z; /* walk thru all vertices adjacent to v */ len = cfg_get_adjacent(G, v, ind); for (k = 1; k <= len; k++) { /* there is an edge (v,w) in the conflict graph */ w = ind[k]; xassert(w != v); /* add value of z[j] that corresponds to vertex w */ j = ref[w]; xassert(1 <= j && j <= n); if (pos[j] == w) sum += P->col[j]->prim; else if (neg[j] == w) sum += 1.0 - P->col[j]->prim; else xassert(w != w); } /* cumulative weight of vertex v is an upper bound of weight * of any clique containing v; so if it not greater than 1, do * not include v in the induced subgraph */ if (sum < 1.010) { vtoi[v] = 0; continue; } /* include vertex v in the induced subgraph */ nn++; vtoi[v] = nn; itov[nn] = v; wgt[nn] = z; } /* induced subgraph has been built */ csa->nn = nn; return; } static int sub_adjacent(struct csa *csa, int i, int adj[]) { /* retrieve vertices of induced subgraph adjacent to specified * vertex */ CFG *G = csa->G; int nv = G->nv; int *ind = csa->ind; int nn = csa->nn; int *vtoi = csa->vtoi; int *itov = csa->itov; int j, k, v, w, len, len1; /* determine original vertex v corresponding to vertex i */ xassert(1 <= i && i <= nn); v = itov[i]; /* retrieve vertices adjacent to vertex v in original graph */ len1 = cfg_get_adjacent(G, v, ind); /* keep only adjacent vertices which are in induced subgraph and * change their numbers appropriately */ len = 0; for (k = 1; k <= len1; k++) { /* there exists edge (v, w) in original graph */ w = ind[k]; xassert(1 <= w && w <= nv && w != v); j = vtoi[w]; if (j != 0) { /* vertex w is vertex j in induced subgraph */ xassert(1 <= j && j <= nn && j != i); adj[++len] = j; } } return len; } static int find_clique(struct csa *csa, int c_ind[]) { /* find maximum weight clique in induced subgraph with exact * Ostergard's algorithm */ int nn = csa->nn; double *wgt = csa->wgt; int i, j, k, p, q, t, ne, nb, len, *iwt, *ind; unsigned char *a; xassert(nn >= 2); /* allocate working array */ ind = talloc(1+nn, int); /* calculate the number of elements in lower triangle (without * diagonal) of adjacency matrix of induced subgraph */ ne = (nn * (nn - 1)) / 2; /* calculate the number of bytes needed to store lower triangle * of adjacency matrix */ nb = (ne + (CHAR_BIT - 1)) / CHAR_BIT; /* allocate lower triangle of adjacency matrix */ a = talloc(nb, unsigned char); /* fill lower triangle of adjacency matrix */ memset(a, 0, nb); for (p = 1; p <= nn; p++) { /* retrieve vertices adjacent to vertex p */ len = sub_adjacent(csa, p, ind); for (k = 1; k <= len; k++) { /* there exists edge (p, q) in induced subgraph */ q = ind[k]; xassert(1 <= q && q <= nn && q != p); /* determine row and column indices of this edge in lower * triangle of adjacency matrix */ if (p > q) i = p, j = q; else /* p < q */ i = q, j = p; /* set bit a[i,j] to 1, i > j */ t = ((i - 1) * (i - 2)) / 2 + (j - 1); a[t / CHAR_BIT] |= (unsigned char)(1 << ((CHAR_BIT - 1) - t % CHAR_BIT)); } } /* scale vertex weights by 1000 and convert them to integers as * required by Ostergard's algorithm */ iwt = ind; for (i = 1; i <= nn; i++) { /* it is assumed that 0 <= wgt[i] <= 1 */ t = (int)(1000.0 * wgt[i] + 0.5); if (t < 0) t = 0; else if (t > 1000) t = 1000; iwt[i] = t; } /* find maximum weight clique */ len = wclique(nn, iwt, a, c_ind); /* free working arrays */ tfree(ind); tfree(a); /* return clique size to calling routine */ return len; } static int func(void *info, int i, int ind[]) { /* auxiliary routine used by routine find_clique1 */ struct csa *csa = info; xassert(1 <= i && i <= csa->nn); return sub_adjacent(csa, i, ind); } static int find_clique1(struct csa *csa, int c_ind[]) { /* find maximum weight clique in induced subgraph with greedy * heuristic */ int nn = csa->nn; double *wgt = csa->wgt; int len; xassert(nn >= 2); len = wclique1(nn, wgt, func, csa, c_ind); /* return clique size to calling routine */ return len; } int cfg_find_clique(void *P, CFG *G, int ind[], double *sum_) { int nv = G->nv; struct csa csa; int i, k, len; double sum; /* initialize common storage area */ csa.P = P; csa.G = G; csa.ind = talloc(1+nv, int); csa.nn = -1; csa.vtoi = talloc(1+nv, int); csa.itov = talloc(1+nv, int); csa.wgt = talloc(1+nv, double); /* build induced subgraph */ build_subgraph(&csa); #ifdef GLP_DEBUG xprintf("nn = %d\n", csa.nn); #endif /* if subgraph has less than two vertices, do nothing */ if (csa.nn < 2) { len = 0; sum = 0.0; goto skip; } /* find maximum weight clique in induced subgraph */ #if 1 /* FIXME */ if (csa.nn <= 50) #endif { /* induced subgraph is small; use exact algorithm */ len = find_clique(&csa, ind); } else { /* induced subgraph is large; use greedy heuristic */ len = find_clique1(&csa, ind); } /* do not report clique, if it has less than two vertices */ if (len < 2) { len = 0; sum = 0.0; goto skip; } /* convert indices of clique vertices from induced subgraph to * original conflict graph and compute clique weight */ sum = 0.0; for (k = 1; k <= len; k++) { i = ind[k]; xassert(1 <= i && i <= csa.nn); sum += csa.wgt[i]; ind[k] = csa.itov[i]; } skip: /* free working arrays */ tfree(csa.ind); tfree(csa.vtoi); tfree(csa.itov); tfree(csa.wgt); /* return to calling routine */ *sum_ = sum; return len; } /* eof */ glpk-4.52.1/src/colamd/0000755000062000006210000000000012175147600013747 5ustar maomkpasswdglpk-4.52.1/src/colamd/colamd.c0000644000062000006210000036777412175147600015402 0ustar maomkpasswd/* ========================================================================== */ /* === colamd/symamd - a sparse matrix column ordering algorithm ============ */ /* ========================================================================== */ /* COLAMD / SYMAMD colamd: an approximate minimum degree column ordering algorithm, for LU factorization of symmetric or unsymmetric matrices, QR factorization, least squares, interior point methods for linear programming problems, and other related problems. symamd: an approximate minimum degree ordering algorithm for Cholesky factorization of symmetric matrices. Purpose: Colamd computes a permutation Q such that the Cholesky factorization of (AQ)'(AQ) has less fill-in and requires fewer floating point operations than A'A. This also provides a good ordering for sparse partial pivoting methods, P(AQ) = LU, where Q is computed prior to numerical factorization, and P is computed during numerical factorization via conventional partial pivoting with row interchanges. Colamd is the column ordering method used in SuperLU, part of the ScaLAPACK library. It is also available as built-in function in MATLAB Version 6, available from MathWorks, Inc. (http://www.mathworks.com). This routine can be used in place of colmmd in MATLAB. Symamd computes a permutation P of a symmetric matrix A such that the Cholesky factorization of PAP' has less fill-in and requires fewer floating point operations than A. Symamd constructs a matrix M such that M'M has the same nonzero pattern of A, and then orders the columns of M using colmmd. The column ordering of M is then returned as the row and column ordering P of A. Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. Acknowledgements: This work was supported by the National Science Foundation, under grants DMS-9504974 and DMS-9803599. Copyright and License: Copyright (c) 1998-2007, Timothy A. Davis, All Rights Reserved. COLAMD is also available under alternate licenses, contact T. Davis for details. This library is 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. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 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: The colamd/symamd library is available at http://www.cise.ufl.edu/research/sparse/colamd/ This is the http://www.cise.ufl.edu/research/sparse/colamd/colamd.c file. It requires the colamd.h file. It is required by the colamdmex.c and symamdmex.c files, for the MATLAB interface to colamd and symamd. Appears as ACM Algorithm 836. See the ChangeLog file for changes since Version 1.0. References: T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 353-376, 2004. T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, an approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, 2004. */ /* ========================================================================== */ /* === Description of user-callable routines ================================ */ /* ========================================================================== */ /* COLAMD includes both int and UF_long versions of all its routines. The * description below is for the int version. For UF_long, all int arguments * become UF_long. UF_long is normally defined as long, except for WIN64. ---------------------------------------------------------------------------- colamd_recommended: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" size_t colamd_recommended (int nnz, int n_row, int n_col) ; size_t colamd_l_recommended (UF_long nnz, UF_long n_row, UF_long n_col) ; Purpose: Returns recommended value of Alen for use by colamd. Returns 0 if any input argument is negative. The use of this routine is optional. Not needed for symamd, which dynamically allocates its own memory. Note that in v2.4 and earlier, these routines returned int or long. They now return a value of type size_t. Arguments (all input arguments): int nnz ; Number of nonzeros in the matrix A. This must be the same value as p [n_col] in the call to colamd - otherwise you will get a wrong value of the recommended memory to use. int n_row ; Number of rows in the matrix A. int n_col ; Number of columns in the matrix A. ---------------------------------------------------------------------------- colamd_set_defaults: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" colamd_set_defaults (double knobs [COLAMD_KNOBS]) ; colamd_l_set_defaults (double knobs [COLAMD_KNOBS]) ; Purpose: Sets the default parameters. The use of this routine is optional. Arguments: double knobs [COLAMD_KNOBS] ; Output only. NOTE: the meaning of the dense row/col knobs has changed in v2.4 knobs [0] and knobs [1] control dense row and col detection: Colamd: rows with more than max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n_col)) entries are removed prior to ordering. Columns with more than max (16, knobs [COLAMD_DENSE_COL] * sqrt (MIN (n_row,n_col))) entries are removed prior to ordering, and placed last in the output column ordering. Symamd: uses only knobs [COLAMD_DENSE_ROW], which is knobs [0]. Rows and columns with more than max (16, knobs [COLAMD_DENSE_ROW] * sqrt (n)) entries are removed prior to ordering, and placed last in the output ordering. COLAMD_DENSE_ROW and COLAMD_DENSE_COL are defined as 0 and 1, respectively, in colamd.h. Default values of these two knobs are both 10. Currently, only knobs [0] and knobs [1] are used, but future versions may use more knobs. If so, they will be properly set to their defaults by the future version of colamd_set_defaults, so that the code that calls colamd will not need to change, assuming that you either use colamd_set_defaults, or pass a (double *) NULL pointer as the knobs array to colamd or symamd. knobs [2]: aggressive absorption knobs [COLAMD_AGGRESSIVE] controls whether or not to do aggressive absorption during the ordering. Default is TRUE. ---------------------------------------------------------------------------- colamd: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" int colamd (int n_row, int n_col, int Alen, int *A, int *p, double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS]) ; UF_long colamd_l (UF_long n_row, UF_long n_col, UF_long Alen, UF_long *A, UF_long *p, double knobs [COLAMD_KNOBS], UF_long stats [COLAMD_STATS]) ; Purpose: Computes a column ordering (Q) of A such that P(AQ)=LU or (AQ)'AQ=LL' have less fill-in and require fewer floating point operations than factorizing the unpermuted matrix A or A'A, respectively. Returns: TRUE (1) if successful, FALSE (0) otherwise. Arguments: int n_row ; Input argument. Number of rows in the matrix A. Restriction: n_row >= 0. Colamd returns FALSE if n_row is negative. int n_col ; Input argument. Number of columns in the matrix A. Restriction: n_col >= 0. Colamd returns FALSE if n_col is negative. int Alen ; Input argument. Restriction (see note): Alen >= 2*nnz + 6*(n_col+1) + 4*(n_row+1) + n_col Colamd returns FALSE if these conditions are not met. Note: this restriction makes an modest assumption regarding the size of the two typedef's structures in colamd.h. We do, however, guarantee that Alen >= colamd_recommended (nnz, n_row, n_col) will be sufficient. Note: the macro version does not check for integer overflow, and thus is not recommended. Use the colamd_recommended routine instead. int A [Alen] ; Input argument, undefined on output. A is an integer array of size Alen. Alen must be at least as large as the bare minimum value given above, but this is very low, and can result in excessive run time. For best performance, we recommend that Alen be greater than or equal to colamd_recommended (nnz, n_row, n_col), which adds nnz/5 to the bare minimum value given above. On input, the row indices of the entries in column c of the matrix are held in A [(p [c]) ... (p [c+1]-1)]. The row indices in a given column c need not be in ascending order, and duplicate row indices may be be present. However, colamd will work a little faster if both of these conditions are met (Colamd puts the matrix into this format, if it finds that the the conditions are not met). The matrix is 0-based. That is, rows are in the range 0 to n_row-1, and columns are in the range 0 to n_col-1. Colamd returns FALSE if any row index is out of range. The contents of A are modified during ordering, and are undefined on output. int p [n_col+1] ; Both input and output argument. p is an integer array of size n_col+1. On input, it holds the "pointers" for the column form of the matrix A. Column c of the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first entry, p [0], must be zero, and p [c] <= p [c+1] must hold for all c in the range 0 to n_col-1. The value p [n_col] is thus the total number of entries in the pattern of the matrix A. Colamd returns FALSE if these conditions are not met. On output, if colamd returns TRUE, the array p holds the column permutation (Q, for P(AQ)=LU or (AQ)'(AQ)=LL'), where p [0] is the first column index in the new ordering, and p [n_col-1] is the last. That is, p [k] = j means that column j of A is the kth pivot column, in AQ, where k is in the range 0 to n_col-1 (p [0] = j means that column j of A is the first column in AQ). If colamd returns FALSE, then no permutation is returned, and p is undefined on output. double knobs [COLAMD_KNOBS] ; Input argument. See colamd_set_defaults for a description. int stats [COLAMD_STATS] ; Output argument. Statistics on the ordering, and error status. See colamd.h for related definitions. Colamd returns FALSE if stats is not present. stats [0]: number of dense or empty rows ignored. stats [1]: number of dense or empty columns ignored (and ordered last in the output permutation p) Note that a row can become "empty" if it contains only "dense" and/or "empty" columns, and similarly a column can become "empty" if it only contains "dense" and/or "empty" rows. stats [2]: number of garbage collections performed. This can be excessively high if Alen is close to the minimum required value. stats [3]: status code. < 0 is an error code. > 1 is a warning or notice. 0 OK. Each column of the input matrix contained row indices in increasing order, with no duplicates. 1 OK, but columns of input matrix were jumbled (unsorted columns or duplicate entries). Colamd had to do some extra work to sort the matrix first and remove duplicate entries, but it still was able to return a valid permutation (return value of colamd was TRUE). stats [4]: highest numbered column that is unsorted or has duplicate entries. stats [5]: last seen duplicate or unsorted row index. stats [6]: number of duplicate or unsorted row indices. -1 A is a null pointer -2 p is a null pointer -3 n_row is negative stats [4]: n_row -4 n_col is negative stats [4]: n_col -5 number of nonzeros in matrix is negative stats [4]: number of nonzeros, p [n_col] -6 p [0] is nonzero stats [4]: p [0] -7 A is too small stats [4]: required size stats [5]: actual size (Alen) -8 a column has a negative number of entries stats [4]: column with < 0 entries stats [5]: number of entries in col -9 a row index is out of bounds stats [4]: column with bad row index stats [5]: bad row index stats [6]: n_row, # of rows of matrx -10 (unused; see symamd.c) -999 (unused; see symamd.c) Future versions may return more statistics in the stats array. Example: See http://www.cise.ufl.edu/research/sparse/colamd/example.c for a complete example. To order the columns of a 5-by-4 matrix with 11 nonzero entries in the following nonzero pattern x 0 x 0 x 0 x x 0 x x 0 0 0 x x x x 0 0 with default knobs and no output statistics, do the following: #include "colamd.h" #define ALEN 100 int A [ALEN] = {0, 1, 4, 2, 4, 0, 1, 2, 3, 1, 3} ; int p [ ] = {0, 3, 5, 9, 11} ; int stats [COLAMD_STATS] ; colamd (5, 4, ALEN, A, p, (double *) NULL, stats) ; The permutation is returned in the array p, and A is destroyed. ---------------------------------------------------------------------------- symamd: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" int symamd (int n, int *A, int *p, int *perm, double knobs [COLAMD_KNOBS], int stats [COLAMD_STATS], void (*allocate) (size_t, size_t), void (*release) (void *)) ; UF_long symamd_l (UF_long n, UF_long *A, UF_long *p, UF_long *perm, double knobs [COLAMD_KNOBS], UF_long stats [COLAMD_STATS], void (*allocate) (size_t, size_t), void (*release) (void *)) ; Purpose: The symamd routine computes an ordering P of a symmetric sparse matrix A such that the Cholesky factorization PAP' = LL' remains sparse. It is based on a column ordering of a matrix M constructed so that the nonzero pattern of M'M is the same as A. The matrix A is assumed to be symmetric; only the strictly lower triangular part is accessed. You must pass your selected memory allocator (usually calloc/free or mxCalloc/mxFree) to symamd, for it to allocate memory for the temporary matrix M. Returns: TRUE (1) if successful, FALSE (0) otherwise. Arguments: int n ; Input argument. Number of rows and columns in the symmetrix matrix A. Restriction: n >= 0. Symamd returns FALSE if n is negative. int A [nnz] ; Input argument. A is an integer array of size nnz, where nnz = p [n]. The row indices of the entries in column c of the matrix are held in A [(p [c]) ... (p [c+1]-1)]. The row indices in a given column c need not be in ascending order, and duplicate row indices may be present. However, symamd will run faster if the columns are in sorted order with no duplicate entries. The matrix is 0-based. That is, rows are in the range 0 to n-1, and columns are in the range 0 to n-1. Symamd returns FALSE if any row index is out of range. The contents of A are not modified. int p [n+1] ; Input argument. p is an integer array of size n+1. On input, it holds the "pointers" for the column form of the matrix A. Column c of the matrix A is held in A [(p [c]) ... (p [c+1]-1)]. The first entry, p [0], must be zero, and p [c] <= p [c+1] must hold for all c in the range 0 to n-1. The value p [n] is thus the total number of entries in the pattern of the matrix A. Symamd returns FALSE if these conditions are not met. The contents of p are not modified. int perm [n+1] ; Output argument. On output, if symamd returns TRUE, the array perm holds the permutation P, where perm [0] is the first index in the new ordering, and perm [n-1] is the last. That is, perm [k] = j means that row and column j of A is the kth column in PAP', where k is in the range 0 to n-1 (perm [0] = j means that row and column j of A are the first row and column in PAP'). The array is used as a workspace during the ordering, which is why it must be of length n+1, not just n. double knobs [COLAMD_KNOBS] ; Input argument. See colamd_set_defaults for a description. int stats [COLAMD_STATS] ; Output argument. Statistics on the ordering, and error status. See colamd.h for related definitions. Symamd returns FALSE if stats is not present. stats [0]: number of dense or empty row and columns ignored (and ordered last in the output permutation perm). Note that a row/column can become "empty" if it contains only "dense" and/or "empty" columns/rows. stats [1]: (same as stats [0]) stats [2]: number of garbage collections performed. stats [3]: status code. < 0 is an error code. > 1 is a warning or notice. 0 OK. Each column of the input matrix contained row indices in increasing order, with no duplicates. 1 OK, but columns of input matrix were jumbled (unsorted columns or duplicate entries). Symamd had to do some extra work to sort the matrix first and remove duplicate entries, but it still was able to return a valid permutation (return value of symamd was TRUE). stats [4]: highest numbered column that is unsorted or has duplicate entries. stats [5]: last seen duplicate or unsorted row index. stats [6]: number of duplicate or unsorted row indices. -1 A is a null pointer -2 p is a null pointer -3 (unused, see colamd.c) -4 n is negative stats [4]: n -5 number of nonzeros in matrix is negative stats [4]: # of nonzeros (p [n]). -6 p [0] is nonzero stats [4]: p [0] -7 (unused) -8 a column has a negative number of entries stats [4]: column with < 0 entries stats [5]: number of entries in col -9 a row index is out of bounds stats [4]: column with bad row index stats [5]: bad row index stats [6]: n_row, # of rows of matrx -10 out of memory (unable to allocate temporary workspace for M or count arrays using the "allocate" routine passed into symamd). Future versions may return more statistics in the stats array. void * (*allocate) (size_t, size_t) A pointer to a function providing memory allocation. The allocated memory must be returned initialized to zero. For a C application, this argument should normally be a pointer to calloc. For a MATLAB mexFunction, the routine mxCalloc is passed instead. void (*release) (size_t, size_t) A pointer to a function that frees memory allocated by the memory allocation routine above. For a C application, this argument should normally be a pointer to free. For a MATLAB mexFunction, the routine mxFree is passed instead. ---------------------------------------------------------------------------- colamd_report: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" colamd_report (int stats [COLAMD_STATS]) ; colamd_l_report (UF_long stats [COLAMD_STATS]) ; Purpose: Prints the error status and statistics recorded in the stats array on the standard error output (for a standard C routine) or on the MATLAB output (for a mexFunction). Arguments: int stats [COLAMD_STATS] ; Input only. Statistics from colamd. ---------------------------------------------------------------------------- symamd_report: ---------------------------------------------------------------------------- C syntax: #include "colamd.h" symamd_report (int stats [COLAMD_STATS]) ; symamd_l_report (UF_long stats [COLAMD_STATS]) ; Purpose: Prints the error status and statistics recorded in the stats array on the standard error output (for a standard C routine) or on the MATLAB output (for a mexFunction). Arguments: int stats [COLAMD_STATS] ; Input only. Statistics from symamd. */ /* ========================================================================== */ /* === Scaffolding code definitions ======================================== */ /* ========================================================================== */ /* Ensure that debugging is turned off: */ #ifndef NDEBUG #define NDEBUG #endif /* turn on debugging by uncommenting the following line #undef NDEBUG */ /* Our "scaffolding code" philosophy: In our opinion, well-written library code should keep its "debugging" code, and just normally have it turned off by the compiler so as not to interfere with performance. This serves several purposes: (1) assertions act as comments to the reader, telling you what the code expects at that point. All assertions will always be true (unless there really is a bug, of course). (2) leaving in the scaffolding code assists anyone who would like to modify the code, or understand the algorithm (by reading the debugging output, one can get a glimpse into what the code is doing). (3) (gasp!) for actually finding bugs. This code has been heavily tested and "should" be fully functional and bug-free ... but you never know... The code will become outrageously slow when debugging is enabled. To control the level of debugging output, set an environment variable D to 0 (little), 1 (some), 2, 3, or 4 (lots). When debugging, you should see the following message on the standard output: colamd: debug version, D = 1 (THIS WILL BE SLOW!) or a similar message for symamd. If you don't, then debugging has not been enabled. */ /* ========================================================================== */ /* === Include files ======================================================== */ /* ========================================================================== */ #include "colamd.h" #if 0 /* by mao */ #include #include #ifdef MATLAB_MEX_FILE #include "mex.h" #include "matrix.h" #endif /* MATLAB_MEX_FILE */ #if !defined (NPRINT) || !defined (NDEBUG) #include #endif #ifndef NULL #define NULL ((void *) 0) #endif #endif /* ========================================================================== */ /* === int or UF_long ======================================================= */ /* ========================================================================== */ #if 0 /* by mao */ /* define UF_long */ #include "UFconfig.h" #endif #ifdef DLONG #define Int UF_long #define ID UF_long_id #define Int_MAX UF_long_max #define COLAMD_recommended colamd_l_recommended #define COLAMD_set_defaults colamd_l_set_defaults #define COLAMD_MAIN colamd_l #define SYMAMD_MAIN symamd_l #define COLAMD_report colamd_l_report #define SYMAMD_report symamd_l_report #else #define Int int #define ID "%d" #define Int_MAX INT_MAX #define COLAMD_recommended colamd_recommended #define COLAMD_set_defaults colamd_set_defaults #define COLAMD_MAIN colamd #define SYMAMD_MAIN symamd #define COLAMD_report colamd_report #define SYMAMD_report symamd_report #endif /* ========================================================================== */ /* === Row and Column structures ============================================ */ /* ========================================================================== */ /* User code that makes use of the colamd/symamd routines need not directly */ /* reference these structures. They are used only for colamd_recommended. */ typedef struct Colamd_Col_struct { Int start ; /* index for A of first row in this column, or DEAD */ /* if column is dead */ Int length ; /* number of rows in this column */ union { Int thickness ; /* number of original columns represented by this */ /* col, if the column is alive */ Int parent ; /* parent in parent tree super-column structure, if */ /* the column is dead */ } shared1 ; union { Int score ; /* the score used to maintain heap, if col is alive */ Int order ; /* pivot ordering of this column, if col is dead */ } shared2 ; union { Int headhash ; /* head of a hash bucket, if col is at the head of */ /* a degree list */ Int hash ; /* hash value, if col is not in a degree list */ Int prev ; /* previous column in degree list, if col is in a */ /* degree list (but not at the head of a degree list) */ } shared3 ; union { Int degree_next ; /* next column, if col is in a degree list */ Int hash_next ; /* next column, if col is in a hash list */ } shared4 ; } Colamd_Col ; typedef struct Colamd_Row_struct { Int start ; /* index for A of first col in this row */ Int length ; /* number of principal columns in this row */ union { Int degree ; /* number of principal & non-principal columns in row */ Int p ; /* used as a row pointer in init_rows_cols () */ } shared1 ; union { Int mark ; /* for computing set differences and marking dead rows*/ Int first_column ;/* first column in row (used in garbage collection) */ } shared2 ; } Colamd_Row ; /* ========================================================================== */ /* === Definitions ========================================================== */ /* ========================================================================== */ /* Routines are either PUBLIC (user-callable) or PRIVATE (not user-callable) */ #define PUBLIC #define PRIVATE static #define DENSE_DEGREE(alpha,n) \ ((Int) MAX (16.0, (alpha) * sqrt ((double) (n)))) #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #define ONES_COMPLEMENT(r) (-(r)-1) /* -------------------------------------------------------------------------- */ /* Change for version 2.1: define TRUE and FALSE only if not yet defined */ /* -------------------------------------------------------------------------- */ #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif /* -------------------------------------------------------------------------- */ #define EMPTY (-1) /* Row and column status */ #define ALIVE (0) #define DEAD (-1) /* Column status */ #define DEAD_PRINCIPAL (-1) #define DEAD_NON_PRINCIPAL (-2) /* Macros for row and column status update and checking. */ #define ROW_IS_DEAD(r) ROW_IS_MARKED_DEAD (Row[r].shared2.mark) #define ROW_IS_MARKED_DEAD(row_mark) (row_mark < ALIVE) #define ROW_IS_ALIVE(r) (Row [r].shared2.mark >= ALIVE) #define COL_IS_DEAD(c) (Col [c].start < ALIVE) #define COL_IS_ALIVE(c) (Col [c].start >= ALIVE) #define COL_IS_DEAD_PRINCIPAL(c) (Col [c].start == DEAD_PRINCIPAL) #define KILL_ROW(r) { Row [r].shared2.mark = DEAD ; } #define KILL_PRINCIPAL_COL(c) { Col [c].start = DEAD_PRINCIPAL ; } #define KILL_NON_PRINCIPAL_COL(c) { Col [c].start = DEAD_NON_PRINCIPAL ; } /* ========================================================================== */ /* === Colamd reporting mechanism =========================================== */ /* ========================================================================== */ #if defined (MATLAB_MEX_FILE) || defined (MATHWORKS) /* In MATLAB, matrices are 1-based to the user, but 0-based internally */ #define INDEX(i) ((i)+1) #else /* In C, matrices are 0-based and indices are reported as such in *_report */ #define INDEX(i) (i) #endif /* All output goes through the PRINTF macro. */ #define PRINTF(params) { if (colamd_printf != NULL) (void) colamd_printf params ; } /* ========================================================================== */ /* === Prototypes of PRIVATE routines ======================================= */ /* ========================================================================== */ PRIVATE Int init_rows_cols ( Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int A [], Int p [], Int stats [COLAMD_STATS] ) ; PRIVATE void init_scoring ( Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int A [], Int head [], double knobs [COLAMD_KNOBS], Int *p_n_row2, Int *p_n_col2, Int *p_max_deg ) ; PRIVATE Int find_ordering ( Int n_row, Int n_col, Int Alen, Colamd_Row Row [], Colamd_Col Col [], Int A [], Int head [], Int n_col2, Int max_deg, Int pfree, Int aggressive ) ; PRIVATE void order_children ( Int n_col, Colamd_Col Col [], Int p [] ) ; PRIVATE void detect_super_cols ( #ifndef NDEBUG Int n_col, Colamd_Row Row [], #endif /* NDEBUG */ Colamd_Col Col [], Int A [], Int head [], Int row_start, Int row_length ) ; PRIVATE Int garbage_collection ( Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int A [], Int *pfree ) ; PRIVATE Int clear_mark ( Int tag_mark, Int max_mark, Int n_row, Colamd_Row Row [] ) ; PRIVATE void print_report ( char *method, Int stats [COLAMD_STATS] ) ; /* ========================================================================== */ /* === Debugging prototypes and definitions ================================= */ /* ========================================================================== */ #ifndef NDEBUG #if 0 /* by mao */ #include #endif /* colamd_debug is the *ONLY* global variable, and is only */ /* present when debugging */ PRIVATE Int colamd_debug = 0 ; /* debug print level */ #define DEBUG0(params) { PRINTF (params) ; } #define DEBUG1(params) { if (colamd_debug >= 1) PRINTF (params) ; } #define DEBUG2(params) { if (colamd_debug >= 2) PRINTF (params) ; } #define DEBUG3(params) { if (colamd_debug >= 3) PRINTF (params) ; } #define DEBUG4(params) { if (colamd_debug >= 4) PRINTF (params) ; } #if 0 /* by mao */ #ifdef MATLAB_MEX_FILE #define ASSERT(expression) (mxAssert ((expression), "")) #else #define ASSERT(expression) (assert (expression)) #endif /* MATLAB_MEX_FILE */ #else #define ASSERT xassert #endif PRIVATE void colamd_get_debug /* gets the debug print level from getenv */ ( char *method ) ; PRIVATE void debug_deg_lists ( Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int head [], Int min_score, Int should, Int max_deg ) ; PRIVATE void debug_mark ( Int n_row, Colamd_Row Row [], Int tag_mark, Int max_mark ) ; PRIVATE void debug_matrix ( Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int A [] ) ; PRIVATE void debug_structures ( Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int A [], Int n_col2 ) ; #else /* NDEBUG */ /* === No debugging ========================================================= */ #define DEBUG0(params) ; #define DEBUG1(params) ; #define DEBUG2(params) ; #define DEBUG3(params) ; #define DEBUG4(params) ; #define ASSERT(expression) #endif /* NDEBUG */ /* ========================================================================== */ /* === USER-CALLABLE ROUTINES: ============================================== */ /* ========================================================================== */ /* ========================================================================== */ /* === colamd_recommended =================================================== */ /* ========================================================================== */ /* The colamd_recommended routine returns the suggested size for Alen. This value has been determined to provide good balance between the number of garbage collections and the memory requirements for colamd. If any argument is negative, or if integer overflow occurs, a 0 is returned as an error condition. 2*nnz space is required for the row and column indices of the matrix. COLAMD_C (n_col) + COLAMD_R (n_row) space is required for the Col and Row arrays, respectively, which are internal to colamd (roughly 6*n_col + 4*n_row). An additional n_col space is the minimal amount of "elbow room", and nnz/5 more space is recommended for run time efficiency. Alen is approximately 2.2*nnz + 7*n_col + 4*n_row + 10. This function is not needed when using symamd. */ /* add two values of type size_t, and check for integer overflow */ static size_t t_add (size_t a, size_t b, int *ok) { (*ok) = (*ok) && ((a + b) >= MAX (a,b)) ; return ((*ok) ? (a + b) : 0) ; } /* compute a*k where k is a small integer, and check for integer overflow */ static size_t t_mult (size_t a, size_t k, int *ok) { size_t i, s = 0 ; for (i = 0 ; i < k ; i++) { s = t_add (s, a, ok) ; } return (s) ; } /* size of the Col and Row structures */ #define COLAMD_C(n_col,ok) \ ((t_mult (t_add (n_col, 1, ok), sizeof (Colamd_Col), ok) / sizeof (Int))) #define COLAMD_R(n_row,ok) \ ((t_mult (t_add (n_row, 1, ok), sizeof (Colamd_Row), ok) / sizeof (Int))) PUBLIC size_t COLAMD_recommended /* returns recommended value of Alen. */ ( /* === Parameters ======================================================= */ Int nnz, /* number of nonzeros in A */ Int n_row, /* number of rows in A */ Int n_col /* number of columns in A */ ) { size_t s, c, r ; int ok = TRUE ; if (nnz < 0 || n_row < 0 || n_col < 0) { return (0) ; } s = t_mult (nnz, 2, &ok) ; /* 2*nnz */ c = COLAMD_C (n_col, &ok) ; /* size of column structures */ r = COLAMD_R (n_row, &ok) ; /* size of row structures */ s = t_add (s, c, &ok) ; s = t_add (s, r, &ok) ; s = t_add (s, n_col, &ok) ; /* elbow room */ s = t_add (s, nnz/5, &ok) ; /* elbow room */ ok = ok && (s < Int_MAX) ; return (ok ? s : 0) ; } /* ========================================================================== */ /* === colamd_set_defaults ================================================== */ /* ========================================================================== */ /* The colamd_set_defaults routine sets the default values of the user- controllable parameters for colamd and symamd: Colamd: rows with more than max (16, knobs [0] * sqrt (n_col)) entries are removed prior to ordering. Columns with more than max (16, knobs [1] * sqrt (MIN (n_row,n_col))) entries are removed prior to ordering, and placed last in the output column ordering. Symamd: Rows and columns with more than max (16, knobs [0] * sqrt (n)) entries are removed prior to ordering, and placed last in the output ordering. knobs [0] dense row control knobs [1] dense column control knobs [2] if nonzero, do aggresive absorption knobs [3..19] unused, but future versions might use this */ PUBLIC void COLAMD_set_defaults ( /* === Parameters ======================================================= */ double knobs [COLAMD_KNOBS] /* knob array */ ) { /* === Local variables ================================================== */ Int i ; if (!knobs) { return ; /* no knobs to initialize */ } for (i = 0 ; i < COLAMD_KNOBS ; i++) { knobs [i] = 0 ; } knobs [COLAMD_DENSE_ROW] = 10 ; knobs [COLAMD_DENSE_COL] = 10 ; knobs [COLAMD_AGGRESSIVE] = TRUE ; /* default: do aggressive absorption*/ } /* ========================================================================== */ /* === symamd =============================================================== */ /* ========================================================================== */ PUBLIC Int SYMAMD_MAIN /* return TRUE if OK, FALSE otherwise */ ( /* === Parameters ======================================================= */ Int n, /* number of rows and columns of A */ Int A [], /* row indices of A */ Int p [], /* column pointers of A */ Int perm [], /* output permutation, size n+1 */ double knobs [COLAMD_KNOBS], /* parameters (uses defaults if NULL) */ Int stats [COLAMD_STATS], /* output statistics and error codes */ void * (*allocate) (size_t, size_t), /* pointer to calloc (ANSI C) or */ /* mxCalloc (for MATLAB mexFunction) */ void (*release) (void *) /* pointer to free (ANSI C) or */ /* mxFree (for MATLAB mexFunction) */ ) { /* === Local variables ================================================== */ Int *count ; /* length of each column of M, and col pointer*/ Int *mark ; /* mark array for finding duplicate entries */ Int *M ; /* row indices of matrix M */ size_t Mlen ; /* length of M */ Int n_row ; /* number of rows in M */ Int nnz ; /* number of entries in A */ Int i ; /* row index of A */ Int j ; /* column index of A */ Int k ; /* row index of M */ Int mnz ; /* number of nonzeros in M */ Int pp ; /* index into a column of A */ Int last_row ; /* last row seen in the current column */ Int length ; /* number of nonzeros in a column */ double cknobs [COLAMD_KNOBS] ; /* knobs for colamd */ double default_knobs [COLAMD_KNOBS] ; /* default knobs for colamd */ #ifndef NDEBUG colamd_get_debug ("symamd") ; #endif /* NDEBUG */ /* === Check the input arguments ======================================== */ if (!stats) { DEBUG0 (("symamd: stats not present\n")) ; return (FALSE) ; } for (i = 0 ; i < COLAMD_STATS ; i++) { stats [i] = 0 ; } stats [COLAMD_STATUS] = COLAMD_OK ; stats [COLAMD_INFO1] = -1 ; stats [COLAMD_INFO2] = -1 ; if (!A) { stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; DEBUG0 (("symamd: A not present\n")) ; return (FALSE) ; } if (!p) /* p is not present */ { stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; DEBUG0 (("symamd: p not present\n")) ; return (FALSE) ; } if (n < 0) /* n must be >= 0 */ { stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; stats [COLAMD_INFO1] = n ; DEBUG0 (("symamd: n negative %d\n", n)) ; return (FALSE) ; } nnz = p [n] ; if (nnz < 0) /* nnz must be >= 0 */ { stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; stats [COLAMD_INFO1] = nnz ; DEBUG0 (("symamd: number of entries negative %d\n", nnz)) ; return (FALSE) ; } if (p [0] != 0) { stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; stats [COLAMD_INFO1] = p [0] ; DEBUG0 (("symamd: p[0] not zero %d\n", p [0])) ; return (FALSE) ; } /* === If no knobs, set default knobs =================================== */ if (!knobs) { COLAMD_set_defaults (default_knobs) ; knobs = default_knobs ; } /* === Allocate count and mark ========================================== */ count = (Int *) ((*allocate) (n+1, sizeof (Int))) ; if (!count) { stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; DEBUG0 (("symamd: allocate count (size %d) failed\n", n+1)) ; return (FALSE) ; } mark = (Int *) ((*allocate) (n+1, sizeof (Int))) ; if (!mark) { stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; (*release) ((void *) count) ; DEBUG0 (("symamd: allocate mark (size %d) failed\n", n+1)) ; return (FALSE) ; } /* === Compute column counts of M, check if A is valid ================== */ stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ for (i = 0 ; i < n ; i++) { mark [i] = -1 ; } for (j = 0 ; j < n ; j++) { last_row = -1 ; length = p [j+1] - p [j] ; if (length < 0) { /* column pointers must be non-decreasing */ stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; stats [COLAMD_INFO1] = j ; stats [COLAMD_INFO2] = length ; (*release) ((void *) count) ; (*release) ((void *) mark) ; DEBUG0 (("symamd: col %d negative length %d\n", j, length)) ; return (FALSE) ; } for (pp = p [j] ; pp < p [j+1] ; pp++) { i = A [pp] ; if (i < 0 || i >= n) { /* row index i, in column j, is out of bounds */ stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; stats [COLAMD_INFO1] = j ; stats [COLAMD_INFO2] = i ; stats [COLAMD_INFO3] = n ; (*release) ((void *) count) ; (*release) ((void *) mark) ; DEBUG0 (("symamd: row %d col %d out of bounds\n", i, j)) ; return (FALSE) ; } if (i <= last_row || mark [i] == j) { /* row index is unsorted or repeated (or both), thus col */ /* is jumbled. This is a notice, not an error condition. */ stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; stats [COLAMD_INFO1] = j ; stats [COLAMD_INFO2] = i ; (stats [COLAMD_INFO3]) ++ ; DEBUG1 (("symamd: row %d col %d unsorted/duplicate\n", i, j)) ; } if (i > j && mark [i] != j) { /* row k of M will contain column indices i and j */ count [i]++ ; count [j]++ ; } /* mark the row as having been seen in this column */ mark [i] = j ; last_row = i ; } } /* v2.4: removed free(mark) */ /* === Compute column pointers of M ===================================== */ /* use output permutation, perm, for column pointers of M */ perm [0] = 0 ; for (j = 1 ; j <= n ; j++) { perm [j] = perm [j-1] + count [j-1] ; } for (j = 0 ; j < n ; j++) { count [j] = perm [j] ; } /* === Construct M ====================================================== */ mnz = perm [n] ; n_row = mnz / 2 ; Mlen = COLAMD_recommended (mnz, n_row, n) ; M = (Int *) ((*allocate) (Mlen, sizeof (Int))) ; DEBUG0 (("symamd: M is %d-by-%d with %d entries, Mlen = %g\n", n_row, n, mnz, (double) Mlen)) ; if (!M) { stats [COLAMD_STATUS] = COLAMD_ERROR_out_of_memory ; (*release) ((void *) count) ; (*release) ((void *) mark) ; DEBUG0 (("symamd: allocate M (size %g) failed\n", (double) Mlen)) ; return (FALSE) ; } k = 0 ; if (stats [COLAMD_STATUS] == COLAMD_OK) { /* Matrix is OK */ for (j = 0 ; j < n ; j++) { ASSERT (p [j+1] - p [j] >= 0) ; for (pp = p [j] ; pp < p [j+1] ; pp++) { i = A [pp] ; ASSERT (i >= 0 && i < n) ; if (i > j) { /* row k of M contains column indices i and j */ M [count [i]++] = k ; M [count [j]++] = k ; k++ ; } } } } else { /* Matrix is jumbled. Do not add duplicates to M. Unsorted cols OK. */ DEBUG0 (("symamd: Duplicates in A.\n")) ; for (i = 0 ; i < n ; i++) { mark [i] = -1 ; } for (j = 0 ; j < n ; j++) { ASSERT (p [j+1] - p [j] >= 0) ; for (pp = p [j] ; pp < p [j+1] ; pp++) { i = A [pp] ; ASSERT (i >= 0 && i < n) ; if (i > j && mark [i] != j) { /* row k of M contains column indices i and j */ M [count [i]++] = k ; M [count [j]++] = k ; k++ ; mark [i] = j ; } } } /* v2.4: free(mark) moved below */ } /* count and mark no longer needed */ (*release) ((void *) count) ; (*release) ((void *) mark) ; /* v2.4: free (mark) moved here */ ASSERT (k == n_row) ; /* === Adjust the knobs for M =========================================== */ for (i = 0 ; i < COLAMD_KNOBS ; i++) { cknobs [i] = knobs [i] ; } /* there are no dense rows in M */ cknobs [COLAMD_DENSE_ROW] = -1 ; cknobs [COLAMD_DENSE_COL] = knobs [COLAMD_DENSE_ROW] ; /* === Order the columns of M =========================================== */ /* v2.4: colamd cannot fail here, so the error check is removed */ (void) COLAMD_MAIN (n_row, n, (Int) Mlen, M, perm, cknobs, stats) ; /* Note that the output permutation is now in perm */ /* === get the statistics for symamd from colamd ======================== */ /* a dense column in colamd means a dense row and col in symamd */ stats [COLAMD_DENSE_ROW] = stats [COLAMD_DENSE_COL] ; /* === Free M =========================================================== */ (*release) ((void *) M) ; DEBUG0 (("symamd: done.\n")) ; return (TRUE) ; } /* ========================================================================== */ /* === colamd =============================================================== */ /* ========================================================================== */ /* The colamd routine computes a column ordering Q of a sparse matrix A such that the LU factorization P(AQ) = LU remains sparse, where P is selected via partial pivoting. The routine can also be viewed as providing a permutation Q such that the Cholesky factorization (AQ)'(AQ) = LL' remains sparse. */ PUBLIC Int COLAMD_MAIN /* returns TRUE if successful, FALSE otherwise*/ ( /* === Parameters ======================================================= */ Int n_row, /* number of rows in A */ Int n_col, /* number of columns in A */ Int Alen, /* length of A */ Int A [], /* row indices of A */ Int p [], /* pointers to columns in A */ double knobs [COLAMD_KNOBS],/* parameters (uses defaults if NULL) */ Int stats [COLAMD_STATS] /* output statistics and error codes */ ) { /* === Local variables ================================================== */ Int i ; /* loop index */ Int nnz ; /* nonzeros in A */ size_t Row_size ; /* size of Row [], in integers */ size_t Col_size ; /* size of Col [], in integers */ size_t need ; /* minimum required length of A */ Colamd_Row *Row ; /* pointer into A of Row [0..n_row] array */ Colamd_Col *Col ; /* pointer into A of Col [0..n_col] array */ Int n_col2 ; /* number of non-dense, non-empty columns */ Int n_row2 ; /* number of non-dense, non-empty rows */ Int ngarbage ; /* number of garbage collections performed */ Int max_deg ; /* maximum row degree */ double default_knobs [COLAMD_KNOBS] ; /* default knobs array */ Int aggressive ; /* do aggressive absorption */ int ok ; #ifndef NDEBUG colamd_get_debug ("colamd") ; #endif /* NDEBUG */ /* === Check the input arguments ======================================== */ if (!stats) { DEBUG0 (("colamd: stats not present\n")) ; return (FALSE) ; } for (i = 0 ; i < COLAMD_STATS ; i++) { stats [i] = 0 ; } stats [COLAMD_STATUS] = COLAMD_OK ; stats [COLAMD_INFO1] = -1 ; stats [COLAMD_INFO2] = -1 ; if (!A) /* A is not present */ { stats [COLAMD_STATUS] = COLAMD_ERROR_A_not_present ; DEBUG0 (("colamd: A not present\n")) ; return (FALSE) ; } if (!p) /* p is not present */ { stats [COLAMD_STATUS] = COLAMD_ERROR_p_not_present ; DEBUG0 (("colamd: p not present\n")) ; return (FALSE) ; } if (n_row < 0) /* n_row must be >= 0 */ { stats [COLAMD_STATUS] = COLAMD_ERROR_nrow_negative ; stats [COLAMD_INFO1] = n_row ; DEBUG0 (("colamd: nrow negative %d\n", n_row)) ; return (FALSE) ; } if (n_col < 0) /* n_col must be >= 0 */ { stats [COLAMD_STATUS] = COLAMD_ERROR_ncol_negative ; stats [COLAMD_INFO1] = n_col ; DEBUG0 (("colamd: ncol negative %d\n", n_col)) ; return (FALSE) ; } nnz = p [n_col] ; if (nnz < 0) /* nnz must be >= 0 */ { stats [COLAMD_STATUS] = COLAMD_ERROR_nnz_negative ; stats [COLAMD_INFO1] = nnz ; DEBUG0 (("colamd: number of entries negative %d\n", nnz)) ; return (FALSE) ; } if (p [0] != 0) { stats [COLAMD_STATUS] = COLAMD_ERROR_p0_nonzero ; stats [COLAMD_INFO1] = p [0] ; DEBUG0 (("colamd: p[0] not zero %d\n", p [0])) ; return (FALSE) ; } /* === If no knobs, set default knobs =================================== */ if (!knobs) { COLAMD_set_defaults (default_knobs) ; knobs = default_knobs ; } aggressive = (knobs [COLAMD_AGGRESSIVE] != FALSE) ; /* === Allocate the Row and Col arrays from array A ===================== */ ok = TRUE ; Col_size = COLAMD_C (n_col, &ok) ; /* size of Col array of structs */ Row_size = COLAMD_R (n_row, &ok) ; /* size of Row array of structs */ /* need = 2*nnz + n_col + Col_size + Row_size ; */ need = t_mult (nnz, 2, &ok) ; need = t_add (need, n_col, &ok) ; need = t_add (need, Col_size, &ok) ; need = t_add (need, Row_size, &ok) ; if (!ok || need > (size_t) Alen || need > Int_MAX) { /* not enough space in array A to perform the ordering */ stats [COLAMD_STATUS] = COLAMD_ERROR_A_too_small ; stats [COLAMD_INFO1] = need ; stats [COLAMD_INFO2] = Alen ; DEBUG0 (("colamd: Need Alen >= %d, given only Alen = %d\n", need,Alen)); return (FALSE) ; } Alen -= Col_size + Row_size ; Col = (Colamd_Col *) &A [Alen] ; Row = (Colamd_Row *) &A [Alen + Col_size] ; /* === Construct the row and column data structures ===================== */ if (!init_rows_cols (n_row, n_col, Row, Col, A, p, stats)) { /* input matrix is invalid */ DEBUG0 (("colamd: Matrix invalid\n")) ; return (FALSE) ; } /* === Initialize scores, kill dense rows/columns ======================= */ init_scoring (n_row, n_col, Row, Col, A, p, knobs, &n_row2, &n_col2, &max_deg) ; /* === Order the supercolumns =========================================== */ ngarbage = find_ordering (n_row, n_col, Alen, Row, Col, A, p, n_col2, max_deg, 2*nnz, aggressive) ; /* === Order the non-principal columns ================================== */ order_children (n_col, Col, p) ; /* === Return statistics in stats ======================================= */ stats [COLAMD_DENSE_ROW] = n_row - n_row2 ; stats [COLAMD_DENSE_COL] = n_col - n_col2 ; stats [COLAMD_DEFRAG_COUNT] = ngarbage ; DEBUG0 (("colamd: done.\n")) ; return (TRUE) ; } /* ========================================================================== */ /* === colamd_report ======================================================== */ /* ========================================================================== */ PUBLIC void COLAMD_report ( Int stats [COLAMD_STATS] ) { print_report ("colamd", stats) ; } /* ========================================================================== */ /* === symamd_report ======================================================== */ /* ========================================================================== */ PUBLIC void SYMAMD_report ( Int stats [COLAMD_STATS] ) { print_report ("symamd", stats) ; } /* ========================================================================== */ /* === NON-USER-CALLABLE ROUTINES: ========================================== */ /* ========================================================================== */ /* There are no user-callable routines beyond this point in the file */ /* ========================================================================== */ /* === init_rows_cols ======================================================= */ /* ========================================================================== */ /* Takes the column form of the matrix in A and creates the row form of the matrix. Also, row and column attributes are stored in the Col and Row structs. If the columns are un-sorted or contain duplicate row indices, this routine will also sort and remove duplicate row indices from the column form of the matrix. Returns FALSE if the matrix is invalid, TRUE otherwise. Not user-callable. */ PRIVATE Int init_rows_cols /* returns TRUE if OK, or FALSE otherwise */ ( /* === Parameters ======================================================= */ Int n_row, /* number of rows of A */ Int n_col, /* number of columns of A */ Colamd_Row Row [], /* of size n_row+1 */ Colamd_Col Col [], /* of size n_col+1 */ Int A [], /* row indices of A, of size Alen */ Int p [], /* pointers to columns in A, of size n_col+1 */ Int stats [COLAMD_STATS] /* colamd statistics */ ) { /* === Local variables ================================================== */ Int col ; /* a column index */ Int row ; /* a row index */ Int *cp ; /* a column pointer */ Int *cp_end ; /* a pointer to the end of a column */ Int *rp ; /* a row pointer */ Int *rp_end ; /* a pointer to the end of a row */ Int last_row ; /* previous row */ /* === Initialize columns, and check column pointers ==================== */ for (col = 0 ; col < n_col ; col++) { Col [col].start = p [col] ; Col [col].length = p [col+1] - p [col] ; if (Col [col].length < 0) { /* column pointers must be non-decreasing */ stats [COLAMD_STATUS] = COLAMD_ERROR_col_length_negative ; stats [COLAMD_INFO1] = col ; stats [COLAMD_INFO2] = Col [col].length ; DEBUG0 (("colamd: col %d length %d < 0\n", col, Col [col].length)) ; return (FALSE) ; } Col [col].shared1.thickness = 1 ; Col [col].shared2.score = 0 ; Col [col].shared3.prev = EMPTY ; Col [col].shared4.degree_next = EMPTY ; } /* p [0..n_col] no longer needed, used as "head" in subsequent routines */ /* === Scan columns, compute row degrees, and check row indices ========= */ stats [COLAMD_INFO3] = 0 ; /* number of duplicate or unsorted row indices*/ for (row = 0 ; row < n_row ; row++) { Row [row].length = 0 ; Row [row].shared2.mark = -1 ; } for (col = 0 ; col < n_col ; col++) { last_row = -1 ; cp = &A [p [col]] ; cp_end = &A [p [col+1]] ; while (cp < cp_end) { row = *cp++ ; /* make sure row indices within range */ if (row < 0 || row >= n_row) { stats [COLAMD_STATUS] = COLAMD_ERROR_row_index_out_of_bounds ; stats [COLAMD_INFO1] = col ; stats [COLAMD_INFO2] = row ; stats [COLAMD_INFO3] = n_row ; DEBUG0 (("colamd: row %d col %d out of bounds\n", row, col)) ; return (FALSE) ; } if (row <= last_row || Row [row].shared2.mark == col) { /* row index are unsorted or repeated (or both), thus col */ /* is jumbled. This is a notice, not an error condition. */ stats [COLAMD_STATUS] = COLAMD_OK_BUT_JUMBLED ; stats [COLAMD_INFO1] = col ; stats [COLAMD_INFO2] = row ; (stats [COLAMD_INFO3]) ++ ; DEBUG1 (("colamd: row %d col %d unsorted/duplicate\n",row,col)); } if (Row [row].shared2.mark != col) { Row [row].length++ ; } else { /* this is a repeated entry in the column, */ /* it will be removed */ Col [col].length-- ; } /* mark the row as having been seen in this column */ Row [row].shared2.mark = col ; last_row = row ; } } /* === Compute row pointers ============================================= */ /* row form of the matrix starts directly after the column */ /* form of matrix in A */ Row [0].start = p [n_col] ; Row [0].shared1.p = Row [0].start ; Row [0].shared2.mark = -1 ; for (row = 1 ; row < n_row ; row++) { Row [row].start = Row [row-1].start + Row [row-1].length ; Row [row].shared1.p = Row [row].start ; Row [row].shared2.mark = -1 ; } /* === Create row form ================================================== */ if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) { /* if cols jumbled, watch for repeated row indices */ for (col = 0 ; col < n_col ; col++) { cp = &A [p [col]] ; cp_end = &A [p [col+1]] ; while (cp < cp_end) { row = *cp++ ; if (Row [row].shared2.mark != col) { A [(Row [row].shared1.p)++] = col ; Row [row].shared2.mark = col ; } } } } else { /* if cols not jumbled, we don't need the mark (this is faster) */ for (col = 0 ; col < n_col ; col++) { cp = &A [p [col]] ; cp_end = &A [p [col+1]] ; while (cp < cp_end) { A [(Row [*cp++].shared1.p)++] = col ; } } } /* === Clear the row marks and set row degrees ========================== */ for (row = 0 ; row < n_row ; row++) { Row [row].shared2.mark = 0 ; Row [row].shared1.degree = Row [row].length ; } /* === See if we need to re-create columns ============================== */ if (stats [COLAMD_STATUS] == COLAMD_OK_BUT_JUMBLED) { DEBUG0 (("colamd: reconstructing column form, matrix jumbled\n")) ; #ifndef NDEBUG /* make sure column lengths are correct */ for (col = 0 ; col < n_col ; col++) { p [col] = Col [col].length ; } for (row = 0 ; row < n_row ; row++) { rp = &A [Row [row].start] ; rp_end = rp + Row [row].length ; while (rp < rp_end) { p [*rp++]-- ; } } for (col = 0 ; col < n_col ; col++) { ASSERT (p [col] == 0) ; } /* now p is all zero (different than when debugging is turned off) */ #endif /* NDEBUG */ /* === Compute col pointers ========================================= */ /* col form of the matrix starts at A [0]. */ /* Note, we may have a gap between the col form and the row */ /* form if there were duplicate entries, if so, it will be */ /* removed upon the first garbage collection */ Col [0].start = 0 ; p [0] = Col [0].start ; for (col = 1 ; col < n_col ; col++) { /* note that the lengths here are for pruned columns, i.e. */ /* no duplicate row indices will exist for these columns */ Col [col].start = Col [col-1].start + Col [col-1].length ; p [col] = Col [col].start ; } /* === Re-create col form =========================================== */ for (row = 0 ; row < n_row ; row++) { rp = &A [Row [row].start] ; rp_end = rp + Row [row].length ; while (rp < rp_end) { A [(p [*rp++])++] = row ; } } } /* === Done. Matrix is not (or no longer) jumbled ====================== */ return (TRUE) ; } /* ========================================================================== */ /* === init_scoring ========================================================= */ /* ========================================================================== */ /* Kills dense or empty columns and rows, calculates an initial score for each column, and places all columns in the degree lists. Not user-callable. */ PRIVATE void init_scoring ( /* === Parameters ======================================================= */ Int n_row, /* number of rows of A */ Int n_col, /* number of columns of A */ Colamd_Row Row [], /* of size n_row+1 */ Colamd_Col Col [], /* of size n_col+1 */ Int A [], /* column form and row form of A */ Int head [], /* of size n_col+1 */ double knobs [COLAMD_KNOBS],/* parameters */ Int *p_n_row2, /* number of non-dense, non-empty rows */ Int *p_n_col2, /* number of non-dense, non-empty columns */ Int *p_max_deg /* maximum row degree */ ) { /* === Local variables ================================================== */ Int c ; /* a column index */ Int r, row ; /* a row index */ Int *cp ; /* a column pointer */ Int deg ; /* degree of a row or column */ Int *cp_end ; /* a pointer to the end of a column */ Int *new_cp ; /* new column pointer */ Int col_length ; /* length of pruned column */ Int score ; /* current column score */ Int n_col2 ; /* number of non-dense, non-empty columns */ Int n_row2 ; /* number of non-dense, non-empty rows */ Int dense_row_count ; /* remove rows with more entries than this */ Int dense_col_count ; /* remove cols with more entries than this */ Int min_score ; /* smallest column score */ Int max_deg ; /* maximum row degree */ Int next_col ; /* Used to add to degree list.*/ #ifndef NDEBUG Int debug_count ; /* debug only. */ #endif /* NDEBUG */ /* === Extract knobs ==================================================== */ /* Note: if knobs contains a NaN, this is undefined: */ if (knobs [COLAMD_DENSE_ROW] < 0) { /* only remove completely dense rows */ dense_row_count = n_col-1 ; } else { dense_row_count = DENSE_DEGREE (knobs [COLAMD_DENSE_ROW], n_col) ; } if (knobs [COLAMD_DENSE_COL] < 0) { /* only remove completely dense columns */ dense_col_count = n_row-1 ; } else { dense_col_count = DENSE_DEGREE (knobs [COLAMD_DENSE_COL], MIN (n_row, n_col)) ; } DEBUG1 (("colamd: densecount: %d %d\n", dense_row_count, dense_col_count)) ; max_deg = 0 ; n_col2 = n_col ; n_row2 = n_row ; /* === Kill empty columns =============================================== */ /* Put the empty columns at the end in their natural order, so that LU */ /* factorization can proceed as far as possible. */ for (c = n_col-1 ; c >= 0 ; c--) { deg = Col [c].length ; if (deg == 0) { /* this is a empty column, kill and order it last */ Col [c].shared2.order = --n_col2 ; KILL_PRINCIPAL_COL (c) ; } } DEBUG1 (("colamd: null columns killed: %d\n", n_col - n_col2)) ; /* === Kill dense columns =============================================== */ /* Put the dense columns at the end, in their natural order */ for (c = n_col-1 ; c >= 0 ; c--) { /* skip any dead columns */ if (COL_IS_DEAD (c)) { continue ; } deg = Col [c].length ; if (deg > dense_col_count) { /* this is a dense column, kill and order it last */ Col [c].shared2.order = --n_col2 ; /* decrement the row degrees */ cp = &A [Col [c].start] ; cp_end = cp + Col [c].length ; while (cp < cp_end) { Row [*cp++].shared1.degree-- ; } KILL_PRINCIPAL_COL (c) ; } } DEBUG1 (("colamd: Dense and null columns killed: %d\n", n_col - n_col2)) ; /* === Kill dense and empty rows ======================================== */ for (r = 0 ; r < n_row ; r++) { deg = Row [r].shared1.degree ; ASSERT (deg >= 0 && deg <= n_col) ; if (deg > dense_row_count || deg == 0) { /* kill a dense or empty row */ KILL_ROW (r) ; --n_row2 ; } else { /* keep track of max degree of remaining rows */ max_deg = MAX (max_deg, deg) ; } } DEBUG1 (("colamd: Dense and null rows killed: %d\n", n_row - n_row2)) ; /* === Compute initial column scores ==================================== */ /* At this point the row degrees are accurate. They reflect the number */ /* of "live" (non-dense) columns in each row. No empty rows exist. */ /* Some "live" columns may contain only dead rows, however. These are */ /* pruned in the code below. */ /* now find the initial matlab score for each column */ for (c = n_col-1 ; c >= 0 ; c--) { /* skip dead column */ if (COL_IS_DEAD (c)) { continue ; } score = 0 ; cp = &A [Col [c].start] ; new_cp = cp ; cp_end = cp + Col [c].length ; while (cp < cp_end) { /* get a row */ row = *cp++ ; /* skip if dead */ if (ROW_IS_DEAD (row)) { continue ; } /* compact the column */ *new_cp++ = row ; /* add row's external degree */ score += Row [row].shared1.degree - 1 ; /* guard against integer overflow */ score = MIN (score, n_col) ; } /* determine pruned column length */ col_length = (Int) (new_cp - &A [Col [c].start]) ; if (col_length == 0) { /* a newly-made null column (all rows in this col are "dense" */ /* and have already been killed) */ DEBUG2 (("Newly null killed: %d\n", c)) ; Col [c].shared2.order = --n_col2 ; KILL_PRINCIPAL_COL (c) ; } else { /* set column length and set score */ ASSERT (score >= 0) ; ASSERT (score <= n_col) ; Col [c].length = col_length ; Col [c].shared2.score = score ; } } DEBUG1 (("colamd: Dense, null, and newly-null columns killed: %d\n", n_col-n_col2)) ; /* At this point, all empty rows and columns are dead. All live columns */ /* are "clean" (containing no dead rows) and simplicial (no supercolumns */ /* yet). Rows may contain dead columns, but all live rows contain at */ /* least one live column. */ #ifndef NDEBUG debug_structures (n_row, n_col, Row, Col, A, n_col2) ; #endif /* NDEBUG */ /* === Initialize degree lists ========================================== */ #ifndef NDEBUG debug_count = 0 ; #endif /* NDEBUG */ /* clear the hash buckets */ for (c = 0 ; c <= n_col ; c++) { head [c] = EMPTY ; } min_score = n_col ; /* place in reverse order, so low column indices are at the front */ /* of the lists. This is to encourage natural tie-breaking */ for (c = n_col-1 ; c >= 0 ; c--) { /* only add principal columns to degree lists */ if (COL_IS_ALIVE (c)) { DEBUG4 (("place %d score %d minscore %d ncol %d\n", c, Col [c].shared2.score, min_score, n_col)) ; /* === Add columns score to DList =============================== */ score = Col [c].shared2.score ; ASSERT (min_score >= 0) ; ASSERT (min_score <= n_col) ; ASSERT (score >= 0) ; ASSERT (score <= n_col) ; ASSERT (head [score] >= EMPTY) ; /* now add this column to dList at proper score location */ next_col = head [score] ; Col [c].shared3.prev = EMPTY ; Col [c].shared4.degree_next = next_col ; /* if there already was a column with the same score, set its */ /* previous pointer to this new column */ if (next_col != EMPTY) { Col [next_col].shared3.prev = c ; } head [score] = c ; /* see if this score is less than current min */ min_score = MIN (min_score, score) ; #ifndef NDEBUG debug_count++ ; #endif /* NDEBUG */ } } #ifndef NDEBUG DEBUG1 (("colamd: Live cols %d out of %d, non-princ: %d\n", debug_count, n_col, n_col-debug_count)) ; ASSERT (debug_count == n_col2) ; debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2, max_deg) ; #endif /* NDEBUG */ /* === Return number of remaining columns, and max row degree =========== */ *p_n_col2 = n_col2 ; *p_n_row2 = n_row2 ; *p_max_deg = max_deg ; } /* ========================================================================== */ /* === find_ordering ======================================================== */ /* ========================================================================== */ /* Order the principal columns of the supercolumn form of the matrix (no supercolumns on input). Uses a minimum approximate column minimum degree ordering method. Not user-callable. */ PRIVATE Int find_ordering /* return the number of garbage collections */ ( /* === Parameters ======================================================= */ Int n_row, /* number of rows of A */ Int n_col, /* number of columns of A */ Int Alen, /* size of A, 2*nnz + n_col or larger */ Colamd_Row Row [], /* of size n_row+1 */ Colamd_Col Col [], /* of size n_col+1 */ Int A [], /* column form and row form of A */ Int head [], /* of size n_col+1 */ Int n_col2, /* Remaining columns to order */ Int max_deg, /* Maximum row degree */ Int pfree, /* index of first free slot (2*nnz on entry) */ Int aggressive ) { /* === Local variables ================================================== */ Int k ; /* current pivot ordering step */ Int pivot_col ; /* current pivot column */ Int *cp ; /* a column pointer */ Int *rp ; /* a row pointer */ Int pivot_row ; /* current pivot row */ Int *new_cp ; /* modified column pointer */ Int *new_rp ; /* modified row pointer */ Int pivot_row_start ; /* pointer to start of pivot row */ Int pivot_row_degree ; /* number of columns in pivot row */ Int pivot_row_length ; /* number of supercolumns in pivot row */ Int pivot_col_score ; /* score of pivot column */ Int needed_memory ; /* free space needed for pivot row */ Int *cp_end ; /* pointer to the end of a column */ Int *rp_end ; /* pointer to the end of a row */ Int row ; /* a row index */ Int col ; /* a column index */ Int max_score ; /* maximum possible score */ Int cur_score ; /* score of current column */ unsigned Int hash ; /* hash value for supernode detection */ Int head_column ; /* head of hash bucket */ Int first_col ; /* first column in hash bucket */ Int tag_mark ; /* marker value for mark array */ Int row_mark ; /* Row [row].shared2.mark */ Int set_difference ; /* set difference size of row with pivot row */ Int min_score ; /* smallest column score */ Int col_thickness ; /* "thickness" (no. of columns in a supercol) */ Int max_mark ; /* maximum value of tag_mark */ Int pivot_col_thickness ; /* number of columns represented by pivot col */ Int prev_col ; /* Used by Dlist operations. */ Int next_col ; /* Used by Dlist operations. */ Int ngarbage ; /* number of garbage collections performed */ #ifndef NDEBUG Int debug_d ; /* debug loop counter */ Int debug_step = 0 ; /* debug loop counter */ #endif /* NDEBUG */ /* === Initialization and clear mark ==================================== */ max_mark = INT_MAX - n_col ; /* INT_MAX defined in */ tag_mark = clear_mark (0, max_mark, n_row, Row) ; min_score = 0 ; ngarbage = 0 ; DEBUG1 (("colamd: Ordering, n_col2=%d\n", n_col2)) ; /* === Order the columns ================================================ */ for (k = 0 ; k < n_col2 ; /* 'k' is incremented below */) { #ifndef NDEBUG if (debug_step % 100 == 0) { DEBUG2 (("\n... Step k: %d out of n_col2: %d\n", k, n_col2)) ; } else { DEBUG3 (("\n----------Step k: %d out of n_col2: %d\n", k, n_col2)) ; } debug_step++ ; debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2-k, max_deg) ; debug_matrix (n_row, n_col, Row, Col, A) ; #endif /* NDEBUG */ /* === Select pivot column, and order it ============================ */ /* make sure degree list isn't empty */ ASSERT (min_score >= 0) ; ASSERT (min_score <= n_col) ; ASSERT (head [min_score] >= EMPTY) ; #ifndef NDEBUG for (debug_d = 0 ; debug_d < min_score ; debug_d++) { ASSERT (head [debug_d] == EMPTY) ; } #endif /* NDEBUG */ /* get pivot column from head of minimum degree list */ while (head [min_score] == EMPTY && min_score < n_col) { min_score++ ; } pivot_col = head [min_score] ; ASSERT (pivot_col >= 0 && pivot_col <= n_col) ; next_col = Col [pivot_col].shared4.degree_next ; head [min_score] = next_col ; if (next_col != EMPTY) { Col [next_col].shared3.prev = EMPTY ; } ASSERT (COL_IS_ALIVE (pivot_col)) ; /* remember score for defrag check */ pivot_col_score = Col [pivot_col].shared2.score ; /* the pivot column is the kth column in the pivot order */ Col [pivot_col].shared2.order = k ; /* increment order count by column thickness */ pivot_col_thickness = Col [pivot_col].shared1.thickness ; k += pivot_col_thickness ; ASSERT (pivot_col_thickness > 0) ; DEBUG3 (("Pivot col: %d thick %d\n", pivot_col, pivot_col_thickness)) ; /* === Garbage_collection, if necessary ============================= */ needed_memory = MIN (pivot_col_score, n_col - k) ; if (pfree + needed_memory >= Alen) { pfree = garbage_collection (n_row, n_col, Row, Col, A, &A [pfree]) ; ngarbage++ ; /* after garbage collection we will have enough */ ASSERT (pfree + needed_memory < Alen) ; /* garbage collection has wiped out the Row[].shared2.mark array */ tag_mark = clear_mark (0, max_mark, n_row, Row) ; #ifndef NDEBUG debug_matrix (n_row, n_col, Row, Col, A) ; #endif /* NDEBUG */ } /* === Compute pivot row pattern ==================================== */ /* get starting location for this new merged row */ pivot_row_start = pfree ; /* initialize new row counts to zero */ pivot_row_degree = 0 ; /* tag pivot column as having been visited so it isn't included */ /* in merged pivot row */ Col [pivot_col].shared1.thickness = -pivot_col_thickness ; /* pivot row is the union of all rows in the pivot column pattern */ cp = &A [Col [pivot_col].start] ; cp_end = cp + Col [pivot_col].length ; while (cp < cp_end) { /* get a row */ row = *cp++ ; DEBUG4 (("Pivot col pattern %d %d\n", ROW_IS_ALIVE (row), row)) ; /* skip if row is dead */ if (ROW_IS_ALIVE (row)) { rp = &A [Row [row].start] ; rp_end = rp + Row [row].length ; while (rp < rp_end) { /* get a column */ col = *rp++ ; /* add the column, if alive and untagged */ col_thickness = Col [col].shared1.thickness ; if (col_thickness > 0 && COL_IS_ALIVE (col)) { /* tag column in pivot row */ Col [col].shared1.thickness = -col_thickness ; ASSERT (pfree < Alen) ; /* place column in pivot row */ A [pfree++] = col ; pivot_row_degree += col_thickness ; } } } } /* clear tag on pivot column */ Col [pivot_col].shared1.thickness = pivot_col_thickness ; max_deg = MAX (max_deg, pivot_row_degree) ; #ifndef NDEBUG DEBUG3 (("check2\n")) ; debug_mark (n_row, Row, tag_mark, max_mark) ; #endif /* NDEBUG */ /* === Kill all rows used to construct pivot row ==================== */ /* also kill pivot row, temporarily */ cp = &A [Col [pivot_col].start] ; cp_end = cp + Col [pivot_col].length ; while (cp < cp_end) { /* may be killing an already dead row */ row = *cp++ ; DEBUG3 (("Kill row in pivot col: %d\n", row)) ; KILL_ROW (row) ; } /* === Select a row index to use as the new pivot row =============== */ pivot_row_length = pfree - pivot_row_start ; if (pivot_row_length > 0) { /* pick the "pivot" row arbitrarily (first row in col) */ pivot_row = A [Col [pivot_col].start] ; DEBUG3 (("Pivotal row is %d\n", pivot_row)) ; } else { /* there is no pivot row, since it is of zero length */ pivot_row = EMPTY ; ASSERT (pivot_row_length == 0) ; } ASSERT (Col [pivot_col].length > 0 || pivot_row_length == 0) ; /* === Approximate degree computation =============================== */ /* Here begins the computation of the approximate degree. The column */ /* score is the sum of the pivot row "length", plus the size of the */ /* set differences of each row in the column minus the pattern of the */ /* pivot row itself. The column ("thickness") itself is also */ /* excluded from the column score (we thus use an approximate */ /* external degree). */ /* The time taken by the following code (compute set differences, and */ /* add them up) is proportional to the size of the data structure */ /* being scanned - that is, the sum of the sizes of each column in */ /* the pivot row. Thus, the amortized time to compute a column score */ /* is proportional to the size of that column (where size, in this */ /* context, is the column "length", or the number of row indices */ /* in that column). The number of row indices in a column is */ /* monotonically non-decreasing, from the length of the original */ /* column on input to colamd. */ /* === Compute set differences ====================================== */ DEBUG3 (("** Computing set differences phase. **\n")) ; /* pivot row is currently dead - it will be revived later. */ DEBUG3 (("Pivot row: ")) ; /* for each column in pivot row */ rp = &A [pivot_row_start] ; rp_end = rp + pivot_row_length ; while (rp < rp_end) { col = *rp++ ; ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; DEBUG3 (("Col: %d\n", col)) ; /* clear tags used to construct pivot row pattern */ col_thickness = -Col [col].shared1.thickness ; ASSERT (col_thickness > 0) ; Col [col].shared1.thickness = col_thickness ; /* === Remove column from degree list =========================== */ cur_score = Col [col].shared2.score ; prev_col = Col [col].shared3.prev ; next_col = Col [col].shared4.degree_next ; ASSERT (cur_score >= 0) ; ASSERT (cur_score <= n_col) ; ASSERT (cur_score >= EMPTY) ; if (prev_col == EMPTY) { head [cur_score] = next_col ; } else { Col [prev_col].shared4.degree_next = next_col ; } if (next_col != EMPTY) { Col [next_col].shared3.prev = prev_col ; } /* === Scan the column ========================================== */ cp = &A [Col [col].start] ; cp_end = cp + Col [col].length ; while (cp < cp_end) { /* get a row */ row = *cp++ ; row_mark = Row [row].shared2.mark ; /* skip if dead */ if (ROW_IS_MARKED_DEAD (row_mark)) { continue ; } ASSERT (row != pivot_row) ; set_difference = row_mark - tag_mark ; /* check if the row has been seen yet */ if (set_difference < 0) { ASSERT (Row [row].shared1.degree <= max_deg) ; set_difference = Row [row].shared1.degree ; } /* subtract column thickness from this row's set difference */ set_difference -= col_thickness ; ASSERT (set_difference >= 0) ; /* absorb this row if the set difference becomes zero */ if (set_difference == 0 && aggressive) { DEBUG3 (("aggressive absorption. Row: %d\n", row)) ; KILL_ROW (row) ; } else { /* save the new mark */ Row [row].shared2.mark = set_difference + tag_mark ; } } } #ifndef NDEBUG debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2-k-pivot_row_degree, max_deg) ; #endif /* NDEBUG */ /* === Add up set differences for each column ======================= */ DEBUG3 (("** Adding set differences phase. **\n")) ; /* for each column in pivot row */ rp = &A [pivot_row_start] ; rp_end = rp + pivot_row_length ; while (rp < rp_end) { /* get a column */ col = *rp++ ; ASSERT (COL_IS_ALIVE (col) && col != pivot_col) ; hash = 0 ; cur_score = 0 ; cp = &A [Col [col].start] ; /* compact the column */ new_cp = cp ; cp_end = cp + Col [col].length ; DEBUG4 (("Adding set diffs for Col: %d.\n", col)) ; while (cp < cp_end) { /* get a row */ row = *cp++ ; ASSERT(row >= 0 && row < n_row) ; row_mark = Row [row].shared2.mark ; /* skip if dead */ if (ROW_IS_MARKED_DEAD (row_mark)) { DEBUG4 ((" Row %d, dead\n", row)) ; continue ; } DEBUG4 ((" Row %d, set diff %d\n", row, row_mark-tag_mark)); ASSERT (row_mark >= tag_mark) ; /* compact the column */ *new_cp++ = row ; /* compute hash function */ hash += row ; /* add set difference */ cur_score += row_mark - tag_mark ; /* integer overflow... */ cur_score = MIN (cur_score, n_col) ; } /* recompute the column's length */ Col [col].length = (Int) (new_cp - &A [Col [col].start]) ; /* === Further mass elimination ================================= */ if (Col [col].length == 0) { DEBUG4 (("further mass elimination. Col: %d\n", col)) ; /* nothing left but the pivot row in this column */ KILL_PRINCIPAL_COL (col) ; pivot_row_degree -= Col [col].shared1.thickness ; ASSERT (pivot_row_degree >= 0) ; /* order it */ Col [col].shared2.order = k ; /* increment order count by column thickness */ k += Col [col].shared1.thickness ; } else { /* === Prepare for supercolumn detection ==================== */ DEBUG4 (("Preparing supercol detection for Col: %d.\n", col)) ; /* save score so far */ Col [col].shared2.score = cur_score ; /* add column to hash table, for supercolumn detection */ hash %= n_col + 1 ; DEBUG4 ((" Hash = %d, n_col = %d.\n", hash, n_col)) ; ASSERT (((Int) hash) <= n_col) ; head_column = head [hash] ; if (head_column > EMPTY) { /* degree list "hash" is non-empty, use prev (shared3) of */ /* first column in degree list as head of hash bucket */ first_col = Col [head_column].shared3.headhash ; Col [head_column].shared3.headhash = col ; } else { /* degree list "hash" is empty, use head as hash bucket */ first_col = - (head_column + 2) ; head [hash] = - (col + 2) ; } Col [col].shared4.hash_next = first_col ; /* save hash function in Col [col].shared3.hash */ Col [col].shared3.hash = (Int) hash ; ASSERT (COL_IS_ALIVE (col)) ; } } /* The approximate external column degree is now computed. */ /* === Supercolumn detection ======================================== */ DEBUG3 (("** Supercolumn detection phase. **\n")) ; detect_super_cols ( #ifndef NDEBUG n_col, Row, #endif /* NDEBUG */ Col, A, head, pivot_row_start, pivot_row_length) ; /* === Kill the pivotal column ====================================== */ KILL_PRINCIPAL_COL (pivot_col) ; /* === Clear mark =================================================== */ tag_mark = clear_mark (tag_mark+max_deg+1, max_mark, n_row, Row) ; #ifndef NDEBUG DEBUG3 (("check3\n")) ; debug_mark (n_row, Row, tag_mark, max_mark) ; #endif /* NDEBUG */ /* === Finalize the new pivot row, and column scores ================ */ DEBUG3 (("** Finalize scores phase. **\n")) ; /* for each column in pivot row */ rp = &A [pivot_row_start] ; /* compact the pivot row */ new_rp = rp ; rp_end = rp + pivot_row_length ; while (rp < rp_end) { col = *rp++ ; /* skip dead columns */ if (COL_IS_DEAD (col)) { continue ; } *new_rp++ = col ; /* add new pivot row to column */ A [Col [col].start + (Col [col].length++)] = pivot_row ; /* retrieve score so far and add on pivot row's degree. */ /* (we wait until here for this in case the pivot */ /* row's degree was reduced due to mass elimination). */ cur_score = Col [col].shared2.score + pivot_row_degree ; /* calculate the max possible score as the number of */ /* external columns minus the 'k' value minus the */ /* columns thickness */ max_score = n_col - k - Col [col].shared1.thickness ; /* make the score the external degree of the union-of-rows */ cur_score -= Col [col].shared1.thickness ; /* make sure score is less or equal than the max score */ cur_score = MIN (cur_score, max_score) ; ASSERT (cur_score >= 0) ; /* store updated score */ Col [col].shared2.score = cur_score ; /* === Place column back in degree list ========================= */ ASSERT (min_score >= 0) ; ASSERT (min_score <= n_col) ; ASSERT (cur_score >= 0) ; ASSERT (cur_score <= n_col) ; ASSERT (head [cur_score] >= EMPTY) ; next_col = head [cur_score] ; Col [col].shared4.degree_next = next_col ; Col [col].shared3.prev = EMPTY ; if (next_col != EMPTY) { Col [next_col].shared3.prev = col ; } head [cur_score] = col ; /* see if this score is less than current min */ min_score = MIN (min_score, cur_score) ; } #ifndef NDEBUG debug_deg_lists (n_row, n_col, Row, Col, head, min_score, n_col2-k, max_deg) ; #endif /* NDEBUG */ /* === Resurrect the new pivot row ================================== */ if (pivot_row_degree > 0) { /* update pivot row length to reflect any cols that were killed */ /* during super-col detection and mass elimination */ Row [pivot_row].start = pivot_row_start ; Row [pivot_row].length = (Int) (new_rp - &A[pivot_row_start]) ; ASSERT (Row [pivot_row].length > 0) ; Row [pivot_row].shared1.degree = pivot_row_degree ; Row [pivot_row].shared2.mark = 0 ; /* pivot row is no longer dead */ DEBUG1 (("Resurrect Pivot_row %d deg: %d\n", pivot_row, pivot_row_degree)) ; } } /* === All principal columns have now been ordered ====================== */ return (ngarbage) ; } /* ========================================================================== */ /* === order_children ======================================================= */ /* ========================================================================== */ /* The find_ordering routine has ordered all of the principal columns (the representatives of the supercolumns). The non-principal columns have not yet been ordered. This routine orders those columns by walking up the parent tree (a column is a child of the column which absorbed it). The final permutation vector is then placed in p [0 ... n_col-1], with p [0] being the first column, and p [n_col-1] being the last. It doesn't look like it at first glance, but be assured that this routine takes time linear in the number of columns. Although not immediately obvious, the time taken by this routine is O (n_col), that is, linear in the number of columns. Not user-callable. */ PRIVATE void order_children ( /* === Parameters ======================================================= */ Int n_col, /* number of columns of A */ Colamd_Col Col [], /* of size n_col+1 */ Int p [] /* p [0 ... n_col-1] is the column permutation*/ ) { /* === Local variables ================================================== */ Int i ; /* loop counter for all columns */ Int c ; /* column index */ Int parent ; /* index of column's parent */ Int order ; /* column's order */ /* === Order each non-principal column ================================== */ for (i = 0 ; i < n_col ; i++) { /* find an un-ordered non-principal column */ ASSERT (COL_IS_DEAD (i)) ; if (!COL_IS_DEAD_PRINCIPAL (i) && Col [i].shared2.order == EMPTY) { parent = i ; /* once found, find its principal parent */ do { parent = Col [parent].shared1.parent ; } while (!COL_IS_DEAD_PRINCIPAL (parent)) ; /* now, order all un-ordered non-principal columns along path */ /* to this parent. collapse tree at the same time */ c = i ; /* get order of parent */ order = Col [parent].shared2.order ; do { ASSERT (Col [c].shared2.order == EMPTY) ; /* order this column */ Col [c].shared2.order = order++ ; /* collaps tree */ Col [c].shared1.parent = parent ; /* get immediate parent of this column */ c = Col [c].shared1.parent ; /* continue until we hit an ordered column. There are */ /* guarranteed not to be anymore unordered columns */ /* above an ordered column */ } while (Col [c].shared2.order == EMPTY) ; /* re-order the super_col parent to largest order for this group */ Col [parent].shared2.order = order ; } } /* === Generate the permutation ========================================= */ for (c = 0 ; c < n_col ; c++) { p [Col [c].shared2.order] = c ; } } /* ========================================================================== */ /* === detect_super_cols ==================================================== */ /* ========================================================================== */ /* Detects supercolumns by finding matches between columns in the hash buckets. Check amongst columns in the set A [row_start ... row_start + row_length-1]. The columns under consideration are currently *not* in the degree lists, and have already been placed in the hash buckets. The hash bucket for columns whose hash function is equal to h is stored as follows: if head [h] is >= 0, then head [h] contains a degree list, so: head [h] is the first column in degree bucket h. Col [head [h]].headhash gives the first column in hash bucket h. otherwise, the degree list is empty, and: -(head [h] + 2) is the first column in hash bucket h. For a column c in a hash bucket, Col [c].shared3.prev is NOT a "previous column" pointer. Col [c].shared3.hash is used instead as the hash number for that column. The value of Col [c].shared4.hash_next is the next column in the same hash bucket. Assuming no, or "few" hash collisions, the time taken by this routine is linear in the sum of the sizes (lengths) of each column whose score has just been computed in the approximate degree computation. Not user-callable. */ PRIVATE void detect_super_cols ( /* === Parameters ======================================================= */ #ifndef NDEBUG /* these two parameters are only needed when debugging is enabled: */ Int n_col, /* number of columns of A */ Colamd_Row Row [], /* of size n_row+1 */ #endif /* NDEBUG */ Colamd_Col Col [], /* of size n_col+1 */ Int A [], /* row indices of A */ Int head [], /* head of degree lists and hash buckets */ Int row_start, /* pointer to set of columns to check */ Int row_length /* number of columns to check */ ) { /* === Local variables ================================================== */ Int hash ; /* hash value for a column */ Int *rp ; /* pointer to a row */ Int c ; /* a column index */ Int super_c ; /* column index of the column to absorb into */ Int *cp1 ; /* column pointer for column super_c */ Int *cp2 ; /* column pointer for column c */ Int length ; /* length of column super_c */ Int prev_c ; /* column preceding c in hash bucket */ Int i ; /* loop counter */ Int *rp_end ; /* pointer to the end of the row */ Int col ; /* a column index in the row to check */ Int head_column ; /* first column in hash bucket or degree list */ Int first_col ; /* first column in hash bucket */ /* === Consider each column in the row ================================== */ rp = &A [row_start] ; rp_end = rp + row_length ; while (rp < rp_end) { col = *rp++ ; if (COL_IS_DEAD (col)) { continue ; } /* get hash number for this column */ hash = Col [col].shared3.hash ; ASSERT (hash <= n_col) ; /* === Get the first column in this hash bucket ===================== */ head_column = head [hash] ; if (head_column > EMPTY) { first_col = Col [head_column].shared3.headhash ; } else { first_col = - (head_column + 2) ; } /* === Consider each column in the hash bucket ====================== */ for (super_c = first_col ; super_c != EMPTY ; super_c = Col [super_c].shared4.hash_next) { ASSERT (COL_IS_ALIVE (super_c)) ; ASSERT (Col [super_c].shared3.hash == hash) ; length = Col [super_c].length ; /* prev_c is the column preceding column c in the hash bucket */ prev_c = super_c ; /* === Compare super_c with all columns after it ================ */ for (c = Col [super_c].shared4.hash_next ; c != EMPTY ; c = Col [c].shared4.hash_next) { ASSERT (c != super_c) ; ASSERT (COL_IS_ALIVE (c)) ; ASSERT (Col [c].shared3.hash == hash) ; /* not identical if lengths or scores are different */ if (Col [c].length != length || Col [c].shared2.score != Col [super_c].shared2.score) { prev_c = c ; continue ; } /* compare the two columns */ cp1 = &A [Col [super_c].start] ; cp2 = &A [Col [c].start] ; for (i = 0 ; i < length ; i++) { /* the columns are "clean" (no dead rows) */ ASSERT (ROW_IS_ALIVE (*cp1)) ; ASSERT (ROW_IS_ALIVE (*cp2)) ; /* row indices will same order for both supercols, */ /* no gather scatter nessasary */ if (*cp1++ != *cp2++) { break ; } } /* the two columns are different if the for-loop "broke" */ if (i != length) { prev_c = c ; continue ; } /* === Got it! two columns are identical =================== */ ASSERT (Col [c].shared2.score == Col [super_c].shared2.score) ; Col [super_c].shared1.thickness += Col [c].shared1.thickness ; Col [c].shared1.parent = super_c ; KILL_NON_PRINCIPAL_COL (c) ; /* order c later, in order_children() */ Col [c].shared2.order = EMPTY ; /* remove c from hash bucket */ Col [prev_c].shared4.hash_next = Col [c].shared4.hash_next ; } } /* === Empty this hash bucket ======================================= */ if (head_column > EMPTY) { /* corresponding degree list "hash" is not empty */ Col [head_column].shared3.headhash = EMPTY ; } else { /* corresponding degree list "hash" is empty */ head [hash] = EMPTY ; } } } /* ========================================================================== */ /* === garbage_collection =================================================== */ /* ========================================================================== */ /* Defragments and compacts columns and rows in the workspace A. Used when all avaliable memory has been used while performing row merging. Returns the index of the first free position in A, after garbage collection. The time taken by this routine is linear is the size of the array A, which is itself linear in the number of nonzeros in the input matrix. Not user-callable. */ PRIVATE Int garbage_collection /* returns the new value of pfree */ ( /* === Parameters ======================================================= */ Int n_row, /* number of rows */ Int n_col, /* number of columns */ Colamd_Row Row [], /* row info */ Colamd_Col Col [], /* column info */ Int A [], /* A [0 ... Alen-1] holds the matrix */ Int *pfree /* &A [0] ... pfree is in use */ ) { /* === Local variables ================================================== */ Int *psrc ; /* source pointer */ Int *pdest ; /* destination pointer */ Int j ; /* counter */ Int r ; /* a row index */ Int c ; /* a column index */ Int length ; /* length of a row or column */ #ifndef NDEBUG Int debug_rows ; DEBUG2 (("Defrag..\n")) ; for (psrc = &A[0] ; psrc < pfree ; psrc++) ASSERT (*psrc >= 0) ; debug_rows = 0 ; #endif /* NDEBUG */ /* === Defragment the columns =========================================== */ pdest = &A[0] ; for (c = 0 ; c < n_col ; c++) { if (COL_IS_ALIVE (c)) { psrc = &A [Col [c].start] ; /* move and compact the column */ ASSERT (pdest <= psrc) ; Col [c].start = (Int) (pdest - &A [0]) ; length = Col [c].length ; for (j = 0 ; j < length ; j++) { r = *psrc++ ; if (ROW_IS_ALIVE (r)) { *pdest++ = r ; } } Col [c].length = (Int) (pdest - &A [Col [c].start]) ; } } /* === Prepare to defragment the rows =================================== */ for (r = 0 ; r < n_row ; r++) { if (ROW_IS_DEAD (r) || (Row [r].length == 0)) { /* This row is already dead, or is of zero length. Cannot compact * a row of zero length, so kill it. NOTE: in the current version, * there are no zero-length live rows. Kill the row (for the first * time, or again) just to be safe. */ KILL_ROW (r) ; } else { /* save first column index in Row [r].shared2.first_column */ psrc = &A [Row [r].start] ; Row [r].shared2.first_column = *psrc ; ASSERT (ROW_IS_ALIVE (r)) ; /* flag the start of the row with the one's complement of row */ *psrc = ONES_COMPLEMENT (r) ; #ifndef NDEBUG debug_rows++ ; #endif /* NDEBUG */ } } /* === Defragment the rows ============================================== */ psrc = pdest ; while (psrc < pfree) { /* find a negative number ... the start of a row */ if (*psrc++ < 0) { psrc-- ; /* get the row index */ r = ONES_COMPLEMENT (*psrc) ; ASSERT (r >= 0 && r < n_row) ; /* restore first column index */ *psrc = Row [r].shared2.first_column ; ASSERT (ROW_IS_ALIVE (r)) ; ASSERT (Row [r].length > 0) ; /* move and compact the row */ ASSERT (pdest <= psrc) ; Row [r].start = (Int) (pdest - &A [0]) ; length = Row [r].length ; for (j = 0 ; j < length ; j++) { c = *psrc++ ; if (COL_IS_ALIVE (c)) { *pdest++ = c ; } } Row [r].length = (Int) (pdest - &A [Row [r].start]) ; ASSERT (Row [r].length > 0) ; #ifndef NDEBUG debug_rows-- ; #endif /* NDEBUG */ } } /* ensure we found all the rows */ ASSERT (debug_rows == 0) ; /* === Return the new value of pfree ==================================== */ return ((Int) (pdest - &A [0])) ; } /* ========================================================================== */ /* === clear_mark =========================================================== */ /* ========================================================================== */ /* Clears the Row [].shared2.mark array, and returns the new tag_mark. Return value is the new tag_mark. Not user-callable. */ PRIVATE Int clear_mark /* return the new value for tag_mark */ ( /* === Parameters ======================================================= */ Int tag_mark, /* new value of tag_mark */ Int max_mark, /* max allowed value of tag_mark */ Int n_row, /* number of rows in A */ Colamd_Row Row [] /* Row [0 ... n_row-1].shared2.mark is set to zero */ ) { /* === Local variables ================================================== */ Int r ; if (tag_mark <= 0 || tag_mark >= max_mark) { for (r = 0 ; r < n_row ; r++) { if (ROW_IS_ALIVE (r)) { Row [r].shared2.mark = 0 ; } } tag_mark = 1 ; } return (tag_mark) ; } /* ========================================================================== */ /* === print_report ========================================================= */ /* ========================================================================== */ PRIVATE void print_report ( char *method, Int stats [COLAMD_STATS] ) { Int i1, i2, i3 ; PRINTF (("\n%s version %d.%d, %s: ", method, COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION, COLAMD_DATE)) ; if (!stats) { PRINTF (("No statistics available.\n")) ; return ; } i1 = stats [COLAMD_INFO1] ; i2 = stats [COLAMD_INFO2] ; i3 = stats [COLAMD_INFO3] ; if (stats [COLAMD_STATUS] >= 0) { PRINTF (("OK. ")) ; } else { PRINTF (("ERROR. ")) ; } switch (stats [COLAMD_STATUS]) { case COLAMD_OK_BUT_JUMBLED: PRINTF(("Matrix has unsorted or duplicate row indices.\n")) ; PRINTF(("%s: number of duplicate or out-of-order row indices: %d\n", method, i3)) ; PRINTF(("%s: last seen duplicate or out-of-order row index: %d\n", method, INDEX (i2))) ; PRINTF(("%s: last seen in column: %d", method, INDEX (i1))) ; /* no break - fall through to next case instead */ case COLAMD_OK: PRINTF(("\n")) ; PRINTF(("%s: number of dense or empty rows ignored: %d\n", method, stats [COLAMD_DENSE_ROW])) ; PRINTF(("%s: number of dense or empty columns ignored: %d\n", method, stats [COLAMD_DENSE_COL])) ; PRINTF(("%s: number of garbage collections performed: %d\n", method, stats [COLAMD_DEFRAG_COUNT])) ; break ; case COLAMD_ERROR_A_not_present: PRINTF(("Array A (row indices of matrix) not present.\n")) ; break ; case COLAMD_ERROR_p_not_present: PRINTF(("Array p (column pointers for matrix) not present.\n")) ; break ; case COLAMD_ERROR_nrow_negative: PRINTF(("Invalid number of rows (%d).\n", i1)) ; break ; case COLAMD_ERROR_ncol_negative: PRINTF(("Invalid number of columns (%d).\n", i1)) ; break ; case COLAMD_ERROR_nnz_negative: PRINTF(("Invalid number of nonzero entries (%d).\n", i1)) ; break ; case COLAMD_ERROR_p0_nonzero: PRINTF(("Invalid column pointer, p [0] = %d, must be zero.\n", i1)); break ; case COLAMD_ERROR_A_too_small: PRINTF(("Array A too small.\n")) ; PRINTF((" Need Alen >= %d, but given only Alen = %d.\n", i1, i2)) ; break ; case COLAMD_ERROR_col_length_negative: PRINTF (("Column %d has a negative number of nonzero entries (%d).\n", INDEX (i1), i2)) ; break ; case COLAMD_ERROR_row_index_out_of_bounds: PRINTF (("Row index (row %d) out of bounds (%d to %d) in column %d.\n", INDEX (i2), INDEX (0), INDEX (i3-1), INDEX (i1))) ; break ; case COLAMD_ERROR_out_of_memory: PRINTF(("Out of memory.\n")) ; break ; /* v2.4: internal-error case deleted */ } } /* ========================================================================== */ /* === colamd debugging routines ============================================ */ /* ========================================================================== */ /* When debugging is disabled, the remainder of this file is ignored. */ #ifndef NDEBUG /* ========================================================================== */ /* === debug_structures ===================================================== */ /* ========================================================================== */ /* At this point, all empty rows and columns are dead. All live columns are "clean" (containing no dead rows) and simplicial (no supercolumns yet). Rows may contain dead columns, but all live rows contain at least one live column. */ PRIVATE void debug_structures ( /* === Parameters ======================================================= */ Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int A [], Int n_col2 ) { /* === Local variables ================================================== */ Int i ; Int c ; Int *cp ; Int *cp_end ; Int len ; Int score ; Int r ; Int *rp ; Int *rp_end ; Int deg ; /* === Check A, Row, and Col ============================================ */ for (c = 0 ; c < n_col ; c++) { if (COL_IS_ALIVE (c)) { len = Col [c].length ; score = Col [c].shared2.score ; DEBUG4 (("initial live col %5d %5d %5d\n", c, len, score)) ; ASSERT (len > 0) ; ASSERT (score >= 0) ; ASSERT (Col [c].shared1.thickness == 1) ; cp = &A [Col [c].start] ; cp_end = cp + len ; while (cp < cp_end) { r = *cp++ ; ASSERT (ROW_IS_ALIVE (r)) ; } } else { i = Col [c].shared2.order ; ASSERT (i >= n_col2 && i < n_col) ; } } for (r = 0 ; r < n_row ; r++) { if (ROW_IS_ALIVE (r)) { i = 0 ; len = Row [r].length ; deg = Row [r].shared1.degree ; ASSERT (len > 0) ; ASSERT (deg > 0) ; rp = &A [Row [r].start] ; rp_end = rp + len ; while (rp < rp_end) { c = *rp++ ; if (COL_IS_ALIVE (c)) { i++ ; } } ASSERT (i > 0) ; } } } /* ========================================================================== */ /* === debug_deg_lists ====================================================== */ /* ========================================================================== */ /* Prints the contents of the degree lists. Counts the number of columns in the degree list and compares it to the total it should have. Also checks the row degrees. */ PRIVATE void debug_deg_lists ( /* === Parameters ======================================================= */ Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int head [], Int min_score, Int should, Int max_deg ) { /* === Local variables ================================================== */ Int deg ; Int col ; Int have ; Int row ; /* === Check the degree lists =========================================== */ if (n_col > 10000 && colamd_debug <= 0) { return ; } have = 0 ; DEBUG4 (("Degree lists: %d\n", min_score)) ; for (deg = 0 ; deg <= n_col ; deg++) { col = head [deg] ; if (col == EMPTY) { continue ; } DEBUG4 (("%d:", deg)) ; while (col != EMPTY) { DEBUG4 ((" %d", col)) ; have += Col [col].shared1.thickness ; ASSERT (COL_IS_ALIVE (col)) ; col = Col [col].shared4.degree_next ; } DEBUG4 (("\n")) ; } DEBUG4 (("should %d have %d\n", should, have)) ; ASSERT (should == have) ; /* === Check the row degrees ============================================ */ if (n_row > 10000 && colamd_debug <= 0) { return ; } for (row = 0 ; row < n_row ; row++) { if (ROW_IS_ALIVE (row)) { ASSERT (Row [row].shared1.degree <= max_deg) ; } } } /* ========================================================================== */ /* === debug_mark =========================================================== */ /* ========================================================================== */ /* Ensures that the tag_mark is less that the maximum and also ensures that each entry in the mark array is less than the tag mark. */ PRIVATE void debug_mark ( /* === Parameters ======================================================= */ Int n_row, Colamd_Row Row [], Int tag_mark, Int max_mark ) { /* === Local variables ================================================== */ Int r ; /* === Check the Row marks ============================================== */ ASSERT (tag_mark > 0 && tag_mark <= max_mark) ; if (n_row > 10000 && colamd_debug <= 0) { return ; } for (r = 0 ; r < n_row ; r++) { ASSERT (Row [r].shared2.mark < tag_mark) ; } } /* ========================================================================== */ /* === debug_matrix ========================================================= */ /* ========================================================================== */ /* Prints out the contents of the columns and the rows. */ PRIVATE void debug_matrix ( /* === Parameters ======================================================= */ Int n_row, Int n_col, Colamd_Row Row [], Colamd_Col Col [], Int A [] ) { /* === Local variables ================================================== */ Int r ; Int c ; Int *rp ; Int *rp_end ; Int *cp ; Int *cp_end ; /* === Dump the rows and columns of the matrix ========================== */ if (colamd_debug < 3) { return ; } DEBUG3 (("DUMP MATRIX:\n")) ; for (r = 0 ; r < n_row ; r++) { DEBUG3 (("Row %d alive? %d\n", r, ROW_IS_ALIVE (r))) ; if (ROW_IS_DEAD (r)) { continue ; } DEBUG3 (("start %d length %d degree %d\n", Row [r].start, Row [r].length, Row [r].shared1.degree)) ; rp = &A [Row [r].start] ; rp_end = rp + Row [r].length ; while (rp < rp_end) { c = *rp++ ; DEBUG4 ((" %d col %d\n", COL_IS_ALIVE (c), c)) ; } } for (c = 0 ; c < n_col ; c++) { DEBUG3 (("Col %d alive? %d\n", c, COL_IS_ALIVE (c))) ; if (COL_IS_DEAD (c)) { continue ; } DEBUG3 (("start %d length %d shared1 %d shared2 %d\n", Col [c].start, Col [c].length, Col [c].shared1.thickness, Col [c].shared2.score)) ; cp = &A [Col [c].start] ; cp_end = cp + Col [c].length ; while (cp < cp_end) { r = *cp++ ; DEBUG4 ((" %d row %d\n", ROW_IS_ALIVE (r), r)) ; } } } PRIVATE void colamd_get_debug ( char *method ) { FILE *f ; colamd_debug = 0 ; /* no debug printing */ f = fopen ("debug", "r") ; if (f == (FILE *) NULL) { colamd_debug = 0 ; } else { fscanf (f, "%d", &colamd_debug) ; fclose (f) ; } DEBUG0 (("%s: debug version, D = %d (THIS WILL BE SLOW!)\n", method, colamd_debug)) ; } #endif /* NDEBUG */ glpk-4.52.1/src/colamd/colamd.h0000644000062000006210000000411112175147600015354 0ustar maomkpasswd/* colamd.h */ /* Written by Andrew Makhorin . */ #ifndef COLAMD_H #define COLAMD_H #define _GLPSTD_STDIO #include "env.h" #define COLAMD_DATE "Nov 1, 2007" #define COLAMD_VERSION_CODE(main, sub) ((main) * 1000 + (sub)) #define COLAMD_MAIN_VERSION 2 #define COLAMD_SUB_VERSION 7 #define COLAMD_SUBSUB_VERSION 1 #define COLAMD_VERSION \ COLAMD_VERSION_CODE(COLAMD_MAIN_VERSION, COLAMD_SUB_VERSION) #define COLAMD_KNOBS 20 #define COLAMD_STATS 20 #define COLAMD_DENSE_ROW 0 #define COLAMD_DENSE_COL 1 #define COLAMD_AGGRESSIVE 2 #define COLAMD_DEFRAG_COUNT 2 #define COLAMD_STATUS 3 #define COLAMD_INFO1 4 #define COLAMD_INFO2 5 #define COLAMD_INFO3 6 #define COLAMD_OK (0) #define COLAMD_OK_BUT_JUMBLED (1) #define COLAMD_ERROR_A_not_present (-1) #define COLAMD_ERROR_p_not_present (-2) #define COLAMD_ERROR_nrow_negative (-3) #define COLAMD_ERROR_ncol_negative (-4) #define COLAMD_ERROR_nnz_negative (-5) #define COLAMD_ERROR_p0_nonzero (-6) #define COLAMD_ERROR_A_too_small (-7) #define COLAMD_ERROR_col_length_negative (-8) #define COLAMD_ERROR_row_index_out_of_bounds (-9) #define COLAMD_ERROR_out_of_memory (-10) #define COLAMD_ERROR_internal_error (-999) #define colamd_recommended _glp_colamd_recommended size_t colamd_recommended(int nnz, int n_row, int n_col); #define colamd_set_defaults _glp_colamd_set_defaults void colamd_set_defaults(double knobs [COLAMD_KNOBS]); #define colamd _glp_colamd int colamd(int n_row, int n_col, int Alen, int A[], int p[], double knobs[COLAMD_KNOBS], int stats[COLAMD_STATS]); #define symamd _glp_symamd int symamd(int n, int A[], int p[], int perm[], double knobs[COLAMD_KNOBS], int stats[COLAMD_STATS], void *(*allocate)(size_t, size_t), void(*release)(void *)); #define colamd_report _glp_colamd_report void colamd_report(int stats[COLAMD_STATS]); #define symamd_report _glp_symamd_report void symamd_report(int stats[COLAMD_STATS]); #define colamd_printf xprintf #endif /* eof */ glpk-4.52.1/src/colamd/COPYING0000644000062000006210000006362512175147600015016 0ustar maomkpasswd GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is 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. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! glpk-4.52.1/src/colamd/README0000644000062000006210000001027412175147600014633 0ustar maomkpasswdNOTE: Files in this subdirectory are NOT part of the GLPK package, but are used with GLPK. The original code was modified according to GLPK requirements by Andrew Makhorin . ************************************************************************ COLAMD/SYMAMD Version 2.7, Copyright (C) 1998-2007, Timothy A. Davis, All Rights Reserved. Description: colamd: an approximate minimum degree column ordering algorithm, for LU factorization of symmetric or unsymmetric matrices, QR factorization, least squares, interior point methods for linear programming problems, and other related problems. symamd: an approximate minimum degree ordering algorithm for Cholesky factorization of symmetric matrices. Purpose: Colamd computes a permutation Q such that the Cholesky factorization of (AQ)'(AQ) has less fill-in and requires fewer floating point operations than A'A. This also provides a good ordering for sparse partial pivoting methods, P(AQ) = LU, where Q is computed prior to numerical factorization, and P is computed during numerical factorization via conventional partial pivoting with row interchanges. Colamd is the column ordering method used in SuperLU, part of the ScaLAPACK library. It is also available as built-in function in MATLAB Version 6, available from MathWorks, Inc. (http://www.mathworks.com). This routine can be used in place of colmmd in MATLAB. Symamd computes a permutation P of a symmetric matrix A such that the Cholesky factorization of PAP' has less fill-in and requires fewer floating point operations than A. Symamd constructs a matrix M such that M'M has the same nonzero pattern of A, and then orders the columns of M using colmmd. The column ordering of M is then returned as the row and column ordering P of A. Authors: The authors of the code itself are Stefan I. Larimore and Timothy A. Davis (davis at cise.ufl.edu), University of Florida. The algorithm was developed in collaboration with John Gilbert, Xerox PARC, and Esmond Ng, Oak Ridge National Laboratory. Acknowledgements: This work was supported by the National Science Foundation, under grants DMS-9504974 and DMS-9803599. License: This library is 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. 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 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. COLAMD is also available under alternate licenses, contact T. Davis for details. Availability: The colamd/symamd library is available at: http://www.cise.ufl.edu/research/sparse/colamd/ References: T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, An approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 353-376, 2004. T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836: COLAMD, an approximate column minimum degree ordering algorithm, ACM Transactions on Mathematical Software, vol. 30, no. 3., pp. 377-380, 2004. glpk-4.52.1/src/env/0000755000062000006210000000000012175147600013300 5ustar maomkpasswdglpk-4.52.1/src/env/alloc.c0000644000062000006210000002054012175147600014537 0ustar maomkpasswd/* alloc.c (dynamic memory allocation) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #define ALIGN 16 /* some processors need data to be properly aligned, so this macro * defines the alignment boundary, in bytes, provided by glpk memory * allocation routines; looks like 16-byte alignment boundary is * sufficient for all 32- and 64-bit platforms (8-byte boundary is not * sufficient for some 64-bit platforms because of jmp_buf) */ #define MBD_SIZE (((sizeof(MBD) + (ALIGN - 1)) / ALIGN) * ALIGN) /* size of memory block descriptor, in bytes, rounded up to multiple * of the alignment boundary */ /*********************************************************************** * dma - dynamic memory allocation (basic routine) * * This routine performs dynamic memory allocation. It is similar to * the standard realloc function, however, it provides every allocated * memory block with a descriptor, which is used for sanity checks on * reallocating/freeing previously allocated memory blocks as well as * for book-keeping the memory usage statistics. */ static void *dma(const char *func, void *ptr, size_t size) { ENV *env = get_env_ptr(); MBD *mbd; if (ptr == NULL) { /* new memory block will be allocated */ mbd = NULL; } else { /* allocated memory block will be reallocated or freed */ /* get pointer to the block descriptor */ mbd = (MBD *)((char *)ptr - MBD_SIZE); /* make sure that the block descriptor is valid */ if (mbd->self != mbd) xerror("%s: ptr = %p; invalid pointer\n", func, ptr); /* remove the block from the linked list */ mbd->self = NULL; if (mbd->prev == NULL) env->mem_ptr = mbd->next; else mbd->prev->next = mbd->next; if (mbd->next == NULL) ; else mbd->next->prev = mbd->prev; /* decrease usage counts */ if (!(env->mem_count >= 1 && env->mem_total >= mbd->size)) xerror("%s: memory allocation error\n", func); env->mem_count--; env->mem_total -= mbd->size; if (size == 0) { /* free the memory block */ free(mbd); return NULL; } } /* allocate/reallocate memory block */ if (size > SIZE_T_MAX - MBD_SIZE) xerror("%s: block too large\n", func); size += MBD_SIZE; if (size > env->mem_limit - env->mem_total) xerror("%s: memory allocation limit exceeded\n", func); if (env->mem_count == INT_MAX) xerror("%s: too many memory blocks allocated\n", func); mbd = (mbd == NULL ? malloc(size) : realloc(mbd, size)); if (mbd == NULL) xerror("%s: no memory available\n", func); /* setup the block descriptor */ mbd->size = size; mbd->self = mbd; mbd->prev = NULL; mbd->next = env->mem_ptr; /* add the block to the beginning of the linked list */ if (mbd->next != NULL) mbd->next->prev = mbd; env->mem_ptr = mbd; /* increase usage counts */ env->mem_count++; if (env->mem_cpeak < env->mem_count) env->mem_cpeak = env->mem_count; env->mem_total += size; if (env->mem_tpeak < env->mem_total) env->mem_tpeak = env->mem_total; return (char *)mbd + MBD_SIZE; } /*********************************************************************** * NAME * * glp_alloc - allocate memory block * * SYNOPSIS * * void *glp_alloc(int n, int size); * * DESCRIPTION * * The routine glp_alloc allocates a memory block of n * size bytes * long. * * Note that being allocated the memory block contains arbitrary data * (not binary zeros!). * * RETURNS * * The routine glp_alloc returns a pointer to the block allocated. * To free this block the routine glp_free (not free!) must be used. */ void *glp_alloc(int n, int size) { if (n < 1) xerror("glp_alloc: n = %d; invalid parameter\n", n); if (size < 1) xerror("glp_alloc: size = %d; invalid parameter\n", size); if ((size_t)n > SIZE_T_MAX / (size_t)size) xerror("glp_alloc: n = %d, size = %d; block too large\n", n, size); return dma("glp_alloc", NULL, (size_t)n * (size_t)size); } /**********************************************************************/ void *glp_realloc(void *ptr, int n, int size) { /* reallocate memory block */ if (ptr == NULL) xerror("glp_realloc: ptr = %p; invalid pointer\n", ptr); if (n < 1) xerror("glp_realloc: n = %d; invalid parameter\n", n); if (size < 1) xerror("glp_realloc: size = %d; invalid parameter\n", size); if ((size_t)n > SIZE_T_MAX / (size_t)size) xerror("glp_realloc: n = %d, size = %d; block too large\n", n, size); return dma("glp_realloc", ptr, (size_t)n * (size_t)size); } /*********************************************************************** * NAME * * glp_free - free (deallocate) memory block * * SYNOPSIS * * void glp_free(void *ptr); * * DESCRIPTION * * The routine glp_free frees (deallocates) a memory block pointed to * by ptr, which was previuosly allocated by the routine glp_alloc or * reallocated by the routine glp_realloc. */ void glp_free(void *ptr) { if (ptr == NULL) xerror("glp_free: ptr = %p; invalid pointer\n", ptr); dma("glp_free", ptr, 0); return; } /*********************************************************************** * NAME * * glp_mem_limit - set memory usage limit * * SYNOPSIS * * void glp_mem_limit(int limit); * * DESCRIPTION * * The routine glp_mem_limit limits the amount of memory available for * dynamic allocation (in GLPK routines) to limit megabytes. */ void glp_mem_limit(int limit) { ENV *env = get_env_ptr(); if (limit < 1) xerror("glp_mem_limit: limit = %d; invalid parameter\n", limit); if ((size_t)limit <= (SIZE_T_MAX >> 20)) env->mem_limit = (size_t)limit << 20; else env->mem_limit = SIZE_T_MAX; return; } /*********************************************************************** * NAME * * glp_mem_usage - get memory usage information * * SYNOPSIS * * void glp_mem_usage(int *count, int *cpeak, size_t *total, * size_t *tpeak); * * DESCRIPTION * * The routine glp_mem_usage reports some information about utilization * of the memory by GLPK routines. Information is stored to locations * specified by corresponding parameters (see below). Any parameter can * be specified as NULL, in which case its value is not stored. * * *count is the number of the memory blocks currently allocated by the * routines glp_malloc and glp_calloc (one call to glp_malloc or * glp_calloc results in allocating one memory block). * * *cpeak is the peak value of *count reached since the initialization * of the GLPK library environment. * * *total is the total amount, in bytes, of the memory blocks currently * allocated by the routines glp_malloc and glp_calloc. * * *tpeak is the peak value of *total reached since the initialization * of the GLPK library envirionment. */ void glp_mem_usage(int *count, int *cpeak, size_t *total, size_t *tpeak) { ENV *env = get_env_ptr(); if (count != NULL) *count = env->mem_count; if (cpeak != NULL) *cpeak = env->mem_cpeak; if (total != NULL) *total = env->mem_total; if (tpeak != NULL) *tpeak = env->mem_tpeak; return; } /* eof */ glpk-4.52.1/src/env/env.c0000644000062000006210000001573612175147600014250 0ustar maomkpasswd/* env.c (GLPK environment initialization/termination) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpk.h" #include "env.h" /*********************************************************************** * NAME * * glp_init_env - initialize GLPK environment * * SYNOPSIS * * int glp_init_env(void); * * DESCRIPTION * * The routine glp_init_env initializes the GLPK environment. Normally * the application program does not need to call this routine, because * it is called automatically on the first call to any API routine. * * RETURNS * * The routine glp_init_env returns one of the following codes: * * 0 - initialization successful; * 1 - environment has been already initialized; * 2 - initialization failed (insufficient memory); * 3 - initialization failed (unsupported programming model). */ int glp_init_env(void) { ENV *env; int ok; /* check if the programming model is supported */ ok = (CHAR_BIT == 8 && sizeof(char) == 1 && sizeof(short) == 2 && sizeof(int) == 4 && (sizeof(void *) == 4 || sizeof(void *) == 8)); if (!ok) return 3; /* check if the environment is already initialized */ if (tls_get_ptr() != NULL) return 1; /* allocate and initialize the environment block */ env = malloc(sizeof(ENV)); if (env == NULL) return 2; memset(env, 0, sizeof(ENV)); sprintf(env->version, "%d.%d", GLP_MAJOR_VERSION, GLP_MINOR_VERSION); env->self = env; env->term_buf = malloc(TBUF_SIZE); if (env->term_buf == NULL) { free(env); return 2; } env->term_out = GLP_ON; env->term_hook = NULL; env->term_info = NULL; env->tee_file = NULL; env->err_file = NULL; env->err_line = 0; env->err_hook = NULL; env->err_info = NULL; env->mem_limit = SIZE_T_MAX; env->mem_ptr = NULL; env->mem_count = env->mem_cpeak = 0; env->mem_total = env->mem_tpeak = 0; env->h_odbc = env->h_mysql = NULL; /* save pointer to the environment block */ tls_set_ptr(env); /* initialization successful */ return 0; } /*********************************************************************** * NAME * * get_env_ptr - retrieve pointer to environment block * * SYNOPSIS * * #include "env.h" * ENV *get_env_ptr(void); * * DESCRIPTION * * The routine get_env_ptr retrieves and returns a pointer to the GLPK * environment block. * * If the GLPK environment has not been initialized yet, the routine * performs initialization. If initialization fails, the routine prints * an error message to stderr and terminates the program. * * RETURNS * * The routine returns a pointer to the environment block. */ ENV *get_env_ptr(void) { ENV *env = tls_get_ptr(); /* check if the environment has been initialized */ if (env == NULL) { /* not initialized yet; perform initialization */ if (glp_init_env() != 0) { /* initialization failed; display an error message */ fprintf(stderr, "GLPK initialization failed\n"); fflush(stderr); /* and abnormally terminate the program */ abort(); } /* initialization successful; retrieve the pointer */ env = tls_get_ptr(); } /* check if the environment block is valid */ if (env->self != env) { fprintf(stderr, "Invalid GLPK environment\n"); fflush(stderr); abort(); } return env; } /*********************************************************************** * NAME * * glp_version - determine library version * * SYNOPSIS * * const char *glp_version(void); * * RETURNS * * The routine glp_version returns a pointer to a null-terminated * character string, which specifies the version of the GLPK library in * the form "X.Y", where X is the major version number, and Y is the * minor version number, for example, "4.16". */ const char *glp_version(void) { ENV *env = get_env_ptr(); return env->version; } /*********************************************************************** * NAME * * glp_free_env - free GLPK environment * * SYNOPSIS * * int glp_free_env(void); * * DESCRIPTION * * The routine glp_free_env frees all resources used by GLPK routines * (memory blocks, etc.) which are currently still in use. * * Normally the application program does not need to call this routine, * because GLPK routines always free all unused resources. However, if * the application program even has deleted all problem objects, there * will be several memory blocks still allocated for the library needs. * For some reasons the application program may want GLPK to free this * memory, in which case it should call glp_free_env. * * Note that a call to glp_free_env invalidates all problem objects as * if no GLPK routine were called. * * RETURNS * * 0 - termination successful; * 1 - environment is inactive (was not initialized). */ int glp_free_env(void) { ENV *env = tls_get_ptr(); MBD *desc; /* check if the environment is active */ if (env == NULL) return 1; /* check if the environment block is valid */ if (env->self != env) { fprintf(stderr, "Invalid GLPK environment\n"); fflush(stderr); abort(); } /* close handles to shared libraries */ if (env->h_odbc != NULL) xdlclose(env->h_odbc); if (env->h_mysql != NULL) xdlclose(env->h_mysql); /* free memory blocks which are still allocated */ while (env->mem_ptr != NULL) { desc = env->mem_ptr; env->mem_ptr = desc->next; free(desc); } /* close text file used for copying terminal output */ if (env->tee_file != NULL) fclose(env->tee_file); /* invalidate the environment block */ env->self = NULL; /* free memory allocated to the environment block */ free(env->term_buf); free(env); /* reset a pointer to the environment block */ tls_set_ptr(NULL); /* termination successful */ return 0; } /* eof */ glpk-4.52.1/src/env/env.h0000644000062000006210000001474412175147600014253 0ustar maomkpasswd/* env.h (GLPK environment) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef ENV_H #define ENV_H #include "stdc.h" typedef struct ENV ENV; typedef struct MBD MBD; #define SIZE_T_MAX (~(size_t)0) /* largest value of size_t type */ #define TBUF_SIZE 4096 /* terminal output buffer size, in bytes */ /* enable/disable flag: */ #define GLP_ON 1 #define GLP_OFF 0 struct ENV { /* GLPK environment block */ char version[7+1]; /* version string returned by the routine glp_version */ ENV *self; /* pointer to this block to check its validity */ /*--------------------------------------------------------------*/ /* terminal output */ char *term_buf; /* char term_buf[TBUF_SIZE]; */ /* terminal output buffer */ int term_out; /* flag to enable/disable terminal output */ int (*term_hook)(void *info, const char *s); /* user-defined routine to intercept terminal output */ void *term_info; /* transit pointer (cookie) passed to the routine term_hook */ FILE *tee_file; /* output stream used to copy terminal output */ /*--------------------------------------------------------------*/ /* error handling */ const char *err_file; /* value of the __FILE__ macro passed to glp_error */ int err_line; /* value of the __LINE__ macro passed to glp_error */ void (*err_hook)(void *info); /* user-defined routine to intercept abnormal termination */ void *err_info; /* transit pointer (cookie) passed to the routine err_hook */ /*--------------------------------------------------------------*/ /* dynamic memory allocation */ size_t mem_limit; /* maximal amount of memory, in bytes, available for dynamic allocation */ MBD *mem_ptr; /* pointer to the linked list of allocated memory blocks */ int mem_count; /* total number of currently allocated memory blocks */ int mem_cpeak; /* peak value of mem_count */ size_t mem_total; /* total amount of currently allocated memory, in bytes; it is the sum of the size field over all memory block descriptors */ size_t mem_tpeak; /* peak value of mem_total */ /*--------------------------------------------------------------*/ /* shared libraries support (optional) */ void *h_odbc; /* handle to ODBC shared library */ void *h_mysql; /* handle to MySQL shared library */ }; struct MBD { /* memory block descriptor */ size_t size; /* size of block, in bytes, including descriptor */ MBD *self; /* pointer to this descriptor to check its validity */ MBD *prev; /* pointer to previous memory block descriptor */ MBD *next; /* pointer to next memory block descriptor */ }; #define get_env_ptr _glp_get_env_ptr ENV *get_env_ptr(void); /* retrieve pointer to environment block */ #define tls_set_ptr _glp_tls_set_ptr void tls_set_ptr(void *ptr); /* store global pointer in TLS */ #define tls_get_ptr _glp_tls_get_ptr void *tls_get_ptr(void); /* retrieve global pointer from TLS */ #define xputs glp_puts void glp_puts(const char *s); /* write string on terminal */ #define xprintf glp_printf void glp_printf(const char *fmt, ...); /* write formatted output on terminal */ #define xvprintf glp_vprintf void glp_vprintf(const char *fmt, va_list arg); /* write formatted output on terminal */ int glp_term_out(int flag); /* enable/disable terminal output */ void glp_term_hook(int (*func)(void *info, const char *s), void *info); /* install hook to intercept terminal output */ int glp_open_tee(const char *fname); /* start copying terminal output to text file */ int glp_close_tee(void); /* stop copying terminal output to text file */ #ifndef GLP_ERRFUNC_DEFINED #define GLP_ERRFUNC_DEFINED typedef void (*glp_errfunc)(const char *fmt, ...); #endif #define xerror glp_error_(__FILE__, __LINE__) glp_errfunc glp_error_(const char *file, int line); /* display fatal error message and terminate execution */ #define xassert(expr) \ ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1))) void glp_assert_(const char *expr, const char *file, int line); /* check for logical condition */ void glp_error_hook(void (*func)(void *info), void *info); /* install hook to intercept abnormal termination */ #define xmalloc(size) glp_alloc(1, size) /* allocate memory block (obsolete) */ #define xcalloc(n, size) glp_alloc(n, size) /* allocate memory block (obsolete) */ #define xalloc(n, size) glp_alloc(n, size) #define talloc(n, type) ((type *)glp_alloc(n, sizeof(type))) void *glp_alloc(int n, int size); /* allocate memory block */ #define xrealloc(ptr, n, size) glp_realloc(ptr, n, size) #define trealloc(ptr, n, type) ((type *)glp_realloc(ptr, n, \ sizeof(type))) void *glp_realloc(void *ptr, int n, int size); /* reallocate memory block */ #define xfree(ptr) glp_free(ptr) #define tfree(ptr) glp_free(ptr) void glp_free(void *ptr); /* free memory block */ void glp_mem_limit(int limit); /* set memory usage limit */ void glp_mem_usage(int *count, int *cpeak, size_t *total, size_t *tpeak); /* get memory usage information */ #define xtime glp_time double glp_time(void); /* determine current universal time */ #define xdifftime glp_difftime double glp_difftime(double t1, double t0); /* compute difference between two time values */ #define xdlopen _glp_xdlopen void *xdlopen(const char *module); #define xdlsym _glp_xdlsym void *xdlsym(void *h, const char *symbol); #define xdlclose _glp_xdlclose void xdlclose(void *h); #endif /* eof */ glpk-4.52.1/src/env/error.c0000644000062000006210000000743112175147600014602 0ustar maomkpasswd/* error.c (error handling) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" /*********************************************************************** * NAME * * glp_error - display fatal error message and terminate execution * * SYNOPSIS * * void glp_error(const char *fmt, ...); * * DESCRIPTION * * The routine glp_error (implemented as a macro) formats its * parameters using the format control string fmt, writes the formatted * message on the terminal, and abnormally terminates the program. */ static void errfunc(const char *fmt, ...) { ENV *env = get_env_ptr(); va_list arg; env->term_out = GLP_ON; va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); xprintf("Error detected in file %s at line %d\n", env->err_file, env->err_line); if (env->err_hook != NULL) env->err_hook(env->err_info); abort(); exit(EXIT_FAILURE); /* no return */ } glp_errfunc glp_error_(const char *file, int line) { ENV *env = get_env_ptr(); env->err_file = file; env->err_line = line; return errfunc; } /*********************************************************************** * NAME * * glp_assert - check for logical condition * * SYNOPSIS * * #include "glplib.h" * void glp_assert(int expr); * * DESCRIPTION * * The routine glp_assert (implemented as a macro) checks for a logical * condition specified by the parameter expr. If the condition is false * (i.e. the value of expr is zero), the routine writes a message on * the terminal and abnormally terminates the program. */ void glp_assert_(const char *expr, const char *file, int line) { glp_error_(file, line)("Assertion failed: %s\n", expr); /* no return */ } /*********************************************************************** * NAME * * glp_error_hook - install hook to intercept abnormal termination * * SYNOPSIS * * void glp_error_hook(void (*func)(void *info), void *info); * * DESCRIPTION * * The routine glp_error_hook installs a user-defined hook routine to * intercept abnormal termination. * * The parameter func specifies the user-defined hook routine. It is * called from the routine glp_error before the latter calls the abort * function to abnormally terminate the application program because of * fatal error. The parameter info is a transit pointer, specified in * the corresponding call to the routine glp_error_hook; it may be used * to pass some information to the hook routine. * * To uninstall the hook routine the parameters func and info should be * both specified as NULL. */ void glp_error_hook(void (*func)(void *info), void *info) { ENV *env = get_env_ptr(); if (func == NULL) { env->err_hook = NULL; env->err_info = NULL; } else { env->err_hook = func; env->err_info = info; } return; } /* eof */ glpk-4.52.1/src/env/stdc.h0000644000062000006210000000245412175147600014413 0ustar maomkpasswd/* stdc.h (standard ANSI C headers) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef STDC_H #define STDC_H #include #include #include #include #include #include #include #include #include #include #include #include #endif /* eof */ glpk-4.52.1/src/env/stdout.c0000644000062000006210000001653712175147600015002 0ustar maomkpasswd/* stdout.c (terminal output) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #undef NDEBUG #include #include "env.h" /*********************************************************************** * NAME * * glp_puts - write string on terminal * * SYNOPSIS * * void glp_puts(const char *s); * * The routine glp_puts writes the string s on the terminal. */ void glp_puts(const char *s) { ENV *env = get_env_ptr(); /* if terminal output is disabled, do nothing */ if (!env->term_out) goto skip; /* pass the string to the hook routine, if defined */ if (env->term_hook != NULL) { if (env->term_hook(env->term_info, s) != 0) goto skip; } /* write the string on the terminal */ fputs(s, stdout); fflush(stdout); /* write the string on the tee file, if required */ if (env->tee_file != NULL) { fputs(s, env->tee_file); fflush(env->tee_file); } skip: return; } /*********************************************************************** * NAME * * glp_printf - write formatted output on terminal * * SYNOPSIS * * void glp_printf(const char *fmt, ...); * * DESCRIPTION * * The routine glp_printf uses the format control string fmt to format * its parameters and writes the formatted output on the terminal. */ void glp_printf(const char *fmt, ...) { ENV *env = get_env_ptr(); va_list arg; /* if terminal output is disabled, do nothing */ if (!env->term_out) goto skip; /* format the output */ va_start(arg, fmt); vsprintf(env->term_buf, fmt, arg); /* (do not use xassert) */ assert(strlen(env->term_buf) < TBUF_SIZE); va_end(arg); /* write the formatted output on the terminal */ glp_puts(env->term_buf); skip: return; } /*********************************************************************** * NAME * * glp_vprintf - write formatted output on terminal * * SYNOPSIS * * void glp_vprintf(const char *fmt, va_list arg); * * DESCRIPTION * * The routine glp_vprintf uses the format control string fmt to format * its parameters specified by the list arg and writes the formatted * output on the terminal. */ void glp_vprintf(const char *fmt, va_list arg) { ENV *env = get_env_ptr(); /* if terminal output is disabled, do nothing */ if (!env->term_out) goto skip; /* format the output */ vsprintf(env->term_buf, fmt, arg); /* (do not use xassert) */ assert(strlen(env->term_buf) < TBUF_SIZE); /* write the formatted output on the terminal */ glp_puts(env->term_buf); skip: return; } /*********************************************************************** * NAME * * glp_term_out - enable/disable terminal output * * SYNOPSIS * * int glp_term_out(int flag); * * DESCRIPTION * * Depending on the parameter flag the routine glp_term_out enables or * disables terminal output performed by glpk routines: * * GLP_ON - enable terminal output; * GLP_OFF - disable terminal output. * * RETURNS * * The routine glp_term_out returns the previous value of the terminal * output flag. */ int glp_term_out(int flag) { ENV *env = get_env_ptr(); int old = env->term_out; if (!(flag == GLP_ON || flag == GLP_OFF)) xerror("glp_term_out: flag = %d; invalid parameter\n", flag); env->term_out = flag; return old; } /*********************************************************************** * NAME * * glp_term_hook - install hook to intercept terminal output * * SYNOPSIS * * void glp_term_hook(int (*func)(void *info, const char *s), * void *info); * * DESCRIPTION * * The routine glp_term_hook installs a user-defined hook routine to * intercept all terminal output performed by glpk routines. * * This feature can be used to redirect the terminal output to other * destination, for example to a file or a text window. * * The parameter func specifies the user-defined hook routine. It is * called from an internal printing routine, which passes to it two * parameters: info and s. The parameter info is a transit pointer, * specified in the corresponding call to the routine glp_term_hook; * it may be used to pass some information to the hook routine. The * parameter s is a pointer to the null terminated character string, * which is intended to be written to the terminal. If the hook routine * returns zero, the printing routine writes the string s to the * terminal in a usual way; otherwise, if the hook routine returns * non-zero, no terminal output is performed. * * To uninstall the hook routine the parameters func and info should be * specified as NULL. */ void glp_term_hook(int (*func)(void *info, const char *s), void *info) { ENV *env = get_env_ptr(); if (func == NULL) { env->term_hook = NULL; env->term_info = NULL; } else { env->term_hook = func; env->term_info = info; } return; } /*********************************************************************** * NAME * * glp_open_tee - start copying terminal output to text file * * SYNOPSIS * * int glp_open_tee(const char *name); * * DESCRIPTION * * The routine glp_open_tee starts copying all the terminal output to * an output text file, whose name is specified by the character string * name. * * RETURNS * * 0 - operation successful * 1 - copying terminal output is already active * 2 - unable to create output file */ int glp_open_tee(const char *name) { ENV *env = get_env_ptr(); if (env->tee_file != NULL) { /* copying terminal output is already active */ return 1; } env->tee_file = fopen(name, "w"); if (env->tee_file == NULL) { /* unable to create output file */ return 2; } return 0; } /*********************************************************************** * NAME * * glp_close_tee - stop copying terminal output to text file * * SYNOPSIS * * int glp_close_tee(void); * * DESCRIPTION * * The routine glp_close_tee stops copying the terminal output to the * output text file previously open by the routine glp_open_tee closing * that file. * * RETURNS * * 0 - operation successful * 1 - copying terminal output was not started */ int glp_close_tee(void) { ENV *env = get_env_ptr(); if (env->tee_file == NULL) { /* copying terminal output was not started */ return 1; } fclose(env->tee_file); env->tee_file = NULL; return 0; } /* eof */ glpk-4.52.1/src/env/time.c0000644000062000006210000001040412175147600014401 0ustar maomkpasswd/* time.c (standard time) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "env.h" #include "jd.h" /*********************************************************************** * NAME * * glp_time - determine current universal time * * SYNOPSIS * * double glp_time(void); * * RETURNS * * The routine glp_time returns the current universal time (UTC), in * milliseconds, elapsed since 00:00:00 GMT January 1, 1970. */ #define EPOCH 2440588 /* jday(1, 1, 1970) */ /* POSIX version ******************************************************/ #if defined(HAVE_SYS_TIME_H) && defined(HAVE_GETTIMEOFDAY) #include #include double glp_time(void) { struct timeval tv; struct tm *tm; int j; double t; gettimeofday(&tv, NULL); tm = gmtime(&tv.tv_sec); j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); xassert(j >= 0); t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 + (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0 + (double)(tv.tv_usec / 1000); return t; } /* MS Windows version *************************************************/ #elif defined(__WOE__) #include double glp_time(void) { SYSTEMTIME st; int j; double t; GetSystemTime(&st); j = jday(st.wDay, st.wMonth, st.wYear); xassert(j >= 0); t = ((((double)(j - EPOCH) * 24.0 + (double)st.wHour) * 60.0 + (double)st.wMinute) * 60.0 + (double)st.wSecond) * 1000.0 + (double)st.wMilliseconds; return t; } /* portable ANSI C version ********************************************/ #else #include double glp_time(void) { time_t timer; struct tm *tm; int j; double t; timer = time(NULL); tm = gmtime(&timer); j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); xassert(j >= 0); t = ((((double)(j - EPOCH) * 24.0 + (double)tm->tm_hour) * 60.0 + (double)tm->tm_min) * 60.0 + (double)tm->tm_sec) * 1000.0; return t; } #endif /*********************************************************************** * NAME * * glp_difftime - compute difference between two time values * * SYNOPSIS * * double glp_difftime(double t1, double t0); * * RETURNS * * The routine glp_difftime returns the difference between two time * values t1 and t0, expressed in seconds. */ double glp_difftime(double t1, double t0) { return (t1 - t0) / 1000.0; } /**********************************************************************/ #ifdef GLP_TEST #include int main(void) { int ttt, ss, mm, hh, day, month, year; double t; t = glp_time(); xprintf("t = %.f\n", t); assert(floor(t) == t); ttt = (int)fmod(t, 1000.0); t = (t - (double)ttt) / 1000.0; assert(floor(t) == t); ss = (int)fmod(t, 60.0); t = (t - (double)ss) / 60.0; assert(floor(t) == t); mm = (int)fmod(t, 60.0); t = (t - (double)mm) / 60.0; assert(floor(t) == t); hh = (int)fmod(t, 24.0); t = (t - (double)hh) / 24.0; assert(floor(t) == t); assert(jdate((int)t + EPOCH, &day, &month, &year) == 0); printf("%04d-%02d-%02d %02d:%02d:%02d.%03d\n", year, month, day, hh, mm, ss, ttt); return 0; } #endif /* eof */ glpk-4.52.1/src/env/tls.c0000644000062000006210000000400612175147600014246 0ustar maomkpasswd/* tls.c (thread local storage) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2001, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" static void *tls = NULL; /* NOTE: in a re-entrant version of the package this variable should be * placed in the Thread Local Storage (TLS) */ /*********************************************************************** * NAME * * tls_set_ptr - store global pointer in TLS * * SYNOPSIS * * #include "env.h" * void tls_set_ptr(void *ptr); * * DESCRIPTION * * The routine tls_set_ptr stores a pointer specified by the parameter * ptr in the Thread Local Storage (TLS). */ void tls_set_ptr(void *ptr) { tls = ptr; return; } /*********************************************************************** * NAME * * tls_get_ptr - retrieve global pointer from TLS * * SYNOPSIS * * #include "env.h" * void *tls_get_ptr(void); * * RETURNS * * The routine tls_get_ptr returns a pointer previously stored by the * routine tls_set_ptr. If the latter has not been called yet, NULL is * returned. */ void *tls_get_ptr(void) { void *ptr; ptr = tls; return ptr; } /* eof */ glpk-4.52.1/src/env2.h0000644000062000006210000000147012175147600013535 0ustar maomkpasswd/* env2.h */ /* (reserved for copyright notice) */ #ifndef ENV2_H #define ENV2_H #include "env.h" typedef struct XFILE XFILE; #define XEOF (-1) #define lib_err_msg _glp_lib_err_msg void lib_err_msg(const char *msg); #define xerrmsg _glp_lib_xerrmsg const char *xerrmsg(void); #define xfopen _glp_lib_xfopen XFILE *xfopen(const char *fname, const char *mode); #define xferror _glp_lib_xferror int xferror(XFILE *file); #define xfeof _glp_lib_xfeof int xfeof(XFILE *file); #define xfgetc _glp_lib_xfgetc int xfgetc(XFILE *file); #define xfputc _glp_lib_xfputc int xfputc(int c, XFILE *file); #define xfflush _glp_lib_xfflush int xfflush(XFILE *fp); #define xfclose _glp_lib_xfclose int xfclose(XFILE *file); #define xfprintf _glp_lib_xfprintf int xfprintf(XFILE *file, const char *fmt, ...); #endif /* eof */ glpk-4.52.1/src/glpapi.h0000644000062000006210000003002412175147600014134 0ustar maomkpasswd/* glpapi.h (application program interface) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPAPI_H #define GLPAPI_H #include "glpk.h" #include "glpavl.h" #include "glpbfd.h" #include "glplpx.h" #include "env.h" typedef struct GLPROW GLPROW; typedef struct GLPCOL GLPCOL; typedef struct GLPAIJ GLPAIJ; #define GLP_PROB_MAGIC 0xD7D9D6C2 struct glp_prob { /* LP/MIP problem object */ unsigned magic; /* magic value used for debugging */ DMP *pool; /* memory pool to store problem object components */ glp_tree *tree; /* pointer to the search tree; set by the MIP solver when this object is used in the tree as a core MIP object */ void *parms; /* reserved for backward compatibility */ /*--------------------------------------------------------------*/ /* LP/MIP data */ char *name; /* problem name (1 to 255 chars); NULL means no name is assigned to the problem */ char *obj; /* objective function name (1 to 255 chars); NULL means no name is assigned to the objective function */ int dir; /* optimization direction flag (objective "sense"): GLP_MIN - minimization GLP_MAX - maximization */ double c0; /* constant term of the objective function ("shift") */ int m_max; /* length of the array of rows (enlarged automatically) */ int n_max; /* length of the array of columns (enlarged automatically) */ int m; /* number of rows, 0 <= m <= m_max */ int n; /* number of columns, 0 <= n <= n_max */ int nnz; /* number of non-zero constraint coefficients, nnz >= 0 */ GLPROW **row; /* GLPROW *row[1+m_max]; */ /* row[i], 1 <= i <= m, is a pointer to i-th row */ GLPCOL **col; /* GLPCOL *col[1+n_max]; */ /* col[j], 1 <= j <= n, is a pointer to j-th column */ AVL *r_tree; /* row index to find rows by their names; NULL means this index does not exist */ AVL *c_tree; /* column index to find columns by their names; NULL means this index does not exist */ /*--------------------------------------------------------------*/ /* basis factorization (LP) */ int valid; /* the factorization is valid only if this flag is set */ int *head; /* int head[1+m_max]; */ /* basis header (valid only if the factorization is valid); head[i] = k is the ordinal number of auxiliary (1 <= k <= m) or structural (m+1 <= k <= m+n) variable which corresponds to i-th basic variable xB[i], 1 <= i <= m */ glp_bfcp *bfcp; /* basis factorization control parameters; may be NULL */ BFD *bfd; /* BFD bfd[1:m,1:m]; */ /* basis factorization driver; may be NULL */ /*--------------------------------------------------------------*/ /* basic solution (LP) */ int pbs_stat; /* primal basic solution status: GLP_UNDEF - primal solution is undefined GLP_FEAS - primal solution is feasible GLP_INFEAS - primal solution is infeasible GLP_NOFEAS - no primal feasible solution exists */ int dbs_stat; /* dual basic solution status: GLP_UNDEF - dual solution is undefined GLP_FEAS - dual solution is feasible GLP_INFEAS - dual solution is infeasible GLP_NOFEAS - no dual feasible solution exists */ double obj_val; /* objective function value */ int it_cnt; /* simplex method iteration count; increased by one on performing one simplex iteration */ int some; /* ordinal number of some auxiliary or structural variable having certain property, 0 <= some <= m+n */ /*--------------------------------------------------------------*/ /* interior-point solution (LP) */ int ipt_stat; /* interior-point solution status: GLP_UNDEF - interior solution is undefined GLP_OPT - interior solution is optimal GLP_INFEAS - interior solution is infeasible GLP_NOFEAS - no feasible solution exists */ double ipt_obj; /* objective function value */ /*--------------------------------------------------------------*/ /* integer solution (MIP) */ int mip_stat; /* integer solution status: GLP_UNDEF - integer solution is undefined GLP_OPT - integer solution is optimal GLP_FEAS - integer solution is feasible GLP_NOFEAS - no integer solution exists */ double mip_obj; /* objective function value */ }; struct GLPROW { /* LP/MIP row (auxiliary variable) */ int i; /* ordinal number (1 to m) assigned to this row */ char *name; /* row name (1 to 255 chars); NULL means no name is assigned to this row */ AVLNODE *node; /* pointer to corresponding node in the row index; NULL means that either the row index does not exist or this row has no name assigned */ #if 1 /* 20/IX-2008 */ int level; unsigned char origin; unsigned char klass; #endif int type; /* type of the auxiliary variable: GLP_FR - free variable GLP_LO - variable with lower bound GLP_UP - variable with upper bound GLP_DB - double-bounded variable GLP_FX - fixed variable */ double lb; /* non-scaled */ /* lower bound; if the row has no lower bound, lb is zero */ double ub; /* non-scaled */ /* upper bound; if the row has no upper bound, ub is zero */ /* if the row type is GLP_FX, ub is equal to lb */ GLPAIJ *ptr; /* non-scaled */ /* pointer to doubly linked list of constraint coefficients which are placed in this row */ double rii; /* diagonal element r[i,i] of scaling matrix R for this row; if the scaling is not used, r[i,i] is 1 */ int stat; /* status of the auxiliary variable: GLP_BS - basic variable GLP_NL - non-basic variable on lower bound GLP_NU - non-basic variable on upper bound GLP_NF - non-basic free variable GLP_NS - non-basic fixed variable */ int bind; /* if the auxiliary variable is basic, head[bind] refers to this row, otherwise, bind is 0; this attribute is valid only if the basis factorization is valid */ double prim; /* non-scaled */ /* primal value of the auxiliary variable in basic solution */ double dual; /* non-scaled */ /* dual value of the auxiliary variable in basic solution */ double pval; /* non-scaled */ /* primal value of the auxiliary variable in interior solution */ double dval; /* non-scaled */ /* dual value of the auxiliary variable in interior solution */ double mipx; /* non-scaled */ /* primal value of the auxiliary variable in integer solution */ }; struct GLPCOL { /* LP/MIP column (structural variable) */ int j; /* ordinal number (1 to n) assigned to this column */ char *name; /* column name (1 to 255 chars); NULL means no name is assigned to this column */ AVLNODE *node; /* pointer to corresponding node in the column index; NULL means that either the column index does not exist or the column has no name assigned */ int kind; /* kind of the structural variable: GLP_CV - continuous variable GLP_IV - integer or binary variable */ int type; /* type of the structural variable: GLP_FR - free variable GLP_LO - variable with lower bound GLP_UP - variable with upper bound GLP_DB - double-bounded variable GLP_FX - fixed variable */ double lb; /* non-scaled */ /* lower bound; if the column has no lower bound, lb is zero */ double ub; /* non-scaled */ /* upper bound; if the column has no upper bound, ub is zero */ /* if the column type is GLP_FX, ub is equal to lb */ double coef; /* non-scaled */ /* objective coefficient at the structural variable */ GLPAIJ *ptr; /* non-scaled */ /* pointer to doubly linked list of constraint coefficients which are placed in this column */ double sjj; /* diagonal element s[j,j] of scaling matrix S for this column; if the scaling is not used, s[j,j] is 1 */ int stat; /* status of the structural variable: GLP_BS - basic variable GLP_NL - non-basic variable on lower bound GLP_NU - non-basic variable on upper bound GLP_NF - non-basic free variable GLP_NS - non-basic fixed variable */ int bind; /* if the structural variable is basic, head[bind] refers to this column; otherwise, bind is 0; this attribute is valid only if the basis factorization is valid */ double prim; /* non-scaled */ /* primal value of the structural variable in basic solution */ double dual; /* non-scaled */ /* dual value of the structural variable in basic solution */ double pval; /* non-scaled */ /* primal value of the structural variable in interior solution */ double dval; /* non-scaled */ /* dual value of the structural variable in interior solution */ double mipx; /* non-scaled */ /* primal value of the structural variable in integer solution */ }; struct GLPAIJ { /* constraint coefficient a[i,j] */ GLPROW *row; /* pointer to row, where this coefficient is placed */ GLPCOL *col; /* pointer to column, where this coefficient is placed */ double val; /* numeric (non-zero) value of this coefficient */ GLPAIJ *r_prev; /* pointer to previous coefficient in the same row */ GLPAIJ *r_next; /* pointer to next coefficient in the same row */ GLPAIJ *c_prev; /* pointer to previous coefficient in the same column */ GLPAIJ *c_next; /* pointer to next coefficient in the same column */ }; #define lpx_put_solution _glp_put_solution void lpx_put_solution(glp_prob *lp, int inval, const int *p_stat, const int *d_stat, const double *obj_val, const int r_stat[], const double r_prim[], const double r_dual[], const int c_stat[], const double c_prim[], const double c_dual[]); /* store basic solution components */ #define lpx_put_mip_soln _glp_put_mip_soln void lpx_put_mip_soln(LPX *lp, int i_stat, double row_mipx[], double col_mipx[]); /* store mixed integer solution components */ #if 1 /* 28/XI-2009 */ int _glp_analyze_row(glp_prob *P, int len, const int ind[], const double val[], int type, double rhs, double eps, int *_piv, double *_x, double *_dx, double *_y, double *_dy, double *_dz); /* simulate one iteration of dual simplex method */ #endif #if 1 /* 08/XII-2009 */ void _glp_mpl_init_rand(glp_tran *tran, int seed); #endif #define glp_skpgen _glp_skpgen void glp_skpgen(int n, int r, int type, int v, int s, int a[], int *b, int c[]); /* Pisinger's 0-1 single knapsack problem generator */ #if 1 /* 28/V-2010 */ int _glp_intopt1(glp_prob *P, const glp_iocp *parm); #endif #endif /* eof */ glpk-4.52.1/src/glpapi01.c0000644000062000006210000014726112175147600014304 0ustar maomkpasswd/* glpapi01.c (problem creating and modifying routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /* CAUTION: DO NOT CHANGE THE LIMITS BELOW */ #define M_MAX 100000000 /* = 100*10^6 */ /* maximal number of rows in the problem object */ #define N_MAX 100000000 /* = 100*10^6 */ /* maximal number of columns in the problem object */ #define NNZ_MAX 500000000 /* = 500*10^6 */ /* maximal number of constraint coefficients in the problem object */ /*********************************************************************** * NAME * * glp_create_prob - create problem object * * SYNOPSIS * * glp_prob *glp_create_prob(void); * * DESCRIPTION * * The routine glp_create_prob creates a new problem object, which is * initially "empty", i.e. has no rows and columns. * * RETURNS * * The routine returns a pointer to the object created, which should be * used in any subsequent operations on this object. */ static void create_prob(glp_prob *lp) { lp->magic = GLP_PROB_MAGIC; lp->pool = dmp_create_pool(); #if 0 /* 17/XI-2009 */ lp->cps = xmalloc(sizeof(struct LPXCPS)); lpx_reset_parms(lp); #else lp->parms = NULL; #endif lp->tree = NULL; #if 0 lp->lwa = 0; lp->cwa = NULL; #endif /* LP/MIP data */ lp->name = NULL; lp->obj = NULL; lp->dir = GLP_MIN; lp->c0 = 0.0; lp->m_max = 100; lp->n_max = 200; lp->m = lp->n = 0; lp->nnz = 0; lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *)); lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *)); lp->r_tree = lp->c_tree = NULL; /* basis factorization */ lp->valid = 0; lp->head = xcalloc(1+lp->m_max, sizeof(int)); lp->bfcp = NULL; lp->bfd = NULL; /* basic solution (LP) */ lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; lp->obj_val = 0.0; lp->it_cnt = 0; lp->some = 0; /* interior-point solution (LP) */ lp->ipt_stat = GLP_UNDEF; lp->ipt_obj = 0.0; /* integer solution (MIP) */ lp->mip_stat = GLP_UNDEF; lp->mip_obj = 0.0; return; } glp_prob *glp_create_prob(void) { glp_prob *lp; lp = xmalloc(sizeof(glp_prob)); create_prob(lp); return lp; } /*********************************************************************** * NAME * * glp_set_prob_name - assign (change) problem name * * SYNOPSIS * * void glp_set_prob_name(glp_prob *lp, const char *name); * * DESCRIPTION * * The routine glp_set_prob_name assigns a given symbolic name (1 up to * 255 characters) to the specified problem object. * * If the parameter name is NULL or empty string, the routine erases an * existing symbolic name of the problem object. */ void glp_set_prob_name(glp_prob *lp, const char *name) { glp_tree *tree = lp->tree; if (tree != NULL && tree->reason != 0) xerror("glp_set_prob_name: operation not allowed\n"); if (lp->name != NULL) { dmp_free_atom(lp->pool, lp->name, strlen(lp->name)+1); lp->name = NULL; } if (!(name == NULL || name[0] == '\0')) { int k; for (k = 0; name[k] != '\0'; k++) { if (k == 256) xerror("glp_set_prob_name: problem name too long\n"); if (iscntrl((unsigned char)name[k])) xerror("glp_set_prob_name: problem name contains invalid" " character(s)\n"); } lp->name = dmp_get_atom(lp->pool, strlen(name)+1); strcpy(lp->name, name); } return; } /*********************************************************************** * NAME * * glp_set_obj_name - assign (change) objective function name * * SYNOPSIS * * void glp_set_obj_name(glp_prob *lp, const char *name); * * DESCRIPTION * * The routine glp_set_obj_name assigns a given symbolic name (1 up to * 255 characters) to the objective function of the specified problem * object. * * If the parameter name is NULL or empty string, the routine erases an * existing name of the objective function. */ void glp_set_obj_name(glp_prob *lp, const char *name) { glp_tree *tree = lp->tree; if (tree != NULL && tree->reason != 0) xerror("glp_set_obj_name: operation not allowed\n"); if (lp->obj != NULL) { dmp_free_atom(lp->pool, lp->obj, strlen(lp->obj)+1); lp->obj = NULL; } if (!(name == NULL || name[0] == '\0')) { int k; for (k = 0; name[k] != '\0'; k++) { if (k == 256) xerror("glp_set_obj_name: objective name too long\n"); if (iscntrl((unsigned char)name[k])) xerror("glp_set_obj_name: objective name contains invali" "d character(s)\n"); } lp->obj = dmp_get_atom(lp->pool, strlen(name)+1); strcpy(lp->obj, name); } return; } /*********************************************************************** * NAME * * glp_set_obj_dir - set (change) optimization direction flag * * SYNOPSIS * * void glp_set_obj_dir(glp_prob *lp, int dir); * * DESCRIPTION * * The routine glp_set_obj_dir sets (changes) optimization direction * flag (i.e. "sense" of the objective function) as specified by the * parameter dir: * * GLP_MIN - minimization; * GLP_MAX - maximization. */ void glp_set_obj_dir(glp_prob *lp, int dir) { glp_tree *tree = lp->tree; if (tree != NULL && tree->reason != 0) xerror("glp_set_obj_dir: operation not allowed\n"); if (!(dir == GLP_MIN || dir == GLP_MAX)) xerror("glp_set_obj_dir: dir = %d; invalid direction flag\n", dir); lp->dir = dir; return; } /*********************************************************************** * NAME * * glp_add_rows - add new rows to problem object * * SYNOPSIS * * int glp_add_rows(glp_prob *lp, int nrs); * * DESCRIPTION * * The routine glp_add_rows adds nrs rows (constraints) to the specified * problem object. New rows are always added to the end of the row list, * so the ordinal numbers of existing rows remain unchanged. * * Being added each new row is initially free (unbounded) and has empty * list of the constraint coefficients. * * RETURNS * * The routine glp_add_rows returns the ordinal number of the first new * row added to the problem object. */ int glp_add_rows(glp_prob *lp, int nrs) { glp_tree *tree = lp->tree; GLPROW *row; int m_new, i; /* determine new number of rows */ if (nrs < 1) xerror("glp_add_rows: nrs = %d; invalid number of rows\n", nrs); if (nrs > M_MAX - lp->m) xerror("glp_add_rows: nrs = %d; too many rows\n", nrs); m_new = lp->m + nrs; /* increase the room, if necessary */ if (lp->m_max < m_new) { GLPROW **save = lp->row; while (lp->m_max < m_new) { lp->m_max += lp->m_max; xassert(lp->m_max > 0); } lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *)); memcpy(&lp->row[1], &save[1], lp->m * sizeof(GLPROW *)); xfree(save); /* do not forget about the basis header */ xfree(lp->head); lp->head = xcalloc(1+lp->m_max, sizeof(int)); } /* add new rows to the end of the row list */ for (i = lp->m+1; i <= m_new; i++) { /* create row descriptor */ lp->row[i] = row = dmp_get_atom(lp->pool, sizeof(GLPROW)); row->i = i; row->name = NULL; row->node = NULL; #if 1 /* 20/IX-2008 */ row->level = 0; row->origin = 0; row->klass = 0; if (tree != NULL) { switch (tree->reason) { case 0: break; case GLP_IROWGEN: xassert(tree->curr != NULL); row->level = tree->curr->level; row->origin = GLP_RF_LAZY; break; case GLP_ICUTGEN: xassert(tree->curr != NULL); row->level = tree->curr->level; row->origin = GLP_RF_CUT; break; default: xassert(tree != tree); } } #endif row->type = GLP_FR; row->lb = row->ub = 0.0; row->ptr = NULL; row->rii = 1.0; row->stat = GLP_BS; #if 0 row->bind = -1; #else row->bind = 0; #endif row->prim = row->dual = 0.0; row->pval = row->dval = 0.0; row->mipx = 0.0; } /* set new number of rows */ lp->m = m_new; /* invalidate the basis factorization */ lp->valid = 0; #if 1 if (tree != NULL && tree->reason != 0) tree->reopt = 1; #endif /* return the ordinal number of the first row added */ return m_new - nrs + 1; } /*********************************************************************** * NAME * * glp_add_cols - add new columns to problem object * * SYNOPSIS * * int glp_add_cols(glp_prob *lp, int ncs); * * DESCRIPTION * * The routine glp_add_cols adds ncs columns (structural variables) to * the specified problem object. New columns are always added to the end * of the column list, so the ordinal numbers of existing columns remain * unchanged. * * Being added each new column is initially fixed at zero and has empty * list of the constraint coefficients. * * RETURNS * * The routine glp_add_cols returns the ordinal number of the first new * column added to the problem object. */ int glp_add_cols(glp_prob *lp, int ncs) { glp_tree *tree = lp->tree; GLPCOL *col; int n_new, j; if (tree != NULL && tree->reason != 0) xerror("glp_add_cols: operation not allowed\n"); /* determine new number of columns */ if (ncs < 1) xerror("glp_add_cols: ncs = %d; invalid number of columns\n", ncs); if (ncs > N_MAX - lp->n) xerror("glp_add_cols: ncs = %d; too many columns\n", ncs); n_new = lp->n + ncs; /* increase the room, if necessary */ if (lp->n_max < n_new) { GLPCOL **save = lp->col; while (lp->n_max < n_new) { lp->n_max += lp->n_max; xassert(lp->n_max > 0); } lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *)); memcpy(&lp->col[1], &save[1], lp->n * sizeof(GLPCOL *)); xfree(save); } /* add new columns to the end of the column list */ for (j = lp->n+1; j <= n_new; j++) { /* create column descriptor */ lp->col[j] = col = dmp_get_atom(lp->pool, sizeof(GLPCOL)); col->j = j; col->name = NULL; col->node = NULL; col->kind = GLP_CV; col->type = GLP_FX; col->lb = col->ub = 0.0; col->coef = 0.0; col->ptr = NULL; col->sjj = 1.0; col->stat = GLP_NS; #if 0 col->bind = -1; #else col->bind = 0; /* the basis may remain valid */ #endif col->prim = col->dual = 0.0; col->pval = col->dval = 0.0; col->mipx = 0.0; } /* set new number of columns */ lp->n = n_new; /* return the ordinal number of the first column added */ return n_new - ncs + 1; } /*********************************************************************** * NAME * * glp_set_row_name - assign (change) row name * * SYNOPSIS * * void glp_set_row_name(glp_prob *lp, int i, const char *name); * * DESCRIPTION * * The routine glp_set_row_name assigns a given symbolic name (1 up to * 255 characters) to i-th row (auxiliary variable) of the specified * problem object. * * If the parameter name is NULL or empty string, the routine erases an * existing name of i-th row. */ void glp_set_row_name(glp_prob *lp, int i, const char *name) { glp_tree *tree = lp->tree; GLPROW *row; if (!(1 <= i && i <= lp->m)) xerror("glp_set_row_name: i = %d; row number out of range\n", i); row = lp->row[i]; if (tree != NULL && tree->reason != 0) { xassert(tree->curr != NULL); xassert(row->level == tree->curr->level); } if (row->name != NULL) { if (row->node != NULL) { xassert(lp->r_tree != NULL); avl_delete_node(lp->r_tree, row->node); row->node = NULL; } dmp_free_atom(lp->pool, row->name, strlen(row->name)+1); row->name = NULL; } if (!(name == NULL || name[0] == '\0')) { int k; for (k = 0; name[k] != '\0'; k++) { if (k == 256) xerror("glp_set_row_name: i = %d; row name too long\n", i); if (iscntrl((unsigned char)name[k])) xerror("glp_set_row_name: i = %d: row name contains inva" "lid character(s)\n", i); } row->name = dmp_get_atom(lp->pool, strlen(name)+1); strcpy(row->name, name); if (lp->r_tree != NULL) { xassert(row->node == NULL); row->node = avl_insert_node(lp->r_tree, row->name); avl_set_node_link(row->node, row); } } return; } /*********************************************************************** * NAME * * glp_set_col_name - assign (change) column name * * SYNOPSIS * * void glp_set_col_name(glp_prob *lp, int j, const char *name); * * DESCRIPTION * * The routine glp_set_col_name assigns a given symbolic name (1 up to * 255 characters) to j-th column (structural variable) of the specified * problem object. * * If the parameter name is NULL or empty string, the routine erases an * existing name of j-th column. */ void glp_set_col_name(glp_prob *lp, int j, const char *name) { glp_tree *tree = lp->tree; GLPCOL *col; if (tree != NULL && tree->reason != 0) xerror("glp_set_col_name: operation not allowed\n"); if (!(1 <= j && j <= lp->n)) xerror("glp_set_col_name: j = %d; column number out of range\n" , j); col = lp->col[j]; if (col->name != NULL) { if (col->node != NULL) { xassert(lp->c_tree != NULL); avl_delete_node(lp->c_tree, col->node); col->node = NULL; } dmp_free_atom(lp->pool, col->name, strlen(col->name)+1); col->name = NULL; } if (!(name == NULL || name[0] == '\0')) { int k; for (k = 0; name[k] != '\0'; k++) { if (k == 256) xerror("glp_set_col_name: j = %d; column name too long\n" , j); if (iscntrl((unsigned char)name[k])) xerror("glp_set_col_name: j = %d: column name contains i" "nvalid character(s)\n", j); } col->name = dmp_get_atom(lp->pool, strlen(name)+1); strcpy(col->name, name); if (lp->c_tree != NULL && col->name != NULL) { xassert(col->node == NULL); col->node = avl_insert_node(lp->c_tree, col->name); avl_set_node_link(col->node, col); } } return; } /*********************************************************************** * NAME * * glp_set_row_bnds - set (change) row bounds * * SYNOPSIS * * void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb, * double ub); * * DESCRIPTION * * The routine glp_set_row_bnds sets (changes) the type and bounds of * i-th row (auxiliary variable) of the specified problem object. * * Parameters type, lb, and ub specify the type, lower bound, and upper * bound, respectively, as follows: * * Type Bounds Comments * ------------------------------------------------------ * GLP_FR -inf < x < +inf Free variable * GLP_LO lb <= x < +inf Variable with lower bound * GLP_UP -inf < x <= ub Variable with upper bound * GLP_DB lb <= x <= ub Double-bounded variable * GLP_FX x = lb Fixed variable * * where x is the auxiliary variable associated with i-th row. * * If the row has no lower bound, the parameter lb is ignored. If the * row has no upper bound, the parameter ub is ignored. If the row is * an equality constraint (i.e. the corresponding auxiliary variable is * of fixed type), only the parameter lb is used while the parameter ub * is ignored. */ void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb, double ub) { GLPROW *row; if (!(1 <= i && i <= lp->m)) xerror("glp_set_row_bnds: i = %d; row number out of range\n", i); row = lp->row[i]; row->type = type; switch (type) { case GLP_FR: row->lb = row->ub = 0.0; if (row->stat != GLP_BS) row->stat = GLP_NF; break; case GLP_LO: row->lb = lb, row->ub = 0.0; if (row->stat != GLP_BS) row->stat = GLP_NL; break; case GLP_UP: row->lb = 0.0, row->ub = ub; if (row->stat != GLP_BS) row->stat = GLP_NU; break; case GLP_DB: row->lb = lb, row->ub = ub; if (!(row->stat == GLP_BS || row->stat == GLP_NL || row->stat == GLP_NU)) row->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU); break; case GLP_FX: row->lb = row->ub = lb; if (row->stat != GLP_BS) row->stat = GLP_NS; break; default: xerror("glp_set_row_bnds: i = %d; type = %d; invalid row ty" "pe\n", i, type); } return; } /*********************************************************************** * NAME * * glp_set_col_bnds - set (change) column bounds * * SYNOPSIS * * void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb, * double ub); * * DESCRIPTION * * The routine glp_set_col_bnds sets (changes) the type and bounds of * j-th column (structural variable) of the specified problem object. * * Parameters type, lb, and ub specify the type, lower bound, and upper * bound, respectively, as follows: * * Type Bounds Comments * ------------------------------------------------------ * GLP_FR -inf < x < +inf Free variable * GLP_LO lb <= x < +inf Variable with lower bound * GLP_UP -inf < x <= ub Variable with upper bound * GLP_DB lb <= x <= ub Double-bounded variable * GLP_FX x = lb Fixed variable * * where x is the structural variable associated with j-th column. * * If the column has no lower bound, the parameter lb is ignored. If the * column has no upper bound, the parameter ub is ignored. If the column * is of fixed type, only the parameter lb is used while the parameter * ub is ignored. */ void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb, double ub) { GLPCOL *col; if (!(1 <= j && j <= lp->n)) xerror("glp_set_col_bnds: j = %d; column number out of range\n" , j); col = lp->col[j]; col->type = type; switch (type) { case GLP_FR: col->lb = col->ub = 0.0; if (col->stat != GLP_BS) col->stat = GLP_NF; break; case GLP_LO: col->lb = lb, col->ub = 0.0; if (col->stat != GLP_BS) col->stat = GLP_NL; break; case GLP_UP: col->lb = 0.0, col->ub = ub; if (col->stat != GLP_BS) col->stat = GLP_NU; break; case GLP_DB: col->lb = lb, col->ub = ub; if (!(col->stat == GLP_BS || col->stat == GLP_NL || col->stat == GLP_NU)) col->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU); break; case GLP_FX: col->lb = col->ub = lb; if (col->stat != GLP_BS) col->stat = GLP_NS; break; default: xerror("glp_set_col_bnds: j = %d; type = %d; invalid column" " type\n", j, type); } return; } /*********************************************************************** * NAME * * glp_set_obj_coef - set (change) obj. coefficient or constant term * * SYNOPSIS * * void glp_set_obj_coef(glp_prob *lp, int j, double coef); * * DESCRIPTION * * The routine glp_set_obj_coef sets (changes) objective coefficient at * j-th column (structural variable) of the specified problem object. * * If the parameter j is 0, the routine sets (changes) the constant term * ("shift") of the objective function. */ void glp_set_obj_coef(glp_prob *lp, int j, double coef) { glp_tree *tree = lp->tree; if (tree != NULL && tree->reason != 0) xerror("glp_set_obj_coef: operation not allowed\n"); if (!(0 <= j && j <= lp->n)) xerror("glp_set_obj_coef: j = %d; column number out of range\n" , j); if (j == 0) lp->c0 = coef; else lp->col[j]->coef = coef; return; } /*********************************************************************** * NAME * * glp_set_mat_row - set (replace) row of the constraint matrix * * SYNOPSIS * * void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[], * const double val[]); * * DESCRIPTION * * The routine glp_set_mat_row stores (replaces) the contents of i-th * row of the constraint matrix of the specified problem object. * * Column indices and numeric values of new row elements must be placed * in locations ind[1], ..., ind[len] and val[1], ..., val[len], where * 0 <= len <= n is the new length of i-th row, n is the current number * of columns in the problem object. Elements with identical column * indices are not allowed. Zero elements are allowed, but they are not * stored in the constraint matrix. * * If the parameter len is zero, the parameters ind and/or val can be * specified as NULL. */ void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[], const double val[]) { glp_tree *tree = lp->tree; GLPROW *row; GLPCOL *col; GLPAIJ *aij, *next; int j, k; /* obtain pointer to i-th row */ if (!(1 <= i && i <= lp->m)) xerror("glp_set_mat_row: i = %d; row number out of range\n", i); row = lp->row[i]; if (tree != NULL && tree->reason != 0) { xassert(tree->curr != NULL); xassert(row->level == tree->curr->level); } /* remove all existing elements from i-th row */ while (row->ptr != NULL) { /* take next element in the row */ aij = row->ptr; /* remove the element from the row list */ row->ptr = aij->r_next; /* obtain pointer to corresponding column */ col = aij->col; /* remove the element from the column list */ if (aij->c_prev == NULL) col->ptr = aij->c_next; else aij->c_prev->c_next = aij->c_next; if (aij->c_next == NULL) ; else aij->c_next->c_prev = aij->c_prev; /* return the element to the memory pool */ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; /* if the corresponding column is basic, invalidate the basis factorization */ if (col->stat == GLP_BS) lp->valid = 0; } /* store new contents of i-th row */ if (!(0 <= len && len <= lp->n)) xerror("glp_set_mat_row: i = %d; len = %d; invalid row length " "\n", i, len); if (len > NNZ_MAX - lp->nnz) xerror("glp_set_mat_row: i = %d; len = %d; too many constraint" " coefficients\n", i, len); for (k = 1; k <= len; k++) { /* take number j of corresponding column */ j = ind[k]; /* obtain pointer to j-th column */ if (!(1 <= j && j <= lp->n)) xerror("glp_set_mat_row: i = %d; ind[%d] = %d; column index" " out of range\n", i, k, j); col = lp->col[j]; /* if there is element with the same column index, it can only be found in the beginning of j-th column list */ if (col->ptr != NULL && col->ptr->row->i == i) xerror("glp_set_mat_row: i = %d; ind[%d] = %d; duplicate co" "lumn indices not allowed\n", i, k, j); /* create new element */ aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; aij->row = row; aij->col = col; aij->val = val[k]; /* add the new element to the beginning of i-th row and j-th column lists */ aij->r_prev = NULL; aij->r_next = row->ptr; aij->c_prev = NULL; aij->c_next = col->ptr; if (aij->r_next != NULL) aij->r_next->r_prev = aij; if (aij->c_next != NULL) aij->c_next->c_prev = aij; row->ptr = col->ptr = aij; /* if the corresponding column is basic, invalidate the basis factorization */ if (col->stat == GLP_BS && aij->val != 0.0) lp->valid = 0; } /* remove zero elements from i-th row */ for (aij = row->ptr; aij != NULL; aij = next) { next = aij->r_next; if (aij->val == 0.0) { /* remove the element from the row list */ if (aij->r_prev == NULL) row->ptr = next; else aij->r_prev->r_next = next; if (next == NULL) ; else next->r_prev = aij->r_prev; /* remove the element from the column list */ xassert(aij->c_prev == NULL); aij->col->ptr = aij->c_next; if (aij->c_next != NULL) aij->c_next->c_prev = NULL; /* return the element to the memory pool */ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; } } return; } /*********************************************************************** * NAME * * glp_set_mat_col - set (replace) column of the constraint matrix * * SYNOPSIS * * void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[], * const double val[]); * * DESCRIPTION * * The routine glp_set_mat_col stores (replaces) the contents of j-th * column of the constraint matrix of the specified problem object. * * Row indices and numeric values of new column elements must be placed * in locations ind[1], ..., ind[len] and val[1], ..., val[len], where * 0 <= len <= m is the new length of j-th column, m is the current * number of rows in the problem object. Elements with identical column * indices are not allowed. Zero elements are allowed, but they are not * stored in the constraint matrix. * * If the parameter len is zero, the parameters ind and/or val can be * specified as NULL. */ void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[], const double val[]) { glp_tree *tree = lp->tree; GLPROW *row; GLPCOL *col; GLPAIJ *aij, *next; int i, k; if (tree != NULL && tree->reason != 0) xerror("glp_set_mat_col: operation not allowed\n"); /* obtain pointer to j-th column */ if (!(1 <= j && j <= lp->n)) xerror("glp_set_mat_col: j = %d; column number out of range\n", j); col = lp->col[j]; /* remove all existing elements from j-th column */ while (col->ptr != NULL) { /* take next element in the column */ aij = col->ptr; /* remove the element from the column list */ col->ptr = aij->c_next; /* obtain pointer to corresponding row */ row = aij->row; /* remove the element from the row list */ if (aij->r_prev == NULL) row->ptr = aij->r_next; else aij->r_prev->r_next = aij->r_next; if (aij->r_next == NULL) ; else aij->r_next->r_prev = aij->r_prev; /* return the element to the memory pool */ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; } /* store new contents of j-th column */ if (!(0 <= len && len <= lp->m)) xerror("glp_set_mat_col: j = %d; len = %d; invalid column leng" "th\n", j, len); if (len > NNZ_MAX - lp->nnz) xerror("glp_set_mat_col: j = %d; len = %d; too many constraint" " coefficients\n", j, len); for (k = 1; k <= len; k++) { /* take number i of corresponding row */ i = ind[k]; /* obtain pointer to i-th row */ if (!(1 <= i && i <= lp->m)) xerror("glp_set_mat_col: j = %d; ind[%d] = %d; row index ou" "t of range\n", j, k, i); row = lp->row[i]; /* if there is element with the same row index, it can only be found in the beginning of i-th row list */ if (row->ptr != NULL && row->ptr->col->j == j) xerror("glp_set_mat_col: j = %d; ind[%d] = %d; duplicate ro" "w indices not allowed\n", j, k, i); /* create new element */ aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; aij->row = row; aij->col = col; aij->val = val[k]; /* add the new element to the beginning of i-th row and j-th column lists */ aij->r_prev = NULL; aij->r_next = row->ptr; aij->c_prev = NULL; aij->c_next = col->ptr; if (aij->r_next != NULL) aij->r_next->r_prev = aij; if (aij->c_next != NULL) aij->c_next->c_prev = aij; row->ptr = col->ptr = aij; } /* remove zero elements from j-th column */ for (aij = col->ptr; aij != NULL; aij = next) { next = aij->c_next; if (aij->val == 0.0) { /* remove the element from the row list */ xassert(aij->r_prev == NULL); aij->row->ptr = aij->r_next; if (aij->r_next != NULL) aij->r_next->r_prev = NULL; /* remove the element from the column list */ if (aij->c_prev == NULL) col->ptr = next; else aij->c_prev->c_next = next; if (next == NULL) ; else next->c_prev = aij->c_prev; /* return the element to the memory pool */ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; } } /* if j-th column is basic, invalidate the basis factorization */ if (col->stat == GLP_BS) lp->valid = 0; return; } /*********************************************************************** * NAME * * glp_load_matrix - load (replace) the whole constraint matrix * * SYNOPSIS * * void glp_load_matrix(glp_prob *lp, int ne, const int ia[], * const int ja[], const double ar[]); * * DESCRIPTION * * The routine glp_load_matrix loads the constraint matrix passed in * the arrays ia, ja, and ar into the specified problem object. Before * loading the current contents of the constraint matrix is destroyed. * * Constraint coefficients (elements of the constraint matrix) must be * specified as triplets (ia[k], ja[k], ar[k]) for k = 1, ..., ne, * where ia[k] is the row index, ja[k] is the column index, ar[k] is a * numeric value of corresponding constraint coefficient. The parameter * ne specifies the total number of (non-zero) elements in the matrix * to be loaded. Coefficients with identical indices are not allowed. * Zero coefficients are allowed, however, they are not stored in the * constraint matrix. * * If the parameter ne is zero, the parameters ia, ja, and ar can be * specified as NULL. */ void glp_load_matrix(glp_prob *lp, int ne, const int ia[], const int ja[], const double ar[]) { glp_tree *tree = lp->tree; GLPROW *row; GLPCOL *col; GLPAIJ *aij, *next; int i, j, k; if (tree != NULL && tree->reason != 0) xerror("glp_load_matrix: operation not allowed\n"); /* clear the constraint matrix */ for (i = 1; i <= lp->m; i++) { row = lp->row[i]; while (row->ptr != NULL) { aij = row->ptr; row->ptr = aij->r_next; dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; } } xassert(lp->nnz == 0); for (j = 1; j <= lp->n; j++) lp->col[j]->ptr = NULL; /* load the new contents of the constraint matrix and build its row lists */ if (ne < 0) xerror("glp_load_matrix: ne = %d; invalid number of constraint" " coefficients\n", ne); if (ne > NNZ_MAX) xerror("glp_load_matrix: ne = %d; too many constraint coeffici" "ents\n", ne); for (k = 1; k <= ne; k++) { /* take indices of new element */ i = ia[k], j = ja[k]; /* obtain pointer to i-th row */ if (!(1 <= i && i <= lp->m)) xerror("glp_load_matrix: ia[%d] = %d; row index out of rang" "e\n", k, i); row = lp->row[i]; /* obtain pointer to j-th column */ if (!(1 <= j && j <= lp->n)) xerror("glp_load_matrix: ja[%d] = %d; column index out of r" "ange\n", k, j); col = lp->col[j]; /* create new element */ aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++; aij->row = row; aij->col = col; aij->val = ar[k]; /* add the new element to the beginning of i-th row list */ aij->r_prev = NULL; aij->r_next = row->ptr; if (aij->r_next != NULL) aij->r_next->r_prev = aij; row->ptr = aij; } xassert(lp->nnz == ne); /* build column lists of the constraint matrix and check elements with identical indices */ for (i = 1; i <= lp->m; i++) { for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) { /* obtain pointer to corresponding column */ col = aij->col; /* if there is element with identical indices, it can only be found in the beginning of j-th column list */ if (col->ptr != NULL && col->ptr->row->i == i) { for (k = 1; k <= ne; k++) if (ia[k] == i && ja[k] == col->j) break; xerror("glp_load_mat: ia[%d] = %d; ja[%d] = %d; duplicat" "e indices not allowed\n", k, i, k, col->j); } /* add the element to the beginning of j-th column list */ aij->c_prev = NULL; aij->c_next = col->ptr; if (aij->c_next != NULL) aij->c_next->c_prev = aij; col->ptr = aij; } } /* remove zero elements from the constraint matrix */ for (i = 1; i <= lp->m; i++) { row = lp->row[i]; for (aij = row->ptr; aij != NULL; aij = next) { next = aij->r_next; if (aij->val == 0.0) { /* remove the element from the row list */ if (aij->r_prev == NULL) row->ptr = next; else aij->r_prev->r_next = next; if (next == NULL) ; else next->r_prev = aij->r_prev; /* remove the element from the column list */ if (aij->c_prev == NULL) aij->col->ptr = aij->c_next; else aij->c_prev->c_next = aij->c_next; if (aij->c_next == NULL) ; else aij->c_next->c_prev = aij->c_prev; /* return the element to the memory pool */ dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--; } } } /* invalidate the basis factorization */ lp->valid = 0; return; } /*********************************************************************** * NAME * * glp_check_dup - check for duplicate elements in sparse matrix * * SYNOPSIS * * int glp_check_dup(int m, int n, int ne, const int ia[], * const int ja[]); * * DESCRIPTION * * The routine glp_check_dup checks for duplicate elements (that is, * elements with identical indices) in a sparse matrix specified in the * coordinate format. * * The parameters m and n specifies, respectively, the number of rows * and columns in the matrix, m >= 0, n >= 0. * * The parameter ne specifies the number of (structurally) non-zero * elements in the matrix, ne >= 0. * * Elements of the matrix are specified as doublets (ia[k],ja[k]) for * k = 1,...,ne, where ia[k] is a row index, ja[k] is a column index. * * The routine glp_check_dup can be used prior to a call to the routine * glp_load_matrix to check that the constraint matrix to be loaded has * no duplicate elements. * * RETURNS * * The routine glp_check_dup returns one of the following values: * * 0 - the matrix has no duplicate elements; * * -k - indices ia[k] or/and ja[k] are out of range; * * +k - element (ia[k],ja[k]) is duplicate. */ int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[]) { int i, j, k, *ptr, *next, ret; char *flag; if (m < 0) xerror("glp_check_dup: m = %d; invalid parameter\n"); if (n < 0) xerror("glp_check_dup: n = %d; invalid parameter\n"); if (ne < 0) xerror("glp_check_dup: ne = %d; invalid parameter\n"); if (ne > 0 && ia == NULL) xerror("glp_check_dup: ia = %p; invalid parameter\n", ia); if (ne > 0 && ja == NULL) xerror("glp_check_dup: ja = %p; invalid parameter\n", ja); for (k = 1; k <= ne; k++) { i = ia[k], j = ja[k]; if (!(1 <= i && i <= m && 1 <= j && j <= n)) { ret = -k; goto done; } } if (m == 0 || n == 0) { ret = 0; goto done; } /* allocate working arrays */ ptr = xcalloc(1+m, sizeof(int)); next = xcalloc(1+ne, sizeof(int)); flag = xcalloc(1+n, sizeof(char)); /* build row lists */ for (i = 1; i <= m; i++) ptr[i] = 0; for (k = 1; k <= ne; k++) { i = ia[k]; next[k] = ptr[i]; ptr[i] = k; } /* clear column flags */ for (j = 1; j <= n; j++) flag[j] = 0; /* check for duplicate elements */ for (i = 1; i <= m; i++) { for (k = ptr[i]; k != 0; k = next[k]) { j = ja[k]; if (flag[j]) { /* find first element (i,j) */ for (k = 1; k <= ne; k++) if (ia[k] == i && ja[k] == j) break; xassert(k <= ne); /* find next (duplicate) element (i,j) */ for (k++; k <= ne; k++) if (ia[k] == i && ja[k] == j) break; xassert(k <= ne); ret = +k; goto skip; } flag[j] = 1; } /* clear column flags */ for (k = ptr[i]; k != 0; k = next[k]) flag[ja[k]] = 0; } /* no duplicate element found */ ret = 0; skip: /* free working arrays */ xfree(ptr); xfree(next); xfree(flag); done: return ret; } /*********************************************************************** * NAME * * glp_sort_matrix - sort elements of the constraint matrix * * SYNOPSIS * * void glp_sort_matrix(glp_prob *P); * * DESCRIPTION * * The routine glp_sort_matrix sorts elements of the constraint matrix * rebuilding its row and column linked lists. On exit from the routine * the constraint matrix is not changed, however, elements in the row * linked lists become ordered by ascending column indices, and the * elements in the column linked lists become ordered by ascending row * indices. */ void glp_sort_matrix(glp_prob *P) { GLPAIJ *aij; int i, j; if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_sort_matrix: P = %p; invalid problem object\n", P); /* rebuild row linked lists */ for (i = P->m; i >= 1; i--) P->row[i]->ptr = NULL; for (j = P->n; j >= 1; j--) { for (aij = P->col[j]->ptr; aij != NULL; aij = aij->c_next) { i = aij->row->i; aij->r_prev = NULL; aij->r_next = P->row[i]->ptr; if (aij->r_next != NULL) aij->r_next->r_prev = aij; P->row[i]->ptr = aij; } } /* rebuild column linked lists */ for (j = P->n; j >= 1; j--) P->col[j]->ptr = NULL; for (i = P->m; i >= 1; i--) { for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) { j = aij->col->j; aij->c_prev = NULL; aij->c_next = P->col[j]->ptr; if (aij->c_next != NULL) aij->c_next->c_prev = aij; P->col[j]->ptr = aij; } } return; } /*********************************************************************** * NAME * * glp_del_rows - delete rows from problem object * * SYNOPSIS * * void glp_del_rows(glp_prob *lp, int nrs, const int num[]); * * DESCRIPTION * * The routine glp_del_rows deletes rows from the specified problem * object. Ordinal numbers of rows to be deleted should be placed in * locations num[1], ..., num[nrs], where nrs > 0. * * Note that deleting rows involves changing ordinal numbers of other * rows remaining in the problem object. New ordinal numbers of the * remaining rows are assigned under the assumption that the original * order of rows is not changed. */ void glp_del_rows(glp_prob *lp, int nrs, const int num[]) { glp_tree *tree = lp->tree; GLPROW *row; int i, k, m_new; /* mark rows to be deleted */ if (!(1 <= nrs && nrs <= lp->m)) xerror("glp_del_rows: nrs = %d; invalid number of rows\n", nrs); for (k = 1; k <= nrs; k++) { /* take the number of row to be deleted */ i = num[k]; /* obtain pointer to i-th row */ if (!(1 <= i && i <= lp->m)) xerror("glp_del_rows: num[%d] = %d; row number out of range" "\n", k, i); row = lp->row[i]; if (tree != NULL && tree->reason != 0) { if (!(tree->reason == GLP_IROWGEN || tree->reason == GLP_ICUTGEN)) xerror("glp_del_rows: operation not allowed\n"); xassert(tree->curr != NULL); if (row->level != tree->curr->level) xerror("glp_del_rows: num[%d] = %d; invalid attempt to d" "elete row created not in current subproblem\n", k,i); if (row->stat != GLP_BS) xerror("glp_del_rows: num[%d] = %d; invalid attempt to d" "elete active row (constraint)\n", k, i); tree->reinv = 1; } /* check that the row is not marked yet */ if (row->i == 0) xerror("glp_del_rows: num[%d] = %d; duplicate row numbers n" "ot allowed\n", k, i); /* erase symbolic name assigned to the row */ glp_set_row_name(lp, i, NULL); xassert(row->node == NULL); /* erase corresponding row of the constraint matrix */ glp_set_mat_row(lp, i, 0, NULL, NULL); xassert(row->ptr == NULL); /* mark the row to be deleted */ row->i = 0; } /* delete all marked rows from the row list */ m_new = 0; for (i = 1; i <= lp->m; i++) { /* obtain pointer to i-th row */ row = lp->row[i]; /* check if the row is marked */ if (row->i == 0) { /* it is marked, delete it */ dmp_free_atom(lp->pool, row, sizeof(GLPROW)); } else { /* it is not marked; keep it */ row->i = ++m_new; lp->row[row->i] = row; } } /* set new number of rows */ lp->m = m_new; /* invalidate the basis factorization */ lp->valid = 0; return; } /*********************************************************************** * NAME * * glp_del_cols - delete columns from problem object * * SYNOPSIS * * void glp_del_cols(glp_prob *lp, int ncs, const int num[]); * * DESCRIPTION * * The routine glp_del_cols deletes columns from the specified problem * object. Ordinal numbers of columns to be deleted should be placed in * locations num[1], ..., num[ncs], where ncs > 0. * * Note that deleting columns involves changing ordinal numbers of * other columns remaining in the problem object. New ordinal numbers * of the remaining columns are assigned under the assumption that the * original order of columns is not changed. */ void glp_del_cols(glp_prob *lp, int ncs, const int num[]) { glp_tree *tree = lp->tree; GLPCOL *col; int j, k, n_new; if (tree != NULL && tree->reason != 0) xerror("glp_del_cols: operation not allowed\n"); /* mark columns to be deleted */ if (!(1 <= ncs && ncs <= lp->n)) xerror("glp_del_cols: ncs = %d; invalid number of columns\n", ncs); for (k = 1; k <= ncs; k++) { /* take the number of column to be deleted */ j = num[k]; /* obtain pointer to j-th column */ if (!(1 <= j && j <= lp->n)) xerror("glp_del_cols: num[%d] = %d; column number out of ra" "nge", k, j); col = lp->col[j]; /* check that the column is not marked yet */ if (col->j == 0) xerror("glp_del_cols: num[%d] = %d; duplicate column number" "s not allowed\n", k, j); /* erase symbolic name assigned to the column */ glp_set_col_name(lp, j, NULL); xassert(col->node == NULL); /* erase corresponding column of the constraint matrix */ glp_set_mat_col(lp, j, 0, NULL, NULL); xassert(col->ptr == NULL); /* mark the column to be deleted */ col->j = 0; /* if it is basic, invalidate the basis factorization */ if (col->stat == GLP_BS) lp->valid = 0; } /* delete all marked columns from the column list */ n_new = 0; for (j = 1; j <= lp->n; j++) { /* obtain pointer to j-th column */ col = lp->col[j]; /* check if the column is marked */ if (col->j == 0) { /* it is marked; delete it */ dmp_free_atom(lp->pool, col, sizeof(GLPCOL)); } else { /* it is not marked; keep it */ col->j = ++n_new; lp->col[col->j] = col; } } /* set new number of columns */ lp->n = n_new; /* if the basis header is still valid, adjust it */ if (lp->valid) { int m = lp->m; int *head = lp->head; for (j = 1; j <= n_new; j++) { k = lp->col[j]->bind; if (k != 0) { xassert(1 <= k && k <= m); head[k] = m + j; } } } return; } /*********************************************************************** * NAME * * glp_copy_prob - copy problem object content * * SYNOPSIS * * void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); * * DESCRIPTION * * The routine glp_copy_prob copies the content of the problem object * prob to the problem object dest. * * The parameter names is a flag. If it is non-zero, the routine also * copies all symbolic names; otherwise, if it is zero, symbolic names * are not copied. */ void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names) { glp_tree *tree = dest->tree; glp_bfcp bfcp; int i, j, len, *ind; double *val; if (tree != NULL && tree->reason != 0) xerror("glp_copy_prob: operation not allowed\n"); if (dest == prob) xerror("glp_copy_prob: copying problem object to itself not al" "lowed\n"); if (!(names == GLP_ON || names == GLP_OFF)) xerror("glp_copy_prob: names = %d; invalid parameter\n", names); glp_erase_prob(dest); if (names && prob->name != NULL) glp_set_prob_name(dest, prob->name); if (names && prob->obj != NULL) glp_set_obj_name(dest, prob->obj); dest->dir = prob->dir; dest->c0 = prob->c0; if (prob->m > 0) glp_add_rows(dest, prob->m); if (prob->n > 0) glp_add_cols(dest, prob->n); glp_get_bfcp(prob, &bfcp); glp_set_bfcp(dest, &bfcp); dest->pbs_stat = prob->pbs_stat; dest->dbs_stat = prob->dbs_stat; dest->obj_val = prob->obj_val; dest->some = prob->some; dest->ipt_stat = prob->ipt_stat; dest->ipt_obj = prob->ipt_obj; dest->mip_stat = prob->mip_stat; dest->mip_obj = prob->mip_obj; for (i = 1; i <= prob->m; i++) { GLPROW *to = dest->row[i]; GLPROW *from = prob->row[i]; if (names && from->name != NULL) glp_set_row_name(dest, i, from->name); to->type = from->type; to->lb = from->lb; to->ub = from->ub; to->rii = from->rii; to->stat = from->stat; to->prim = from->prim; to->dual = from->dual; to->pval = from->pval; to->dval = from->dval; to->mipx = from->mipx; } ind = xcalloc(1+prob->m, sizeof(int)); val = xcalloc(1+prob->m, sizeof(double)); for (j = 1; j <= prob->n; j++) { GLPCOL *to = dest->col[j]; GLPCOL *from = prob->col[j]; if (names && from->name != NULL) glp_set_col_name(dest, j, from->name); to->kind = from->kind; to->type = from->type; to->lb = from->lb; to->ub = from->ub; to->coef = from->coef; len = glp_get_mat_col(prob, j, ind, val); glp_set_mat_col(dest, j, len, ind, val); to->sjj = from->sjj; to->stat = from->stat; to->prim = from->prim; to->dual = from->dual; to->pval = from->pval; to->dval = from->dval; to->mipx = from->mipx; } xfree(ind); xfree(val); return; } /*********************************************************************** * NAME * * glp_erase_prob - erase problem object content * * SYNOPSIS * * void glp_erase_prob(glp_prob *lp); * * DESCRIPTION * * The routine glp_erase_prob erases the content of the specified * problem object. The effect of this operation is the same as if the * problem object would be deleted with the routine glp_delete_prob and * then created anew with the routine glp_create_prob, with exception * that the handle (pointer) to the problem object remains valid. */ static void delete_prob(glp_prob *lp); void glp_erase_prob(glp_prob *lp) { glp_tree *tree = lp->tree; if (tree != NULL && tree->reason != 0) xerror("glp_erase_prob: operation not allowed\n"); delete_prob(lp); create_prob(lp); return; } /*********************************************************************** * NAME * * glp_delete_prob - delete problem object * * SYNOPSIS * * void glp_delete_prob(glp_prob *lp); * * DESCRIPTION * * The routine glp_delete_prob deletes the specified problem object and * frees all the memory allocated to it. */ static void delete_prob(glp_prob *lp) { lp->magic = 0x3F3F3F3F; dmp_delete_pool(lp->pool); #if 0 /* 17/XI-2009 */ xfree(lp->cps); #else if (lp->parms != NULL) xfree(lp->parms); #endif xassert(lp->tree == NULL); #if 0 if (lp->cwa != NULL) xfree(lp->cwa); #endif xfree(lp->row); xfree(lp->col); if (lp->r_tree != NULL) avl_delete_tree(lp->r_tree); if (lp->c_tree != NULL) avl_delete_tree(lp->c_tree); xfree(lp->head); if (lp->bfcp != NULL) xfree(lp->bfcp); if (lp->bfd != NULL) bfd_delete_it(lp->bfd); return; } void glp_delete_prob(glp_prob *lp) { glp_tree *tree = lp->tree; if (tree != NULL && tree->reason != 0) xerror("glp_delete_prob: operation not allowed\n"); delete_prob(lp); xfree(lp); return; } /* eof */ glpk-4.52.1/src/glpapi02.c0000644000062000006210000003230512175147600014275 0ustar maomkpasswd/* glpapi02.c (problem retrieving routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * glp_get_prob_name - retrieve problem name * * SYNOPSIS * * const char *glp_get_prob_name(glp_prob *lp); * * RETURNS * * The routine glp_get_prob_name returns a pointer to an internal * buffer, which contains symbolic name of the problem. However, if the * problem has no assigned name, the routine returns NULL. */ const char *glp_get_prob_name(glp_prob *lp) { char *name; name = lp->name; return name; } /*********************************************************************** * NAME * * glp_get_obj_name - retrieve objective function name * * SYNOPSIS * * const char *glp_get_obj_name(glp_prob *lp); * * RETURNS * * The routine glp_get_obj_name returns a pointer to an internal * buffer, which contains a symbolic name of the objective function. * However, if the objective function has no assigned name, the routine * returns NULL. */ const char *glp_get_obj_name(glp_prob *lp) { char *name; name = lp->obj; return name; } /*********************************************************************** * NAME * * glp_get_obj_dir - retrieve optimization direction flag * * SYNOPSIS * * int glp_get_obj_dir(glp_prob *lp); * * RETURNS * * The routine glp_get_obj_dir returns the optimization direction flag * (i.e. "sense" of the objective function): * * GLP_MIN - minimization; * GLP_MAX - maximization. */ int glp_get_obj_dir(glp_prob *lp) { int dir = lp->dir; return dir; } /*********************************************************************** * NAME * * glp_get_num_rows - retrieve number of rows * * SYNOPSIS * * int glp_get_num_rows(glp_prob *lp); * * RETURNS * * The routine glp_get_num_rows returns the current number of rows in * the specified problem object. */ int glp_get_num_rows(glp_prob *lp) { int m = lp->m; return m; } /*********************************************************************** * NAME * * glp_get_num_cols - retrieve number of columns * * SYNOPSIS * * int glp_get_num_cols(glp_prob *lp); * * RETURNS * * The routine glp_get_num_cols returns the current number of columns * in the specified problem object. */ int glp_get_num_cols(glp_prob *lp) { int n = lp->n; return n; } /*********************************************************************** * NAME * * glp_get_row_name - retrieve row name * * SYNOPSIS * * const char *glp_get_row_name(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_name returns a pointer to an internal * buffer, which contains symbolic name of i-th row. However, if i-th * row has no assigned name, the routine returns NULL. */ const char *glp_get_row_name(glp_prob *lp, int i) { char *name; if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_name: i = %d; row number out of range\n", i); name = lp->row[i]->name; return name; } /*********************************************************************** * NAME * * glp_get_col_name - retrieve column name * * SYNOPSIS * * const char *glp_get_col_name(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_name returns a pointer to an internal * buffer, which contains symbolic name of j-th column. However, if j-th * column has no assigned name, the routine returns NULL. */ const char *glp_get_col_name(glp_prob *lp, int j) { char *name; if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_name: j = %d; column number out of range\n" , j); name = lp->col[j]->name; return name; } /*********************************************************************** * NAME * * glp_get_row_type - retrieve row type * * SYNOPSIS * * int glp_get_row_type(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_type returns the type of i-th row, i.e. the * type of corresponding auxiliary variable, as follows: * * GLP_FR - free (unbounded) variable; * GLP_LO - variable with lower bound; * GLP_UP - variable with upper bound; * GLP_DB - double-bounded variable; * GLP_FX - fixed variable. */ int glp_get_row_type(glp_prob *lp, int i) { if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_type: i = %d; row number out of range\n", i); return lp->row[i]->type; } /*********************************************************************** * NAME * * glp_get_row_lb - retrieve row lower bound * * SYNOPSIS * * double glp_get_row_lb(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_lb returns the lower bound of i-th row, i.e. * the lower bound of corresponding auxiliary variable. However, if the * row has no lower bound, the routine returns -DBL_MAX. */ double glp_get_row_lb(glp_prob *lp, int i) { double lb; if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_lb: i = %d; row number out of range\n", i); switch (lp->row[i]->type) { case GLP_FR: case GLP_UP: lb = -DBL_MAX; break; case GLP_LO: case GLP_DB: case GLP_FX: lb = lp->row[i]->lb; break; default: xassert(lp != lp); } return lb; } /*********************************************************************** * NAME * * glp_get_row_ub - retrieve row upper bound * * SYNOPSIS * * double glp_get_row_ub(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_ub returns the upper bound of i-th row, i.e. * the upper bound of corresponding auxiliary variable. However, if the * row has no upper bound, the routine returns +DBL_MAX. */ double glp_get_row_ub(glp_prob *lp, int i) { double ub; if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_ub: i = %d; row number out of range\n", i); switch (lp->row[i]->type) { case GLP_FR: case GLP_LO: ub = +DBL_MAX; break; case GLP_UP: case GLP_DB: case GLP_FX: ub = lp->row[i]->ub; break; default: xassert(lp != lp); } return ub; } /*********************************************************************** * NAME * * glp_get_col_type - retrieve column type * * SYNOPSIS * * int glp_get_col_type(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_type returns the type of j-th column, i.e. * the type of corresponding structural variable, as follows: * * GLP_FR - free (unbounded) variable; * GLP_LO - variable with lower bound; * GLP_UP - variable with upper bound; * GLP_DB - double-bounded variable; * GLP_FX - fixed variable. */ int glp_get_col_type(glp_prob *lp, int j) { if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_type: j = %d; column number out of range\n" , j); return lp->col[j]->type; } /*********************************************************************** * NAME * * glp_get_col_lb - retrieve column lower bound * * SYNOPSIS * * double glp_get_col_lb(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_lb returns the lower bound of j-th column, * i.e. the lower bound of corresponding structural variable. However, * if the column has no lower bound, the routine returns -DBL_MAX. */ double glp_get_col_lb(glp_prob *lp, int j) { double lb; if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_lb: j = %d; column number out of range\n", j); switch (lp->col[j]->type) { case GLP_FR: case GLP_UP: lb = -DBL_MAX; break; case GLP_LO: case GLP_DB: case GLP_FX: lb = lp->col[j]->lb; break; default: xassert(lp != lp); } return lb; } /*********************************************************************** * NAME * * glp_get_col_ub - retrieve column upper bound * * SYNOPSIS * * double glp_get_col_ub(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_ub returns the upper bound of j-th column, * i.e. the upper bound of corresponding structural variable. However, * if the column has no upper bound, the routine returns +DBL_MAX. */ double glp_get_col_ub(glp_prob *lp, int j) { double ub; if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_ub: j = %d; column number out of range\n", j); switch (lp->col[j]->type) { case GLP_FR: case GLP_LO: ub = +DBL_MAX; break; case GLP_UP: case GLP_DB: case GLP_FX: ub = lp->col[j]->ub; break; default: xassert(lp != lp); } return ub; } /*********************************************************************** * NAME * * glp_get_obj_coef - retrieve obj. coefficient or constant term * * SYNOPSIS * * double glp_get_obj_coef(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_obj_coef returns the objective coefficient at * j-th structural variable (column) of the specified problem object. * * If the parameter j is zero, the routine returns the constant term * ("shift") of the objective function. */ double glp_get_obj_coef(glp_prob *lp, int j) { if (!(0 <= j && j <= lp->n)) xerror("glp_get_obj_coef: j = %d; column number out of range\n" , j); return j == 0 ? lp->c0 : lp->col[j]->coef; } /*********************************************************************** * NAME * * glp_get_num_nz - retrieve number of constraint coefficients * * SYNOPSIS * * int glp_get_num_nz(glp_prob *lp); * * RETURNS * * The routine glp_get_num_nz returns the number of (non-zero) elements * in the constraint matrix of the specified problem object. */ int glp_get_num_nz(glp_prob *lp) { int nnz = lp->nnz; return nnz; } /*********************************************************************** * NAME * * glp_get_mat_row - retrieve row of the constraint matrix * * SYNOPSIS * * int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[]); * * DESCRIPTION * * The routine glp_get_mat_row scans (non-zero) elements of i-th row * of the constraint matrix of the specified problem object and stores * their column indices and numeric values to locations ind[1], ..., * ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= n * is the number of elements in i-th row, n is the number of columns. * * The parameter ind and/or val can be specified as NULL, in which case * corresponding information is not stored. * * RETURNS * * The routine glp_get_mat_row returns the length len, i.e. the number * of (non-zero) elements in i-th row. */ int glp_get_mat_row(glp_prob *lp, int i, int ind[], double val[]) { GLPAIJ *aij; int len; if (!(1 <= i && i <= lp->m)) xerror("glp_get_mat_row: i = %d; row number out of range\n", i); len = 0; for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) { len++; if (ind != NULL) ind[len] = aij->col->j; if (val != NULL) val[len] = aij->val; } xassert(len <= lp->n); return len; } /*********************************************************************** * NAME * * glp_get_mat_col - retrieve column of the constraint matrix * * SYNOPSIS * * int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[]); * * DESCRIPTION * * The routine glp_get_mat_col scans (non-zero) elements of j-th column * of the constraint matrix of the specified problem object and stores * their row indices and numeric values to locations ind[1], ..., * ind[len] and val[1], ..., val[len], respectively, where 0 <= len <= m * is the number of elements in j-th column, m is the number of rows. * * The parameter ind or/and val can be specified as NULL, in which case * corresponding information is not stored. * * RETURNS * * The routine glp_get_mat_col returns the length len, i.e. the number * of (non-zero) elements in j-th column. */ int glp_get_mat_col(glp_prob *lp, int j, int ind[], double val[]) { GLPAIJ *aij; int len; if (!(1 <= j && j <= lp->n)) xerror("glp_get_mat_col: j = %d; column number out of range\n", j); len = 0; for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) { len++; if (ind != NULL) ind[len] = aij->row->i; if (val != NULL) val[len] = aij->val; } xassert(len <= lp->m); return len; } /* eof */ glpk-4.52.1/src/glpapi03.c0000644000062000006210000001217312175147600014277 0ustar maomkpasswd/* glpapi03.c (row and column searching routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * glp_create_index - create the name index * * SYNOPSIS * * void glp_create_index(glp_prob *lp); * * DESCRIPTION * * The routine glp_create_index creates the name index for the * specified problem object. The name index is an auxiliary data * structure, which is intended to quickly (i.e. for logarithmic time) * find rows and columns by their names. * * This routine can be called at any time. If the name index already * exists, the routine does nothing. */ void glp_create_index(glp_prob *lp) { GLPROW *row; GLPCOL *col; int i, j; /* create row name index */ if (lp->r_tree == NULL) { lp->r_tree = avl_create_tree(avl_strcmp, NULL); for (i = 1; i <= lp->m; i++) { row = lp->row[i]; xassert(row->node == NULL); if (row->name != NULL) { row->node = avl_insert_node(lp->r_tree, row->name); avl_set_node_link(row->node, row); } } } /* create column name index */ if (lp->c_tree == NULL) { lp->c_tree = avl_create_tree(avl_strcmp, NULL); for (j = 1; j <= lp->n; j++) { col = lp->col[j]; xassert(col->node == NULL); if (col->name != NULL) { col->node = avl_insert_node(lp->c_tree, col->name); avl_set_node_link(col->node, col); } } } return; } /*********************************************************************** * NAME * * glp_find_row - find row by its name * * SYNOPSIS * * int glp_find_row(glp_prob *lp, const char *name); * * RETURNS * * The routine glp_find_row returns the ordinal number of a row, * which is assigned (by the routine glp_set_row_name) the specified * symbolic name. If no such row exists, the routine returns 0. */ int glp_find_row(glp_prob *lp, const char *name) { AVLNODE *node; int i = 0; if (lp->r_tree == NULL) xerror("glp_find_row: row name index does not exist\n"); if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) { node = avl_find_node(lp->r_tree, name); if (node != NULL) i = ((GLPROW *)avl_get_node_link(node))->i; } return i; } /*********************************************************************** * NAME * * glp_find_col - find column by its name * * SYNOPSIS * * int glp_find_col(glp_prob *lp, const char *name); * * RETURNS * * The routine glp_find_col returns the ordinal number of a column, * which is assigned (by the routine glp_set_col_name) the specified * symbolic name. If no such column exists, the routine returns 0. */ int glp_find_col(glp_prob *lp, const char *name) { AVLNODE *node; int j = 0; if (lp->c_tree == NULL) xerror("glp_find_col: column name index does not exist\n"); if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) { node = avl_find_node(lp->c_tree, name); if (node != NULL) j = ((GLPCOL *)avl_get_node_link(node))->j; } return j; } /*********************************************************************** * NAME * * glp_delete_index - delete the name index * * SYNOPSIS * * void glp_delete_index(glp_prob *lp); * * DESCRIPTION * * The routine glp_delete_index deletes the name index previously * created by the routine glp_create_index and frees the memory * allocated to this auxiliary data structure. * * This routine can be called at any time. If the name index does not * exist, the routine does nothing. */ void glp_delete_index(glp_prob *lp) { int i, j; /* delete row name index */ if (lp->r_tree != NULL) { for (i = 1; i <= lp->m; i++) lp->row[i]->node = NULL; avl_delete_tree(lp->r_tree), lp->r_tree = NULL; } /* delete column name index */ if (lp->c_tree != NULL) { for (j = 1; j <= lp->n; j++) lp->col[j]->node = NULL; avl_delete_tree(lp->c_tree), lp->c_tree = NULL; } return; } /* eof */ glpk-4.52.1/src/glpapi04.c0000644000062000006210000001104012175147600014270 0ustar maomkpasswd/* glpapi04.c (problem scaling routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * glp_set_rii - set (change) row scale factor * * SYNOPSIS * * void glp_set_rii(glp_prob *lp, int i, double rii); * * DESCRIPTION * * The routine glp_set_rii sets (changes) the scale factor r[i,i] for * i-th row of the specified problem object. */ void glp_set_rii(glp_prob *lp, int i, double rii) { if (!(1 <= i && i <= lp->m)) xerror("glp_set_rii: i = %d; row number out of range\n", i); if (rii <= 0.0) xerror("glp_set_rii: i = %d; rii = %g; invalid scale factor\n", i, rii); if (lp->valid && lp->row[i]->rii != rii) { GLPAIJ *aij; for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) { if (aij->col->stat == GLP_BS) { /* invalidate the basis factorization */ lp->valid = 0; break; } } } lp->row[i]->rii = rii; return; } /*********************************************************************** * NAME * * glp_set sjj - set (change) column scale factor * * SYNOPSIS * * void glp_set_sjj(glp_prob *lp, int j, double sjj); * * DESCRIPTION * * The routine glp_set_sjj sets (changes) the scale factor s[j,j] for * j-th column of the specified problem object. */ void glp_set_sjj(glp_prob *lp, int j, double sjj) { if (!(1 <= j && j <= lp->n)) xerror("glp_set_sjj: j = %d; column number out of range\n", j); if (sjj <= 0.0) xerror("glp_set_sjj: j = %d; sjj = %g; invalid scale factor\n", j, sjj); if (lp->valid && lp->col[j]->sjj != sjj && lp->col[j]->stat == GLP_BS) { /* invalidate the basis factorization */ lp->valid = 0; } lp->col[j]->sjj = sjj; return; } /*********************************************************************** * NAME * * glp_get_rii - retrieve row scale factor * * SYNOPSIS * * double glp_get_rii(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_rii returns current scale factor r[i,i] for i-th * row of the specified problem object. */ double glp_get_rii(glp_prob *lp, int i) { if (!(1 <= i && i <= lp->m)) xerror("glp_get_rii: i = %d; row number out of range\n", i); return lp->row[i]->rii; } /*********************************************************************** * NAME * * glp_get_sjj - retrieve column scale factor * * SYNOPSIS * * double glp_get_sjj(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_sjj returns current scale factor s[j,j] for j-th * column of the specified problem object. */ double glp_get_sjj(glp_prob *lp, int j) { if (!(1 <= j && j <= lp->n)) xerror("glp_get_sjj: j = %d; column number out of range\n", j); return lp->col[j]->sjj; } /*********************************************************************** * NAME * * glp_unscale_prob - unscale problem data * * SYNOPSIS * * void glp_unscale_prob(glp_prob *lp); * * DESCRIPTION * * The routine glp_unscale_prob performs unscaling of problem data for * the specified problem object. * * "Unscaling" means replacing the current scaling matrices R and S by * unity matrices that cancels the scaling effect. */ void glp_unscale_prob(glp_prob *lp) { int m = glp_get_num_rows(lp); int n = glp_get_num_cols(lp); int i, j; for (i = 1; i <= m; i++) glp_set_rii(lp, i, 1.0); for (j = 1; j <= n; j++) glp_set_sjj(lp, j, 1.0); return; } /* eof */ glpk-4.52.1/src/glpapi05.c0000644000062000006210000001314512175147600014301 0ustar maomkpasswd/* glpapi05.c (LP basis constructing routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * glp_set_row_stat - set (change) row status * * SYNOPSIS * * void glp_set_row_stat(glp_prob *lp, int i, int stat); * * DESCRIPTION * * The routine glp_set_row_stat sets (changes) status of the auxiliary * variable associated with i-th row. * * The new status of the auxiliary variable should be specified by the * parameter stat as follows: * * GLP_BS - basic variable; * GLP_NL - non-basic variable; * GLP_NU - non-basic variable on its upper bound; if the variable is * not double-bounded, this means the same as GLP_NL (only in * case of this routine); * GLP_NF - the same as GLP_NL (only in case of this routine); * GLP_NS - the same as GLP_NL (only in case of this routine). */ void glp_set_row_stat(glp_prob *lp, int i, int stat) { GLPROW *row; if (!(1 <= i && i <= lp->m)) xerror("glp_set_row_stat: i = %d; row number out of range\n", i); if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU || stat == GLP_NF || stat == GLP_NS)) xerror("glp_set_row_stat: i = %d; stat = %d; invalid status\n", i, stat); row = lp->row[i]; if (stat != GLP_BS) { switch (row->type) { case GLP_FR: stat = GLP_NF; break; case GLP_LO: stat = GLP_NL; break; case GLP_UP: stat = GLP_NU; break; case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break; case GLP_FX: stat = GLP_NS; break; default: xassert(row != row); } } if (row->stat == GLP_BS && stat != GLP_BS || row->stat != GLP_BS && stat == GLP_BS) { /* invalidate the basis factorization */ lp->valid = 0; } row->stat = stat; return; } /*********************************************************************** * NAME * * glp_set_col_stat - set (change) column status * * SYNOPSIS * * void glp_set_col_stat(glp_prob *lp, int j, int stat); * * DESCRIPTION * * The routine glp_set_col_stat sets (changes) status of the structural * variable associated with j-th column. * * The new status of the structural variable should be specified by the * parameter stat as follows: * * GLP_BS - basic variable; * GLP_NL - non-basic variable; * GLP_NU - non-basic variable on its upper bound; if the variable is * not double-bounded, this means the same as GLP_NL (only in * case of this routine); * GLP_NF - the same as GLP_NL (only in case of this routine); * GLP_NS - the same as GLP_NL (only in case of this routine). */ void glp_set_col_stat(glp_prob *lp, int j, int stat) { GLPCOL *col; if (!(1 <= j && j <= lp->n)) xerror("glp_set_col_stat: j = %d; column number out of range\n" , j); if (!(stat == GLP_BS || stat == GLP_NL || stat == GLP_NU || stat == GLP_NF || stat == GLP_NS)) xerror("glp_set_col_stat: j = %d; stat = %d; invalid status\n", j, stat); col = lp->col[j]; if (stat != GLP_BS) { switch (col->type) { case GLP_FR: stat = GLP_NF; break; case GLP_LO: stat = GLP_NL; break; case GLP_UP: stat = GLP_NU; break; case GLP_DB: if (stat != GLP_NU) stat = GLP_NL; break; case GLP_FX: stat = GLP_NS; break; default: xassert(col != col); } } if (col->stat == GLP_BS && stat != GLP_BS || col->stat != GLP_BS && stat == GLP_BS) { /* invalidate the basis factorization */ lp->valid = 0; } col->stat = stat; return; } /*********************************************************************** * NAME * * glp_std_basis - construct standard initial LP basis * * SYNOPSIS * * void glp_std_basis(glp_prob *lp); * * DESCRIPTION * * The routine glp_std_basis builds the "standard" (trivial) initial * basis for the specified problem object. * * In the "standard" basis all auxiliary variables are basic, and all * structural variables are non-basic. */ void glp_std_basis(glp_prob *lp) { int i, j; /* make all auxiliary variables basic */ for (i = 1; i <= lp->m; i++) glp_set_row_stat(lp, i, GLP_BS); /* make all structural variables non-basic */ for (j = 1; j <= lp->n; j++) { GLPCOL *col = lp->col[j]; if (col->type == GLP_DB && fabs(col->lb) > fabs(col->ub)) glp_set_col_stat(lp, j, GLP_NU); else glp_set_col_stat(lp, j, GLP_NL); } return; } /* eof */ glpk-4.52.1/src/glpapi06.c0000644000062000006210000006375612175147600014317 0ustar maomkpasswd/* glpapi06.c (simplex method routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" #include "glpnpp.h" #include "glpspx.h" /*********************************************************************** * NAME * * glp_simplex - solve LP problem with the simplex method * * SYNOPSIS * * int glp_simplex(glp_prob *P, const glp_smcp *parm); * * DESCRIPTION * * The routine glp_simplex is a driver to the LP solver based on the * simplex method. This routine retrieves problem data from the * specified problem object, calls the solver to solve the problem * instance, and stores results of computations back into the problem * object. * * The simplex solver has a set of control parameters. Values of the * control parameters can be passed in a structure glp_smcp, which the * parameter parm points to. * * The parameter parm can be specified as NULL, in which case the LP * solver uses default settings. * * RETURNS * * 0 The LP problem instance has been successfully solved. This code * does not necessarily mean that the solver has found optimal * solution. It only means that the solution process was successful. * * GLP_EBADB * Unable to start the search, because the initial basis specified * in the problem object is invalid--the number of basic (auxiliary * and structural) variables is not the same as the number of rows in * the problem object. * * GLP_ESING * Unable to start the search, because the basis matrix correspodning * to the initial basis is singular within the working precision. * * GLP_ECOND * Unable to start the search, because the basis matrix correspodning * to the initial basis is ill-conditioned, i.e. its condition number * is too large. * * GLP_EBOUND * Unable to start the search, because some double-bounded variables * have incorrect bounds. * * GLP_EFAIL * The search was prematurely terminated due to the solver failure. * * GLP_EOBJLL * The search was prematurely terminated, because the objective * function being maximized has reached its lower limit and continues * decreasing (dual simplex only). * * GLP_EOBJUL * The search was prematurely terminated, because the objective * function being minimized has reached its upper limit and continues * increasing (dual simplex only). * * GLP_EITLIM * The search was prematurely terminated, because the simplex * iteration limit has been exceeded. * * GLP_ETMLIM * The search was prematurely terminated, because the time limit has * been exceeded. * * GLP_ENOPFS * The LP problem instance has no primal feasible solution (only if * the LP presolver is used). * * GLP_ENODFS * The LP problem instance has no dual feasible solution (only if the * LP presolver is used). */ static void trivial_lp(glp_prob *P, const glp_smcp *parm) { /* solve trivial LP which has empty constraint matrix */ GLPROW *row; GLPCOL *col; int i, j; double p_infeas, d_infeas, zeta; P->valid = 0; P->pbs_stat = P->dbs_stat = GLP_FEAS; P->obj_val = P->c0; P->some = 0; p_infeas = d_infeas = 0.0; /* make all auxiliary variables basic */ for (i = 1; i <= P->m; i++) { row = P->row[i]; row->stat = GLP_BS; row->prim = row->dual = 0.0; /* check primal feasibility */ if (row->type == GLP_LO || row->type == GLP_DB || row->type == GLP_FX) { /* row has lower bound */ if (row->lb > + parm->tol_bnd) { P->pbs_stat = GLP_NOFEAS; if (P->some == 0 && parm->meth != GLP_PRIMAL) P->some = i; } if (p_infeas < + row->lb) p_infeas = + row->lb; } if (row->type == GLP_UP || row->type == GLP_DB || row->type == GLP_FX) { /* row has upper bound */ if (row->ub < - parm->tol_bnd) { P->pbs_stat = GLP_NOFEAS; if (P->some == 0 && parm->meth != GLP_PRIMAL) P->some = i; } if (p_infeas < - row->ub) p_infeas = - row->ub; } } /* determine scale factor for the objective row */ zeta = 1.0; for (j = 1; j <= P->n; j++) { col = P->col[j]; if (zeta < fabs(col->coef)) zeta = fabs(col->coef); } zeta = (P->dir == GLP_MIN ? +1.0 : -1.0) / zeta; /* make all structural variables non-basic */ for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->type == GLP_FR) col->stat = GLP_NF, col->prim = 0.0; else if (col->type == GLP_LO) lo: col->stat = GLP_NL, col->prim = col->lb; else if (col->type == GLP_UP) up: col->stat = GLP_NU, col->prim = col->ub; else if (col->type == GLP_DB) { if (zeta * col->coef > 0.0) goto lo; else if (zeta * col->coef < 0.0) goto up; else if (fabs(col->lb) <= fabs(col->ub)) goto lo; else goto up; } else if (col->type == GLP_FX) col->stat = GLP_NS, col->prim = col->lb; col->dual = col->coef; P->obj_val += col->coef * col->prim; /* check dual feasibility */ if (col->type == GLP_FR || col->type == GLP_LO) { /* column has no upper bound */ if (zeta * col->dual < - parm->tol_dj) { P->dbs_stat = GLP_NOFEAS; if (P->some == 0 && parm->meth == GLP_PRIMAL) P->some = P->m + j; } if (d_infeas < - zeta * col->dual) d_infeas = - zeta * col->dual; } if (col->type == GLP_FR || col->type == GLP_UP) { /* column has no lower bound */ if (zeta * col->dual > + parm->tol_dj) { P->dbs_stat = GLP_NOFEAS; if (P->some == 0 && parm->meth == GLP_PRIMAL) P->some = P->m + j; } if (d_infeas < + zeta * col->dual) d_infeas = + zeta * col->dual; } } /* simulate the simplex solver output */ if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) { xprintf("~%6d: obj = %17.9e infeas = %10.3e\n", P->it_cnt, P->obj_val, parm->meth == GLP_PRIMAL ? p_infeas : d_infeas); } if (parm->msg_lev >= GLP_MSG_ALL && parm->out_dly == 0) { if (P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS) xprintf("OPTIMAL SOLUTION FOUND\n"); else if (P->pbs_stat == GLP_NOFEAS) xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); else if (parm->meth == GLP_PRIMAL) xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); else xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); } return; } static int solve_lp(glp_prob *P, const glp_smcp *parm) { /* solve LP directly without using the preprocessor */ int ret; if (!glp_bf_exists(P)) { ret = glp_factorize(P); if (ret == 0) ; else if (ret == GLP_EBADB) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: initial basis is invalid\n"); } else if (ret == GLP_ESING) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: initial basis is singular\n"); } else if (ret == GLP_ECOND) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf( "glp_simplex: initial basis is ill-conditioned\n"); } else xassert(ret != ret); if (ret != 0) goto done; } if (parm->meth == GLP_PRIMAL) ret = spx_primal(P, parm); else if (parm->meth == GLP_DUALP) { ret = spx_dual(P, parm); if (ret == GLP_EFAIL && P->valid) ret = spx_primal(P, parm); } else if (parm->meth == GLP_DUAL) ret = spx_dual(P, parm); else xassert(parm != parm); done: return ret; } static int preprocess_and_solve_lp(glp_prob *P, const glp_smcp *parm) { /* solve LP using the preprocessor */ NPP *npp; glp_prob *lp = NULL; glp_bfcp bfcp; int ret; if (parm->msg_lev >= GLP_MSG_ALL) xprintf("Preprocessing...\n"); /* create preprocessor workspace */ npp = npp_create_wksp(); /* load original problem into the preprocessor workspace */ npp_load_prob(npp, P, GLP_OFF, GLP_SOL, GLP_OFF); /* process LP prior to applying primal/dual simplex method */ ret = npp_simplex(npp, parm); if (ret == 0) ; else if (ret == GLP_ENOPFS) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n"); } else if (ret == GLP_ENODFS) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); } else xassert(ret != ret); if (ret != 0) goto done; /* build transformed LP */ lp = glp_create_prob(); npp_build_prob(npp, lp); /* if the transformed LP is empty, it has empty solution, which is optimal */ if (lp->m == 0 && lp->n == 0) { lp->pbs_stat = lp->dbs_stat = GLP_FEAS; lp->obj_val = lp->c0; if (parm->msg_lev >= GLP_MSG_ON && parm->out_dly == 0) { xprintf("~%6d: obj = %17.9e infeas = %10.3e\n", P->it_cnt, lp->obj_val, 0.0); } if (parm->msg_lev >= GLP_MSG_ALL) xprintf("OPTIMAL SOLUTION FOUND BY LP PREPROCESSOR\n"); goto post; } if (parm->msg_lev >= GLP_MSG_ALL) { xprintf("%d row%s, %d column%s, %d non-zero%s\n", lp->m, lp->m == 1 ? "" : "s", lp->n, lp->n == 1 ? "" : "s", lp->nnz, lp->nnz == 1 ? "" : "s"); } /* inherit basis factorization control parameters */ glp_get_bfcp(P, &bfcp); glp_set_bfcp(lp, &bfcp); /* scale the transformed problem */ { ENV *env = get_env_ptr(); int term_out = env->term_out; if (!term_out || parm->msg_lev < GLP_MSG_ALL) env->term_out = GLP_OFF; else env->term_out = GLP_ON; glp_scale_prob(lp, GLP_SF_AUTO); env->term_out = term_out; } /* build advanced initial basis */ { ENV *env = get_env_ptr(); int term_out = env->term_out; if (!term_out || parm->msg_lev < GLP_MSG_ALL) env->term_out = GLP_OFF; else env->term_out = GLP_ON; glp_adv_basis(lp, 0); env->term_out = term_out; } /* solve the transformed LP */ lp->it_cnt = P->it_cnt; ret = solve_lp(lp, parm); P->it_cnt = lp->it_cnt; /* only optimal solution can be postprocessed */ if (!(ret == 0 && lp->pbs_stat == GLP_FEAS && lp->dbs_stat == GLP_FEAS)) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: unable to recover undefined or non-op" "timal solution\n"); if (ret == 0) { if (lp->pbs_stat == GLP_NOFEAS) ret = GLP_ENOPFS; else if (lp->dbs_stat == GLP_NOFEAS) ret = GLP_ENODFS; else xassert(lp != lp); } goto done; } post: /* postprocess solution from the transformed LP */ npp_postprocess(npp, lp); /* the transformed LP is no longer needed */ glp_delete_prob(lp), lp = NULL; /* store solution to the original problem */ npp_unload_sol(npp, P); /* the original LP has been successfully solved */ ret = 0; done: /* delete the transformed LP, if it exists */ if (lp != NULL) glp_delete_prob(lp); /* delete preprocessor workspace */ npp_delete_wksp(npp); return ret; } int glp_simplex(glp_prob *P, const glp_smcp *parm) { /* solve LP problem with the simplex method */ glp_smcp _parm; int i, j, ret; /* check problem object */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_simplex: P = %p; invalid problem object\n", P); if (P->tree != NULL && P->tree->reason != 0) xerror("glp_simplex: operation not allowed\n"); /* check control parameters */ if (parm == NULL) parm = &_parm, glp_init_smcp((glp_smcp *)parm); if (!(parm->msg_lev == GLP_MSG_OFF || parm->msg_lev == GLP_MSG_ERR || parm->msg_lev == GLP_MSG_ON || parm->msg_lev == GLP_MSG_ALL || parm->msg_lev == GLP_MSG_DBG)) xerror("glp_simplex: msg_lev = %d; invalid parameter\n", parm->msg_lev); if (!(parm->meth == GLP_PRIMAL || parm->meth == GLP_DUALP || parm->meth == GLP_DUAL)) xerror("glp_simplex: meth = %d; invalid parameter\n", parm->meth); if (!(parm->pricing == GLP_PT_STD || parm->pricing == GLP_PT_PSE)) xerror("glp_simplex: pricing = %d; invalid parameter\n", parm->pricing); if (!(parm->r_test == GLP_RT_STD || parm->r_test == GLP_RT_HAR)) xerror("glp_simplex: r_test = %d; invalid parameter\n", parm->r_test); if (!(0.0 < parm->tol_bnd && parm->tol_bnd < 1.0)) xerror("glp_simplex: tol_bnd = %g; invalid parameter\n", parm->tol_bnd); if (!(0.0 < parm->tol_dj && parm->tol_dj < 1.0)) xerror("glp_simplex: tol_dj = %g; invalid parameter\n", parm->tol_dj); if (!(0.0 < parm->tol_piv && parm->tol_piv < 1.0)) xerror("glp_simplex: tol_piv = %g; invalid parameter\n", parm->tol_piv); if (parm->it_lim < 0) xerror("glp_simplex: it_lim = %d; invalid parameter\n", parm->it_lim); if (parm->tm_lim < 0) xerror("glp_simplex: tm_lim = %d; invalid parameter\n", parm->tm_lim); if (parm->out_frq < 1) xerror("glp_simplex: out_frq = %d; invalid parameter\n", parm->out_frq); if (parm->out_dly < 0) xerror("glp_simplex: out_dly = %d; invalid parameter\n", parm->out_dly); if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF)) xerror("glp_simplex: presolve = %d; invalid parameter\n", parm->presolve); /* basic solution is currently undefined */ P->pbs_stat = P->dbs_stat = GLP_UNDEF; P->obj_val = 0.0; P->some = 0; /* check bounds of double-bounded variables */ for (i = 1; i <= P->m; i++) { GLPROW *row = P->row[i]; if (row->type == GLP_DB && row->lb >= row->ub) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: row %d: lb = %g, ub = %g; incorrec" "t bounds\n", i, row->lb, row->ub); ret = GLP_EBOUND; goto done; } } for (j = 1; j <= P->n; j++) { GLPCOL *col = P->col[j]; if (col->type == GLP_DB && col->lb >= col->ub) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_simplex: column %d: lb = %g, ub = %g; incor" "rect bounds\n", j, col->lb, col->ub); ret = GLP_EBOUND; goto done; } } /* solve LP problem */ if (parm->msg_lev >= GLP_MSG_ALL) { xprintf("GLPK Simplex Optimizer, v%s\n", glp_version()); xprintf("%d row%s, %d column%s, %d non-zero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", P->nnz, P->nnz == 1 ? "" : "s"); } if (P->nnz == 0) trivial_lp(P, parm), ret = 0; else if (!parm->presolve) ret = solve_lp(P, parm); else ret = preprocess_and_solve_lp(P, parm); done: /* return to the application program */ return ret; } /*********************************************************************** * NAME * * glp_init_smcp - initialize simplex method control parameters * * SYNOPSIS * * void glp_init_smcp(glp_smcp *parm); * * DESCRIPTION * * The routine glp_init_smcp initializes control parameters, which are * used by the simplex solver, with default values. * * Default values of the control parameters are stored in a glp_smcp * structure, which the parameter parm points to. */ void glp_init_smcp(glp_smcp *parm) { parm->msg_lev = GLP_MSG_ALL; parm->meth = GLP_PRIMAL; parm->pricing = GLP_PT_PSE; parm->r_test = GLP_RT_HAR; parm->tol_bnd = 1e-7; parm->tol_dj = 1e-7; parm->tol_piv = 1e-10; parm->obj_ll = -DBL_MAX; parm->obj_ul = +DBL_MAX; parm->it_lim = INT_MAX; parm->tm_lim = INT_MAX; parm->out_frq = 500; parm->out_dly = 0; parm->presolve = GLP_OFF; return; } /*********************************************************************** * NAME * * glp_get_status - retrieve generic status of basic solution * * SYNOPSIS * * int glp_get_status(glp_prob *lp); * * RETURNS * * The routine glp_get_status reports the generic status of the basic * solution for the specified problem object as follows: * * GLP_OPT - solution is optimal; * GLP_FEAS - solution is feasible; * GLP_INFEAS - solution is infeasible; * GLP_NOFEAS - problem has no feasible solution; * GLP_UNBND - problem has unbounded solution; * GLP_UNDEF - solution is undefined. */ int glp_get_status(glp_prob *lp) { int status; status = glp_get_prim_stat(lp); switch (status) { case GLP_FEAS: switch (glp_get_dual_stat(lp)) { case GLP_FEAS: status = GLP_OPT; break; case GLP_NOFEAS: status = GLP_UNBND; break; case GLP_UNDEF: case GLP_INFEAS: status = status; break; default: xassert(lp != lp); } break; case GLP_UNDEF: case GLP_INFEAS: case GLP_NOFEAS: status = status; break; default: xassert(lp != lp); } return status; } /*********************************************************************** * NAME * * glp_get_prim_stat - retrieve status of primal basic solution * * SYNOPSIS * * int glp_get_prim_stat(glp_prob *lp); * * RETURNS * * The routine glp_get_prim_stat reports the status of the primal basic * solution for the specified problem object as follows: * * GLP_UNDEF - primal solution is undefined; * GLP_FEAS - primal solution is feasible; * GLP_INFEAS - primal solution is infeasible; * GLP_NOFEAS - no primal feasible solution exists. */ int glp_get_prim_stat(glp_prob *lp) { int pbs_stat = lp->pbs_stat; return pbs_stat; } /*********************************************************************** * NAME * * glp_get_dual_stat - retrieve status of dual basic solution * * SYNOPSIS * * int glp_get_dual_stat(glp_prob *lp); * * RETURNS * * The routine glp_get_dual_stat reports the status of the dual basic * solution for the specified problem object as follows: * * GLP_UNDEF - dual solution is undefined; * GLP_FEAS - dual solution is feasible; * GLP_INFEAS - dual solution is infeasible; * GLP_NOFEAS - no dual feasible solution exists. */ int glp_get_dual_stat(glp_prob *lp) { int dbs_stat = lp->dbs_stat; return dbs_stat; } /*********************************************************************** * NAME * * glp_get_obj_val - retrieve objective value (basic solution) * * SYNOPSIS * * double glp_get_obj_val(glp_prob *lp); * * RETURNS * * The routine glp_get_obj_val returns value of the objective function * for basic solution. */ double glp_get_obj_val(glp_prob *lp) { /*struct LPXCPS *cps = lp->cps;*/ double z; z = lp->obj_val; /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ return z; } /*********************************************************************** * NAME * * glp_get_row_stat - retrieve row status * * SYNOPSIS * * int glp_get_row_stat(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_stat returns current status assigned to the * auxiliary variable associated with i-th row as follows: * * GLP_BS - basic variable; * GLP_NL - non-basic variable on its lower bound; * GLP_NU - non-basic variable on its upper bound; * GLP_NF - non-basic free (unbounded) variable; * GLP_NS - non-basic fixed variable. */ int glp_get_row_stat(glp_prob *lp, int i) { if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_stat: i = %d; row number out of range\n", i); return lp->row[i]->stat; } /*********************************************************************** * NAME * * glp_get_row_prim - retrieve row primal value (basic solution) * * SYNOPSIS * * double glp_get_row_prim(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_prim returns primal value of the auxiliary * variable associated with i-th row. */ double glp_get_row_prim(glp_prob *lp, int i) { /*struct LPXCPS *cps = lp->cps;*/ double prim; if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_prim: i = %d; row number out of range\n", i); prim = lp->row[i]->prim; /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/ return prim; } /*********************************************************************** * NAME * * glp_get_row_dual - retrieve row dual value (basic solution) * * SYNOPSIS * * double glp_get_row_dual(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_dual returns dual value (i.e. reduced cost) * of the auxiliary variable associated with i-th row. */ double glp_get_row_dual(glp_prob *lp, int i) { /*struct LPXCPS *cps = lp->cps;*/ double dual; if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_dual: i = %d; row number out of range\n", i); dual = lp->row[i]->dual; /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/ return dual; } /*********************************************************************** * NAME * * glp_get_col_stat - retrieve column status * * SYNOPSIS * * int glp_get_col_stat(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_stat returns current status assigned to the * structural variable associated with j-th column as follows: * * GLP_BS - basic variable; * GLP_NL - non-basic variable on its lower bound; * GLP_NU - non-basic variable on its upper bound; * GLP_NF - non-basic free (unbounded) variable; * GLP_NS - non-basic fixed variable. */ int glp_get_col_stat(glp_prob *lp, int j) { if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_stat: j = %d; column number out of range\n" , j); return lp->col[j]->stat; } /*********************************************************************** * NAME * * glp_get_col_prim - retrieve column primal value (basic solution) * * SYNOPSIS * * double glp_get_col_prim(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_prim returns primal value of the structural * variable associated with j-th column. */ double glp_get_col_prim(glp_prob *lp, int j) { /*struct LPXCPS *cps = lp->cps;*/ double prim; if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_prim: j = %d; column number out of range\n" , j); prim = lp->col[j]->prim; /*if (cps->round && fabs(prim) < 1e-9) prim = 0.0;*/ return prim; } /*********************************************************************** * NAME * * glp_get_col_dual - retrieve column dual value (basic solution) * * SYNOPSIS * * double glp_get_col_dual(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_dual returns dual value (i.e. reduced cost) * of the structural variable associated with j-th column. */ double glp_get_col_dual(glp_prob *lp, int j) { /*struct LPXCPS *cps = lp->cps;*/ double dual; if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_dual: j = %d; column number out of range\n" , j); dual = lp->col[j]->dual; /*if (cps->round && fabs(dual) < 1e-9) dual = 0.0;*/ return dual; } /*********************************************************************** * NAME * * glp_get_unbnd_ray - determine variable causing unboundedness * * SYNOPSIS * * int glp_get_unbnd_ray(glp_prob *lp); * * RETURNS * * The routine glp_get_unbnd_ray returns the number k of a variable, * which causes primal or dual unboundedness. If 1 <= k <= m, it is * k-th auxiliary variable, and if m+1 <= k <= m+n, it is (k-m)-th * structural variable, where m is the number of rows, n is the number * of columns in the problem object. If such variable is not defined, * the routine returns 0. * * COMMENTS * * If it is not exactly known which version of the simplex solver * detected unboundedness, i.e. whether the unboundedness is primal or * dual, it is sufficient to check the status of the variable reported * with the routine glp_get_row_stat or glp_get_col_stat. If the * variable is non-basic, the unboundedness is primal, otherwise, if * the variable is basic, the unboundedness is dual (the latter case * means that the problem has no primal feasible dolution). */ int glp_get_unbnd_ray(glp_prob *lp) { int k; k = lp->some; xassert(k >= 0); if (k > lp->m + lp->n) k = 0; return k; } /* eof */ glpk-4.52.1/src/glpapi07.c0000644000062000006210000003517712175147600014314 0ustar maomkpasswd/* glpapi07.c (exact simplex solver) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "glplib.h" #include "glpssx.h" /*********************************************************************** * NAME * * glp_exact - solve LP problem in exact arithmetic * * SYNOPSIS * * int glp_exact(glp_prob *lp, const glp_smcp *parm); * * DESCRIPTION * * The routine glp_exact is a tentative implementation of the primal * two-phase simplex method based on exact (rational) arithmetic. It is * similar to the routine glp_simplex, however, for all internal * computations it uses arithmetic of rational numbers, which is exact * in mathematical sense, i.e. free of round-off errors unlike floating * point arithmetic. * * Note that the routine glp_exact uses inly two control parameters * passed in the structure glp_smcp, namely, it_lim and tm_lim. * * RETURNS * * 0 The LP problem instance has been successfully solved. This code * does not necessarily mean that the solver has found optimal * solution. It only means that the solution process was successful. * * GLP_EBADB * Unable to start the search, because the initial basis specified * in the problem object is invalid--the number of basic (auxiliary * and structural) variables is not the same as the number of rows in * the problem object. * * GLP_ESING * Unable to start the search, because the basis matrix correspodning * to the initial basis is exactly singular. * * GLP_EBOUND * Unable to start the search, because some double-bounded variables * have incorrect bounds. * * GLP_EFAIL * The problem has no rows/columns. * * GLP_EITLIM * The search was prematurely terminated, because the simplex * iteration limit has been exceeded. * * GLP_ETMLIM * The search was prematurely terminated, because the time limit has * been exceeded. */ static void set_d_eps(mpq_t x, double val) { /* convert double val to rational x obtaining a more adequate fraction than provided by mpq_set_d due to allowing a small approximation error specified by a given relative tolerance; for example, mpq_set_d would give the following 1/3 ~= 0.333333333333333314829616256247391... -> -> 6004799503160661/18014398509481984 while this routine gives exactly 1/3 */ int s, n, j; double f, p, q, eps = 1e-9; mpq_t temp; xassert(-DBL_MAX <= val && val <= +DBL_MAX); #if 1 /* 30/VII-2008 */ if (val == floor(val)) { /* if val is integral, do not approximate */ mpq_set_d(x, val); goto done; } #endif if (val > 0.0) s = +1; else if (val < 0.0) s = -1; else { mpq_set_si(x, 0, 1); goto done; } f = frexp(fabs(val), &n); /* |val| = f * 2^n, where 0.5 <= f < 1.0 */ fp2rat(f, 0.1 * eps, &p, &q); /* f ~= p / q, where p and q are integers */ mpq_init(temp); mpq_set_d(x, p); mpq_set_d(temp, q); mpq_div(x, x, temp); mpq_set_si(temp, 1, 1); for (j = 1; j <= abs(n); j++) mpq_add(temp, temp, temp); if (n > 0) mpq_mul(x, x, temp); else if (n < 0) mpq_div(x, x, temp); mpq_clear(temp); if (s < 0) mpq_neg(x, x); /* check that the desired tolerance has been attained */ xassert(fabs(val - mpq_get_d(x)) <= eps * (1.0 + fabs(val))); done: return; } static void load_data(SSX *ssx, LPX *lp) { /* load LP problem data into simplex solver workspace */ int m = ssx->m; int n = ssx->n; int nnz = ssx->A_ptr[n+1]-1; int j, k, type, loc, len, *ind; double lb, ub, coef, *val; xassert(lpx_get_num_rows(lp) == m); xassert(lpx_get_num_cols(lp) == n); xassert(lpx_get_num_nz(lp) == nnz); /* types and bounds of rows and columns */ for (k = 1; k <= m+n; k++) { if (k <= m) { type = lpx_get_row_type(lp, k); lb = lpx_get_row_lb(lp, k); ub = lpx_get_row_ub(lp, k); } else { type = lpx_get_col_type(lp, k-m); lb = lpx_get_col_lb(lp, k-m); ub = lpx_get_col_ub(lp, k-m); } switch (type) { case LPX_FR: type = SSX_FR; break; case LPX_LO: type = SSX_LO; break; case LPX_UP: type = SSX_UP; break; case LPX_DB: type = SSX_DB; break; case LPX_FX: type = SSX_FX; break; default: xassert(type != type); } ssx->type[k] = type; set_d_eps(ssx->lb[k], lb); set_d_eps(ssx->ub[k], ub); } /* optimization direction */ switch (lpx_get_obj_dir(lp)) { case LPX_MIN: ssx->dir = SSX_MIN; break; case LPX_MAX: ssx->dir = SSX_MAX; break; default: xassert(lp != lp); } /* objective coefficients */ for (k = 0; k <= m+n; k++) { if (k == 0) coef = lpx_get_obj_coef(lp, 0); else if (k <= m) coef = 0.0; else coef = lpx_get_obj_coef(lp, k-m); set_d_eps(ssx->coef[k], coef); } /* constraint coefficients */ ind = xcalloc(1+m, sizeof(int)); val = xcalloc(1+m, sizeof(double)); loc = 0; for (j = 1; j <= n; j++) { ssx->A_ptr[j] = loc+1; len = lpx_get_mat_col(lp, j, ind, val); for (k = 1; k <= len; k++) { loc++; ssx->A_ind[loc] = ind[k]; set_d_eps(ssx->A_val[loc], val[k]); } } xassert(loc == nnz); xfree(ind); xfree(val); return; } static int load_basis(SSX *ssx, LPX *lp) { /* load current LP basis into simplex solver workspace */ int m = ssx->m; int n = ssx->n; int *type = ssx->type; int *stat = ssx->stat; int *Q_row = ssx->Q_row; int *Q_col = ssx->Q_col; int i, j, k; xassert(lpx_get_num_rows(lp) == m); xassert(lpx_get_num_cols(lp) == n); /* statuses of rows and columns */ for (k = 1; k <= m+n; k++) { if (k <= m) stat[k] = lpx_get_row_stat(lp, k); else stat[k] = lpx_get_col_stat(lp, k-m); switch (stat[k]) { case LPX_BS: stat[k] = SSX_BS; break; case LPX_NL: stat[k] = SSX_NL; xassert(type[k] == SSX_LO || type[k] == SSX_DB); break; case LPX_NU: stat[k] = SSX_NU; xassert(type[k] == SSX_UP || type[k] == SSX_DB); break; case LPX_NF: stat[k] = SSX_NF; xassert(type[k] == SSX_FR); break; case LPX_NS: stat[k] = SSX_NS; xassert(type[k] == SSX_FX); break; default: xassert(stat != stat); } } /* build permutation matix Q */ i = j = 0; for (k = 1; k <= m+n; k++) { if (stat[k] == SSX_BS) { i++; if (i > m) return 1; Q_row[k] = i, Q_col[i] = k; } else { j++; if (j > n) return 1; Q_row[k] = m+j, Q_col[m+j] = k; } } xassert(i == m && j == n); return 0; } int glp_exact(glp_prob *lp, const glp_smcp *parm) { glp_smcp _parm; SSX *ssx; int m = lpx_get_num_rows(lp); int n = lpx_get_num_cols(lp); int nnz = lpx_get_num_nz(lp); int i, j, k, type, pst, dst, ret, *stat; double lb, ub, *prim, *dual, sum; if (parm == NULL) parm = &_parm, glp_init_smcp((glp_smcp *)parm); /* check control parameters */ if (parm->it_lim < 0) xerror("glp_exact: it_lim = %d; invalid parameter\n", parm->it_lim); if (parm->tm_lim < 0) xerror("glp_exact: tm_lim = %d; invalid parameter\n", parm->tm_lim); /* the problem must have at least one row and one column */ if (!(m > 0 && n > 0)) { xprintf("glp_exact: problem has no rows/columns\n"); return GLP_EFAIL; } #if 1 /* basic solution is currently undefined */ lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; lp->obj_val = 0.0; lp->some = 0; #endif /* check that all double-bounded variables have correct bounds */ for (k = 1; k <= m+n; k++) { if (k <= m) { type = lpx_get_row_type(lp, k); lb = lpx_get_row_lb(lp, k); ub = lpx_get_row_ub(lp, k); } else { type = lpx_get_col_type(lp, k-m); lb = lpx_get_col_lb(lp, k-m); ub = lpx_get_col_ub(lp, k-m); } if (type == LPX_DB && lb >= ub) { xprintf("glp_exact: %s %d has invalid bounds\n", k <= m ? "row" : "column", k <= m ? k : k-m); return GLP_EBOUND; } } /* create the simplex solver workspace */ xprintf("glp_exact: %d rows, %d columns, %d non-zeros\n", m, n, nnz); #ifdef HAVE_GMP xprintf("GNU MP bignum library is being used\n"); #else xprintf("GLPK bignum module is being used\n"); xprintf("(Consider installing GNU MP to attain a much better perf" "ormance.)\n"); #endif ssx = ssx_create(m, n, nnz); /* load LP problem data into the workspace */ load_data(ssx, lp); /* load current LP basis into the workspace */ if (load_basis(ssx, lp)) { xprintf("glp_exact: initial LP basis is invalid\n"); ret = GLP_EBADB; goto done; } /* inherit some control parameters from the LP object */ #if 0 ssx->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM); ssx->it_cnt = lpx_get_int_parm(lp, LPX_K_ITCNT); ssx->tm_lim = lpx_get_real_parm(lp, LPX_K_TMLIM); #else ssx->it_lim = parm->it_lim; ssx->it_cnt = lp->it_cnt; ssx->tm_lim = (double)parm->tm_lim / 1000.0; #endif ssx->out_frq = 5.0; ssx->tm_beg = xtime(); #if 0 /* 10/VI-2013 */ ssx->tm_lag = xlset(0); #else ssx->tm_lag = 0.0; #endif /* solve LP */ ret = ssx_driver(ssx); /* copy back some statistics to the LP object */ #if 0 lpx_set_int_parm(lp, LPX_K_ITLIM, ssx->it_lim); lpx_set_int_parm(lp, LPX_K_ITCNT, ssx->it_cnt); lpx_set_real_parm(lp, LPX_K_TMLIM, ssx->tm_lim); #else lp->it_cnt = ssx->it_cnt; #endif /* analyze the return code */ switch (ret) { case 0: /* optimal solution found */ ret = 0; pst = LPX_P_FEAS, dst = LPX_D_FEAS; break; case 1: /* problem has no feasible solution */ ret = 0; pst = LPX_P_NOFEAS, dst = LPX_D_INFEAS; break; case 2: /* problem has unbounded solution */ ret = 0; pst = LPX_P_FEAS, dst = LPX_D_NOFEAS; #if 1 xassert(1 <= ssx->q && ssx->q <= n); lp->some = ssx->Q_col[m + ssx->q]; xassert(1 <= lp->some && lp->some <= m+n); #endif break; case 3: /* iteration limit exceeded (phase I) */ ret = GLP_EITLIM; pst = LPX_P_INFEAS, dst = LPX_D_INFEAS; break; case 4: /* iteration limit exceeded (phase II) */ ret = GLP_EITLIM; pst = LPX_P_FEAS, dst = LPX_D_INFEAS; break; case 5: /* time limit exceeded (phase I) */ ret = GLP_ETMLIM; pst = LPX_P_INFEAS, dst = LPX_D_INFEAS; break; case 6: /* time limit exceeded (phase II) */ ret = GLP_ETMLIM; pst = LPX_P_FEAS, dst = LPX_D_INFEAS; break; case 7: /* initial basis matrix is singular */ ret = GLP_ESING; goto done; default: xassert(ret != ret); } /* obtain final basic solution components */ stat = xcalloc(1+m+n, sizeof(int)); prim = xcalloc(1+m+n, sizeof(double)); dual = xcalloc(1+m+n, sizeof(double)); for (k = 1; k <= m+n; k++) { if (ssx->stat[k] == SSX_BS) { i = ssx->Q_row[k]; /* x[k] = xB[i] */ xassert(1 <= i && i <= m); stat[k] = LPX_BS; prim[k] = mpq_get_d(ssx->bbar[i]); dual[k] = 0.0; } else { j = ssx->Q_row[k] - m; /* x[k] = xN[j] */ xassert(1 <= j && j <= n); switch (ssx->stat[k]) { case SSX_NF: stat[k] = LPX_NF; prim[k] = 0.0; break; case SSX_NL: stat[k] = LPX_NL; prim[k] = mpq_get_d(ssx->lb[k]); break; case SSX_NU: stat[k] = LPX_NU; prim[k] = mpq_get_d(ssx->ub[k]); break; case SSX_NS: stat[k] = LPX_NS; prim[k] = mpq_get_d(ssx->lb[k]); break; default: xassert(ssx != ssx); } dual[k] = mpq_get_d(ssx->cbar[j]); } } /* and store them into the LP object */ pst = pst - LPX_P_UNDEF + GLP_UNDEF; dst = dst - LPX_D_UNDEF + GLP_UNDEF; for (k = 1; k <= m+n; k++) stat[k] = stat[k] - LPX_BS + GLP_BS; sum = lpx_get_obj_coef(lp, 0); for (j = 1; j <= n; j++) sum += lpx_get_obj_coef(lp, j) * prim[m+j]; lpx_put_solution(lp, 1, &pst, &dst, &sum, &stat[0], &prim[0], &dual[0], &stat[m], &prim[m], &dual[m]); xfree(stat); xfree(prim); xfree(dual); done: /* delete the simplex solver workspace */ ssx_delete(ssx); /* return to the application program */ return ret; } /* eof */ glpk-4.52.1/src/glpapi08.c0000644000062000006210000003031512175147600014302 0ustar maomkpasswd/* glpapi08.c (interior-point method routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "glpipm.h" #include "glpnpp.h" /*********************************************************************** * NAME * * glp_interior - solve LP problem with the interior-point method * * SYNOPSIS * * int glp_interior(glp_prob *P, const glp_iptcp *parm); * * The routine glp_interior is a driver to the LP solver based on the * interior-point method. * * The interior-point solver has a set of control parameters. Values of * the control parameters can be passed in a structure glp_iptcp, which * the parameter parm points to. * * Currently this routine implements an easy variant of the primal-dual * interior-point method based on Mehrotra's technique. * * This routine transforms the original LP problem to an equivalent LP * problem in the standard formulation (all constraints are equalities, * all variables are non-negative), calls the routine ipm_main to solve * the transformed problem, and then transforms an obtained solution to * the solution of the original problem. * * RETURNS * * 0 The LP problem instance has been successfully solved. This code * does not necessarily mean that the solver has found optimal * solution. It only means that the solution process was successful. * * GLP_EFAIL * The problem has no rows/columns. * * GLP_ENOCVG * Very slow convergence or divergence. * * GLP_EITLIM * Iteration limit exceeded. * * GLP_EINSTAB * Numerical instability on solving Newtonian system. */ static void transform(NPP *npp) { /* transform LP to the standard formulation */ NPPROW *row, *prev_row; NPPCOL *col, *prev_col; for (row = npp->r_tail; row != NULL; row = prev_row) { prev_row = row->prev; if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) npp_free_row(npp, row); else if (row->lb == -DBL_MAX) npp_leq_row(npp, row); else if (row->ub == +DBL_MAX) npp_geq_row(npp, row); else if (row->lb != row->ub) { if (fabs(row->lb) < fabs(row->ub)) npp_geq_row(npp, row); else npp_leq_row(npp, row); } } for (col = npp->c_tail; col != NULL; col = prev_col) { prev_col = col->prev; if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) npp_free_col(npp, col); else if (col->lb == -DBL_MAX) npp_ubnd_col(npp, col); else if (col->ub == +DBL_MAX) { if (col->lb != 0.0) npp_lbnd_col(npp, col); } else if (col->lb != col->ub) { if (fabs(col->lb) < fabs(col->ub)) { if (col->lb != 0.0) npp_lbnd_col(npp, col); } else npp_ubnd_col(npp, col); npp_dbnd_col(npp, col); } else npp_fixed_col(npp, col); } for (row = npp->r_head; row != NULL; row = row->next) xassert(row->lb == row->ub); for (col = npp->c_head; col != NULL; col = col->next) xassert(col->lb == 0.0 && col->ub == +DBL_MAX); return; } int glp_interior(glp_prob *P, const glp_iptcp *parm) { glp_iptcp _parm; GLPROW *row; GLPCOL *col; NPP *npp = NULL; glp_prob *prob = NULL; int i, j, ret; /* check control parameters */ if (parm == NULL) glp_init_iptcp(&_parm), parm = &_parm; if (!(parm->msg_lev == GLP_MSG_OFF || parm->msg_lev == GLP_MSG_ERR || parm->msg_lev == GLP_MSG_ON || parm->msg_lev == GLP_MSG_ALL)) xerror("glp_interior: msg_lev = %d; invalid parameter\n", parm->msg_lev); if (!(parm->ord_alg == GLP_ORD_NONE || parm->ord_alg == GLP_ORD_QMD || parm->ord_alg == GLP_ORD_AMD || parm->ord_alg == GLP_ORD_SYMAMD)) xerror("glp_interior: ord_alg = %d; invalid parameter\n", parm->ord_alg); /* interior-point solution is currently undefined */ P->ipt_stat = GLP_UNDEF; P->ipt_obj = 0.0; /* check bounds of double-bounded variables */ for (i = 1; i <= P->m; i++) { row = P->row[i]; if (row->type == GLP_DB && row->lb >= row->ub) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_interior: row %d: lb = %g, ub = %g; incorre" "ct bounds\n", i, row->lb, row->ub); ret = GLP_EBOUND; goto done; } } for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->type == GLP_DB && col->lb >= col->ub) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_interior: column %d: lb = %g, ub = %g; inco" "rrect bounds\n", j, col->lb, col->ub); ret = GLP_EBOUND; goto done; } } /* transform LP to the standard formulation */ if (parm->msg_lev >= GLP_MSG_ALL) xprintf("Original LP has %d row(s), %d column(s), and %d non-z" "ero(s)\n", P->m, P->n, P->nnz); npp = npp_create_wksp(); npp_load_prob(npp, P, GLP_OFF, GLP_IPT, GLP_ON); transform(npp); prob = glp_create_prob(); npp_build_prob(npp, prob); if (parm->msg_lev >= GLP_MSG_ALL) xprintf("Working LP has %d row(s), %d column(s), and %d non-ze" "ro(s)\n", prob->m, prob->n, prob->nnz); #if 1 /* currently empty problem cannot be solved */ if (!(prob->m > 0 && prob->n > 0)) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_interior: unable to solve empty problem\n"); ret = GLP_EFAIL; goto done; } #endif /* scale the resultant LP */ { ENV *env = get_env_ptr(); int term_out = env->term_out; env->term_out = GLP_OFF; glp_scale_prob(prob, GLP_SF_EQ); env->term_out = term_out; } /* warn about dense columns */ if (parm->msg_lev >= GLP_MSG_ON && prob->m >= 200) { int len, cnt = 0; for (j = 1; j <= prob->n; j++) { len = glp_get_mat_col(prob, j, NULL, NULL); if ((double)len >= 0.20 * (double)prob->m) cnt++; } if (cnt == 1) xprintf("WARNING: PROBLEM HAS ONE DENSE COLUMN\n"); else if (cnt > 0) xprintf("WARNING: PROBLEM HAS %d DENSE COLUMNS\n", cnt); } /* solve the transformed LP */ ret = ipm_solve(prob, parm); /* postprocess solution from the transformed LP */ npp_postprocess(npp, prob); /* and store solution to the original LP */ npp_unload_sol(npp, P); done: /* free working program objects */ if (npp != NULL) npp_delete_wksp(npp); if (prob != NULL) glp_delete_prob(prob); /* return to the application program */ return ret; } /*********************************************************************** * NAME * * glp_init_iptcp - initialize interior-point solver control parameters * * SYNOPSIS * * void glp_init_iptcp(glp_iptcp *parm); * * DESCRIPTION * * The routine glp_init_iptcp initializes control parameters, which are * used by the interior-point solver, with default values. * * Default values of the control parameters are stored in the glp_iptcp * structure, which the parameter parm points to. */ void glp_init_iptcp(glp_iptcp *parm) { parm->msg_lev = GLP_MSG_ALL; parm->ord_alg = GLP_ORD_AMD; return; } /*********************************************************************** * NAME * * glp_ipt_status - retrieve status of interior-point solution * * SYNOPSIS * * int glp_ipt_status(glp_prob *lp); * * RETURNS * * The routine glp_ipt_status reports the status of solution found by * the interior-point solver as follows: * * GLP_UNDEF - interior-point solution is undefined; * GLP_OPT - interior-point solution is optimal; * GLP_INFEAS - interior-point solution is infeasible; * GLP_NOFEAS - no feasible solution exists. */ int glp_ipt_status(glp_prob *lp) { int ipt_stat = lp->ipt_stat; return ipt_stat; } /*********************************************************************** * NAME * * glp_ipt_obj_val - retrieve objective value (interior point) * * SYNOPSIS * * double glp_ipt_obj_val(glp_prob *lp); * * RETURNS * * The routine glp_ipt_obj_val returns value of the objective function * for interior-point solution. */ double glp_ipt_obj_val(glp_prob *lp) { /*struct LPXCPS *cps = lp->cps;*/ double z; z = lp->ipt_obj; /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ return z; } /*********************************************************************** * NAME * * glp_ipt_row_prim - retrieve row primal value (interior point) * * SYNOPSIS * * double glp_ipt_row_prim(glp_prob *lp, int i); * * RETURNS * * The routine glp_ipt_row_prim returns primal value of the auxiliary * variable associated with i-th row. */ double glp_ipt_row_prim(glp_prob *lp, int i) { /*struct LPXCPS *cps = lp->cps;*/ double pval; if (!(1 <= i && i <= lp->m)) xerror("glp_ipt_row_prim: i = %d; row number out of range\n", i); pval = lp->row[i]->pval; /*if (cps->round && fabs(pval) < 1e-9) pval = 0.0;*/ return pval; } /*********************************************************************** * NAME * * glp_ipt_row_dual - retrieve row dual value (interior point) * * SYNOPSIS * * double glp_ipt_row_dual(glp_prob *lp, int i); * * RETURNS * * The routine glp_ipt_row_dual returns dual value (i.e. reduced cost) * of the auxiliary variable associated with i-th row. */ double glp_ipt_row_dual(glp_prob *lp, int i) { /*struct LPXCPS *cps = lp->cps;*/ double dval; if (!(1 <= i && i <= lp->m)) xerror("glp_ipt_row_dual: i = %d; row number out of range\n", i); dval = lp->row[i]->dval; /*if (cps->round && fabs(dval) < 1e-9) dval = 0.0;*/ return dval; } /*********************************************************************** * NAME * * glp_ipt_col_prim - retrieve column primal value (interior point) * * SYNOPSIS * * double glp_ipt_col_prim(glp_prob *lp, int j); * * RETURNS * * The routine glp_ipt_col_prim returns primal value of the structural * variable associated with j-th column. */ double glp_ipt_col_prim(glp_prob *lp, int j) { /*struct LPXCPS *cps = lp->cps;*/ double pval; if (!(1 <= j && j <= lp->n)) xerror("glp_ipt_col_prim: j = %d; column number out of range\n" , j); pval = lp->col[j]->pval; /*if (cps->round && fabs(pval) < 1e-9) pval = 0.0;*/ return pval; } /*********************************************************************** * NAME * * glp_ipt_col_dual - retrieve column dual value (interior point) * * SYNOPSIS * * #include "glplpx.h" * double glp_ipt_col_dual(glp_prob *lp, int j); * * RETURNS * * The routine glp_ipt_col_dual returns dual value (i.e. reduced cost) * of the structural variable associated with j-th column. */ double glp_ipt_col_dual(glp_prob *lp, int j) { /*struct LPXCPS *cps = lp->cps;*/ double dval; if (!(1 <= j && j <= lp->n)) xerror("glp_ipt_col_dual: j = %d; column number out of range\n" , j); dval = lp->col[j]->dval; /*if (cps->round && fabs(dval) < 1e-9) dval = 0.0;*/ return dval; } /* eof */ glpk-4.52.1/src/glpapi09.c0000644000062000006210000006163212175147600014311 0ustar maomkpasswd/* glpapi09.c (mixed integer programming routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" #include "glpnpp.h" /*********************************************************************** * NAME * * glp_set_col_kind - set (change) column kind * * SYNOPSIS * * void glp_set_col_kind(glp_prob *mip, int j, int kind); * * DESCRIPTION * * The routine glp_set_col_kind sets (changes) the kind of j-th column * (structural variable) as specified by the parameter kind: * * GLP_CV - continuous variable; * GLP_IV - integer variable; * GLP_BV - binary variable. */ void glp_set_col_kind(glp_prob *mip, int j, int kind) { GLPCOL *col; if (!(1 <= j && j <= mip->n)) xerror("glp_set_col_kind: j = %d; column number out of range\n" , j); col = mip->col[j]; switch (kind) { case GLP_CV: col->kind = GLP_CV; break; case GLP_IV: col->kind = GLP_IV; break; case GLP_BV: col->kind = GLP_IV; if (!(col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0)) glp_set_col_bnds(mip, j, GLP_DB, 0.0, 1.0); break; default: xerror("glp_set_col_kind: j = %d; kind = %d; invalid column" " kind\n", j, kind); } return; } /*********************************************************************** * NAME * * glp_get_col_kind - retrieve column kind * * SYNOPSIS * * int glp_get_col_kind(glp_prob *mip, int j); * * RETURNS * * The routine glp_get_col_kind returns the kind of j-th column, i.e. * the kind of corresponding structural variable, as follows: * * GLP_CV - continuous variable; * GLP_IV - integer variable; * GLP_BV - binary variable */ int glp_get_col_kind(glp_prob *mip, int j) { GLPCOL *col; int kind; if (!(1 <= j && j <= mip->n)) xerror("glp_get_col_kind: j = %d; column number out of range\n" , j); col = mip->col[j]; kind = col->kind; switch (kind) { case GLP_CV: break; case GLP_IV: if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) kind = GLP_BV; break; default: xassert(kind != kind); } return kind; } /*********************************************************************** * NAME * * glp_get_num_int - retrieve number of integer columns * * SYNOPSIS * * int glp_get_num_int(glp_prob *mip); * * RETURNS * * The routine glp_get_num_int returns the current number of columns, * which are marked as integer. */ int glp_get_num_int(glp_prob *mip) { GLPCOL *col; int j, count = 0; for (j = 1; j <= mip->n; j++) { col = mip->col[j]; if (col->kind == GLP_IV) count++; } return count; } /*********************************************************************** * NAME * * glp_get_num_bin - retrieve number of binary columns * * SYNOPSIS * * int glp_get_num_bin(glp_prob *mip); * * RETURNS * * The routine glp_get_num_bin returns the current number of columns, * which are marked as binary. */ int glp_get_num_bin(glp_prob *mip) { GLPCOL *col; int j, count = 0; for (j = 1; j <= mip->n; j++) { col = mip->col[j]; if (col->kind == GLP_IV && col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) count++; } return count; } /*********************************************************************** * NAME * * glp_intopt - solve MIP problem with the branch-and-bound method * * SYNOPSIS * * int glp_intopt(glp_prob *P, const glp_iocp *parm); * * DESCRIPTION * * The routine glp_intopt is a driver to the MIP solver based on the * branch-and-bound method. * * On entry the problem object should contain optimal solution to LP * relaxation (which can be obtained with the routine glp_simplex). * * The MIP solver has a set of control parameters. Values of the control * parameters can be passed in a structure glp_iocp, which the parameter * parm points to. * * The parameter parm can be specified as NULL, in which case the MIP * solver uses default settings. * * RETURNS * * 0 The MIP problem instance has been successfully solved. This code * does not necessarily mean that the solver has found optimal * solution. It only means that the solution process was successful. * * GLP_EBOUND * Unable to start the search, because some double-bounded variables * have incorrect bounds or some integer variables have non-integer * (fractional) bounds. * * GLP_EROOT * Unable to start the search, because optimal basis for initial LP * relaxation is not provided. * * GLP_EFAIL * The search was prematurely terminated due to the solver failure. * * GLP_EMIPGAP * The search was prematurely terminated, because the relative mip * gap tolerance has been reached. * * GLP_ETMLIM * The search was prematurely terminated, because the time limit has * been exceeded. * * GLP_ENOPFS * The MIP problem instance has no primal feasible solution (only if * the MIP presolver is used). * * GLP_ENODFS * LP relaxation of the MIP problem instance has no dual feasible * solution (only if the MIP presolver is used). * * GLP_ESTOP * The search was prematurely terminated by application. */ #if 0 /* 11/VII-2013 */ static int solve_mip(glp_prob *P, const glp_iocp *parm) #else static int solve_mip(glp_prob *P, const glp_iocp *parm, glp_prob *P0 /* problem passed to glp_intopt */, NPP *npp /* preprocessor workspace or NULL */) #endif { /* solve MIP directly without using the preprocessor */ glp_tree *T; int ret; /* optimal basis to LP relaxation must be provided */ if (glp_get_status(P) != GLP_OPT) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: optimal basis to initial LP relaxation" " not provided\n"); ret = GLP_EROOT; goto done; } /* it seems all is ok */ if (parm->msg_lev >= GLP_MSG_ALL) xprintf("Integer optimization begins...\n"); /* create the branch-and-bound tree */ T = ios_create_tree(P, parm); #if 1 /* 11/VII-2013 */ T->P = P0; T->npp = npp; #endif /* solve the problem instance */ ret = ios_driver(T); /* delete the branch-and-bound tree */ ios_delete_tree(T); /* analyze exit code reported by the mip driver */ if (ret == 0) { if (P->mip_stat == GLP_FEAS) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("INTEGER OPTIMAL SOLUTION FOUND\n"); P->mip_stat = GLP_OPT; } else { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n"); P->mip_stat = GLP_NOFEAS; } } else if (ret == GLP_EMIPGAP) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("RELATIVE MIP GAP TOLERANCE REACHED; SEARCH TERMINA" "TED\n"); } else if (ret == GLP_ETMLIM) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); } else if (ret == GLP_EFAIL) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: cannot solve current LP relaxation\n"); } else if (ret == GLP_ESTOP) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("SEARCH TERMINATED BY APPLICATION\n"); } else xassert(ret != ret); done: return ret; } static int preprocess_and_solve_mip(glp_prob *P, const glp_iocp *parm) { /* solve MIP using the preprocessor */ ENV *env = get_env_ptr(); int term_out = env->term_out; NPP *npp; glp_prob *mip = NULL; glp_bfcp bfcp; glp_smcp smcp; int ret; if (parm->msg_lev >= GLP_MSG_ALL) xprintf("Preprocessing...\n"); /* create preprocessor workspace */ npp = npp_create_wksp(); /* load original problem into the preprocessor workspace */ npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF); /* process MIP prior to applying the branch-and-bound method */ if (!term_out || parm->msg_lev < GLP_MSG_ALL) env->term_out = GLP_OFF; else env->term_out = GLP_ON; ret = npp_integer(npp, parm); env->term_out = term_out; if (ret == 0) ; else if (ret == GLP_ENOPFS) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION\n"); } else if (ret == GLP_ENODFS) { if (parm->msg_lev >= GLP_MSG_ALL) xprintf("LP RELAXATION HAS NO DUAL FEASIBLE SOLUTION\n"); } else xassert(ret != ret); if (ret != 0) goto done; /* build transformed MIP */ mip = glp_create_prob(); npp_build_prob(npp, mip); /* if the transformed MIP is empty, it has empty solution, which is optimal */ if (mip->m == 0 && mip->n == 0) { mip->mip_stat = GLP_OPT; mip->mip_obj = mip->c0; if (parm->msg_lev >= GLP_MSG_ALL) { xprintf("Objective value = %17.9e\n", mip->mip_obj); xprintf("INTEGER OPTIMAL SOLUTION FOUND BY MIP PREPROCESSOR" "\n"); } goto post; } /* display some statistics */ if (parm->msg_lev >= GLP_MSG_ALL) { int ni = glp_get_num_int(mip); int nb = glp_get_num_bin(mip); char s[50]; xprintf("%d row%s, %d column%s, %d non-zero%s\n", mip->m, mip->m == 1 ? "" : "s", mip->n, mip->n == 1 ? "" : "s", mip->nnz, mip->nnz == 1 ? "" : "s"); if (nb == 0) strcpy(s, "none of"); else if (ni == 1 && nb == 1) strcpy(s, ""); else if (nb == 1) strcpy(s, "one of"); else if (nb == ni) strcpy(s, "all of"); else sprintf(s, "%d of", nb); xprintf("%d integer variable%s, %s which %s binary\n", ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); } /* inherit basis factorization control parameters */ glp_get_bfcp(P, &bfcp); glp_set_bfcp(mip, &bfcp); /* scale the transformed problem */ if (!term_out || parm->msg_lev < GLP_MSG_ALL) env->term_out = GLP_OFF; else env->term_out = GLP_ON; glp_scale_prob(mip, GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP); env->term_out = term_out; /* build advanced initial basis */ if (!term_out || parm->msg_lev < GLP_MSG_ALL) env->term_out = GLP_OFF; else env->term_out = GLP_ON; glp_adv_basis(mip, 0); env->term_out = term_out; /* solve initial LP relaxation */ if (parm->msg_lev >= GLP_MSG_ALL) xprintf("Solving LP relaxation...\n"); glp_init_smcp(&smcp); smcp.msg_lev = parm->msg_lev; mip->it_cnt = P->it_cnt; ret = glp_simplex(mip, &smcp); P->it_cnt = mip->it_cnt; if (ret != 0) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: cannot solve LP relaxation\n"); ret = GLP_EFAIL; goto done; } /* check status of the basic solution */ ret = glp_get_status(mip); if (ret == GLP_OPT) ret = 0; else if (ret == GLP_NOFEAS) ret = GLP_ENOPFS; else if (ret == GLP_UNBND) ret = GLP_ENODFS; else xassert(ret != ret); if (ret != 0) goto done; /* solve the transformed MIP */ mip->it_cnt = P->it_cnt; #if 0 /* 11/VII-2013 */ ret = solve_mip(mip, parm); #else if (parm->use_sol) { mip->mip_stat = P->mip_stat; mip->mip_obj = P->mip_obj; } ret = solve_mip(mip, parm, P, npp); #endif P->it_cnt = mip->it_cnt; /* only integer feasible solution can be postprocessed */ if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS)) { P->mip_stat = mip->mip_stat; goto done; } /* postprocess solution from the transformed MIP */ post: npp_postprocess(npp, mip); /* the transformed MIP is no longer needed */ glp_delete_prob(mip), mip = NULL; /* store solution to the original problem */ npp_unload_sol(npp, P); done: /* delete the transformed MIP, if it exists */ if (mip != NULL) glp_delete_prob(mip); /* delete preprocessor workspace */ npp_delete_wksp(npp); return ret; } #ifndef HAVE_ALIEN_SOLVER /* 28/V-2010 */ int _glp_intopt1(glp_prob *P, const glp_iocp *parm) { xassert(P == P); xassert(parm == parm); xprintf("glp_intopt: no alien solver is available\n"); return GLP_EFAIL; } #endif int glp_intopt(glp_prob *P, const glp_iocp *parm) { /* solve MIP problem with the branch-and-bound method */ glp_iocp _parm; int i, j, ret; /* check problem object */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_intopt: P = %p; invalid problem object\n", P); if (P->tree != NULL) xerror("glp_intopt: operation not allowed\n"); /* check control parameters */ if (parm == NULL) parm = &_parm, glp_init_iocp((glp_iocp *)parm); if (!(parm->msg_lev == GLP_MSG_OFF || parm->msg_lev == GLP_MSG_ERR || parm->msg_lev == GLP_MSG_ON || parm->msg_lev == GLP_MSG_ALL || parm->msg_lev == GLP_MSG_DBG)) xerror("glp_intopt: msg_lev = %d; invalid parameter\n", parm->msg_lev); if (!(parm->br_tech == GLP_BR_FFV || parm->br_tech == GLP_BR_LFV || parm->br_tech == GLP_BR_MFV || parm->br_tech == GLP_BR_DTH || parm->br_tech == GLP_BR_PCH)) xerror("glp_intopt: br_tech = %d; invalid parameter\n", parm->br_tech); if (!(parm->bt_tech == GLP_BT_DFS || parm->bt_tech == GLP_BT_BFS || parm->bt_tech == GLP_BT_BLB || parm->bt_tech == GLP_BT_BPH)) xerror("glp_intopt: bt_tech = %d; invalid parameter\n", parm->bt_tech); if (!(0.0 < parm->tol_int && parm->tol_int < 1.0)) xerror("glp_intopt: tol_int = %g; invalid parameter\n", parm->tol_int); if (!(0.0 < parm->tol_obj && parm->tol_obj < 1.0)) xerror("glp_intopt: tol_obj = %g; invalid parameter\n", parm->tol_obj); if (parm->tm_lim < 0) xerror("glp_intopt: tm_lim = %d; invalid parameter\n", parm->tm_lim); if (parm->out_frq < 0) xerror("glp_intopt: out_frq = %d; invalid parameter\n", parm->out_frq); if (parm->out_dly < 0) xerror("glp_intopt: out_dly = %d; invalid parameter\n", parm->out_dly); if (!(0 <= parm->cb_size && parm->cb_size <= 256)) xerror("glp_intopt: cb_size = %d; invalid parameter\n", parm->cb_size); if (!(parm->pp_tech == GLP_PP_NONE || parm->pp_tech == GLP_PP_ROOT || parm->pp_tech == GLP_PP_ALL)) xerror("glp_intopt: pp_tech = %d; invalid parameter\n", parm->pp_tech); if (parm->mip_gap < 0.0) xerror("glp_intopt: mip_gap = %g; invalid parameter\n", parm->mip_gap); if (!(parm->mir_cuts == GLP_ON || parm->mir_cuts == GLP_OFF)) xerror("glp_intopt: mir_cuts = %d; invalid parameter\n", parm->mir_cuts); if (!(parm->gmi_cuts == GLP_ON || parm->gmi_cuts == GLP_OFF)) xerror("glp_intopt: gmi_cuts = %d; invalid parameter\n", parm->gmi_cuts); if (!(parm->cov_cuts == GLP_ON || parm->cov_cuts == GLP_OFF)) xerror("glp_intopt: cov_cuts = %d; invalid parameter\n", parm->cov_cuts); if (!(parm->clq_cuts == GLP_ON || parm->clq_cuts == GLP_OFF)) xerror("glp_intopt: clq_cuts = %d; invalid parameter\n", parm->clq_cuts); if (!(parm->presolve == GLP_ON || parm->presolve == GLP_OFF)) xerror("glp_intopt: presolve = %d; invalid parameter\n", parm->presolve); if (!(parm->binarize == GLP_ON || parm->binarize == GLP_OFF)) xerror("glp_intopt: binarize = %d; invalid parameter\n", parm->binarize); if (!(parm->fp_heur == GLP_ON || parm->fp_heur == GLP_OFF)) xerror("glp_intopt: fp_heur = %d; invalid parameter\n", parm->fp_heur); #if 1 /* 28/V-2010 */ if (!(parm->alien == GLP_ON || parm->alien == GLP_OFF)) xerror("glp_intopt: alien = %d; invalid parameter\n", parm->alien); #endif #if 0 /* 11/VII-2013 */ /* integer solution is currently undefined */ P->mip_stat = GLP_UNDEF; P->mip_obj = 0.0; #else if (!parm->use_sol) P->mip_stat = GLP_UNDEF; if (P->mip_stat == GLP_NOFEAS) P->mip_stat = GLP_UNDEF; if (P->mip_stat == GLP_UNDEF) P->mip_obj = 0.0; else if (P->mip_stat == GLP_OPT) P->mip_stat = GLP_FEAS; #endif /* check bounds of double-bounded variables */ for (i = 1; i <= P->m; i++) { GLPROW *row = P->row[i]; if (row->type == GLP_DB && row->lb >= row->ub) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: row %d: lb = %g, ub = %g; incorrect" " bounds\n", i, row->lb, row->ub); ret = GLP_EBOUND; goto done; } } for (j = 1; j <= P->n; j++) { GLPCOL *col = P->col[j]; if (col->type == GLP_DB && col->lb >= col->ub) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: column %d: lb = %g, ub = %g; incorr" "ect bounds\n", j, col->lb, col->ub); ret = GLP_EBOUND; goto done; } } /* bounds of all integer variables must be integral */ for (j = 1; j <= P->n; j++) { GLPCOL *col = P->col[j]; if (col->kind != GLP_IV) continue; if (col->type == GLP_LO || col->type == GLP_DB) { if (col->lb != floor(col->lb)) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: integer column %d has non-intege" "r lower bound %g\n", j, col->lb); ret = GLP_EBOUND; goto done; } } if (col->type == GLP_UP || col->type == GLP_DB) { if (col->ub != floor(col->ub)) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: integer column %d has non-intege" "r upper bound %g\n", j, col->ub); ret = GLP_EBOUND; goto done; } } if (col->type == GLP_FX) { if (col->lb != floor(col->lb)) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("glp_intopt: integer column %d has non-intege" "r fixed value %g\n", j, col->lb); ret = GLP_EBOUND; goto done; } } } /* solve MIP problem */ if (parm->msg_lev >= GLP_MSG_ALL) { int ni = glp_get_num_int(P); int nb = glp_get_num_bin(P); char s[50]; xprintf("GLPK Integer Optimizer, v%s\n", glp_version()); xprintf("%d row%s, %d column%s, %d non-zero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", P->nnz, P->nnz == 1 ? "" : "s"); if (nb == 0) strcpy(s, "none of"); else if (ni == 1 && nb == 1) strcpy(s, ""); else if (nb == 1) strcpy(s, "one of"); else if (nb == ni) strcpy(s, "all of"); else sprintf(s, "%d of", nb); xprintf("%d integer variable%s, %s which %s binary\n", ni, ni == 1 ? "" : "s", s, nb == 1 ? "is" : "are"); } #if 1 /* 28/V-2010 */ if (parm->alien) { /* use alien integer optimizer */ ret = _glp_intopt1(P, parm); goto done; } #endif if (!parm->presolve) #if 0 /* 11/VII-2013 */ ret = solve_mip(P, parm); #else ret = solve_mip(P, parm, P, NULL); #endif else ret = preprocess_and_solve_mip(P, parm); done: /* return to the application program */ return ret; } /*********************************************************************** * NAME * * glp_init_iocp - initialize integer optimizer control parameters * * SYNOPSIS * * void glp_init_iocp(glp_iocp *parm); * * DESCRIPTION * * The routine glp_init_iocp initializes control parameters, which are * used by the integer optimizer, with default values. * * Default values of the control parameters are stored in a glp_iocp * structure, which the parameter parm points to. */ void glp_init_iocp(glp_iocp *parm) { parm->msg_lev = GLP_MSG_ALL; parm->br_tech = GLP_BR_DTH; parm->bt_tech = GLP_BT_BLB; parm->tol_int = 1e-5; parm->tol_obj = 1e-7; parm->tm_lim = INT_MAX; parm->out_frq = 5000; parm->out_dly = 10000; parm->cb_func = NULL; parm->cb_info = NULL; parm->cb_size = 0; parm->pp_tech = GLP_PP_ALL; parm->mip_gap = 0.0; parm->mir_cuts = GLP_OFF; parm->gmi_cuts = GLP_OFF; parm->cov_cuts = GLP_OFF; parm->clq_cuts = GLP_OFF; parm->presolve = GLP_OFF; parm->binarize = GLP_OFF; parm->fp_heur = GLP_OFF; #if 1 /* 25/V-2013 */ parm->ps_heur = GLP_OFF; #endif #if 1 /* 29/VI-2013 */ parm->ps_tm_lim = 60000; /* 1 minute */ #endif #if 1 /* 11/VII-2013 */ parm->use_sol = GLP_OFF; parm->save_sol = NULL; #endif #if 1 /* 28/V-2010 */ parm->alien = GLP_OFF; #endif return; } /*********************************************************************** * NAME * * glp_mip_status - retrieve status of MIP solution * * SYNOPSIS * * int glp_mip_status(glp_prob *mip); * * RETURNS * * The routine lpx_mip_status reports the status of MIP solution found * by the branch-and-bound solver as follows: * * GLP_UNDEF - MIP solution is undefined; * GLP_OPT - MIP solution is integer optimal; * GLP_FEAS - MIP solution is integer feasible but its optimality * (or non-optimality) has not been proven, perhaps due to * premature termination of the search; * GLP_NOFEAS - problem has no integer feasible solution (proven by the * solver). */ int glp_mip_status(glp_prob *mip) { int mip_stat = mip->mip_stat; return mip_stat; } /*********************************************************************** * NAME * * glp_mip_obj_val - retrieve objective value (MIP solution) * * SYNOPSIS * * double glp_mip_obj_val(glp_prob *mip); * * RETURNS * * The routine glp_mip_obj_val returns value of the objective function * for MIP solution. */ double glp_mip_obj_val(glp_prob *mip) { /*struct LPXCPS *cps = mip->cps;*/ double z; z = mip->mip_obj; /*if (cps->round && fabs(z) < 1e-9) z = 0.0;*/ return z; } /*********************************************************************** * NAME * * glp_mip_row_val - retrieve row value (MIP solution) * * SYNOPSIS * * double glp_mip_row_val(glp_prob *mip, int i); * * RETURNS * * The routine glp_mip_row_val returns value of the auxiliary variable * associated with i-th row. */ double glp_mip_row_val(glp_prob *mip, int i) { /*struct LPXCPS *cps = mip->cps;*/ double mipx; if (!(1 <= i && i <= mip->m)) xerror("glp_mip_row_val: i = %d; row number out of range\n", i) ; mipx = mip->row[i]->mipx; /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/ return mipx; } /*********************************************************************** * NAME * * glp_mip_col_val - retrieve column value (MIP solution) * * SYNOPSIS * * double glp_mip_col_val(glp_prob *mip, int j); * * RETURNS * * The routine glp_mip_col_val returns value of the structural variable * associated with j-th column. */ double glp_mip_col_val(glp_prob *mip, int j) { /*struct LPXCPS *cps = mip->cps;*/ double mipx; if (!(1 <= j && j <= mip->n)) xerror("glp_mip_col_val: j = %d; column number out of range\n", j); mipx = mip->col[j]->mipx; /*if (cps->round && fabs(mipx) < 1e-9) mipx = 0.0;*/ return mipx; } /* eof */ glpk-4.52.1/src/glpapi10.c0000644000062000006210000002433212175147600014275 0ustar maomkpasswd/* glpapi10.c (solution checking routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" void glp_check_kkt(glp_prob *P, int sol, int cond, double *_ae_max, int *_ae_ind, double *_re_max, int *_re_ind) { /* check feasibility and optimality conditions */ int m = P->m; int n = P->n; GLPROW *row; GLPCOL *col; GLPAIJ *aij; int i, j, ae_ind, re_ind; double e, sp, sn, t, ae_max, re_max; if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) xerror("glp_check_kkt: sol = %d; invalid solution indicator\n", sol); if (!(cond == GLP_KKT_PE || cond == GLP_KKT_PB || cond == GLP_KKT_DE || cond == GLP_KKT_DB || cond == GLP_KKT_CS)) xerror("glp_check_kkt: cond = %d; invalid condition indicator " "\n", cond); ae_max = re_max = 0.0; ae_ind = re_ind = 0; if (cond == GLP_KKT_PE) { /* xR - A * xS = 0 */ for (i = 1; i <= m; i++) { row = P->row[i]; sp = sn = 0.0; /* t := xR[i] */ if (sol == GLP_SOL) t = row->prim; else if (sol == GLP_IPT) t = row->pval; else if (sol == GLP_MIP) t = row->mipx; else xassert(sol != sol); if (t >= 0.0) sp += t; else sn -= t; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { col = aij->col; /* t := - a[i,j] * xS[j] */ if (sol == GLP_SOL) t = - aij->val * col->prim; else if (sol == GLP_IPT) t = - aij->val * col->pval; else if (sol == GLP_MIP) t = - aij->val * col->mipx; else xassert(sol != sol); if (t >= 0.0) sp += t; else sn -= t; } /* absolute error */ e = fabs(sp - sn); if (ae_max < e) ae_max = e, ae_ind = i; /* relative error */ e /= (1.0 + sp + sn); if (re_max < e) re_max = e, re_ind = i; } } else if (cond == GLP_KKT_PB) { /* lR <= xR <= uR */ for (i = 1; i <= m; i++) { row = P->row[i]; /* t := xR[i] */ if (sol == GLP_SOL) t = row->prim; else if (sol == GLP_IPT) t = row->pval; else if (sol == GLP_MIP) t = row->mipx; else xassert(sol != sol); /* check lower bound */ if (row->type == GLP_LO || row->type == GLP_DB || row->type == GLP_FX) { if (t < row->lb) { /* absolute error */ e = row->lb - t; if (ae_max < e) ae_max = e, ae_ind = i; /* relative error */ e /= (1.0 + fabs(row->lb)); if (re_max < e) re_max = e, re_ind = i; } } /* check upper bound */ if (row->type == GLP_UP || row->type == GLP_DB || row->type == GLP_FX) { if (t > row->ub) { /* absolute error */ e = t - row->ub; if (ae_max < e) ae_max = e, ae_ind = i; /* relative error */ e /= (1.0 + fabs(row->ub)); if (re_max < e) re_max = e, re_ind = i; } } } /* lS <= xS <= uS */ for (j = 1; j <= n; j++) { col = P->col[j]; /* t := xS[j] */ if (sol == GLP_SOL) t = col->prim; else if (sol == GLP_IPT) t = col->pval; else if (sol == GLP_MIP) t = col->mipx; else xassert(sol != sol); /* check lower bound */ if (col->type == GLP_LO || col->type == GLP_DB || col->type == GLP_FX) { if (t < col->lb) { /* absolute error */ e = col->lb - t; if (ae_max < e) ae_max = e, ae_ind = m+j; /* relative error */ e /= (1.0 + fabs(col->lb)); if (re_max < e) re_max = e, re_ind = m+j; } } /* check upper bound */ if (col->type == GLP_UP || col->type == GLP_DB || col->type == GLP_FX) { if (t > col->ub) { /* absolute error */ e = t - col->ub; if (ae_max < e) ae_max = e, ae_ind = m+j; /* relative error */ e /= (1.0 + fabs(col->ub)); if (re_max < e) re_max = e, re_ind = m+j; } } } } else if (cond == GLP_KKT_DE) { /* A' * (lambdaR - cR) + (lambdaS - cS) = 0 */ for (j = 1; j <= n; j++) { col = P->col[j]; sp = sn = 0.0; /* t := lambdaS[j] - cS[j] */ if (sol == GLP_SOL) t = col->dual - col->coef; else if (sol == GLP_IPT) t = col->dval - col->coef; else xassert(sol != sol); if (t >= 0.0) sp += t; else sn -= t; for (aij = col->ptr; aij != NULL; aij = aij->c_next) { row = aij->row; /* t := a[i,j] * (lambdaR[i] - cR[i]) */ if (sol == GLP_SOL) t = aij->val * row->dual; else if (sol == GLP_IPT) t = aij->val * row->dval; else xassert(sol != sol); if (t >= 0.0) sp += t; else sn -= t; } /* absolute error */ e = fabs(sp - sn); if (ae_max < e) ae_max = e, ae_ind = m+j; /* relative error */ e /= (1.0 + sp + sn); if (re_max < e) re_max = e, re_ind = m+j; } } else if (cond == GLP_KKT_DB) { /* check lambdaR */ for (i = 1; i <= m; i++) { row = P->row[i]; /* t := lambdaR[i] */ if (sol == GLP_SOL) t = row->dual; else if (sol == GLP_IPT) t = row->dval; else xassert(sol != sol); /* correct sign */ if (P->dir == GLP_MIN) t = + t; else if (P->dir == GLP_MAX) t = - t; else xassert(P != P); /* check for positivity */ #if 1 /* 08/III-2013 */ /* the former check was correct */ /* the bug reported by David Price is related to violation of complementarity slackness, not to this condition */ if (row->type == GLP_FR || row->type == GLP_LO) #else if (row->stat == GLP_NF || row->stat == GLP_NL) #endif { if (t < 0.0) { e = - t; if (ae_max < e) ae_max = re_max = e, ae_ind = re_ind = i; } } /* check for negativity */ #if 1 /* 08/III-2013 */ /* see comment above */ if (row->type == GLP_FR || row->type == GLP_UP) #else if (row->stat == GLP_NF || row->stat == GLP_NU) #endif { if (t > 0.0) { e = + t; if (ae_max < e) ae_max = re_max = e, ae_ind = re_ind = i; } } } /* check lambdaS */ for (j = 1; j <= n; j++) { col = P->col[j]; /* t := lambdaS[j] */ if (sol == GLP_SOL) t = col->dual; else if (sol == GLP_IPT) t = col->dval; else xassert(sol != sol); /* correct sign */ if (P->dir == GLP_MIN) t = + t; else if (P->dir == GLP_MAX) t = - t; else xassert(P != P); /* check for positivity */ #if 1 /* 08/III-2013 */ /* see comment above */ if (col->type == GLP_FR || col->type == GLP_LO) #else if (col->stat == GLP_NF || col->stat == GLP_NL) #endif { if (t < 0.0) { e = - t; if (ae_max < e) ae_max = re_max = e, ae_ind = re_ind = m+j; } } /* check for negativity */ #if 1 /* 08/III-2013 */ /* see comment above */ if (col->type == GLP_FR || col->type == GLP_UP) #else if (col->stat == GLP_NF || col->stat == GLP_NU) #endif { if (t > 0.0) { e = + t; if (ae_max < e) ae_max = re_max = e, ae_ind = re_ind = m+j; } } } } else xassert(cond != cond); if (_ae_max != NULL) *_ae_max = ae_max; if (_ae_ind != NULL) *_ae_ind = ae_ind; if (_re_max != NULL) *_re_max = re_max; if (_re_ind != NULL) *_re_ind = re_ind; return; } /* eof */ glpk-4.52.1/src/glpapi11.c0000644000062000006210000012706412175147600014304 0ustar maomkpasswd/* glpapi11.c (utility routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #if 1 /* 11/VI-2013 */ #include "env2.h" #endif #include "glpapi.h" #include "glpsdf.h" int glp_print_sol(glp_prob *P, const char *fname) { /* write basic solution in printable format */ XFILE *fp; GLPROW *row; GLPCOL *col; int i, j, t, ae_ind, re_ind, ret; double ae_max, re_max; xprintf("Writing basic solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "%-12s%s\n", "Problem:", P->name == NULL ? "" : P->name); xfprintf(fp, "%-12s%d\n", "Rows:", P->m); xfprintf(fp, "%-12s%d\n", "Columns:", P->n); xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); t = glp_get_status(P); xfprintf(fp, "%-12s%s\n", "Status:", t == GLP_OPT ? "OPTIMAL" : t == GLP_FEAS ? "FEASIBLE" : t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : t == GLP_UNBND ? "UNBOUNDED" : t == GLP_UNDEF ? "UNDEFINED" : "???"); xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", P->obj == NULL ? "" : P->obj, P->obj == NULL ? "" : " = ", P->obj_val, P->dir == GLP_MIN ? "MINimum" : P->dir == GLP_MAX ? "MAXimum" : "???"); xfprintf(fp, "\n"); xfprintf(fp, " No. Row name St Activity Lower bound " " Upper bound Marginal\n"); xfprintf(fp, "------ ------------ -- ------------- ------------- " "------------- -------------\n"); for (i = 1; i <= P->m; i++) { row = P->row[i]; xfprintf(fp, "%6d ", i); if (row->name == NULL || strlen(row->name) <= 12) xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); else xfprintf(fp, "%s\n%20s", row->name, ""); xfprintf(fp, "%s ", row->stat == GLP_BS ? "B " : row->stat == GLP_NL ? "NL" : row->stat == GLP_NU ? "NU" : row->stat == GLP_NF ? "NF" : row->stat == GLP_NS ? "NS" : "??"); xfprintf(fp, "%13.6g ", fabs(row->prim) <= 1e-9 ? 0.0 : row->prim); if (row->type == GLP_LO || row->type == GLP_DB || row->type == GLP_FX) xfprintf(fp, "%13.6g ", row->lb); else xfprintf(fp, "%13s ", ""); if (row->type == GLP_UP || row->type == GLP_DB) xfprintf(fp, "%13.6g ", row->ub); else xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); if (row->stat != GLP_BS) { if (fabs(row->dual) <= 1e-9) xfprintf(fp, "%13s", "< eps"); else xfprintf(fp, "%13.6g ", row->dual); } xfprintf(fp, "\n"); } xfprintf(fp, "\n"); xfprintf(fp, " No. Column name St Activity Lower bound " " Upper bound Marginal\n"); xfprintf(fp, "------ ------------ -- ------------- ------------- " "------------- -------------\n"); for (j = 1; j <= P->n; j++) { col = P->col[j]; xfprintf(fp, "%6d ", j); if (col->name == NULL || strlen(col->name) <= 12) xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); else xfprintf(fp, "%s\n%20s", col->name, ""); xfprintf(fp, "%s ", col->stat == GLP_BS ? "B " : col->stat == GLP_NL ? "NL" : col->stat == GLP_NU ? "NU" : col->stat == GLP_NF ? "NF" : col->stat == GLP_NS ? "NS" : "??"); xfprintf(fp, "%13.6g ", fabs(col->prim) <= 1e-9 ? 0.0 : col->prim); if (col->type == GLP_LO || col->type == GLP_DB || col->type == GLP_FX) xfprintf(fp, "%13.6g ", col->lb); else xfprintf(fp, "%13s ", ""); if (col->type == GLP_UP || col->type == GLP_DB) xfprintf(fp, "%13.6g ", col->ub); else xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); if (col->stat != GLP_BS) { if (fabs(col->dual) <= 1e-9) xfprintf(fp, "%13s", "< eps"); else xfprintf(fp, "%13.6g ", col->dual); } xfprintf(fp, "\n"); } xfprintf(fp, "\n"); xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", ae_max, ae_ind); xfprintf(fp, " max.rel.err = %.2e on row %d\n", re_max, re_ind); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", ae_max, ae_ind <= P->m ? "row" : "column", ae_ind <= P->m ? ae_ind : ae_ind - P->m); xfprintf(fp, " max.rel.err = %.2e on %s %d\n", re_max, re_ind <= P->m ? "row" : "column", re_ind <= P->m ? re_ind : re_ind - P->m); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" "E"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); xfprintf(fp, " max.rel.err = %.2e on column %d\n", re_max, re_ind == 0 ? 0 : re_ind - P->m); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", ae_max, ae_ind <= P->m ? "row" : "column", ae_ind <= P->m ? ae_ind : ae_ind - P->m); xfprintf(fp, " max.rel.err = %.2e on %s %d\n", re_max, re_ind <= P->m ? "row" : "column", re_ind <= P->m ? re_ind : re_ind - P->m); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") ; xfprintf(fp, "\n"); xfprintf(fp, "End of output\n"); xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /*********************************************************************** * NAME * * glp_read_sol - read basic solution from text file * * SYNOPSIS * * int glp_read_sol(glp_prob *lp, const char *fname); * * DESCRIPTION * * The routine glp_read_sol reads basic solution from a text file whose * name is specified by the parameter fname into the problem object. * * For the file format see description of the routine glp_write_sol. * * RETURNS * * On success the routine returns zero, otherwise non-zero. */ int glp_read_sol(glp_prob *lp, const char *fname) { glp_data *data; jmp_buf jump; int i, j, k, ret = 0; xprintf("Reading basic solution from `%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; goto done; } if (setjmp(jump)) { ret = 1; goto done; } glp_sdf_set_jump(data, jump); /* number of rows, number of columns */ k = glp_sdf_read_int(data); if (k != lp->m) glp_sdf_error(data, "wrong number of rows\n"); k = glp_sdf_read_int(data); if (k != lp->n) glp_sdf_error(data, "wrong number of columns\n"); /* primal status, dual status, objective value */ k = glp_sdf_read_int(data); if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS || k == GLP_NOFEAS)) glp_sdf_error(data, "invalid primal status\n"); lp->pbs_stat = k; k = glp_sdf_read_int(data); if (!(k == GLP_UNDEF || k == GLP_FEAS || k == GLP_INFEAS || k == GLP_NOFEAS)) glp_sdf_error(data, "invalid dual status\n"); lp->dbs_stat = k; lp->obj_val = glp_sdf_read_num(data); /* rows (auxiliary variables) */ for (i = 1; i <= lp->m; i++) { GLPROW *row = lp->row[i]; /* status, primal value, dual value */ k = glp_sdf_read_int(data); if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU || k == GLP_NF || k == GLP_NS)) glp_sdf_error(data, "invalid row status\n"); glp_set_row_stat(lp, i, k); row->prim = glp_sdf_read_num(data); row->dual = glp_sdf_read_num(data); } /* columns (structural variables) */ for (j = 1; j <= lp->n; j++) { GLPCOL *col = lp->col[j]; /* status, primal value, dual value */ k = glp_sdf_read_int(data); if (!(k == GLP_BS || k == GLP_NL || k == GLP_NU || k == GLP_NF || k == GLP_NS)) glp_sdf_error(data, "invalid column status\n"); glp_set_col_stat(lp, j, k); col->prim = glp_sdf_read_num(data); col->dual = glp_sdf_read_num(data); } xprintf("%d lines were read\n", glp_sdf_line(data)); done: if (ret) lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; if (data != NULL) glp_sdf_close_file(data); return ret; } /*********************************************************************** * NAME * * glp_write_sol - write basic solution to text file * * SYNOPSIS * * int glp_write_sol(glp_prob *lp, const char *fname); * * DESCRIPTION * * The routine glp_write_sol writes the current basic solution to a * text file whose name is specified by the parameter fname. This file * can be read back with the routine glp_read_sol. * * RETURNS * * On success the routine returns zero, otherwise non-zero. * * FILE FORMAT * * The file created by the routine glp_write_sol is a plain text file, * which contains the following information: * * m n * p_stat d_stat obj_val * r_stat[1] r_prim[1] r_dual[1] * . . . * r_stat[m] r_prim[m] r_dual[m] * c_stat[1] c_prim[1] c_dual[1] * . . . * c_stat[n] c_prim[n] c_dual[n] * * where: * m is the number of rows (auxiliary variables); * n is the number of columns (structural variables); * p_stat is the primal status of the basic solution (GLP_UNDEF = 1, * GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4); * d_stat is the dual status of the basic solution (GLP_UNDEF = 1, * GLP_FEAS = 2, GLP_INFEAS = 3, or GLP_NOFEAS = 4); * obj_val is the objective value; * r_stat[i], i = 1,...,m, is the status of i-th row (GLP_BS = 1, * GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5); * r_prim[i], i = 1,...,m, is the primal value of i-th row; * r_dual[i], i = 1,...,m, is the dual value of i-th row; * c_stat[j], j = 1,...,n, is the status of j-th column (GLP_BS = 1, * GLP_NL = 2, GLP_NU = 3, GLP_NF = 4, or GLP_NS = 5); * c_prim[j], j = 1,...,n, is the primal value of j-th column; * c_dual[j], j = 1,...,n, is the dual value of j-th column. */ int glp_write_sol(glp_prob *lp, const char *fname) { XFILE *fp; int i, j, ret = 0; xprintf("Writing basic solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* number of rows, number of columns */ xfprintf(fp, "%d %d\n", lp->m, lp->n); /* primal status, dual status, objective value */ xfprintf(fp, "%d %d %.*g\n", lp->pbs_stat, lp->dbs_stat, DBL_DIG, lp->obj_val); /* rows (auxiliary variables) */ for (i = 1; i <= lp->m; i++) { GLPROW *row = lp->row[i]; /* status, primal value, dual value */ xfprintf(fp, "%d %.*g %.*g\n", row->stat, DBL_DIG, row->prim, DBL_DIG, row->dual); } /* columns (structural variables) */ for (j = 1; j <= lp->n; j++) { GLPCOL *col = lp->col[j]; /* status, primal value, dual value */ xfprintf(fp, "%d %.*g %.*g\n", col->stat, DBL_DIG, col->prim, DBL_DIG, col->dual); } xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", 2 + lp->m + lp->n); done: if (fp != NULL) xfclose(fp); return ret; } /**********************************************************************/ static char *format(char buf[13+1], double x) { /* format floating-point number in MPS/360-like style */ if (x == -DBL_MAX) strcpy(buf, " -Inf"); else if (x == +DBL_MAX) strcpy(buf, " +Inf"); else if (fabs(x) <= 999999.99998) { sprintf(buf, "%13.5f", x); #if 1 if (strcmp(buf, " 0.00000") == 0 || strcmp(buf, " -0.00000") == 0) strcpy(buf, " . "); else if (memcmp(buf, " 0.", 8) == 0) memcpy(buf, " .", 8); else if (memcmp(buf, " -0.", 8) == 0) memcpy(buf, " -.", 8); #endif } else sprintf(buf, "%13.6g", x); return buf; } int glp_print_ranges(glp_prob *P, int len, const int list[], int flags, const char *fname) { /* print sensitivity analysis report */ XFILE *fp = NULL; GLPROW *row; GLPCOL *col; int m, n, pass, k, t, numb, type, stat, var1, var2, count, page, ret; double lb, ub, slack, coef, prim, dual, value1, value2, coef1, coef2, obj1, obj2; const char *name, *limit; char buf[13+1]; /* sanity checks */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_print_ranges: P = %p; invalid problem object\n", P); m = P->m, n = P->n; if (len < 0) xerror("glp_print_ranges: len = %d; invalid list length\n", len); if (len > 0) { if (list == NULL) xerror("glp_print_ranges: list = %p: invalid parameter\n", list); for (t = 1; t <= len; t++) { k = list[t]; if (!(1 <= k && k <= m+n)) xerror("glp_print_ranges: list[%d] = %d; row/column numb" "er out of range\n", t, k); } } if (flags != 0) xerror("glp_print_ranges: flags = %d; invalid parameter\n", flags); if (fname == NULL) xerror("glp_print_ranges: fname = %p; invalid parameter\n", fname); if (glp_get_status(P) != GLP_OPT) { xprintf("glp_print_ranges: optimal basic solution required\n"); ret = 1; goto done; } if (!glp_bf_exists(P)) { xprintf("glp_print_ranges: basis factorization required\n"); ret = 2; goto done; } /* start reporting */ xprintf("Write sensitivity analysis report to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 3; goto done; } page = count = 0; for (pass = 1; pass <= 2; pass++) for (t = 1; t <= (len == 0 ? m+n : len); t++) { if (t == 1) count = 0; k = (len == 0 ? t : list[t]); if (pass == 1 && k > m || pass == 2 && k <= m) continue; if (count == 0) { xfprintf(fp, "GLPK %-4s - SENSITIVITY ANALYSIS REPORT%73sPa" "ge%4d\n", glp_version(), "", ++page); xfprintf(fp, "\n"); xfprintf(fp, "%-12s%s\n", "Problem:", P->name == NULL ? "" : P->name); xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", P->obj == NULL ? "" : P->obj, P->obj == NULL ? "" : " = ", P->obj_val, P->dir == GLP_MIN ? "MINimum" : P->dir == GLP_MAX ? "MAXimum" : "???"); xfprintf(fp, "\n"); xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " "%s\n", "No.", pass == 1 ? "Row name" : "Column name", "St", "Activity", pass == 1 ? "Slack" : "Obj coef", "Lower bound", "Activity", "Obj coef", "Obj value at", "Limiting"); xfprintf(fp, "%6s %-12s %2s %13s %13s %13s %13s %13s %13s " "%s\n", "", "", "", "", "Marginal", "Upper bound", "range", "range", "break point", "variable"); xfprintf(fp, "------ ------------ -- ------------- --------" "----- ------------- ------------- ------------- ------" "------- ------------\n"); } if (pass == 1) { numb = k; xassert(1 <= numb && numb <= m); row = P->row[numb]; name = row->name; type = row->type; lb = glp_get_row_lb(P, numb); ub = glp_get_row_ub(P, numb); coef = 0.0; stat = row->stat; prim = row->prim; if (type == GLP_FR) slack = - prim; else if (type == GLP_LO) slack = lb - prim; else if (type == GLP_UP || type == GLP_DB || type == GLP_FX) slack = ub - prim; dual = row->dual; } else { numb = k - m; xassert(1 <= numb && numb <= n); col = P->col[numb]; name = col->name; lb = glp_get_col_lb(P, numb); ub = glp_get_col_ub(P, numb); coef = col->coef; stat = col->stat; prim = col->prim; slack = 0.0; dual = col->dual; } if (stat != GLP_BS) { glp_analyze_bound(P, k, &value1, &var1, &value2, &var2); if (stat == GLP_NF) coef1 = coef2 = coef; else if (stat == GLP_NS) coef1 = -DBL_MAX, coef2 = +DBL_MAX; else if (stat == GLP_NL && P->dir == GLP_MIN || stat == GLP_NU && P->dir == GLP_MAX) coef1 = coef - dual, coef2 = +DBL_MAX; else coef1 = -DBL_MAX, coef2 = coef - dual; if (value1 == -DBL_MAX) { if (dual < -1e-9) obj1 = +DBL_MAX; else if (dual > +1e-9) obj1 = -DBL_MAX; else obj1 = P->obj_val; } else obj1 = P->obj_val + dual * (value1 - prim); if (value2 == +DBL_MAX) { if (dual < -1e-9) obj2 = -DBL_MAX; else if (dual > +1e-9) obj2 = +DBL_MAX; else obj2 = P->obj_val; } else obj2 = P->obj_val + dual * (value2 - prim); } else { glp_analyze_coef(P, k, &coef1, &var1, &value1, &coef2, &var2, &value2); if (coef1 == -DBL_MAX) { if (prim < -1e-9) obj1 = +DBL_MAX; else if (prim > +1e-9) obj1 = -DBL_MAX; else obj1 = P->obj_val; } else obj1 = P->obj_val + (coef1 - coef) * prim; if (coef2 == +DBL_MAX) { if (prim < -1e-9) obj2 = -DBL_MAX; else if (prim > +1e-9) obj2 = +DBL_MAX; else obj2 = P->obj_val; } else obj2 = P->obj_val + (coef2 - coef) * prim; } /*** first line ***/ /* row/column number */ xfprintf(fp, "%6d", numb); /* row/column name */ xfprintf(fp, " %-12.12s", name == NULL ? "" : name); if (name != NULL && strlen(name) > 12) xfprintf(fp, "%s\n%6s %12s", name+12, "", ""); /* row/column status */ xfprintf(fp, " %2s", stat == GLP_BS ? "BS" : stat == GLP_NL ? "NL" : stat == GLP_NU ? "NU" : stat == GLP_NF ? "NF" : stat == GLP_NS ? "NS" : "??"); /* row/column activity */ xfprintf(fp, " %s", format(buf, prim)); /* row slack, column objective coefficient */ xfprintf(fp, " %s", format(buf, k <= m ? slack : coef)); /* row/column lower bound */ xfprintf(fp, " %s", format(buf, lb)); /* row/column activity range */ xfprintf(fp, " %s", format(buf, value1)); /* row/column objective coefficient range */ xfprintf(fp, " %s", format(buf, coef1)); /* objective value at break point */ xfprintf(fp, " %s", format(buf, obj1)); /* limiting variable name */ if (var1 != 0) { if (var1 <= m) limit = glp_get_row_name(P, var1); else limit = glp_get_col_name(P, var1 - m); if (limit != NULL) xfprintf(fp, " %s", limit); } xfprintf(fp, "\n"); /*** second line ***/ xfprintf(fp, "%6s %-12s %2s %13s", "", "", "", ""); /* row/column reduced cost */ xfprintf(fp, " %s", format(buf, dual)); /* row/column upper bound */ xfprintf(fp, " %s", format(buf, ub)); /* row/column activity range */ xfprintf(fp, " %s", format(buf, value2)); /* row/column objective coefficient range */ xfprintf(fp, " %s", format(buf, coef2)); /* objective value at break point */ xfprintf(fp, " %s", format(buf, obj2)); /* limiting variable name */ if (var2 != 0) { if (var2 <= m) limit = glp_get_row_name(P, var2); else limit = glp_get_col_name(P, var2 - m); if (limit != NULL) xfprintf(fp, " %s", limit); } xfprintf(fp, "\n"); xfprintf(fp, "\n"); /* print 10 items per page */ count = (count + 1) % 10; } xfprintf(fp, "End of report\n"); xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 4; goto done; } ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /**********************************************************************/ int glp_print_ipt(glp_prob *P, const char *fname) { /* write interior-point solution in printable format */ XFILE *fp; GLPROW *row; GLPCOL *col; int i, j, t, ae_ind, re_ind, ret; double ae_max, re_max; xprintf("Writing interior-point solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "%-12s%s\n", "Problem:", P->name == NULL ? "" : P->name); xfprintf(fp, "%-12s%d\n", "Rows:", P->m); xfprintf(fp, "%-12s%d\n", "Columns:", P->n); xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); t = glp_ipt_status(P); xfprintf(fp, "%-12s%s\n", "Status:", t == GLP_OPT ? "OPTIMAL" : t == GLP_UNDEF ? "UNDEFINED" : t == GLP_INFEAS ? "INFEASIBLE (INTERMEDIATE)" : t == GLP_NOFEAS ? "INFEASIBLE (FINAL)" : "???"); xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", P->obj == NULL ? "" : P->obj, P->obj == NULL ? "" : " = ", P->ipt_obj, P->dir == GLP_MIN ? "MINimum" : P->dir == GLP_MAX ? "MAXimum" : "???"); xfprintf(fp, "\n"); xfprintf(fp, " No. Row name Activity Lower bound " " Upper bound Marginal\n"); xfprintf(fp, "------ ------------ ------------- ------------- " "------------- -------------\n"); for (i = 1; i <= P->m; i++) { row = P->row[i]; xfprintf(fp, "%6d ", i); if (row->name == NULL || strlen(row->name) <= 12) xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); else xfprintf(fp, "%s\n%20s", row->name, ""); xfprintf(fp, "%3s", ""); xfprintf(fp, "%13.6g ", fabs(row->pval) <= 1e-9 ? 0.0 : row->pval); if (row->type == GLP_LO || row->type == GLP_DB || row->type == GLP_FX) xfprintf(fp, "%13.6g ", row->lb); else xfprintf(fp, "%13s ", ""); if (row->type == GLP_UP || row->type == GLP_DB) xfprintf(fp, "%13.6g ", row->ub); else xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); if (fabs(row->dval) <= 1e-9) xfprintf(fp, "%13s", "< eps"); else xfprintf(fp, "%13.6g ", row->dval); xfprintf(fp, "\n"); } xfprintf(fp, "\n"); xfprintf(fp, " No. Column name Activity Lower bound " " Upper bound Marginal\n"); xfprintf(fp, "------ ------------ ------------- ------------- " "------------- -------------\n"); for (j = 1; j <= P->n; j++) { col = P->col[j]; xfprintf(fp, "%6d ", j); if (col->name == NULL || strlen(col->name) <= 12) xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); else xfprintf(fp, "%s\n%20s", col->name, ""); xfprintf(fp, "%3s", ""); xfprintf(fp, "%13.6g ", fabs(col->pval) <= 1e-9 ? 0.0 : col->pval); if (col->type == GLP_LO || col->type == GLP_DB || col->type == GLP_FX) xfprintf(fp, "%13.6g ", col->lb); else xfprintf(fp, "%13s ", ""); if (col->type == GLP_UP || col->type == GLP_DB) xfprintf(fp, "%13.6g ", col->ub); else xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); if (fabs(col->dval) <= 1e-9) xfprintf(fp, "%13s", "< eps"); else xfprintf(fp, "%13.6g ", col->dval); xfprintf(fp, "\n"); } xfprintf(fp, "\n"); xfprintf(fp, "Karush-Kuhn-Tucker optimality conditions:\n"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_IPT, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", ae_max, ae_ind); xfprintf(fp, " max.rel.err = %.2e on row %d\n", re_max, re_ind); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS WRONG"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_IPT, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", ae_max, ae_ind <= P->m ? "row" : "column", ae_ind <= P->m ? ae_ind : ae_ind - P->m); xfprintf(fp, " max.rel.err = %.2e on %s %d\n", re_max, re_ind <= P->m ? "row" : "column", re_ind <= P->m ? re_ind : re_ind - P->m); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "PRIMAL SOLUTION IS INFEASIBL" "E"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_IPT, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.DE: max.abs.err = %.2e on column %d\n", ae_max, ae_ind == 0 ? 0 : ae_ind - P->m); xfprintf(fp, " max.rel.err = %.2e on column %d\n", re_max, re_ind == 0 ? 0 : re_ind - P->m); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS WRONG"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_IPT, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.DB: max.abs.err = %.2e on %s %d\n", ae_max, ae_ind <= P->m ? "row" : "column", ae_ind <= P->m ? ae_ind : ae_ind - P->m); xfprintf(fp, " max.rel.err = %.2e on %s %d\n", re_max, re_ind <= P->m ? "row" : "column", re_ind <= P->m ? re_ind : re_ind - P->m); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "DUAL SOLUTION IS INFEASIBLE") ; xfprintf(fp, "\n"); xfprintf(fp, "End of output\n"); xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /*********************************************************************** * NAME * * glp_read_ipt - read interior-point solution from text file * * SYNOPSIS * * int glp_read_ipt(glp_prob *lp, const char *fname); * * DESCRIPTION * * The routine glp_read_ipt reads interior-point solution from a text * file whose name is specified by the parameter fname into the problem * object. * * For the file format see description of the routine glp_write_ipt. * * RETURNS * * On success the routine returns zero, otherwise non-zero. */ int glp_read_ipt(glp_prob *lp, const char *fname) { glp_data *data; jmp_buf jump; int i, j, k, ret = 0; xprintf("Reading interior-point solution from `%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; goto done; } if (setjmp(jump)) { ret = 1; goto done; } glp_sdf_set_jump(data, jump); /* number of rows, number of columns */ k = glp_sdf_read_int(data); if (k != lp->m) glp_sdf_error(data, "wrong number of rows\n"); k = glp_sdf_read_int(data); if (k != lp->n) glp_sdf_error(data, "wrong number of columns\n"); /* solution status, objective value */ k = glp_sdf_read_int(data); if (!(k == GLP_UNDEF || k == GLP_OPT)) glp_sdf_error(data, "invalid solution status\n"); lp->ipt_stat = k; lp->ipt_obj = glp_sdf_read_num(data); /* rows (auxiliary variables) */ for (i = 1; i <= lp->m; i++) { GLPROW *row = lp->row[i]; /* primal value, dual value */ row->pval = glp_sdf_read_num(data); row->dval = glp_sdf_read_num(data); } /* columns (structural variables) */ for (j = 1; j <= lp->n; j++) { GLPCOL *col = lp->col[j]; /* primal value, dual value */ col->pval = glp_sdf_read_num(data); col->dval = glp_sdf_read_num(data); } xprintf("%d lines were read\n", glp_sdf_line(data)); done: if (ret) lp->ipt_stat = GLP_UNDEF; if (data != NULL) glp_sdf_close_file(data); return ret; } /*********************************************************************** * NAME * * glp_write_ipt - write interior-point solution to text file * * SYNOPSIS * * int glp_write_ipt(glp_prob *lp, const char *fname); * * DESCRIPTION * * The routine glp_write_ipt writes the current interior-point solution * to a text file whose name is specified by the parameter fname. This * file can be read back with the routine glp_read_ipt. * * RETURNS * * On success the routine returns zero, otherwise non-zero. * * FILE FORMAT * * The file created by the routine glp_write_ipt is a plain text file, * which contains the following information: * * m n * stat obj_val * r_prim[1] r_dual[1] * . . . * r_prim[m] r_dual[m] * c_prim[1] c_dual[1] * . . . * c_prim[n] c_dual[n] * * where: * m is the number of rows (auxiliary variables); * n is the number of columns (structural variables); * stat is the solution status (GLP_UNDEF = 1 or GLP_OPT = 5); * obj_val is the objective value; * r_prim[i], i = 1,...,m, is the primal value of i-th row; * r_dual[i], i = 1,...,m, is the dual value of i-th row; * c_prim[j], j = 1,...,n, is the primal value of j-th column; * c_dual[j], j = 1,...,n, is the dual value of j-th column. */ int glp_write_ipt(glp_prob *lp, const char *fname) { XFILE *fp; int i, j, ret = 0; xprintf("Writing interior-point solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* number of rows, number of columns */ xfprintf(fp, "%d %d\n", lp->m, lp->n); /* solution status, objective value */ xfprintf(fp, "%d %.*g\n", lp->ipt_stat, DBL_DIG, lp->ipt_obj); /* rows (auxiliary variables) */ for (i = 1; i <= lp->m; i++) { GLPROW *row = lp->row[i]; /* primal value, dual value */ xfprintf(fp, "%.*g %.*g\n", DBL_DIG, row->pval, DBL_DIG, row->dval); } /* columns (structural variables) */ for (j = 1; j <= lp->n; j++) { GLPCOL *col = lp->col[j]; /* primal value, dual value */ xfprintf(fp, "%.*g %.*g\n", DBL_DIG, col->pval, DBL_DIG, col->dval); } xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", 2 + lp->m + lp->n); done: if (fp != NULL) xfclose(fp); return ret; } /**********************************************************************/ int glp_print_mip(glp_prob *P, const char *fname) { /* write MIP solution in printable format */ XFILE *fp; GLPROW *row; GLPCOL *col; int i, j, t, ae_ind, re_ind, ret; double ae_max, re_max; xprintf("Writing MIP solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "%-12s%s\n", "Problem:", P->name == NULL ? "" : P->name); xfprintf(fp, "%-12s%d\n", "Rows:", P->m); xfprintf(fp, "%-12s%d (%d integer, %d binary)\n", "Columns:", P->n, glp_get_num_int(P), glp_get_num_bin(P)); xfprintf(fp, "%-12s%d\n", "Non-zeros:", P->nnz); t = glp_mip_status(P); xfprintf(fp, "%-12s%s\n", "Status:", t == GLP_OPT ? "INTEGER OPTIMAL" : t == GLP_FEAS ? "INTEGER NON-OPTIMAL" : t == GLP_NOFEAS ? "INTEGER EMPTY" : t == GLP_UNDEF ? "INTEGER UNDEFINED" : "???"); xfprintf(fp, "%-12s%s%s%.10g (%s)\n", "Objective:", P->obj == NULL ? "" : P->obj, P->obj == NULL ? "" : " = ", P->mip_obj, P->dir == GLP_MIN ? "MINimum" : P->dir == GLP_MAX ? "MAXimum" : "???"); xfprintf(fp, "\n"); xfprintf(fp, " No. Row name Activity Lower bound " " Upper bound\n"); xfprintf(fp, "------ ------------ ------------- ------------- " "-------------\n"); for (i = 1; i <= P->m; i++) { row = P->row[i]; xfprintf(fp, "%6d ", i); if (row->name == NULL || strlen(row->name) <= 12) xfprintf(fp, "%-12s ", row->name == NULL ? "" : row->name); else xfprintf(fp, "%s\n%20s", row->name, ""); xfprintf(fp, "%3s", ""); xfprintf(fp, "%13.6g ", fabs(row->mipx) <= 1e-9 ? 0.0 : row->mipx); if (row->type == GLP_LO || row->type == GLP_DB || row->type == GLP_FX) xfprintf(fp, "%13.6g ", row->lb); else xfprintf(fp, "%13s ", ""); if (row->type == GLP_UP || row->type == GLP_DB) xfprintf(fp, "%13.6g ", row->ub); else xfprintf(fp, "%13s ", row->type == GLP_FX ? "=" : ""); xfprintf(fp, "\n"); } xfprintf(fp, "\n"); xfprintf(fp, " No. Column name Activity Lower bound " " Upper bound\n"); xfprintf(fp, "------ ------------ ------------- ------------- " "-------------\n"); for (j = 1; j <= P->n; j++) { col = P->col[j]; xfprintf(fp, "%6d ", j); if (col->name == NULL || strlen(col->name) <= 12) xfprintf(fp, "%-12s ", col->name == NULL ? "" : col->name); else xfprintf(fp, "%s\n%20s", col->name, ""); xfprintf(fp, "%s ", col->kind == GLP_CV ? " " : col->kind == GLP_IV ? "*" : "?"); xfprintf(fp, "%13.6g ", fabs(col->mipx) <= 1e-9 ? 0.0 : col->mipx); if (col->type == GLP_LO || col->type == GLP_DB || col->type == GLP_FX) xfprintf(fp, "%13.6g ", col->lb); else xfprintf(fp, "%13s ", ""); if (col->type == GLP_UP || col->type == GLP_DB) xfprintf(fp, "%13.6g ", col->ub); else xfprintf(fp, "%13s ", col->type == GLP_FX ? "=" : ""); xfprintf(fp, "\n"); } xfprintf(fp, "\n"); xfprintf(fp, "Integer feasibility conditions:\n"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.PE: max.abs.err = %.2e on row %d\n", ae_max, ae_ind); xfprintf(fp, " max.rel.err = %.2e on row %d\n", re_max, re_ind); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "SOLUTION IS WRONG"); xfprintf(fp, "\n"); glp_check_kkt(P, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, &re_ind); xfprintf(fp, "KKT.PB: max.abs.err = %.2e on %s %d\n", ae_max, ae_ind <= P->m ? "row" : "column", ae_ind <= P->m ? ae_ind : ae_ind - P->m); xfprintf(fp, " max.rel.err = %.2e on %s %d\n", re_max, re_ind <= P->m ? "row" : "column", re_ind <= P->m ? re_ind : re_ind - P->m); xfprintf(fp, "%8s%s\n", "", re_max <= 1e-9 ? "High quality" : re_max <= 1e-6 ? "Medium quality" : re_max <= 1e-3 ? "Low quality" : "SOLUTION IS INFEASIBLE"); xfprintf(fp, "\n"); xfprintf(fp, "End of output\n"); xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /*********************************************************************** * NAME * * glp_read_mip - read MIP solution from text file * * SYNOPSIS * * int glp_read_mip(glp_prob *mip, const char *fname); * * DESCRIPTION * * The routine glp_read_mip reads MIP solution from a text file whose * name is specified by the parameter fname into the problem object. * * For the file format see description of the routine glp_write_mip. * * RETURNS * * On success the routine returns zero, otherwise non-zero. */ int glp_read_mip(glp_prob *mip, const char *fname) { glp_data *data; jmp_buf jump; int i, j, k, ret = 0; xprintf("Reading MIP solution from `%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; goto done; } if (setjmp(jump)) { ret = 1; goto done; } glp_sdf_set_jump(data, jump); /* number of rows, number of columns */ k = glp_sdf_read_int(data); if (k != mip->m) glp_sdf_error(data, "wrong number of rows\n"); k = glp_sdf_read_int(data); if (k != mip->n) glp_sdf_error(data, "wrong number of columns\n"); /* solution status, objective value */ k = glp_sdf_read_int(data); if (!(k == GLP_UNDEF || k == GLP_OPT || k == GLP_FEAS || k == GLP_NOFEAS)) glp_sdf_error(data, "invalid solution status\n"); mip->mip_stat = k; mip->mip_obj = glp_sdf_read_num(data); /* rows (auxiliary variables) */ for (i = 1; i <= mip->m; i++) { GLPROW *row = mip->row[i]; row->mipx = glp_sdf_read_num(data); } /* columns (structural variables) */ for (j = 1; j <= mip->n; j++) { GLPCOL *col = mip->col[j]; col->mipx = glp_sdf_read_num(data); if (col->kind == GLP_IV && col->mipx != floor(col->mipx)) glp_sdf_error(data, "non-integer column value"); } xprintf("%d lines were read\n", glp_sdf_line(data)); done: if (ret) mip->mip_stat = GLP_UNDEF; if (data != NULL) glp_sdf_close_file(data); return ret; } /*********************************************************************** * NAME * * glp_write_mip - write MIP solution to text file * * SYNOPSIS * * int glp_write_mip(glp_prob *mip, const char *fname); * * DESCRIPTION * * The routine glp_write_mip writes the current MIP solution to a text * file whose name is specified by the parameter fname. This file can * be read back with the routine glp_read_mip. * * RETURNS * * On success the routine returns zero, otherwise non-zero. * * FILE FORMAT * * The file created by the routine glp_write_sol is a plain text file, * which contains the following information: * * m n * stat obj_val * r_val[1] * . . . * r_val[m] * c_val[1] * . . . * c_val[n] * * where: * m is the number of rows (auxiliary variables); * n is the number of columns (structural variables); * stat is the solution status (GLP_UNDEF = 1, GLP_FEAS = 2, * GLP_NOFEAS = 4, or GLP_OPT = 5); * obj_val is the objective value; * r_val[i], i = 1,...,m, is the value of i-th row; * c_val[j], j = 1,...,n, is the value of j-th column. */ int glp_write_mip(glp_prob *mip, const char *fname) { XFILE *fp; int i, j, ret = 0; xprintf("Writing MIP solution to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* number of rows, number of columns */ xfprintf(fp, "%d %d\n", mip->m, mip->n); /* solution status, objective value */ xfprintf(fp, "%d %.*g\n", mip->mip_stat, DBL_DIG, mip->mip_obj); /* rows (auxiliary variables) */ for (i = 1; i <= mip->m; i++) xfprintf(fp, "%.*g\n", DBL_DIG, mip->row[i]->mipx); /* columns (structural variables) */ for (j = 1; j <= mip->n; j++) xfprintf(fp, "%.*g\n", DBL_DIG, mip->col[j]->mipx); xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", 2 + mip->m + mip->n); done: if (fp != NULL) xfclose(fp); return ret; } /* eof */ glpk-4.52.1/src/glpapi12.c0000644000062000006210000023630212175147600014301 0ustar maomkpasswd/* glpapi12.c (basis factorization and simplex tableau routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * glp_bf_exists - check if the basis factorization exists * * SYNOPSIS * * int glp_bf_exists(glp_prob *lp); * * RETURNS * * If the basis factorization for the current basis associated with * the specified problem object exists and therefore is available for * computations, the routine glp_bf_exists returns non-zero. Otherwise * the routine returns zero. */ int glp_bf_exists(glp_prob *lp) { int ret; ret = (lp->m == 0 || lp->valid); return ret; } /*********************************************************************** * NAME * * glp_factorize - compute the basis factorization * * SYNOPSIS * * int glp_factorize(glp_prob *lp); * * DESCRIPTION * * The routine glp_factorize computes the basis factorization for the * current basis associated with the specified problem object. * * RETURNS * * 0 The basis factorization has been successfully computed. * * GLP_EBADB * The basis matrix is invalid, i.e. the number of basic (auxiliary * and structural) variables differs from the number of rows in the * problem object. * * GLP_ESING * The basis matrix is singular within the working precision. * * GLP_ECOND * The basis matrix is ill-conditioned. */ static int b_col(void *info, int j, int ind[], double val[]) { glp_prob *lp = info; int m = lp->m; GLPAIJ *aij; int k, len; xassert(1 <= j && j <= m); /* determine the ordinal number of basic auxiliary or structural variable x[k] corresponding to basic variable xB[j] */ k = lp->head[j]; /* build j-th column of the basic matrix, which is k-th column of the scaled augmented matrix (I | -R*A*S) */ if (k <= m) { /* x[k] is auxiliary variable */ len = 1; ind[1] = k; val[1] = 1.0; } else { /* x[k] is structural variable */ len = 0; for (aij = lp->col[k-m]->ptr; aij != NULL; aij = aij->c_next) { len++; ind[len] = aij->row->i; val[len] = - aij->row->rii * aij->val * aij->col->sjj; } } return len; } static void copy_bfcp(glp_prob *lp); int glp_factorize(glp_prob *lp) { int m = lp->m; int n = lp->n; GLPROW **row = lp->row; GLPCOL **col = lp->col; int *head = lp->head; int j, k, stat, ret; /* invalidate the basis factorization */ lp->valid = 0; /* build the basis header */ j = 0; for (k = 1; k <= m+n; k++) { if (k <= m) { stat = row[k]->stat; row[k]->bind = 0; } else { stat = col[k-m]->stat; col[k-m]->bind = 0; } if (stat == GLP_BS) { j++; if (j > m) { /* too many basic variables */ ret = GLP_EBADB; goto fini; } head[j] = k; if (k <= m) row[k]->bind = j; else col[k-m]->bind = j; } } if (j < m) { /* too few basic variables */ ret = GLP_EBADB; goto fini; } /* try to factorize the basis matrix */ if (m > 0) { if (lp->bfd == NULL) { lp->bfd = bfd_create_it(); copy_bfcp(lp); } switch (bfd_factorize(lp->bfd, m, lp->head, b_col, lp)) { case 0: /* ok */ break; case BFD_ESING: /* singular matrix */ ret = GLP_ESING; goto fini; case BFD_ECOND: /* ill-conditioned matrix */ ret = GLP_ECOND; goto fini; default: xassert(lp != lp); } lp->valid = 1; } /* factorization successful */ ret = 0; fini: /* bring the return code to the calling program */ return ret; } /*********************************************************************** * NAME * * glp_bf_updated - check if the basis factorization has been updated * * SYNOPSIS * * int glp_bf_updated(glp_prob *lp); * * RETURNS * * If the basis factorization has been just computed from scratch, the * routine glp_bf_updated returns zero. Otherwise, if the factorization * has been updated one or more times, the routine returns non-zero. */ int glp_bf_updated(glp_prob *lp) { int cnt; if (!(lp->m == 0 || lp->valid)) xerror("glp_bf_update: basis factorization does not exist\n"); #if 0 /* 15/XI-2009 */ cnt = (lp->m == 0 ? 0 : lp->bfd->upd_cnt); #else cnt = (lp->m == 0 ? 0 : bfd_get_count(lp->bfd)); #endif return cnt; } /*********************************************************************** * NAME * * glp_get_bfcp - retrieve basis factorization control parameters * * SYNOPSIS * * void glp_get_bfcp(glp_prob *lp, glp_bfcp *parm); * * DESCRIPTION * * The routine glp_get_bfcp retrieves control parameters, which are * used on computing and updating the basis factorization associated * with the specified problem object. * * Current values of control parameters are stored by the routine in * a glp_bfcp structure, which the parameter parm points to. */ void glp_get_bfcp(glp_prob *lp, glp_bfcp *parm) { glp_bfcp *bfcp = lp->bfcp; if (bfcp == NULL) { parm->type = GLP_BF_FT; parm->lu_size = 0; parm->piv_tol = 0.10; parm->piv_lim = 4; parm->suhl = GLP_ON; parm->eps_tol = 1e-15; parm->max_gro = 1e+10; parm->nfs_max = 100; parm->upd_tol = 1e-6; parm->nrs_max = 100; parm->rs_size = 0; } else memcpy(parm, bfcp, sizeof(glp_bfcp)); return; } /*********************************************************************** * NAME * * glp_set_bfcp - change basis factorization control parameters * * SYNOPSIS * * void glp_set_bfcp(glp_prob *lp, const glp_bfcp *parm); * * DESCRIPTION * * The routine glp_set_bfcp changes control parameters, which are used * by internal GLPK routines in computing and updating the basis * factorization associated with the specified problem object. * * New values of the control parameters should be passed in a structure * glp_bfcp, which the parameter parm points to. * * The parameter parm can be specified as NULL, in which case all * control parameters are reset to their default values. */ #if 0 /* 15/XI-2009 */ static void copy_bfcp(glp_prob *lp) { glp_bfcp _parm, *parm = &_parm; BFD *bfd = lp->bfd; glp_get_bfcp(lp, parm); xassert(bfd != NULL); bfd->type = parm->type; bfd->lu_size = parm->lu_size; bfd->piv_tol = parm->piv_tol; bfd->piv_lim = parm->piv_lim; bfd->suhl = parm->suhl; bfd->eps_tol = parm->eps_tol; bfd->max_gro = parm->max_gro; bfd->nfs_max = parm->nfs_max; bfd->upd_tol = parm->upd_tol; bfd->nrs_max = parm->nrs_max; bfd->rs_size = parm->rs_size; return; } #else static void copy_bfcp(glp_prob *lp) { glp_bfcp _parm, *parm = &_parm; glp_get_bfcp(lp, parm); bfd_set_parm(lp->bfd, parm); return; } #endif void glp_set_bfcp(glp_prob *lp, const glp_bfcp *parm) { glp_bfcp *bfcp = lp->bfcp; if (parm == NULL) { /* reset to default values */ if (bfcp != NULL) xfree(bfcp), lp->bfcp = NULL; } else { /* set to specified values */ if (bfcp == NULL) bfcp = lp->bfcp = xmalloc(sizeof(glp_bfcp)); memcpy(bfcp, parm, sizeof(glp_bfcp)); if (!(bfcp->type == GLP_BF_FT || bfcp->type == GLP_BF_BG || bfcp->type == GLP_BF_GR)) xerror("glp_set_bfcp: type = %d; invalid parameter\n", bfcp->type); if (bfcp->lu_size < 0) xerror("glp_set_bfcp: lu_size = %d; invalid parameter\n", bfcp->lu_size); if (!(0.0 < bfcp->piv_tol && bfcp->piv_tol < 1.0)) xerror("glp_set_bfcp: piv_tol = %g; invalid parameter\n", bfcp->piv_tol); if (bfcp->piv_lim < 1) xerror("glp_set_bfcp: piv_lim = %d; invalid parameter\n", bfcp->piv_lim); if (!(bfcp->suhl == GLP_ON || bfcp->suhl == GLP_OFF)) xerror("glp_set_bfcp: suhl = %d; invalid parameter\n", bfcp->suhl); if (!(0.0 <= bfcp->eps_tol && bfcp->eps_tol <= 1e-6)) xerror("glp_set_bfcp: eps_tol = %g; invalid parameter\n", bfcp->eps_tol); if (bfcp->max_gro < 1.0) xerror("glp_set_bfcp: max_gro = %g; invalid parameter\n", bfcp->max_gro); if (!(1 <= bfcp->nfs_max && bfcp->nfs_max <= 32767)) xerror("glp_set_bfcp: nfs_max = %d; invalid parameter\n", bfcp->nfs_max); if (!(0.0 < bfcp->upd_tol && bfcp->upd_tol < 1.0)) xerror("glp_set_bfcp: upd_tol = %g; invalid parameter\n", bfcp->upd_tol); if (!(1 <= bfcp->nrs_max && bfcp->nrs_max <= 32767)) xerror("glp_set_bfcp: nrs_max = %d; invalid parameter\n", bfcp->nrs_max); if (bfcp->rs_size < 0) xerror("glp_set_bfcp: rs_size = %d; invalid parameter\n", bfcp->nrs_max); if (bfcp->rs_size == 0) bfcp->rs_size = 20 * bfcp->nrs_max; } if (lp->bfd != NULL) copy_bfcp(lp); return; } /*********************************************************************** * NAME * * glp_get_bhead - retrieve the basis header information * * SYNOPSIS * * int glp_get_bhead(glp_prob *lp, int k); * * DESCRIPTION * * The routine glp_get_bhead returns the basis header information for * the current basis associated with the specified problem object. * * RETURNS * * If xB[k], 1 <= k <= m, is i-th auxiliary variable (1 <= i <= m), the * routine returns i. Otherwise, if xB[k] is j-th structural variable * (1 <= j <= n), the routine returns m+j. Here m is the number of rows * and n is the number of columns in the problem object. */ int glp_get_bhead(glp_prob *lp, int k) { if (!(lp->m == 0 || lp->valid)) xerror("glp_get_bhead: basis factorization does not exist\n"); if (!(1 <= k && k <= lp->m)) xerror("glp_get_bhead: k = %d; index out of range\n", k); return lp->head[k]; } /*********************************************************************** * NAME * * glp_get_row_bind - retrieve row index in the basis header * * SYNOPSIS * * int glp_get_row_bind(glp_prob *lp, int i); * * RETURNS * * The routine glp_get_row_bind returns the index k of basic variable * xB[k], 1 <= k <= m, which is i-th auxiliary variable, 1 <= i <= m, * in the current basis associated with the specified problem object, * where m is the number of rows. However, if i-th auxiliary variable * is non-basic, the routine returns zero. */ int glp_get_row_bind(glp_prob *lp, int i) { if (!(lp->m == 0 || lp->valid)) xerror("glp_get_row_bind: basis factorization does not exist\n" ); if (!(1 <= i && i <= lp->m)) xerror("glp_get_row_bind: i = %d; row number out of range\n", i); return lp->row[i]->bind; } /*********************************************************************** * NAME * * glp_get_col_bind - retrieve column index in the basis header * * SYNOPSIS * * int glp_get_col_bind(glp_prob *lp, int j); * * RETURNS * * The routine glp_get_col_bind returns the index k of basic variable * xB[k], 1 <= k <= m, which is j-th structural variable, 1 <= j <= n, * in the current basis associated with the specified problem object, * where m is the number of rows, n is the number of columns. However, * if j-th structural variable is non-basic, the routine returns zero.*/ int glp_get_col_bind(glp_prob *lp, int j) { if (!(lp->m == 0 || lp->valid)) xerror("glp_get_col_bind: basis factorization does not exist\n" ); if (!(1 <= j && j <= lp->n)) xerror("glp_get_col_bind: j = %d; column number out of range\n" , j); return lp->col[j]->bind; } /*********************************************************************** * NAME * * glp_ftran - perform forward transformation (solve system B*x = b) * * SYNOPSIS * * void glp_ftran(glp_prob *lp, double x[]); * * DESCRIPTION * * The routine glp_ftran performs forward transformation, i.e. solves * the system B*x = b, where B is the basis matrix corresponding to the * current basis for the specified problem object, x is the vector of * unknowns to be computed, b is the vector of right-hand sides. * * On entry elements of the vector b should be stored in dense format * in locations x[1], ..., x[m], where m is the number of rows. On exit * the routine stores elements of the vector x in the same locations. * * SCALING/UNSCALING * * Let A~ = (I | -A) is the augmented constraint matrix of the original * (unscaled) problem. In the scaled LP problem instead the matrix A the * scaled matrix A" = R*A*S is actually used, so * * A~" = (I | A") = (I | R*A*S) = (R*I*inv(R) | R*A*S) = * (1) * = R*(I | A)*S~ = R*A~*S~, * * is the scaled augmented constraint matrix, where R and S are diagonal * scaling matrices used to scale rows and columns of the matrix A, and * * S~ = diag(inv(R) | S) (2) * * is an augmented diagonal scaling matrix. * * By definition: * * A~ = (B | N), (3) * * where B is the basic matrix, which consists of basic columns of the * augmented constraint matrix A~, and N is a matrix, which consists of * non-basic columns of A~. From (1) it follows that: * * A~" = (B" | N") = (R*B*SB | R*N*SN), (4) * * where SB and SN are parts of the augmented scaling matrix S~, which * correspond to basic and non-basic variables, respectively. Therefore * * B" = R*B*SB, (5) * * which is the scaled basis matrix. */ void glp_ftran(glp_prob *lp, double x[]) { int m = lp->m; GLPROW **row = lp->row; GLPCOL **col = lp->col; int i, k; /* B*x = b ===> (R*B*SB)*(inv(SB)*x) = R*b ===> B"*x" = b", where b" = R*b, x = SB*x" */ if (!(m == 0 || lp->valid)) xerror("glp_ftran: basis factorization does not exist\n"); /* b" := R*b */ for (i = 1; i <= m; i++) x[i] *= row[i]->rii; /* x" := inv(B")*b" */ if (m > 0) bfd_ftran(lp->bfd, x); /* x := SB*x" */ for (i = 1; i <= m; i++) { k = lp->head[i]; if (k <= m) x[i] /= row[k]->rii; else x[i] *= col[k-m]->sjj; } return; } /*********************************************************************** * NAME * * glp_btran - perform backward transformation (solve system B'*x = b) * * SYNOPSIS * * void glp_btran(glp_prob *lp, double x[]); * * DESCRIPTION * * The routine glp_btran performs backward transformation, i.e. solves * the system B'*x = b, where B' is a matrix transposed to the basis * matrix corresponding to the current basis for the specified problem * problem object, x is the vector of unknowns to be computed, b is the * vector of right-hand sides. * * On entry elements of the vector b should be stored in dense format * in locations x[1], ..., x[m], where m is the number of rows. On exit * the routine stores elements of the vector x in the same locations. * * SCALING/UNSCALING * * See comments to the routine glp_ftran. */ void glp_btran(glp_prob *lp, double x[]) { int m = lp->m; GLPROW **row = lp->row; GLPCOL **col = lp->col; int i, k; /* B'*x = b ===> (SB*B'*R)*(inv(R)*x) = SB*b ===> (B")'*x" = b", where b" = SB*b, x = R*x" */ if (!(m == 0 || lp->valid)) xerror("glp_btran: basis factorization does not exist\n"); /* b" := SB*b */ for (i = 1; i <= m; i++) { k = lp->head[i]; if (k <= m) x[i] /= row[k]->rii; else x[i] *= col[k-m]->sjj; } /* x" := inv[(B")']*b" */ if (m > 0) bfd_btran(lp->bfd, x); /* x := R*x" */ for (i = 1; i <= m; i++) x[i] *= row[i]->rii; return; } /*********************************************************************** * NAME * * glp_warm_up - "warm up" LP basis * * SYNOPSIS * * int glp_warm_up(glp_prob *P); * * DESCRIPTION * * The routine glp_warm_up "warms up" the LP basis for the specified * problem object using current statuses assigned to rows and columns * (that is, to auxiliary and structural variables). * * This operation includes computing factorization of the basis matrix * (if it does not exist), computing primal and dual components of basic * solution, and determining the solution status. * * RETURNS * * 0 The operation has been successfully performed. * * GLP_EBADB * The basis matrix is invalid, i.e. the number of basic (auxiliary * and structural) variables differs from the number of rows in the * problem object. * * GLP_ESING * The basis matrix is singular within the working precision. * * GLP_ECOND * The basis matrix is ill-conditioned. */ int glp_warm_up(glp_prob *P) { GLPROW *row; GLPCOL *col; GLPAIJ *aij; int i, j, type, stat, ret; double eps, temp, *work; /* invalidate basic solution */ P->pbs_stat = P->dbs_stat = GLP_UNDEF; P->obj_val = 0.0; P->some = 0; for (i = 1; i <= P->m; i++) { row = P->row[i]; row->prim = row->dual = 0.0; } for (j = 1; j <= P->n; j++) { col = P->col[j]; col->prim = col->dual = 0.0; } /* compute the basis factorization, if necessary */ if (!glp_bf_exists(P)) { ret = glp_factorize(P); if (ret != 0) goto done; } /* allocate working array */ work = xcalloc(1+P->m, sizeof(double)); /* determine and store values of non-basic variables, compute vector (- N * xN) */ for (i = 1; i <= P->m; i++) work[i] = 0.0; for (i = 1; i <= P->m; i++) { row = P->row[i]; if (row->stat == GLP_BS) continue; else if (row->stat == GLP_NL) row->prim = row->lb; else if (row->stat == GLP_NU) row->prim = row->ub; else if (row->stat == GLP_NF) row->prim = 0.0; else if (row->stat == GLP_NS) row->prim = row->lb; else xassert(row != row); /* N[j] is i-th column of matrix (I|-A) */ work[i] -= row->prim; } for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->stat == GLP_BS) continue; else if (col->stat == GLP_NL) col->prim = col->lb; else if (col->stat == GLP_NU) col->prim = col->ub; else if (col->stat == GLP_NF) col->prim = 0.0; else if (col->stat == GLP_NS) col->prim = col->lb; else xassert(col != col); /* N[j] is (m+j)-th column of matrix (I|-A) */ if (col->prim != 0.0) { for (aij = col->ptr; aij != NULL; aij = aij->c_next) work[aij->row->i] += aij->val * col->prim; } } /* compute vector of basic variables xB = - inv(B) * N * xN */ glp_ftran(P, work); /* store values of basic variables, check primal feasibility */ P->pbs_stat = GLP_FEAS; for (i = 1; i <= P->m; i++) { row = P->row[i]; if (row->stat != GLP_BS) continue; row->prim = work[row->bind]; type = row->type; if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { eps = 1e-6 + 1e-9 * fabs(row->lb); if (row->prim < row->lb - eps) P->pbs_stat = GLP_INFEAS; } if (type == GLP_UP || type == GLP_DB || type == GLP_FX) { eps = 1e-6 + 1e-9 * fabs(row->ub); if (row->prim > row->ub + eps) P->pbs_stat = GLP_INFEAS; } } for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->stat != GLP_BS) continue; col->prim = work[col->bind]; type = col->type; if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { eps = 1e-6 + 1e-9 * fabs(col->lb); if (col->prim < col->lb - eps) P->pbs_stat = GLP_INFEAS; } if (type == GLP_UP || type == GLP_DB || type == GLP_FX) { eps = 1e-6 + 1e-9 * fabs(col->ub); if (col->prim > col->ub + eps) P->pbs_stat = GLP_INFEAS; } } /* compute value of the objective function */ P->obj_val = P->c0; for (j = 1; j <= P->n; j++) { col = P->col[j]; P->obj_val += col->coef * col->prim; } /* build vector cB of objective coefficients at basic variables */ for (i = 1; i <= P->m; i++) work[i] = 0.0; for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->stat == GLP_BS) work[col->bind] = col->coef; } /* compute vector of simplex multipliers pi = inv(B') * cB */ glp_btran(P, work); /* compute and store reduced costs of non-basic variables d[j] = c[j] - N'[j] * pi, check dual feasibility */ P->dbs_stat = GLP_FEAS; for (i = 1; i <= P->m; i++) { row = P->row[i]; if (row->stat == GLP_BS) { row->dual = 0.0; continue; } /* N[j] is i-th column of matrix (I|-A) */ row->dual = - work[i]; #if 0 /* 07/III-2013 */ type = row->type; temp = (P->dir == GLP_MIN ? + row->dual : - row->dual); if ((type == GLP_FR || type == GLP_LO) && temp < -1e-5 || (type == GLP_FR || type == GLP_UP) && temp > +1e-5) P->dbs_stat = GLP_INFEAS; #else stat = row->stat; temp = (P->dir == GLP_MIN ? + row->dual : - row->dual); if ((stat == GLP_NF || stat == GLP_NL) && temp < -1e-5 || (stat == GLP_NF || stat == GLP_NU) && temp > +1e-5) P->dbs_stat = GLP_INFEAS; #endif } for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->stat == GLP_BS) { col->dual = 0.0; continue; } /* N[j] is (m+j)-th column of matrix (I|-A) */ col->dual = col->coef; for (aij = col->ptr; aij != NULL; aij = aij->c_next) col->dual += aij->val * work[aij->row->i]; #if 0 /* 07/III-2013 */ type = col->type; temp = (P->dir == GLP_MIN ? + col->dual : - col->dual); if ((type == GLP_FR || type == GLP_LO) && temp < -1e-5 || (type == GLP_FR || type == GLP_UP) && temp > +1e-5) P->dbs_stat = GLP_INFEAS; #else stat = col->stat; temp = (P->dir == GLP_MIN ? + col->dual : - col->dual); if ((stat == GLP_NF || stat == GLP_NL) && temp < -1e-5 || (stat == GLP_NF || stat == GLP_NU) && temp > +1e-5) P->dbs_stat = GLP_INFEAS; #endif } /* free working array */ xfree(work); ret = 0; done: return ret; } /*********************************************************************** * NAME * * glp_eval_tab_row - compute row of the simplex tableau * * SYNOPSIS * * int glp_eval_tab_row(glp_prob *lp, int k, int ind[], double val[]); * * DESCRIPTION * * The routine glp_eval_tab_row computes a row of the current simplex * tableau for the basic variable, which is specified by the number k: * if 1 <= k <= m, x[k] is k-th auxiliary variable; if m+1 <= k <= m+n, * x[k] is (k-m)-th structural variable, where m is number of rows, and * n is number of columns. The current basis must be available. * * The routine stores column indices and numerical values of non-zero * elements of the computed row using sparse format to the locations * ind[1], ..., ind[len] and val[1], ..., val[len], respectively, where * 0 <= len <= n is number of non-zeros returned on exit. * * Element indices stored in the array ind have the same sense as the * index k, i.e. indices 1 to m denote auxiliary variables and indices * m+1 to m+n denote structural ones (all these variables are obviously * non-basic by definition). * * The computed row shows how the specified basic variable x[k] = xB[i] * depends on non-basic variables: * * xB[i] = alfa[i,1]*xN[1] + alfa[i,2]*xN[2] + ... + alfa[i,n]*xN[n], * * where alfa[i,j] are elements of the simplex table row, xN[j] are * non-basic (auxiliary and structural) variables. * * RETURNS * * The routine returns number of non-zero elements in the simplex table * row stored in the arrays ind and val. * * BACKGROUND * * The system of equality constraints of the LP problem is: * * xR = A * xS, (1) * * where xR is the vector of auxliary variables, xS is the vector of * structural variables, A is the matrix of constraint coefficients. * * The system (1) can be written in homogenous form as follows: * * A~ * x = 0, (2) * * where A~ = (I | -A) is the augmented constraint matrix (has m rows * and m+n columns), x = (xR | xS) is the vector of all (auxiliary and * structural) variables. * * By definition for the current basis we have: * * A~ = (B | N), (3) * * where B is the basis matrix. Thus, the system (2) can be written as: * * B * xB + N * xN = 0. (4) * * From (4) it follows that: * * xB = A^ * xN, (5) * * where the matrix * * A^ = - inv(B) * N (6) * * is called the simplex table. * * It is understood that i-th row of the simplex table is: * * e * A^ = - e * inv(B) * N, (7) * * where e is a unity vector with e[i] = 1. * * To compute i-th row of the simplex table the routine first computes * i-th row of the inverse: * * rho = inv(B') * e, (8) * * where B' is a matrix transposed to B, and then computes elements of * i-th row of the simplex table as scalar products: * * alfa[i,j] = - rho * N[j] for all j, (9) * * where N[j] is a column of the augmented constraint matrix A~, which * corresponds to some non-basic auxiliary or structural variable. */ int glp_eval_tab_row(glp_prob *lp, int k, int ind[], double val[]) { int m = lp->m; int n = lp->n; int i, t, len, lll, *iii; double alfa, *rho, *vvv; if (!(m == 0 || lp->valid)) xerror("glp_eval_tab_row: basis factorization does not exist\n" ); if (!(1 <= k && k <= m+n)) xerror("glp_eval_tab_row: k = %d; variable number out of range" , k); /* determine xB[i] which corresponds to x[k] */ if (k <= m) i = glp_get_row_bind(lp, k); else i = glp_get_col_bind(lp, k-m); if (i == 0) xerror("glp_eval_tab_row: k = %d; variable must be basic", k); xassert(1 <= i && i <= m); /* allocate working arrays */ rho = xcalloc(1+m, sizeof(double)); iii = xcalloc(1+m, sizeof(int)); vvv = xcalloc(1+m, sizeof(double)); /* compute i-th row of the inverse; see (8) */ for (t = 1; t <= m; t++) rho[t] = 0.0; rho[i] = 1.0; glp_btran(lp, rho); /* compute i-th row of the simplex table */ len = 0; for (k = 1; k <= m+n; k++) { if (k <= m) { /* x[k] is auxiliary variable, so N[k] is a unity column */ if (glp_get_row_stat(lp, k) == GLP_BS) continue; /* compute alfa[i,j]; see (9) */ alfa = - rho[k]; } else { /* x[k] is structural variable, so N[k] is a column of the original constraint matrix A with negative sign */ if (glp_get_col_stat(lp, k-m) == GLP_BS) continue; /* compute alfa[i,j]; see (9) */ lll = glp_get_mat_col(lp, k-m, iii, vvv); alfa = 0.0; for (t = 1; t <= lll; t++) alfa += rho[iii[t]] * vvv[t]; } /* store alfa[i,j] */ if (alfa != 0.0) len++, ind[len] = k, val[len] = alfa; } xassert(len <= n); /* free working arrays */ xfree(rho); xfree(iii); xfree(vvv); /* return to the calling program */ return len; } /*********************************************************************** * NAME * * glp_eval_tab_col - compute column of the simplex tableau * * SYNOPSIS * * int glp_eval_tab_col(glp_prob *lp, int k, int ind[], double val[]); * * DESCRIPTION * * The routine glp_eval_tab_col computes a column of the current simplex * table for the non-basic variable, which is specified by the number k: * if 1 <= k <= m, x[k] is k-th auxiliary variable; if m+1 <= k <= m+n, * x[k] is (k-m)-th structural variable, where m is number of rows, and * n is number of columns. The current basis must be available. * * The routine stores row indices and numerical values of non-zero * elements of the computed column using sparse format to the locations * ind[1], ..., ind[len] and val[1], ..., val[len] respectively, where * 0 <= len <= m is number of non-zeros returned on exit. * * Element indices stored in the array ind have the same sense as the * index k, i.e. indices 1 to m denote auxiliary variables and indices * m+1 to m+n denote structural ones (all these variables are obviously * basic by the definition). * * The computed column shows how basic variables depend on the specified * non-basic variable x[k] = xN[j]: * * xB[1] = ... + alfa[1,j]*xN[j] + ... * xB[2] = ... + alfa[2,j]*xN[j] + ... * . . . . . . * xB[m] = ... + alfa[m,j]*xN[j] + ... * * where alfa[i,j] are elements of the simplex table column, xB[i] are * basic (auxiliary and structural) variables. * * RETURNS * * The routine returns number of non-zero elements in the simplex table * column stored in the arrays ind and val. * * BACKGROUND * * As it was explained in comments to the routine glp_eval_tab_row (see * above) the simplex table is the following matrix: * * A^ = - inv(B) * N. (1) * * Therefore j-th column of the simplex table is: * * A^ * e = - inv(B) * N * e = - inv(B) * N[j], (2) * * where e is a unity vector with e[j] = 1, B is the basis matrix, N[j] * is a column of the augmented constraint matrix A~, which corresponds * to the given non-basic auxiliary or structural variable. */ int glp_eval_tab_col(glp_prob *lp, int k, int ind[], double val[]) { int m = lp->m; int n = lp->n; int t, len, stat; double *col; if (!(m == 0 || lp->valid)) xerror("glp_eval_tab_col: basis factorization does not exist\n" ); if (!(1 <= k && k <= m+n)) xerror("glp_eval_tab_col: k = %d; variable number out of range" , k); if (k <= m) stat = glp_get_row_stat(lp, k); else stat = glp_get_col_stat(lp, k-m); if (stat == GLP_BS) xerror("glp_eval_tab_col: k = %d; variable must be non-basic", k); /* obtain column N[k] with negative sign */ col = xcalloc(1+m, sizeof(double)); for (t = 1; t <= m; t++) col[t] = 0.0; if (k <= m) { /* x[k] is auxiliary variable, so N[k] is a unity column */ col[k] = -1.0; } else { /* x[k] is structural variable, so N[k] is a column of the original constraint matrix A with negative sign */ len = glp_get_mat_col(lp, k-m, ind, val); for (t = 1; t <= len; t++) col[ind[t]] = val[t]; } /* compute column of the simplex table, which corresponds to the specified non-basic variable x[k] */ glp_ftran(lp, col); len = 0; for (t = 1; t <= m; t++) { if (col[t] != 0.0) { len++; ind[len] = glp_get_bhead(lp, t); val[len] = col[t]; } } xfree(col); /* return to the calling program */ return len; } /*********************************************************************** * NAME * * glp_transform_row - transform explicitly specified row * * SYNOPSIS * * int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); * * DESCRIPTION * * The routine glp_transform_row performs the same operation as the * routine glp_eval_tab_row with exception that the row to be * transformed is specified explicitly as a sparse vector. * * The explicitly specified row may be thought as a linear form: * * x = a[1]*x[m+1] + a[2]*x[m+2] + ... + a[n]*x[m+n], (1) * * where x is an auxiliary variable for this row, a[j] are coefficients * of the linear form, x[m+j] are structural variables. * * On entry column indices and numerical values of non-zero elements of * the row should be stored in locations ind[1], ..., ind[len] and * val[1], ..., val[len], where len is the number of non-zero elements. * * This routine uses the system of equality constraints and the current * basis in order to express the auxiliary variable x in (1) through the * current non-basic variables (as if the transformed row were added to * the problem object and its auxiliary variable were basic), i.e. the * resultant row has the form: * * x = alfa[1]*xN[1] + alfa[2]*xN[2] + ... + alfa[n]*xN[n], (2) * * where xN[j] are non-basic (auxiliary or structural) variables, n is * the number of columns in the LP problem object. * * On exit the routine stores indices and numerical values of non-zero * elements of the resultant row (2) in locations ind[1], ..., ind[len'] * and val[1], ..., val[len'], where 0 <= len' <= n is the number of * non-zero elements in the resultant row returned by the routine. Note * that indices (numbers) of non-basic variables stored in the array ind * correspond to original ordinal numbers of variables: indices 1 to m * mean auxiliary variables and indices m+1 to m+n mean structural ones. * * RETURNS * * The routine returns len', which is the number of non-zero elements in * the resultant row stored in the arrays ind and val. * * BACKGROUND * * The explicitly specified row (1) is transformed in the same way as it * were the objective function row. * * From (1) it follows that: * * x = aB * xB + aN * xN, (3) * * where xB is the vector of basic variables, xN is the vector of * non-basic variables. * * The simplex table, which corresponds to the current basis, is: * * xB = [-inv(B) * N] * xN. (4) * * Therefore substituting xB from (4) to (3) we have: * * x = aB * [-inv(B) * N] * xN + aN * xN = * (5) * = rho * (-N) * xN + aN * xN = alfa * xN, * * where: * * rho = inv(B') * aB, (6) * * and * * alfa = aN + rho * (-N) (7) * * is the resultant row computed by the routine. */ int glp_transform_row(glp_prob *P, int len, int ind[], double val[]) { int i, j, k, m, n, t, lll, *iii; double alfa, *a, *aB, *rho, *vvv; if (!glp_bf_exists(P)) xerror("glp_transform_row: basis factorization does not exist " "\n"); m = glp_get_num_rows(P); n = glp_get_num_cols(P); /* unpack the row to be transformed to the array a */ a = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) a[j] = 0.0; if (!(0 <= len && len <= n)) xerror("glp_transform_row: len = %d; invalid row length\n", len); for (t = 1; t <= len; t++) { j = ind[t]; if (!(1 <= j && j <= n)) xerror("glp_transform_row: ind[%d] = %d; column index out o" "f range\n", t, j); if (val[t] == 0.0) xerror("glp_transform_row: val[%d] = 0; zero coefficient no" "t allowed\n", t); if (a[j] != 0.0) xerror("glp_transform_row: ind[%d] = %d; duplicate column i" "ndices not allowed\n", t, j); a[j] = val[t]; } /* construct the vector aB */ aB = xcalloc(1+m, sizeof(double)); for (i = 1; i <= m; i++) { k = glp_get_bhead(P, i); /* xB[i] is k-th original variable */ xassert(1 <= k && k <= m+n); aB[i] = (k <= m ? 0.0 : a[k-m]); } /* solve the system B'*rho = aB to compute the vector rho */ rho = aB, glp_btran(P, rho); /* compute coefficients at non-basic auxiliary variables */ len = 0; for (i = 1; i <= m; i++) { if (glp_get_row_stat(P, i) != GLP_BS) { alfa = - rho[i]; if (alfa != 0.0) { len++; ind[len] = i; val[len] = alfa; } } } /* compute coefficients at non-basic structural variables */ iii = xcalloc(1+m, sizeof(int)); vvv = xcalloc(1+m, sizeof(double)); for (j = 1; j <= n; j++) { if (glp_get_col_stat(P, j) != GLP_BS) { alfa = a[j]; lll = glp_get_mat_col(P, j, iii, vvv); for (t = 1; t <= lll; t++) alfa += vvv[t] * rho[iii[t]]; if (alfa != 0.0) { len++; ind[len] = m+j; val[len] = alfa; } } } xassert(len <= n); xfree(iii); xfree(vvv); xfree(aB); xfree(a); return len; } /*********************************************************************** * NAME * * glp_transform_col - transform explicitly specified column * * SYNOPSIS * * int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); * * DESCRIPTION * * The routine glp_transform_col performs the same operation as the * routine glp_eval_tab_col with exception that the column to be * transformed is specified explicitly as a sparse vector. * * The explicitly specified column may be thought as if it were added * to the original system of equality constraints: * * x[1] = a[1,1]*x[m+1] + ... + a[1,n]*x[m+n] + a[1]*x * x[2] = a[2,1]*x[m+1] + ... + a[2,n]*x[m+n] + a[2]*x (1) * . . . . . . . . . . . . . . . * x[m] = a[m,1]*x[m+1] + ... + a[m,n]*x[m+n] + a[m]*x * * where x[i] are auxiliary variables, x[m+j] are structural variables, * x is a structural variable for the explicitly specified column, a[i] * are constraint coefficients for x. * * On entry row indices and numerical values of non-zero elements of * the column should be stored in locations ind[1], ..., ind[len] and * val[1], ..., val[len], where len is the number of non-zero elements. * * This routine uses the system of equality constraints and the current * basis in order to express the current basic variables through the * structural variable x in (1) (as if the transformed column were added * to the problem object and the variable x were non-basic), i.e. the * resultant column has the form: * * xB[1] = ... + alfa[1]*x * xB[2] = ... + alfa[2]*x (2) * . . . . . . * xB[m] = ... + alfa[m]*x * * where xB are basic (auxiliary and structural) variables, m is the * number of rows in the problem object. * * On exit the routine stores indices and numerical values of non-zero * elements of the resultant column (2) in locations ind[1], ..., * ind[len'] and val[1], ..., val[len'], where 0 <= len' <= m is the * number of non-zero element in the resultant column returned by the * routine. Note that indices (numbers) of basic variables stored in * the array ind correspond to original ordinal numbers of variables: * indices 1 to m mean auxiliary variables and indices m+1 to m+n mean * structural ones. * * RETURNS * * The routine returns len', which is the number of non-zero elements * in the resultant column stored in the arrays ind and val. * * BACKGROUND * * The explicitly specified column (1) is transformed in the same way * as any other column of the constraint matrix using the formula: * * alfa = inv(B) * a, (3) * * where alfa is the resultant column computed by the routine. */ int glp_transform_col(glp_prob *P, int len, int ind[], double val[]) { int i, m, t; double *a, *alfa; if (!glp_bf_exists(P)) xerror("glp_transform_col: basis factorization does not exist " "\n"); m = glp_get_num_rows(P); /* unpack the column to be transformed to the array a */ a = xcalloc(1+m, sizeof(double)); for (i = 1; i <= m; i++) a[i] = 0.0; if (!(0 <= len && len <= m)) xerror("glp_transform_col: len = %d; invalid column length\n", len); for (t = 1; t <= len; t++) { i = ind[t]; if (!(1 <= i && i <= m)) xerror("glp_transform_col: ind[%d] = %d; row index out of r" "ange\n", t, i); if (val[t] == 0.0) xerror("glp_transform_col: val[%d] = 0; zero coefficient no" "t allowed\n", t); if (a[i] != 0.0) xerror("glp_transform_col: ind[%d] = %d; duplicate row indi" "ces not allowed\n", t, i); a[i] = val[t]; } /* solve the system B*a = alfa to compute the vector alfa */ alfa = a, glp_ftran(P, alfa); /* store resultant coefficients */ len = 0; for (i = 1; i <= m; i++) { if (alfa[i] != 0.0) { len++; ind[len] = glp_get_bhead(P, i); val[len] = alfa[i]; } } xfree(a); return len; } /*********************************************************************** * NAME * * glp_prim_rtest - perform primal ratio test * * SYNOPSIS * * int glp_prim_rtest(glp_prob *P, int len, const int ind[], * const double val[], int dir, double eps); * * DESCRIPTION * * The routine glp_prim_rtest performs the primal ratio test using an * explicitly specified column of the simplex table. * * The current basic solution associated with the LP problem object * must be primal feasible. * * The explicitly specified column of the simplex table shows how the * basic variables xB depend on some non-basic variable x (which is not * necessarily presented in the problem object): * * xB[1] = ... + alfa[1] * x + ... * xB[2] = ... + alfa[2] * x + ... (*) * . . . . . . . . * xB[m] = ... + alfa[m] * x + ... * * The column (*) is specifed on entry to the routine using the sparse * format. Ordinal numbers of basic variables xB[i] should be placed in * locations ind[1], ..., ind[len], where ordinal number 1 to m denote * auxiliary variables, and ordinal numbers m+1 to m+n denote structural * variables. The corresponding non-zero coefficients alfa[i] should be * placed in locations val[1], ..., val[len]. The arrays ind and val are * not changed on exit. * * The parameter dir specifies direction in which the variable x changes * on entering the basis: +1 means increasing, -1 means decreasing. * * The parameter eps is an absolute tolerance (small positive number) * used by the routine to skip small alfa[j] of the row (*). * * The routine determines which basic variable (among specified in * ind[1], ..., ind[len]) should leave the basis in order to keep primal * feasibility. * * RETURNS * * The routine glp_prim_rtest returns the index piv in the arrays ind * and val corresponding to the pivot element chosen, 1 <= piv <= len. * If the adjacent basic solution is primal unbounded and therefore the * choice cannot be made, the routine returns zero. * * COMMENTS * * If the non-basic variable x is presented in the LP problem object, * the column (*) can be computed with the routine glp_eval_tab_col; * otherwise it can be computed with the routine glp_transform_col. */ int glp_prim_rtest(glp_prob *P, int len, const int ind[], const double val[], int dir, double eps) { int k, m, n, piv, t, type, stat; double alfa, big, beta, lb, ub, temp, teta; if (glp_get_prim_stat(P) != GLP_FEAS) xerror("glp_prim_rtest: basic solution is not primal feasible " "\n"); if (!(dir == +1 || dir == -1)) xerror("glp_prim_rtest: dir = %d; invalid parameter\n", dir); if (!(0.0 < eps && eps < 1.0)) xerror("glp_prim_rtest: eps = %g; invalid parameter\n", eps); m = glp_get_num_rows(P); n = glp_get_num_cols(P); /* initial settings */ piv = 0, teta = DBL_MAX, big = 0.0; /* walk through the entries of the specified column */ for (t = 1; t <= len; t++) { /* get the ordinal number of basic variable */ k = ind[t]; if (!(1 <= k && k <= m+n)) xerror("glp_prim_rtest: ind[%d] = %d; variable number out o" "f range\n", t, k); /* determine type, bounds, status and primal value of basic variable xB[i] = x[k] in the current basic solution */ if (k <= m) { type = glp_get_row_type(P, k); lb = glp_get_row_lb(P, k); ub = glp_get_row_ub(P, k); stat = glp_get_row_stat(P, k); beta = glp_get_row_prim(P, k); } else { type = glp_get_col_type(P, k-m); lb = glp_get_col_lb(P, k-m); ub = glp_get_col_ub(P, k-m); stat = glp_get_col_stat(P, k-m); beta = glp_get_col_prim(P, k-m); } if (stat != GLP_BS) xerror("glp_prim_rtest: ind[%d] = %d; non-basic variable no" "t allowed\n", t, k); /* determine influence coefficient at basic variable xB[i] in the explicitly specified column and turn to the case of increasing the variable x in order to simplify the program logic */ alfa = (dir > 0 ? + val[t] : - val[t]); /* analyze main cases */ if (type == GLP_FR) { /* xB[i] is free variable */ continue; } else if (type == GLP_LO) lo: { /* xB[i] has an lower bound */ if (alfa > - eps) continue; temp = (lb - beta) / alfa; } else if (type == GLP_UP) up: { /* xB[i] has an upper bound */ if (alfa < + eps) continue; temp = (ub - beta) / alfa; } else if (type == GLP_DB) { /* xB[i] has both lower and upper bounds */ if (alfa < 0.0) goto lo; else goto up; } else if (type == GLP_FX) { /* xB[i] is fixed variable */ if (- eps < alfa && alfa < + eps) continue; temp = 0.0; } else xassert(type != type); /* if the value of the variable xB[i] violates its lower or upper bound (slightly, because the current basis is assumed to be primal feasible), temp is negative; we can think this happens due to round-off errors and the value is exactly on the bound; this allows replacing temp by zero */ if (temp < 0.0) temp = 0.0; /* apply the minimal ratio test */ if (teta > temp || teta == temp && big < fabs(alfa)) piv = t, teta = temp, big = fabs(alfa); } /* return index of the pivot element chosen */ return piv; } /*********************************************************************** * NAME * * glp_dual_rtest - perform dual ratio test * * SYNOPSIS * * int glp_dual_rtest(glp_prob *P, int len, const int ind[], * const double val[], int dir, double eps); * * DESCRIPTION * * The routine glp_dual_rtest performs the dual ratio test using an * explicitly specified row of the simplex table. * * The current basic solution associated with the LP problem object * must be dual feasible. * * The explicitly specified row of the simplex table is a linear form * that shows how some basic variable x (which is not necessarily * presented in the problem object) depends on non-basic variables xN: * * x = alfa[1] * xN[1] + alfa[2] * xN[2] + ... + alfa[n] * xN[n]. (*) * * The row (*) is specified on entry to the routine using the sparse * format. Ordinal numbers of non-basic variables xN[j] should be placed * in locations ind[1], ..., ind[len], where ordinal numbers 1 to m * denote auxiliary variables, and ordinal numbers m+1 to m+n denote * structural variables. The corresponding non-zero coefficients alfa[j] * should be placed in locations val[1], ..., val[len]. The arrays ind * and val are not changed on exit. * * The parameter dir specifies direction in which the variable x changes * on leaving the basis: +1 means that x goes to its lower bound, and -1 * means that x goes to its upper bound. * * The parameter eps is an absolute tolerance (small positive number) * used by the routine to skip small alfa[j] of the row (*). * * The routine determines which non-basic variable (among specified in * ind[1], ..., ind[len]) should enter the basis in order to keep dual * feasibility. * * RETURNS * * The routine glp_dual_rtest returns the index piv in the arrays ind * and val corresponding to the pivot element chosen, 1 <= piv <= len. * If the adjacent basic solution is dual unbounded and therefore the * choice cannot be made, the routine returns zero. * * COMMENTS * * If the basic variable x is presented in the LP problem object, the * row (*) can be computed with the routine glp_eval_tab_row; otherwise * it can be computed with the routine glp_transform_row. */ int glp_dual_rtest(glp_prob *P, int len, const int ind[], const double val[], int dir, double eps) { int k, m, n, piv, t, stat; double alfa, big, cost, obj, temp, teta; if (glp_get_dual_stat(P) != GLP_FEAS) xerror("glp_dual_rtest: basic solution is not dual feasible\n") ; if (!(dir == +1 || dir == -1)) xerror("glp_dual_rtest: dir = %d; invalid parameter\n", dir); if (!(0.0 < eps && eps < 1.0)) xerror("glp_dual_rtest: eps = %g; invalid parameter\n", eps); m = glp_get_num_rows(P); n = glp_get_num_cols(P); /* take into account optimization direction */ obj = (glp_get_obj_dir(P) == GLP_MIN ? +1.0 : -1.0); /* initial settings */ piv = 0, teta = DBL_MAX, big = 0.0; /* walk through the entries of the specified row */ for (t = 1; t <= len; t++) { /* get ordinal number of non-basic variable */ k = ind[t]; if (!(1 <= k && k <= m+n)) xerror("glp_dual_rtest: ind[%d] = %d; variable number out o" "f range\n", t, k); /* determine status and reduced cost of non-basic variable x[k] = xN[j] in the current basic solution */ if (k <= m) { stat = glp_get_row_stat(P, k); cost = glp_get_row_dual(P, k); } else { stat = glp_get_col_stat(P, k-m); cost = glp_get_col_dual(P, k-m); } if (stat == GLP_BS) xerror("glp_dual_rtest: ind[%d] = %d; basic variable not al" "lowed\n", t, k); /* determine influence coefficient at non-basic variable xN[j] in the explicitly specified row and turn to the case of increasing the variable x in order to simplify the program logic */ alfa = (dir > 0 ? + val[t] : - val[t]); /* analyze main cases */ if (stat == GLP_NL) { /* xN[j] is on its lower bound */ if (alfa < + eps) continue; temp = (obj * cost) / alfa; } else if (stat == GLP_NU) { /* xN[j] is on its upper bound */ if (alfa > - eps) continue; temp = (obj * cost) / alfa; } else if (stat == GLP_NF) { /* xN[j] is non-basic free variable */ if (- eps < alfa && alfa < + eps) continue; temp = 0.0; } else if (stat == GLP_NS) { /* xN[j] is non-basic fixed variable */ continue; } else xassert(stat != stat); /* if the reduced cost of the variable xN[j] violates its zero bound (slightly, because the current basis is assumed to be dual feasible), temp is negative; we can think this happens due to round-off errors and the reduced cost is exact zero; this allows replacing temp by zero */ if (temp < 0.0) temp = 0.0; /* apply the minimal ratio test */ if (teta > temp || teta == temp && big < fabs(alfa)) piv = t, teta = temp, big = fabs(alfa); } /* return index of the pivot element chosen */ return piv; } /*********************************************************************** * NAME * * glp_analyze_row - simulate one iteration of dual simplex method * * SYNOPSIS * * int glp_analyze_row(glp_prob *P, int len, const int ind[], * const double val[], int type, double rhs, double eps, int *piv, * double *x, double *dx, double *y, double *dy, double *dz); * * DESCRIPTION * * Let the current basis be optimal or dual feasible, and there be * specified a row (constraint), which is violated by the current basic * solution. The routine glp_analyze_row simulates one iteration of the * dual simplex method to determine some information on the adjacent * basis (see below), where the specified row becomes active constraint * (i.e. its auxiliary variable becomes non-basic). * * The current basic solution associated with the problem object passed * to the routine must be dual feasible, and its primal components must * be defined. * * The row to be analyzed must be previously transformed either with * the routine glp_eval_tab_row (if the row is in the problem object) * or with the routine glp_transform_row (if the row is external, i.e. * not in the problem object). This is needed to express the row only * through (auxiliary and structural) variables, which are non-basic in * the current basis: * * y = alfa[1] * xN[1] + alfa[2] * xN[2] + ... + alfa[n] * xN[n], * * where y is an auxiliary variable of the row, alfa[j] is an influence * coefficient, xN[j] is a non-basic variable. * * The row is passed to the routine in sparse format. Ordinal numbers * of non-basic variables are stored in locations ind[1], ..., ind[len], * where numbers 1 to m denote auxiliary variables while numbers m+1 to * m+n denote structural variables. Corresponding non-zero coefficients * alfa[j] are stored in locations val[1], ..., val[len]. The arrays * ind and val are ot changed on exit. * * The parameters type and rhs specify the row type and its right-hand * side as follows: * * type = GLP_LO: y = sum alfa[j] * xN[j] >= rhs * * type = GLP_UP: y = sum alfa[j] * xN[j] <= rhs * * The parameter eps is an absolute tolerance (small positive number) * used by the routine to skip small coefficients alfa[j] on performing * the dual ratio test. * * If the operation was successful, the routine stores the following * information to corresponding location (if some parameter is NULL, * its value is not stored): * * piv index in the array ind and val, 1 <= piv <= len, determining * the non-basic variable, which would enter the adjacent basis; * * x value of the non-basic variable in the current basis; * * dx difference between values of the non-basic variable in the * adjacent and current bases, dx = x.new - x.old; * * y value of the row (i.e. of its auxiliary variable) in the * current basis; * * dy difference between values of the row in the adjacent and * current bases, dy = y.new - y.old; * * dz difference between values of the objective function in the * adjacent and current bases, dz = z.new - z.old. Note that in * case of minimization dz >= 0, and in case of maximization * dz <= 0, i.e. in the adjacent basis the objective function * always gets worse (degrades). */ int _glp_analyze_row(glp_prob *P, int len, const int ind[], const double val[], int type, double rhs, double eps, int *_piv, double *_x, double *_dx, double *_y, double *_dy, double *_dz) { int t, k, dir, piv, ret = 0; double x, dx, y, dy, dz; if (P->pbs_stat == GLP_UNDEF) xerror("glp_analyze_row: primal basic solution components are " "undefined\n"); if (P->dbs_stat != GLP_FEAS) xerror("glp_analyze_row: basic solution is not dual feasible\n" ); /* compute the row value y = sum alfa[j] * xN[j] in the current basis */ if (!(0 <= len && len <= P->n)) xerror("glp_analyze_row: len = %d; invalid row length\n", len); y = 0.0; for (t = 1; t <= len; t++) { /* determine value of x[k] = xN[j] in the current basis */ k = ind[t]; if (!(1 <= k && k <= P->m+P->n)) xerror("glp_analyze_row: ind[%d] = %d; row/column index out" " of range\n", t, k); if (k <= P->m) { /* x[k] is auxiliary variable */ if (P->row[k]->stat == GLP_BS) xerror("glp_analyze_row: ind[%d] = %d; basic auxiliary v" "ariable is not allowed\n", t, k); x = P->row[k]->prim; } else { /* x[k] is structural variable */ if (P->col[k-P->m]->stat == GLP_BS) xerror("glp_analyze_row: ind[%d] = %d; basic structural " "variable is not allowed\n", t, k); x = P->col[k-P->m]->prim; } y += val[t] * x; } /* check if the row is primal infeasible in the current basis, i.e. the constraint is violated at the current point */ if (type == GLP_LO) { if (y >= rhs) { /* the constraint is not violated */ ret = 1; goto done; } /* in the adjacent basis y goes to its lower bound */ dir = +1; } else if (type == GLP_UP) { if (y <= rhs) { /* the constraint is not violated */ ret = 1; goto done; } /* in the adjacent basis y goes to its upper bound */ dir = -1; } else xerror("glp_analyze_row: type = %d; invalid parameter\n", type); /* compute dy = y.new - y.old */ dy = rhs - y; /* perform dual ratio test to determine which non-basic variable should enter the adjacent basis to keep it dual feasible */ piv = glp_dual_rtest(P, len, ind, val, dir, eps); if (piv == 0) { /* no dual feasible adjacent basis exists */ ret = 2; goto done; } /* non-basic variable x[k] = xN[j] should enter the basis */ k = ind[piv]; xassert(1 <= k && k <= P->m+P->n); /* determine its value in the current basis */ if (k <= P->m) x = P->row[k]->prim; else x = P->col[k-P->m]->prim; /* compute dx = x.new - x.old = dy / alfa[j] */ xassert(val[piv] != 0.0); dx = dy / val[piv]; /* compute dz = z.new - z.old = d[j] * dx, where d[j] is reduced cost of xN[j] in the current basis */ if (k <= P->m) dz = P->row[k]->dual * dx; else dz = P->col[k-P->m]->dual * dx; /* store the analysis results */ if (_piv != NULL) *_piv = piv; if (_x != NULL) *_x = x; if (_dx != NULL) *_dx = dx; if (_y != NULL) *_y = y; if (_dy != NULL) *_dy = dy; if (_dz != NULL) *_dz = dz; done: return ret; } #if 0 int main(void) { /* example program for the routine glp_analyze_row */ glp_prob *P; glp_smcp parm; int i, k, len, piv, ret, ind[1+100]; double rhs, x, dx, y, dy, dz, val[1+100]; P = glp_create_prob(); /* read plan.mps (see glpk/examples) */ ret = glp_read_mps(P, GLP_MPS_DECK, NULL, "plan.mps"); glp_assert(ret == 0); /* and solve it to optimality */ ret = glp_simplex(P, NULL); glp_assert(ret == 0); glp_assert(glp_get_status(P) == GLP_OPT); /* the optimal objective value is 296.217 */ /* we would like to know what happens if we would add a new row (constraint) to plan.mps: .01 * bin1 + .01 * bin2 + .02 * bin4 + .02 * bin5 <= 12 */ /* first, we specify this new row */ glp_create_index(P); len = 0; ind[++len] = glp_find_col(P, "BIN1"), val[len] = .01; ind[++len] = glp_find_col(P, "BIN2"), val[len] = .01; ind[++len] = glp_find_col(P, "BIN4"), val[len] = .02; ind[++len] = glp_find_col(P, "BIN5"), val[len] = .02; rhs = 12; /* then we can compute value of the row (i.e. of its auxiliary variable) in the current basis to see if the constraint is violated */ y = 0.0; for (k = 1; k <= len; k++) y += val[k] * glp_get_col_prim(P, ind[k]); glp_printf("y = %g\n", y); /* this prints y = 15.1372, so the constraint is violated, since we require that y <= rhs = 12 */ /* now we transform the row to express it only through non-basic (auxiliary and artificial) variables */ len = glp_transform_row(P, len, ind, val); /* finally, we simulate one step of the dual simplex method to obtain necessary information for the adjacent basis */ ret = _glp_analyze_row(P, len, ind, val, GLP_UP, rhs, 1e-9, &piv, &x, &dx, &y, &dy, &dz); glp_assert(ret == 0); glp_printf("k = %d, x = %g; dx = %g; y = %g; dy = %g; dz = %g\n", ind[piv], x, dx, y, dy, dz); /* this prints dz = 5.64418 and means that in the adjacent basis the objective function would be 296.217 + 5.64418 = 301.861 */ /* now we actually include the row into the problem object; note that the arrays ind and val are clobbered, so we need to build them once again */ len = 0; ind[++len] = glp_find_col(P, "BIN1"), val[len] = .01; ind[++len] = glp_find_col(P, "BIN2"), val[len] = .01; ind[++len] = glp_find_col(P, "BIN4"), val[len] = .02; ind[++len] = glp_find_col(P, "BIN5"), val[len] = .02; rhs = 12; i = glp_add_rows(P, 1); glp_set_row_bnds(P, i, GLP_UP, 0, rhs); glp_set_mat_row(P, i, len, ind, val); /* and perform one dual simplex iteration */ glp_init_smcp(&parm); parm.meth = GLP_DUAL; parm.it_lim = 1; glp_simplex(P, &parm); /* the current objective value is 301.861 */ return 0; } #endif /*********************************************************************** * NAME * * glp_analyze_bound - analyze active bound of non-basic variable * * SYNOPSIS * * void glp_analyze_bound(glp_prob *P, int k, double *limit1, int *var1, * double *limit2, int *var2); * * DESCRIPTION * * The routine glp_analyze_bound analyzes the effect of varying the * active bound of specified non-basic variable. * * The non-basic variable is specified by the parameter k, where * 1 <= k <= m means auxiliary variable of corresponding row while * m+1 <= k <= m+n means structural variable (column). * * Note that the current basic solution must be optimal, and the basis * factorization must exist. * * Results of the analysis have the following meaning. * * value1 is the minimal value of the active bound, at which the basis * still remains primal feasible and thus optimal. -DBL_MAX means that * the active bound has no lower limit. * * var1 is the ordinal number of an auxiliary (1 to m) or structural * (m+1 to n) basic variable, which reaches its bound first and thereby * limits further decreasing the active bound being analyzed. * if value1 = -DBL_MAX, var1 is set to 0. * * value2 is the maximal value of the active bound, at which the basis * still remains primal feasible and thus optimal. +DBL_MAX means that * the active bound has no upper limit. * * var2 is the ordinal number of an auxiliary (1 to m) or structural * (m+1 to n) basic variable, which reaches its bound first and thereby * limits further increasing the active bound being analyzed. * if value2 = +DBL_MAX, var2 is set to 0. */ void glp_analyze_bound(glp_prob *P, int k, double *value1, int *var1, double *value2, int *var2) { GLPROW *row; GLPCOL *col; int m, n, stat, kase, p, len, piv, *ind; double x, new_x, ll, uu, xx, delta, *val; /* sanity checks */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_analyze_bound: P = %p; invalid problem object\n", P); m = P->m, n = P->n; if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) xerror("glp_analyze_bound: optimal basic solution required\n"); if (!(m == 0 || P->valid)) xerror("glp_analyze_bound: basis factorization required\n"); if (!(1 <= k && k <= m+n)) xerror("glp_analyze_bound: k = %d; variable number out of rang" "e\n", k); /* retrieve information about the specified non-basic variable x[k] whose active bound is to be analyzed */ if (k <= m) { row = P->row[k]; stat = row->stat; x = row->prim; } else { col = P->col[k-m]; stat = col->stat; x = col->prim; } if (stat == GLP_BS) xerror("glp_analyze_bound: k = %d; basic variable not allowed " "\n", k); /* allocate working arrays */ ind = xcalloc(1+m, sizeof(int)); val = xcalloc(1+m, sizeof(double)); /* compute column of the simplex table corresponding to the non-basic variable x[k] */ len = glp_eval_tab_col(P, k, ind, val); xassert(0 <= len && len <= m); /* perform analysis */ for (kase = -1; kase <= +1; kase += 2) { /* kase < 0 means active bound of x[k] is decreasing; kase > 0 means active bound of x[k] is increasing */ /* use the primal ratio test to determine some basic variable x[p] which reaches its bound first */ piv = glp_prim_rtest(P, len, ind, val, kase, 1e-9); if (piv == 0) { /* nothing limits changing the active bound of x[k] */ p = 0; new_x = (kase < 0 ? -DBL_MAX : +DBL_MAX); goto store; } /* basic variable x[p] limits changing the active bound of x[k]; determine its value in the current basis */ xassert(1 <= piv && piv <= len); p = ind[piv]; if (p <= m) { row = P->row[p]; ll = glp_get_row_lb(P, row->i); uu = glp_get_row_ub(P, row->i); stat = row->stat; xx = row->prim; } else { col = P->col[p-m]; ll = glp_get_col_lb(P, col->j); uu = glp_get_col_ub(P, col->j); stat = col->stat; xx = col->prim; } xassert(stat == GLP_BS); /* determine delta x[p] = bound of x[p] - value of x[p] */ if (kase < 0 && val[piv] > 0.0 || kase > 0 && val[piv] < 0.0) { /* delta x[p] < 0, so x[p] goes toward its lower bound */ xassert(ll != -DBL_MAX); delta = ll - xx; } else { /* delta x[p] > 0, so x[p] goes toward its upper bound */ xassert(uu != +DBL_MAX); delta = uu - xx; } /* delta x[p] = alfa[p,k] * delta x[k], so new x[k] = x[k] + delta x[k] = x[k] + delta x[p] / alfa[p,k] is the value of x[k] in the adjacent basis */ xassert(val[piv] != 0.0); new_x = x + delta / val[piv]; store: /* store analysis results */ if (kase < 0) { if (value1 != NULL) *value1 = new_x; if (var1 != NULL) *var1 = p; } else { if (value2 != NULL) *value2 = new_x; if (var2 != NULL) *var2 = p; } } /* free working arrays */ xfree(ind); xfree(val); return; } /*********************************************************************** * NAME * * glp_analyze_coef - analyze objective coefficient at basic variable * * SYNOPSIS * * void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, * double *value1, double *coef2, int *var2, double *value2); * * DESCRIPTION * * The routine glp_analyze_coef analyzes the effect of varying the * objective coefficient at specified basic variable. * * The basic variable is specified by the parameter k, where * 1 <= k <= m means auxiliary variable of corresponding row while * m+1 <= k <= m+n means structural variable (column). * * Note that the current basic solution must be optimal, and the basis * factorization must exist. * * Results of the analysis have the following meaning. * * coef1 is the minimal value of the objective coefficient, at which * the basis still remains dual feasible and thus optimal. -DBL_MAX * means that the objective coefficient has no lower limit. * * var1 is the ordinal number of an auxiliary (1 to m) or structural * (m+1 to n) non-basic variable, whose reduced cost reaches its zero * bound first and thereby limits further decreasing the objective * coefficient being analyzed. If coef1 = -DBL_MAX, var1 is set to 0. * * value1 is value of the basic variable being analyzed in an adjacent * basis, which is defined as follows. Let the objective coefficient * reaches its minimal value (coef1) and continues decreasing. Then the * reduced cost of the limiting non-basic variable (var1) becomes dual * infeasible and the current basis becomes non-optimal that forces the * limiting non-basic variable to enter the basis replacing there some * basic variable that leaves the basis to keep primal feasibility. * Should note that on determining the adjacent basis current bounds * of the basic variable being analyzed are ignored as if it were free * (unbounded) variable, so it cannot leave the basis. It may happen * that no dual feasible adjacent basis exists, in which case value1 is * set to -DBL_MAX or +DBL_MAX. * * coef2 is the maximal value of the objective coefficient, at which * the basis still remains dual feasible and thus optimal. +DBL_MAX * means that the objective coefficient has no upper limit. * * var2 is the ordinal number of an auxiliary (1 to m) or structural * (m+1 to n) non-basic variable, whose reduced cost reaches its zero * bound first and thereby limits further increasing the objective * coefficient being analyzed. If coef2 = +DBL_MAX, var2 is set to 0. * * value2 is value of the basic variable being analyzed in an adjacent * basis, which is defined exactly in the same way as value1 above with * exception that now the objective coefficient is increasing. */ void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, double *value1, double *coef2, int *var2, double *value2) { GLPROW *row; GLPCOL *col; int m, n, type, stat, kase, p, q, dir, clen, cpiv, rlen, rpiv, *cind, *rind; double lb, ub, coef, x, lim_coef, new_x, d, delta, ll, uu, xx, *rval, *cval; /* sanity checks */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_analyze_coef: P = %p; invalid problem object\n", P); m = P->m, n = P->n; if (!(P->pbs_stat == GLP_FEAS && P->dbs_stat == GLP_FEAS)) xerror("glp_analyze_coef: optimal basic solution required\n"); if (!(m == 0 || P->valid)) xerror("glp_analyze_coef: basis factorization required\n"); if (!(1 <= k && k <= m+n)) xerror("glp_analyze_coef: k = %d; variable number out of range" "\n", k); /* retrieve information about the specified basic variable x[k] whose objective coefficient c[k] is to be analyzed */ if (k <= m) { row = P->row[k]; type = row->type; lb = row->lb; ub = row->ub; coef = 0.0; stat = row->stat; x = row->prim; } else { col = P->col[k-m]; type = col->type; lb = col->lb; ub = col->ub; coef = col->coef; stat = col->stat; x = col->prim; } if (stat != GLP_BS) xerror("glp_analyze_coef: k = %d; non-basic variable not allow" "ed\n", k); /* allocate working arrays */ cind = xcalloc(1+m, sizeof(int)); cval = xcalloc(1+m, sizeof(double)); rind = xcalloc(1+n, sizeof(int)); rval = xcalloc(1+n, sizeof(double)); /* compute row of the simplex table corresponding to the basic variable x[k] */ rlen = glp_eval_tab_row(P, k, rind, rval); xassert(0 <= rlen && rlen <= n); /* perform analysis */ for (kase = -1; kase <= +1; kase += 2) { /* kase < 0 means objective coefficient c[k] is decreasing; kase > 0 means objective coefficient c[k] is increasing */ /* note that decreasing c[k] is equivalent to increasing dual variable lambda[k] and vice versa; we need to correctly set the dir flag as required by the routine glp_dual_rtest */ if (P->dir == GLP_MIN) dir = - kase; else if (P->dir == GLP_MAX) dir = + kase; else xassert(P != P); /* use the dual ratio test to determine non-basic variable x[q] whose reduced cost d[q] reaches zero bound first */ rpiv = glp_dual_rtest(P, rlen, rind, rval, dir, 1e-9); if (rpiv == 0) { /* nothing limits changing c[k] */ lim_coef = (kase < 0 ? -DBL_MAX : +DBL_MAX); q = 0; /* x[k] keeps its current value */ new_x = x; goto store; } /* non-basic variable x[q] limits changing coefficient c[k]; determine its status and reduced cost d[k] in the current basis */ xassert(1 <= rpiv && rpiv <= rlen); q = rind[rpiv]; xassert(1 <= q && q <= m+n); if (q <= m) { row = P->row[q]; stat = row->stat; d = row->dual; } else { col = P->col[q-m]; stat = col->stat; d = col->dual; } /* note that delta d[q] = new d[q] - d[q] = - d[q], because new d[q] = 0; delta d[q] = alfa[k,q] * delta c[k], so delta c[k] = delta d[q] / alfa[k,q] = - d[q] / alfa[k,q] */ xassert(rval[rpiv] != 0.0); delta = - d / rval[rpiv]; /* compute new c[k] = c[k] + delta c[k], which is the limiting value of the objective coefficient c[k] */ lim_coef = coef + delta; /* let c[k] continue decreasing/increasing that makes d[q] dual infeasible and forces x[q] to enter the basis; to perform the primal ratio test we need to know in which direction x[q] changes on entering the basis; we determine that analyzing the sign of delta d[q] (see above), since d[q] may be close to zero having wrong sign */ /* let, for simplicity, the problem is minimization */ if (kase < 0 && rval[rpiv] > 0.0 || kase > 0 && rval[rpiv] < 0.0) { /* delta d[q] < 0, so d[q] being non-negative will become negative, so x[q] will increase */ dir = +1; } else { /* delta d[q] > 0, so d[q] being non-positive will become positive, so x[q] will decrease */ dir = -1; } /* if the problem is maximization, correct the direction */ if (P->dir == GLP_MAX) dir = - dir; /* check that we didn't make a silly mistake */ if (dir > 0) xassert(stat == GLP_NL || stat == GLP_NF); else xassert(stat == GLP_NU || stat == GLP_NF); /* compute column of the simplex table corresponding to the non-basic variable x[q] */ clen = glp_eval_tab_col(P, q, cind, cval); /* make x[k] temporarily free (unbounded) */ if (k <= m) { row = P->row[k]; row->type = GLP_FR; row->lb = row->ub = 0.0; } else { col = P->col[k-m]; col->type = GLP_FR; col->lb = col->ub = 0.0; } /* use the primal ratio test to determine some basic variable which leaves the basis */ cpiv = glp_prim_rtest(P, clen, cind, cval, dir, 1e-9); /* restore original bounds of the basic variable x[k] */ if (k <= m) { row = P->row[k]; row->type = type; row->lb = lb, row->ub = ub; } else { col = P->col[k-m]; col->type = type; col->lb = lb, col->ub = ub; } if (cpiv == 0) { /* non-basic variable x[q] can change unlimitedly */ if (dir < 0 && rval[rpiv] > 0.0 || dir > 0 && rval[rpiv] < 0.0) { /* delta x[k] = alfa[k,q] * delta x[q] < 0 */ new_x = -DBL_MAX; } else { /* delta x[k] = alfa[k,q] * delta x[q] > 0 */ new_x = +DBL_MAX; } goto store; } /* some basic variable x[p] limits changing non-basic variable x[q] in the adjacent basis */ xassert(1 <= cpiv && cpiv <= clen); p = cind[cpiv]; xassert(1 <= p && p <= m+n); xassert(p != k); if (p <= m) { row = P->row[p]; xassert(row->stat == GLP_BS); ll = glp_get_row_lb(P, row->i); uu = glp_get_row_ub(P, row->i); xx = row->prim; } else { col = P->col[p-m]; xassert(col->stat == GLP_BS); ll = glp_get_col_lb(P, col->j); uu = glp_get_col_ub(P, col->j); xx = col->prim; } /* determine delta x[p] = new x[p] - x[p] */ if (dir < 0 && cval[cpiv] > 0.0 || dir > 0 && cval[cpiv] < 0.0) { /* delta x[p] < 0, so x[p] goes toward its lower bound */ xassert(ll != -DBL_MAX); delta = ll - xx; } else { /* delta x[p] > 0, so x[p] goes toward its upper bound */ xassert(uu != +DBL_MAX); delta = uu - xx; } /* compute new x[k] = x[k] + alfa[k,q] * delta x[q], where delta x[q] = delta x[p] / alfa[p,q] */ xassert(cval[cpiv] != 0.0); new_x = x + (rval[rpiv] / cval[cpiv]) * delta; store: /* store analysis results */ if (kase < 0) { if (coef1 != NULL) *coef1 = lim_coef; if (var1 != NULL) *var1 = q; if (value1 != NULL) *value1 = new_x; } else { if (coef2 != NULL) *coef2 = lim_coef; if (var2 != NULL) *var2 = q; if (value2 != NULL) *value2 = new_x; } } /* free working arrays */ xfree(cind); xfree(cval); xfree(rind); xfree(rval); return; } /* eof */ glpk-4.52.1/src/glpapi13.c0000644000062000006210000005456312175147600014311 0ustar maomkpasswd/* glpapi13.c (branch-and-bound interface routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * NAME * * glp_ios_reason - determine reason for calling the callback routine * * SYNOPSIS * * glp_ios_reason(glp_tree *tree); * * RETURNS * * The routine glp_ios_reason returns a code, which indicates why the * user-defined callback routine is being called. */ int glp_ios_reason(glp_tree *tree) { return tree->reason; } /*********************************************************************** * NAME * * glp_ios_get_prob - access the problem object * * SYNOPSIS * * glp_prob *glp_ios_get_prob(glp_tree *tree); * * DESCRIPTION * * The routine glp_ios_get_prob can be called from the user-defined * callback routine to access the problem object, which is used by the * MIP solver. It is the original problem object passed to the routine * glp_intopt if the MIP presolver is not used; otherwise it is an * internal problem object built by the presolver. If the current * subproblem exists, LP segment of the problem object corresponds to * its LP relaxation. * * RETURNS * * The routine glp_ios_get_prob returns a pointer to the problem object * used by the MIP solver. */ glp_prob *glp_ios_get_prob(glp_tree *tree) { return tree->mip; } /*********************************************************************** * NAME * * glp_ios_tree_size - determine size of the branch-and-bound tree * * SYNOPSIS * * void glp_ios_tree_size(glp_tree *tree, int *a_cnt, int *n_cnt, * int *t_cnt); * * DESCRIPTION * * The routine glp_ios_tree_size stores the following three counts which * characterize the current size of the branch-and-bound tree: * * a_cnt is the current number of active nodes, i.e. the current size of * the active list; * * n_cnt is the current number of all (active and inactive) nodes; * * t_cnt is the total number of nodes including those which have been * already removed from the tree. This count is increased whenever * a new node appears in the tree and never decreased. * * If some of the parameters a_cnt, n_cnt, t_cnt is a null pointer, the * corresponding count is not stored. */ void glp_ios_tree_size(glp_tree *tree, int *a_cnt, int *n_cnt, int *t_cnt) { if (a_cnt != NULL) *a_cnt = tree->a_cnt; if (n_cnt != NULL) *n_cnt = tree->n_cnt; if (t_cnt != NULL) *t_cnt = tree->t_cnt; return; } /*********************************************************************** * NAME * * glp_ios_curr_node - determine current active subproblem * * SYNOPSIS * * int glp_ios_curr_node(glp_tree *tree); * * RETURNS * * The routine glp_ios_curr_node returns the reference number of the * current active subproblem. However, if the current subproblem does * not exist, the routine returns zero. */ int glp_ios_curr_node(glp_tree *tree) { IOSNPD *node; /* obtain pointer to the current subproblem */ node = tree->curr; /* return its reference number */ return node == NULL ? 0 : node->p; } /*********************************************************************** * NAME * * glp_ios_next_node - determine next active subproblem * * SYNOPSIS * * int glp_ios_next_node(glp_tree *tree, int p); * * RETURNS * * If the parameter p is zero, the routine glp_ios_next_node returns * the reference number of the first active subproblem. However, if the * tree is empty, zero is returned. * * If the parameter p is not zero, it must specify the reference number * of some active subproblem, in which case the routine returns the * reference number of the next active subproblem. However, if there is * no next active subproblem in the list, zero is returned. * * All subproblems in the active list are ordered chronologically, i.e. * subproblem A precedes subproblem B if A was created before B. */ int glp_ios_next_node(glp_tree *tree, int p) { IOSNPD *node; if (p == 0) { /* obtain pointer to the first active subproblem */ node = tree->head; } else { /* obtain pointer to the specified subproblem */ if (!(1 <= p && p <= tree->nslots)) err: xerror("glp_ios_next_node: p = %d; invalid subproblem refer" "ence number\n", p); node = tree->slot[p].node; if (node == NULL) goto err; /* the specified subproblem must be active */ if (node->count != 0) xerror("glp_ios_next_node: p = %d; subproblem not in the ac" "tive list\n", p); /* obtain pointer to the next active subproblem */ node = node->next; } /* return the reference number */ return node == NULL ? 0 : node->p; } /*********************************************************************** * NAME * * glp_ios_prev_node - determine previous active subproblem * * SYNOPSIS * * int glp_ios_prev_node(glp_tree *tree, int p); * * RETURNS * * If the parameter p is zero, the routine glp_ios_prev_node returns * the reference number of the last active subproblem. However, if the * tree is empty, zero is returned. * * If the parameter p is not zero, it must specify the reference number * of some active subproblem, in which case the routine returns the * reference number of the previous active subproblem. However, if there * is no previous active subproblem in the list, zero is returned. * * All subproblems in the active list are ordered chronologically, i.e. * subproblem A precedes subproblem B if A was created before B. */ int glp_ios_prev_node(glp_tree *tree, int p) { IOSNPD *node; if (p == 0) { /* obtain pointer to the last active subproblem */ node = tree->tail; } else { /* obtain pointer to the specified subproblem */ if (!(1 <= p && p <= tree->nslots)) err: xerror("glp_ios_prev_node: p = %d; invalid subproblem refer" "ence number\n", p); node = tree->slot[p].node; if (node == NULL) goto err; /* the specified subproblem must be active */ if (node->count != 0) xerror("glp_ios_prev_node: p = %d; subproblem not in the ac" "tive list\n", p); /* obtain pointer to the previous active subproblem */ node = node->prev; } /* return the reference number */ return node == NULL ? 0 : node->p; } /*********************************************************************** * NAME * * glp_ios_up_node - determine parent subproblem * * SYNOPSIS * * int glp_ios_up_node(glp_tree *tree, int p); * * RETURNS * * The parameter p must specify the reference number of some (active or * inactive) subproblem, in which case the routine iet_get_up_node * returns the reference number of its parent subproblem. However, if * the specified subproblem is the root of the tree and, therefore, has * no parent, the routine returns zero. */ int glp_ios_up_node(glp_tree *tree, int p) { IOSNPD *node; /* obtain pointer to the specified subproblem */ if (!(1 <= p && p <= tree->nslots)) err: xerror("glp_ios_up_node: p = %d; invalid subproblem reference " "number\n", p); node = tree->slot[p].node; if (node == NULL) goto err; /* obtain pointer to the parent subproblem */ node = node->up; /* return the reference number */ return node == NULL ? 0 : node->p; } /*********************************************************************** * NAME * * glp_ios_node_level - determine subproblem level * * SYNOPSIS * * int glp_ios_node_level(glp_tree *tree, int p); * * RETURNS * * The routine glp_ios_node_level returns the level of the subproblem, * whose reference number is p, in the branch-and-bound tree. (The root * subproblem has level 0, and the level of any other subproblem is the * level of its parent plus one.) */ int glp_ios_node_level(glp_tree *tree, int p) { IOSNPD *node; /* obtain pointer to the specified subproblem */ if (!(1 <= p && p <= tree->nslots)) err: xerror("glp_ios_node_level: p = %d; invalid subproblem referen" "ce number\n", p); node = tree->slot[p].node; if (node == NULL) goto err; /* return the node level */ return node->level; } /*********************************************************************** * NAME * * glp_ios_node_bound - determine subproblem local bound * * SYNOPSIS * * double glp_ios_node_bound(glp_tree *tree, int p); * * RETURNS * * The routine glp_ios_node_bound returns the local bound for (active or * inactive) subproblem, whose reference number is p. * * COMMENTS * * The local bound for subproblem p is an lower (minimization) or upper * (maximization) bound for integer optimal solution to this subproblem * (not to the original problem). This bound is local in the sense that * only subproblems in the subtree rooted at node p cannot have better * integer feasible solutions. * * On creating a subproblem (due to the branching step) its local bound * is inherited from its parent and then may get only stronger (never * weaker). For the root subproblem its local bound is initially set to * -DBL_MAX (minimization) or +DBL_MAX (maximization) and then improved * as the root LP relaxation has been solved. * * Note that the local bound is not necessarily the optimal objective * value to corresponding LP relaxation; it may be stronger. */ double glp_ios_node_bound(glp_tree *tree, int p) { IOSNPD *node; /* obtain pointer to the specified subproblem */ if (!(1 <= p && p <= tree->nslots)) err: xerror("glp_ios_node_bound: p = %d; invalid subproblem referen" "ce number\n", p); node = tree->slot[p].node; if (node == NULL) goto err; /* return the node local bound */ return node->bound; } /*********************************************************************** * NAME * * glp_ios_best_node - find active subproblem with best local bound * * SYNOPSIS * * int glp_ios_best_node(glp_tree *tree); * * RETURNS * * The routine glp_ios_best_node returns the reference number of the * active subproblem, whose local bound is best (i.e. smallest in case * of minimization or largest in case of maximization). However, if the * tree is empty, the routine returns zero. * * COMMENTS * * The best local bound is an lower (minimization) or upper * (maximization) bound for integer optimal solution to the original * MIP problem. */ int glp_ios_best_node(glp_tree *tree) { return ios_best_node(tree); } /*********************************************************************** * NAME * * glp_ios_mip_gap - compute relative MIP gap * * SYNOPSIS * * double glp_ios_mip_gap(glp_tree *tree); * * DESCRIPTION * * The routine glp_ios_mip_gap computes the relative MIP gap with the * following formula: * * gap = |best_mip - best_bnd| / (|best_mip| + DBL_EPSILON), * * where best_mip is the best integer feasible solution found so far, * best_bnd is the best (global) bound. If no integer feasible solution * has been found yet, gap is set to DBL_MAX. * * RETURNS * * The routine glp_ios_mip_gap returns the relative MIP gap. */ double glp_ios_mip_gap(glp_tree *tree) { return ios_relative_gap(tree); } /*********************************************************************** * NAME * * glp_ios_node_data - access subproblem application-specific data * * SYNOPSIS * * void *glp_ios_node_data(glp_tree *tree, int p); * * DESCRIPTION * * The routine glp_ios_node_data allows the application accessing a * memory block allocated for the subproblem (which may be active or * inactive), whose reference number is p. * * The size of the block is defined by the control parameter cb_size * passed to the routine glp_intopt. The block is initialized by binary * zeros on creating corresponding subproblem, and its contents is kept * until the subproblem will be removed from the tree. * * The application may use these memory blocks to store specific data * for each subproblem. * * RETURNS * * The routine glp_ios_node_data returns a pointer to the memory block * for the specified subproblem. Note that if cb_size = 0, the routine * returns a null pointer. */ void *glp_ios_node_data(glp_tree *tree, int p) { IOSNPD *node; /* obtain pointer to the specified subproblem */ if (!(1 <= p && p <= tree->nslots)) err: xerror("glp_ios_node_level: p = %d; invalid subproblem referen" "ce number\n", p); node = tree->slot[p].node; if (node == NULL) goto err; /* return pointer to the application-specific data */ return node->data; } /*********************************************************************** * NAME * * glp_ios_row_attr - retrieve additional row attributes * * SYNOPSIS * * void glp_ios_row_attr(glp_tree *tree, int i, glp_attr *attr); * * DESCRIPTION * * The routine glp_ios_row_attr retrieves additional attributes of row * i and stores them in the structure glp_attr. */ void glp_ios_row_attr(glp_tree *tree, int i, glp_attr *attr) { GLPROW *row; if (!(1 <= i && i <= tree->mip->m)) xerror("glp_ios_row_attr: i = %d; row number out of range\n", i); row = tree->mip->row[i]; attr->level = row->level; attr->origin = row->origin; attr->klass = row->klass; return; } /**********************************************************************/ int glp_ios_pool_size(glp_tree *tree) { /* determine current size of the cut pool */ if (tree->reason != GLP_ICUTGEN) xerror("glp_ios_pool_size: operation not allowed\n"); xassert(tree->local != NULL); return tree->local->size; } /**********************************************************************/ int glp_ios_add_row(glp_tree *tree, const char *name, int klass, int flags, int len, const int ind[], const double val[], int type, double rhs) { /* add row (constraint) to the cut pool */ int num; if (tree->reason != GLP_ICUTGEN) xerror("glp_ios_add_row: operation not allowed\n"); xassert(tree->local != NULL); num = ios_add_row(tree, tree->local, name, klass, flags, len, ind, val, type, rhs); return num; } /**********************************************************************/ void glp_ios_del_row(glp_tree *tree, int i) { /* remove row (constraint) from the cut pool */ if (tree->reason != GLP_ICUTGEN) xerror("glp_ios_del_row: operation not allowed\n"); ios_del_row(tree, tree->local, i); return; } /**********************************************************************/ void glp_ios_clear_pool(glp_tree *tree) { /* remove all rows (constraints) from the cut pool */ if (tree->reason != GLP_ICUTGEN) xerror("glp_ios_clear_pool: operation not allowed\n"); ios_clear_pool(tree, tree->local); return; } /*********************************************************************** * NAME * * glp_ios_can_branch - check if can branch upon specified variable * * SYNOPSIS * * int glp_ios_can_branch(glp_tree *tree, int j); * * RETURNS * * If j-th variable (column) can be used to branch upon, the routine * glp_ios_can_branch returns non-zero, otherwise zero. */ int glp_ios_can_branch(glp_tree *tree, int j) { if (!(1 <= j && j <= tree->mip->n)) xerror("glp_ios_can_branch: j = %d; column number out of range" "\n", j); return tree->non_int[j]; } /*********************************************************************** * NAME * * glp_ios_branch_upon - choose variable to branch upon * * SYNOPSIS * * void glp_ios_branch_upon(glp_tree *tree, int j, int sel); * * DESCRIPTION * * The routine glp_ios_branch_upon can be called from the user-defined * callback routine in response to the reason GLP_IBRANCH to choose a * branching variable, whose ordinal number is j. Should note that only * variables, for which the routine glp_ios_can_branch returns non-zero, * can be used to branch upon. * * The parameter sel is a flag that indicates which branch (subproblem) * should be selected next to continue the search: * * GLP_DN_BRNCH - select down-branch; * GLP_UP_BRNCH - select up-branch; * GLP_NO_BRNCH - use general selection technique. */ void glp_ios_branch_upon(glp_tree *tree, int j, int sel) { if (!(1 <= j && j <= tree->mip->n)) xerror("glp_ios_branch_upon: j = %d; column number out of rang" "e\n", j); if (!(sel == GLP_DN_BRNCH || sel == GLP_UP_BRNCH || sel == GLP_NO_BRNCH)) xerror("glp_ios_branch_upon: sel = %d: invalid branch selectio" "n flag\n", sel); if (!(tree->non_int[j])) xerror("glp_ios_branch_upon: j = %d; variable cannot be used t" "o branch upon\n", j); if (tree->br_var != 0) xerror("glp_ios_branch_upon: branching variable already chosen" "\n"); tree->br_var = j; tree->br_sel = sel; return; } /*********************************************************************** * NAME * * glp_ios_select_node - select subproblem to continue the search * * SYNOPSIS * * void glp_ios_select_node(glp_tree *tree, int p); * * DESCRIPTION * * The routine glp_ios_select_node can be called from the user-defined * callback routine in response to the reason GLP_ISELECT to select an * active subproblem, whose reference number is p. The search will be * continued from the subproblem selected. */ void glp_ios_select_node(glp_tree *tree, int p) { IOSNPD *node; /* obtain pointer to the specified subproblem */ if (!(1 <= p && p <= tree->nslots)) err: xerror("glp_ios_select_node: p = %d; invalid subproblem refere" "nce number\n", p); node = tree->slot[p].node; if (node == NULL) goto err; /* the specified subproblem must be active */ if (node->count != 0) xerror("glp_ios_select_node: p = %d; subproblem not in the act" "ive list\n", p); /* no subproblem must be selected yet */ if (tree->next_p != 0) xerror("glp_ios_select_node: subproblem already selected\n"); /* select the specified subproblem to continue the search */ tree->next_p = p; return; } /*********************************************************************** * NAME * * glp_ios_heur_sol - provide solution found by heuristic * * SYNOPSIS * * int glp_ios_heur_sol(glp_tree *tree, const double x[]); * * DESCRIPTION * * The routine glp_ios_heur_sol can be called from the user-defined * callback routine in response to the reason GLP_IHEUR to provide an * integer feasible solution found by a primal heuristic. * * Primal values of *all* variables (columns) found by the heuristic * should be placed in locations x[1], ..., x[n], where n is the number * of columns in the original problem object. Note that the routine * glp_ios_heur_sol *does not* check primal feasibility of the solution * provided. * * Using the solution passed in the array x the routine computes value * of the objective function. If the objective value is better than the * best known integer feasible solution, the routine computes values of * auxiliary variables (rows) and stores all solution components in the * problem object. * * RETURNS * * If the provided solution is accepted, the routine glp_ios_heur_sol * returns zero. Otherwise, if the provided solution is rejected, the * routine returns non-zero. */ int glp_ios_heur_sol(glp_tree *tree, const double x[]) { glp_prob *mip = tree->mip; int m = tree->orig_m; int n = tree->n; int i, j; double obj; xassert(mip->m >= m); xassert(mip->n == n); /* check values of integer variables and compute value of the objective function */ obj = mip->c0; for (j = 1; j <= n; j++) { GLPCOL *col = mip->col[j]; if (col->kind == GLP_IV) { /* provided value must be integral */ if (x[j] != floor(x[j])) return 1; } obj += col->coef * x[j]; } /* check if the provided solution is better than the best known integer feasible solution */ if (mip->mip_stat == GLP_FEAS) { switch (mip->dir) { case GLP_MIN: if (obj >= tree->mip->mip_obj) return 1; break; case GLP_MAX: if (obj <= tree->mip->mip_obj) return 1; break; default: xassert(mip != mip); } } /* it is better; store it in the problem object */ if (tree->parm->msg_lev >= GLP_MSG_ON) xprintf("Solution found by heuristic: %.12g\n", obj); mip->mip_stat = GLP_FEAS; mip->mip_obj = obj; for (j = 1; j <= n; j++) mip->col[j]->mipx = x[j]; for (i = 1; i <= m; i++) { GLPROW *row = mip->row[i]; GLPAIJ *aij; row->mipx = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) row->mipx += aij->val * aij->col->mipx; } #if 1 /* 11/VII-2013 */ ios_process_sol(tree); #endif return 0; } /*********************************************************************** * NAME * * glp_ios_terminate - terminate the solution process. * * SYNOPSIS * * void glp_ios_terminate(glp_tree *tree); * * DESCRIPTION * * The routine glp_ios_terminate sets a flag indicating that the MIP * solver should prematurely terminate the search. */ void glp_ios_terminate(glp_tree *tree) { if (tree->parm->msg_lev >= GLP_MSG_DBG) xprintf("The search is prematurely terminated due to applicati" "on request\n"); tree->stop = 1; return; } /* eof */ glpk-4.52.1/src/glpapi14.c0000644000062000006210000002203312175147600014275 0ustar maomkpasswd/* glpapi14.c (processing models in GNU MathProg language) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "glpmpl.h" glp_tran *glp_mpl_alloc_wksp(void) { /* allocate the MathProg translator workspace */ glp_tran *tran; tran = mpl_initialize(); return tran; } #if 1 /* 08/XII-2009 */ void _glp_mpl_init_rand(glp_tran *tran, int seed) { if (tran->phase != 0) xerror("glp_mpl_init_rand: invalid call sequence\n"); rng_init_rand(tran->rand, seed); return; } #endif int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip) { /* read and translate model section */ int ret; if (tran->phase != 0) xerror("glp_mpl_read_model: invalid call sequence\n"); ret = mpl_read_model(tran, (char *)fname, skip); if (ret == 1 || ret == 2) ret = 0; else if (ret == 4) ret = 1; else xassert(ret != ret); return ret; } int glp_mpl_read_data(glp_tran *tran, const char *fname) { /* read and translate data section */ int ret; if (!(tran->phase == 1 || tran->phase == 2)) xerror("glp_mpl_read_data: invalid call sequence\n"); ret = mpl_read_data(tran, (char *)fname); if (ret == 2) ret = 0; else if (ret == 4) ret = 1; else xassert(ret != ret); return ret; } int glp_mpl_generate(glp_tran *tran, const char *fname) { /* generate the model */ int ret; if (!(tran->phase == 1 || tran->phase == 2)) xerror("glp_mpl_generate: invalid call sequence\n"); ret = mpl_generate(tran, (char *)fname); if (ret == 3) ret = 0; else if (ret == 4) ret = 1; return ret; } void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob) { /* build LP/MIP problem instance from the model */ int m, n, i, j, t, kind, type, len, *ind; double lb, ub, *val; if (tran->phase != 3) xerror("glp_mpl_build_prob: invalid call sequence\n"); /* erase the problem object */ glp_erase_prob(prob); /* set problem name */ glp_set_prob_name(prob, mpl_get_prob_name(tran)); /* build rows (constraints) */ m = mpl_get_num_rows(tran); if (m > 0) glp_add_rows(prob, m); for (i = 1; i <= m; i++) { /* set row name */ glp_set_row_name(prob, i, mpl_get_row_name(tran, i)); /* set row bounds */ type = mpl_get_row_bnds(tran, i, &lb, &ub); switch (type) { case MPL_FR: type = GLP_FR; break; case MPL_LO: type = GLP_LO; break; case MPL_UP: type = GLP_UP; break; case MPL_DB: type = GLP_DB; break; case MPL_FX: type = GLP_FX; break; default: xassert(type != type); } if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) { type = GLP_FX; if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; } glp_set_row_bnds(prob, i, type, lb, ub); /* warn about non-zero constant term */ if (mpl_get_row_c0(tran, i) != 0.0) xprintf("glp_mpl_build_prob: row %s; constant term %.12g ig" "nored\n", mpl_get_row_name(tran, i), mpl_get_row_c0(tran, i)); } /* build columns (variables) */ n = mpl_get_num_cols(tran); if (n > 0) glp_add_cols(prob, n); for (j = 1; j <= n; j++) { /* set column name */ glp_set_col_name(prob, j, mpl_get_col_name(tran, j)); /* set column kind */ kind = mpl_get_col_kind(tran, j); switch (kind) { case MPL_NUM: break; case MPL_INT: case MPL_BIN: glp_set_col_kind(prob, j, GLP_IV); break; default: xassert(kind != kind); } /* set column bounds */ type = mpl_get_col_bnds(tran, j, &lb, &ub); switch (type) { case MPL_FR: type = GLP_FR; break; case MPL_LO: type = GLP_LO; break; case MPL_UP: type = GLP_UP; break; case MPL_DB: type = GLP_DB; break; case MPL_FX: type = GLP_FX; break; default: xassert(type != type); } if (kind == MPL_BIN) { if (type == GLP_FR || type == GLP_UP || lb < 0.0) lb = 0.0; if (type == GLP_FR || type == GLP_LO || ub > 1.0) ub = 1.0; type = GLP_DB; } if (type == GLP_DB && fabs(lb - ub) < 1e-9 * (1.0 + fabs(lb))) { type = GLP_FX; if (fabs(lb) <= fabs(ub)) ub = lb; else lb = ub; } glp_set_col_bnds(prob, j, type, lb, ub); } /* load the constraint matrix */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (i = 1; i <= m; i++) { len = mpl_get_mat_row(tran, i, ind, val); glp_set_mat_row(prob, i, len, ind, val); } /* build objective function (the first objective is used) */ for (i = 1; i <= m; i++) { kind = mpl_get_row_kind(tran, i); if (kind == MPL_MIN || kind == MPL_MAX) { /* set objective name */ glp_set_obj_name(prob, mpl_get_row_name(tran, i)); /* set optimization direction */ glp_set_obj_dir(prob, kind == MPL_MIN ? GLP_MIN : GLP_MAX); /* set constant term */ glp_set_obj_coef(prob, 0, mpl_get_row_c0(tran, i)); /* set objective coefficients */ len = mpl_get_mat_row(tran, i, ind, val); for (t = 1; t <= len; t++) glp_set_obj_coef(prob, ind[t], val[t]); break; } } /* free working arrays */ xfree(ind); xfree(val); return; } int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol) { /* postsolve the model */ int i, j, m, n, stat, ret; double prim, dual; if (!(tran->phase == 3 && !tran->flag_p)) xerror("glp_mpl_postsolve: invalid call sequence\n"); if (!(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP)) xerror("glp_mpl_postsolve: sol = %d; invalid parameter\n", sol); m = mpl_get_num_rows(tran); n = mpl_get_num_cols(tran); if (!(m == glp_get_num_rows(prob) && n == glp_get_num_cols(prob))) xerror("glp_mpl_postsolve: wrong problem object\n"); if (!mpl_has_solve_stmt(tran)) { ret = 0; goto done; } for (i = 1; i <= m; i++) { if (sol == GLP_SOL) { stat = glp_get_row_stat(prob, i); prim = glp_get_row_prim(prob, i); dual = glp_get_row_dual(prob, i); } else if (sol == GLP_IPT) { stat = 0; prim = glp_ipt_row_prim(prob, i); dual = glp_ipt_row_dual(prob, i); } else if (sol == GLP_MIP) { stat = 0; prim = glp_mip_row_val(prob, i); dual = 0.0; } else xassert(sol != sol); if (fabs(prim) < 1e-9) prim = 0.0; if (fabs(dual) < 1e-9) dual = 0.0; mpl_put_row_soln(tran, i, stat, prim, dual); } for (j = 1; j <= n; j++) { if (sol == GLP_SOL) { stat = glp_get_col_stat(prob, j); prim = glp_get_col_prim(prob, j); dual = glp_get_col_dual(prob, j); } else if (sol == GLP_IPT) { stat = 0; prim = glp_ipt_col_prim(prob, j); dual = glp_ipt_col_dual(prob, j); } else if (sol == GLP_MIP) { stat = 0; prim = glp_mip_col_val(prob, j); dual = 0.0; } else xassert(sol != sol); if (fabs(prim) < 1e-9) prim = 0.0; if (fabs(dual) < 1e-9) dual = 0.0; mpl_put_col_soln(tran, j, stat, prim, dual); } ret = mpl_postsolve(tran); if (ret == 3) ret = 0; else if (ret == 4) ret = 1; done: return ret; } void glp_mpl_free_wksp(glp_tran *tran) { /* free the MathProg translator workspace */ mpl_terminate(tran); return; } /* eof */ glpk-4.52.1/src/glpapi15.c0000644000062000006210000004461712175147600014312 0ustar maomkpasswd/* glpapi15.c (basic graph and network routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #if 1 /* 11/VI-2013 */ #include "env2.h" #endif #include "glpapi.h" #include "glpsdf.h" /* CAUTION: DO NOT CHANGE THE LIMITS BELOW */ #define NV_MAX 100000000 /* = 100*10^6 */ /* maximal number of vertices in the graph */ #define NA_MAX 500000000 /* = 500*10^6 */ /* maximal number of arcs in the graph */ /*********************************************************************** * NAME * * glp_create_graph - create graph * * SYNOPSIS * * glp_graph *glp_create_graph(int v_size, int a_size); * * DESCRIPTION * * The routine creates a new graph, which initially is empty, i.e. has * no vertices and arcs. * * The parameter v_size specifies the size of data associated with each * vertex of the graph (0 to 256 bytes). * * The parameter a_size specifies the size of data associated with each * arc of the graph (0 to 256 bytes). * * RETURNS * * The routine returns a pointer to the graph created. */ static void create_graph(glp_graph *G, int v_size, int a_size) { G->pool = dmp_create_pool(); G->name = NULL; G->nv_max = 50; G->nv = G->na = 0; G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *)); G->index = NULL; G->v_size = v_size; G->a_size = a_size; return; } glp_graph *glp_create_graph(int v_size, int a_size) { glp_graph *G; if (!(0 <= v_size && v_size <= 256)) xerror("glp_create_graph: v_size = %d; invalid size of vertex " "data\n", v_size); if (!(0 <= a_size && a_size <= 256)) xerror("glp_create_graph: a_size = %d; invalid size of arc dat" "a\n", a_size); G = xmalloc(sizeof(glp_graph)); create_graph(G, v_size, a_size); return G; } /*********************************************************************** * NAME * * glp_set_graph_name - assign (change) graph name * * SYNOPSIS * * void glp_set_graph_name(glp_graph *G, const char *name); * * DESCRIPTION * * The routine glp_set_graph_name assigns a symbolic name specified by * the character string name (1 to 255 chars) to the graph. * * If the parameter name is NULL or an empty string, the routine erases * the existing symbolic name of the graph. */ void glp_set_graph_name(glp_graph *G, const char *name) { if (G->name != NULL) { dmp_free_atom(G->pool, G->name, strlen(G->name)+1); G->name = NULL; } if (!(name == NULL || name[0] == '\0')) { int j; for (j = 0; name[j] != '\0'; j++) { if (j == 256) xerror("glp_set_graph_name: graph name too long\n"); if (iscntrl((unsigned char)name[j])) xerror("glp_set_graph_name: graph name contains invalid " "character(s)\n"); } G->name = dmp_get_atom(G->pool, strlen(name)+1); strcpy(G->name, name); } return; } /*********************************************************************** * NAME * * glp_add_vertices - add new vertices to graph * * SYNOPSIS * * int glp_add_vertices(glp_graph *G, int nadd); * * DESCRIPTION * * The routine glp_add_vertices adds nadd vertices to the specified * graph. New vertices are always added to the end of the vertex list, * so ordinal numbers of existing vertices remain unchanged. * * Being added each new vertex is isolated (has no incident arcs). * * RETURNS * * The routine glp_add_vertices returns an ordinal number of the first * new vertex added to the graph. */ int glp_add_vertices(glp_graph *G, int nadd) { int i, nv_new; if (nadd < 1) xerror("glp_add_vertices: nadd = %d; invalid number of vertice" "s\n", nadd); if (nadd > NV_MAX - G->nv) xerror("glp_add_vertices: nadd = %d; too many vertices\n", nadd); /* determine new number of vertices */ nv_new = G->nv + nadd; /* increase the room, if necessary */ if (G->nv_max < nv_new) { glp_vertex **save = G->v; while (G->nv_max < nv_new) { G->nv_max += G->nv_max; xassert(G->nv_max > 0); } G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *)); memcpy(&G->v[1], &save[1], G->nv * sizeof(glp_vertex *)); xfree(save); } /* add new vertices to the end of the vertex list */ for (i = G->nv+1; i <= nv_new; i++) { glp_vertex *v; G->v[i] = v = dmp_get_atom(G->pool, sizeof(glp_vertex)); v->i = i; v->name = NULL; v->entry = NULL; if (G->v_size == 0) v->data = NULL; else { v->data = dmp_get_atom(G->pool, G->v_size); memset(v->data, 0, G->v_size); } v->temp = NULL; v->in = v->out = NULL; } /* set new number of vertices */ G->nv = nv_new; /* return the ordinal number of the first vertex added */ return nv_new - nadd + 1; } /**********************************************************************/ void glp_set_vertex_name(glp_graph *G, int i, const char *name) { /* assign (change) vertex name */ glp_vertex *v; if (!(1 <= i && i <= G->nv)) xerror("glp_set_vertex_name: i = %d; vertex number out of rang" "e\n", i); v = G->v[i]; if (v->name != NULL) { if (v->entry != NULL) { xassert(G->index != NULL); avl_delete_node(G->index, v->entry); v->entry = NULL; } dmp_free_atom(G->pool, v->name, strlen(v->name)+1); v->name = NULL; } if (!(name == NULL || name[0] == '\0')) { int k; for (k = 0; name[k] != '\0'; k++) { if (k == 256) xerror("glp_set_vertex_name: i = %d; vertex name too lon" "g\n", i); if (iscntrl((unsigned char)name[k])) xerror("glp_set_vertex_name: i = %d; vertex name contain" "s invalid character(s)\n", i); } v->name = dmp_get_atom(G->pool, strlen(name)+1); strcpy(v->name, name); if (G->index != NULL) { xassert(v->entry == NULL); v->entry = avl_insert_node(G->index, v->name); avl_set_node_link(v->entry, v); } } return; } /*********************************************************************** * NAME * * glp_add_arc - add new arc to graph * * SYNOPSIS * * glp_arc *glp_add_arc(glp_graph *G, int i, int j); * * DESCRIPTION * * The routine glp_add_arc adds a new arc to the specified graph. * * The parameters i and j specify the ordinal numbers of, resp., tail * and head vertices of the arc. Note that self-loops and multiple arcs * are allowed. * * RETURNS * * The routine glp_add_arc returns a pointer to the arc added. */ glp_arc *glp_add_arc(glp_graph *G, int i, int j) { glp_arc *a; if (!(1 <= i && i <= G->nv)) xerror("glp_add_arc: i = %d; tail vertex number out of range\n" , i); if (!(1 <= j && j <= G->nv)) xerror("glp_add_arc: j = %d; head vertex number out of range\n" , j); if (G->na == NA_MAX) xerror("glp_add_arc: too many arcs\n"); a = dmp_get_atom(G->pool, sizeof(glp_arc)); a->tail = G->v[i]; a->head = G->v[j]; if (G->a_size == 0) a->data = NULL; else { a->data = dmp_get_atom(G->pool, G->a_size); memset(a->data, 0, G->a_size); } a->temp = NULL; a->t_prev = NULL; a->t_next = G->v[i]->out; if (a->t_next != NULL) a->t_next->t_prev = a; a->h_prev = NULL; a->h_next = G->v[j]->in; if (a->h_next != NULL) a->h_next->h_prev = a; G->v[i]->out = G->v[j]->in = a; G->na++; return a; } /*********************************************************************** * NAME * * glp_del_vertices - delete vertices from graph * * SYNOPSIS * * void glp_del_vertices(glp_graph *G, int ndel, const int num[]); * * DESCRIPTION * * The routine glp_del_vertices deletes vertices along with all * incident arcs from the specified graph. Ordinal numbers of vertices * to be deleted should be placed in locations num[1], ..., num[ndel], * ndel > 0. * * Note that deleting vertices involves changing ordinal numbers of * other vertices remaining in the graph. New ordinal numbers of the * remaining vertices are assigned under the assumption that the * original order of vertices is not changed. */ void glp_del_vertices(glp_graph *G, int ndel, const int num[]) { glp_vertex *v; int i, k, nv_new; /* scan the list of vertices to be deleted */ if (!(1 <= ndel && ndel <= G->nv)) xerror("glp_del_vertices: ndel = %d; invalid number of vertice" "s\n", ndel); for (k = 1; k <= ndel; k++) { /* take the number of vertex to be deleted */ i = num[k]; /* obtain pointer to i-th vertex */ if (!(1 <= i && i <= G->nv)) xerror("glp_del_vertices: num[%d] = %d; vertex number out o" "f range\n", k, i); v = G->v[i]; /* check that the vertex is not marked yet */ if (v->i == 0) xerror("glp_del_vertices: num[%d] = %d; duplicate vertex nu" "mbers not allowed\n", k, i); /* erase symbolic name assigned to the vertex */ glp_set_vertex_name(G, i, NULL); xassert(v->name == NULL); xassert(v->entry == NULL); /* free vertex data, if allocated */ if (v->data != NULL) dmp_free_atom(G->pool, v->data, G->v_size); /* delete all incoming arcs */ while (v->in != NULL) glp_del_arc(G, v->in); /* delete all outgoing arcs */ while (v->out != NULL) glp_del_arc(G, v->out); /* mark the vertex to be deleted */ v->i = 0; } /* delete all marked vertices from the vertex list */ nv_new = 0; for (i = 1; i <= G->nv; i++) { /* obtain pointer to i-th vertex */ v = G->v[i]; /* check if the vertex is marked */ if (v->i == 0) { /* it is marked, delete it */ dmp_free_atom(G->pool, v, sizeof(glp_vertex)); } else { /* it is not marked, keep it */ v->i = ++nv_new; G->v[v->i] = v; } } /* set new number of vertices in the graph */ G->nv = nv_new; return; } /*********************************************************************** * NAME * * glp_del_arc - delete arc from graph * * SYNOPSIS * * void glp_del_arc(glp_graph *G, glp_arc *a); * * DESCRIPTION * * The routine glp_del_arc deletes an arc from the specified graph. * The arc to be deleted must exist. */ void glp_del_arc(glp_graph *G, glp_arc *a) { /* some sanity checks */ xassert(G->na > 0); xassert(1 <= a->tail->i && a->tail->i <= G->nv); xassert(a->tail == G->v[a->tail->i]); xassert(1 <= a->head->i && a->head->i <= G->nv); xassert(a->head == G->v[a->head->i]); /* remove the arc from the list of incoming arcs */ if (a->h_prev == NULL) a->head->in = a->h_next; else a->h_prev->h_next = a->h_next; if (a->h_next == NULL) ; else a->h_next->h_prev = a->h_prev; /* remove the arc from the list of outgoing arcs */ if (a->t_prev == NULL) a->tail->out = a->t_next; else a->t_prev->t_next = a->t_next; if (a->t_next == NULL) ; else a->t_next->t_prev = a->t_prev; /* free arc data, if allocated */ if (a->data != NULL) dmp_free_atom(G->pool, a->data, G->a_size); /* delete the arc from the graph */ dmp_free_atom(G->pool, a, sizeof(glp_arc)); G->na--; return; } /*********************************************************************** * NAME * * glp_erase_graph - erase graph content * * SYNOPSIS * * void glp_erase_graph(glp_graph *G, int v_size, int a_size); * * DESCRIPTION * * The routine glp_erase_graph erases the content of the specified * graph. The effect of this operation is the same as if the graph * would be deleted with the routine glp_delete_graph and then created * anew with the routine glp_create_graph, with exception that the * handle (pointer) to the graph remains valid. */ static void delete_graph(glp_graph *G) { dmp_delete_pool(G->pool); xfree(G->v); if (G->index != NULL) avl_delete_tree(G->index); return; } void glp_erase_graph(glp_graph *G, int v_size, int a_size) { if (!(0 <= v_size && v_size <= 256)) xerror("glp_erase_graph: v_size = %d; invalid size of vertex d" "ata\n", v_size); if (!(0 <= a_size && a_size <= 256)) xerror("glp_erase_graph: a_size = %d; invalid size of arc data" "\n", a_size); delete_graph(G); create_graph(G, v_size, a_size); return; } /*********************************************************************** * NAME * * glp_delete_graph - delete graph * * SYNOPSIS * * void glp_delete_graph(glp_graph *G); * * DESCRIPTION * * The routine glp_delete_graph deletes the specified graph and frees * all the memory allocated to this program object. */ void glp_delete_graph(glp_graph *G) { delete_graph(G); xfree(G); return; } /**********************************************************************/ void glp_create_v_index(glp_graph *G) { /* create vertex name index */ glp_vertex *v; int i; if (G->index == NULL) { G->index = avl_create_tree(avl_strcmp, NULL); for (i = 1; i <= G->nv; i++) { v = G->v[i]; xassert(v->entry == NULL); if (v->name != NULL) { v->entry = avl_insert_node(G->index, v->name); avl_set_node_link(v->entry, v); } } } return; } int glp_find_vertex(glp_graph *G, const char *name) { /* find vertex by its name */ AVLNODE *node; int i = 0; if (G->index == NULL) xerror("glp_find_vertex: vertex name index does not exist\n"); if (!(name == NULL || name[0] == '\0' || strlen(name) > 255)) { node = avl_find_node(G->index, name); if (node != NULL) i = ((glp_vertex *)avl_get_node_link(node))->i; } return i; } void glp_delete_v_index(glp_graph *G) { /* delete vertex name index */ int i; if (G->index != NULL) { avl_delete_tree(G->index), G->index = NULL; for (i = 1; i <= G->nv; i++) G->v[i]->entry = NULL; } return; } /*********************************************************************** * NAME * * glp_read_graph - read graph from plain text file * * SYNOPSIS * * int glp_read_graph(glp_graph *G, const char *fname); * * DESCRIPTION * * The routine glp_read_graph reads a graph from a plain text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_read_graph(glp_graph *G, const char *fname) { glp_data *data; jmp_buf jump; int nv, na, i, j, k, ret; glp_erase_graph(G, G->v_size, G->a_size); xprintf("Reading graph from `%s'...\n", fname); data = glp_sdf_open_file(fname); if (data == NULL) { ret = 1; goto done; } if (setjmp(jump)) { ret = 1; goto done; } glp_sdf_set_jump(data, jump); nv = glp_sdf_read_int(data); if (nv < 0) glp_sdf_error(data, "invalid number of vertices\n"); na = glp_sdf_read_int(data); if (na < 0) glp_sdf_error(data, "invalid number of arcs\n"); xprintf("Graph has %d vert%s and %d arc%s\n", nv, nv == 1 ? "ex" : "ices", na, na == 1 ? "" : "s"); if (nv > 0) glp_add_vertices(G, nv); for (k = 1; k <= na; k++) { i = glp_sdf_read_int(data); if (!(1 <= i && i <= nv)) glp_sdf_error(data, "tail vertex number out of range\n"); j = glp_sdf_read_int(data); if (!(1 <= j && j <= nv)) glp_sdf_error(data, "head vertex number out of range\n"); glp_add_arc(G, i, j); } xprintf("%d lines were read\n", glp_sdf_line(data)); ret = 0; done: if (data != NULL) glp_sdf_close_file(data); return ret; } /*********************************************************************** * NAME * * glp_write_graph - write graph to plain text file * * SYNOPSIS * * int glp_write_graph(glp_graph *G, const char *fname). * * DESCRIPTION * * The routine glp_write_graph writes the specified graph to a plain * text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_write_graph(glp_graph *G, const char *fname) { XFILE *fp; glp_vertex *v; glp_arc *a; int i, count, ret; xprintf("Writing graph to `%s'...\n", fname); fp = xfopen(fname, "w"), count = 0; if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "%d %d\n", G->nv, G->na), count++; for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) xfprintf(fp, "%d %d\n", a->tail->i, a->head->i), count++; } xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /* eof */ glpk-4.52.1/src/glpapi16.c0000644000062000006210000002563412175147600014311 0ustar maomkpasswd/* glpapi16.c (graph and network analysis routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "mc13d.h" /*********************************************************************** * NAME * * glp_weak_comp - find all weakly connected components of graph * * SYNOPSIS * * int glp_weak_comp(glp_graph *G, int v_num); * * DESCRIPTION * * The routine glp_weak_comp finds all weakly connected components of * the specified graph. * * The parameter v_num specifies an offset of the field of type int * in the vertex data block, to which the routine stores the number of * a (weakly) connected component containing that vertex. If v_num < 0, * no component numbers are stored. * * The components are numbered in arbitrary order from 1 to nc, where * nc is the total number of components found, 0 <= nc <= |V|. * * RETURNS * * The routine returns nc, the total number of components found. */ int glp_weak_comp(glp_graph *G, int v_num) { glp_vertex *v; glp_arc *a; int f, i, j, nc, nv, pos1, pos2, *prev, *next, *list; if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) xerror("glp_weak_comp: v_num = %d; invalid offset\n", v_num); nv = G->nv; if (nv == 0) { nc = 0; goto done; } /* allocate working arrays */ prev = xcalloc(1+nv, sizeof(int)); next = xcalloc(1+nv, sizeof(int)); list = xcalloc(1+nv, sizeof(int)); /* if vertex i is unlabelled, prev[i] is the index of previous unlabelled vertex, and next[i] is the index of next unlabelled vertex; if vertex i is labelled, then prev[i] < 0, and next[i] is the connected component number */ /* initially all vertices are unlabelled */ f = 1; for (i = 1; i <= nv; i++) prev[i] = i - 1, next[i] = i + 1; next[nv] = 0; /* main loop (until all vertices have been labelled) */ nc = 0; while (f != 0) { /* take an unlabelled vertex */ i = f; /* and remove it from the list of unlabelled vertices */ f = next[i]; if (f != 0) prev[f] = 0; /* label the vertex; it begins a new component */ prev[i] = -1, next[i] = ++nc; /* breadth first search */ list[1] = i, pos1 = pos2 = 1; while (pos1 <= pos2) { /* dequeue vertex i */ i = list[pos1++]; /* consider all arcs incoming to vertex i */ for (a = G->v[i]->in; a != NULL; a = a->h_next) { /* vertex j is adjacent to vertex i */ j = a->tail->i; if (prev[j] >= 0) { /* vertex j is unlabelled */ /* remove it from the list of unlabelled vertices */ if (prev[j] == 0) f = next[j]; else next[prev[j]] = next[j]; if (next[j] == 0) ; else prev[next[j]] = prev[j]; /* label the vertex */ prev[j] = -1, next[j] = nc; /* and enqueue it for further consideration */ list[++pos2] = j; } } /* consider all arcs outgoing from vertex i */ for (a = G->v[i]->out; a != NULL; a = a->t_next) { /* vertex j is adjacent to vertex i */ j = a->head->i; if (prev[j] >= 0) { /* vertex j is unlabelled */ /* remove it from the list of unlabelled vertices */ if (prev[j] == 0) f = next[j]; else next[prev[j]] = next[j]; if (next[j] == 0) ; else prev[next[j]] = prev[j]; /* label the vertex */ prev[j] = -1, next[j] = nc; /* and enqueue it for further consideration */ list[++pos2] = j; } } } } /* store component numbers */ if (v_num >= 0) { for (i = 1; i <= nv; i++) { v = G->v[i]; memcpy((char *)v->data + v_num, &next[i], sizeof(int)); } } /* free working arrays */ xfree(prev); xfree(next); xfree(list); done: return nc; } /*********************************************************************** * NAME * * glp_strong_comp - find all strongly connected components of graph * * SYNOPSIS * * int glp_strong_comp(glp_graph *G, int v_num); * * DESCRIPTION * * The routine glp_strong_comp finds all strongly connected components * of the specified graph. * * The parameter v_num specifies an offset of the field of type int * in the vertex data block, to which the routine stores the number of * a strongly connected component containing that vertex. If v_num < 0, * no component numbers are stored. * * The components are numbered in arbitrary order from 1 to nc, where * nc is the total number of components found, 0 <= nc <= |V|. However, * the component numbering has the property that for every arc (i->j) * in the graph the condition num(i) >= num(j) holds. * * RETURNS * * The routine returns nc, the total number of components found. */ int glp_strong_comp(glp_graph *G, int v_num) { glp_vertex *v; glp_arc *a; int i, k, last, n, na, nc, *icn, *ip, *lenr, *ior, *ib, *lowl, *numb, *prev; if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) xerror("glp_strong_comp: v_num = %d; invalid offset\n", v_num); n = G->nv; if (n == 0) { nc = 0; goto done; } na = G->na; icn = xcalloc(1+na, sizeof(int)); ip = xcalloc(1+n, sizeof(int)); lenr = xcalloc(1+n, sizeof(int)); ior = xcalloc(1+n, sizeof(int)); ib = xcalloc(1+n, sizeof(int)); lowl = xcalloc(1+n, sizeof(int)); numb = xcalloc(1+n, sizeof(int)); prev = xcalloc(1+n, sizeof(int)); k = 1; for (i = 1; i <= n; i++) { v = G->v[i]; ip[i] = k; for (a = v->out; a != NULL; a = a->t_next) icn[k++] = a->head->i; lenr[i] = k - ip[i]; } xassert(na == k-1); nc = mc13d(n, icn, ip, lenr, ior, ib, lowl, numb, prev); if (v_num >= 0) { xassert(ib[1] == 1); for (k = 1; k <= nc; k++) { last = (k < nc ? ib[k+1] : n+1); xassert(ib[k] < last); for (i = ib[k]; i < last; i++) { v = G->v[ior[i]]; memcpy((char *)v->data + v_num, &k, sizeof(int)); } } } xfree(icn); xfree(ip); xfree(lenr); xfree(ior); xfree(ib); xfree(lowl); xfree(numb); xfree(prev); done: return nc; } /*********************************************************************** * NAME * * glp_top_sort - topological sorting of acyclic digraph * * SYNOPSIS * * int glp_top_sort(glp_graph *G, int v_num); * * DESCRIPTION * * The routine glp_top_sort performs topological sorting of vertices of * the specified acyclic digraph. * * The parameter v_num specifies an offset of the field of type int in * the vertex data block, to which the routine stores the vertex number * assigned. If v_num < 0, vertex numbers are not stored. * * The vertices are numbered from 1 to n, where n is the total number * of vertices in the graph. The vertex numbering has the property that * for every arc (i->j) in the graph the condition num(i) < num(j) * holds. Special case num(i) = 0 means that vertex i is not assigned a * number, because the graph is *not* acyclic. * * RETURNS * * If the graph is acyclic and therefore all the vertices have been * assigned numbers, the routine glp_top_sort returns zero. Otherwise, * if the graph is not acyclic, the routine returns the number of * vertices which have not been numbered, i.e. for which num(i) = 0. */ static int top_sort(glp_graph *G, int num[]) { glp_arc *a; int i, j, cnt, top, *stack, *indeg; /* allocate working arrays */ indeg = xcalloc(1+G->nv, sizeof(int)); stack = xcalloc(1+G->nv, sizeof(int)); /* determine initial indegree of each vertex; push into the stack the vertices having zero indegree */ top = 0; for (i = 1; i <= G->nv; i++) { num[i] = indeg[i] = 0; for (a = G->v[i]->in; a != NULL; a = a->h_next) indeg[i]++; if (indeg[i] == 0) stack[++top] = i; } /* assign numbers to vertices in the sorted order */ cnt = 0; while (top > 0) { /* pull vertex i from the stack */ i = stack[top--]; /* it has zero indegree in the current graph */ xassert(indeg[i] == 0); /* so assign it a next number */ xassert(num[i] == 0); num[i] = ++cnt; /* remove vertex i from the current graph, update indegree of its adjacent vertices, and push into the stack new vertices whose indegree becomes zero */ for (a = G->v[i]->out; a != NULL; a = a->t_next) { j = a->head->i; /* there exists arc (i->j) in the graph */ xassert(indeg[j] > 0); indeg[j]--; if (indeg[j] == 0) stack[++top] = j; } } /* free working arrays */ xfree(indeg); xfree(stack); return G->nv - cnt; } int glp_top_sort(glp_graph *G, int v_num) { glp_vertex *v; int i, cnt, *num; if (v_num >= 0 && v_num > G->v_size - (int)sizeof(int)) xerror("glp_top_sort: v_num = %d; invalid offset\n", v_num); if (G->nv == 0) { cnt = 0; goto done; } num = xcalloc(1+G->nv, sizeof(int)); cnt = top_sort(G, num); if (v_num >= 0) { for (i = 1; i <= G->nv; i++) { v = G->v[i]; memcpy((char *)v->data + v_num, &num[i], sizeof(int)); } } xfree(num); done: return cnt; } /* eof */ glpk-4.52.1/src/glpapi17.c0000644000062000006210000012266612175147600014315 0ustar maomkpasswd/* glpapi17.c (flow network problems) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "ffalg.h" #include "mc21a.h" #include "okalg.h" #include "relax4.h" /*********************************************************************** * NAME * * glp_mincost_lp - convert minimum cost flow problem to LP * * SYNOPSIS * * void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, * int v_rhs, int a_low, int a_cap, int a_cost); * * DESCRIPTION * * The routine glp_mincost_lp builds an LP problem, which corresponds * to the minimum cost flow problem on the specified network G. */ void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, int v_rhs, int a_low, int a_cap, int a_cost) { glp_vertex *v; glp_arc *a; int i, j, type, ind[1+2]; double rhs, low, cap, cost, val[1+2]; if (!(names == GLP_ON || names == GLP_OFF)) xerror("glp_mincost_lp: names = %d; invalid parameter\n", names); if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_mincost_lp: v_rhs = %d; invalid offset\n", v_rhs); if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) xerror("glp_mincost_lp: a_low = %d; invalid offset\n", a_low); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_mincost_lp: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_mincost_lp: a_cost = %d; invalid offset\n", a_cost) ; glp_erase_prob(lp); if (names) glp_set_prob_name(lp, G->name); if (G->nv > 0) glp_add_rows(lp, G->nv); for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (names) glp_set_row_name(lp, i, v->name); if (v_rhs >= 0) memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); else rhs = 0.0; glp_set_row_bnds(lp, i, GLP_FX, rhs, rhs); } if (G->na > 0) glp_add_cols(lp, G->na); for (i = 1, j = 0; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { j++; if (names) { char name[50+1]; sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); xassert(strlen(name) < sizeof(name)); glp_set_col_name(lp, j, name); } if (a->tail->i != a->head->i) { ind[1] = a->tail->i, val[1] = +1.0; ind[2] = a->head->i, val[2] = -1.0; glp_set_mat_col(lp, j, 2, ind, val); } if (a_low >= 0) memcpy(&low, (char *)a->data + a_low, sizeof(double)); else low = 0.0; if (a_cap >= 0) memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); else cap = 1.0; if (cap == DBL_MAX) type = GLP_LO; else if (low != cap) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp, j, type, low, cap); if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 0.0; glp_set_obj_coef(lp, j, cost); } } xassert(j == G->na); return; } /**********************************************************************/ int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, double *sol, int a_x, int v_pi) { /* find minimum-cost flow with out-of-kilter algorithm */ glp_vertex *v; glp_arc *a; int nv, na, i, k, s, t, *tail, *head, *low, *cap, *cost, *x, *pi, ret; double sum, temp; if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_mincost_okalg: v_rhs = %d; invalid offset\n", v_rhs); if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) xerror("glp_mincost_okalg: a_low = %d; invalid offset\n", a_low); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_mincost_okalg: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_mincost_okalg: a_cost = %d; invalid offset\n", a_cost); if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double)) xerror("glp_mincost_okalg: a_x = %d; invalid offset\n", a_x); if (v_pi >= 0 && v_pi > G->v_size - (int)sizeof(double)) xerror("glp_mincost_okalg: v_pi = %d; invalid offset\n", v_pi); /* s is artificial source node */ s = G->nv + 1; /* t is artificial sink node */ t = s + 1; /* nv is the total number of nodes in the resulting network */ nv = t; /* na is the total number of arcs in the resulting network */ na = G->na + 1; for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (v_rhs >= 0) memcpy(&temp, (char *)v->data + v_rhs, sizeof(double)); else temp = 0.0; if (temp != 0.0) na++; } /* allocate working arrays */ tail = xcalloc(1+na, sizeof(int)); head = xcalloc(1+na, sizeof(int)); low = xcalloc(1+na, sizeof(int)); cap = xcalloc(1+na, sizeof(int)); cost = xcalloc(1+na, sizeof(int)); x = xcalloc(1+na, sizeof(int)); pi = xcalloc(1+nv, sizeof(int)); /* construct the resulting network */ k = 0; /* (original arcs) */ for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { k++; tail[k] = a->tail->i; head[k] = a->head->i; if (tail[k] == head[k]) { ret = GLP_EDATA; goto done; } if (a_low >= 0) memcpy(&temp, (char *)a->data + a_low, sizeof(double)); else temp = 0.0; if (!(0.0 <= temp && temp <= (double)INT_MAX && temp == floor(temp))) { ret = GLP_EDATA; goto done; } low[k] = (int)temp; if (a_cap >= 0) memcpy(&temp, (char *)a->data + a_cap, sizeof(double)); else temp = 1.0; if (!((double)low[k] <= temp && temp <= (double)INT_MAX && temp == floor(temp))) { ret = GLP_EDATA; goto done; } cap[k] = (int)temp; if (a_cost >= 0) memcpy(&temp, (char *)a->data + a_cost, sizeof(double)); else temp = 0.0; if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) { ret = GLP_EDATA; goto done; } cost[k] = (int)temp; } } /* (artificial arcs) */ sum = 0.0; for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (v_rhs >= 0) memcpy(&temp, (char *)v->data + v_rhs, sizeof(double)); else temp = 0.0; if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) { ret = GLP_EDATA; goto done; } if (temp > 0.0) { /* artificial arc from s to original source i */ k++; tail[k] = s; head[k] = i; low[k] = cap[k] = (int)(+temp); /* supply */ cost[k] = 0; sum += (double)temp; } else if (temp < 0.0) { /* artificial arc from original sink i to t */ k++; tail[k] = i; head[k] = t; low[k] = cap[k] = (int)(-temp); /* demand */ cost[k] = 0; } } /* (feedback arc from t to s) */ k++; xassert(k == na); tail[k] = t; head[k] = s; if (sum > (double)INT_MAX) { ret = GLP_EDATA; goto done; } low[k] = cap[k] = (int)sum; /* total supply/demand */ cost[k] = 0; /* find minimal-cost circulation in the resulting network */ ret = okalg(nv, na, tail, head, low, cap, cost, x, pi); switch (ret) { case 0: /* optimal circulation found */ ret = 0; break; case 1: /* no feasible circulation exists */ ret = GLP_ENOPFS; break; case 2: /* integer overflow occured */ ret = GLP_ERANGE; goto done; case 3: /* optimality test failed (logic error) */ ret = GLP_EFAIL; goto done; default: xassert(ret != ret); } /* store solution components */ /* (objective function = the total cost) */ if (sol != NULL) { temp = 0.0; for (k = 1; k <= na; k++) temp += (double)cost[k] * (double)x[k]; *sol = temp; } /* (arc flows) */ if (a_x >= 0) { k = 0; for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { temp = (double)x[++k]; memcpy((char *)a->data + a_x, &temp, sizeof(double)); } } } /* (node potentials = Lagrange multipliers) */ if (v_pi >= 0) { for (i = 1; i <= G->nv; i++) { v = G->v[i]; temp = - (double)pi[i]; memcpy((char *)v->data + v_pi, &temp, sizeof(double)); } } done: /* free working arrays */ xfree(tail); xfree(head); xfree(low); xfree(cap); xfree(cost); xfree(x); xfree(pi); return ret; } /**********************************************************************/ static int overflow(int u, int v) { /* check for integer overflow on computing u + v */ if (u > 0 && v > 0 && u + v < 0) return 1; if (u < 0 && v < 0 && u + v > 0) return 1; return 0; } int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, int crash, double *sol, int a_x, int a_rc) { /* find minimum-cost flow with Bertsekas-Tseng relaxation method (RELAX-IV) */ glp_vertex *v; glp_arc *a; struct relax4_csa csa; int i, k, large, n, na, ret; double cap, cost, low, rc, rhs, sum, x; if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_mincost_relax4: v_rhs = %d; invalid offset\n", v_rhs); if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) xerror("glp_mincost_relax4: a_low = %d; invalid offset\n", a_low); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_mincost_relax4: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_mincost_relax4: a_cost = %d; invalid offset\n", a_cost); if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double)) xerror("glp_mincost_relax4: a_x = %d; invalid offset\n", a_x); if (a_rc >= 0 && a_rc > G->a_size - (int)sizeof(double)) xerror("glp_mincost_relax4: a_rc = %d; invalid offset\n", a_rc); csa.n = n = G->nv; /* number of nodes */ csa.na = na = G->na; /* number of arcs */ csa.large = large = INT_MAX / 4; csa.repeat = 0; csa.crash = crash; /* allocate working arrays */ csa.startn = xcalloc(1+na, sizeof(int)); csa.endn = xcalloc(1+na, sizeof(int)); csa.fou = xcalloc(1+n, sizeof(int)); csa.nxtou = xcalloc(1+na, sizeof(int)); csa.fin = xcalloc(1+n, sizeof(int)); csa.nxtin = xcalloc(1+na, sizeof(int)); csa.rc = xcalloc(1+na, sizeof(int)); csa.u = xcalloc(1+na, sizeof(int)); csa.dfct = xcalloc(1+n, sizeof(int)); csa.x = xcalloc(1+na, sizeof(int)); csa.label = xcalloc(1+n, sizeof(int)); csa.prdcsr = xcalloc(1+n, sizeof(int)); csa.save = xcalloc(1+na, sizeof(int)); csa.tfstou = xcalloc(1+n, sizeof(int)); csa.tnxtou = xcalloc(1+na, sizeof(int)); csa.tfstin = xcalloc(1+n, sizeof(int)); csa.tnxtin = xcalloc(1+na, sizeof(int)); csa.nxtqueue = xcalloc(1+n, sizeof(int)); csa.scan = xcalloc(1+n, sizeof(char)); csa.mark = xcalloc(1+n, sizeof(char)); if (crash) { csa.extend_arc = xcalloc(1+n, sizeof(int)); csa.sb_level = xcalloc(1+n, sizeof(int)); csa.sb_arc = xcalloc(1+n, sizeof(int)); } else { csa.extend_arc = NULL; csa.sb_level = NULL; csa.sb_arc = NULL; } /* scan nodes */ for (i = 1; i <= n; i++) { v = G->v[i]; /* get supply at i-th node */ if (v_rhs >= 0) memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); else rhs = 0.0; if (!(fabs(rhs) <= (double)large && rhs == floor(rhs))) { ret = GLP_EDATA; goto done; } /* set demand at i-th node */ csa.dfct[i] = -(int)rhs; } /* scan arcs */ k = 0; for (i = 1; i <= n; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { k++; /* set endpoints of k-th arc */ if (a->tail->i == a->head->i) { /* self-loops not allowed */ ret = GLP_EDATA; goto done; } csa.startn[k] = a->tail->i; csa.endn[k] = a->head->i; /* set per-unit cost for k-th arc flow */ if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 0.0; if (!(fabs(cost) <= (double)large && cost == floor(cost))) { ret = GLP_EDATA; goto done; } csa.rc[k] = (int)cost; /* get lower bound for k-th arc flow */ if (a_low >= 0) memcpy(&low, (char *)a->data + a_low, sizeof(double)); else low = 0.0; if (!(0.0 <= low && low <= (double)large && low == floor(low))) { ret = GLP_EDATA; goto done; } /* get upper bound for k-th arc flow */ if (a_cap >= 0) memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); else cap = 1.0; if (!(low <= cap && cap <= (double)large && cap == floor(cap))) { ret = GLP_EDATA; goto done; } /* substitute x = x' + low, where 0 <= x' <= cap - low */ csa.u[k] = (int)(cap - low); /* correct demands at endpoints of k-th arc */ if (overflow(csa.dfct[a->tail->i], +low)) { ret = GLP_ERANGE; goto done; } csa.dfct[a->tail->i] += low; if (overflow(csa.dfct[a->head->i], -low)) { ret = GLP_ERANGE; goto done; } csa.dfct[a->head->i] -= low; } } /* construct linked list for network topology */ relax4_inidat(&csa); /* find minimum-cost flow */ ret = relax4(&csa); if (ret != 0) { /* problem is found to be infeasible */ xassert(1 <= ret && ret <= 8); ret = GLP_ENOPFS; goto done; } /* store solution */ sum = 0.0; k = 0; for (i = 1; i <= n; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { k++; /* get lower bound for k-th arc flow */ if (a_low >= 0) memcpy(&low, (char *)a->data + a_low, sizeof(double)); else low = 0.0; /* store original flow x = x' + low thru k-th arc */ x = (double)csa.x[k] + low; if (a_x >= 0) memcpy((char *)a->data + a_x, &x, sizeof(double)); /* store reduced cost for k-th arc flow */ rc = (double)csa.rc[k]; if (a_rc >= 0) memcpy((char *)a->data + a_rc, &rc, sizeof(double)); /* get per-unit cost for k-th arc flow */ if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 0.0; /* compute the total cost */ sum += cost * x; } } /* store the total cost */ if (sol != NULL) *sol = sum; done: /* free working arrays */ xfree(csa.startn); xfree(csa.endn); xfree(csa.fou); xfree(csa.nxtou); xfree(csa.fin); xfree(csa.nxtin); xfree(csa.rc); xfree(csa.u); xfree(csa.dfct); xfree(csa.x); xfree(csa.label); xfree(csa.prdcsr); xfree(csa.save); xfree(csa.tfstou); xfree(csa.tnxtou); xfree(csa.tfstin); xfree(csa.tnxtin); xfree(csa.nxtqueue); xfree(csa.scan); xfree(csa.mark); if (crash) { xfree(csa.extend_arc); xfree(csa.sb_level); xfree(csa.sb_arc); } return ret; } /*********************************************************************** * NAME * * glp_maxflow_lp - convert maximum flow problem to LP * * SYNOPSIS * * void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s, * int t, int a_cap); * * DESCRIPTION * * The routine glp_maxflow_lp builds an LP problem, which corresponds * to the maximum flow problem on the specified network G. */ void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s, int t, int a_cap) { glp_vertex *v; glp_arc *a; int i, j, type, ind[1+2]; double cap, val[1+2]; if (!(names == GLP_ON || names == GLP_OFF)) xerror("glp_maxflow_lp: names = %d; invalid parameter\n", names); if (!(1 <= s && s <= G->nv)) xerror("glp_maxflow_lp: s = %d; source node number out of rang" "e\n", s); if (!(1 <= t && t <= G->nv)) xerror("glp_maxflow_lp: t = %d: sink node number out of range " "\n", t); if (s == t) xerror("glp_maxflow_lp: s = t = %d; source and sink nodes must" " be distinct\n", s); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_maxflow_lp: a_cap = %d; invalid offset\n", a_cap); glp_erase_prob(lp); if (names) glp_set_prob_name(lp, G->name); glp_set_obj_dir(lp, GLP_MAX); glp_add_rows(lp, G->nv); for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (names) glp_set_row_name(lp, i, v->name); if (i == s) type = GLP_LO; else if (i == t) type = GLP_UP; else type = GLP_FX; glp_set_row_bnds(lp, i, type, 0.0, 0.0); } if (G->na > 0) glp_add_cols(lp, G->na); for (i = 1, j = 0; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { j++; if (names) { char name[50+1]; sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); xassert(strlen(name) < sizeof(name)); glp_set_col_name(lp, j, name); } if (a->tail->i != a->head->i) { ind[1] = a->tail->i, val[1] = +1.0; ind[2] = a->head->i, val[2] = -1.0; glp_set_mat_col(lp, j, 2, ind, val); } if (a_cap >= 0) memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); else cap = 1.0; if (cap == DBL_MAX) type = GLP_LO; else if (cap != 0.0) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(lp, j, type, 0.0, cap); if (a->tail->i == s) glp_set_obj_coef(lp, j, +1.0); else if (a->head->i == s) glp_set_obj_coef(lp, j, -1.0); } } xassert(j == G->na); return; } int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, double *sol, int a_x, int v_cut) { /* find maximal flow with Ford-Fulkerson algorithm */ glp_vertex *v; glp_arc *a; int nv, na, i, k, flag, *tail, *head, *cap, *x, ret; char *cut; double temp; if (!(1 <= s && s <= G->nv)) xerror("glp_maxflow_ffalg: s = %d; source node number out of r" "ange\n", s); if (!(1 <= t && t <= G->nv)) xerror("glp_maxflow_ffalg: t = %d: sink node number out of ran" "ge\n", t); if (s == t) xerror("glp_maxflow_ffalg: s = t = %d; source and sink nodes m" "ust be distinct\n", s); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_maxflow_ffalg: a_cap = %d; invalid offset\n", a_cap); if (v_cut >= 0 && v_cut > G->v_size - (int)sizeof(int)) xerror("glp_maxflow_ffalg: v_cut = %d; invalid offset\n", v_cut); /* allocate working arrays */ nv = G->nv; na = G->na; tail = xcalloc(1+na, sizeof(int)); head = xcalloc(1+na, sizeof(int)); cap = xcalloc(1+na, sizeof(int)); x = xcalloc(1+na, sizeof(int)); if (v_cut < 0) cut = NULL; else cut = xcalloc(1+nv, sizeof(char)); /* copy the flow network */ k = 0; for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { k++; tail[k] = a->tail->i; head[k] = a->head->i; if (tail[k] == head[k]) { ret = GLP_EDATA; goto done; } if (a_cap >= 0) memcpy(&temp, (char *)a->data + a_cap, sizeof(double)); else temp = 1.0; if (!(0.0 <= temp && temp <= (double)INT_MAX && temp == floor(temp))) { ret = GLP_EDATA; goto done; } cap[k] = (int)temp; } } xassert(k == na); /* find maximal flow in the flow network */ ffalg(nv, na, tail, head, s, t, cap, x, cut); ret = 0; /* store solution components */ /* (objective function = total flow through the network) */ if (sol != NULL) { temp = 0.0; for (k = 1; k <= na; k++) { if (tail[k] == s) temp += (double)x[k]; else if (head[k] == s) temp -= (double)x[k]; } *sol = temp; } /* (arc flows) */ if (a_x >= 0) { k = 0; for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { temp = (double)x[++k]; memcpy((char *)a->data + a_x, &temp, sizeof(double)); } } } /* (node flags) */ if (v_cut >= 0) { for (i = 1; i <= G->nv; i++) { v = G->v[i]; flag = cut[i]; memcpy((char *)v->data + v_cut, &flag, sizeof(int)); } } done: /* free working arrays */ xfree(tail); xfree(head); xfree(cap); xfree(x); if (cut != NULL) xfree(cut); return ret; } /*********************************************************************** * NAME * * glp_check_asnprob - check correctness of assignment problem data * * SYNOPSIS * * int glp_check_asnprob(glp_graph *G, int v_set); * * RETURNS * * If the specified assignment problem data are correct, the routine * glp_check_asnprob returns zero, otherwise, non-zero. */ int glp_check_asnprob(glp_graph *G, int v_set) { glp_vertex *v; int i, k, ret = 0; if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_check_asnprob: v_set = %d; invalid offset\n", v_set); for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (v_set >= 0) { memcpy(&k, (char *)v->data + v_set, sizeof(int)); if (k == 0) { if (v->in != NULL) { ret = 1; break; } } else if (k == 1) { if (v->out != NULL) { ret = 2; break; } } else { ret = 3; break; } } else { if (v->in != NULL && v->out != NULL) { ret = 4; break; } } } return ret; } /*********************************************************************** * NAME * * glp_asnprob_lp - convert assignment problem to LP * * SYNOPSIS * * int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, * int v_set, int a_cost); * * DESCRIPTION * * The routine glp_asnprob_lp builds an LP problem, which corresponds * to the assignment problem on the specified graph G. * * RETURNS * * If the LP problem has been successfully built, the routine returns * zero, otherwise, non-zero. */ int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, int v_set, int a_cost) { glp_vertex *v; glp_arc *a; int i, j, ret, ind[1+2]; double cost, val[1+2]; if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX || form == GLP_ASN_MMP)) xerror("glp_asnprob_lp: form = %d; invalid parameter\n", form); if (!(names == GLP_ON || names == GLP_OFF)) xerror("glp_asnprob_lp: names = %d; invalid parameter\n", names); if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_asnprob_lp: v_set = %d; invalid offset\n", v_set); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_asnprob_lp: a_cost = %d; invalid offset\n", a_cost); ret = glp_check_asnprob(G, v_set); if (ret != 0) goto done; glp_erase_prob(P); if (names) glp_set_prob_name(P, G->name); glp_set_obj_dir(P, form == GLP_ASN_MIN ? GLP_MIN : GLP_MAX); if (G->nv > 0) glp_add_rows(P, G->nv); for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (names) glp_set_row_name(P, i, v->name); glp_set_row_bnds(P, i, form == GLP_ASN_MMP ? GLP_UP : GLP_FX, 1.0, 1.0); } if (G->na > 0) glp_add_cols(P, G->na); for (i = 1, j = 0; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { j++; if (names) { char name[50+1]; sprintf(name, "x[%d,%d]", a->tail->i, a->head->i); xassert(strlen(name) < sizeof(name)); glp_set_col_name(P, j, name); } ind[1] = a->tail->i, val[1] = +1.0; ind[2] = a->head->i, val[2] = +1.0; glp_set_mat_col(P, j, 2, ind, val); glp_set_col_bnds(P, j, GLP_DB, 0.0, 1.0); if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 1.0; glp_set_obj_coef(P, j, cost); } } xassert(j == G->na); done: return ret; } /**********************************************************************/ int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, double *sol, int a_x) { /* solve assignment problem with out-of-kilter algorithm */ glp_vertex *v; glp_arc *a; int nv, na, i, k, *tail, *head, *low, *cap, *cost, *x, *pi, ret; double temp; if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX || form == GLP_ASN_MMP)) xerror("glp_asnprob_okalg: form = %d; invalid parameter\n", form); if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_asnprob_okalg: v_set = %d; invalid offset\n", v_set); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_asnprob_okalg: a_cost = %d; invalid offset\n", a_cost); if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int)) xerror("glp_asnprob_okalg: a_x = %d; invalid offset\n", a_x); if (glp_check_asnprob(G, v_set)) return GLP_EDATA; /* nv is the total number of nodes in the resulting network */ nv = G->nv + 1; /* na is the total number of arcs in the resulting network */ na = G->na + G->nv; /* allocate working arrays */ tail = xcalloc(1+na, sizeof(int)); head = xcalloc(1+na, sizeof(int)); low = xcalloc(1+na, sizeof(int)); cap = xcalloc(1+na, sizeof(int)); cost = xcalloc(1+na, sizeof(int)); x = xcalloc(1+na, sizeof(int)); pi = xcalloc(1+nv, sizeof(int)); /* construct the resulting network */ k = 0; /* (original arcs) */ for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { k++; tail[k] = a->tail->i; head[k] = a->head->i; low[k] = 0; cap[k] = 1; if (a_cost >= 0) memcpy(&temp, (char *)a->data + a_cost, sizeof(double)); else temp = 1.0; if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp))) { ret = GLP_EDATA; goto done; } cost[k] = (int)temp; if (form != GLP_ASN_MIN) cost[k] = - cost[k]; } } /* (artificial arcs) */ for (i = 1; i <= G->nv; i++) { v = G->v[i]; k++; if (v->out == NULL) tail[k] = i, head[k] = nv; else if (v->in == NULL) tail[k] = nv, head[k] = i; else xassert(v != v); low[k] = (form == GLP_ASN_MMP ? 0 : 1); cap[k] = 1; cost[k] = 0; } xassert(k == na); /* find minimal-cost circulation in the resulting network */ ret = okalg(nv, na, tail, head, low, cap, cost, x, pi); switch (ret) { case 0: /* optimal circulation found */ ret = 0; break; case 1: /* no feasible circulation exists */ ret = GLP_ENOPFS; break; case 2: /* integer overflow occured */ ret = GLP_ERANGE; goto done; case 3: /* optimality test failed (logic error) */ ret = GLP_EFAIL; goto done; default: xassert(ret != ret); } /* store solution components */ /* (objective function = the total cost) */ if (sol != NULL) { temp = 0.0; for (k = 1; k <= na; k++) temp += (double)cost[k] * (double)x[k]; if (form != GLP_ASN_MIN) temp = - temp; *sol = temp; } /* (arc flows) */ if (a_x >= 0) { k = 0; for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { k++; if (ret == 0) xassert(x[k] == 0 || x[k] == 1); memcpy((char *)a->data + a_x, &x[k], sizeof(int)); } } } done: /* free working arrays */ xfree(tail); xfree(head); xfree(low); xfree(cap); xfree(cost); xfree(x); xfree(pi); return ret; } /*********************************************************************** * NAME * * glp_asnprob_hall - find bipartite matching of maximum cardinality * * SYNOPSIS * * int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); * * DESCRIPTION * * The routine glp_asnprob_hall finds a matching of maximal cardinality * in the specified bipartite graph G. It uses a version of the Fortran * routine MC21A developed by I.S.Duff [1], which implements Hall's * algorithm [2]. * * RETURNS * * The routine glp_asnprob_hall returns the cardinality of the matching * found. However, if the specified graph is incorrect (as detected by * the routine glp_check_asnprob), the routine returns negative value. * * REFERENCES * * 1. I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM * Trans. on Math. Softw. 7 (1981), 387-390. * * 2. M.Hall, "An Algorithm for distinct representatives," Amer. Math. * Monthly 63 (1956), 716-717. */ int glp_asnprob_hall(glp_graph *G, int v_set, int a_x) { glp_vertex *v; glp_arc *a; int card, i, k, loc, n, n1, n2, xij; int *num, *icn, *ip, *lenr, *iperm, *pr, *arp, *cv, *out; if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_asnprob_hall: v_set = %d; invalid offset\n", v_set); if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int)) xerror("glp_asnprob_hall: a_x = %d; invalid offset\n", a_x); if (glp_check_asnprob(G, v_set)) return -1; /* determine the number of vertices in sets R and S and renumber vertices in S which correspond to columns of the matrix; skip all isolated vertices */ num = xcalloc(1+G->nv, sizeof(int)); n1 = n2 = 0; for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (v->in == NULL && v->out != NULL) n1++, num[i] = 0; /* vertex in R */ else if (v->in != NULL && v->out == NULL) n2++, num[i] = n2; /* vertex in S */ else { xassert(v->in == NULL && v->out == NULL); num[i] = -1; /* isolated vertex */ } } /* the matrix must be square, thus, if it has more columns than rows, extra rows will be just empty, and vice versa */ n = (n1 >= n2 ? n1 : n2); /* allocate working arrays */ icn = xcalloc(1+G->na, sizeof(int)); ip = xcalloc(1+n, sizeof(int)); lenr = xcalloc(1+n, sizeof(int)); iperm = xcalloc(1+n, sizeof(int)); pr = xcalloc(1+n, sizeof(int)); arp = xcalloc(1+n, sizeof(int)); cv = xcalloc(1+n, sizeof(int)); out = xcalloc(1+n, sizeof(int)); /* build the adjacency matrix of the bipartite graph in row-wise format (rows are vertices in R, columns are vertices in S) */ k = 0, loc = 1; for (i = 1; i <= G->nv; i++) { if (num[i] != 0) continue; /* vertex i in R */ ip[++k] = loc; v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { xassert(num[a->head->i] != 0); icn[loc++] = num[a->head->i]; } lenr[k] = loc - ip[k]; } xassert(loc-1 == G->na); /* make all extra rows empty (all extra columns are empty due to the row-wise format used) */ for (k++; k <= n; k++) ip[k] = loc, lenr[k] = 0; /* find a row permutation that maximizes the number of non-zeros on the main diagonal */ card = mc21a(n, icn, ip, lenr, iperm, pr, arp, cv, out); #if 1 /* 18/II-2010 */ /* FIXED: if card = n, arp remains clobbered on exit */ for (i = 1; i <= n; i++) arp[i] = 0; for (i = 1; i <= card; i++) { k = iperm[i]; xassert(1 <= k && k <= n); xassert(arp[k] == 0); arp[k] = i; } #endif /* store solution, if necessary */ if (a_x < 0) goto skip; k = 0; for (i = 1; i <= G->nv; i++) { if (num[i] != 0) continue; /* vertex i in R */ k++; v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { /* arp[k] is the number of matched column or zero */ if (arp[k] == num[a->head->i]) { xassert(arp[k] != 0); xij = 1; } else xij = 0; memcpy((char *)a->data + a_x, &xij, sizeof(int)); } } skip: /* free working arrays */ xfree(num); xfree(icn); xfree(ip); xfree(lenr); xfree(iperm); xfree(pr); xfree(arp); xfree(cv); xfree(out); return card; } /*********************************************************************** * NAME * * glp_cpp - solve critical path problem * * SYNOPSIS * * double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); * * DESCRIPTION * * The routine glp_cpp solves the critical path problem represented in * the form of the project network. * * The parameter G is a pointer to the graph object, which specifies * the project network. This graph must be acyclic. Multiple arcs are * allowed being considered as single arcs. * * The parameter v_t specifies an offset of the field of type double * in the vertex data block, which contains time t[i] >= 0 needed to * perform corresponding job j. If v_t < 0, it is assumed that t[i] = 1 * for all jobs. * * The parameter v_es specifies an offset of the field of type double * in the vertex data block, to which the routine stores earliest start * time for corresponding job. If v_es < 0, this time is not stored. * * The parameter v_ls specifies an offset of the field of type double * in the vertex data block, to which the routine stores latest start * time for corresponding job. If v_ls < 0, this time is not stored. * * RETURNS * * The routine glp_cpp returns the minimal project duration, that is, * minimal time needed to perform all jobs in the project. */ static void sorting(glp_graph *G, int list[]); double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls) { glp_vertex *v; glp_arc *a; int i, j, k, nv, *list; double temp, total, *t, *es, *ls; if (v_t >= 0 && v_t > G->v_size - (int)sizeof(double)) xerror("glp_cpp: v_t = %d; invalid offset\n", v_t); if (v_es >= 0 && v_es > G->v_size - (int)sizeof(double)) xerror("glp_cpp: v_es = %d; invalid offset\n", v_es); if (v_ls >= 0 && v_ls > G->v_size - (int)sizeof(double)) xerror("glp_cpp: v_ls = %d; invalid offset\n", v_ls); nv = G->nv; if (nv == 0) { total = 0.0; goto done; } /* allocate working arrays */ t = xcalloc(1+nv, sizeof(double)); es = xcalloc(1+nv, sizeof(double)); ls = xcalloc(1+nv, sizeof(double)); list = xcalloc(1+nv, sizeof(int)); /* retrieve job times */ for (i = 1; i <= nv; i++) { v = G->v[i]; if (v_t >= 0) { memcpy(&t[i], (char *)v->data + v_t, sizeof(double)); if (t[i] < 0.0) xerror("glp_cpp: t[%d] = %g; invalid time\n", i, t[i]); } else t[i] = 1.0; } /* perform topological sorting to determine the list of nodes (jobs) such that if list[k] = i and list[kk] = j and there exists arc (i->j), then k < kk */ sorting(G, list); /* FORWARD PASS */ /* determine earliest start times */ for (k = 1; k <= nv; k++) { j = list[k]; es[j] = 0.0; for (a = G->v[j]->in; a != NULL; a = a->h_next) { i = a->tail->i; /* there exists arc (i->j) in the project network */ temp = es[i] + t[i]; if (es[j] < temp) es[j] = temp; } } /* determine the minimal project duration */ total = 0.0; for (i = 1; i <= nv; i++) { temp = es[i] + t[i]; if (total < temp) total = temp; } /* BACKWARD PASS */ /* determine latest start times */ for (k = nv; k >= 1; k--) { i = list[k]; ls[i] = total - t[i]; for (a = G->v[i]->out; a != NULL; a = a->t_next) { j = a->head->i; /* there exists arc (i->j) in the project network */ temp = ls[j] - t[i]; if (ls[i] > temp) ls[i] = temp; } /* avoid possible round-off errors */ if (ls[i] < es[i]) ls[i] = es[i]; } /* store results, if necessary */ if (v_es >= 0) { for (i = 1; i <= nv; i++) { v = G->v[i]; memcpy((char *)v->data + v_es, &es[i], sizeof(double)); } } if (v_ls >= 0) { for (i = 1; i <= nv; i++) { v = G->v[i]; memcpy((char *)v->data + v_ls, &ls[i], sizeof(double)); } } /* free working arrays */ xfree(t); xfree(es); xfree(ls); xfree(list); done: return total; } static void sorting(glp_graph *G, int list[]) { /* perform topological sorting to determine the list of nodes (jobs) such that if list[k] = i and list[kk] = j and there exists arc (i->j), then k < kk */ int i, k, nv, v_size, *num; void **save; nv = G->nv; v_size = G->v_size; save = xcalloc(1+nv, sizeof(void *)); num = xcalloc(1+nv, sizeof(int)); G->v_size = sizeof(int); for (i = 1; i <= nv; i++) { save[i] = G->v[i]->data; G->v[i]->data = &num[i]; list[i] = 0; } if (glp_top_sort(G, 0) != 0) xerror("glp_cpp: project network is not acyclic\n"); G->v_size = v_size; for (i = 1; i <= nv; i++) { G->v[i]->data = save[i]; k = num[i]; xassert(1 <= k && k <= nv); xassert(list[k] == 0); list[k] = i; } xfree(save); xfree(num); return; } /* eof */ glpk-4.52.1/src/glpapi18.c0000644000062000006210000001023612175147600014303 0ustar maomkpasswd/* glpapi18.c (maximum clique problem) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "wclique.h" static void set_edge(int nv, unsigned char a[], int i, int j) { int k; xassert(1 <= j && j < i && i <= nv); k = ((i - 1) * (i - 2)) / 2 + (j - 1); a[k / CHAR_BIT] |= (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT)); return; } int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set) { /* find maximum weight clique with exact algorithm */ glp_arc *e; int i, j, k, len, x, *w, *ind, ret = 0; unsigned char *a; double s, t; if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) xerror("glp_wclique_exact: v_wgt = %d; invalid parameter\n", v_wgt); if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_wclique_exact: v_set = %d; invalid parameter\n", v_set); if (G->nv == 0) { /* empty graph has only empty clique */ if (sol != NULL) *sol = 0.0; return 0; } /* allocate working arrays */ w = xcalloc(1+G->nv, sizeof(int)); ind = xcalloc(1+G->nv, sizeof(int)); len = G->nv; /* # vertices */ len = len * (len - 1) / 2; /* # entries in lower triangle */ len = (len + (CHAR_BIT - 1)) / CHAR_BIT; /* # bytes needed */ a = xcalloc(len, sizeof(char)); memset(a, 0, len * sizeof(char)); /* determine vertex weights */ s = 0.0; for (i = 1; i <= G->nv; i++) { if (v_wgt >= 0) { memcpy(&t, (char *)G->v[i]->data + v_wgt, sizeof(double)); if (!(0.0 <= t && t <= (double)INT_MAX && t == floor(t))) { ret = GLP_EDATA; goto done; } w[i] = (int)t; } else w[i] = 1; s += (double)w[i]; } if (s > (double)INT_MAX) { ret = GLP_EDATA; goto done; } /* build the adjacency matrix */ for (i = 1; i <= G->nv; i++) { for (e = G->v[i]->in; e != NULL; e = e->h_next) { j = e->tail->i; /* there exists edge (j,i) in the graph */ if (i > j) set_edge(G->nv, a, i, j); } for (e = G->v[i]->out; e != NULL; e = e->t_next) { j = e->head->i; /* there exists edge (i,j) in the graph */ if (i > j) set_edge(G->nv, a, i, j); } } /* find maximum weight clique in the graph */ len = wclique(G->nv, w, a, ind); /* compute the clique weight */ s = 0.0; for (k = 1; k <= len; k++) { i = ind[k]; xassert(1 <= i && i <= G->nv); s += (double)w[i]; } if (sol != NULL) *sol = s; /* mark vertices included in the clique */ if (v_set >= 0) { x = 0; for (i = 1; i <= G->nv; i++) memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); x = 1; for (k = 1; k <= len; k++) { i = ind[k]; memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); } } done: /* free working arrays */ xfree(w); xfree(ind); xfree(a); return ret; } /* eof */ glpk-4.52.1/src/glpapi19.c0000644000062000006210000001071312175147600014304 0ustar maomkpasswd/* glpapi19.c (driver to MiniSat solver) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "minisat.h" int glp_minisat1(glp_prob *P) { /* solve CNF-SAT problem with MiniSat solver */ solver *s; GLPAIJ *aij; int i, j, len, ret, *ind; double sum; /* check problem object */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_minisat1: P = %p; invalid problem object\n", P); if (P->tree != NULL) xerror("glp_minisat1: operation not allowed\n"); /* integer solution is currently undefined */ P->mip_stat = GLP_UNDEF; P->mip_obj = 0.0; /* check that problem object encodes CNF-SAT instance */ if (glp_check_cnfsat(P) != 0) { xprintf("glp_minisat1: problem object does not encode CNF-SAT " "instance\n"); ret = GLP_EDATA; goto done; } /* solve CNF-SAT problem */ xprintf("Solving CNF-SAT problem...\n"); xprintf("Instance has %d variable%s, %d clause%s, and %d literal%" "s\n", P->n, P->n == 1 ? "" : "s", P->m, P->m == 1 ? "" : "s", P->nnz, P->nnz == 1 ? "" : "s"); /* if CNF-SAT has no clauses, it is satisfiable */ if (P->m == 0) { P->mip_stat = GLP_OPT; for (j = 1; j <= P->n; j++) P->col[j]->mipx = 0.0; goto fini; } /* if CNF-SAT has an empty clause, it is unsatisfiable */ for (i = 1; i <= P->m; i++) { if (P->row[i]->ptr == NULL) { P->mip_stat = GLP_NOFEAS; goto fini; } } /* prepare input data for the solver */ s = solver_new(); solver_setnvars(s, P->n); ind = xcalloc(1+P->n, sizeof(int)); for (i = 1; i <= P->m; i++) { len = 0; for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) { ind[++len] = toLit(aij->col->j-1); if (aij->val < 0.0) ind[len] = lit_neg(ind[len]); } xassert(len > 0); xassert(solver_addclause(s, &ind[1], &ind[1+len])); } xfree(ind); /* call the solver */ s->verbosity = 1; if (solver_solve(s, 0, 0)) { /* instance is reported as satisfiable */ P->mip_stat = GLP_OPT; /* copy solution to the problem object */ xassert(s->model.size == P->n); for (j = 1; j <= P->n; j++) { P->col[j]->mipx = s->model.ptr[j-1] == l_True ? 1.0 : 0.0; } /* compute row values */ for (i = 1; i <= P->m; i++) { sum = 0; for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) sum += aij->val * aij->col->mipx; P->row[i]->mipx = sum; } /* check integer feasibility */ for (i = 1; i <= P->m; i++) { if (P->row[i]->mipx < P->row[i]->lb) { /* solution is wrong */ P->mip_stat = GLP_UNDEF; break; } } } else { /* instance is reported as unsatisfiable */ P->mip_stat = GLP_NOFEAS; } solver_delete(s); fini: /* report the instance status */ if (P->mip_stat == GLP_OPT) { xprintf("SATISFIABLE\n"); ret = 0; } else if (P->mip_stat == GLP_NOFEAS) { xprintf("UNSATISFIABLE\n"); ret = 0; } else { xprintf("glp_minisat1: solver failed\n"); ret = GLP_EFAIL; } done: return ret; } /* eof */ glpk-4.52.1/src/glpapi20.c0000644000062000006210000002302612175147600014275 0ustar maomkpasswd/* glpapi20.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpnpp.h" int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound) { /* solve integer feasibility problem */ NPP *npp = NULL; glp_prob *mip = NULL; int *obj_ind = NULL; double *obj_val = NULL; int obj_row = 0; int i, j, k, obj_len, temp, ret; /* check the problem object */ if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_intfeas1: P = %p; invalid problem object\n", P); if (P->tree != NULL) xerror("glp_intfeas1: operation not allowed\n"); /* integer solution is currently undefined */ P->mip_stat = GLP_UNDEF; P->mip_obj = 0.0; /* check columns (variables) */ for (j = 1; j <= P->n; j++) { GLPCOL *col = P->col[j]; #if 0 /* currently binarization is not yet implemented */ if (!(col->kind == GLP_IV || col->type == GLP_FX)) { xprintf("glp_intfeas1: column %d: non-integer non-fixed var" "iable not allowed\n", j); #else if (!((col->kind == GLP_IV && col->lb == 0.0 && col->ub == 1.0) || col->type == GLP_FX)) { xprintf("glp_intfeas1: column %d: non-binary non-fixed vari" "able not allowed\n", j); #endif ret = GLP_EDATA; goto done; } temp = (int)col->lb; if ((double)temp != col->lb) { if (col->type == GLP_FX) xprintf("glp_intfeas1: column %d: fixed value %g is non-" "integer or out of range\n", j, col->lb); else xprintf("glp_intfeas1: column %d: lower bound %g is non-" "integer or out of range\n", j, col->lb); ret = GLP_EDATA; goto done; } temp = (int)col->ub; if ((double)temp != col->ub) { xprintf("glp_intfeas1: column %d: upper bound %g is non-int" "eger or out of range\n", j, col->ub); ret = GLP_EDATA; goto done; } if (col->type == GLP_DB && col->lb > col->ub) { xprintf("glp_intfeas1: column %d: lower bound %g is greater" " than upper bound %g\n", j, col->lb, col->ub); ret = GLP_EBOUND; goto done; } } /* check rows (constraints) */ for (i = 1; i <= P->m; i++) { GLPROW *row = P->row[i]; GLPAIJ *aij; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { temp = (int)aij->val; if ((double)temp != aij->val) { xprintf("glp_intfeas1: row = %d, column %d: constraint c" "oefficient %g is non-integer or out of range\n", i, aij->col->j, aij->val); ret = GLP_EDATA; goto done; } } temp = (int)row->lb; if ((double)temp != row->lb) { if (row->type == GLP_FX) xprintf("glp_intfeas1: row = %d: fixed value %g is non-i" "nteger or out of range\n", i, row->lb); else xprintf("glp_intfeas1: row = %d: lower bound %g is non-i" "nteger or out of range\n", i, row->lb); ret = GLP_EDATA; goto done; } temp = (int)row->ub; if ((double)temp != row->ub) { xprintf("glp_intfeas1: row = %d: upper bound %g is non-inte" "ger or out of range\n", i, row->ub); ret = GLP_EDATA; goto done; } if (row->type == GLP_DB && row->lb > row->ub) { xprintf("glp_intfeas1: row %d: lower bound %g is greater th" "an upper bound %g\n", i, row->lb, row->ub); ret = GLP_EBOUND; goto done; } } /* check the objective function */ temp = (int)P->c0; if ((double)temp != P->c0) { xprintf("glp_intfeas1: objective constant term %g is non-integ" "er or out of range\n", P->c0); ret = GLP_EDATA; goto done; } for (j = 1; j <= P->n; j++) { temp = (int)P->col[j]->coef; if ((double)temp != P->col[j]->coef) { xprintf("glp_intfeas1: column %d: objective coefficient is " "non-integer or out of range\n", j, P->col[j]->coef); ret = GLP_EDATA; goto done; } } /* save the objective function and set it to zero */ obj_ind = xcalloc(1+P->n, sizeof(int)); obj_val = xcalloc(1+P->n, sizeof(double)); obj_len = 0; obj_ind[0] = 0; obj_val[0] = P->c0; P->c0 = 0.0; for (j = 1; j <= P->n; j++) { if (P->col[j]->coef != 0.0) { obj_len++; obj_ind[obj_len] = j; obj_val[obj_len] = P->col[j]->coef; P->col[j]->coef = 0.0; } } /* add inequality to bound the objective function, if required */ if (!use_bound) xprintf("Will search for ANY feasible solution\n"); else { xprintf("Will search only for solution not worse than %d\n", obj_bound); obj_row = glp_add_rows(P, 1); glp_set_mat_row(P, obj_row, obj_len, obj_ind, obj_val); if (P->dir == GLP_MIN) glp_set_row_bnds(P, obj_row, GLP_UP, 0.0, (double)obj_bound - obj_val[0]); else if (P->dir == GLP_MAX) glp_set_row_bnds(P, obj_row, GLP_LO, (double)obj_bound - obj_val[0], 0.0); else xassert(P != P); } /* create preprocessor workspace */ xprintf("Translating to CNF-SAT...\n"); xprintf("Original problem has %d row%s, %d column%s, and %d non-z" "ero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", P->nnz, P->nnz == 1 ? "" : "s"); npp = npp_create_wksp(); /* load the original problem into the preprocessor workspace */ npp_load_prob(npp, P, GLP_OFF, GLP_MIP, GLP_OFF); /* perform translation to SAT-CNF problem instance */ ret = npp_sat_encode_prob(npp); if (ret == 0) ; else if (ret == GLP_ENOPFS) xprintf("PROBLEM HAS NO INTEGER FEASIBLE SOLUTION\n"); else if (ret == GLP_ERANGE) xprintf("glp_intfeas1: translation to SAT-CNF failed because o" "f integer overflow\n"); else xassert(ret != ret); if (ret != 0) goto done; /* build SAT-CNF problem instance and try to solve it */ mip = glp_create_prob(); npp_build_prob(npp, mip); ret = glp_minisat1(mip); /* only integer feasible solution can be postprocessed */ if (!(mip->mip_stat == GLP_OPT || mip->mip_stat == GLP_FEAS)) { P->mip_stat = mip->mip_stat; goto done; } /* postprocess the solution found */ npp_postprocess(npp, mip); /* the transformed problem is no longer needed */ glp_delete_prob(mip), mip = NULL; /* store solution to the original problem object */ npp_unload_sol(npp, P); /* change the solution status to 'integer feasible' */ P->mip_stat = GLP_FEAS; /* check integer feasibility */ for (i = 1; i <= P->m; i++) { GLPROW *row; GLPAIJ *aij; double sum; row = P->row[i]; sum = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) sum += aij->val * aij->col->mipx; xassert(sum == row->mipx); if (row->type == GLP_LO || row->type == GLP_DB || row->type == GLP_FX) xassert(sum >= row->lb); if (row->type == GLP_UP || row->type == GLP_DB || row->type == GLP_FX) xassert(sum <= row->ub); } /* compute value of the original objective function */ P->mip_obj = obj_val[0]; for (k = 1; k <= obj_len; k++) P->mip_obj += obj_val[k] * P->col[obj_ind[k]]->mipx; xprintf("Objective value = %17.9e\n", P->mip_obj); done: /* delete the transformed problem, if it exists */ if (mip != NULL) glp_delete_prob(mip); /* delete the preprocessor workspace, if it exists */ if (npp != NULL) npp_delete_wksp(npp); /* remove inequality used to bound the objective function */ if (obj_row > 0) { int ind[1+1]; ind[1] = obj_row; glp_del_rows(P, 1, ind); } /* restore the original objective function */ if (obj_ind != NULL) { P->c0 = obj_val[0]; for (k = 1; k <= obj_len; k++) P->col[obj_ind[k]]->coef = obj_val[k]; xfree(obj_ind); xfree(obj_val); } return ret; } /* eof */ glpk-4.52.1/src/glpapi21.c0000644000062000006210000015016612175147600014304 0ustar maomkpasswd/* glpapi21.c (stand-alone LP/MIP solver) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "glpgmp.h" #include "glplib.h" struct csa { /* common storage area */ glp_prob *prob; /* LP/MIP problem object */ glp_bfcp bfcp; /* basis factorization control parameters */ glp_smcp smcp; /* simplex method control parameters */ glp_iptcp iptcp; /* interior-point method control parameters */ glp_iocp iocp; /* integer optimizer control parameters */ glp_tran *tran; /* model translator workspace */ glp_graph *graph; /* network problem object */ int format; /* problem file format: */ #define FMT_MPS_DECK 1 /* fixed MPS */ #define FMT_MPS_FILE 2 /* free MPS */ #define FMT_LP 3 /* CPLEX LP */ #define FMT_GLP 4 /* GLPK LP/MIP */ #define FMT_MATHPROG 5 /* MathProg */ #define FMT_MIN_COST 6 /* DIMACS min-cost flow */ #define FMT_MAX_FLOW 7 /* DIMACS maximum flow */ #if 1 /* 06/VIII-2011 */ #define FMT_CNF 8 /* DIMACS CNF-SAT */ #endif const char *in_file; /* name of input problem file */ #define DATA_MAX 10 /* maximal number of input data files */ int ndf; /* number of input data files specified */ const char *in_data[1+DATA_MAX]; /* name(s) of input data file(s) */ const char *out_dpy; /* name of output file to send display output; NULL means the display output is sent to the terminal */ int seed; /* seed value to be passed to the MathProg translator; initially set to 1; 0x80000000 means the value is omitted */ int solution; /* solution type flag: */ #define SOL_BASIC 1 /* basic */ #define SOL_INTERIOR 2 /* interior-point */ #define SOL_INTEGER 3 /* mixed integer */ const char *in_res; /* name of input solution file in raw format */ int dir; /* optimization direction flag: 0 - not specified GLP_MIN - minimization GLP_MAX - maximization */ int scale; /* automatic problem scaling flag */ const char *out_sol; /* name of output solution file in printable format */ const char *out_res; /* name of output solution file in raw format */ const char *out_ranges; /* name of output file to write sensitivity analysis report */ int check; /* input data checking flag; no solution is performed */ const char *new_name; /* new name to be assigned to the problem */ const char *out_mps; /* name of output problem file in fixed MPS format */ const char *out_freemps; /* name of output problem file in free MPS format */ const char *out_cpxlp; /* name of output problem file in CPLEX LP format */ const char *out_glp; /* name of output problem file in GLPK format */ const char *out_pb; /* name of output problem file in OPB format */ const char *out_npb; /* name of output problem file in normalized OPB format */ #if 1 /* 06/VIII-2011 */ const char *out_cnf; /* name of output problem file in DIMACS CNF-SAT format */ #endif const char *log_file; /* name of output file to hardcopy terminal output */ int crash; /* initial basis option: */ #define USE_STD_BASIS 1 /* use standard basis */ #define USE_ADV_BASIS 2 /* use advanced basis */ #define USE_CPX_BASIS 3 /* use Bixby's basis */ #define USE_INI_BASIS 4 /* use initial basis from ini_file */ const char *ini_file; /* name of input file containing initial basis */ int exact; /* flag to use glp_exact rather than glp_simplex */ int xcheck; /* flag to check final basis with glp_exact */ int nomip; /* flag to consider MIP as pure LP */ #if 1 /* 15/VIII-2011 */ int minisat; /* option to solve feasibility problem with MiniSat solver */ int use_bnd; /* option to bound objective function */ int obj_bnd; /* upper (minization) or lower (maximization) objective bound */ #endif #if 1 /* 11/VII-2013 */ const char *use_sol; /* name of input mip solution file in GLPK format */ #endif }; static void print_help(const char *my_name) { /* print help information */ xprintf("Usage: %s [options...] filename\n", my_name); xprintf("\n"); xprintf("General options:\n"); xprintf(" --mps read LP/MIP problem in fixed MPS fo" "rmat\n"); xprintf(" --freemps read LP/MIP problem in free MPS for" "mat (default)\n"); xprintf(" --lp read LP/MIP problem in CPLEX LP for" "mat\n"); xprintf(" --glp read LP/MIP problem in GLPK format " "\n"); xprintf(" --math read LP/MIP model written in GNU Ma" "thProg modeling\n"); xprintf(" language\n"); xprintf(" -m filename, --model filename\n"); xprintf(" read model section and optional dat" "a section from\n"); xprintf(" filename (same as --math)\n"); xprintf(" -d filename, --data filename\n"); xprintf(" read data section from filename (fo" "r --math only);\n"); xprintf(" if model file also has data section" ", it is ignored\n"); xprintf(" -y filename, --display filename\n"); xprintf(" send display output to filename (fo" "r --math only);\n"); xprintf(" by default the output is sent to te" "rminal\n"); xprintf(" --seed value initialize pseudo-random number gen" "erator used in\n"); xprintf(" MathProg model with specified seed " "(any integer);\n"); xprintf(" if seed value is ?, some random see" "d will be used\n"); xprintf(" --mincost read min-cost flow problem in DIMAC" "S format\n"); xprintf(" --maxflow read maximum flow problem in DIMACS" " format\n"); #if 1 /* 06/VIII-2011 */ xprintf(" --cnf read CNF-SAT problem in DIMACS form" "at\n"); #endif xprintf(" --simplex use simplex method (default)\n"); xprintf(" --interior use interior point method (LP only)" "\n"); xprintf(" -r filename, --read filename\n"); xprintf(" read solution from filename rather " "to find it with\n"); xprintf(" the solver\n"); xprintf(" --min minimization\n"); xprintf(" --max maximization\n"); xprintf(" --scale scale problem (default)\n"); xprintf(" --noscale do not scale problem\n"); xprintf(" -o filename, --output filename\n"); xprintf(" write solution to filename in print" "able format\n"); xprintf(" -w filename, --write filename\n"); xprintf(" write solution to filename in plain" " text format\n"); xprintf(" --ranges filename\n"); xprintf(" write sensitivity analysis report t" "o filename in\n"); xprintf(" printable format (simplex only)\n"); xprintf(" --tmlim nnn limit solution time to nnn seconds " "\n"); xprintf(" --memlim nnn limit available memory to nnn megab" "ytes\n"); xprintf(" --check do not solve problem, check input d" "ata only\n"); xprintf(" --name probname change problem name to probname\n"); xprintf(" --wmps filename write problem to filename in fixed " "MPS format\n"); xprintf(" --wfreemps filename\n"); xprintf(" write problem to filename in free M" "PS format\n"); xprintf(" --wlp filename write problem to filename in CPLEX " "LP format\n"); xprintf(" --wglp filename write problem to filename in GLPK f" "ormat\n"); #if 0 xprintf(" --wpb filename write problem to filename in OPB fo" "rmat\n"); xprintf(" --wnpb filename write problem to filename in normal" "ized OPB format\n"); #endif #if 1 /* 06/VIII-2011 */ xprintf(" --wcnf filename write problem to filename in DIMACS" " CNF-SAT format\n"); #endif xprintf(" --log filename write copy of terminal output to fi" "lename\n"); xprintf(" -h, --help display this help information and e" "xit\n"); xprintf(" -v, --version display program version and exit\n") ; xprintf("\n"); xprintf("LP basis factorization options:\n"); xprintf(" --luf LU + Forrest-Tomlin update\n"); xprintf(" (faster, less stable; default)\n"); xprintf(" --cbg LU + Schur complement + Bartels-Gol" "ub update\n"); xprintf(" (slower, more stable)\n"); xprintf(" --cgr LU + Schur complement + Givens rota" "tion update\n"); xprintf(" (slower, more stable)\n"); xprintf("\n"); xprintf("Options specific to simplex solver:\n"); xprintf(" --primal use primal simplex (default)\n"); xprintf(" --dual use dual simplex\n"); xprintf(" --std use standard initial basis of all s" "lacks\n"); xprintf(" --adv use advanced initial basis (default" ")\n"); xprintf(" --bib use Bixby's initial basis\n"); xprintf(" --ini filename use as initial basis previously sav" "ed with -w\n"); xprintf(" (disables LP presolver)\n"); xprintf(" --steep use steepest edge technique (defaul" "t)\n"); xprintf(" --nosteep use standard \"textbook\" pricing\n" ); xprintf(" --relax use Harris' two-pass ratio test (de" "fault)\n"); xprintf(" --norelax use standard \"textbook\" ratio tes" "t\n"); xprintf(" --presol use presolver (default; assumes --s" "cale and --adv)\n"); xprintf(" --nopresol do not use presolver\n"); xprintf(" --exact use simplex method based on exact a" "rithmetic\n"); xprintf(" --xcheck check final basis using exact arith" "metic\n"); xprintf("\n"); xprintf("Options specific to interior-point solver:\n"); xprintf(" --nord use natural (original) ordering\n"); xprintf(" --qmd use quotient minimum degree orderin" "g\n"); xprintf(" --amd use approximate minimum degree orde" "ring (default)\n"); xprintf(" --symamd use approximate minimum degree orde" "ring\n"); xprintf("\n"); xprintf("Options specific to MIP solver:\n"); xprintf(" --nomip consider all integer variables as c" "ontinuous\n"); xprintf(" (allows solving MIP as pure LP)\n"); xprintf(" --first branch on first integer variable\n") ; xprintf(" --last branch on last integer variable\n"); xprintf(" --mostf branch on most fractional variable " "\n"); xprintf(" --drtom branch using heuristic by Driebeck " "and Tomlin\n"); xprintf(" (default)\n"); xprintf(" --pcost branch using hybrid pseudocost heur" "istic (may be\n"); xprintf(" useful for hard instances)\n"); xprintf(" --dfs backtrack using depth first search " "\n"); xprintf(" --bfs backtrack using breadth first searc" "h\n"); xprintf(" --bestp backtrack using the best projection" " heuristic\n"); xprintf(" --bestb backtrack using node with best loca" "l bound\n"); xprintf(" (default)\n"); xprintf(" --intopt use MIP presolver (default)\n"); xprintf(" --nointopt do not use MIP presolver\n"); xprintf(" --binarize replace general integer variables b" "y binary ones\n"); xprintf(" (assumes --intopt)\n"); xprintf(" --fpump apply feasibility pump heuristic\n") ; #if 1 /* 29/VI-2013 */ xprintf(" --proxy [nnn] apply proximity search heuristic (n" "nn is time limit\n"); xprintf(" in seconds; default is 60)\n"); #endif xprintf(" --gomory generate Gomory's mixed integer cut" "s\n"); xprintf(" --mir generate MIR (mixed integer roundin" "g) cuts\n"); xprintf(" --cover generate mixed cover cuts\n"); xprintf(" --clique generate clique cuts\n"); xprintf(" --cuts generate all cuts above\n"); xprintf(" --mipgap tol set relative mip gap tolerance to t" "ol\n"); #if 1 /* 15/VIII-2011 */ xprintf(" --minisat translate integer feasibility probl" "em to CNF-SAT\n"); xprintf(" and solve it with MiniSat solver\n") ; xprintf(" --objbnd bound add inequality obj <= bound (minimi" "zation) or\n"); xprintf(" obj >= bound (maximization) to inte" "ger feasibility\n"); xprintf(" problem (assumes --minisat)\n"); #endif xprintf("\n"); xprintf("For description of the MPS and CPLEX LP formats see Refe" "rence Manual.\n"); xprintf("For description of the modeling language see \"GLPK: Mod" "eling Language\n"); xprintf("GNU MathProg\". Both documents are included in the GLPK " "distribution.\n"); xprintf("\n"); xprintf("See GLPK web page at .\n"); xprintf("\n"); xprintf("Please report bugs to .\n"); return; } static void print_version(int briefly) { /* print version information */ xprintf("GLPSOL: GLPK LP/MIP Solver, v%s\n", glp_version()); if (briefly) goto done; xprintf("\n"); xprintf("Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, " "2007, 2008,\n"); xprintf("2009, 2010, 2011, 2013 Andrew Makhorin, Department for A" "pplied\n"); xprintf("Informatics, Moscow Aviation Institute, Moscow, Russia. " "All rights\n"); xprintf("reserved. E-mail: .\n"); xprintf("\n"); xprintf("This program has ABSOLUTELY NO WARRANTY.\n"); xprintf("\n"); xprintf("This program is free software; you may re-distribute it " "under the terms\n"); xprintf("of the GNU General Public License version 3 or later.\n") ; done: return; } static int parse_cmdline(struct csa *csa, int argc, const char *argv[]) { /* parse command-line parameters */ int k; #define p(str) (strcmp(argv[k], str) == 0) for (k = 1; k < argc; k++) { if (p("--mps")) csa->format = FMT_MPS_DECK; else if (p("--freemps")) csa->format = FMT_MPS_FILE; else if (p("--lp") || p("--cpxlp")) csa->format = FMT_LP; else if (p("--glp")) csa->format = FMT_GLP; else if (p("--math") || p("-m") || p("--model")) csa->format = FMT_MATHPROG; else if (p("-d") || p("--data")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No input data file specified\n"); return 1; } if (csa->ndf == DATA_MAX) { xprintf("Too many input data files\n"); return 1; } csa->in_data[++(csa->ndf)] = argv[k]; } else if (p("-y") || p("--display")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No display output file specified\n"); return 1; } if (csa->out_dpy != NULL) { xprintf("Only one display output file allowed\n"); return 1; } csa->out_dpy = argv[k]; } else if (p("--seed")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) { xprintf("No seed value specified\n"); return 1; } if (strcmp(argv[k], "?") == 0) csa->seed = 0x80000000; else if (str2int(argv[k], &csa->seed)) { xprintf("Invalid seed value '%s'\n", argv[k]); return 1; } } else if (p("--mincost")) csa->format = FMT_MIN_COST; else if (p("--maxflow")) csa->format = FMT_MAX_FLOW; #if 1 /* 06/VIII-2011 */ else if (p("--cnf")) csa->format = FMT_CNF; #endif else if (p("--simplex")) csa->solution = SOL_BASIC; else if (p("--interior")) csa->solution = SOL_INTERIOR; #if 1 /* 28/V-2010 */ else if (p("--alien")) csa->iocp.alien = GLP_ON; #endif else if (p("-r") || p("--read")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No input solution file specified\n"); return 1; } if (csa->in_res != NULL) { xprintf("Only one input solution file allowed\n"); return 1; } csa->in_res = argv[k]; } else if (p("--min")) csa->dir = GLP_MIN; else if (p("--max")) csa->dir = GLP_MAX; else if (p("--scale")) csa->scale = 1; else if (p("--noscale")) csa->scale = 0; else if (p("-o") || p("--output")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No output solution file specified\n"); return 1; } if (csa->out_sol != NULL) { xprintf("Only one output solution file allowed\n"); return 1; } csa->out_sol = argv[k]; } else if (p("-w") || p("--write")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No output solution file specified\n"); return 1; } if (csa->out_res != NULL) { xprintf("Only one output solution file allowed\n"); return 1; } csa->out_res = argv[k]; } else if (p("--ranges") || p("--bounds")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No output file specified to write sensitivity a" "nalysis report\n"); return 1; } if (csa->out_ranges != NULL) { xprintf("Only one output file allowed to write sensitivi" "ty analysis report\n"); return 1; } csa->out_ranges = argv[k]; } else if (p("--tmlim")) { int tm_lim; k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No time limit specified\n"); return 1; } if (str2int(argv[k], &tm_lim) || tm_lim < 0) { xprintf("Invalid time limit '%s'\n", argv[k]); return 1; } if (tm_lim <= INT_MAX / 1000) csa->smcp.tm_lim = csa->iocp.tm_lim = 1000 * tm_lim; else csa->smcp.tm_lim = csa->iocp.tm_lim = INT_MAX; } else if (p("--memlim")) { int mem_lim; k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No memory limit specified\n"); return 1; } if (str2int(argv[k], &mem_lim) || mem_lim < 1) { xprintf("Invalid memory limit '%s'\n", argv[k]); return 1; } glp_mem_limit(mem_lim); } else if (p("--check")) csa->check = 1; else if (p("--name")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No problem name specified\n"); return 1; } if (csa->new_name != NULL) { xprintf("Only one problem name allowed\n"); return 1; } csa->new_name = argv[k]; } else if (p("--wmps")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No fixed MPS output file specified\n"); return 1; } if (csa->out_mps != NULL) { xprintf("Only one fixed MPS output file allowed\n"); return 1; } csa->out_mps = argv[k]; } else if (p("--wfreemps")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No free MPS output file specified\n"); return 1; } if (csa->out_freemps != NULL) { xprintf("Only one free MPS output file allowed\n"); return 1; } csa->out_freemps = argv[k]; } else if (p("--wlp") || p("--wcpxlp") || p("--wlpt")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No CPLEX LP output file specified\n"); return 1; } if (csa->out_cpxlp != NULL) { xprintf("Only one CPLEX LP output file allowed\n"); return 1; } csa->out_cpxlp = argv[k]; } else if (p("--wglp")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No GLPK LP/MIP output file specified\n"); return 1; } if (csa->out_glp != NULL) { xprintf("Only one GLPK LP/MIP output file allowed\n"); return 1; } csa->out_glp = argv[k]; } else if (p("--wpb")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No problem output file specified\n"); return 1; } if (csa->out_pb != NULL) { xprintf("Only one OPB output file allowed\n"); return 1; } csa->out_pb = argv[k]; } else if (p("--wnpb")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No problem output file specified\n"); return 1; } if (csa->out_npb != NULL) { xprintf("Only one normalized OPB output file allowed\n"); return 1; } csa->out_npb = argv[k]; } #if 1 /* 06/VIII-2011 */ else if (p("--wcnf")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No problem output file specified\n"); return 1; } if (csa->out_cnf != NULL) { xprintf("Only one output DIMACS CNF-SAT file allowed\n"); return 1; } csa->out_cnf = argv[k]; } #endif else if (p("--log")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No log file specified\n"); return 1; } if (csa->log_file != NULL) { xprintf("Only one log file allowed\n"); return 1; } csa->log_file = argv[k]; } else if (p("-h") || p("--help")) { print_help(argv[0]); return -1; } else if (p("-v") || p("--version")) { print_version(0); return -1; } else if (p("--luf")) csa->bfcp.type = GLP_BF_FT; else if (p("--cbg")) csa->bfcp.type = GLP_BF_BG; else if (p("--cgr")) csa->bfcp.type = GLP_BF_GR; else if (p("--primal")) csa->smcp.meth = GLP_PRIMAL; else if (p("--dual")) csa->smcp.meth = GLP_DUAL; else if (p("--std")) csa->crash = USE_STD_BASIS; else if (p("--adv")) csa->crash = USE_ADV_BASIS; else if (p("--bib")) csa->crash = USE_CPX_BASIS; else if (p("--ini")) { csa->crash = USE_INI_BASIS; csa->smcp.presolve = GLP_OFF; k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No initial basis file specified\n"); return 1; } if (csa->ini_file != NULL) { xprintf("Only one initial basis file allowed\n"); return 1; } csa->ini_file = argv[k]; } else if (p("--steep")) csa->smcp.pricing = GLP_PT_PSE; else if (p("--nosteep")) csa->smcp.pricing = GLP_PT_STD; else if (p("--relax")) csa->smcp.r_test = GLP_RT_HAR; else if (p("--norelax")) csa->smcp.r_test = GLP_RT_STD; else if (p("--presol")) csa->smcp.presolve = GLP_ON; else if (p("--nopresol")) csa->smcp.presolve = GLP_OFF; else if (p("--exact")) csa->exact = 1; else if (p("--xcheck")) csa->xcheck = 1; else if (p("--nord")) csa->iptcp.ord_alg = GLP_ORD_NONE; else if (p("--qmd")) csa->iptcp.ord_alg = GLP_ORD_QMD; else if (p("--amd")) csa->iptcp.ord_alg = GLP_ORD_AMD; else if (p("--symamd")) csa->iptcp.ord_alg = GLP_ORD_SYMAMD; else if (p("--nomip")) csa->nomip = 1; else if (p("--first")) csa->iocp.br_tech = GLP_BR_FFV; else if (p("--last")) csa->iocp.br_tech = GLP_BR_LFV; else if (p("--drtom")) csa->iocp.br_tech = GLP_BR_DTH; else if (p("--mostf")) csa->iocp.br_tech = GLP_BR_MFV; else if (p("--pcost")) csa->iocp.br_tech = GLP_BR_PCH; else if (p("--dfs")) csa->iocp.bt_tech = GLP_BT_DFS; else if (p("--bfs")) csa->iocp.bt_tech = GLP_BT_BFS; else if (p("--bestp")) csa->iocp.bt_tech = GLP_BT_BPH; else if (p("--bestb")) csa->iocp.bt_tech = GLP_BT_BLB; else if (p("--intopt")) csa->iocp.presolve = GLP_ON; else if (p("--nointopt")) csa->iocp.presolve = GLP_OFF; else if (p("--binarize")) csa->iocp.presolve = csa->iocp.binarize = GLP_ON; else if (p("--fpump")) csa->iocp.fp_heur = GLP_ON; #if 1 /* 29/VI-2013 */ else if (p("--proxy")) { csa->iocp.ps_heur = GLP_ON; if (argv[k+1] && isdigit((unsigned char)argv[k+1][0])) { int nnn; k++; if (str2int(argv[k], &nnn) || nnn < 1) { xprintf("Invalid proxy time limit '%s'\n", argv[k]); return 1; } csa->iocp.ps_tm_lim = 1000 * nnn; } } #endif else if (p("--gomory")) csa->iocp.gmi_cuts = GLP_ON; else if (p("--mir")) csa->iocp.mir_cuts = GLP_ON; else if (p("--cover")) csa->iocp.cov_cuts = GLP_ON; else if (p("--clique")) csa->iocp.clq_cuts = GLP_ON; else if (p("--cuts")) csa->iocp.gmi_cuts = csa->iocp.mir_cuts = csa->iocp.cov_cuts = csa->iocp.clq_cuts = GLP_ON; else if (p("--mipgap")) { double mip_gap; k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No relative gap tolerance specified\n"); return 1; } if (str2num(argv[k], &mip_gap) || mip_gap < 0.0) { xprintf("Invalid relative mip gap tolerance '%s'\n", argv[k]); return 1; } csa->iocp.mip_gap = mip_gap; } #if 1 /* 15/VIII-2011 */ else if (p("--minisat")) csa->minisat = 1; else if (p("--objbnd")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-' && !isdigit((unsigned char)argv[k][1])) { xprintf("No objective bound specified\n"); return 1; } csa->minisat = 1; csa->use_bnd = 1; if (str2int(argv[k], &csa->obj_bnd)) { xprintf("Invalid objective bound '%s' (should be integer" " value)\n", argv[k]); return 1; } } #endif #if 1 /* 11/VII-2013 */ else if (p("--use")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No input MIP solution file specified\n"); return 1; } if (csa->use_sol != NULL) { xprintf("Only one input MIP solution file allowed\n"); return 1; } csa->use_sol = argv[k]; } else if (p("--save")) { k++; if (k == argc || argv[k][0] == '\0' || argv[k][0] == '-') { xprintf("No output MIP solution file specified\n"); return 1; } if (csa->iocp.save_sol != NULL) { xprintf("Only one output MIP solution file allowed\n"); return 1; } csa->iocp.save_sol = argv[k]; } #endif else if (argv[k][0] == '-' || (argv[k][0] == '-' && argv[k][1] == '-')) { xprintf("Invalid option '%s'; try %s --help\n", argv[k], argv[0]); return 1; } else { if (csa->in_file != NULL) { xprintf("Only one input problem file allowed\n"); return 1; } csa->in_file = argv[k]; } } #undef p return 0; } typedef struct { double rhs, pi; } v_data; typedef struct { double low, cap, cost, x; } a_data; int glp_main(int argc, const char *argv[]) { /* stand-alone LP/MIP solver */ struct csa _csa, *csa = &_csa; int ret; #if 0 /* 10/VI-2013 */ glp_long start; #else double start; #endif /* perform initialization */ csa->prob = glp_create_prob(); glp_get_bfcp(csa->prob, &csa->bfcp); glp_init_smcp(&csa->smcp); csa->smcp.presolve = GLP_ON; glp_init_iptcp(&csa->iptcp); glp_init_iocp(&csa->iocp); csa->iocp.presolve = GLP_ON; csa->tran = NULL; csa->graph = NULL; csa->format = FMT_MPS_FILE; csa->in_file = NULL; csa->ndf = 0; csa->out_dpy = NULL; csa->seed = 1; csa->solution = SOL_BASIC; csa->in_res = NULL; csa->dir = 0; csa->scale = 1; csa->out_sol = NULL; csa->out_res = NULL; csa->out_ranges = NULL; csa->check = 0; csa->new_name = NULL; csa->out_mps = NULL; csa->out_freemps = NULL; csa->out_cpxlp = NULL; csa->out_glp = NULL; csa->out_pb = NULL; csa->out_npb = NULL; #if 1 /* 06/VIII-2011 */ csa->out_cnf = NULL; #endif csa->log_file = NULL; csa->crash = USE_ADV_BASIS; csa->ini_file = NULL; csa->exact = 0; csa->xcheck = 0; csa->nomip = 0; #if 1 /* 15/VIII-2011 */ csa->minisat = 0; csa->use_bnd = 0; csa->obj_bnd = 0; #endif #if 1 /* 11/VII-2013 */ csa->use_sol = NULL; #endif /* parse command-line parameters */ ret = parse_cmdline(csa, argc, argv); if (ret < 0) { ret = EXIT_SUCCESS; goto done; } if (ret > 0) { ret = EXIT_FAILURE; goto done; } /*--------------------------------------------------------------*/ /* remove all output files specified in the command line */ if (csa->out_dpy != NULL) remove(csa->out_dpy); if (csa->out_sol != NULL) remove(csa->out_sol); if (csa->out_res != NULL) remove(csa->out_res); if (csa->out_ranges != NULL) remove(csa->out_ranges); if (csa->out_mps != NULL) remove(csa->out_mps); if (csa->out_freemps != NULL) remove(csa->out_freemps); if (csa->out_cpxlp != NULL) remove(csa->out_cpxlp); if (csa->out_glp != NULL) remove(csa->out_glp); if (csa->out_pb != NULL) remove(csa->out_pb); if (csa->out_npb != NULL) remove(csa->out_npb); #if 1 /* 06/VIII-2011 */ if (csa->out_cnf != NULL) remove(csa->out_cnf); #endif if (csa->log_file != NULL) remove(csa->log_file); /*--------------------------------------------------------------*/ /* open log file, if required */ if (csa->log_file != NULL) { if (glp_open_tee(csa->log_file)) { xprintf("Unable to create log file\n"); ret = EXIT_FAILURE; goto done; } } /*--------------------------------------------------------------*/ /* print version information */ print_version(1); /*--------------------------------------------------------------*/ /* print parameters specified in the command line */ if (argc > 1) { int k, len = INT_MAX; xprintf("Parameter(s) specified in the command line:"); for (k = 1; k < argc; k++) { if (len > 72) xprintf("\n"), len = 0; xprintf(" %s", argv[k]); len += 1 + strlen(argv[k]); } xprintf("\n"); } /*--------------------------------------------------------------*/ /* read problem data from the input file */ if (csa->in_file == NULL) { xprintf("No input problem file specified; try %s --help\n", argv[0]); ret = EXIT_FAILURE; goto done; } if (csa->format == FMT_MPS_DECK) { ret = glp_read_mps(csa->prob, GLP_MPS_DECK, NULL, csa->in_file); if (ret != 0) err1: { xprintf("MPS file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_MPS_FILE) { ret = glp_read_mps(csa->prob, GLP_MPS_FILE, NULL, csa->in_file); if (ret != 0) goto err1; } else if (csa->format == FMT_LP) { ret = glp_read_lp(csa->prob, NULL, csa->in_file); if (ret != 0) { xprintf("CPLEX LP file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_GLP) { ret = glp_read_prob(csa->prob, 0, csa->in_file); if (ret != 0) { xprintf("GLPK LP/MIP file processing error\n"); ret = EXIT_FAILURE; goto done; } } else if (csa->format == FMT_MATHPROG) { int k; /* allocate the translator workspace */ csa->tran = glp_mpl_alloc_wksp(); /* set seed value */ if (csa->seed == 0x80000000) #if 0 /* 10/VI-2013 */ { csa->seed = glp_time().lo; #else { csa->seed = (int)fmod(glp_time(), 1000000000.0); #endif xprintf("Seed value %d will be used\n", csa->seed); } _glp_mpl_init_rand(csa->tran, csa->seed); /* read model section and optional data section */ if (glp_mpl_read_model(csa->tran, csa->in_file, csa->ndf > 0)) err2: { xprintf("MathProg model processing error\n"); ret = EXIT_FAILURE; goto done; } /* read optional data section(s), if necessary */ for (k = 1; k <= csa->ndf; k++) { if (glp_mpl_read_data(csa->tran, csa->in_data[k])) goto err2; } /* generate the model */ if (glp_mpl_generate(csa->tran, csa->out_dpy)) goto err2; /* build the problem instance from the model */ glp_mpl_build_prob(csa->tran, csa->prob); } else if (csa->format == FMT_MIN_COST) { csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_mincost(csa->graph, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost), csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_mincost_lp(csa->prob, csa->graph, GLP_ON, offsetof(v_data, rhs), offsetof(a_data, low), offsetof(a_data, cap), offsetof(a_data, cost)); glp_set_prob_name(csa->prob, csa->in_file); } else if (csa->format == FMT_MAX_FLOW) { int s, t; csa->graph = glp_create_graph(sizeof(v_data), sizeof(a_data)); ret = glp_read_maxflow(csa->graph, &s, &t, offsetof(a_data, cap), csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_maxflow_lp(csa->prob, csa->graph, GLP_ON, s, t, offsetof(a_data, cap)); glp_set_prob_name(csa->prob, csa->in_file); } #if 1 /* 06/VIII-2011 */ else if (csa->format == FMT_CNF) { ret = glp_read_cnfsat(csa->prob, csa->in_file); if (ret != 0) { xprintf("DIMACS file processing error\n"); ret = EXIT_FAILURE; goto done; } glp_set_prob_name(csa->prob, csa->in_file); } #endif else xassert(csa != csa); /*--------------------------------------------------------------*/ /* change problem name, if required */ if (csa->new_name != NULL) glp_set_prob_name(csa->prob, csa->new_name); /* change optimization direction, if required */ if (csa->dir != 0) glp_set_obj_dir(csa->prob, csa->dir); /* sort elements of the constraint matrix */ glp_sort_matrix(csa->prob); /*--------------------------------------------------------------*/ /* write problem data in fixed MPS format, if required */ if (csa->out_mps != NULL) { ret = glp_write_mps(csa->prob, GLP_MPS_DECK, NULL, csa->out_mps); if (ret != 0) { xprintf("Unable to write problem in fixed MPS format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in free MPS format, if required */ if (csa->out_freemps != NULL) { ret = glp_write_mps(csa->prob, GLP_MPS_FILE, NULL, csa->out_freemps); if (ret != 0) { xprintf("Unable to write problem in free MPS format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in CPLEX LP format, if required */ if (csa->out_cpxlp != NULL) { ret = glp_write_lp(csa->prob, NULL, csa->out_cpxlp); if (ret != 0) { xprintf("Unable to write problem in CPLEX LP format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in GLPK format, if required */ if (csa->out_glp != NULL) { ret = glp_write_prob(csa->prob, 0, csa->out_glp); if (ret != 0) { xprintf("Unable to write problem in GLPK format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in OPB format, if required */ if (csa->out_pb != NULL) { ret = lpx_write_pb(csa->prob, csa->out_pb, 0, 0); if (ret != 0) { xprintf("Unable to write problem in OPB format\n"); ret = EXIT_FAILURE; goto done; } } /* write problem data in normalized OPB format, if required */ if (csa->out_npb != NULL) { ret = lpx_write_pb(csa->prob, csa->out_npb, 1, 1); if (ret != 0) { xprintf( "Unable to write problem in normalized OPB format\n"); ret = EXIT_FAILURE; goto done; } } #if 1 /* 06/VIII-2011 */ /* write problem data in DIMACS CNF-SAT format, if required */ if (csa->out_cnf != NULL) { ret = glp_write_cnfsat(csa->prob, csa->out_cnf); if (ret != 0) { xprintf( "Unable to write problem in DIMACS CNF-SAT format\n"); ret = EXIT_FAILURE; goto done; } } #endif /*--------------------------------------------------------------*/ /* if only problem data check is required, skip computations */ if (csa->check) { ret = EXIT_SUCCESS; goto done; } /*--------------------------------------------------------------*/ /* determine the solution type */ if (!csa->nomip && glp_get_num_int(csa->prob) + glp_get_num_bin(csa->prob) > 0) { if (csa->solution == SOL_INTERIOR) { xprintf("Interior-point method is not able to solve MIP pro" "blem; use --simplex\n"); ret = EXIT_FAILURE; goto done; } csa->solution = SOL_INTEGER; } /*--------------------------------------------------------------*/ /* if solution is provided, read it and skip computations */ if (csa->in_res != NULL) { if (csa->solution == SOL_BASIC) ret = glp_read_sol(csa->prob, csa->in_res); else if (csa->solution == SOL_INTERIOR) ret = glp_read_ipt(csa->prob, csa->in_res); else if (csa->solution == SOL_INTEGER) ret = glp_read_mip(csa->prob, csa->in_res); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to read problem solution\n"); ret = EXIT_FAILURE; goto done; } goto skip; } #if 1 /* 11/VII-2013 */ /*--------------------------------------------------------------*/ /* if initial MIP solution is provided, read it */ if (csa->solution == SOL_INTEGER && csa->use_sol != NULL) { ret = glp_read_mip(csa->prob, csa->use_sol); if (ret != 0) { xprintf("Unable to read initial MIP solution\n"); ret = EXIT_FAILURE; goto done; } csa->iocp.use_sol = GLP_ON; } #endif /*--------------------------------------------------------------*/ /* scale the problem data, if required */ if (csa->scale) { if (csa->solution == SOL_BASIC && !csa->smcp.presolve || csa->solution == SOL_INTERIOR || csa->solution == SOL_INTEGER && !csa->iocp.presolve) glp_scale_prob(csa->prob, GLP_SF_AUTO); } /*--------------------------------------------------------------*/ /* construct starting LP basis */ if (csa->solution == SOL_BASIC && !csa->smcp.presolve || csa->solution == SOL_INTEGER && !csa->iocp.presolve) { if (csa->crash == USE_STD_BASIS) glp_std_basis(csa->prob); else if (csa->crash == USE_ADV_BASIS) glp_adv_basis(csa->prob, 0); else if (csa->crash == USE_CPX_BASIS) glp_cpx_basis(csa->prob); else if (csa->crash == USE_INI_BASIS) { ret = glp_read_sol(csa->prob, csa->ini_file); if (ret != 0) { xprintf("Unable to read initial basis\n"); ret = EXIT_FAILURE; goto done; } } else xassert(csa != csa); } /*--------------------------------------------------------------*/ /* solve the problem */ start = xtime(); if (csa->solution == SOL_BASIC) { if (!csa->exact) { glp_set_bfcp(csa->prob, &csa->bfcp); glp_simplex(csa->prob, &csa->smcp); if (csa->xcheck) { if (csa->smcp.presolve && glp_get_status(csa->prob) != GLP_OPT) xprintf("If you need to check final basis for non-opt" "imal solution, use --nopresol\n"); else glp_exact(csa->prob, &csa->smcp); } if (csa->out_sol != NULL || csa->out_res != NULL) { if (csa->smcp.presolve && glp_get_status(csa->prob) != GLP_OPT) xprintf("If you need actual output for non-optimal solut" "ion, use --nopresol\n"); } } else glp_exact(csa->prob, &csa->smcp); } else if (csa->solution == SOL_INTERIOR) glp_interior(csa->prob, &csa->iptcp); #if 1 /* 15/VIII-2011 */ else if (csa->solution == SOL_INTEGER && csa->minisat) { if (glp_check_cnfsat(csa->prob) == 0) glp_minisat1(csa->prob); else glp_intfeas1(csa->prob, csa->use_bnd, csa->obj_bnd); } #endif else if (csa->solution == SOL_INTEGER) { if (!csa->iocp.presolve) { glp_set_bfcp(csa->prob, &csa->bfcp); glp_simplex(csa->prob, &csa->smcp); } #if 0 csa->iocp.msg_lev = GLP_MSG_DBG; csa->iocp.pp_tech = GLP_PP_NONE; #endif glp_intopt(csa->prob, &csa->iocp); } else xassert(csa != csa); /*--------------------------------------------------------------*/ /* display statistics */ xprintf("Time used: %.1f secs\n", xdifftime(xtime(), start)); #if 0 /* 16/II-2012 */ { glp_long tpeak; char buf[50]; glp_mem_usage(NULL, NULL, NULL, &tpeak); xprintf("Memory used: %.1f Mb (%s bytes)\n", xltod(tpeak) / 1048576.0, xltoa(tpeak, buf)); } #else { size_t tpeak; glp_mem_usage(NULL, NULL, NULL, &tpeak); xprintf("Memory used: %.1f Mb (%.0f bytes)\n", (double)tpeak / 1048576.0, (double)tpeak); } #endif /*--------------------------------------------------------------*/ skip: /* postsolve the model, if necessary */ if (csa->tran != NULL) { if (csa->solution == SOL_BASIC) { if (!(glp_get_status(csa->prob) == GLP_OPT || glp_get_status(csa->prob) == GLP_FEAS)) ret = -1; else ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_SOL); } else if (csa->solution == SOL_INTERIOR) { if (!(glp_ipt_status(csa->prob) == GLP_OPT || glp_ipt_status(csa->prob) == GLP_FEAS)) ret = -1; else ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_IPT); } else if (csa->solution == SOL_INTEGER) { if (!(glp_mip_status(csa->prob) == GLP_OPT || glp_mip_status(csa->prob) == GLP_FEAS)) ret = -1; else ret = glp_mpl_postsolve(csa->tran, csa->prob, GLP_MIP); } else xassert(csa != csa); if (ret > 0) { xprintf("Model postsolving error\n"); ret = EXIT_FAILURE; goto done; } } /*--------------------------------------------------------------*/ /* write problem solution in printable format, if required */ if (csa->out_sol != NULL) { if (csa->solution == SOL_BASIC) ret = lpx_print_sol(csa->prob, csa->out_sol); else if (csa->solution == SOL_INTERIOR) ret = lpx_print_ips(csa->prob, csa->out_sol); else if (csa->solution == SOL_INTEGER) ret = lpx_print_mip(csa->prob, csa->out_sol); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to write problem solution\n"); ret = EXIT_FAILURE; goto done; } } /* write problem solution in printable format, if required */ if (csa->out_res != NULL) { if (csa->solution == SOL_BASIC) ret = glp_write_sol(csa->prob, csa->out_res); else if (csa->solution == SOL_INTERIOR) ret = glp_write_ipt(csa->prob, csa->out_res); else if (csa->solution == SOL_INTEGER) ret = glp_write_mip(csa->prob, csa->out_res); else xassert(csa != csa); if (ret != 0) { xprintf("Unable to write problem solution\n"); ret = EXIT_FAILURE; goto done; } } /* write sensitivity analysis report, if required */ if (csa->out_ranges != NULL) { if (csa->solution == SOL_BASIC) { if (glp_get_status(csa->prob) == GLP_OPT) { if (glp_bf_exists(csa->prob)) ranges: { ret = glp_print_ranges(csa->prob, 0, NULL, 0, csa->out_ranges); if (ret != 0) { xprintf("Unable to write sensitivity analysis repo" "rt\n"); ret = EXIT_FAILURE; goto done; } } else { ret = glp_factorize(csa->prob); if (ret == 0) goto ranges; xprintf("Cannot produce sensitivity analysis report d" "ue to error in basis factorization (glp_factorize" " returned %d); try --nopresol\n", ret); } } else xprintf("Cannot produce sensitivity analysis report for " "non-optimal basic solution\n"); } else xprintf("Cannot produce sensitivity analysis report for int" "erior-point or MIP solution\n"); } /*--------------------------------------------------------------*/ /* all seems to be ok */ ret = EXIT_SUCCESS; /*--------------------------------------------------------------*/ done: /* delete the LP/MIP problem object */ if (csa->prob != NULL) glp_delete_prob(csa->prob); /* free the translator workspace, if necessary */ if (csa->tran != NULL) glp_mpl_free_wksp(csa->tran); /* delete the network problem object, if necessary */ if (csa->graph != NULL) glp_delete_graph(csa->graph); xassert(gmp_pool_count() == 0); gmp_free_mem(); /* close log file, if necessary */ if (csa->log_file != NULL) glp_close_tee(); /* check that no memory blocks are still allocated */ #if 0 /* 16/II-2012 */ { int count; glp_long total; glp_mem_usage(&count, NULL, &total, NULL); if (count != 0) xerror("Error: %d memory block(s) were lost\n", count); xassert(count == 0); xassert(total.lo == 0 && total.hi == 0); } #else { int count; size_t total; glp_mem_usage(&count, NULL, &total, NULL); if (count != 0) xerror("Error: %d memory block(s) were lost\n", count); xassert(total == 0); } #endif /* free the GLPK environment */ glp_free_env(); /* return to the control program */ return ret; } /* eof */ glpk-4.52.1/src/glpavl.c0000644000062000006210000002624512175147600014152 0ustar maomkpasswd/* glpavl.c (binary search tree) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpavl.h" #include "env.h" AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1, const void *key2), void *info) { /* create AVL tree */ AVL *tree; tree = xmalloc(sizeof(AVL)); tree->pool = dmp_create_pool(); tree->root = NULL; tree->fcmp = fcmp; tree->info = info; tree->size = 0; tree->height = 0; return tree; } int avl_strcmp(void *info, const void *key1, const void *key2) { /* compare character string keys */ xassert(info == info); return strcmp(key1, key2); } static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node); AVLNODE *avl_insert_node(AVL *tree, const void *key) { /* insert new node into AVL tree */ AVLNODE *p, *q, *r; short int flag; /* find an appropriate point for insertion */ p = NULL; q = tree->root; while (q != NULL) { p = q; if (tree->fcmp(tree->info, key, p->key) <= 0) { flag = 0; q = p->left; p->rank++; } else { flag = 1; q = p->right; } } /* create new node and insert it into the tree */ r = dmp_get_atom(tree->pool, sizeof(AVLNODE)); r->key = key; r->type = 0; r->link = NULL; r->rank = 1; r->up = p; r->flag = (short int)(p == NULL ? 0 : flag); r->bal = 0; r->left = NULL; r->right = NULL; tree->size++; if (p == NULL) tree->root = r; else if (flag == 0) p->left = r; else p->right = r; /* go upstairs to the root and correct all subtrees affected by insertion */ while (p != NULL) { if (flag == 0) { /* the height of the left subtree of [p] is increased */ if (p->bal > 0) { p->bal = 0; break; } if (p->bal < 0) { rotate_subtree(tree, p); break; } p->bal = -1; flag = p->flag; p = p->up; } else { /* the height of the right subtree of [p] is increased */ if (p->bal < 0) { p->bal = 0; break; } if (p->bal > 0) { rotate_subtree(tree, p); break; } p->bal = +1; flag = p->flag; p = p->up; } } /* if the root has been reached, the height of the entire tree is increased */ if (p == NULL) tree->height++; return r; } void avl_set_node_type(AVLNODE *node, int type) { /* assign the type field of specified node */ node->type = type; return; } void avl_set_node_link(AVLNODE *node, void *link) { /* assign the link field of specified node */ node->link = link; return; } AVLNODE *avl_find_node(AVL *tree, const void *key) { /* find node in AVL tree */ AVLNODE *p; int c; p = tree->root; while (p != NULL) { c = tree->fcmp(tree->info, key, p->key); if (c == 0) break; p = (c < 0 ? p->left : p->right); } return p; } int avl_get_node_type(AVLNODE *node) { /* retrieve the type field of specified node */ return node->type; } void *avl_get_node_link(AVLNODE *node) { /* retrieve the link field of specified node */ return node->link; } static AVLNODE *find_next_node(AVL *tree, AVLNODE *node) { /* find next node in AVL tree */ AVLNODE *p, *q; if (tree->root == NULL) return NULL; p = node; q = (p == NULL ? tree->root : p->right); if (q == NULL) { /* go upstairs from the left subtree */ for (;;) { q = p->up; if (q == NULL) break; if (p->flag == 0) break; p = q; } } else { /* go downstairs into the right subtree */ for (;;) { p = q->left; if (p == NULL) break; q = p; } } return q; } void avl_delete_node(AVL *tree, AVLNODE *node) { /* delete specified node from AVL tree */ AVLNODE *f, *p, *q, *r, *s, *x, *y; short int flag; p = node; /* if both subtrees of the specified node are non-empty, the node should be interchanged with the next one, at least one subtree of which is always empty */ if (p->left == NULL || p->right == NULL) goto skip; f = p->up; q = p->left; r = find_next_node(tree, p); s = r->right; if (p->right == r) { if (f == NULL) tree->root = r; else if (p->flag == 0) f->left = r; else f->right = r; r->rank = p->rank; r->up = f; r->flag = p->flag; r->bal = p->bal; r->left = q; r->right = p; q->up = r; p->rank = 1; p->up = r; p->flag = 1; p->bal = (short int)(s == NULL ? 0 : +1); p->left = NULL; p->right = s; if (s != NULL) s->up = p; } else { x = p->right; y = r->up; if (f == NULL) tree->root = r; else if (p->flag == 0) f->left = r; else f->right = r; r->rank = p->rank; r->up = f; r->flag = p->flag; r->bal = p->bal; r->left = q; r->right = x; q->up = r; x->up = r; y->left = p; p->rank = 1; p->up = y; p->flag = 0; p->bal = (short int)(s == NULL ? 0 : +1); p->left = NULL; p->right = s; if (s != NULL) s->up = p; } skip: /* now the specified node [p] has at least one empty subtree; go upstairs to the root and adjust the rank field of all nodes affected by deletion */ q = p; f = q->up; while (f != NULL) { if (q->flag == 0) f->rank--; q = f; f = q->up; } /* delete the specified node from the tree */ f = p->up; flag = p->flag; q = p->left != NULL ? p->left : p->right; if (f == NULL) tree->root = q; else if (flag == 0) f->left = q; else f->right = q; if (q != NULL) q->up = f, q->flag = flag; tree->size--; /* go upstairs to the root and correct all subtrees affected by deletion */ while (f != NULL) { if (flag == 0) { /* the height of the left subtree of [f] is decreased */ if (f->bal == 0) { f->bal = +1; break; } if (f->bal < 0) f->bal = 0; else { f = rotate_subtree(tree, f); if (f->bal < 0) break; } flag = f->flag; f = f->up; } else { /* the height of the right subtree of [f] is decreased */ if (f->bal == 0) { f->bal = -1; break; } if (f->bal > 0) f->bal = 0; else { f = rotate_subtree(tree, f); if (f->bal > 0) break; } flag = f->flag; f = f->up; } } /* if the root has been reached, the height of the entire tree is decreased */ if (f == NULL) tree->height--; /* returns the deleted node to the memory pool */ dmp_free_atom(tree->pool, p, sizeof(AVLNODE)); return; } static AVLNODE *rotate_subtree(AVL *tree, AVLNODE *node) { /* restore balance of AVL subtree */ AVLNODE *f, *p, *q, *r, *x, *y; xassert(node != NULL); p = node; if (p->bal < 0) { /* perform negative (left) rotation */ f = p->up; q = p->left; r = q->right; if (q->bal <= 0) { /* perform single negative rotation */ if (f == NULL) tree->root = q; else if (p->flag == 0) f->left = q; else f->right = q; p->rank -= q->rank; q->up = f; q->flag = p->flag; q->bal++; q->right = p; p->up = q; p->flag = 1; p->bal = (short int)(-q->bal); p->left = r; if (r != NULL) r->up = p, r->flag = 0; node = q; } else { /* perform double negative rotation */ x = r->left; y = r->right; if (f == NULL) tree->root = r; else if (p->flag == 0) f->left = r; else f->right = r; p->rank -= (q->rank + r->rank); r->rank += q->rank; p->bal = (short int)(r->bal >= 0 ? 0 : +1); q->bal = (short int)(r->bal <= 0 ? 0 : -1); r->up = f; r->flag = p->flag; r->bal = 0; r->left = q; r->right = p; p->up = r; p->flag = 1; p->left = y; q->up = r; q->flag = 0; q->right = x; if (x != NULL) x->up = q, x->flag = 1; if (y != NULL) y->up = p, y->flag = 0; node = r; } } else { /* perform positive (right) rotation */ f = p->up; q = p->right; r = q->left; if (q->bal >= 0) { /* perform single positive rotation */ if (f == NULL) tree->root = q; else if (p->flag == 0) f->left = q; else f->right = q; q->rank += p->rank; q->up = f; q->flag = p->flag; q->bal--; q->left = p; p->up = q; p->flag = 0; p->bal = (short int)(-q->bal); p->right = r; if (r != NULL) r->up = p, r->flag = 1; node = q; } else { /* perform double positive rotation */ x = r->left; y = r->right; if (f == NULL) tree->root = r; else if (p->flag == 0) f->left = r; else f->right = r; q->rank -= r->rank; r->rank += p->rank; p->bal = (short int)(r->bal <= 0 ? 0 : -1); q->bal = (short int)(r->bal >= 0 ? 0 : +1); r->up = f; r->flag = p->flag; r->bal = 0; r->left = p; r->right = q; p->up = r; p->flag = 0; p->right = x; q->up = r; q->flag = 1; q->left = y; if (x != NULL) x->up = p, x->flag = 1; if (y != NULL) y->up = q, y->flag = 0; node = r; } } return node; } void avl_delete_tree(AVL *tree) { /* delete AVL tree */ dmp_delete_pool(tree->pool); xfree(tree); return; } /* eof */ glpk-4.52.1/src/glpavl.h0000644000062000006210000001036712175147600014155 0ustar maomkpasswd/* glpavl.h (binary search tree) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPAVL_H #define GLPAVL_H #include "dmp.h" typedef struct AVL AVL; typedef struct AVLNODE AVLNODE; struct AVL { /* AVL tree (Adelson-Velsky & Landis binary search tree) */ DMP *pool; /* memory pool for allocating nodes */ AVLNODE *root; /* pointer to the root node */ int (*fcmp)(void *info, const void *key1, const void *key2); /* application-defined key comparison routine */ void *info; /* transit pointer passed to the routine fcmp */ int size; /* the tree size (the total number of nodes) */ int height; /* the tree height */ }; struct AVLNODE { /* node of AVL tree */ const void *key; /* pointer to the node key (data structure for representing keys is supplied by the application) */ int rank; /* node rank = relative position of the node in its own subtree = the number of nodes in the left subtree plus one */ int type; /* reserved for the application specific information */ void *link; /* reserved for the application specific information */ AVLNODE *up; /* pointer to the parent node */ short int flag; /* node flag: 0 - this node is the left child of its parent (or this node is the root of the tree and has no parent) 1 - this node is the right child of its parent */ short int bal; /* node balance = the difference between heights of the right and left subtrees: -1 - the left subtree is higher than the right one; 0 - the left and right subtrees have the same height; +1 - the left subtree is lower than the right one */ AVLNODE *left; /* pointer to the root of the left subtree */ AVLNODE *right; /* pointer to the root of the right subtree */ }; #define avl_create_tree _glp_avl_create_tree AVL *avl_create_tree(int (*fcmp)(void *info, const void *key1, const void *key2), void *info); /* create AVL tree */ #define avl_strcmp _glp_avl_strcmp int avl_strcmp(void *info, const void *key1, const void *key2); /* compare character string keys */ #define avl_insert_node _glp_avl_insert_node AVLNODE *avl_insert_node(AVL *tree, const void *key); /* insert new node into AVL tree */ #define avl_set_node_type _glp_avl_set_node_type void avl_set_node_type(AVLNODE *node, int type); /* assign the type field of specified node */ #define avl_set_node_link _glp_avl_set_node_link void avl_set_node_link(AVLNODE *node, void *link); /* assign the link field of specified node */ #define avl_find_node _glp_avl_find_node AVLNODE *avl_find_node(AVL *tree, const void *key); /* find node in AVL tree */ #define avl_get_node_type _glp_avl_get_node_type int avl_get_node_type(AVLNODE *node); /* retrieve the type field of specified node */ #define avl_get_node_link _glp_avl_get_node_link void *avl_get_node_link(AVLNODE *node); /* retrieve the link field of specified node */ #define avl_delete_node _glp_avl_delete_node void avl_delete_node(AVL *tree, AVLNODE *node); /* delete specified node from AVL tree */ #define avl_delete_tree _glp_avl_delete_tree void avl_delete_tree(AVL *tree); /* delete AVL tree */ #endif /* eof */ glpk-4.52.1/src/glpbfd.c0000644000062000006210000004027512175147600014122 0ustar maomkpasswd/* glpbfd.c (LP basis factorization driver) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #if 0 /* 27/IV-2013 */ #include "glpfhv.h" #else #include "fhvint.h" #endif #include "glplpf.h" /* CAUTION: DO NOT CHANGE THE LIMIT BELOW */ #define M_MAX 100000000 /* = 100*10^6 */ /* maximal order of the basis matrix */ struct BFD { /* LP basis factorization */ int valid; /* factorization is valid only if this flag is set */ int type; /* factorization type: GLP_BF_FT - LUF + Forrest-Tomlin GLP_BF_BG - LUF + Schur compl. + Bartels-Golub GLP_BF_GR - LUF + Schur compl. + Givens rotation */ #if 0 /* 27/IV-2013 */ FHV *fhv; /* LP basis factorization (GLP_BF_FT) */ #else FHVINT *fi; /* interface to FHV-factorization (GLP_BF_FT) */ #endif LPF *lpf; /* LP basis factorization (GLP_BF_BG, GLP_BF_GR) */ int lu_size; /* luf.sv_size */ double piv_tol; /* luf.piv_tol */ int piv_lim; /* luf.piv_lim */ int suhl; /* luf.suhl */ double eps_tol; /* luf.eps_tol */ double max_gro; /* luf.max_gro */ int nfs_max; /* fhv.hh_max */ double upd_tol; /* fhv.upd_tol */ int nrs_max; /* lpf.n_max */ int rs_size; /* lpf.v_size */ /* internal control parameters */ int upd_lim; /* the factorization update limit */ int upd_cnt; /* the factorization update count */ }; /*********************************************************************** * NAME * * bfd_create_it - create LP basis factorization * * SYNOPSIS * * #include "glpbfd.h" * BFD *bfd_create_it(void); * * DESCRIPTION * * The routine bfd_create_it creates a program object, which represents * a factorization of LP basis. * * RETURNS * * The routine bfd_create_it returns a pointer to the object created. */ BFD *bfd_create_it(void) { BFD *bfd; bfd = xmalloc(sizeof(BFD)); bfd->valid = 0; bfd->type = GLP_BF_FT; #if 0 /* 27/IV-2013 */ bfd->fhv = NULL; #else bfd->fi = NULL; #endif bfd->lpf = NULL; bfd->lu_size = 0; bfd->piv_tol = 0.10; bfd->piv_lim = 4; bfd->suhl = 1; bfd->eps_tol = 1e-15; bfd->max_gro = 1e+10; bfd->nfs_max = 100; bfd->upd_tol = 1e-6; bfd->nrs_max = 100; bfd->rs_size = 1000; bfd->upd_lim = -1; bfd->upd_cnt = 0; return bfd; } /**********************************************************************/ void bfd_set_parm(BFD *bfd, const void *_parm) { /* change LP basis factorization control parameters */ const glp_bfcp *parm = _parm; xassert(bfd != NULL); bfd->type = parm->type; bfd->lu_size = parm->lu_size; bfd->piv_tol = parm->piv_tol; bfd->piv_lim = parm->piv_lim; bfd->suhl = parm->suhl; bfd->eps_tol = parm->eps_tol; bfd->max_gro = parm->max_gro; bfd->nfs_max = parm->nfs_max; bfd->upd_tol = parm->upd_tol; bfd->nrs_max = parm->nrs_max; bfd->rs_size = parm->rs_size; return; } /*********************************************************************** * NAME * * bfd_factorize - compute LP basis factorization * * SYNOPSIS * * #include "glpbfd.h" * int bfd_factorize(BFD *bfd, int m, int bh[], int (*col)(void *info, * int j, int ind[], double val[]), void *info); * * DESCRIPTION * * The routine bfd_factorize computes the factorization of the basis * matrix B specified by the routine col. * * The parameter bfd specified the basis factorization data structure * created with the routine bfd_create_it. * * The parameter m specifies the order of B, m > 0. * * The array bh specifies the basis header: bh[j], 1 <= j <= m, is the * number of j-th column of B in some original matrix. The array bh is * optional and can be specified as NULL. * * The formal routine col specifies the matrix B to be factorized. To * obtain j-th column of A the routine bfd_factorize calls the routine * col with the parameter j (1 <= j <= n). In response the routine col * should store row indices and numerical values of non-zero elements * of j-th column of B to locations ind[1,...,len] and val[1,...,len], * respectively, where len is the number of non-zeros in j-th column * returned on exit. Neither zero nor duplicate elements are allowed. * * The parameter info is a transit pointer passed to the routine col. * * RETURNS * * 0 The factorization has been successfully computed. * * BFD_ESING * The specified matrix is singular within the working precision. * * BFD_ECOND * The specified matrix is ill-conditioned. * * For more details see comments to the routine luf_factorize. */ int bfd_factorize(BFD *bfd, int m, const int bh[], int (*col) (void *info, int j, int ind[], double val[]), void *info) #if 0 /* 06/VI-2013 */ { LUF *luf; #else { #endif int nov, ret; xassert(bfd != NULL); xassert(1 <= m && m <= M_MAX); /* invalidate the factorization */ bfd->valid = 0; /* create the factorization, if necessary */ nov = 0; switch (bfd->type) { case GLP_BF_FT: if (bfd->lpf != NULL) lpf_delete_it(bfd->lpf), bfd->lpf = NULL; #if 0 /* 27/IV-2013 */ if (bfd->fhv == NULL) bfd->fhv = fhv_create_it(), nov = 1; #else if (bfd->fi == NULL) bfd->fi = fhvint_create(), nov = 1; #endif break; case GLP_BF_BG: case GLP_BF_GR: #if 0 /* 27/IV-2013 */ if (bfd->fhv != NULL) fhv_delete_it(bfd->fhv), bfd->fhv = NULL; #else if (bfd->fi != NULL) fhvint_delete(bfd->fi), bfd->fi = NULL; #endif if (bfd->lpf == NULL) bfd->lpf = lpf_create_it(), nov = 1; break; default: xassert(bfd != bfd); } #if 0 /* 06/VI-2013 */ /* set control parameters specific to LUF */ #if 0 /* 27/IV-2013 */ if (bfd->fhv != NULL) luf = bfd->fhv->luf; #else if (bfd->fi != NULL) goto skip; #endif else if (bfd->lpf != NULL) luf = bfd->lpf->luf; else xassert(bfd != bfd); if (nov) luf->new_sva = bfd->lu_size; luf->piv_tol = bfd->piv_tol; luf->piv_lim = bfd->piv_lim; luf->suhl = bfd->suhl; luf->eps_tol = bfd->eps_tol; luf->max_gro = bfd->max_gro; #endif #if 0 /* 27/IV-2013 */ /* set control parameters specific to FHV */ if (bfd->fhv != NULL) { if (nov) bfd->fhv->hh_max = bfd->nfs_max; bfd->fhv->upd_tol = bfd->upd_tol; } #endif /* set control parameters specific to LPF */ if (bfd->lpf != NULL) { if (nov) bfd->lpf->n_max = bfd->nrs_max; if (nov) bfd->lpf->v_size = bfd->rs_size; } #if 0 /* 27/IV-2013 */ /* try to factorize the basis matrix */ if (bfd->fhv != NULL) { switch (fhv_factorize(bfd->fhv, m, col, info)) { case 0: break; case FHV_ESING: ret = BFD_ESING; goto done; case FHV_ECOND: ret = BFD_ECOND; goto done; default: xassert(bfd != bfd); } } #else skip: /* try to factorize the basis matrix */ if (bfd->fi != NULL) { /* FIXME */ if (fhvint_factorize(bfd->fi, m, col, info) != 0) { ret = BFD_ESING; goto done; } /* printf("*** FACTORIZED; m = %d ***\n", m); */ } #endif else if (bfd->lpf != NULL) { switch (lpf_factorize(bfd->lpf, m, bh, col, info)) { case 0: /* set the Schur complement update type */ switch (bfd->type) { case GLP_BF_BG: /* Bartels-Golub update */ bfd->lpf->scf->t_opt = SCF_TBG; break; case GLP_BF_GR: /* Givens rotation update */ bfd->lpf->scf->t_opt = SCF_TGR; break; default: xassert(bfd != bfd); } break; case LPF_ESING: ret = BFD_ESING; goto done; case LPF_ECOND: ret = BFD_ECOND; goto done; default: xassert(bfd != bfd); } } else xassert(bfd != bfd); /* the basis matrix has been successfully factorized */ bfd->valid = 1; bfd->upd_cnt = 0; ret = 0; done: /* return to the calling program */ return ret; } /*********************************************************************** * NAME * * bfd_ftran - perform forward transformation (solve system B*x = b) * * SYNOPSIS * * #include "glpbfd.h" * void bfd_ftran(BFD *bfd, double x[]); * * DESCRIPTION * * The routine bfd_ftran performs forward transformation, i.e. solves * the system B*x = b, where B is the basis matrix, x is the vector of * unknowns to be computed, b is the vector of right-hand sides. * * On entry elements of the vector b should be stored in dense format * in locations x[1], ..., x[m], where m is the number of rows. On exit * the routine stores elements of the vector x in the same locations. */ void bfd_ftran(BFD *bfd, double x[]) { xassert(bfd != NULL); xassert(bfd->valid); #if 0 /* 27/IV-2013 */ if (bfd->fhv != NULL) fhv_ftran(bfd->fhv, x); #else if (bfd->fi != NULL) fhvint_ftran(bfd->fi, x); #endif else if (bfd->lpf != NULL) lpf_ftran(bfd->lpf, x); else xassert(bfd != bfd); return; } /*********************************************************************** * NAME * * bfd_btran - perform backward transformation (solve system B'*x = b) * * SYNOPSIS * * #include "glpbfd.h" * void bfd_btran(BFD *bfd, double x[]); * * DESCRIPTION * * The routine bfd_btran performs backward transformation, i.e. solves * the system B'*x = b, where B' is a matrix transposed to the basis * matrix B, x is the vector of unknowns to be computed, b is the vector * of right-hand sides. * * On entry elements of the vector b should be stored in dense format * in locations x[1], ..., x[m], where m is the number of rows. On exit * the routine stores elements of the vector x in the same locations. */ void bfd_btran(BFD *bfd, double x[]) { xassert(bfd != NULL); xassert(bfd->valid); #if 0 /* 27/IV-2013 */ if (bfd->fhv != NULL) fhv_btran(bfd->fhv, x); #else if (bfd->fi != NULL) fhvint_btran(bfd->fi, x); #endif else if (bfd->lpf != NULL) lpf_btran(bfd->lpf, x); else xassert(bfd != bfd); return; } /*********************************************************************** * NAME * * bfd_update_it - update LP basis factorization * * SYNOPSIS * * #include "glpbfd.h" * int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], * const double val[]); * * DESCRIPTION * * The routine bfd_update_it updates the factorization of the basis * matrix B after replacing its j-th column by a new vector. * * The parameter j specifies the number of column of B, which has been * replaced, 1 <= j <= m, where m is the order of B. * * The parameter bh specifies the basis header entry for the new column * of B, which is the number of the new column in some original matrix. * This parameter is optional and can be specified as 0. * * Row indices and numerical values of non-zero elements of the new * column of B should be placed in locations ind[1], ..., ind[len] and * val[1], ..., val[len], resp., where len is the number of non-zeros * in the column. Neither zero nor duplicate elements are allowed. * * RETURNS * * 0 The factorization has been successfully updated. * * BFD_ESING * New basis matrix is singular within the working precision. * * BFD_ECHECK * The factorization is inaccurate. * * BFD_ELIMIT * Factorization update limit has been reached. * * BFD_EROOM * Overflow of the sparse vector area. * * In case of non-zero return code the factorization becomes invalid. * It should not be used until it has been recomputed with the routine * bfd_factorize. */ int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], const double val[]) { int ret; xassert(bfd != NULL); xassert(bfd->valid); /* try to update the factorization */ #if 0 /* 27/IV-2013 */ if (bfd->fhv != NULL) { switch (fhv_update_it(bfd->fhv, j, len, ind, val)) { case 0: break; case FHV_ESING: bfd->valid = 0; ret = BFD_ESING; goto done; case FHV_ECHECK: bfd->valid = 0; ret = BFD_ECHECK; goto done; case FHV_ELIMIT: bfd->valid = 0; ret = BFD_ELIMIT; goto done; case FHV_EROOM: bfd->valid = 0; ret = BFD_EROOM; goto done; default: xassert(bfd != bfd); } } #else if (bfd->fi != NULL) { /* see fhv_ft_update for return codes */ switch (fhvint_update(bfd->fi, j, len, ind, val)) { case 0: break; case 1: bfd->valid = 0; ret = BFD_ESING; goto done; case 2: case 3: case 5: bfd->valid = 0; ret = BFD_ECHECK; goto done; case 4: bfd->valid = 0; ret = BFD_ELIMIT; goto done; default: xassert(bfd != bfd); } } #endif else if (bfd->lpf != NULL) { switch (lpf_update_it(bfd->lpf, j, bh, len, ind, val)) { case 0: break; case LPF_ESING: bfd->valid = 0; ret = BFD_ESING; goto done; case LPF_ELIMIT: bfd->valid = 0; ret = BFD_ELIMIT; goto done; default: xassert(bfd != bfd); } } else xassert(bfd != bfd); /* the factorization has been successfully updated */ /* increase the update count */ bfd->upd_cnt++; ret = 0; done: /* return to the calling program */ return ret; } /**********************************************************************/ int bfd_get_count(BFD *bfd) { /* determine factorization update count */ xassert(bfd != NULL); xassert(bfd->valid); return bfd->upd_cnt; } /*********************************************************************** * NAME * * bfd_delete_it - delete LP basis factorization * * SYNOPSIS * * #include "glpbfd.h" * void bfd_delete_it(BFD *bfd); * * DESCRIPTION * * The routine bfd_delete_it deletes LP basis factorization specified * by the parameter fhv and frees all memory allocated to this program * object. */ void bfd_delete_it(BFD *bfd) { xassert(bfd != NULL); #if 0 /* 27/IV-2013 */ if (bfd->fhv != NULL) fhv_delete_it(bfd->fhv); #else if (bfd->fi != NULL) fhvint_delete(bfd->fi); #endif if (bfd->lpf != NULL) lpf_delete_it(bfd->lpf); xfree(bfd); return; } /* eof */ glpk-4.52.1/src/glpbfd.h0000644000062000006210000000502112175147600014115 0ustar maomkpasswd/* glpbfd.h (LP basis factorization driver) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPBFD_H #define GLPBFD_H typedef struct BFD BFD; /* return codes: */ #define BFD_ESING 1 /* singular matrix */ #define BFD_ECOND 2 /* ill-conditioned matrix */ #define BFD_ECHECK 3 /* insufficient accuracy */ #define BFD_ELIMIT 4 /* update limit reached */ #define BFD_EROOM 5 /* SVA overflow */ #define bfd_create_it _glp_bfd_create_it BFD *bfd_create_it(void); /* create LP basis factorization */ #define bfd_set_parm _glp_bfd_set_parm void bfd_set_parm(BFD *bfd, const void *parm); /* change LP basis factorization control parameters */ #define bfd_factorize _glp_bfd_factorize int bfd_factorize(BFD *bfd, int m, const int bh[], int (*col) (void *info, int j, int ind[], double val[]), void *info); /* compute LP basis factorization */ #define bfd_ftran _glp_bfd_ftran void bfd_ftran(BFD *bfd, double x[]); /* perform forward transformation (solve system B*x = b) */ #define bfd_btran _glp_bfd_btran void bfd_btran(BFD *bfd, double x[]); /* perform backward transformation (solve system B'*x = b) */ #define bfd_update_it _glp_bfd_update_it int bfd_update_it(BFD *bfd, int j, int bh, int len, const int ind[], const double val[]); /* update LP basis factorization */ #define bfd_get_count _glp_bfd_get_count int bfd_get_count(BFD *bfd); /* determine factorization update count */ #define bfd_delete_it _glp_bfd_delete_it void bfd_delete_it(BFD *bfd); /* delete LP basis factorization */ #endif /* eof */ glpk-4.52.1/src/glpbfx.c0000644000062000006210000000514412175147600014142 0ustar maomkpasswd/* glpbfx.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ typedef struct BFX BFX; #define GLPBFX_DEFINED #include "glpbfx.h" #include "env.h" #include "glplux.h" struct BFX { int valid; LUX *lux; }; BFX *bfx_create_binv(void) { /* create factorization of the basis matrix */ BFX *bfx; bfx = xmalloc(sizeof(BFX)); bfx->valid = 0; bfx->lux = NULL; return bfx; } int bfx_factorize(BFX *binv, int m, int (*col)(void *info, int j, int ind[], mpq_t val[]), void *info) { /* compute factorization of the basis matrix */ int ret; xassert(m > 0); if (binv->lux != NULL && binv->lux->n != m) { lux_delete(binv->lux); binv->lux = NULL; } if (binv->lux == NULL) binv->lux = lux_create(m); ret = lux_decomp(binv->lux, col, info); binv->valid = (ret == 0); return ret; } void bfx_ftran(BFX *binv, mpq_t x[], int save) { /* perform forward transformation (FTRAN) */ xassert(binv->valid); lux_solve(binv->lux, 0, x); xassert(save == save); return; } void bfx_btran(BFX *binv, mpq_t x[]) { /* perform backward transformation (BTRAN) */ xassert(binv->valid); lux_solve(binv->lux, 1, x); return; } int bfx_update(BFX *binv, int j) { /* update factorization of the basis matrix */ xassert(binv->valid); xassert(1 <= j && j <= binv->lux->n); return 1; } void bfx_delete_binv(BFX *binv) { /* delete factorization of the basis matrix */ if (binv->lux != NULL) lux_delete(binv->lux); xfree(binv); return; } /* eof */ glpk-4.52.1/src/glpbfx.h0000644000062000006210000000457112175147600014152 0ustar maomkpasswd/* glpbfx.h (basis factorization interface, bignum arithmetic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPBFX_H #define GLPBFX_H #include "glpgmp.h" #ifndef GLPBFX_DEFINED #define GLPBFX_DEFINED typedef struct { double _opaque_bfx; } BFX; #endif #define bfx_create_binv _glp_bfx_create_binv #define bfx_is_valid _glp_bfx_is_valid #define bfx_invalidate _glp_bfx_invalidate #define bfx_factorize _glp_bfx_factorize #define bfx_ftran _glp_bfx_ftran #define bfx_btran _glp_bfx_btran #define bfx_update _glp_bfx_update #define bfx_delete_binv _glp_bfx_delete_binv BFX *bfx_create_binv(void); /* create factorization of the basis matrix */ int bfx_is_valid(BFX *binv); /* check if factorization is valid */ void bfx_invalidate(BFX *binv); /* invalidate factorization of the basis matrix */ int bfx_factorize(BFX *binv, int m, int (*col)(void *info, int j, int ind[], mpq_t val[]), void *info); /* compute factorization of the basis matrix */ void bfx_ftran(BFX *binv, mpq_t x[], int save); /* perform forward transformation (FTRAN) */ void bfx_btran(BFX *binv, mpq_t x[]); /* perform backward transformation (BTRAN) */ int bfx_update(BFX *binv, int j); /* update factorization of the basis matrix */ void bfx_delete_binv(BFX *binv); /* delete factorization of the basis matrix */ #endif /* eof */ glpk-4.52.1/src/glpcpx.c0000644000062000006210000012553712175147600014166 0ustar maomkpasswd/* glpcpx.c (CPLEX LP format routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #if 1 /* 11/VI-2013 */ #include "env2.h" #endif #include "glpapi.h" #include "glplib.h" /*********************************************************************** * NAME * * glp_init_cpxcp - initialize CPLEX LP format control parameters * * SYNOPSIS * * void glp_init_cpxcp(glp_cpxcp *parm): * * The routine glp_init_cpxcp initializes control parameters used by * the CPLEX LP input/output routines glp_read_lp and glp_write_lp with * default values. * * Default values of the control parameters are stored in the glp_cpxcp * structure, which the parameter parm points to. */ void glp_init_cpxcp(glp_cpxcp *parm) { xassert(parm != NULL); return; } static void check_parm(const char *func, const glp_cpxcp *parm) { /* check control parameters */ xassert(func != NULL); xassert(parm != NULL); return; } /*********************************************************************** * NAME * * glp_read_lp - read problem data in CPLEX LP format * * SYNOPSIS * * int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char * *fname); * * DESCRIPTION * * The routine glp_read_lp reads problem data in CPLEX LP format from * a text file. * * The parameter parm is a pointer to the structure glp_cpxcp, which * specifies control parameters used by the routine. If parm is NULL, * the routine uses default settings. * * The character string fname specifies a name of the text file to be * read. * * Note that before reading data the current content of the problem * object is completely erased with the routine glp_erase_prob. * * RETURNS * * If the operation was successful, the routine glp_read_lp returns * zero. Otherwise, it prints an error message and returns non-zero. */ struct csa { /* common storage area */ glp_prob *P; /* LP/MIP problem object */ const glp_cpxcp *parm; /* pointer to control parameters */ const char *fname; /* name of input CPLEX LP file */ XFILE *fp; /* stream assigned to input CPLEX LP file */ jmp_buf jump; /* label for go to in case of error */ int count; /* line count */ int c; /* current character or XEOF */ int token; /* current token: */ #define T_EOF 0x00 /* end of file */ #define T_MINIMIZE 0x01 /* keyword 'minimize' */ #define T_MAXIMIZE 0x02 /* keyword 'maximize' */ #define T_SUBJECT_TO 0x03 /* keyword 'subject to' */ #define T_BOUNDS 0x04 /* keyword 'bounds' */ #define T_GENERAL 0x05 /* keyword 'general' */ #define T_INTEGER 0x06 /* keyword 'integer' */ #define T_BINARY 0x07 /* keyword 'binary' */ #define T_END 0x08 /* keyword 'end' */ #define T_NAME 0x09 /* symbolic name */ #define T_NUMBER 0x0A /* numeric constant */ #define T_PLUS 0x0B /* delimiter '+' */ #define T_MINUS 0x0C /* delimiter '-' */ #define T_COLON 0x0D /* delimiter ':' */ #define T_LE 0x0E /* delimiter '<=' */ #define T_GE 0x0F /* delimiter '>=' */ #define T_EQ 0x10 /* delimiter '=' */ char image[255+1]; /* image of current token */ int imlen; /* length of token image */ double value; /* value of numeric constant */ int n_max; /* length of the following five arrays (enlarged automatically, if necessary) */ int *ind; /* int ind[1+n_max]; */ double *val; /* double val[1+n_max]; */ char *flag; /* char flag[1+n_max]; */ /* working arrays used to construct linear forms */ double *lb; /* double lb[1+n_max]; */ double *ub; /* double ub[1+n_max]; */ /* lower and upper bounds of variables (columns) */ #if 1 /* 27/VII-2013 */ int lb_warn, ub_warn; /* warning 'lower/upper bound redefined' already issued */ #endif }; #define CHAR_SET "!\"#$%&()/,.;?@_`'{}|~" /* characters, which may appear in symbolic names */ static void error(struct csa *csa, const char *fmt, ...) { /* print error message and terminate processing */ va_list arg; xprintf("%s:%d: ", csa->fname, csa->count); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); longjmp(csa->jump, 1); /* no return */ } static void warning(struct csa *csa, const char *fmt, ...) { /* print warning message and continue processing */ va_list arg; xprintf("%s:%d: warning: ", csa->fname, csa->count); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); return; } static void read_char(struct csa *csa) { /* read next character from input file */ int c; xassert(csa->c != XEOF); if (csa->c == '\n') csa->count++; c = xfgetc(csa->fp); if (c < 0) { if (xferror(csa->fp)) error(csa, "read error - %s\n", xerrmsg()); else if (csa->c == '\n') { csa->count--; c = XEOF; } else { warning(csa, "missing final end of line\n"); c = '\n'; } } else if (c == '\n') ; else if (isspace(c)) c = ' '; else if (iscntrl(c)) error(csa, "invalid control character 0x%02X\n", c); csa->c = c; return; } static void add_char(struct csa *csa) { /* append current character to current token */ if (csa->imlen == sizeof(csa->image)-1) error(csa, "token '%.15s...' too long\n", csa->image); csa->image[csa->imlen++] = (char)csa->c; csa->image[csa->imlen] = '\0'; read_char(csa); return; } static int the_same(char *s1, char *s2) { /* compare two character strings ignoring case sensitivity */ for (; *s1 != '\0'; s1++, s2++) { if (tolower((unsigned char)*s1) != tolower((unsigned char)*s2)) return 0; } return 1; } static void scan_token(struct csa *csa) { /* scan next token */ int flag; csa->token = -1; csa->image[0] = '\0'; csa->imlen = 0; csa->value = 0.0; loop: flag = 0; /* skip non-significant characters */ while (csa->c == ' ') read_char(csa); /* recognize and scan current token */ if (csa->c == XEOF) csa->token = T_EOF; else if (csa->c == '\n') { read_char(csa); /* if the next character is letter, it may begin a keyword */ if (isalpha(csa->c)) { flag = 1; goto name; } goto loop; } else if (csa->c == '\\') { /* comment; ignore everything until end-of-line */ while (csa->c != '\n') read_char(csa); goto loop; } else if (isalpha(csa->c) || csa->c != '.' && strchr(CHAR_SET, csa->c) != NULL) name: { /* symbolic name */ csa->token = T_NAME; while (isalnum(csa->c) || strchr(CHAR_SET, csa->c) != NULL) add_char(csa); if (flag) { /* check for keyword */ if (the_same(csa->image, "minimize")) csa->token = T_MINIMIZE; else if (the_same(csa->image, "minimum")) csa->token = T_MINIMIZE; else if (the_same(csa->image, "min")) csa->token = T_MINIMIZE; else if (the_same(csa->image, "maximize")) csa->token = T_MAXIMIZE; else if (the_same(csa->image, "maximum")) csa->token = T_MAXIMIZE; else if (the_same(csa->image, "max")) csa->token = T_MAXIMIZE; else if (the_same(csa->image, "subject")) { if (csa->c == ' ') { read_char(csa); if (tolower(csa->c) == 't') { csa->token = T_SUBJECT_TO; csa->image[csa->imlen++] = ' '; csa->image[csa->imlen] = '\0'; add_char(csa); if (tolower(csa->c) != 'o') error(csa, "keyword 'subject to' incomplete\n"); add_char(csa); if (isalpha(csa->c)) error(csa, "keyword '%s%c...' not recognized\n", csa->image, csa->c); } } } else if (the_same(csa->image, "such")) { if (csa->c == ' ') { read_char(csa); if (tolower(csa->c) == 't') { csa->token = T_SUBJECT_TO; csa->image[csa->imlen++] = ' '; csa->image[csa->imlen] = '\0'; add_char(csa); if (tolower(csa->c) != 'h') err: error(csa, "keyword 'such that' incomplete\n"); add_char(csa); if (tolower(csa->c) != 'a') goto err; add_char(csa); if (tolower(csa->c) != 't') goto err; add_char(csa); if (isalpha(csa->c)) error(csa, "keyword '%s%c...' not recognized\n", csa->image, csa->c); } } } else if (the_same(csa->image, "st")) csa->token = T_SUBJECT_TO; else if (the_same(csa->image, "s.t.")) csa->token = T_SUBJECT_TO; else if (the_same(csa->image, "st.")) csa->token = T_SUBJECT_TO; else if (the_same(csa->image, "bounds")) csa->token = T_BOUNDS; else if (the_same(csa->image, "bound")) csa->token = T_BOUNDS; else if (the_same(csa->image, "general")) csa->token = T_GENERAL; else if (the_same(csa->image, "generals")) csa->token = T_GENERAL; else if (the_same(csa->image, "gen")) csa->token = T_GENERAL; else if (the_same(csa->image, "integer")) csa->token = T_INTEGER; else if (the_same(csa->image, "integers")) csa->token = T_INTEGER; else if (the_same(csa->image, "int")) csa->token = T_INTEGER; else if (the_same(csa->image, "binary")) csa->token = T_BINARY; else if (the_same(csa->image, "binaries")) csa->token = T_BINARY; else if (the_same(csa->image, "bin")) csa->token = T_BINARY; else if (the_same(csa->image, "end")) csa->token = T_END; } } else if (isdigit(csa->c) || csa->c == '.') { /* numeric constant */ csa->token = T_NUMBER; /* scan integer part */ while (isdigit(csa->c)) add_char(csa); /* scan optional fractional part (it is mandatory, if there is no integer part) */ if (csa->c == '.') { add_char(csa); if (csa->imlen == 1 && !isdigit(csa->c)) error(csa, "invalid use of decimal point\n"); while (isdigit(csa->c)) add_char(csa); } /* scan optional decimal exponent */ if (csa->c == 'e' || csa->c == 'E') { add_char(csa); if (csa->c == '+' || csa->c == '-') add_char(csa); if (!isdigit(csa->c)) error(csa, "numeric constant '%s' incomplete\n", csa->image); while (isdigit(csa->c)) add_char(csa); } /* convert the numeric constant to floating-point */ if (str2num(csa->image, &csa->value)) error(csa, "numeric constant '%s' out of range\n", csa->image); } else if (csa->c == '+') csa->token = T_PLUS, add_char(csa); else if (csa->c == '-') csa->token = T_MINUS, add_char(csa); else if (csa->c == ':') csa->token = T_COLON, add_char(csa); else if (csa->c == '<') { csa->token = T_LE, add_char(csa); if (csa->c == '=') add_char(csa); } else if (csa->c == '>') { csa->token = T_GE, add_char(csa); if (csa->c == '=') add_char(csa); } else if (csa->c == '=') { csa->token = T_EQ, add_char(csa); if (csa->c == '<') csa->token = T_LE, add_char(csa); else if (csa->c == '>') csa->token = T_GE, add_char(csa); } else error(csa, "character '%c' not recognized\n", csa->c); /* skip non-significant characters */ while (csa->c == ' ') read_char(csa); return; } static int find_col(struct csa *csa, char *name) { /* find column by its symbolic name */ int j; j = glp_find_col(csa->P, name); if (j == 0) { /* not found; create new column */ j = glp_add_cols(csa->P, 1); glp_set_col_name(csa->P, j, name); /* enlarge working arrays, if necessary */ if (csa->n_max < j) { int n_max = csa->n_max; int *ind = csa->ind; double *val = csa->val; char *flag = csa->flag; double *lb = csa->lb; double *ub = csa->ub; csa->n_max += csa->n_max; csa->ind = xcalloc(1+csa->n_max, sizeof(int)); memcpy(&csa->ind[1], &ind[1], n_max * sizeof(int)); xfree(ind); csa->val = xcalloc(1+csa->n_max, sizeof(double)); memcpy(&csa->val[1], &val[1], n_max * sizeof(double)); xfree(val); csa->flag = xcalloc(1+csa->n_max, sizeof(char)); memset(&csa->flag[1], 0, csa->n_max * sizeof(char)); memcpy(&csa->flag[1], &flag[1], n_max * sizeof(char)); xfree(flag); csa->lb = xcalloc(1+csa->n_max, sizeof(double)); memcpy(&csa->lb[1], &lb[1], n_max * sizeof(double)); xfree(lb); csa->ub = xcalloc(1+csa->n_max, sizeof(double)); memcpy(&csa->ub[1], &ub[1], n_max * sizeof(double)); xfree(ub); } csa->lb[j] = +DBL_MAX, csa->ub[j] = -DBL_MAX; } return j; } /*********************************************************************** * parse_linear_form - parse linear form * * This routine parses the linear form using the following syntax: * * ::= * ::= * ::= | * ::= | + | - | * + | - * * The routine returns the number of terms in the linear form. */ static int parse_linear_form(struct csa *csa) { int j, k, len = 0, newlen; double s, coef; loop: /* parse an optional sign */ if (csa->token == T_PLUS) s = +1.0, scan_token(csa); else if (csa->token == T_MINUS) s = -1.0, scan_token(csa); else s = +1.0; /* parse an optional coefficient */ if (csa->token == T_NUMBER) coef = csa->value, scan_token(csa); else coef = 1.0; /* parse a variable name */ if (csa->token != T_NAME) error(csa, "missing variable name\n"); /* find the corresponding column */ j = find_col(csa, csa->image); /* check if the variable is already used in the linear form */ if (csa->flag[j]) error(csa, "multiple use of variable '%s' not allowed\n", csa->image); /* add new term to the linear form */ len++, csa->ind[len] = j, csa->val[len] = s * coef; /* and mark that the variable is used in the linear form */ csa->flag[j] = 1; scan_token(csa); /* if the next token is a sign, there is another term */ if (csa->token == T_PLUS || csa->token == T_MINUS) goto loop; /* clear marks of the variables used in the linear form */ for (k = 1; k <= len; k++) csa->flag[csa->ind[k]] = 0; /* remove zero coefficients */ newlen = 0; for (k = 1; k <= len; k++) { if (csa->val[k] != 0.0) { newlen++; csa->ind[newlen] = csa->ind[k]; csa->val[newlen] = csa->val[k]; } } return newlen; } /*********************************************************************** * parse_objective - parse objective function * * This routine parses definition of the objective function using the * following syntax: * * ::= minimize | minimum | min | maximize | maximum | max * ::= | : * ::= */ static void parse_objective(struct csa *csa) { /* parse objective sense */ int k, len; /* parse the keyword 'minimize' or 'maximize' */ if (csa->token == T_MINIMIZE) glp_set_obj_dir(csa->P, GLP_MIN); else if (csa->token == T_MAXIMIZE) glp_set_obj_dir(csa->P, GLP_MAX); else xassert(csa != csa); scan_token(csa); /* parse objective name */ if (csa->token == T_NAME && csa->c == ':') { /* objective name is followed by a colon */ glp_set_obj_name(csa->P, csa->image); scan_token(csa); xassert(csa->token == T_COLON); scan_token(csa); } else { /* objective name is not specified; use default */ glp_set_obj_name(csa->P, "obj"); } /* parse linear form */ len = parse_linear_form(csa); for (k = 1; k <= len; k++) glp_set_obj_coef(csa->P, csa->ind[k], csa->val[k]); return; } /*********************************************************************** * parse_constraints - parse constraints section * * This routine parses the constraints section using the following * syntax: * * ::= | : * ::= < | <= | =< | > | >= | => | = * ::= | + | * - * ::= * * ::= subject to | such that | st | s.t. | st. * ::= | * */ static void parse_constraints(struct csa *csa) { int i, len, type; double s; /* parse the keyword 'subject to' */ xassert(csa->token == T_SUBJECT_TO); scan_token(csa); loop: /* create new row (constraint) */ i = glp_add_rows(csa->P, 1); /* parse row name */ if (csa->token == T_NAME && csa->c == ':') { /* row name is followed by a colon */ if (glp_find_row(csa->P, csa->image) != 0) error(csa, "constraint '%s' multiply defined\n", csa->image); glp_set_row_name(csa->P, i, csa->image); scan_token(csa); xassert(csa->token == T_COLON); scan_token(csa); } else { /* row name is not specified; use default */ char name[50]; sprintf(name, "r.%d", csa->count); glp_set_row_name(csa->P, i, name); } /* parse linear form */ len = parse_linear_form(csa); glp_set_mat_row(csa->P, i, len, csa->ind, csa->val); /* parse constraint sense */ if (csa->token == T_LE) type = GLP_UP, scan_token(csa); else if (csa->token == T_GE) type = GLP_LO, scan_token(csa); else if (csa->token == T_EQ) type = GLP_FX, scan_token(csa); else error(csa, "missing constraint sense\n"); /* parse right-hand side */ if (csa->token == T_PLUS) s = +1.0, scan_token(csa); else if (csa->token == T_MINUS) s = -1.0, scan_token(csa); else s = +1.0; if (csa->token != T_NUMBER) error(csa, "missing right-hand side\n"); glp_set_row_bnds(csa->P, i, type, s * csa->value, s * csa->value); /* the rest of the current line must be empty */ if (!(csa->c == '\n' || csa->c == XEOF)) error(csa, "invalid symbol(s) beyond right-hand side\n"); scan_token(csa); /* if the next token is a sign, numeric constant, or a symbolic name, here is another constraint */ if (csa->token == T_PLUS || csa->token == T_MINUS || csa->token == T_NUMBER || csa->token == T_NAME) goto loop; return; } static void set_lower_bound(struct csa *csa, int j, double lb) { /* set lower bound of j-th variable */ if (csa->lb[j] != +DBL_MAX && !csa->lb_warn) { warning(csa, "lower bound of variable '%s' redefined\n", glp_get_col_name(csa->P, j)); csa->lb_warn = 1; } csa->lb[j] = lb; return; } static void set_upper_bound(struct csa *csa, int j, double ub) { /* set upper bound of j-th variable */ if (csa->ub[j] != -DBL_MAX && !csa->ub_warn) { warning(csa, "upper bound of variable '%s' redefined\n", glp_get_col_name(csa->P, j)); csa->ub_warn = 1; } csa->ub[j] = ub; return; } /*********************************************************************** * parse_bounds - parse bounds section * * This routine parses the bounds section using the following syntax: * * ::= * ::= infinity | inf * ::= | + | * - | + | - * ::= < | <= | =< * ::= > | >= | => * ::= | * | | * | = | free * ::= bounds | bound * ::= | * */ static void parse_bounds(struct csa *csa) { int j, lb_flag; double lb, s; /* parse the keyword 'bounds' */ xassert(csa->token == T_BOUNDS); scan_token(csa); loop: /* bound definition can start with a sign, numeric constant, or a symbolic name */ if (!(csa->token == T_PLUS || csa->token == T_MINUS || csa->token == T_NUMBER || csa->token == T_NAME)) goto done; /* parse bound definition */ if (csa->token == T_PLUS || csa->token == T_MINUS) { /* parse signed lower bound */ lb_flag = 1; s = (csa->token == T_PLUS ? +1.0 : -1.0); scan_token(csa); if (csa->token == T_NUMBER) lb = s * csa->value, scan_token(csa); else if (the_same(csa->image, "infinity") || the_same(csa->image, "inf")) { if (s > 0.0) error(csa, "invalid use of '+inf' as lower bound\n"); lb = -DBL_MAX, scan_token(csa); } else error(csa, "missing lower bound\n"); } else if (csa->token == T_NUMBER) { /* parse unsigned lower bound */ lb_flag = 1; lb = csa->value, scan_token(csa); } else { /* lower bound is not specified */ lb_flag = 0; } /* parse the token that should follow the lower bound */ if (lb_flag) { if (csa->token != T_LE) error(csa, "missing '<', '<=', or '=<' after lower bound\n") ; scan_token(csa); } /* parse variable name */ if (csa->token != T_NAME) error(csa, "missing variable name\n"); j = find_col(csa, csa->image); /* set lower bound */ if (lb_flag) set_lower_bound(csa, j, lb); scan_token(csa); /* parse the context that follows the variable name */ if (csa->token == T_LE) { /* parse upper bound */ scan_token(csa); if (csa->token == T_PLUS || csa->token == T_MINUS) { /* parse signed upper bound */ s = (csa->token == T_PLUS ? +1.0 : -1.0); scan_token(csa); if (csa->token == T_NUMBER) { set_upper_bound(csa, j, s * csa->value); scan_token(csa); } else if (the_same(csa->image, "infinity") || the_same(csa->image, "inf")) { if (s < 0.0) error(csa, "invalid use of '-inf' as upper bound\n"); set_upper_bound(csa, j, +DBL_MAX); scan_token(csa); } else error(csa, "missing upper bound\n"); } else if (csa->token == T_NUMBER) { /* parse unsigned upper bound */ set_upper_bound(csa, j, csa->value); scan_token(csa); } else error(csa, "missing upper bound\n"); } else if (csa->token == T_GE) { /* parse lower bound */ if (lb_flag) { /* the context '... <= x >= ...' is invalid */ error(csa, "invalid bound definition\n"); } scan_token(csa); if (csa->token == T_PLUS || csa->token == T_MINUS) { /* parse signed lower bound */ s = (csa->token == T_PLUS ? +1.0 : -1.0); scan_token(csa); if (csa->token == T_NUMBER) { set_lower_bound(csa, j, s * csa->value); scan_token(csa); } else if (the_same(csa->image, "infinity") || the_same(csa->image, "inf") == 0) { if (s > 0.0) error(csa, "invalid use of '+inf' as lower bound\n"); set_lower_bound(csa, j, -DBL_MAX); scan_token(csa); } else error(csa, "missing lower bound\n"); } else if (csa->token == T_NUMBER) { /* parse unsigned lower bound */ set_lower_bound(csa, j, csa->value); scan_token(csa); } else error(csa, "missing lower bound\n"); } else if (csa->token == T_EQ) { /* parse fixed value */ if (lb_flag) { /* the context '... <= x = ...' is invalid */ error(csa, "invalid bound definition\n"); } scan_token(csa); if (csa->token == T_PLUS || csa->token == T_MINUS) { /* parse signed fixed value */ s = (csa->token == T_PLUS ? +1.0 : -1.0); scan_token(csa); if (csa->token == T_NUMBER) { set_lower_bound(csa, j, s * csa->value); set_upper_bound(csa, j, s * csa->value); scan_token(csa); } else error(csa, "missing fixed value\n"); } else if (csa->token == T_NUMBER) { /* parse unsigned fixed value */ set_lower_bound(csa, j, csa->value); set_upper_bound(csa, j, csa->value); scan_token(csa); } else error(csa, "missing fixed value\n"); } else if (the_same(csa->image, "free")) { /* parse the keyword 'free' */ if (lb_flag) { /* the context '... <= x free ...' is invalid */ error(csa, "invalid bound definition\n"); } set_lower_bound(csa, j, -DBL_MAX); set_upper_bound(csa, j, +DBL_MAX); scan_token(csa); } else if (!lb_flag) { /* neither lower nor upper bounds are specified */ error(csa, "invalid bound definition\n"); } goto loop; done: return; } /*********************************************************************** * parse_integer - parse general, integer, or binary section * * ::= * ::= general | generals | gen * ::= integer | integers | int * ::= binary | binaries | bin *

::= * ::=
| * */ static void parse_integer(struct csa *csa) { int j, binary; /* parse the keyword 'general', 'integer', or 'binary' */ if (csa->token == T_GENERAL) binary = 0, scan_token(csa); else if (csa->token == T_INTEGER) binary = 0, scan_token(csa); else if (csa->token == T_BINARY) binary = 1, scan_token(csa); else xassert(csa != csa); /* parse list of variables (may be empty) */ while (csa->token == T_NAME) { /* find the corresponding column */ j = find_col(csa, csa->image); /* change kind of the variable */ glp_set_col_kind(csa->P, j, GLP_IV); /* set 0-1 bounds for the binary variable */ if (binary) { set_lower_bound(csa, j, 0.0); set_upper_bound(csa, j, 1.0); } scan_token(csa); } return; } int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname) { /* read problem data in CPLEX LP format */ glp_cpxcp _parm; struct csa _csa, *csa = &_csa; int ret; xprintf("Reading problem data from '%s'...\n", fname); if (parm == NULL) glp_init_cpxcp(&_parm), parm = &_parm; /* check control parameters */ check_parm("glp_read_lp", parm); /* initialize common storage area */ csa->P = P; csa->parm = parm; csa->fname = fname; csa->fp = NULL; if (setjmp(csa->jump)) { ret = 1; goto done; } csa->count = 0; csa->c = '\n'; csa->token = T_EOF; csa->image[0] = '\0'; csa->imlen = 0; csa->value = 0.0; csa->n_max = 100; csa->ind = xcalloc(1+csa->n_max, sizeof(int)); csa->val = xcalloc(1+csa->n_max, sizeof(double)); csa->flag = xcalloc(1+csa->n_max, sizeof(char)); memset(&csa->flag[1], 0, csa->n_max * sizeof(char)); csa->lb = xcalloc(1+csa->n_max, sizeof(double)); csa->ub = xcalloc(1+csa->n_max, sizeof(double)); #if 1 /* 27/VII-2013 */ csa->lb_warn = csa->ub_warn = 0; #endif /* erase problem object */ glp_erase_prob(P); glp_create_index(P); /* open input CPLEX LP file */ csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open '%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* scan very first token */ scan_token(csa); /* parse definition of the objective function */ if (!(csa->token == T_MINIMIZE || csa->token == T_MAXIMIZE)) error(csa, "'minimize' or 'maximize' keyword missing\n"); parse_objective(csa); /* parse constraints section */ if (csa->token != T_SUBJECT_TO) error(csa, "constraints section missing\n"); parse_constraints(csa); /* parse optional bounds section */ if (csa->token == T_BOUNDS) parse_bounds(csa); /* parse optional general, integer, and binary sections */ while (csa->token == T_GENERAL || csa->token == T_INTEGER || csa->token == T_BINARY) parse_integer(csa); /* check for the keyword 'end' */ if (csa->token == T_END) scan_token(csa); else if (csa->token == T_EOF) warning(csa, "keyword 'end' missing\n"); else error(csa, "symbol '%s' in wrong position\n", csa->image); /* nothing must follow the keyword 'end' (except comments) */ if (csa->token != T_EOF) error(csa, "extra symbol(s) detected beyond 'end'\n"); /* set bounds of variables */ { int j, type; double lb, ub; for (j = 1; j <= P->n; j++) { lb = csa->lb[j]; ub = csa->ub[j]; if (lb == +DBL_MAX) lb = 0.0; /* default lb */ if (ub == -DBL_MAX) ub = +DBL_MAX; /* default ub */ if (lb == -DBL_MAX && ub == +DBL_MAX) type = GLP_FR; else if (ub == +DBL_MAX) type = GLP_LO; else if (lb == -DBL_MAX) type = GLP_UP; else if (lb != ub) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(csa->P, j, type, lb, ub); } } /* print some statistics */ xprintf("%d row%s, %d column%s, %d non-zero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", P->nnz, P->nnz == 1 ? "" : "s"); if (glp_get_num_int(P) > 0) { int ni = glp_get_num_int(P); int nb = glp_get_num_bin(P); if (ni == 1) { if (nb == 0) xprintf("One variable is integer\n"); else xprintf("One variable is binary\n"); } else { xprintf("%d integer variables, ", ni); if (nb == 0) xprintf("none"); else if (nb == 1) xprintf("one"); else if (nb == ni) xprintf("all"); else xprintf("%d", nb); xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); } } xprintf("%d lines were read\n", csa->count); /* problem data has been successfully read */ glp_delete_index(P); glp_sort_matrix(P); ret = 0; done: if (csa->fp != NULL) xfclose(csa->fp); xfree(csa->ind); xfree(csa->val); xfree(csa->flag); xfree(csa->lb); xfree(csa->ub); if (ret != 0) glp_erase_prob(P); return ret; } /*********************************************************************** * NAME * * glp_write_lp - write problem data in CPLEX LP format * * SYNOPSIS * * int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char * *fname); * * DESCRIPTION * * The routine glp_write_lp writes problem data in CPLEX LP format to * a text file. * * The parameter parm is a pointer to the structure glp_cpxcp, which * specifies control parameters used by the routine. If parm is NULL, * the routine uses default settings. * * The character string fname specifies a name of the text file to be * written. * * RETURNS * * If the operation was successful, the routine glp_write_lp returns * zero. Otherwise, it prints an error message and returns non-zero. */ #define csa csa1 struct csa { /* common storage area */ glp_prob *P; /* pointer to problem object */ const glp_cpxcp *parm; /* pointer to control parameters */ }; static int check_name(char *name) { /* check if specified name is valid for CPLEX LP format */ if (*name == '.') return 1; if (isdigit((unsigned char)*name)) return 1; for (; *name; name++) { if (!isalnum((unsigned char)*name) && strchr(CHAR_SET, (unsigned char)*name) == NULL) return 1; } return 0; /* name is ok */ } static void adjust_name(char *name) { /* attempt to adjust specified name to make it valid for CPLEX LP format */ for (; *name; name++) { if (*name == ' ') *name = '_'; else if (*name == '-') *name = '~'; else if (*name == '[') *name = '('; else if (*name == ']') *name = ')'; } return; } static char *row_name(struct csa *csa, int i, char rname[255+1]) { /* construct symbolic name of i-th row (constraint) */ const char *name; if (i == 0) name = glp_get_obj_name(csa->P); else name = glp_get_row_name(csa->P, i); if (name == NULL) goto fake; strcpy(rname, name); adjust_name(rname); if (check_name(rname)) goto fake; return rname; fake: if (i == 0) strcpy(rname, "obj"); else sprintf(rname, "r_%d", i); return rname; } static char *col_name(struct csa *csa, int j, char cname[255+1]) { /* construct symbolic name of j-th column (variable) */ const char *name; name = glp_get_col_name(csa->P, j); if (name == NULL) goto fake; strcpy(cname, name); adjust_name(cname); if (check_name(cname)) goto fake; return cname; fake: sprintf(cname, "x_%d", j); return cname; } int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname) { /* write problem data in CPLEX LP format */ glp_cpxcp _parm; struct csa _csa, *csa = &_csa; XFILE *fp; GLPROW *row; GLPCOL *col; GLPAIJ *aij; int i, j, len, flag, count, ret; char line[1000+1], term[500+1], name[255+1]; xprintf("Writing problem data to '%s'...\n", fname); if (parm == NULL) glp_init_cpxcp(&_parm), parm = &_parm; /* check control parameters */ check_parm("glp_write_lp", parm); /* initialize common storage area */ csa->P = P; csa->parm = parm; /* create output CPLEX LP file */ fp = xfopen(fname, "w"), count = 0; if (fp == NULL) { xprintf("Unable to create '%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* write problem name */ xfprintf(fp, "\\* Problem: %s *\\\n", P->name == NULL ? "Unknown" : P->name), count++; xfprintf(fp, "\n"), count++; /* the problem should contain at least one row and one column */ if (!(P->m > 0 && P->n > 0)) { xprintf("Warning: problem has no rows/columns\n"); xfprintf(fp, "\\* WARNING: PROBLEM HAS NO ROWS/COLUMNS *\\\n"), count++; xfprintf(fp, "\n"), count++; goto skip; } /* write the objective function definition */ if (P->dir == GLP_MIN) xfprintf(fp, "Minimize\n"), count++; else if (P->dir == GLP_MAX) xfprintf(fp, "Maximize\n"), count++; else xassert(P != P); row_name(csa, 0, name); sprintf(line, " %s:", name); len = 0; for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->coef != 0.0 || col->ptr == NULL) { len++; col_name(csa, j, name); if (col->coef == 0.0) sprintf(term, " + 0 %s", name); /* empty column */ else if (col->coef == +1.0) sprintf(term, " + %s", name); else if (col->coef == -1.0) sprintf(term, " - %s", name); else if (col->coef > 0.0) sprintf(term, " + %.*g %s", DBL_DIG, +col->coef, name); else sprintf(term, " - %.*g %s", DBL_DIG, -col->coef, name); if (strlen(line) + strlen(term) > 72) xfprintf(fp, "%s\n", line), line[0] = '\0', count++; strcat(line, term); } } if (len == 0) { /* empty objective */ sprintf(term, " 0 %s", col_name(csa, 1, name)); strcat(line, term); } xfprintf(fp, "%s\n", line), count++; if (P->c0 != 0.0) xfprintf(fp, "\\* constant term = %.*g *\\\n", DBL_DIG, P->c0), count++; xfprintf(fp, "\n"), count++; /* write the constraints section */ xfprintf(fp, "Subject To\n"), count++; for (i = 1; i <= P->m; i++) { row = P->row[i]; if (row->type == GLP_FR) continue; /* skip free row */ row_name(csa, i, name); sprintf(line, " %s:", name); /* linear form */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) { col_name(csa, aij->col->j, name); if (aij->val == +1.0) sprintf(term, " + %s", name); else if (aij->val == -1.0) sprintf(term, " - %s", name); else if (aij->val > 0.0) sprintf(term, " + %.*g %s", DBL_DIG, +aij->val, name); else sprintf(term, " - %.*g %s", DBL_DIG, -aij->val, name); if (strlen(line) + strlen(term) > 72) xfprintf(fp, "%s\n", line), line[0] = '\0', count++; strcat(line, term); } if (row->type == GLP_DB) { /* double-bounded (ranged) constraint */ sprintf(term, " - ~r_%d", i); if (strlen(line) + strlen(term) > 72) xfprintf(fp, "%s\n", line), line[0] = '\0', count++; strcat(line, term); } else if (row->ptr == NULL) { /* empty constraint */ sprintf(term, " 0 %s", col_name(csa, 1, name)); strcat(line, term); } /* right hand-side */ if (row->type == GLP_LO) sprintf(term, " >= %.*g", DBL_DIG, row->lb); else if (row->type == GLP_UP) sprintf(term, " <= %.*g", DBL_DIG, row->ub); else if (row->type == GLP_DB || row->type == GLP_FX) sprintf(term, " = %.*g", DBL_DIG, row->lb); else xassert(row != row); if (strlen(line) + strlen(term) > 72) xfprintf(fp, "%s\n", line), line[0] = '\0', count++; strcat(line, term); xfprintf(fp, "%s\n", line), count++; } xfprintf(fp, "\n"), count++; /* write the bounds section */ flag = 0; for (i = 1; i <= P->m; i++) { row = P->row[i]; if (row->type != GLP_DB) continue; if (!flag) xfprintf(fp, "Bounds\n"), flag = 1, count++; xfprintf(fp, " 0 <= ~r_%d <= %.*g\n", i, DBL_DIG, row->ub - row->lb), count++; } for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->type == GLP_LO && col->lb == 0.0) continue; if (!flag) xfprintf(fp, "Bounds\n"), flag = 1, count++; col_name(csa, j, name); if (col->type == GLP_FR) xfprintf(fp, " %s free\n", name), count++; else if (col->type == GLP_LO) xfprintf(fp, " %s >= %.*g\n", name, DBL_DIG, col->lb), count++; else if (col->type == GLP_UP) xfprintf(fp, " -Inf <= %s <= %.*g\n", name, DBL_DIG, col->ub), count++; else if (col->type == GLP_DB) xfprintf(fp, " %.*g <= %s <= %.*g\n", DBL_DIG, col->lb, name, DBL_DIG, col->ub), count++; else if (col->type == GLP_FX) xfprintf(fp, " %s = %.*g\n", name, DBL_DIG, col->lb), count++; else xassert(col != col); } if (flag) xfprintf(fp, "\n"), count++; /* write the integer section */ flag = 0; for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->kind == GLP_CV) continue; xassert(col->kind == GLP_IV); if (!flag) xfprintf(fp, "Generals\n"), flag = 1, count++; xfprintf(fp, " %s\n", col_name(csa, j, name)), count++; } if (flag) xfprintf(fp, "\n"), count++; skip: /* write the end keyword */ xfprintf(fp, "End\n"), count++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on '%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* problem data has been successfully written */ xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /* eof */ glpk-4.52.1/src/glpdmx.c0000644000062000006210000016110012175147600014146 0ustar maomkpasswd/* glpdmx.c (reading/writing data in DIMACS format) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #if 1 /* 11/VI-2013 */ #include "env2.h" #endif #define _GLPSTD_STDIO #include "glpapi.h" #include "glplib.h" struct csa { /* common storage area */ jmp_buf jump; /* label for go to in case of error */ const char *fname; /* name of input text file */ XFILE *fp; /* stream assigned to input text file */ int count; /* line count */ int c; /* current character */ char field[255+1]; /* data field */ int empty; /* warning 'empty line ignored' was printed */ int nonint; /* warning 'non-integer data detected' was printed */ }; static void error(struct csa *csa, const char *fmt, ...) { /* print error message and terminate processing */ va_list arg; xprintf("%s:%d: error: ", csa->fname, csa->count); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); xprintf("\n"); longjmp(csa->jump, 1); /* no return */ } static void warning(struct csa *csa, const char *fmt, ...) { /* print warning message and continue processing */ va_list arg; xprintf("%s:%d: warning: ", csa->fname, csa->count); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); xprintf("\n"); return; } static void read_char(struct csa *csa) { /* read character from input text file */ int c; if (csa->c == '\n') csa->count++; c = xfgetc(csa->fp); if (c < 0) { if (xferror(csa->fp)) error(csa, "read error - %s", xerrmsg()); else if (csa->c == '\n') error(csa, "unexpected end of file"); else { warning(csa, "missing final end of line"); c = '\n'; } } else if (c == '\n') ; else if (isspace(c)) c = ' '; else if (iscntrl(c)) error(csa, "invalid control character 0x%02X", c); csa->c = c; return; } static void read_designator(struct csa *csa) { /* read one-character line designator */ xassert(csa->c == '\n'); read_char(csa); for (;;) { /* skip preceding white-space characters */ while (csa->c == ' ') read_char(csa); if (csa->c == '\n') { /* ignore empty line */ if (!csa->empty) { warning(csa, "empty line ignored"); csa->empty = 1; } read_char(csa); } else if (csa->c == 'c') { /* skip comment line */ while (csa->c != '\n') read_char(csa); read_char(csa); } else { /* hmm... looks like a line designator */ csa->field[0] = (char)csa->c, csa->field[1] = '\0'; /* check that it is followed by a white-space character */ read_char(csa); if (!(csa->c == ' ' || csa->c == '\n')) error(csa, "line designator missing or invalid"); break; } } return; } static void read_field(struct csa *csa) { /* read data field */ int len = 0; /* skip preceding white-space characters */ while (csa->c == ' ') read_char(csa); /* scan data field */ if (csa->c == '\n') error(csa, "unexpected end of line"); while (!(csa->c == ' ' || csa->c == '\n')) { if (len == sizeof(csa->field)-1) error(csa, "data field `%.15s...' too long", csa->field); csa->field[len++] = (char)csa->c; read_char(csa); } csa->field[len] = '\0'; return; } static void end_of_line(struct csa *csa) { /* skip white-space characters until end of line */ while (csa->c == ' ') read_char(csa); if (csa->c != '\n') error(csa, "too many data fields specified"); return; } static void check_int(struct csa *csa, double num) { /* print a warning if non-integer data are detected */ if (!csa->nonint && num != floor(num)) { warning(csa, "non-integer data detected"); csa->nonint = 1; } return; } /*********************************************************************** * NAME * * glp_read_mincost - read min-cost flow problem data in DIMACS format * * SYNOPSIS * * int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, * int a_cost, const char *fname); * * DESCRIPTION * * The routine glp_read_mincost reads minimum cost flow problem data in * DIMACS format from a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, const char *fname) { struct csa _csa, *csa = &_csa; glp_vertex *v; glp_arc *a; int i, j, k, nv, na, ret = 0; double rhs, low, cap, cost; char *flag = NULL; if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_read_mincost: v_rhs = %d; invalid offset\n", v_rhs); if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) xerror("glp_read_mincost: a_low = %d; invalid offset\n", a_low); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_read_mincost: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_read_mincost: a_cost = %d; invalid offset\n", a_cost); glp_erase_graph(G, G->v_size, G->a_size); if (setjmp(csa->jump)) { ret = 1; goto done; } csa->fname = fname; csa->fp = NULL; csa->count = 0; csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; xprintf("Reading min-cost flow problem data from `%s'...\n", fname); csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); longjmp(csa->jump, 1); } /* read problem line */ read_designator(csa); if (strcmp(csa->field, "p") != 0) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "min") != 0) error(csa, "wrong problem designator; `min' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) error(csa, "number of nodes missing or invalid"); read_field(csa); if (!(str2int(csa->field, &na) == 0 && na >= 0)) error(csa, "number of arcs missing or invalid"); xprintf("Flow network has %d node%s and %d arc%s\n", nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); if (nv > 0) glp_add_vertices(G, nv); end_of_line(csa); /* read node descriptor lines */ flag = xcalloc(1+nv, sizeof(char)); memset(&flag[1], 0, nv * sizeof(char)); if (v_rhs >= 0) { rhs = 0.0; for (i = 1; i <= nv; i++) { v = G->v[i]; memcpy((char *)v->data + v_rhs, &rhs, sizeof(double)); } } for (;;) { read_designator(csa); if (strcmp(csa->field, "n") != 0) break; read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "node number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "node number %d out of range", i); if (flag[i]) error(csa, "duplicate descriptor of node %d", i); read_field(csa); if (str2num(csa->field, &rhs) != 0) error(csa, "node supply/demand missing or invalid"); check_int(csa, rhs); if (v_rhs >= 0) { v = G->v[i]; memcpy((char *)v->data + v_rhs, &rhs, sizeof(double)); } flag[i] = 1; end_of_line(csa); } xfree(flag), flag = NULL; /* read arc descriptor lines */ for (k = 1; k <= na; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "a") != 0) error(csa, "wrong line designator; `a' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "starting node number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "starting node number %d out of range", i); read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "ending node number missing or invalid"); if (!(1 <= j && j <= nv)) error(csa, "ending node number %d out of range", j); read_field(csa); if (!(str2num(csa->field, &low) == 0 && low >= 0.0)) error(csa, "lower bound of arc flow missing or invalid"); check_int(csa, low); read_field(csa); if (!(str2num(csa->field, &cap) == 0 && cap >= low)) error(csa, "upper bound of arc flow missing or invalid"); check_int(csa, cap); read_field(csa); if (str2num(csa->field, &cost) != 0) error(csa, "per-unit cost of arc flow missing or invalid"); check_int(csa, cost); a = glp_add_arc(G, i, j); if (a_low >= 0) memcpy((char *)a->data + a_low, &low, sizeof(double)); if (a_cap >= 0) memcpy((char *)a->data + a_cap, &cap, sizeof(double)); if (a_cost >= 0) memcpy((char *)a->data + a_cost, &cost, sizeof(double)); end_of_line(csa); } xprintf("%d lines were read\n", csa->count); done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); if (csa->fp != NULL) xfclose(csa->fp); if (flag != NULL) xfree(flag); return ret; } /*********************************************************************** * NAME * * glp_write_mincost - write min-cost flow problem data in DIMACS format * * SYNOPSIS * * int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, * int a_cost, const char *fname); * * DESCRIPTION * * The routine glp_write_mincost writes minimum cost flow problem data * in DIMACS format to a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, const char *fname) { XFILE *fp; glp_vertex *v; glp_arc *a; int i, count = 0, ret; double rhs, low, cap, cost; if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_write_mincost: v_rhs = %d; invalid offset\n", v_rhs); if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double)) xerror("glp_write_mincost: a_low = %d; invalid offset\n", a_low); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_write_mincost: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_write_mincost: a_cost = %d; invalid offset\n", a_cost); xprintf("Writing min-cost flow problem data to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "c %s\n", G->name == NULL ? "unknown" : G->name), count++; xfprintf(fp, "p min %d %d\n", G->nv, G->na), count++; if (v_rhs >= 0) { for (i = 1; i <= G->nv; i++) { v = G->v[i]; memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double)); if (rhs != 0.0) xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, rhs), count++; } } for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { if (a_low >= 0) memcpy(&low, (char *)a->data + a_low, sizeof(double)); else low = 0.0; if (a_cap >= 0) memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); else cap = 1.0; if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 0.0; xfprintf(fp, "a %d %d %.*g %.*g %.*g\n", a->tail->i, a->head->i, DBL_DIG, low, DBL_DIG, cap, DBL_DIG, cost), count++; } } xfprintf(fp, "c eof\n"), count++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /*********************************************************************** * NAME * * glp_read_maxflow - read maximum flow problem data in DIMACS format * * SYNOPSIS * * int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, * const char *fname); * * DESCRIPTION * * The routine glp_read_maxflow reads maximum flow problem data in * DIMACS format from a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_read_maxflow(glp_graph *G, int *_s, int *_t, int a_cap, const char *fname) { struct csa _csa, *csa = &_csa; glp_arc *a; int i, j, k, s, t, nv, na, ret = 0; double cap; if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_read_maxflow: a_cap = %d; invalid offset\n", a_cap); glp_erase_graph(G, G->v_size, G->a_size); if (setjmp(csa->jump)) { ret = 1; goto done; } csa->fname = fname; csa->fp = NULL; csa->count = 0; csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; xprintf("Reading maximum flow problem data from `%s'...\n", fname); csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); longjmp(csa->jump, 1); } /* read problem line */ read_designator(csa); if (strcmp(csa->field, "p") != 0) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "max") != 0) error(csa, "wrong problem designator; `max' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 2)) error(csa, "number of nodes missing or invalid"); read_field(csa); if (!(str2int(csa->field, &na) == 0 && na >= 0)) error(csa, "number of arcs missing or invalid"); xprintf("Flow network has %d node%s and %d arc%s\n", nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); if (nv > 0) glp_add_vertices(G, nv); end_of_line(csa); /* read node descriptor lines */ s = t = 0; for (;;) { read_designator(csa); if (strcmp(csa->field, "n") != 0) break; read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "node number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "node number %d out of range", i); read_field(csa); if (strcmp(csa->field, "s") == 0) { if (s > 0) error(csa, "only one source node allowed"); s = i; } else if (strcmp(csa->field, "t") == 0) { if (t > 0) error(csa, "only one sink node allowed"); t = i; } else error(csa, "wrong node designator; `s' or `t' expected"); if (s > 0 && s == t) error(csa, "source and sink nodes must be distinct"); end_of_line(csa); } if (s == 0) error(csa, "source node descriptor missing\n"); if (t == 0) error(csa, "sink node descriptor missing\n"); if (_s != NULL) *_s = s; if (_t != NULL) *_t = t; /* read arc descriptor lines */ for (k = 1; k <= na; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "a") != 0) error(csa, "wrong line designator; `a' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "starting node number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "starting node number %d out of range", i); read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "ending node number missing or invalid"); if (!(1 <= j && j <= nv)) error(csa, "ending node number %d out of range", j); read_field(csa); if (!(str2num(csa->field, &cap) == 0 && cap >= 0.0)) error(csa, "arc capacity missing or invalid"); check_int(csa, cap); a = glp_add_arc(G, i, j); if (a_cap >= 0) memcpy((char *)a->data + a_cap, &cap, sizeof(double)); end_of_line(csa); } xprintf("%d lines were read\n", csa->count); done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); if (csa->fp != NULL) xfclose(csa->fp); return ret; } /*********************************************************************** * NAME * * glp_write_maxflow - write maximum flow problem data in DIMACS format * * SYNOPSIS * * int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, * const char *fname); * * DESCRIPTION * * The routine glp_write_maxflow writes maximum flow problem data in * DIMACS format to a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, const char *fname) { XFILE *fp; glp_vertex *v; glp_arc *a; int i, count = 0, ret; double cap; if (!(1 <= s && s <= G->nv)) xerror("glp_write_maxflow: s = %d; source node number out of r" "ange\n", s); if (!(1 <= t && t <= G->nv)) xerror("glp_write_maxflow: t = %d: sink node number out of ran" "ge\n", t); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_write_mincost: a_cap = %d; invalid offset\n", a_cap); xprintf("Writing maximum flow problem data to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "c %s\n", G->name == NULL ? "unknown" : G->name), count++; xfprintf(fp, "p max %d %d\n", G->nv, G->na), count++; xfprintf(fp, "n %d s\n", s), count++; xfprintf(fp, "n %d t\n", t), count++; for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { if (a_cap >= 0) memcpy(&cap, (char *)a->data + a_cap, sizeof(double)); else cap = 1.0; xfprintf(fp, "a %d %d %.*g\n", a->tail->i, a->head->i, DBL_DIG, cap), count++; } } xfprintf(fp, "c eof\n"), count++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /*********************************************************************** * NAME * * glp_read_asnprob - read assignment problem data in DIMACS format * * SYNOPSIS * * int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, * const char *fname); * * DESCRIPTION * * The routine glp_read_asnprob reads assignment problem data in DIMACS * format from a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname) { struct csa _csa, *csa = &_csa; glp_vertex *v; glp_arc *a; int nv, na, n1, i, j, k, ret = 0; double cost; char *flag = NULL; if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_read_asnprob: v_set = %d; invalid offset\n", v_set); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_read_asnprob: a_cost = %d; invalid offset\n", a_cost); glp_erase_graph(G, G->v_size, G->a_size); if (setjmp(csa->jump)) { ret = 1; goto done; } csa->fname = fname; csa->fp = NULL; csa->count = 0; csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; xprintf("Reading assignment problem data from `%s'...\n", fname); csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); longjmp(csa->jump, 1); } /* read problem line */ read_designator(csa); if (strcmp(csa->field, "p") != 0) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "asn") != 0) error(csa, "wrong problem designator; `asn' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) error(csa, "number of nodes missing or invalid"); read_field(csa); if (!(str2int(csa->field, &na) == 0 && na >= 0)) error(csa, "number of arcs missing or invalid"); if (nv > 0) glp_add_vertices(G, nv); end_of_line(csa); /* read node descriptor lines */ flag = xcalloc(1+nv, sizeof(char)); memset(&flag[1], 0, nv * sizeof(char)); n1 = 0; for (;;) { read_designator(csa); if (strcmp(csa->field, "n") != 0) break; read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "node number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "node number %d out of range", i); if (flag[i]) error(csa, "duplicate descriptor of node %d", i); flag[i] = 1, n1++; end_of_line(csa); } xprintf( "Assignment problem has %d + %d = %d node%s and %d arc%s\n", n1, nv - n1, nv, nv == 1 ? "" : "s", na, na == 1 ? "" : "s"); if (v_set >= 0) { for (i = 1; i <= nv; i++) { v = G->v[i]; k = (flag[i] ? 0 : 1); memcpy((char *)v->data + v_set, &k, sizeof(int)); } } /* read arc descriptor lines */ for (k = 1; k <= na; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "a") != 0) error(csa, "wrong line designator; `a' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "starting node number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "starting node number %d out of range", i); if (!flag[i]) error(csa, "node %d cannot be a starting node", i); read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "ending node number missing or invalid"); if (!(1 <= j && j <= nv)) error(csa, "ending node number %d out of range", j); if (flag[j]) error(csa, "node %d cannot be an ending node", j); read_field(csa); if (str2num(csa->field, &cost) != 0) error(csa, "arc cost missing or invalid"); check_int(csa, cost); a = glp_add_arc(G, i, j); if (a_cost >= 0) memcpy((char *)a->data + a_cost, &cost, sizeof(double)); end_of_line(csa); } xprintf("%d lines were read\n", csa->count); done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); if (csa->fp != NULL) xfclose(csa->fp); if (flag != NULL) xfree(flag); return ret; } /*********************************************************************** * NAME * * glp_write_asnprob - write assignment problem data in DIMACS format * * SYNOPSIS * * int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, * const char *fname); * * DESCRIPTION * * The routine glp_write_asnprob writes assignment problem data in * DIMACS format to a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname) { XFILE *fp; glp_vertex *v; glp_arc *a; int i, k, count = 0, ret; double cost; if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_write_asnprob: v_set = %d; invalid offset\n", v_set); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_write_asnprob: a_cost = %d; invalid offset\n", a_cost); xprintf("Writing assignment problem data to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "c %s\n", G->name == NULL ? "unknown" : G->name), count++; xfprintf(fp, "p asn %d %d\n", G->nv, G->na), count++; for (i = 1; i <= G->nv; i++) { v = G->v[i]; if (v_set >= 0) memcpy(&k, (char *)v->data + v_set, sizeof(int)); else k = (v->out != NULL ? 0 : 1); if (k == 0) xfprintf(fp, "n %d\n", i), count++; } for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (a = v->out; a != NULL; a = a->t_next) { if (a_cost >= 0) memcpy(&cost, (char *)a->data + a_cost, sizeof(double)); else cost = 1.0; xfprintf(fp, "a %d %d %.*g\n", a->tail->i, a->head->i, DBL_DIG, cost), count++; } } xfprintf(fp, "c eof\n"), count++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /*********************************************************************** * NAME * * glp_read_ccdata - read graph in DIMACS clique/coloring format * * SYNOPSIS * * int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); * * DESCRIPTION * * The routine glp_read_ccdata reads an (undirected) graph in DIMACS * clique/coloring format from a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname) { struct csa _csa, *csa = &_csa; glp_vertex *v; int i, j, k, nv, ne, ret = 0; double w; char *flag = NULL; if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) xerror("glp_read_ccdata: v_wgt = %d; invalid offset\n", v_wgt); glp_erase_graph(G, G->v_size, G->a_size); if (setjmp(csa->jump)) { ret = 1; goto done; } csa->fname = fname; csa->fp = NULL; csa->count = 0; csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; xprintf("Reading graph from `%s'...\n", fname); csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); longjmp(csa->jump, 1); } /* read problem line */ read_designator(csa); if (strcmp(csa->field, "p") != 0) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "edge") != 0) error(csa, "wrong problem designator; `edge' expected"); read_field(csa); if (!(str2int(csa->field, &nv) == 0 && nv >= 0)) error(csa, "number of vertices missing or invalid"); read_field(csa); if (!(str2int(csa->field, &ne) == 0 && ne >= 0)) error(csa, "number of edges missing or invalid"); xprintf("Graph has %d vert%s and %d edge%s\n", nv, nv == 1 ? "ex" : "ices", ne, ne == 1 ? "" : "s"); if (nv > 0) glp_add_vertices(G, nv); end_of_line(csa); /* read node descriptor lines */ flag = xcalloc(1+nv, sizeof(char)); memset(&flag[1], 0, nv * sizeof(char)); if (v_wgt >= 0) { w = 1.0; for (i = 1; i <= nv; i++) { v = G->v[i]; memcpy((char *)v->data + v_wgt, &w, sizeof(double)); } } for (;;) { read_designator(csa); if (strcmp(csa->field, "n") != 0) break; read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "vertex number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "vertex number %d out of range", i); if (flag[i]) error(csa, "duplicate descriptor of vertex %d", i); read_field(csa); if (str2num(csa->field, &w) != 0) error(csa, "vertex weight missing or invalid"); check_int(csa, w); if (v_wgt >= 0) { v = G->v[i]; memcpy((char *)v->data + v_wgt, &w, sizeof(double)); } flag[i] = 1; end_of_line(csa); } xfree(flag), flag = NULL; /* read edge descriptor lines */ for (k = 1; k <= ne; k++) { if (k > 1) read_designator(csa); if (strcmp(csa->field, "e") != 0) error(csa, "wrong line designator; `e' expected"); read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "first vertex number missing or invalid"); if (!(1 <= i && i <= nv)) error(csa, "first vertex number %d out of range", i); read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "second vertex number missing or invalid"); if (!(1 <= j && j <= nv)) error(csa, "second vertex number %d out of range", j); glp_add_arc(G, i, j); end_of_line(csa); } xprintf("%d lines were read\n", csa->count); done: if (ret) glp_erase_graph(G, G->v_size, G->a_size); if (csa->fp != NULL) xfclose(csa->fp); if (flag != NULL) xfree(flag); return ret; } /*********************************************************************** * NAME * * glp_write_ccdata - write graph in DIMACS clique/coloring format * * SYNOPSIS * * int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); * * DESCRIPTION * * The routine glp_write_ccdata writes the specified graph in DIMACS * clique/coloring format to a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname) { XFILE *fp; glp_vertex *v; glp_arc *e; int i, count = 0, ret; double w; if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) xerror("glp_write_ccdata: v_wgt = %d; invalid offset\n", v_wgt); xprintf("Writing graph to `%s'\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "c %s\n", G->name == NULL ? "unknown" : G->name), count++; xfprintf(fp, "p edge %d %d\n", G->nv, G->na), count++; if (v_wgt >= 0) { for (i = 1; i <= G->nv; i++) { v = G->v[i]; memcpy(&w, (char *)v->data + v_wgt, sizeof(double)); if (w != 1.0) xfprintf(fp, "n %d %.*g\n", i, DBL_DIG, w), count++; } } for (i = 1; i <= G->nv; i++) { v = G->v[i]; for (e = v->out; e != NULL; e = e->t_next) xfprintf(fp, "e %d %d\n", e->tail->i, e->head->i), count++; } xfprintf(fp, "c eof\n"), count++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /*********************************************************************** * NAME * * glp_read_prob - read problem data in GLPK format * * SYNOPSIS * * int glp_read_prob(glp_prob *P, int flags, const char *fname); * * The routine glp_read_prob reads problem data in GLPK LP/MIP format * from a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_read_prob(glp_prob *P, int flags, const char *fname) { struct csa _csa, *csa = &_csa; int mip, m, n, nnz, ne, i, j, k, type, kind, ret, *ln = NULL, *ia = NULL, *ja = NULL; double lb, ub, temp, *ar = NULL; char *rf = NULL, *cf = NULL; if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_read_prob: P = %p; invalid problem object\n", P); if (flags != 0) xerror("glp_read_prob: flags = %d; invalid parameter\n", flags); if (fname == NULL) xerror("glp_read_prob: fname = %d; invalid parameter\n", fname); glp_erase_prob(P); if (setjmp(csa->jump)) { ret = 1; goto done; } csa->fname = fname; csa->fp = NULL; csa->count = 0; csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; xprintf("Reading problem data from `%s'...\n", fname); csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); longjmp(csa->jump, 1); } /* read problem line */ read_designator(csa); if (strcmp(csa->field, "p") != 0) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "lp") == 0) mip = 0; else if (strcmp(csa->field, "mip") == 0) mip = 1; else error(csa, "wrong problem designator; `lp' or `mip' expected\n" ); read_field(csa); if (strcmp(csa->field, "min") == 0) glp_set_obj_dir(P, GLP_MIN); else if (strcmp(csa->field, "max") == 0) glp_set_obj_dir(P, GLP_MAX); else error(csa, "objective sense missing or invalid"); read_field(csa); if (!(str2int(csa->field, &m) == 0 && m >= 0)) error(csa, "number of rows missing or invalid"); read_field(csa); if (!(str2int(csa->field, &n) == 0 && n >= 0)) error(csa, "number of columns missing or invalid"); read_field(csa); if (!(str2int(csa->field, &nnz) == 0 && nnz >= 0)) error(csa, "number of constraint coefficients missing or inval" "id"); if (m > 0) { glp_add_rows(P, m); for (i = 1; i <= m; i++) glp_set_row_bnds(P, i, GLP_FX, 0.0, 0.0); } if (n > 0) { glp_add_cols(P, n); for (j = 1; j <= n; j++) { if (!mip) glp_set_col_bnds(P, j, GLP_LO, 0.0, 0.0); else glp_set_col_kind(P, j, GLP_BV); } } end_of_line(csa); /* allocate working arrays */ rf = xcalloc(1+m, sizeof(char)); memset(rf, 0, 1+m); cf = xcalloc(1+n, sizeof(char)); memset(cf, 0, 1+n); ln = xcalloc(1+nnz, sizeof(int)); ia = xcalloc(1+nnz, sizeof(int)); ja = xcalloc(1+nnz, sizeof(int)); ar = xcalloc(1+nnz, sizeof(double)); /* read descriptor lines */ ne = 0; for (;;) { read_designator(csa); if (strcmp(csa->field, "i") == 0) { /* row descriptor */ read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "row number missing or invalid"); if (!(1 <= i && i <= m)) error(csa, "row number out of range"); read_field(csa); if (strcmp(csa->field, "f") == 0) type = GLP_FR; else if (strcmp(csa->field, "l") == 0) type = GLP_LO; else if (strcmp(csa->field, "u") == 0) type = GLP_UP; else if (strcmp(csa->field, "d") == 0) type = GLP_DB; else if (strcmp(csa->field, "s") == 0) type = GLP_FX; else error(csa, "row type missing or invalid"); if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { read_field(csa); if (str2num(csa->field, &lb) != 0) error(csa, "row lower bound/fixed value missing or in" "valid"); } else lb = 0.0; if (type == GLP_UP || type == GLP_DB) { read_field(csa); if (str2num(csa->field, &ub) != 0) error(csa, "row upper bound missing or invalid"); } else ub = 0.0; if (rf[i] & 0x01) error(csa, "duplicate row descriptor"); glp_set_row_bnds(P, i, type, lb, ub), rf[i] |= 0x01; } else if (strcmp(csa->field, "j") == 0) { /* column descriptor */ read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "column number missing or invalid"); if (!(1 <= j && j <= n)) error(csa, "column number out of range"); if (!mip) kind = GLP_CV; else { read_field(csa); if (strcmp(csa->field, "c") == 0) kind = GLP_CV; else if (strcmp(csa->field, "i") == 0) kind = GLP_IV; else if (strcmp(csa->field, "b") == 0) { kind = GLP_IV; type = GLP_DB, lb = 0.0, ub = 1.0; goto skip; } else error(csa, "column kind missing or invalid"); } read_field(csa); if (strcmp(csa->field, "f") == 0) type = GLP_FR; else if (strcmp(csa->field, "l") == 0) type = GLP_LO; else if (strcmp(csa->field, "u") == 0) type = GLP_UP; else if (strcmp(csa->field, "d") == 0) type = GLP_DB; else if (strcmp(csa->field, "s") == 0) type = GLP_FX; else error(csa, "column type missing or invalid"); if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { read_field(csa); if (str2num(csa->field, &lb) != 0) error(csa, "column lower bound/fixed value missing or" " invalid"); } else lb = 0.0; if (type == GLP_UP || type == GLP_DB) { read_field(csa); if (str2num(csa->field, &ub) != 0) error(csa, "column upper bound missing or invalid"); } else ub = 0.0; skip: if (cf[j] & 0x01) error(csa, "duplicate column descriptor"); glp_set_col_kind(P, j, kind); glp_set_col_bnds(P, j, type, lb, ub), cf[j] |= 0x01; } else if (strcmp(csa->field, "a") == 0) { /* coefficient descriptor */ read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "row number missing or invalid"); if (!(0 <= i && i <= m)) error(csa, "row number out of range"); read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "column number missing or invalid"); if (!((i == 0 ? 0 : 1) <= j && j <= n)) error(csa, "column number out of range"); read_field(csa); if (i == 0) { if (str2num(csa->field, &temp) != 0) error(csa, "objective %s missing or invalid", j == 0 ? "constant term" : "coefficient"); if (cf[j] & 0x10) error(csa, "duplicate objective %s", j == 0 ? "constant term" : "coefficient"); glp_set_obj_coef(P, j, temp), cf[j] |= 0x10; } else { if (str2num(csa->field, &temp) != 0) error(csa, "constraint coefficient missing or invalid" ); if (ne == nnz) error(csa, "too many constraint coefficient descripto" "rs"); ln[++ne] = csa->count; ia[ne] = i, ja[ne] = j, ar[ne] = temp; } } else if (strcmp(csa->field, "n") == 0) { /* symbolic name descriptor */ read_field(csa); if (strcmp(csa->field, "p") == 0) { /* problem name */ read_field(csa); if (P->name != NULL) error(csa, "duplicate problem name"); glp_set_prob_name(P, csa->field); } else if (strcmp(csa->field, "z") == 0) { /* objective name */ read_field(csa); if (P->obj != NULL) error(csa, "duplicate objective name"); glp_set_obj_name(P, csa->field); } else if (strcmp(csa->field, "i") == 0) { /* row name */ read_field(csa); if (str2int(csa->field, &i) != 0) error(csa, "row number missing or invalid"); if (!(1 <= i && i <= m)) error(csa, "row number out of range"); read_field(csa); if (P->row[i]->name != NULL) error(csa, "duplicate row name"); glp_set_row_name(P, i, csa->field); } else if (strcmp(csa->field, "j") == 0) { /* column name */ read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "column number missing or invalid"); if (!(1 <= j && j <= n)) error(csa, "column number out of range"); read_field(csa); if (P->col[j]->name != NULL) error(csa, "duplicate column name"); glp_set_col_name(P, j, csa->field); } else error(csa, "object designator missing or invalid"); } else if (strcmp(csa->field, "e") == 0) break; else error(csa, "line designator missing or invalid"); end_of_line(csa); } if (ne < nnz) error(csa, "too few constraint coefficient descriptors"); xassert(ne == nnz); k = glp_check_dup(m, n, ne, ia, ja); xassert(0 <= k && k <= nnz); if (k > 0) { csa->count = ln[k]; error(csa, "duplicate constraint coefficient"); } glp_load_matrix(P, ne, ia, ja, ar); /* print some statistics */ if (P->name != NULL) xprintf("Problem: %s\n", P->name); if (P->obj != NULL) xprintf("Objective: %s\n", P->obj); xprintf("%d row%s, %d column%s, %d non-zero%s\n", m, m == 1 ? "" : "s", n, n == 1 ? "" : "s", nnz, nnz == 1 ? "" : "s"); if (glp_get_num_int(P) > 0) { int ni = glp_get_num_int(P); int nb = glp_get_num_bin(P); if (ni == 1) { if (nb == 0) xprintf("One variable is integer\n"); else xprintf("One variable is binary\n"); } else { xprintf("%d integer variables, ", ni); if (nb == 0) xprintf("none"); else if (nb == 1) xprintf("one"); else if (nb == ni) xprintf("all"); else xprintf("%d", nb); xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); } } xprintf("%d lines were read\n", csa->count); /* problem data has been successfully read */ glp_sort_matrix(P); ret = 0; done: if (csa->fp != NULL) xfclose(csa->fp); if (rf != NULL) xfree(rf); if (cf != NULL) xfree(cf); if (ln != NULL) xfree(ln); if (ia != NULL) xfree(ia); if (ja != NULL) xfree(ja); if (ar != NULL) xfree(ar); if (ret) glp_erase_prob(P); return ret; } /*********************************************************************** * NAME * * glp_write_prob - write problem data in GLPK format * * SYNOPSIS * * int glp_write_prob(glp_prob *P, int flags, const char *fname); * * The routine glp_write_prob writes problem data in GLPK LP/MIP format * to a text file. * * RETURNS * * If the operation was successful, the routine returns zero. Otherwise * it prints an error message and returns non-zero. */ int glp_write_prob(glp_prob *P, int flags, const char *fname) { XFILE *fp; GLPROW *row; GLPCOL *col; GLPAIJ *aij; int mip, i, j, count, ret; if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_write_prob: P = %p; invalid problem object\n", P); if (flags != 0) xerror("glp_write_prob: flags = %d; invalid parameter\n", flags); if (fname == NULL) xerror("glp_write_prob: fname = %d; invalid parameter\n", fname); xprintf("Writing problem data to `%s'...\n", fname); fp = xfopen(fname, "w"), count = 0; if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* write problem line */ mip = (glp_get_num_int(P) > 0); xfprintf(fp, "p %s %s %d %d %d\n", !mip ? "lp" : "mip", P->dir == GLP_MIN ? "min" : P->dir == GLP_MAX ? "max" : "???", P->m, P->n, P->nnz), count++; if (P->name != NULL) xfprintf(fp, "n p %s\n", P->name), count++; if (P->obj != NULL) xfprintf(fp, "n z %s\n", P->obj), count++; /* write row descriptors */ for (i = 1; i <= P->m; i++) { row = P->row[i]; if (row->type == GLP_FX && row->lb == 0.0) goto skip1; xfprintf(fp, "i %d ", i), count++; if (row->type == GLP_FR) xfprintf(fp, "f\n"); else if (row->type == GLP_LO) xfprintf(fp, "l %.*g\n", DBL_DIG, row->lb); else if (row->type == GLP_UP) xfprintf(fp, "u %.*g\n", DBL_DIG, row->ub); else if (row->type == GLP_DB) xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, row->lb, DBL_DIG, row->ub); else if (row->type == GLP_FX) xfprintf(fp, "s %.*g\n", DBL_DIG, row->lb); else xassert(row != row); skip1: if (row->name != NULL) xfprintf(fp, "n i %d %s\n", i, row->name), count++; } /* write column descriptors */ for (j = 1; j <= P->n; j++) { col = P->col[j]; if (!mip && col->type == GLP_LO && col->lb == 0.0) goto skip2; if (mip && col->kind == GLP_IV && col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) goto skip2; xfprintf(fp, "j %d ", j), count++; if (mip) { if (col->kind == GLP_CV) xfprintf(fp, "c "); else if (col->kind == GLP_IV) xfprintf(fp, "i "); else xassert(col != col); } if (col->type == GLP_FR) xfprintf(fp, "f\n"); else if (col->type == GLP_LO) xfprintf(fp, "l %.*g\n", DBL_DIG, col->lb); else if (col->type == GLP_UP) xfprintf(fp, "u %.*g\n", DBL_DIG, col->ub); else if (col->type == GLP_DB) xfprintf(fp, "d %.*g %.*g\n", DBL_DIG, col->lb, DBL_DIG, col->ub); else if (col->type == GLP_FX) xfprintf(fp, "s %.*g\n", DBL_DIG, col->lb); else xassert(col != col); skip2: if (col->name != NULL) xfprintf(fp, "n j %d %s\n", j, col->name), count++; } /* write objective coefficient descriptors */ if (P->c0 != 0.0) xfprintf(fp, "a 0 0 %.*g\n", DBL_DIG, P->c0), count++; for (j = 1; j <= P->n; j++) { col = P->col[j]; if (col->coef != 0.0) xfprintf(fp, "a 0 %d %.*g\n", j, DBL_DIG, col->coef), count++; } /* write constraint coefficient descriptors */ for (i = 1; i <= P->m; i++) { row = P->row[i]; for (aij = row->ptr; aij != NULL; aij = aij->r_next) xfprintf(fp, "a %d %d %.*g\n", i, aij->col->j, DBL_DIG, aij->val), count++; } /* write end line */ xfprintf(fp, "e o f\n"), count++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /**********************************************************************/ int glp_read_cnfsat(glp_prob *P, const char *fname) { /* read CNF-SAT problem data in DIMACS format */ struct csa _csa, *csa = &_csa; int m, n, i, j, len, neg, rhs, ret = 0, *ind = NULL; double *val = NULL; char *map = NULL; if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_read_cnfsat: P = %p; invalid problem object\n", P); if (fname == NULL) xerror("glp_read_cnfsat: fname = %p; invalid parameter\n", fname); glp_erase_prob(P); if (setjmp(csa->jump)) { ret = 1; goto done; } csa->fname = fname; csa->fp = NULL; csa->count = 0; csa->c = '\n'; csa->field[0] = '\0'; csa->empty = csa->nonint = 0; xprintf("Reading CNF-SAT problem data from `%s'...\n", fname); csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); longjmp(csa->jump, 1); } /* read problem line */ read_designator(csa); if (strcmp(csa->field, "p") != 0) error(csa, "problem line missing or invalid"); read_field(csa); if (strcmp(csa->field, "cnf") != 0) error(csa, "wrong problem designator; `cnf' expected\n"); read_field(csa); if (!(str2int(csa->field, &n) == 0 && n >= 0)) error(csa, "number of variables missing or invalid\n"); read_field(csa); if (!(str2int(csa->field, &m) == 0 && m >= 0)) error(csa, "number of clauses missing or invalid\n"); xprintf("Instance has %d variable%s and %d clause%s\n", n, n == 1 ? "" : "s", m, m == 1 ? "" : "s"); end_of_line(csa); if (m > 0) glp_add_rows(P, m); if (n > 0) { glp_add_cols(P, n); for (j = 1; j <= n; j++) glp_set_col_kind(P, j, GLP_BV); } /* allocate working arrays */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); map = xcalloc(1+n, sizeof(char)); for (j = 1; j <= n; j++) map[j] = 0; /* read clauses */ for (i = 1; i <= m; i++) { /* read i-th clause */ len = 0, rhs = 1; for (;;) { /* skip white-space characters */ while (csa->c == ' ' || csa->c == '\n') read_char(csa); /* read term */ read_field(csa); if (str2int(csa->field, &j) != 0) error(csa, "variable number missing or invalid\n"); if (j > 0) neg = 0; else if (j < 0) neg = 1, j = -j, rhs--; else break; if (!(1 <= j && j <= n)) error(csa, "variable number out of range\n"); if (map[j]) error(csa, "duplicate variable number\n"); len++, ind[len] = j, val[len] = (neg ? -1.0 : +1.0); map[j] = 1; } glp_set_row_bnds(P, i, GLP_LO, (double)rhs, 0.0); glp_set_mat_row(P, i, len, ind, val); while (len > 0) map[ind[len--]] = 0; } xprintf("%d lines were read\n", csa->count); /* problem data has been successfully read */ glp_sort_matrix(P); done: if (csa->fp != NULL) xfclose(csa->fp); if (ind != NULL) xfree(ind); if (val != NULL) xfree(val); if (map != NULL) xfree(map); if (ret) glp_erase_prob(P); return ret; } /**********************************************************************/ int glp_check_cnfsat(glp_prob *P) { /* check for CNF-SAT problem instance */ int m = P->m; int n = P->n; GLPROW *row; GLPCOL *col; GLPAIJ *aij; int i, j, neg; if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_check_cnfsat: P = %p; invalid problem object\n", P); /* check columns */ for (j = 1; j <= n; j++) { col = P->col[j]; /* the variable should be binary */ if (!(col->kind == GLP_IV && col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0)) return 1; } /* objective function should be zero */ if (P->c0 != 0.0) return 2; for (j = 1; j <= n; j++) { col = P->col[j]; if (col->coef != 0.0) return 3; } /* check rows */ for (i = 1; i <= m; i++) { row = P->row[i]; /* the row should be of ">=" type */ if (row->type != GLP_LO) return 4; /* check constraint coefficients */ neg = 0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { /* the constraint coefficient should be +1 or -1 */ if (aij->val == +1.0) ; else if (aij->val == -1.0) neg++; else return 5; } /* the right-hand side should be (1 - neg), where neg is the number of negative constraint coefficients in the row */ if (row->lb != (double)(1 - neg)) return 6; } /* congratulations; this is CNF-SAT */ return 0; } /**********************************************************************/ int glp_write_cnfsat(glp_prob *P, const char *fname) { /* write CNF-SAT problem data in DIMACS format */ XFILE *fp = NULL; GLPAIJ *aij; int i, j, len, count = 0, ret; char s[50]; if (P == NULL || P->magic != GLP_PROB_MAGIC) xerror("glp_write_cnfsat: P = %p; invalid problem object\n", P); if (glp_check_cnfsat(P) != 0) { xprintf("glp_write_cnfsat: problem object does not encode CNF-" "SAT instance\n"); ret = 1; goto done; } xprintf("Writing CNF-SAT problem data to `%s'...\n", fname); fp = xfopen(fname, "w"); if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xfprintf(fp, "c %s\n", P->name == NULL ? "unknown" : P->name), count++; xfprintf(fp, "p cnf %d %d\n", P->n, P->m), count++; for (i = 1; i <= P->m; i++) { len = 0; for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) { j = aij->col->j; if (aij->val < 0.0) j = -j; sprintf(s, "%d", j); if (len > 0 && len + 1 + strlen(s) > 72) xfprintf(fp, "\n"), count++, len = 0; xfprintf(fp, "%s%s", len == 0 ? "" : " ", s); if (len > 0) len++; len += strlen(s); } if (len > 0 && len + 1 + 1 > 72) xfprintf(fp, "\n"), count++, len = 0; xfprintf(fp, "%s0\n", len == 0 ? "" : " "), count++; } xfprintf(fp, "c eof\n"), count++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } xprintf("%d lines were written\n", count); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /* eof */ glpk-4.52.1/src/glpenv07.c0000644000062000006210000003727712175147600014336 0ustar maomkpasswd/* glpenv07.c (stream input/output) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env2.h" #include "zlib.h" #if 1 /* 11/VI-2013 */ #define IOERR_MSG_SIZE 1024 /* i/o error message buffer size, in bytes */ static char env_ioerr_msg[IOERR_MSG_SIZE] = "No error"; /* input/output error message buffer */ struct XFILE { /* input/output stream descriptor */ int type; /* stream handle type: */ #define FH_FILE 0x11 /* FILE */ #define FH_ZLIB 0x22 /* gzFile */ void *fh; /* pointer to stream handle */ #if 0 /* 11/VI-2013 */ XFILE *prev; /* pointer to previous stream descriptor */ XFILE *next; /* pointer to next stream descriptor */ #endif }; #endif /*********************************************************************** * NAME * * lib_err_msg - save error message string * * SYNOPSIS * * #include "glpenv.h" * void lib_err_msg(const char *msg); * * DESCRIPTION * * The routine lib_err_msg saves an error message string specified by * the parameter msg. The message is obtained by some library routines * with a call to strerror(errno). */ void lib_err_msg(const char *msg) { /*ENV *env = get_env_ptr();*/ int len = strlen(msg); if (len >= IOERR_MSG_SIZE) len = IOERR_MSG_SIZE - 1; #if 0 /* 11/VI-2013 */ memcpy(env->ioerr_msg, msg, len); if (len > 0 && env->ioerr_msg[len-1] == '\n') len--; env->ioerr_msg[len] = '\0'; #else memcpy(env_ioerr_msg, msg, len); if (len > 0 && env_ioerr_msg[len-1] == '\n') len--; env_ioerr_msg[len] = '\0'; #endif return; } /*********************************************************************** * NAME * * xerrmsg - retrieve error message string * * SYNOPSIS * * #include "glpenv.h" * const char *xerrmsg(void); * * RETURNS * * The routine xerrmsg returns a pointer to an error message string * previously set by some library routine to indicate an error. */ const char *xerrmsg(void) { /*ENV *env = get_env_ptr();*/ #if 0 /* 11/VI-2013 */ return env->ioerr_msg; #else return env_ioerr_msg; #endif } /*********************************************************************** * NAME * * xfopen - open a stream * * SYNOPSIS * * #include "glpenv.h" * XFILE *xfopen(const char *fname, const char *mode); * * DESCRIPTION * * The routine xfopen opens the file whose name is a string pointed to * by fname and associates a stream with it. * * The parameter mode points to a string, which indicates the open mode * and should be one of the following: * * "r" open text file for reading; * "w" truncate to zero length or create text file for writing; * "rb" open binary file for reading; * "wb" truncate to zero length or create binary file for writing. * * RETURNS * * The routine xfopen returns a pointer to the object controlling the * stream. If the open operation fails, xfopen returns NULL. */ static void *c_fopen(const char *fname, const char *mode); static void *z_fopen(const char *fname, const char *mode); static int is_gz_file(const char *fname) { char *ext = strrchr(fname, '.'); return ext != NULL && strcmp(ext, ".gz") == 0; } XFILE *xfopen(const char *fname, const char *mode) { /*ENV *env = get_env_ptr();*/ XFILE *fp; int type; void *fh; if (!is_gz_file(fname)) { type = FH_FILE; fh = c_fopen(fname, mode); } else { type = FH_ZLIB; fh = z_fopen(fname, mode); } if (fh == NULL) { fp = NULL; goto done; } fp = xmalloc(sizeof(XFILE)); fp->type = type; fp->fh = fh; #if 0 /* 11/VI-2013 */ fp->prev = NULL; fp->next = env->file_ptr; if (fp->next != NULL) fp->next->prev = fp; env->file_ptr = fp; #endif done: return fp; } /*********************************************************************** * NAME * * xfgetc - read character from the stream * * SYNOPSIS * * #include "glpenv.h" * int xfgetc(XFILE *fp); * * DESCRIPTION * * If the end-of-file indicator for the input stream pointed to by fp * is not set and a next character is present, the routine xfgetc * obtains that character as an unsigned char converted to an int and * advances the associated file position indicator for the stream (if * defined). * * RETURNS * * If the end-of-file indicator for the stream is set, or if the * stream is at end-of-file, the end-of-file indicator for the stream * is set and the routine xfgetc returns XEOF. Otherwise, the routine * xfgetc returns the next character from the input stream pointed to * by fp. If a read error occurs, the error indicator for the stream is * set and the xfgetc routine returns XEOF. * * Note: An end-of-file and a read error can be distinguished by use of * the routines xfeof and xferror. */ static int c_fgetc(void *fh); static int z_fgetc(void *fh); int xfgetc(XFILE *fp) { int c; switch (fp->type) { case FH_FILE: c = c_fgetc(fp->fh); break; case FH_ZLIB: c = z_fgetc(fp->fh); break; default: xassert(fp != fp); } return c; } /*********************************************************************** * NAME * * xfputc - write character to the stream * * SYNOPSIS * * #include "glpenv.h" * int xfputc(int c, XFILE *fp); * * DESCRIPTION * * The routine xfputc writes the character specified by c (converted * to an unsigned char) to the output stream pointed to by fp, at the * position indicated by the associated file position indicator (if * defined), and advances the indicator appropriately. * * RETURNS * * The routine xfputc returns the character written. If a write error * occurs, the error indicator for the stream is set and xfputc returns * XEOF. */ static int c_fputc(int c, void *fh); static int z_fputc(int c, void *fh); int xfputc(int c, XFILE *fp) { switch (fp->type) { case FH_FILE: c = c_fputc(c, fp->fh); break; case FH_ZLIB: c = z_fputc(c, fp->fh); break; default: xassert(fp != fp); } return c; } /*********************************************************************** * NAME * * xferror - test error indicator for the stream * * SYNOPSIS * * #include "glpenv.h" * int xferror(XFILE *fp); * * DESCRIPTION * * The routine xferror tests the error indicator for the stream * pointed to by fp. * * RETURNS * * The routine xferror returns non-zero if and only if the error * indicator is set for the stream. */ static int c_ferror(void *fh); static int z_ferror(void *fh); int xferror(XFILE *fp) { int ret; switch (fp->type) { case FH_FILE: ret = c_ferror(fp->fh); break; case FH_ZLIB: ret = z_ferror(fp->fh); break; default: xassert(fp != fp); } return ret; } /*********************************************************************** * NAME * * xfeof - test end-of-file indicator for the stream * * SYNOPSIS * * #include "glpenv.h" * int xfeof(XFILE *fp); * * DESCRIPTION * * The routine xfeof tests the end-of-file indicator for the stream * pointed to by fp. * * RETURNS * * The routine xfeof returns non-zero if and only if the end-of-file * indicator is set for the stream. */ static int c_feof(void *fh); static int z_feof(void *fh); int xfeof(XFILE *fp) { int ret; switch (fp->type) { case FH_FILE: ret = c_feof(fp->fh); break; case FH_ZLIB: ret = z_feof(fp->fh); break; default: xassert(fp != fp); } return ret; } int xfprintf(XFILE *file, const char *fmt, ...) { ENV *env = get_env_ptr(); int cnt, j; va_list arg; va_start(arg, fmt); cnt = vsprintf(env->term_buf, fmt, arg); va_end(arg); for (j = 0; j < cnt; j++) { if (xfputc(env->term_buf[j], file) < 0) { cnt = -1; break; } } return cnt; } /*********************************************************************** * NAME * * xfflush - flush the stream * * SYNOPSIS * * #include "glpenv.h" * int xfflush(XFILE *fp); * * DESCRIPTION * * The routine xfflush causes any unwritten data for the output stream * pointed to by fp to be written to the associated file. * * RETURNS * * The routine xfflush returns zero if the stream was successfully * flushed. Otherwise, xfflush sets the error indicator for the stream * and returns XEOF. */ static int c_fflush(void *fh); static int z_fflush(void *fh); int xfflush(XFILE *fp) { int ret; switch (fp->type) { case FH_FILE: ret = c_fflush(fp->fh); break; case FH_ZLIB: ret = z_fflush(fp->fh); break; default: xassert(fp != fp); } return ret; } /*********************************************************************** * NAME * * xfclose - close the stream * * SYNOPSIS * * #include "glpenv.h" * int xfclose(XFILE *fp); * * DESCRIPTION * * A successful call to the routine xfclose causes the stream pointed * to by fp to be flushed and the associated file to be closed. Whether * or not the call succeeds, the stream is disassociated from the file. * * RETURNS * * The routine xfclose returns zero if the stream was successfully * closed, or XEOF if any errors were detected. */ static int c_fclose(void *fh); static int z_fclose(void *fh); int xfclose(XFILE *fp) { /*ENV *env = get_env_ptr();*/ int ret; switch (fp->type) { case FH_FILE: ret = c_fclose(fp->fh); break; case FH_ZLIB: ret = z_fclose(fp->fh); break; default: xassert(fp != fp); } fp->type = 0xF00BAD; #if 0 /* 11/VI-2013 */ if (fp->prev == NULL) env->file_ptr = fp->next; else fp->prev->next = fp->next; if (fp->next == NULL) ; else fp->next->prev = fp->prev; #endif xfree(fp); return ret; } /*********************************************************************** * The following routines implement stream input/output based on the * standard C streams. */ static void *c_fopen(const char *fname, const char *mode) { FILE *fh; if (strcmp(fname, "/dev/stdin") == 0) fh = stdin; else if (strcmp(fname, "/dev/stdout") == 0) fh = stdout; else if (strcmp(fname, "/dev/stderr") == 0) fh = stderr; else fh = fopen(fname, mode); if (fh == NULL) lib_err_msg(strerror(errno)); return fh; } static int c_fgetc(void *_fh) { FILE *fh = _fh; int c; if (ferror(fh) || feof(fh)) { c = XEOF; goto done; } c = fgetc(fh); if (ferror(fh)) { lib_err_msg(strerror(errno)); c = XEOF; } else if (feof(fh)) c = XEOF; else xassert(0x00 <= c && c <= 0xFF); done: return c; } static int c_fputc(int c, void *_fh) { FILE *fh = _fh; if (ferror(fh)) { c = XEOF; goto done; } c = (unsigned char)c; fputc(c, fh); if (ferror(fh)) { lib_err_msg(strerror(errno)); c = XEOF; } done: return c; } static int c_ferror(void *_fh) { FILE *fh = _fh; return ferror(fh); } static int c_feof(void *_fh) { FILE *fh = _fh; return feof(fh); } static int c_fflush(void *_fh) { FILE *fh = _fh; int ret; ret = fflush(fh); if (ret != 0) { lib_err_msg(strerror(errno)); ret = XEOF; } return ret; } static int c_fclose(void *_fh) { FILE *fh = _fh; int ret; if (fh == stdin) ret = 0; else if (fh == stdout || fh == stderr) fflush(fh), ret = 0; else ret = fclose(fh); if (ret != 0) { lib_err_msg(strerror(errno)); ret = XEOF; } return ret; } /*********************************************************************** * The following routines implement stream input/output based on the * zlib library, which provides processing .gz files "on the fly". */ struct z_file { /* .gz file handle */ gzFile file; /* pointer to .gz stream */ int err; /* i/o error indicator */ int eof; /* end-of-file indicator */ }; static void *z_fopen(const char *fname, const char *mode) { struct z_file *fh; gzFile file; if (strcmp(mode, "r") == 0 || strcmp(mode, "rb") == 0) mode = "rb"; else if (strcmp(mode, "w") == 0 || strcmp(mode, "wb") == 0) mode = "wb"; else { lib_err_msg("Invalid open mode"); fh = NULL; goto done; } file = gzopen(fname, mode); if (file == NULL) { lib_err_msg(strerror(errno)); fh = NULL; goto done; } fh = xmalloc(sizeof(struct z_file)); fh->file = file; fh->err = fh->eof = 0; done: return fh; } static int z_fgetc(void *_fh) { struct z_file *fh = _fh; int c; if (fh->err || fh->eof) { c = XEOF; goto done; } c = gzgetc(fh->file); if (c < 0) { int errnum; const char *msg; msg = gzerror(fh->file, &errnum); if (errnum == Z_STREAM_END) fh->eof = 1; else if (errnum == Z_ERRNO) { fh->err = 1; lib_err_msg(strerror(errno)); } else { fh->err = 1; lib_err_msg(msg); } c = XEOF; } else xassert(0x00 <= c && c <= 0xFF); done: return c; } static int z_fputc(int c, void *_fh) { struct z_file *fh = _fh; if (fh->err) { c = XEOF; goto done; } c = (unsigned char)c; if (gzputc(fh->file, c) < 0) { int errnum; const char *msg; fh->err = 1; msg = gzerror(fh->file, &errnum); if (errnum == Z_ERRNO) lib_err_msg(strerror(errno)); else lib_err_msg(msg); c = XEOF; } done: return c; } static int z_ferror(void *_fh) { struct z_file *fh = _fh; return fh->err; } static int z_feof(void *_fh) { struct z_file *fh = _fh; return fh->eof; } static int z_fflush(void *_fh) { struct z_file *fh = _fh; int ret; ret = gzflush(fh->file, Z_FINISH); if (ret == Z_OK) ret = 0; else { int errnum; const char *msg; fh->err = 1; msg = gzerror(fh->file, &errnum); if (errnum == Z_ERRNO) lib_err_msg(strerror(errno)); else lib_err_msg(msg); ret = XEOF; } return ret; } static int z_fclose(void *_fh) { struct z_file *fh = _fh; gzclose(fh->file); xfree(fh); return 0; } /* eof */ glpk-4.52.1/src/glpenv08.c0000644000062000006210000000744412175147600014330 0ustar maomkpasswd/* glpenv08.c (shared library support) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "env2.h" /* GNU version ********************************************************/ #if defined(HAVE_LTDL) #include void *xdlopen(const char *module) { void *h = NULL; if (lt_dlinit() != 0) { lib_err_msg(lt_dlerror()); goto done; } h = lt_dlopen(module); if (h == NULL) { lib_err_msg(lt_dlerror()); if (lt_dlexit() != 0) xerror("xdlopen: %s\n", lt_dlerror()); } done: return h; } void *xdlsym(void *h, const char *symbol) { void *ptr; xassert(h != NULL); ptr = lt_dlsym(h, symbol); if (ptr == NULL) xerror("xdlsym: %s: %s\n", symbol, lt_dlerror()); return ptr; } void xdlclose(void *h) { xassert(h != NULL); if (lt_dlclose(h) != 0) xerror("xdlclose: %s\n", lt_dlerror()); if (lt_dlexit() != 0) xerror("xdlclose: %s\n", lt_dlerror()); return; } /* POSIX version ******************************************************/ #elif defined(HAVE_DLFCN) #include void *xdlopen(const char *module) { void *h; h = dlopen(module, RTLD_NOW); if (h == NULL) lib_err_msg(dlerror()); return h; } void *xdlsym(void *h, const char *symbol) { void *ptr; xassert(h != NULL); ptr = dlsym(h, symbol); if (ptr == NULL) xerror("xdlsym: %s: %s\n", symbol, dlerror()); return ptr; } void xdlclose(void *h) { xassert(h != NULL); if (dlclose(h) != 0) xerror("xdlclose: %s\n", dlerror()); return; } /* MS Windows version *************************************************/ #elif defined(__WOE__) #include void *xdlopen(const char *module) { void *h; h = LoadLibrary(module); if (h == NULL) { char msg[20]; sprintf(msg, "Error %d", GetLastError()); lib_err_msg(msg); } return h; } void *xdlsym(void *h, const char *symbol) { void *ptr; xassert(h != NULL); ptr = GetProcAddress(h, symbol); if (ptr == NULL) xerror("xdlsym: %s: Error %d\n", symbol, GetLastError()); return ptr; } void xdlclose(void *h) { xassert(h != NULL); if (!FreeLibrary(h)) xerror("xdlclose: Error %d\n", GetLastError()); return; } /* NULL version *******************************************************/ #else void *xdlopen(const char *module) { xassert(module == module); lib_err_msg("Shared libraries not supported"); return NULL; } void *xdlsym(void *h, const char *symbol) { xassert(h != h); xassert(symbol != symbol); return NULL; } void xdlclose(void *h) { xassert(h != h); return; } #endif /* eof */ glpk-4.52.1/src/glpgmp.c0000644000062000006210000007603112175147600014151 0ustar maomkpasswd/* glpgmp.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_STDIO #if 1 /* 11/VI-2013 */ #include "bignum.h" #endif #include "dmp.h" #include "glpgmp.h" #include "env.h" #define xfault xerror #ifdef HAVE_GMP /* use GNU MP bignum library */ int gmp_pool_count(void) { return 0; } void gmp_free_mem(void) { return; } #else /* use GLPK bignum module */ static DMP *gmp_pool = NULL; static int gmp_size = 0; static unsigned short *gmp_work = NULL; void *gmp_get_atom(int size) { if (gmp_pool == NULL) gmp_pool = dmp_create_pool(); return dmp_get_atom(gmp_pool, size); } void gmp_free_atom(void *ptr, int size) { xassert(gmp_pool != NULL); dmp_free_atom(gmp_pool, ptr, size); return; } int gmp_pool_count(void) { if (gmp_pool == NULL) return 0; else #if 0 /* 10/VI-2013 */ return dmp_in_use(gmp_pool).lo; #else return dmp_in_use(gmp_pool); #endif } unsigned short *gmp_get_work(int size) { xassert(size > 0); if (gmp_size < size) { if (gmp_size == 0) { xassert(gmp_work == NULL); gmp_size = 100; } else { xassert(gmp_work != NULL); xfree(gmp_work); } while (gmp_size < size) gmp_size += gmp_size; gmp_work = xcalloc(gmp_size, sizeof(unsigned short)); } return gmp_work; } void gmp_free_mem(void) { if (gmp_pool != NULL) dmp_delete_pool(gmp_pool); if (gmp_work != NULL) xfree(gmp_work); gmp_pool = NULL; gmp_size = 0; gmp_work = NULL; return; } /*====================================================================*/ mpz_t _mpz_init(void) { /* initialize x, and set its value to 0 */ mpz_t x; x = gmp_get_atom(sizeof(struct mpz)); x->val = 0; x->ptr = NULL; return x; } void mpz_clear(mpz_t x) { /* free the space occupied by x */ mpz_set_si(x, 0); xassert(x->ptr == NULL); /* free the number descriptor */ gmp_free_atom(x, sizeof(struct mpz)); return; } void mpz_set(mpz_t z, mpz_t x) { /* set the value of z from x */ struct mpz_seg *e, *ee, *es; if (z != x) { mpz_set_si(z, 0); z->val = x->val; xassert(z->ptr == NULL); for (e = x->ptr, es = NULL; e != NULL; e = e->next) { ee = gmp_get_atom(sizeof(struct mpz_seg)); memcpy(ee->d, e->d, 12); ee->next = NULL; if (z->ptr == NULL) z->ptr = ee; else es->next = ee; es = ee; } } return; } void mpz_set_si(mpz_t x, int val) { /* set the value of x to val */ struct mpz_seg *e; /* free existing segments, if any */ while (x->ptr != NULL) { e = x->ptr; x->ptr = e->next; gmp_free_atom(e, sizeof(struct mpz_seg)); } /* assign new value */ if (val == 0x80000000) { /* long format is needed */ x->val = -1; x->ptr = e = gmp_get_atom(sizeof(struct mpz_seg)); memset(e->d, 0, 12); e->d[1] = 0x8000; e->next = NULL; } else { /* short format is enough */ x->val = val; } return; } double mpz_get_d(mpz_t x) { /* convert x to a double, truncating if necessary */ struct mpz_seg *e; int j; double val, deg; if (x->ptr == NULL) val = (double)x->val; else { xassert(x->val != 0); val = 0.0; deg = 1.0; for (e = x->ptr; e != NULL; e = e->next) { for (j = 0; j <= 5; j++) { val += deg * (double)((int)e->d[j]); deg *= 65536.0; } } if (x->val < 0) val = - val; } return val; } double mpz_get_d_2exp(int *exp, mpz_t x) { /* convert x to a double, truncating if necessary (i.e. rounding towards zero), and returning the exponent separately; the return value is in the range 0.5 <= |d| < 1 and the exponent is stored to *exp; d*2^exp is the (truncated) x value; if x is zero, the return is 0.0 and 0 is stored to *exp; this is similar to the standard C frexp function */ struct mpz_seg *e; int j, n, n1; double val; if (x->ptr == NULL) val = (double)x->val, n = 0; else { xassert(x->val != 0); val = 0.0, n = 0; for (e = x->ptr; e != NULL; e = e->next) { for (j = 0; j <= 5; j++) { val += (double)((int)e->d[j]); val /= 65536.0, n += 16; } } if (x->val < 0) val = - val; } val = frexp(val, &n1); *exp = n + n1; return val; } void mpz_swap(mpz_t x, mpz_t y) { /* swap the values x and y efficiently */ int val; void *ptr; val = x->val, ptr = x->ptr; x->val = y->val, x->ptr = y->ptr; y->val = val, y->ptr = ptr; return; } static void normalize(mpz_t x) { /* normalize integer x that includes removing non-significant (leading) zeros and converting to short format, if possible */ struct mpz_seg *es, *e; /* if the integer is in short format, it remains unchanged */ if (x->ptr == NULL) { xassert(x->val != 0x80000000); goto done; } xassert(x->val == +1 || x->val == -1); /* find the last (most significant) non-zero segment */ es = NULL; for (e = x->ptr; e != NULL; e = e->next) { if (e->d[0] || e->d[1] || e->d[2] || e->d[3] || e->d[4] || e->d[5]) es = e; } /* if all segments contain zeros, the integer is zero */ if (es == NULL) { mpz_set_si(x, 0); goto done; } /* remove non-significant (leading) zero segments */ while (es->next != NULL) { e = es->next; es->next = e->next; gmp_free_atom(e, sizeof(struct mpz_seg)); } /* convert the integer to short format, if possible */ e = x->ptr; if (e->next == NULL && e->d[1] <= 0x7FFF && !e->d[2] && !e->d[3] && !e->d[4] && !e->d[5]) { int val; val = (int)e->d[0] + ((int)e->d[1] << 16); if (x->val < 0) val = - val; mpz_set_si(x, val); } done: return; } void mpz_add(mpz_t z, mpz_t x, mpz_t y) { /* set z to x + y */ static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL }; struct mpz_seg dumx, dumy, *ex, *ey, *ez, *es, *ee; int k, sx, sy, sz; unsigned int t; /* if [x] = 0 then [z] = [y] */ if (x->val == 0) { xassert(x->ptr == NULL); mpz_set(z, y); goto done; } /* if [y] = 0 then [z] = [x] */ if (y->val == 0) { xassert(y->ptr == NULL); mpz_set(z, x); goto done; } /* special case when both [x] and [y] are in short format */ if (x->ptr == NULL && y->ptr == NULL) { int xval = x->val, yval = y->val, zval = x->val + y->val; xassert(xval != 0x80000000 && yval != 0x80000000); if (!(xval > 0 && yval > 0 && zval <= 0 || xval < 0 && yval < 0 && zval >= 0)) { mpz_set_si(z, zval); goto done; } } /* convert [x] to long format, if necessary */ if (x->ptr == NULL) { xassert(x->val != 0x80000000); if (x->val >= 0) { sx = +1; t = (unsigned int)(+ x->val); } else { sx = -1; t = (unsigned int)(- x->val); } ex = &dumx; ex->d[0] = (unsigned short)t; ex->d[1] = (unsigned short)(t >> 16); ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; ex->next = NULL; } else { sx = x->val; xassert(sx == +1 || sx == -1); ex = x->ptr; } /* convert [y] to long format, if necessary */ if (y->ptr == NULL) { xassert(y->val != 0x80000000); if (y->val >= 0) { sy = +1; t = (unsigned int)(+ y->val); } else { sy = -1; t = (unsigned int)(- y->val); } ey = &dumy; ey->d[0] = (unsigned short)t; ey->d[1] = (unsigned short)(t >> 16); ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; ey->next = NULL; } else { sy = y->val; xassert(sy == +1 || sy == -1); ey = y->ptr; } /* main fragment */ sz = sx; ez = es = NULL; if (sx > 0 && sy > 0 || sx < 0 && sy < 0) { /* [x] and [y] have identical signs -- addition */ t = 0; for (; ex || ey; ex = ex->next, ey = ey->next) { if (ex == NULL) ex = &zero; if (ey == NULL) ey = &zero; ee = gmp_get_atom(sizeof(struct mpz_seg)); for (k = 0; k <= 5; k++) { t += (unsigned int)ex->d[k]; t += (unsigned int)ey->d[k]; ee->d[k] = (unsigned short)t; t >>= 16; } ee->next = NULL; if (ez == NULL) ez = ee; else es->next = ee; es = ee; } if (t) { /* overflow -- one extra digit is needed */ ee = gmp_get_atom(sizeof(struct mpz_seg)); ee->d[0] = 1; ee->d[1] = ee->d[2] = ee->d[3] = ee->d[4] = ee->d[5] = 0; ee->next = NULL; xassert(es != NULL); es->next = ee; } } else { /* [x] and [y] have different signs -- subtraction */ t = 1; for (; ex || ey; ex = ex->next, ey = ey->next) { if (ex == NULL) ex = &zero; if (ey == NULL) ey = &zero; ee = gmp_get_atom(sizeof(struct mpz_seg)); for (k = 0; k <= 5; k++) { t += (unsigned int)ex->d[k]; t += (0xFFFF - (unsigned int)ey->d[k]); ee->d[k] = (unsigned short)t; t >>= 16; } ee->next = NULL; if (ez == NULL) ez = ee; else es->next = ee; es = ee; } if (!t) { /* |[x]| < |[y]| -- result in complement coding */ sz = - sz; t = 1; for (ee = ez; ee != NULL; ee = ee->next) for (k = 0; k <= 5; k++) { t += (0xFFFF - (unsigned int)ee->d[k]); ee->d[k] = (unsigned short)t; t >>= 16; } } } /* contruct and normalize result */ mpz_set_si(z, 0); z->val = sz; z->ptr = ez; normalize(z); done: return; } void mpz_sub(mpz_t z, mpz_t x, mpz_t y) { /* set z to x - y */ if (x == y) mpz_set_si(z, 0); else { y->val = - y->val; mpz_add(z, x, y); if (y != z) y->val = - y->val; } return; } void mpz_mul(mpz_t z, mpz_t x, mpz_t y) { /* set z to x * y */ struct mpz_seg dumx, dumy, *ex, *ey, *es, *e; int sx, sy, k, nx, ny, n; unsigned int t; unsigned short *work, *wx, *wy; /* if [x] = 0 then [z] = 0 */ if (x->val == 0) { xassert(x->ptr == NULL); mpz_set_si(z, 0); goto done; } /* if [y] = 0 then [z] = 0 */ if (y->val == 0) { xassert(y->ptr == NULL); mpz_set_si(z, 0); goto done; } /* special case when both [x] and [y] are in short format */ if (x->ptr == NULL && y->ptr == NULL) { int xval = x->val, yval = y->val, sz = +1; xassert(xval != 0x80000000 && yval != 0x80000000); if (xval < 0) xval = - xval, sz = - sz; if (yval < 0) yval = - yval, sz = - sz; if (xval <= 0x7FFFFFFF / yval) { mpz_set_si(z, sz * (xval * yval)); goto done; } } /* convert [x] to long format, if necessary */ if (x->ptr == NULL) { xassert(x->val != 0x80000000); if (x->val >= 0) { sx = +1; t = (unsigned int)(+ x->val); } else { sx = -1; t = (unsigned int)(- x->val); } ex = &dumx; ex->d[0] = (unsigned short)t; ex->d[1] = (unsigned short)(t >> 16); ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; ex->next = NULL; } else { sx = x->val; xassert(sx == +1 || sx == -1); ex = x->ptr; } /* convert [y] to long format, if necessary */ if (y->ptr == NULL) { xassert(y->val != 0x80000000); if (y->val >= 0) { sy = +1; t = (unsigned int)(+ y->val); } else { sy = -1; t = (unsigned int)(- y->val); } ey = &dumy; ey->d[0] = (unsigned short)t; ey->d[1] = (unsigned short)(t >> 16); ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; ey->next = NULL; } else { sy = y->val; xassert(sy == +1 || sy == -1); ey = y->ptr; } /* determine the number of digits of [x] */ nx = n = 0; for (e = ex; e != NULL; e = e->next) for (k = 0; k <= 5; k++) { n++; if (e->d[k]) nx = n; } xassert(nx > 0); /* determine the number of digits of [y] */ ny = n = 0; for (e = ey; e != NULL; e = e->next) for (k = 0; k <= 5; k++) { n++; if (e->d[k]) ny = n; } xassert(ny > 0); /* we need working array containing at least nx+ny+ny places */ work = gmp_get_work(nx+ny+ny); /* load digits of [x] */ wx = &work[0]; for (n = 0; n < nx; n++) wx[ny+n] = 0; for (n = 0, e = ex; e != NULL; e = e->next) for (k = 0; k <= 5; k++, n++) if (e->d[k]) wx[ny+n] = e->d[k]; /* load digits of [y] */ wy = &work[nx+ny]; for (n = 0; n < ny; n++) wy[n] = 0; for (n = 0, e = ey; e != NULL; e = e->next) for (k = 0; k <= 5; k++, n++) if (e->d[k]) wy[n] = e->d[k]; /* compute [x] * [y] */ bigmul(nx, ny, wx, wy); /* construct and normalize result */ mpz_set_si(z, 0); z->val = sx * sy; es = NULL; k = 6; for (n = 0; n < nx+ny; n++) { if (k > 5) { e = gmp_get_atom(sizeof(struct mpz_seg)); e->d[0] = e->d[1] = e->d[2] = 0; e->d[3] = e->d[4] = e->d[5] = 0; e->next = NULL; if (z->ptr == NULL) z->ptr = e; else es->next = e; es = e; k = 0; } es->d[k++] = wx[n]; } normalize(z); done: return; } void mpz_neg(mpz_t z, mpz_t x) { /* set z to 0 - x */ mpz_set(z, x); z->val = - z->val; return; } void mpz_abs(mpz_t z, mpz_t x) { /* set z to the absolute value of x */ mpz_set(z, x); if (z->val < 0) z->val = - z->val; return; } void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y) { /* divide x by y, forming quotient q and/or remainder r if q = NULL then quotient is not stored; if r = NULL then remainder is not stored the sign of quotient is determined as in algebra while the sign of remainder is the same as the sign of dividend: +26 : +7 = +3, remainder is +5 -26 : +7 = -3, remainder is -5 +26 : -7 = -3, remainder is +5 -26 : -7 = +3, remainder is -5 */ struct mpz_seg dumx, dumy, *ex, *ey, *es, *e; int sx, sy, k, nx, ny, n; unsigned int t; unsigned short *work, *wx, *wy; /* divide by zero is not allowed */ if (y->val == 0) { xassert(y->ptr == NULL); xfault("mpz_div: divide by zero not allowed\n"); } /* if [x] = 0 then [q] = [r] = 0 */ if (x->val == 0) { xassert(x->ptr == NULL); if (q != NULL) mpz_set_si(q, 0); if (r != NULL) mpz_set_si(r, 0); goto done; } /* special case when both [x] and [y] are in short format */ if (x->ptr == NULL && y->ptr == NULL) { int xval = x->val, yval = y->val; xassert(xval != 0x80000000 && yval != 0x80000000); if (q != NULL) mpz_set_si(q, xval / yval); if (r != NULL) mpz_set_si(r, xval % yval); goto done; } /* convert [x] to long format, if necessary */ if (x->ptr == NULL) { xassert(x->val != 0x80000000); if (x->val >= 0) { sx = +1; t = (unsigned int)(+ x->val); } else { sx = -1; t = (unsigned int)(- x->val); } ex = &dumx; ex->d[0] = (unsigned short)t; ex->d[1] = (unsigned short)(t >> 16); ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; ex->next = NULL; } else { sx = x->val; xassert(sx == +1 || sx == -1); ex = x->ptr; } /* convert [y] to long format, if necessary */ if (y->ptr == NULL) { xassert(y->val != 0x80000000); if (y->val >= 0) { sy = +1; t = (unsigned int)(+ y->val); } else { sy = -1; t = (unsigned int)(- y->val); } ey = &dumy; ey->d[0] = (unsigned short)t; ey->d[1] = (unsigned short)(t >> 16); ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; ey->next = NULL; } else { sy = y->val; xassert(sy == +1 || sy == -1); ey = y->ptr; } /* determine the number of digits of [x] */ nx = n = 0; for (e = ex; e != NULL; e = e->next) for (k = 0; k <= 5; k++) { n++; if (e->d[k]) nx = n; } xassert(nx > 0); /* determine the number of digits of [y] */ ny = n = 0; for (e = ey; e != NULL; e = e->next) for (k = 0; k <= 5; k++) { n++; if (e->d[k]) ny = n; } xassert(ny > 0); /* if nx < ny then [q] = 0 and [r] = [x] */ if (nx < ny) { if (r != NULL) mpz_set(r, x); if (q != NULL) mpz_set_si(q, 0); goto done; } /* we need working array containing at least nx+ny+1 places */ work = gmp_get_work(nx+ny+1); /* load digits of [x] */ wx = &work[0]; for (n = 0; n < nx; n++) wx[n] = 0; for (n = 0, e = ex; e != NULL; e = e->next) for (k = 0; k <= 5; k++, n++) if (e->d[k]) wx[n] = e->d[k]; /* load digits of [y] */ wy = &work[nx+1]; for (n = 0; n < ny; n++) wy[n] = 0; for (n = 0, e = ey; e != NULL; e = e->next) for (k = 0; k <= 5; k++, n++) if (e->d[k]) wy[n] = e->d[k]; /* compute quotient and remainder */ xassert(wy[ny-1] != 0); bigdiv(nx-ny, ny, wx, wy); /* construct and normalize quotient */ if (q != NULL) { mpz_set_si(q, 0); q->val = sx * sy; es = NULL; k = 6; for (n = ny; n <= nx; n++) { if (k > 5) { e = gmp_get_atom(sizeof(struct mpz_seg)); e->d[0] = e->d[1] = e->d[2] = 0; e->d[3] = e->d[4] = e->d[5] = 0; e->next = NULL; if (q->ptr == NULL) q->ptr = e; else es->next = e; es = e; k = 0; } es->d[k++] = wx[n]; } normalize(q); } /* construct and normalize remainder */ if (r != NULL) { mpz_set_si(r, 0); r->val = sx; es = NULL; k = 6; for (n = 0; n < ny; n++) { if (k > 5) { e = gmp_get_atom(sizeof(struct mpz_seg)); e->d[0] = e->d[1] = e->d[2] = 0; e->d[3] = e->d[4] = e->d[5] = 0; e->next = NULL; if (r->ptr == NULL) r->ptr = e; else es->next = e; es = e; k = 0; } es->d[k++] = wx[n]; } normalize(r); } done: return; } void mpz_gcd(mpz_t z, mpz_t x, mpz_t y) { /* set z to the greatest common divisor of x and y */ /* in case of arbitrary integers GCD(x, y) = GCD(|x|, |y|), and, in particular, GCD(0, 0) = 0 */ mpz_t u, v, r; mpz_init(u); mpz_init(v); mpz_init(r); mpz_abs(u, x); mpz_abs(v, y); while (mpz_sgn(v)) { mpz_div(NULL, r, u, v); mpz_set(u, v); mpz_set(v, r); } mpz_set(z, u); mpz_clear(u); mpz_clear(v); mpz_clear(r); return; } int mpz_cmp(mpz_t x, mpz_t y) { /* compare x and y; return a positive value if x > y, zero if x = y, or a nefative value if x < y */ static struct mpz_seg zero = { { 0, 0, 0, 0, 0, 0 }, NULL }; struct mpz_seg dumx, dumy, *ex, *ey; int cc, sx, sy, k; unsigned int t; if (x == y) { cc = 0; goto done; } /* special case when both [x] and [y] are in short format */ if (x->ptr == NULL && y->ptr == NULL) { int xval = x->val, yval = y->val; xassert(xval != 0x80000000 && yval != 0x80000000); cc = (xval > yval ? +1 : xval < yval ? -1 : 0); goto done; } /* special case when [x] and [y] have different signs */ if (x->val > 0 && y->val <= 0 || x->val == 0 && y->val < 0) { cc = +1; goto done; } if (x->val < 0 && y->val >= 0 || x->val == 0 && y->val > 0) { cc = -1; goto done; } /* convert [x] to long format, if necessary */ if (x->ptr == NULL) { xassert(x->val != 0x80000000); if (x->val >= 0) { sx = +1; t = (unsigned int)(+ x->val); } else { sx = -1; t = (unsigned int)(- x->val); } ex = &dumx; ex->d[0] = (unsigned short)t; ex->d[1] = (unsigned short)(t >> 16); ex->d[2] = ex->d[3] = ex->d[4] = ex->d[5] = 0; ex->next = NULL; } else { sx = x->val; xassert(sx == +1 || sx == -1); ex = x->ptr; } /* convert [y] to long format, if necessary */ if (y->ptr == NULL) { xassert(y->val != 0x80000000); if (y->val >= 0) { sy = +1; t = (unsigned int)(+ y->val); } else { sy = -1; t = (unsigned int)(- y->val); } ey = &dumy; ey->d[0] = (unsigned short)t; ey->d[1] = (unsigned short)(t >> 16); ey->d[2] = ey->d[3] = ey->d[4] = ey->d[5] = 0; ey->next = NULL; } else { sy = y->val; xassert(sy == +1 || sy == -1); ey = y->ptr; } /* main fragment */ xassert(sx > 0 && sy > 0 || sx < 0 && sy < 0); cc = 0; for (; ex || ey; ex = ex->next, ey = ey->next) { if (ex == NULL) ex = &zero; if (ey == NULL) ey = &zero; for (k = 0; k <= 5; k++) { if (ex->d[k] > ey->d[k]) cc = +1; if (ex->d[k] < ey->d[k]) cc = -1; } } if (sx < 0) cc = - cc; done: return cc; } int mpz_sgn(mpz_t x) { /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ int s; s = (x->val > 0 ? +1 : x->val < 0 ? -1 : 0); return s; } int mpz_out_str(void *_fp, int base, mpz_t x) { /* output x on stream fp, as a string in given base; the base may vary from 2 to 36; return the number of bytes written, or if an error occurred, return 0 */ FILE *fp = _fp; mpz_t b, y, r; int n, j, nwr = 0; unsigned char *d; static char *set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (!(2 <= base && base <= 36)) xfault("mpz_out_str: base = %d; invalid base\n", base); mpz_init(b); mpz_set_si(b, base); mpz_init(y); mpz_init(r); /* determine the number of digits */ mpz_abs(y, x); for (n = 0; mpz_sgn(y) != 0; n++) mpz_div(y, NULL, y, b); if (n == 0) n = 1; /* compute the digits */ d = xmalloc(n); mpz_abs(y, x); for (j = 0; j < n; j++) { mpz_div(y, r, y, b); xassert(0 <= r->val && r->val < base && r->ptr == NULL); d[j] = (unsigned char)r->val; } /* output the integer to the stream */ if (fp == NULL) fp = stdout; if (mpz_sgn(x) < 0) fputc('-', fp), nwr++; for (j = n-1; j >= 0; j--) fputc(set[d[j]], fp), nwr++; if (ferror(fp)) nwr = 0; mpz_clear(b); mpz_clear(y); mpz_clear(r); xfree(d); return nwr; } /*====================================================================*/ mpq_t _mpq_init(void) { /* initialize x, and set its value to 0/1 */ mpq_t x; x = gmp_get_atom(sizeof(struct mpq)); x->p.val = 0; x->p.ptr = NULL; x->q.val = 1; x->q.ptr = NULL; return x; } void mpq_clear(mpq_t x) { /* free the space occupied by x */ mpz_set_si(&x->p, 0); xassert(x->p.ptr == NULL); mpz_set_si(&x->q, 0); xassert(x->q.ptr == NULL); /* free the number descriptor */ gmp_free_atom(x, sizeof(struct mpq)); return; } void mpq_canonicalize(mpq_t x) { /* remove any factors that are common to the numerator and denominator of x, and make the denominator positive */ mpz_t f; xassert(x->q.val != 0); if (x->q.val < 0) { mpz_neg(&x->p, &x->p); mpz_neg(&x->q, &x->q); } mpz_init(f); mpz_gcd(f, &x->p, &x->q); if (!(f->val == 1 && f->ptr == NULL)) { mpz_div(&x->p, NULL, &x->p, f); mpz_div(&x->q, NULL, &x->q, f); } mpz_clear(f); return; } void mpq_set(mpq_t z, mpq_t x) { /* set the value of z from x */ if (z != x) { mpz_set(&z->p, &x->p); mpz_set(&z->q, &x->q); } return; } void mpq_set_si(mpq_t x, int p, unsigned int q) { /* set the value of x to p/q */ if (q == 0) xfault("mpq_set_si: zero denominator not allowed\n"); mpz_set_si(&x->p, p); xassert(q <= 0x7FFFFFFF); mpz_set_si(&x->q, q); return; } double mpq_get_d(mpq_t x) { /* convert x to a double, truncating if necessary */ int np, nq; double p, q; p = mpz_get_d_2exp(&np, &x->p); q = mpz_get_d_2exp(&nq, &x->q); return ldexp(p / q, np - nq); } void mpq_set_d(mpq_t x, double val) { /* set x to val; there is no rounding, the conversion is exact */ int s, n, d, j; double f; mpz_t temp; xassert(-DBL_MAX <= val && val <= +DBL_MAX); mpq_set_si(x, 0, 1); if (val > 0.0) s = +1; else if (val < 0.0) s = -1; else goto done; f = frexp(fabs(val), &n); /* |val| = f * 2^n, where 0.5 <= f < 1.0 */ mpz_init(temp); while (f != 0.0) { f *= 16.0, n -= 4; d = (int)f; xassert(0 <= d && d <= 15); f -= (double)d; /* x := 16 * x + d */ mpz_set_si(temp, 16); mpz_mul(&x->p, &x->p, temp); mpz_set_si(temp, d); mpz_add(&x->p, &x->p, temp); } mpz_clear(temp); /* x := x * 2^n */ if (n > 0) { for (j = 1; j <= n; j++) mpz_add(&x->p, &x->p, &x->p); } else if (n < 0) { for (j = 1; j <= -n; j++) mpz_add(&x->q, &x->q, &x->q); mpq_canonicalize(x); } if (s < 0) mpq_neg(x, x); done: return; } void mpq_add(mpq_t z, mpq_t x, mpq_t y) { /* set z to x + y */ mpz_t p, q; mpz_init(p); mpz_init(q); mpz_mul(p, &x->p, &y->q); mpz_mul(q, &x->q, &y->p); mpz_add(p, p, q); mpz_mul(q, &x->q, &y->q); mpz_set(&z->p, p); mpz_set(&z->q, q); mpz_clear(p); mpz_clear(q); mpq_canonicalize(z); return; } void mpq_sub(mpq_t z, mpq_t x, mpq_t y) { /* set z to x - y */ mpz_t p, q; mpz_init(p); mpz_init(q); mpz_mul(p, &x->p, &y->q); mpz_mul(q, &x->q, &y->p); mpz_sub(p, p, q); mpz_mul(q, &x->q, &y->q); mpz_set(&z->p, p); mpz_set(&z->q, q); mpz_clear(p); mpz_clear(q); mpq_canonicalize(z); return; } void mpq_mul(mpq_t z, mpq_t x, mpq_t y) { /* set z to x * y */ mpz_mul(&z->p, &x->p, &y->p); mpz_mul(&z->q, &x->q, &y->q); mpq_canonicalize(z); return; } void mpq_div(mpq_t z, mpq_t x, mpq_t y) { /* set z to x / y */ mpz_t p, q; if (mpq_sgn(y) == 0) xfault("mpq_div: zero divisor not allowed\n"); mpz_init(p); mpz_init(q); mpz_mul(p, &x->p, &y->q); mpz_mul(q, &x->q, &y->p); mpz_set(&z->p, p); mpz_set(&z->q, q); mpz_clear(p); mpz_clear(q); mpq_canonicalize(z); return; } void mpq_neg(mpq_t z, mpq_t x) { /* set z to 0 - x */ mpq_set(z, x); mpz_neg(&z->p, &z->p); return; } void mpq_abs(mpq_t z, mpq_t x) { /* set z to the absolute value of x */ mpq_set(z, x); mpz_abs(&z->p, &z->p); xassert(mpz_sgn(&x->q) > 0); return; } int mpq_cmp(mpq_t x, mpq_t y) { /* compare x and y; return a positive value if x > y, zero if x = y, or a nefative value if x < y */ mpq_t temp; int s; mpq_init(temp); mpq_sub(temp, x, y); s = mpq_sgn(temp); mpq_clear(temp); return s; } int mpq_sgn(mpq_t x) { /* return +1 if x > 0, 0 if x = 0, and -1 if x < 0 */ int s; s = mpz_sgn(&x->p); xassert(mpz_sgn(&x->q) > 0); return s; } int mpq_out_str(void *_fp, int base, mpq_t x) { /* output x on stream fp, as a string in given base; the base may vary from 2 to 36; output is in the form 'num/den' or if the denominator is 1 then just 'num'; if the parameter fp is a null pointer, stdout is assumed; return the number of bytes written, or if an error occurred, return 0 */ FILE *fp = _fp; int nwr; if (!(2 <= base && base <= 36)) xfault("mpq_out_str: base = %d; invalid base\n", base); if (fp == NULL) fp = stdout; nwr = mpz_out_str(fp, base, &x->p); if (x->q.val == 1 && x->q.ptr == NULL) ; else { fputc('/', fp), nwr++; nwr += mpz_out_str(fp, base, &x->q); } if (ferror(fp)) nwr = 0; return nwr; } #endif /* eof */ glpk-4.52.1/src/glpgmp.h0000644000062000006210000001433112175147600014151 0ustar maomkpasswd/* glpgmp.h (bignum arithmetic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPGMP_H #define GLPGMP_H #ifdef HAVE_CONFIG_H #include #endif #ifdef HAVE_GMP /* use GNU MP bignum library */ #include #define gmp_pool_count _glp_gmp_pool_count #define gmp_free_mem _glp_gmp_free_mem int gmp_pool_count(void); void gmp_free_mem(void); #else /* use GLPK bignum module */ /*---------------------------------------------------------------------- // INTEGER NUMBERS // // Depending on its magnitude an integer number of arbitrary precision // is represented either in short format or in long format. // // Short format corresponds to the int type and allows representing // integer numbers in the range [-(2^31-1), +(2^31-1)]. Note that for // the most negative number of int type the short format is not used. // // In long format integer numbers are represented using the positional // system with the base (radix) 2^16 = 65536: // // x = (-1)^s sum{j in 0..n-1} d[j] * 65536^j, // // where x is the integer to be represented, s is its sign (+1 or -1), // d[j] are its digits (0 <= d[j] <= 65535). // // RATIONAL NUMBERS // // A rational number is represented as an irreducible fraction: // // p / q, // // where p (numerator) and q (denominator) are integer numbers (q > 0) // having no common divisors. */ struct mpz { /* integer number */ int val; /* if ptr is a null pointer, the number is in short format, and val is its value; otherwise, the number is in long format, and val is its sign (+1 or -1) */ struct mpz_seg *ptr; /* pointer to the linked list of the number segments ordered in ascending of powers of the base */ }; struct mpz_seg { /* integer number segment */ unsigned short d[6]; /* six digits of the number ordered in ascending of powers of the base */ struct mpz_seg *next; /* pointer to the next number segment */ }; struct mpq { /* rational number (p / q) */ struct mpz p; /* numerator */ struct mpz q; /* denominator */ }; typedef struct mpz *mpz_t; typedef struct mpq *mpq_t; #define gmp_get_atom _glp_gmp_get_atom #define gmp_free_atom _glp_gmp_free_atom #define gmp_pool_count _glp_gmp_pool_count #define gmp_get_work _glp_gmp_get_work #define gmp_free_mem _glp_gmp_free_mem #define _mpz_init _glp_mpz_init #define mpz_clear _glp_mpz_clear #define mpz_set _glp_mpz_set #define mpz_set_si _glp_mpz_set_si #define mpz_get_d _glp_mpz_get_d #define mpz_get_d_2exp _glp_mpz_get_d_2exp #define mpz_swap _glp_mpz_swap #define mpz_add _glp_mpz_add #define mpz_sub _glp_mpz_sub #define mpz_mul _glp_mpz_mul #define mpz_neg _glp_mpz_neg #define mpz_abs _glp_mpz_abs #define mpz_div _glp_mpz_div #define mpz_gcd _glp_mpz_gcd #define mpz_cmp _glp_mpz_cmp #define mpz_sgn _glp_mpz_sgn #define mpz_out_str _glp_mpz_out_str #define _mpq_init _glp_mpq_init #define mpq_clear _glp_mpq_clear #define mpq_canonicalize _glp_mpq_canonicalize #define mpq_set _glp_mpq_set #define mpq_set_si _glp_mpq_set_si #define mpq_get_d _glp_mpq_get_d #define mpq_set_d _glp_mpq_set_d #define mpq_add _glp_mpq_add #define mpq_sub _glp_mpq_sub #define mpq_mul _glp_mpq_mul #define mpq_div _glp_mpq_div #define mpq_neg _glp_mpq_neg #define mpq_abs _glp_mpq_abs #define mpq_cmp _glp_mpq_cmp #define mpq_sgn _glp_mpq_sgn #define mpq_out_str _glp_mpq_out_str void *gmp_get_atom(int size); void gmp_free_atom(void *ptr, int size); int gmp_pool_count(void); unsigned short *gmp_get_work(int size); void gmp_free_mem(void); mpz_t _mpz_init(void); #define mpz_init(x) (void)((x) = _mpz_init()) void mpz_clear(mpz_t x); void mpz_set(mpz_t z, mpz_t x); void mpz_set_si(mpz_t x, int val); double mpz_get_d(mpz_t x); double mpz_get_d_2exp(int *exp, mpz_t x); void mpz_swap(mpz_t x, mpz_t y); void mpz_add(mpz_t, mpz_t, mpz_t); void mpz_sub(mpz_t, mpz_t, mpz_t); void mpz_mul(mpz_t, mpz_t, mpz_t); void mpz_neg(mpz_t z, mpz_t x); void mpz_abs(mpz_t z, mpz_t x); void mpz_div(mpz_t q, mpz_t r, mpz_t x, mpz_t y); void mpz_gcd(mpz_t z, mpz_t x, mpz_t y); int mpz_cmp(mpz_t x, mpz_t y); int mpz_sgn(mpz_t x); int mpz_out_str(void *fp, int base, mpz_t x); mpq_t _mpq_init(void); #define mpq_init(x) (void)((x) = _mpq_init()) void mpq_clear(mpq_t x); void mpq_canonicalize(mpq_t x); void mpq_set(mpq_t z, mpq_t x); void mpq_set_si(mpq_t x, int p, unsigned int q); double mpq_get_d(mpq_t x); void mpq_set_d(mpq_t x, double val); void mpq_add(mpq_t z, mpq_t x, mpq_t y); void mpq_sub(mpq_t z, mpq_t x, mpq_t y); void mpq_mul(mpq_t z, mpq_t x, mpq_t y); void mpq_div(mpq_t z, mpq_t x, mpq_t y); void mpq_neg(mpq_t z, mpq_t x); void mpq_abs(mpq_t z, mpq_t x); int mpq_cmp(mpq_t x, mpq_t y); int mpq_sgn(mpq_t x); int mpq_out_str(void *fp, int base, mpq_t x); #endif #endif /* eof */ glpk-4.52.1/src/glphbm.c0000644000062000006210000004623012175147600014132 0ustar maomkpasswd/* glphbm.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_ERRNO #define _GLPSTD_STDIO #include "env.h" #include "glphbm.h" #include "glplib.h" /*********************************************************************** * NAME * * hbm_read_mat - read sparse matrix in Harwell-Boeing format * * SYNOPSIS * * #include "glphbm.h" * HBM *hbm_read_mat(const char *fname); * * DESCRIPTION * * The routine hbm_read_mat reads a sparse matrix in the Harwell-Boeing * format from a text file whose name is the character string fname. * * Detailed description of the Harwell-Boeing format recognised by this * routine is given in the following report: * * I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing * Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992. * * RETURNS * * If no error occured, the routine hbm_read_mat returns a pointer to * a data structure containing the matrix. In case of error the routine * prints an appropriate error message and returns NULL. */ struct dsa { /* working area used by routine hbm_read_mat */ const char *fname; /* name of input text file */ FILE *fp; /* stream assigned to input text file */ int seqn; /* card sequential number */ char card[80+1]; /* card image buffer */ int fmt_p; /* scale factor */ int fmt_k; /* iterator */ int fmt_f; /* format code */ int fmt_w; /* field width */ int fmt_d; /* number of decimal places after point */ }; /*********************************************************************** * read_card - read next data card * * This routine reads the next 80-column card from the input text file * and stores its image into the character string card. If the card was * read successfully, the routine returns zero, otherwise non-zero. */ #if 1 /* 11/III-2012 */ static int read_card(struct dsa *dsa) { int c, len = 0; char buf[255+1]; dsa->seqn++; for (;;) { c = fgetc(dsa->fp); if (c == EOF) { if (ferror(dsa->fp)) xprintf("%s:%d: read error\n", dsa->fname, dsa->seqn); else xprintf("%s:%d: unexpected end-of-file\n", dsa->fname, dsa->seqn); return 1; } else if (c == '\r') /* nop */; else if (c == '\n') break; else if (iscntrl(c)) { xprintf("%s:%d: invalid control character\n", dsa->fname, dsa->seqn, c); return 1; } else { if (len == sizeof(buf)-1) goto err; buf[len++] = (char)c; } } /* remove trailing spaces */ while (len > 80 && buf[len-1] == ' ') len--; buf[len] = '\0'; /* line should not be longer than 80 chars */ if (len > 80) err: { xerror("%s:%d: card image too long\n", dsa->fname, dsa->seqn); return 1; } /* padd by spaces to 80-column card image */ strcpy(dsa->card, buf); memset(&dsa->card[len], ' ', 80 - len); dsa->card[80] = '\0'; return 0; } #endif /*********************************************************************** * scan_int - scan integer value from the current card * * This routine scans an integer value from the current card, where fld * is the name of the field, pos is the position of the field, width is * the width of the field, val points to a location to which the scanned * value should be stored. If the value was scanned successfully, the * routine returns zero, otherwise non-zero. */ static int scan_int(struct dsa *dsa, char *fld, int pos, int width, int *val) { char str[80+1]; xassert(1 <= width && width <= 80); memcpy(str, dsa->card + pos, width), str[width] = '\0'; if (str2int(strspx(str), val)) { xprintf("%s:%d: field `%s' contains invalid value `%s'\n", dsa->fname, dsa->seqn, fld, str); return 1; } return 0; } /*********************************************************************** * parse_fmt - parse Fortran format specification * * This routine parses the Fortran format specification represented as * character string which fmt points to and stores format elements into * appropriate static locations. Should note that not all valid Fortran * format specifications may be recognised. If the format specification * was recognised, the routine returns zero, otherwise non-zero. */ static int parse_fmt(struct dsa *dsa, char *fmt) { int k, s, val; char str[80+1]; /* first character should be left parenthesis */ if (fmt[0] != '(') fail: { xprintf("hbm_read_mat: format `%s' not recognised\n", fmt); return 1; } k = 1; /* optional scale factor */ dsa->fmt_p = 0; if (isdigit((unsigned char)fmt[k])) { s = 0; while (isdigit((unsigned char)fmt[k])) { if (s == 80) goto fail; str[s++] = fmt[k++]; } str[s] = '\0'; if (str2int(str, &val)) goto fail; if (toupper((unsigned char)fmt[k]) != 'P') goto iter; dsa->fmt_p = val, k++; if (!(0 <= dsa->fmt_p && dsa->fmt_p <= 255)) goto fail; /* optional comma may follow scale factor */ if (fmt[k] == ',') k++; } /* optional iterator */ dsa->fmt_k = 1; if (isdigit((unsigned char)fmt[k])) { s = 0; while (isdigit((unsigned char)fmt[k])) { if (s == 80) goto fail; str[s++] = fmt[k++]; } str[s] = '\0'; if (str2int(str, &val)) goto fail; iter: dsa->fmt_k = val; if (!(1 <= dsa->fmt_k && dsa->fmt_k <= 255)) goto fail; } /* format code */ dsa->fmt_f = toupper((unsigned char)fmt[k++]); if (!(dsa->fmt_f == 'D' || dsa->fmt_f == 'E' || dsa->fmt_f == 'F' || dsa->fmt_f == 'G' || dsa->fmt_f == 'I')) goto fail; /* field width */ if (!isdigit((unsigned char)fmt[k])) goto fail; s = 0; while (isdigit((unsigned char)fmt[k])) { if (s == 80) goto fail; str[s++] = fmt[k++]; } str[s] = '\0'; if (str2int(str, &dsa->fmt_w)) goto fail; if (!(1 <= dsa->fmt_w && dsa->fmt_w <= 255)) goto fail; /* optional number of decimal places after point */ dsa->fmt_d = 0; if (fmt[k] == '.') { k++; if (!isdigit((unsigned char)fmt[k])) goto fail; s = 0; while (isdigit((unsigned char)fmt[k])) { if (s == 80) goto fail; str[s++] = fmt[k++]; } str[s] = '\0'; if (str2int(str, &dsa->fmt_d)) goto fail; if (!(0 <= dsa->fmt_d && dsa->fmt_d <= 255)) goto fail; } /* last character should be right parenthesis */ if (!(fmt[k] == ')' && fmt[k+1] == '\0')) goto fail; return 0; } /*********************************************************************** * read_int_array - read array of integer type * * This routine reads an integer array from the input text file, where * name is array name, fmt is Fortran format specification that controls * reading, n is number of array elements, val is array of integer type. * If the array was read successful, the routine returns zero, otherwise * non-zero. */ static int read_int_array(struct dsa *dsa, char *name, char *fmt, int n, int val[]) { int k, pos; char str[80+1]; if (parse_fmt(dsa, fmt)) return 1; if (!(dsa->fmt_f == 'I' && dsa->fmt_w <= 80 && dsa->fmt_k * dsa->fmt_w <= 80)) { xprintf( "%s:%d: can't read array `%s' - invalid format `%s'\n", dsa->fname, dsa->seqn, name, fmt); return 1; } for (k = 1, pos = INT_MAX; k <= n; k++, pos++) { if (pos >= dsa->fmt_k) { if (read_card(dsa)) return 1; pos = 0; } memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w); str[dsa->fmt_w] = '\0'; strspx(str); if (str2int(str, &val[k])) { xprintf( "%s:%d: can't read array `%s' - invalid value `%s'\n", dsa->fname, dsa->seqn, name, str); return 1; } } return 0; } /*********************************************************************** * read_real_array - read array of real type * * This routine reads a real array from the input text file, where name * is array name, fmt is Fortran format specification that controls * reading, n is number of array elements, val is array of real type. * If the array was read successful, the routine returns zero, otherwise * non-zero. */ static int read_real_array(struct dsa *dsa, char *name, char *fmt, int n, double val[]) { int k, pos; char str[80+1], *ptr; if (parse_fmt(dsa, fmt)) return 1; if (!(dsa->fmt_f != 'I' && dsa->fmt_w <= 80 && dsa->fmt_k * dsa->fmt_w <= 80)) { xprintf( "%s:%d: can't read array `%s' - invalid format `%s'\n", dsa->fname, dsa->seqn, name, fmt); return 1; } for (k = 1, pos = INT_MAX; k <= n; k++, pos++) { if (pos >= dsa->fmt_k) { if (read_card(dsa)) return 1; pos = 0; } memcpy(str, dsa->card + dsa->fmt_w * pos, dsa->fmt_w); str[dsa->fmt_w] = '\0'; strspx(str); if (strchr(str, '.') == NULL && strcmp(str, "0")) { xprintf("%s(%d): can't read array `%s' - value `%s' has no " "decimal point\n", dsa->fname, dsa->seqn, name, str); return 1; } /* sometimes lower case letters appear */ for (ptr = str; *ptr; ptr++) *ptr = (char)toupper((unsigned char)*ptr); ptr = strchr(str, 'D'); if (ptr != NULL) *ptr = 'E'; /* value may appear with decimal exponent but without letters E or D (for example, -123.456-012), so missing letter should be inserted */ ptr = strchr(str+1, '+'); if (ptr == NULL) ptr = strchr(str+1, '-'); if (ptr != NULL && *(ptr-1) != 'E') { xassert(strlen(str) < 80); memmove(ptr+1, ptr, strlen(ptr)+1); *ptr = 'E'; } if (str2num(str, &val[k])) { xprintf( "%s:%d: can't read array `%s' - invalid value `%s'\n", dsa->fname, dsa->seqn, name, str); return 1; } } return 0; } HBM *hbm_read_mat(const char *fname) { struct dsa _dsa, *dsa = &_dsa; HBM *hbm = NULL; dsa->fname = fname; xprintf("hbm_read_mat: reading matrix from `%s'...\n", dsa->fname); dsa->fp = fopen(dsa->fname, "r"); if (dsa->fp == NULL) { xprintf("hbm_read_mat: unable to open `%s' - %s\n", dsa->fname, strerror(errno)); goto fail; } dsa->seqn = 0; hbm = xmalloc(sizeof(HBM)); memset(hbm, 0, sizeof(HBM)); /* read the first heading card */ if (read_card(dsa)) goto fail; memcpy(hbm->title, dsa->card, 72), hbm->title[72] = '\0'; strtrim(hbm->title); xprintf("%s\n", hbm->title); memcpy(hbm->key, dsa->card+72, 8), hbm->key[8] = '\0'; strspx(hbm->key); xprintf("key = %s\n", hbm->key); /* read the second heading card */ if (read_card(dsa)) goto fail; if (scan_int(dsa, "totcrd", 0, 14, &hbm->totcrd)) goto fail; if (scan_int(dsa, "ptrcrd", 14, 14, &hbm->ptrcrd)) goto fail; if (scan_int(dsa, "indcrd", 28, 14, &hbm->indcrd)) goto fail; if (scan_int(dsa, "valcrd", 42, 14, &hbm->valcrd)) goto fail; if (scan_int(dsa, "rhscrd", 56, 14, &hbm->rhscrd)) goto fail; xprintf("totcrd = %d; ptrcrd = %d; indcrd = %d; valcrd = %d; rhsc" "rd = %d\n", hbm->totcrd, hbm->ptrcrd, hbm->indcrd, hbm->valcrd, hbm->rhscrd); /* read the third heading card */ if (read_card(dsa)) goto fail; memcpy(hbm->mxtype, dsa->card, 3), hbm->mxtype[3] = '\0'; if (strchr("RCP", hbm->mxtype[0]) == NULL || strchr("SUHZR", hbm->mxtype[1]) == NULL || strchr("AE", hbm->mxtype[2]) == NULL) { xprintf("%s:%d: matrix type `%s' not recognised\n", dsa->fname, dsa->seqn, hbm->mxtype); goto fail; } if (scan_int(dsa, "nrow", 14, 14, &hbm->nrow)) goto fail; if (scan_int(dsa, "ncol", 28, 14, &hbm->ncol)) goto fail; if (scan_int(dsa, "nnzero", 42, 14, &hbm->nnzero)) goto fail; if (scan_int(dsa, "neltvl", 56, 14, &hbm->neltvl)) goto fail; xprintf("mxtype = %s; nrow = %d; ncol = %d; nnzero = %d; neltvl =" " %d\n", hbm->mxtype, hbm->nrow, hbm->ncol, hbm->nnzero, hbm->neltvl); /* read the fourth heading card */ if (read_card(dsa)) goto fail; memcpy(hbm->ptrfmt, dsa->card, 16), hbm->ptrfmt[16] = '\0'; strspx(hbm->ptrfmt); memcpy(hbm->indfmt, dsa->card+16, 16), hbm->indfmt[16] = '\0'; strspx(hbm->indfmt); memcpy(hbm->valfmt, dsa->card+32, 20), hbm->valfmt[20] = '\0'; strspx(hbm->valfmt); memcpy(hbm->rhsfmt, dsa->card+52, 20), hbm->rhsfmt[20] = '\0'; strspx(hbm->rhsfmt); xprintf("ptrfmt = %s; indfmt = %s; valfmt = %s; rhsfmt = %s\n", hbm->ptrfmt, hbm->indfmt, hbm->valfmt, hbm->rhsfmt); /* read the fifth heading card (optional) */ if (hbm->rhscrd <= 0) { strcpy(hbm->rhstyp, "???"); hbm->nrhs = 0; hbm->nrhsix = 0; } else { if (read_card(dsa)) goto fail; memcpy(hbm->rhstyp, dsa->card, 3), hbm->rhstyp[3] = '\0'; if (scan_int(dsa, "nrhs", 14, 14, &hbm->nrhs)) goto fail; if (scan_int(dsa, "nrhsix", 28, 14, &hbm->nrhsix)) goto fail; xprintf("rhstyp = `%s'; nrhs = %d; nrhsix = %d\n", hbm->rhstyp, hbm->nrhs, hbm->nrhsix); } /* read matrix structure */ hbm->colptr = xcalloc(1+hbm->ncol+1, sizeof(int)); if (read_int_array(dsa, "colptr", hbm->ptrfmt, hbm->ncol+1, hbm->colptr)) goto fail; hbm->rowind = xcalloc(1+hbm->nnzero, sizeof(int)); if (read_int_array(dsa, "rowind", hbm->indfmt, hbm->nnzero, hbm->rowind)) goto fail; /* read matrix values */ if (hbm->valcrd <= 0) goto done; if (hbm->mxtype[2] == 'A') { /* assembled matrix */ hbm->values = xcalloc(1+hbm->nnzero, sizeof(double)); if (read_real_array(dsa, "values", hbm->valfmt, hbm->nnzero, hbm->values)) goto fail; } else { /* elemental (unassembled) matrix */ hbm->values = xcalloc(1+hbm->neltvl, sizeof(double)); if (read_real_array(dsa, "values", hbm->valfmt, hbm->neltvl, hbm->values)) goto fail; } /* read right-hand sides */ if (hbm->nrhs <= 0) goto done; if (hbm->rhstyp[0] == 'F') { /* dense format */ hbm->nrhsvl = hbm->nrow * hbm->nrhs; hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double)); if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl, hbm->rhsval)) goto fail; } else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'A') { /* sparse format */ /* read pointers */ hbm->rhsptr = xcalloc(1+hbm->nrhs+1, sizeof(int)); if (read_int_array(dsa, "rhsptr", hbm->ptrfmt, hbm->nrhs+1, hbm->rhsptr)) goto fail; /* read sparsity pattern */ hbm->rhsind = xcalloc(1+hbm->nrhsix, sizeof(int)); if (read_int_array(dsa, "rhsind", hbm->indfmt, hbm->nrhsix, hbm->rhsind)) goto fail; /* read values */ hbm->rhsval = xcalloc(1+hbm->nrhsix, sizeof(double)); if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsix, hbm->rhsval)) goto fail; } else if (hbm->rhstyp[0] == 'M' && hbm->mxtype[2] == 'E') { /* elemental format */ hbm->rhsval = xcalloc(1+hbm->nrhsvl, sizeof(double)); if (read_real_array(dsa, "rhsval", hbm->rhsfmt, hbm->nrhsvl, hbm->rhsval)) goto fail; } else { xprintf("%s:%d: right-hand side type `%c' not recognised\n", dsa->fname, dsa->seqn, hbm->rhstyp[0]); goto fail; } /* read starting guesses */ if (hbm->rhstyp[1] == 'G') { hbm->nguess = hbm->nrow * hbm->nrhs; hbm->sguess = xcalloc(1+hbm->nguess, sizeof(double)); if (read_real_array(dsa, "sguess", hbm->rhsfmt, hbm->nguess, hbm->sguess)) goto fail; } /* read solution vectors */ if (hbm->rhstyp[2] == 'X') { hbm->nexact = hbm->nrow * hbm->nrhs; hbm->xexact = xcalloc(1+hbm->nexact, sizeof(double)); if (read_real_array(dsa, "xexact", hbm->rhsfmt, hbm->nexact, hbm->xexact)) goto fail; } done: /* reading has been completed */ xprintf("hbm_read_mat: %d cards were read\n", dsa->seqn); fclose(dsa->fp); return hbm; fail: /* something wrong in Danish kingdom */ if (hbm != NULL) { if (hbm->colptr != NULL) xfree(hbm->colptr); if (hbm->rowind != NULL) xfree(hbm->rowind); if (hbm->rhsptr != NULL) xfree(hbm->rhsptr); if (hbm->rhsind != NULL) xfree(hbm->rhsind); if (hbm->values != NULL) xfree(hbm->values); if (hbm->rhsval != NULL) xfree(hbm->rhsval); if (hbm->sguess != NULL) xfree(hbm->sguess); if (hbm->xexact != NULL) xfree(hbm->xexact); xfree(hbm); } if (dsa->fp != NULL) fclose(dsa->fp); return NULL; } /*********************************************************************** * NAME * * hbm_free_mat - free sparse matrix in Harwell-Boeing format * * SYNOPSIS * * #include "glphbm.h" * void hbm_free_mat(HBM *hbm); * * DESCRIPTION * * The hbm_free_mat routine frees all the memory allocated to the data * structure containing a sparse matrix in the Harwell-Boeing format. */ void hbm_free_mat(HBM *hbm) { if (hbm->colptr != NULL) xfree(hbm->colptr); if (hbm->rowind != NULL) xfree(hbm->rowind); if (hbm->rhsptr != NULL) xfree(hbm->rhsptr); if (hbm->rhsind != NULL) xfree(hbm->rhsind); if (hbm->values != NULL) xfree(hbm->values); if (hbm->rhsval != NULL) xfree(hbm->rhsval); if (hbm->sguess != NULL) xfree(hbm->sguess); if (hbm->xexact != NULL) xfree(hbm->xexact); xfree(hbm); return; } /* eof */ glpk-4.52.1/src/glphbm.h0000644000062000006210000001103412175147600014131 0ustar maomkpasswd/* glphbm.h (Harwell-Boeing sparse matrix format) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPHBM_H #define GLPHBM_H typedef struct HBM HBM; struct HBM { /* sparse matrix in Harwell-Boeing format; for details see the report: I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing Sparse Matrix Collection (Release I), 1992 */ char title[72+1]; /* matrix title (informative) */ char key[8+1]; /* matrix key (informative) */ char mxtype[3+1]; /* matrix type: R.. real matrix C.. complex matrix P.. pattern only (no numerical values supplied) .S. symmetric (lower triangle + main diagonal) .U. unsymmetric .H. hermitian (lower triangle + main diagonal) .Z. skew symmetric (lower triangle only) .R. rectangular ..A assembled ..E elemental (unassembled) */ char rhstyp[3+1]; /* optional types: F.. right-hand sides in dense format M.. right-hand sides in same format as matrix .G. starting vector(s) (guess) is supplied ..X exact solution vector(s) is supplied */ char ptrfmt[16+1]; /* format for pointers */ char indfmt[16+1]; /* format for row (or variable) indices */ char valfmt[20+1]; /* format for numerical values of coefficient matrix */ char rhsfmt[20+1]; /* format for numerical values of right-hand sides */ int totcrd; /* total number of cards excluding header */ int ptrcrd; /* number of cards for ponters */ int indcrd; /* number of cards for row (or variable) indices */ int valcrd; /* number of cards for numerical values */ int rhscrd; /* number of lines for right-hand sides; including starting guesses and solution vectors if present; zero indicates no right-hand side data is present */ int nrow; /* number of rows (or variables) */ int ncol; /* number of columns (or elements) */ int nnzero; /* number of row (or variable) indices; equal to number of entries for assembled matrix */ int neltvl; /* number of elemental matrix entries; zero in case of assembled matrix */ int nrhs; /* number of right-hand sides */ int nrhsix; /* number of row indices; ignored in case of unassembled matrix */ int nrhsvl; /* total number of entries in all right-hand sides */ int nguess; /* total number of entries in all starting guesses */ int nexact; /* total number of entries in all solution vectors */ int *colptr; /* alias: eltptr */ /* column pointers (in case of assembled matrix); elemental matrix pointers (in case of unassembled matrix) */ int *rowind; /* alias: varind */ /* row indices (in case of assembled matrix); variable indices (in case of unassembled matrix) */ int *rhsptr; /* right-hand side pointers */ int *rhsind; /* right-hand side indices */ double *values; /* matrix values */ double *rhsval; /* right-hand side values */ double *sguess; /* starting guess values */ double *xexact; /* solution vector values */ }; #define hbm_read_mat _glp_hbm_read_mat HBM *hbm_read_mat(const char *fname); /* read sparse matrix in Harwell-Boeing format */ #define hbm_free_mat _glp_hbm_free_mat void hbm_free_mat(HBM *hbm); /* free sparse matrix in Harwell-Boeing format */ #endif /* eof */ glpk-4.52.1/src/glpini01.c0000644000062000006210000001161612175147600014304 0ustar maomkpasswd/* glpini01.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "glpapi.h" #include "triang.h" /*********************************************************************** * NAME * * glp_adv_basis - construct advanced initial LP basis * * SYNOPSIS * * void glp_adv_basis(glp_prob *P, int flags); * * DESCRIPTION * * The routine glp_adv_basis constructs an advanced initial LP basis * for the specified problem object. * * The parameter flag is reserved for use in the future and should be * specified as zero. * * NOTE * * The routine glp_adv_basis should be called after the constraint * matrix has been scaled (if scaling is used). */ static int mat(void *info, int k, int ind[], double val[]) { glp_prob *P = info; int m = P->m; int n = P->n; GLPROW **row = P->row; GLPCOL **col = P->col; GLPAIJ *aij; int i, j, len; if (k > 0) { /* retrieve scaled row of constraint matrix */ i = +k; xassert(1 <= i && i <= m); len = 0; if (row[i]->type == GLP_FX) { for (aij = row[i]->ptr; aij != NULL; aij = aij->r_next) { j = aij->col->j; if (col[j]->type != GLP_FX) { len++; ind[len] = j; val[len] = aij->row->rii * aij->val * aij->col->sjj; } } } } else { /* retrieve scaled column of constraint matrix */ j = -k; xassert(1 <= j && j <= n); len = 0; if (col[j]->type != GLP_FX) { for (aij = col[j]->ptr; aij != NULL; aij = aij->c_next) { i = aij->row->i; if (row[i]->type == GLP_FX) { len++; ind[len] = i; val[len] = aij->row->rii * aij->val * aij->col->sjj; } } } } return len; } void glp_adv_basis(glp_prob *P, int flags) { int i, j, k, m, n, min_mn, size, *rn, *cn; char *flag; if (flags != 0) xerror("glp_adv_basis: flags = %d; invalid flags\n", flags); m = P->m; /* number of rows */ n = P->n; /* number of columns */ if (m == 0 || n == 0) { /* trivial case */ glp_std_basis(P); goto done; } xprintf("Constructing initial basis...\n"); /* allocate working arrays */ min_mn = (m < n ? m : n); rn = talloc(1+min_mn, int); cn = talloc(1+min_mn, int); flag = talloc(1+m, char); /* make the basis empty */ for (i = 1; i <= m; i++) { flag[i] = 0; glp_set_row_stat(P, i, GLP_NS); } for (j = 1; j <= n; j++) glp_set_col_stat(P, j, GLP_NS); /* find maximal triangular part of the constraint matrix; to prevent including non-fixed rows and fixed columns in the triangular part, such rows and columns are temporarily made empty by the routine mat */ #if 1 /* FIXME: tolerance */ size = triang(m, n, mat, P, 0.001, rn, cn); #endif xassert(0 <= size && size <= min_mn); /* include in the basis non-fixed structural variables, whose columns constitute the triangular part */ for (k = 1; k <= size; k++) { i = rn[k]; xassert(1 <= i && i <= m); flag[i] = 1; j = cn[k]; xassert(1 <= j && j <= n); glp_set_col_stat(P, j, GLP_BS); } /* include in the basis appropriate auxiliary variables, whose unity columns preserve triangular form of the basis matrix */ for (i = 1; i <= m; i++) { if (flag[i] == 0) { glp_set_row_stat(P, i, GLP_BS); if (P->row[i]->type != GLP_FX) size++; } } /* size of triangular part = (number of rows) - (number of basic fixed auxiliary variables) */ xprintf("Size of triangular part is %d\n", size); /* deallocate working arrays */ tfree(rn); tfree(cn); tfree(flag); done: return; } /* eof */ glpk-4.52.1/src/glpini02.c0000644000062000006210000002145512175147600014307 0ustar maomkpasswd/* glpini02.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" struct var { /* structural variable */ int j; /* ordinal number */ double q; /* penalty value */ }; static int fcmp(const void *ptr1, const void *ptr2) { /* this routine is passed to the qsort() function */ struct var *col1 = (void *)ptr1, *col2 = (void *)ptr2; if (col1->q < col2->q) return -1; if (col1->q > col2->q) return +1; return 0; } static int get_column(glp_prob *lp, int j, int ind[], double val[]) { /* Bixby's algorithm assumes that the constraint matrix is scaled such that the maximum absolute value in every non-zero row and column is 1 */ int k, len; double big; len = glp_get_mat_col(lp, j, ind, val); big = 0.0; for (k = 1; k <= len; k++) if (big < fabs(val[k])) big = fabs(val[k]); if (big == 0.0) big = 1.0; for (k = 1; k <= len; k++) val[k] /= big; return len; } static void cpx_basis(glp_prob *lp) { /* main routine */ struct var *C, *C2, *C3, *C4; int m, n, i, j, jk, k, l, ll, t, n2, n3, n4, type, len, *I, *r, *ind; double alpha, gamma, cmax, temp, *v, *val; xprintf("Constructing initial basis...\n"); /* determine the number of rows and columns */ m = glp_get_num_rows(lp); n = glp_get_num_cols(lp); /* allocate working arrays */ C = xcalloc(1+n, sizeof(struct var)); I = xcalloc(1+m, sizeof(int)); r = xcalloc(1+m, sizeof(int)); v = xcalloc(1+m, sizeof(double)); ind = xcalloc(1+m, sizeof(int)); val = xcalloc(1+m, sizeof(double)); /* make all auxiliary variables non-basic */ for (i = 1; i <= m; i++) { if (glp_get_row_type(lp, i) != GLP_DB) glp_set_row_stat(lp, i, GLP_NS); else if (fabs(glp_get_row_lb(lp, i)) <= fabs(glp_get_row_ub(lp, i))) glp_set_row_stat(lp, i, GLP_NL); else glp_set_row_stat(lp, i, GLP_NU); } /* make all structural variables non-basic */ for (j = 1; j <= n; j++) { if (glp_get_col_type(lp, j) != GLP_DB) glp_set_col_stat(lp, j, GLP_NS); else if (fabs(glp_get_col_lb(lp, j)) <= fabs(glp_get_col_ub(lp, j))) glp_set_col_stat(lp, j, GLP_NL); else glp_set_col_stat(lp, j, GLP_NU); } /* C2 is a set of free structural variables */ n2 = 0, C2 = C + 0; for (j = 1; j <= n; j++) { type = glp_get_col_type(lp, j); if (type == GLP_FR) { n2++; C2[n2].j = j; C2[n2].q = 0.0; } } /* C3 is a set of structural variables having excatly one (lower or upper) bound */ n3 = 0, C3 = C2 + n2; for (j = 1; j <= n; j++) { type = glp_get_col_type(lp, j); if (type == GLP_LO) { n3++; C3[n3].j = j; C3[n3].q = + glp_get_col_lb(lp, j); } else if (type == GLP_UP) { n3++; C3[n3].j = j; C3[n3].q = - glp_get_col_ub(lp, j); } } /* C4 is a set of structural variables having both (lower and upper) bounds */ n4 = 0, C4 = C3 + n3; for (j = 1; j <= n; j++) { type = glp_get_col_type(lp, j); if (type == GLP_DB) { n4++; C4[n4].j = j; C4[n4].q = glp_get_col_lb(lp, j) - glp_get_col_ub(lp, j); } } /* compute gamma = max{|c[j]|: 1 <= j <= n} */ gamma = 0.0; for (j = 1; j <= n; j++) { temp = fabs(glp_get_obj_coef(lp, j)); if (gamma < temp) gamma = temp; } /* compute cmax */ cmax = (gamma == 0.0 ? 1.0 : 1000.0 * gamma); /* compute final penalty for all structural variables within sets C2, C3, and C4 */ switch (glp_get_obj_dir(lp)) { case GLP_MIN: temp = +1.0; break; case GLP_MAX: temp = -1.0; break; default: xassert(lp != lp); } for (k = 1; k <= n2+n3+n4; k++) { j = C[k].j; C[k].q += (temp * glp_get_obj_coef(lp, j)) / cmax; } /* sort structural variables within C2, C3, and C4 in ascending order of penalty value */ qsort(C2+1, n2, sizeof(struct var), fcmp); for (k = 1; k < n2; k++) xassert(C2[k].q <= C2[k+1].q); qsort(C3+1, n3, sizeof(struct var), fcmp); for (k = 1; k < n3; k++) xassert(C3[k].q <= C3[k+1].q); qsort(C4+1, n4, sizeof(struct var), fcmp); for (k = 1; k < n4; k++) xassert(C4[k].q <= C4[k+1].q); /*** STEP 1 ***/ for (i = 1; i <= m; i++) { type = glp_get_row_type(lp, i); if (type != GLP_FX) { /* row i is either free or inequality constraint */ glp_set_row_stat(lp, i, GLP_BS); I[i] = 1; r[i] = 1; } else { /* row i is equality constraint */ I[i] = 0; r[i] = 0; } v[i] = +DBL_MAX; } /*** STEP 2 ***/ for (k = 1; k <= n2+n3+n4; k++) { jk = C[k].j; len = get_column(lp, jk, ind, val); /* let alpha = max{|A[l,jk]|: r[l] = 0} and let l' be such that alpha = |A[l',jk]| */ alpha = 0.0, ll = 0; for (t = 1; t <= len; t++) { l = ind[t]; if (r[l] == 0 && alpha < fabs(val[t])) alpha = fabs(val[t]), ll = l; } if (alpha >= 0.99) { /* B := B union {jk} */ glp_set_col_stat(lp, jk, GLP_BS); I[ll] = 1; v[ll] = alpha; /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */ for (t = 1; t <= len; t++) { l = ind[t]; if (val[t] != 0.0) r[l]++; } /* continue to the next k */ continue; } /* if |A[l,jk]| > 0.01 * v[l] for some l, continue to the next k */ for (t = 1; t <= len; t++) { l = ind[t]; if (fabs(val[t]) > 0.01 * v[l]) break; } if (t <= len) continue; /* otherwise, let alpha = max{|A[l,jk]|: I[l] = 0} and let l' be such that alpha = |A[l',jk]| */ alpha = 0.0, ll = 0; for (t = 1; t <= len; t++) { l = ind[t]; if (I[l] == 0 && alpha < fabs(val[t])) alpha = fabs(val[t]), ll = l; } /* if alpha = 0, continue to the next k */ if (alpha == 0.0) continue; /* B := B union {jk} */ glp_set_col_stat(lp, jk, GLP_BS); I[ll] = 1; v[ll] = alpha; /* r[l] := r[l] + 1 for all l such that |A[l,jk]| != 0 */ for (t = 1; t <= len; t++) { l = ind[t]; if (val[t] != 0.0) r[l]++; } } /*** STEP 3 ***/ /* add an artificial variable (auxiliary variable for equality constraint) to cover each remaining uncovered row */ for (i = 1; i <= m; i++) if (I[i] == 0) glp_set_row_stat(lp, i, GLP_BS); /* free working arrays */ xfree(C); xfree(I); xfree(r); xfree(v); xfree(ind); xfree(val); return; } /*********************************************************************** * NAME * * glp_cpx_basis - construct Bixby's initial LP basis * * SYNOPSIS * * void glp_cpx_basis(glp_prob *lp); * * DESCRIPTION * * The routine glp_cpx_basis constructs an advanced initial basis for * the specified problem object. * * The routine is based on Bixby's algorithm described in the paper: * * Robert E. Bixby. Implementing the Simplex Method: The Initial Basis. * ORSA Journal on Computing, Vol. 4, No. 3, 1992, pp. 267-84. */ void glp_cpx_basis(glp_prob *lp) { if (lp->m == 0 || lp->n == 0) glp_std_basis(lp); else cpx_basis(lp); return; } /* eof */ glpk-4.52.1/src/glpios.h0000644000062000006210000005505712175147600014172 0ustar maomkpasswd/* glpios.h (integer optimization suite) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPIOS_H #define GLPIOS_H #include "glpapi.h" typedef struct IOSLOT IOSLOT; typedef struct IOSNPD IOSNPD; typedef struct IOSBND IOSBND; typedef struct IOSTAT IOSTAT; typedef struct IOSROW IOSROW; typedef struct IOSAIJ IOSAIJ; typedef struct IOSPOOL IOSPOOL; typedef struct IOSCUT IOSCUT; struct glp_tree { /* branch-and-bound tree */ int magic; /* magic value used for debugging */ DMP *pool; /* memory pool to store all IOS components */ int n; /* number of columns (variables) */ /*--------------------------------------------------------------*/ /* problem components corresponding to the original MIP and its LP relaxation (used to restore the original problem object on exit from the solver) */ int orig_m; /* number of rows */ unsigned char *orig_type; /* uchar orig_type[1+orig_m+n]; */ /* types of all variables */ double *orig_lb; /* double orig_lb[1+orig_m+n]; */ /* lower bounds of all variables */ double *orig_ub; /* double orig_ub[1+orig_m+n]; */ /* upper bounds of all variables */ unsigned char *orig_stat; /* uchar orig_stat[1+orig_m+n]; */ /* statuses of all variables */ double *orig_prim; /* double orig_prim[1+orig_m+n]; */ /* primal values of all variables */ double *orig_dual; /* double orig_dual[1+orig_m+n]; */ /* dual values of all variables */ double orig_obj; /* optimal objective value for LP relaxation */ /*--------------------------------------------------------------*/ /* branch-and-bound tree */ int nslots; /* length of the array of slots (enlarged automatically) */ int avail; /* index of the first free slot; 0 means all slots are in use */ IOSLOT *slot; /* IOSLOT slot[1+nslots]; */ /* array of slots: slot[0] is not used; slot[p], 1 <= p <= nslots, either contains a pointer to some node of the branch-and-bound tree, in which case p is used on API level as the reference number of corresponding subproblem, or is free; all free slots are linked into single linked list; slot[1] always contains a pointer to the root node (it is free only if the tree is empty) */ IOSNPD *head; /* pointer to the head of the active list */ IOSNPD *tail; /* pointer to the tail of the active list */ /* the active list is a doubly linked list of active subproblems which correspond to leaves of the tree; all subproblems in the active list are ordered chronologically (each a new subproblem is always added to the tail of the list) */ int a_cnt; /* current number of active nodes (including the current one) */ int n_cnt; /* current number of all (active and inactive) nodes */ int t_cnt; /* total number of nodes including those which have been already removed from the tree; this count is increased by one whenever a new node is created and never decreased */ /*--------------------------------------------------------------*/ /* problem components corresponding to the root subproblem */ int root_m; /* number of rows */ unsigned char *root_type; /* uchar root_type[1+root_m+n]; */ /* types of all variables */ double *root_lb; /* double root_lb[1+root_m+n]; */ /* lower bounds of all variables */ double *root_ub; /* double root_ub[1+root_m+n]; */ /* upper bounds of all variables */ unsigned char *root_stat; /* uchar root_stat[1+root_m+n]; */ /* statuses of all variables */ /*--------------------------------------------------------------*/ /* current subproblem and its LP relaxation */ IOSNPD *curr; /* pointer to the current subproblem (which can be only active); NULL means the current subproblem does not exist */ glp_prob *mip; /* original problem object passed to the solver; if the current subproblem exists, its LP segment corresponds to LP relaxation of the current subproblem; if the current subproblem does not exist, its LP segment corresponds to LP relaxation of the root subproblem (note that the root subproblem may differ from the original MIP, because it may be preprocessed and/or may have additional rows) */ unsigned char *non_int; /* uchar non_int[1+n]; */ /* these column flags are set each time when LP relaxation of the current subproblem has been solved; non_int[0] is not used; non_int[j], 1 <= j <= n, is j-th column flag; if this flag is set, corresponding variable is required to be integer, but its value in basic solution is fractional */ /*--------------------------------------------------------------*/ /* problem components corresponding to the parent (predecessor) subproblem for the current subproblem; used to inspect changes on freezing the current subproblem */ int pred_m; /* number of rows */ int pred_max; /* length of the following four arrays (enlarged automatically), pred_max >= pred_m + n */ unsigned char *pred_type; /* uchar pred_type[1+pred_m+n]; */ /* types of all variables */ double *pred_lb; /* double pred_lb[1+pred_m+n]; */ /* lower bounds of all variables */ double *pred_ub; /* double pred_ub[1+pred_m+n]; */ /* upper bounds of all variables */ unsigned char *pred_stat; /* uchar pred_stat[1+pred_m+n]; */ /* statuses of all variables */ /****************************************************************/ /* built-in cut generators segment */ IOSPOOL *local; /* local cut pool */ void *mir_gen; /* pointer to working area used by the MIR cut generator */ void *clq_gen; /* pointer to working area used by the clique cut generator */ /*--------------------------------------------------------------*/ void *pcost; /* pointer to working area used on pseudocost branching */ int *iwrk; /* int iwrk[1+n]; */ /* working array */ double *dwrk; /* double dwrk[1+n]; */ /* working array */ /*--------------------------------------------------------------*/ /* control parameters and statistics */ const glp_iocp *parm; /* copy of control parameters passed to the solver */ #if 0 /* 10/VI-2013 */ glp_long tm_beg; #else double tm_beg; #endif /* starting time of the search, in seconds; the total time of the search is the difference between xtime() and tm_beg */ #if 0 /* 10/VI-2013 */ glp_long tm_lag; #else double tm_lag; #endif /* the most recent time, in seconds, at which the progress of the the search was displayed */ int sol_cnt; /* number of integer feasible solutions found */ #if 1 /* 11/VII-2013 */ void *P; /* glp_prob *P; */ /* problem passed to glp_intopt */ void *npp; /* NPP *npp; */ /* preprocessor workspace or NULL */ const char *save_sol; /* filename (template) to save every new solution */ int save_cnt; /* count to generate filename */ #endif /*--------------------------------------------------------------*/ /* advanced solver interface */ int reason; /* flag indicating the reason why the callback routine is being called (see glpk.h) */ int stop; /* flag indicating that the callback routine requires premature termination of the search */ int next_p; /* reference number of active subproblem selected to continue the search; 0 means no subproblem has been selected */ int reopt; /* flag indicating that the current LP relaxation needs to be re-optimized */ int reinv; /* flag indicating that some (non-active) rows were removed from the current LP relaxation, so if there no new rows appear, the basis must be re-factorized */ int br_var; /* the number of variable chosen to branch on */ int br_sel; /* flag indicating which branch (subproblem) is suggested to be selected to continue the search: GLP_DN_BRNCH - select down-branch GLP_UP_BRNCH - select up-branch GLP_NO_BRNCH - use general selection technique */ int child; /* subproblem reference number corresponding to br_sel */ }; struct IOSLOT { /* node subproblem slot */ IOSNPD *node; /* pointer to subproblem descriptor; NULL means free slot */ int next; /* index of another free slot (only if this slot is free) */ }; struct IOSNPD { /* node subproblem descriptor */ int p; /* subproblem reference number (it is the index to corresponding slot, i.e. slot[p] points to this descriptor) */ IOSNPD *up; /* pointer to the parent subproblem; NULL means this node is the root of the tree, in which case p = 1 */ int level; /* node level (the root node has level 0) */ int count; /* if count = 0, this subproblem is active; if count > 0, this subproblem is inactive, in which case count is the number of its child subproblems */ /* the following three linked lists are destroyed on reviving and built anew on freezing the subproblem: */ IOSBND *b_ptr; /* linked list of rows and columns of the parent subproblem whose types and bounds were changed */ IOSTAT *s_ptr; /* linked list of rows and columns of the parent subproblem whose statuses were changed */ IOSROW *r_ptr; /* linked list of rows (cuts) added to the parent subproblem */ int solved; /* how many times LP relaxation of this subproblem was solved; for inactive subproblem this count is always non-zero; for active subproblem, which is not current, this count may be non-zero, if the subproblem was temporarily suspended */ double lp_obj; /* optimal objective value to LP relaxation of this subproblem; on creating a subproblem this value is inherited from its parent; for the root subproblem, which has no parent, this value is initially set to -DBL_MAX (minimization) or +DBL_MAX (maximization); each time the subproblem is re-optimized, this value is appropriately changed */ double bound; /* local lower (minimization) or upper (maximization) bound for integer optimal solution to *this* subproblem; this bound is local in the sense that only subproblems in the subtree rooted at this node cannot have better integer feasible solutions; on creating a subproblem its local bound is inherited from its parent and then can be made stronger (never weaker); for the root subproblem its local bound is initially set to -DBL_MAX (minimization) or +DBL_MAX (maximization) and then improved as the root LP relaxation has been solved */ /* the following two quantities are defined only if LP relaxation of this subproblem was solved at least once (solved > 0): */ int ii_cnt; /* number of integer variables whose value in optimal solution to LP relaxation of this subproblem is fractional */ double ii_sum; /* sum of integer infeasibilities */ #if 1 /* 30/XI-2009 */ int changed; /* how many times this subproblem was re-formulated (by adding cutting plane constraints) */ #endif int br_var; /* ordinal number of branching variable, 1 <= br_var <= n, used to split this subproblem; 0 means that either this subproblem is active or branching was made on a constraint */ double br_val; /* (fractional) value of branching variable in optimal solution to final LP relaxation of this subproblem */ void *data; /* char data[tree->cb_size]; */ /* pointer to the application-specific data */ IOSNPD *temp; /* working pointer used by some routines */ IOSNPD *prev; /* pointer to previous subproblem in the active list */ IOSNPD *next; /* pointer to next subproblem in the active list */ }; struct IOSBND { /* bounds change entry */ int k; /* ordinal number of corresponding row (1 <= k <= m) or column (m+1 <= k <= m+n), where m and n are the number of rows and columns, resp., in the parent subproblem */ unsigned char type; /* new type */ double lb; /* new lower bound */ double ub; /* new upper bound */ IOSBND *next; /* pointer to next entry for the same subproblem */ }; struct IOSTAT { /* status change entry */ int k; /* ordinal number of corresponding row (1 <= k <= m) or column (m+1 <= k <= m+n), where m and n are the number of rows and columns, resp., in the parent subproblem */ unsigned char stat; /* new status */ IOSTAT *next; /* pointer to next entry for the same subproblem */ }; struct IOSROW { /* row (constraint) addition entry */ char *name; /* row name or NULL */ unsigned char origin; /* row origin flag (see glp_attr.origin) */ unsigned char klass; /* row class descriptor (see glp_attr.klass) */ unsigned char type; /* row type (GLP_LO, GLP_UP, etc.) */ double lb; /* row lower bound */ double ub; /* row upper bound */ IOSAIJ *ptr; /* pointer to the row coefficient list */ double rii; /* row scale factor */ unsigned char stat; /* row status (GLP_BS, GLP_NL, etc.) */ IOSROW *next; /* pointer to next entry for the same subproblem */ }; struct IOSAIJ { /* constraint coefficient */ int j; /* variable (column) number, 1 <= j <= n */ double val; /* non-zero coefficient value */ IOSAIJ *next; /* pointer to next coefficient for the same row */ }; struct IOSPOOL { /* cut pool */ int size; /* pool size = number of cuts in the pool */ IOSCUT *head; /* pointer to the first cut */ IOSCUT *tail; /* pointer to the last cut */ int ord; /* ordinal number of the current cut, 1 <= ord <= size */ IOSCUT *curr; /* pointer to the current cut */ }; struct IOSCUT { /* cut (cutting plane constraint) */ char *name; /* cut name or NULL */ unsigned char klass; /* cut class descriptor (see glp_attr.klass) */ IOSAIJ *ptr; /* pointer to the cut coefficient list */ unsigned char type; /* cut type: GLP_LO: sum a[j] * x[j] >= b GLP_UP: sum a[j] * x[j] <= b GLP_FX: sum a[j] * x[j] = b */ double rhs; /* cut right-hand side */ IOSCUT *prev; /* pointer to previous cut */ IOSCUT *next; /* pointer to next cut */ }; #define ios_create_tree _glp_ios_create_tree glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm); /* create branch-and-bound tree */ #define ios_revive_node _glp_ios_revive_node void ios_revive_node(glp_tree *tree, int p); /* revive specified subproblem */ #define ios_freeze_node _glp_ios_freeze_node void ios_freeze_node(glp_tree *tree); /* freeze current subproblem */ #define ios_clone_node _glp_ios_clone_node void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]); /* clone specified subproblem */ #define ios_delete_node _glp_ios_delete_node void ios_delete_node(glp_tree *tree, int p); /* delete specified subproblem */ #define ios_delete_tree _glp_ios_delete_tree void ios_delete_tree(glp_tree *tree); /* delete branch-and-bound tree */ #define ios_eval_degrad _glp_ios_eval_degrad void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up); /* estimate obj. degrad. for down- and up-branches */ #define ios_round_bound _glp_ios_round_bound double ios_round_bound(glp_tree *tree, double bound); /* improve local bound by rounding */ #define ios_is_hopeful _glp_ios_is_hopeful int ios_is_hopeful(glp_tree *tree, double bound); /* check if subproblem is hopeful */ #define ios_best_node _glp_ios_best_node int ios_best_node(glp_tree *tree); /* find active node with best local bound */ #define ios_relative_gap _glp_ios_relative_gap double ios_relative_gap(glp_tree *tree); /* compute relative mip gap */ #define ios_solve_node _glp_ios_solve_node int ios_solve_node(glp_tree *tree); /* solve LP relaxation of current subproblem */ #define ios_create_pool _glp_ios_create_pool IOSPOOL *ios_create_pool(glp_tree *tree); /* create cut pool */ #define ios_add_row _glp_ios_add_row int ios_add_row(glp_tree *tree, IOSPOOL *pool, const char *name, int klass, int flags, int len, const int ind[], const double val[], int type, double rhs); /* add row (constraint) to the cut pool */ #define ios_find_row _glp_ios_find_row IOSCUT *ios_find_row(IOSPOOL *pool, int i); /* find row (constraint) in the cut pool */ #define ios_del_row _glp_ios_del_row void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i); /* remove row (constraint) from the cut pool */ #define ios_clear_pool _glp_ios_clear_pool void ios_clear_pool(glp_tree *tree, IOSPOOL *pool); /* remove all rows (constraints) from the cut pool */ #define ios_delete_pool _glp_ios_delete_pool void ios_delete_pool(glp_tree *tree, IOSPOOL *pool); /* delete cut pool */ #if 1 /* 11/VII-2013 */ #define ios_process_sol _glp_ios_process_sol void ios_process_sol(glp_tree *T); /* process integer feasible solution just found */ #endif #define ios_preprocess_node _glp_ios_preprocess_node int ios_preprocess_node(glp_tree *tree, int max_pass); /* preprocess current subproblem */ #define ios_driver _glp_ios_driver int ios_driver(glp_tree *tree); /* branch-and-bound driver */ /**********************************************************************/ typedef struct IOSVEC IOSVEC; struct IOSVEC { /* sparse vector v = (v[j]) */ int n; /* dimension, n >= 0 */ int nnz; /* number of non-zero components, 0 <= nnz <= n */ int *pos; /* int pos[1+n]; */ /* pos[j] = k, 1 <= j <= n, is position of (non-zero) v[j] in the arrays ind and val, where 1 <= k <= nnz; pos[j] = 0 means that v[j] is structural zero */ int *ind; /* int ind[1+n]; */ /* ind[k] = j, 1 <= k <= nnz, is index of v[j] */ double *val; /* double val[1+n]; */ /* val[k], 1 <= k <= nnz, is a numeric value of v[j] */ }; #define ios_create_vec _glp_ios_create_vec IOSVEC *ios_create_vec(int n); /* create sparse vector */ #define ios_check_vec _glp_ios_check_vec void ios_check_vec(IOSVEC *v); /* check that sparse vector has correct representation */ #define ios_get_vj _glp_ios_get_vj double ios_get_vj(IOSVEC *v, int j); /* retrieve component of sparse vector */ #define ios_set_vj _glp_ios_set_vj void ios_set_vj(IOSVEC *v, int j, double val); /* set/change component of sparse vector */ #define ios_clear_vec _glp_ios_clear_vec void ios_clear_vec(IOSVEC *v); /* set all components of sparse vector to zero */ #define ios_clean_vec _glp_ios_clean_vec void ios_clean_vec(IOSVEC *v, double eps); /* remove zero or small components from sparse vector */ #define ios_copy_vec _glp_ios_copy_vec void ios_copy_vec(IOSVEC *x, IOSVEC *y); /* copy sparse vector (x := y) */ #define ios_linear_comb _glp_ios_linear_comb void ios_linear_comb(IOSVEC *x, double a, IOSVEC *y); /* compute linear combination (x := x + a * y) */ #define ios_delete_vec _glp_ios_delete_vec void ios_delete_vec(IOSVEC *v); /* delete sparse vector */ /**********************************************************************/ #define ios_gmi_gen _glp_ios_gmi_gen void ios_gmi_gen(glp_tree *tree); /* generate Gomory's mixed integer cuts */ #define ios_mir_init _glp_ios_mir_init void *ios_mir_init(glp_tree *tree); /* initialize MIR cut generator */ #define ios_mir_gen _glp_ios_mir_gen void ios_mir_gen(glp_tree *tree, void *gen); /* generate MIR cuts */ #define ios_mir_term _glp_ios_mir_term void ios_mir_term(void *gen); /* terminate MIR cut generator */ #define ios_cov_gen _glp_ios_cov_gen void ios_cov_gen(glp_tree *tree); /* generate mixed cover cuts */ #define ios_clq_init _glp_ios_clq_init void *ios_clq_init(glp_tree *tree); /* initialize clique cut generator */ #define ios_clq_gen _glp_ios_clq_gen void ios_clq_gen(glp_tree *tree, void *gen); /* generate clique cuts */ #define ios_clq_term _glp_ios_clq_term void ios_clq_term(void *gen); /* terminate clique cut generator */ #define ios_pcost_init _glp_ios_pcost_init void *ios_pcost_init(glp_tree *tree); /* initialize working data used on pseudocost branching */ #define ios_pcost_branch _glp_ios_pcost_branch int ios_pcost_branch(glp_tree *T, int *next); /* choose branching variable with pseudocost branching */ #define ios_pcost_update _glp_ios_pcost_update void ios_pcost_update(glp_tree *tree); /* update history information for pseudocost branching */ #define ios_pcost_free _glp_ios_pcost_free void ios_pcost_free(glp_tree *tree); /* free working area used on pseudocost branching */ #define ios_feas_pump _glp_ios_feas_pump void ios_feas_pump(glp_tree *T); /* feasibility pump heuristic */ #if 1 /* 25/V-2013 */ #define ios_proxy_heur _glp_ios_proxy_heur void ios_proxy_heur(glp_tree *T); /* proximity search heuristic */ #endif #define ios_process_cuts _glp_ios_process_cuts void ios_process_cuts(glp_tree *T); /* process cuts stored in the local cut pool */ #define ios_choose_node _glp_ios_choose_node int ios_choose_node(glp_tree *T); /* select subproblem to continue the search */ #define ios_choose_var _glp_ios_choose_var int ios_choose_var(glp_tree *T, int *next); /* select variable to branch on */ #endif /* eof */ glpk-4.52.1/src/glpios01.c0000644000062000006210000014621212175147600014320 0ustar maomkpasswd/* glpios01.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" #include "glplib.h" /*********************************************************************** * NAME * * ios_create_tree - create branch-and-bound tree * * SYNOPSIS * * #include "glpios.h" * glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm); * * DESCRIPTION * * The routine ios_create_tree creates the branch-and-bound tree. * * Being created the tree consists of the only root subproblem whose * reference number is 1. Note that initially the root subproblem is in * frozen state and therefore needs to be revived. * * RETURNS * * The routine returns a pointer to the tree created. */ static IOSNPD *new_node(glp_tree *tree, IOSNPD *parent); glp_tree *ios_create_tree(glp_prob *mip, const glp_iocp *parm) { int m = mip->m; int n = mip->n; glp_tree *tree; int i, j; xassert(mip->tree == NULL); mip->tree = tree = xmalloc(sizeof(glp_tree)); tree->pool = dmp_create_pool(); tree->n = n; /* save original problem components */ tree->orig_m = m; tree->orig_type = xcalloc(1+m+n, sizeof(char)); tree->orig_lb = xcalloc(1+m+n, sizeof(double)); tree->orig_ub = xcalloc(1+m+n, sizeof(double)); tree->orig_stat = xcalloc(1+m+n, sizeof(char)); tree->orig_prim = xcalloc(1+m+n, sizeof(double)); tree->orig_dual = xcalloc(1+m+n, sizeof(double)); for (i = 1; i <= m; i++) { GLPROW *row = mip->row[i]; tree->orig_type[i] = (char)row->type; tree->orig_lb[i] = row->lb; tree->orig_ub[i] = row->ub; tree->orig_stat[i] = (char)row->stat; tree->orig_prim[i] = row->prim; tree->orig_dual[i] = row->dual; } for (j = 1; j <= n; j++) { GLPCOL *col = mip->col[j]; tree->orig_type[m+j] = (char)col->type; tree->orig_lb[m+j] = col->lb; tree->orig_ub[m+j] = col->ub; tree->orig_stat[m+j] = (char)col->stat; tree->orig_prim[m+j] = col->prim; tree->orig_dual[m+j] = col->dual; } tree->orig_obj = mip->obj_val; /* initialize the branch-and-bound tree */ tree->nslots = 0; tree->avail = 0; tree->slot = NULL; tree->head = tree->tail = NULL; tree->a_cnt = tree->n_cnt = tree->t_cnt = 0; /* the root subproblem is not solved yet, so its final components are unknown so far */ tree->root_m = 0; tree->root_type = NULL; tree->root_lb = tree->root_ub = NULL; tree->root_stat = NULL; /* the current subproblem does not exist yet */ tree->curr = NULL; tree->mip = mip; /*tree->solved = 0;*/ tree->non_int = xcalloc(1+n, sizeof(char)); memset(&tree->non_int[1], 0, n); /* arrays to save parent subproblem components will be allocated later */ tree->pred_m = tree->pred_max = 0; tree->pred_type = NULL; tree->pred_lb = tree->pred_ub = NULL; tree->pred_stat = NULL; /* cut generator */ tree->local = ios_create_pool(tree); /*tree->first_attempt = 1;*/ /*tree->max_added_cuts = 0;*/ /*tree->min_eff = 0.0;*/ /*tree->miss = 0;*/ /*tree->just_selected = 0;*/ tree->mir_gen = NULL; tree->clq_gen = NULL; /*tree->round = 0;*/ #if 0 /* create the conflict graph */ tree->n_ref = xcalloc(1+n, sizeof(int)); memset(&tree->n_ref[1], 0, n * sizeof(int)); tree->c_ref = xcalloc(1+n, sizeof(int)); memset(&tree->c_ref[1], 0, n * sizeof(int)); tree->g = scg_create_graph(0); tree->j_ref = xcalloc(1+tree->g->n_max, sizeof(int)); #endif /* pseudocost branching */ tree->pcost = NULL; tree->iwrk = xcalloc(1+n, sizeof(int)); tree->dwrk = xcalloc(1+n, sizeof(double)); /* initialize control parameters */ tree->parm = parm; tree->tm_beg = xtime(); #if 0 /* 10/VI-2013 */ tree->tm_lag = xlset(0); #else tree->tm_lag = 0.0; #endif tree->sol_cnt = 0; #if 1 /* 11/VII-2013 */ tree->P = NULL; tree->npp = NULL; tree->save_sol = parm->save_sol; tree->save_cnt = 0; #endif /* initialize advanced solver interface */ tree->reason = 0; tree->reopt = 0; tree->reinv = 0; tree->br_var = 0; tree->br_sel = 0; tree->child = 0; tree->next_p = 0; /*tree->btrack = NULL;*/ tree->stop = 0; /* create the root subproblem, which initially is identical to the original MIP */ new_node(tree, NULL); return tree; } /*********************************************************************** * NAME * * ios_revive_node - revive specified subproblem * * SYNOPSIS * * #include "glpios.h" * void ios_revive_node(glp_tree *tree, int p); * * DESCRIPTION * * The routine ios_revive_node revives the specified subproblem, whose * reference number is p, and thereby makes it the current subproblem. * Note that the specified subproblem must be active. Besides, if the * current subproblem already exists, it must be frozen before reviving * another subproblem. */ void ios_revive_node(glp_tree *tree, int p) { glp_prob *mip = tree->mip; IOSNPD *node, *root; /* obtain pointer to the specified subproblem */ xassert(1 <= p && p <= tree->nslots); node = tree->slot[p].node; xassert(node != NULL); /* the specified subproblem must be active */ xassert(node->count == 0); /* the current subproblem must not exist */ xassert(tree->curr == NULL); /* the specified subproblem becomes current */ tree->curr = node; /*tree->solved = 0;*/ /* obtain pointer to the root subproblem */ root = tree->slot[1].node; xassert(root != NULL); /* at this point problem object components correspond to the root subproblem, so if the root subproblem should be revived, there is nothing more to do */ if (node == root) goto done; xassert(mip->m == tree->root_m); /* build path from the root to the current node */ node->temp = NULL; for (node = node; node != NULL; node = node->up) { if (node->up == NULL) xassert(node == root); else node->up->temp = node; } /* go down from the root to the current node and make necessary changes to restore components of the current subproblem */ for (node = root; node != NULL; node = node->temp) { int m = mip->m; int n = mip->n; /* if the current node is reached, the problem object at this point corresponds to its parent, so save attributes of rows and columns for the parent subproblem */ if (node->temp == NULL) { int i, j; tree->pred_m = m; /* allocate/reallocate arrays, if necessary */ if (tree->pred_max < m + n) { int new_size = m + n + 100; if (tree->pred_type != NULL) xfree(tree->pred_type); if (tree->pred_lb != NULL) xfree(tree->pred_lb); if (tree->pred_ub != NULL) xfree(tree->pred_ub); if (tree->pred_stat != NULL) xfree(tree->pred_stat); tree->pred_max = new_size; tree->pred_type = xcalloc(1+new_size, sizeof(char)); tree->pred_lb = xcalloc(1+new_size, sizeof(double)); tree->pred_ub = xcalloc(1+new_size, sizeof(double)); tree->pred_stat = xcalloc(1+new_size, sizeof(char)); } /* save row attributes */ for (i = 1; i <= m; i++) { GLPROW *row = mip->row[i]; tree->pred_type[i] = (char)row->type; tree->pred_lb[i] = row->lb; tree->pred_ub[i] = row->ub; tree->pred_stat[i] = (char)row->stat; } /* save column attributes */ for (j = 1; j <= n; j++) { GLPCOL *col = mip->col[j]; tree->pred_type[mip->m+j] = (char)col->type; tree->pred_lb[mip->m+j] = col->lb; tree->pred_ub[mip->m+j] = col->ub; tree->pred_stat[mip->m+j] = (char)col->stat; } } /* change bounds of rows and columns */ { IOSBND *b; for (b = node->b_ptr; b != NULL; b = b->next) { if (b->k <= m) glp_set_row_bnds(mip, b->k, b->type, b->lb, b->ub); else glp_set_col_bnds(mip, b->k-m, b->type, b->lb, b->ub); } } /* change statuses of rows and columns */ { IOSTAT *s; for (s = node->s_ptr; s != NULL; s = s->next) { if (s->k <= m) glp_set_row_stat(mip, s->k, s->stat); else glp_set_col_stat(mip, s->k-m, s->stat); } } /* add new rows */ if (node->r_ptr != NULL) { IOSROW *r; IOSAIJ *a; int i, len, *ind; double *val; ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (r = node->r_ptr; r != NULL; r = r->next) { i = glp_add_rows(mip, 1); glp_set_row_name(mip, i, r->name); #if 1 /* 20/IX-2008 */ xassert(mip->row[i]->level == 0); mip->row[i]->level = node->level; mip->row[i]->origin = r->origin; mip->row[i]->klass = r->klass; #endif glp_set_row_bnds(mip, i, r->type, r->lb, r->ub); len = 0; for (a = r->ptr; a != NULL; a = a->next) len++, ind[len] = a->j, val[len] = a->val; glp_set_mat_row(mip, i, len, ind, val); glp_set_rii(mip, i, r->rii); glp_set_row_stat(mip, i, r->stat); } xfree(ind); xfree(val); } #if 0 /* add new edges to the conflict graph */ /* add new cliques to the conflict graph */ /* (not implemented yet) */ xassert(node->own_nn == 0); xassert(node->own_nc == 0); xassert(node->e_ptr == NULL); #endif } /* the specified subproblem has been revived */ node = tree->curr; /* delete its bound change list */ while (node->b_ptr != NULL) { IOSBND *b; b = node->b_ptr; node->b_ptr = b->next; dmp_free_atom(tree->pool, b, sizeof(IOSBND)); } /* delete its status change list */ while (node->s_ptr != NULL) { IOSTAT *s; s = node->s_ptr; node->s_ptr = s->next; dmp_free_atom(tree->pool, s, sizeof(IOSTAT)); } #if 1 /* 20/XI-2009 */ /* delete its row addition list (additional rows may appear, for example, due to branching on GUB constraints */ while (node->r_ptr != NULL) { IOSROW *r; r = node->r_ptr; node->r_ptr = r->next; xassert(r->name == NULL); while (r->ptr != NULL) { IOSAIJ *a; a = r->ptr; r->ptr = a->next; dmp_free_atom(tree->pool, a, sizeof(IOSAIJ)); } dmp_free_atom(tree->pool, r, sizeof(IOSROW)); } #endif done: return; } /*********************************************************************** * NAME * * ios_freeze_node - freeze current subproblem * * SYNOPSIS * * #include "glpios.h" * void ios_freeze_node(glp_tree *tree); * * DESCRIPTION * * The routine ios_freeze_node freezes the current subproblem. */ void ios_freeze_node(glp_tree *tree) { glp_prob *mip = tree->mip; int m = mip->m; int n = mip->n; IOSNPD *node; /* obtain pointer to the current subproblem */ node = tree->curr; xassert(node != NULL); if (node->up == NULL) { /* freeze the root subproblem */ int k; xassert(node->p == 1); xassert(tree->root_m == 0); xassert(tree->root_type == NULL); xassert(tree->root_lb == NULL); xassert(tree->root_ub == NULL); xassert(tree->root_stat == NULL); tree->root_m = m; tree->root_type = xcalloc(1+m+n, sizeof(char)); tree->root_lb = xcalloc(1+m+n, sizeof(double)); tree->root_ub = xcalloc(1+m+n, sizeof(double)); tree->root_stat = xcalloc(1+m+n, sizeof(char)); for (k = 1; k <= m+n; k++) { if (k <= m) { GLPROW *row = mip->row[k]; tree->root_type[k] = (char)row->type; tree->root_lb[k] = row->lb; tree->root_ub[k] = row->ub; tree->root_stat[k] = (char)row->stat; } else { GLPCOL *col = mip->col[k-m]; tree->root_type[k] = (char)col->type; tree->root_lb[k] = col->lb; tree->root_ub[k] = col->ub; tree->root_stat[k] = (char)col->stat; } } } else { /* freeze non-root subproblem */ int root_m = tree->root_m; int pred_m = tree->pred_m; int i, j, k; xassert(pred_m <= m); /* build change lists for rows and columns which exist in the parent subproblem */ xassert(node->b_ptr == NULL); xassert(node->s_ptr == NULL); for (k = 1; k <= pred_m + n; k++) { int pred_type, pred_stat, type, stat; double pred_lb, pred_ub, lb, ub; /* determine attributes in the parent subproblem */ pred_type = tree->pred_type[k]; pred_lb = tree->pred_lb[k]; pred_ub = tree->pred_ub[k]; pred_stat = tree->pred_stat[k]; /* determine attributes in the current subproblem */ if (k <= pred_m) { GLPROW *row = mip->row[k]; type = row->type; lb = row->lb; ub = row->ub; stat = row->stat; } else { GLPCOL *col = mip->col[k - pred_m]; type = col->type; lb = col->lb; ub = col->ub; stat = col->stat; } /* save type and bounds of a row/column, if changed */ if (!(pred_type == type && pred_lb == lb && pred_ub == ub)) { IOSBND *b; b = dmp_get_atom(tree->pool, sizeof(IOSBND)); b->k = k; b->type = (unsigned char)type; b->lb = lb; b->ub = ub; b->next = node->b_ptr; node->b_ptr = b; } /* save status of a row/column, if changed */ if (pred_stat != stat) { IOSTAT *s; s = dmp_get_atom(tree->pool, sizeof(IOSTAT)); s->k = k; s->stat = (unsigned char)stat; s->next = node->s_ptr; node->s_ptr = s; } } /* save new rows added to the current subproblem */ xassert(node->r_ptr == NULL); if (pred_m < m) { int i, len, *ind; double *val; ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (i = m; i > pred_m; i--) { GLPROW *row = mip->row[i]; IOSROW *r; const char *name; r = dmp_get_atom(tree->pool, sizeof(IOSROW)); name = glp_get_row_name(mip, i); if (name == NULL) r->name = NULL; else { r->name = dmp_get_atom(tree->pool, strlen(name)+1); strcpy(r->name, name); } #if 1 /* 20/IX-2008 */ r->origin = row->origin; r->klass = row->klass; #endif r->type = (unsigned char)row->type; r->lb = row->lb; r->ub = row->ub; r->ptr = NULL; len = glp_get_mat_row(mip, i, ind, val); for (k = 1; k <= len; k++) { IOSAIJ *a; a = dmp_get_atom(tree->pool, sizeof(IOSAIJ)); a->j = ind[k]; a->val = val[k]; a->next = r->ptr; r->ptr = a; } r->rii = row->rii; r->stat = (unsigned char)row->stat; r->next = node->r_ptr; node->r_ptr = r; } xfree(ind); xfree(val); } /* remove all rows missing in the root subproblem */ if (m != root_m) { int nrs, *num; nrs = m - root_m; xassert(nrs > 0); num = xcalloc(1+nrs, sizeof(int)); for (i = 1; i <= nrs; i++) num[i] = root_m + i; glp_del_rows(mip, nrs, num); xfree(num); } m = mip->m; /* and restore attributes of all rows and columns for the root subproblem */ xassert(m == root_m); for (i = 1; i <= m; i++) { glp_set_row_bnds(mip, i, tree->root_type[i], tree->root_lb[i], tree->root_ub[i]); glp_set_row_stat(mip, i, tree->root_stat[i]); } for (j = 1; j <= n; j++) { glp_set_col_bnds(mip, j, tree->root_type[m+j], tree->root_lb[m+j], tree->root_ub[m+j]); glp_set_col_stat(mip, j, tree->root_stat[m+j]); } #if 1 /* remove all edges and cliques missing in the conflict graph for the root subproblem */ /* (not implemented yet) */ #endif } /* the current subproblem has been frozen */ tree->curr = NULL; return; } /*********************************************************************** * NAME * * ios_clone_node - clone specified subproblem * * SYNOPSIS * * #include "glpios.h" * void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]); * * DESCRIPTION * * The routine ios_clone_node clones the specified subproblem, whose * reference number is p, creating its nnn exact copies. Note that the * specified subproblem must be active and must be in the frozen state * (i.e. it must not be the current subproblem). * * Each clone, an exact copy of the specified subproblem, becomes a new * active subproblem added to the end of the active list. After cloning * the specified subproblem becomes inactive. * * The reference numbers of clone subproblems are stored to locations * ref[1], ..., ref[nnn]. */ static int get_slot(glp_tree *tree) { int p; /* if no free slots are available, increase the room */ if (tree->avail == 0) { int nslots = tree->nslots; IOSLOT *save = tree->slot; if (nslots == 0) tree->nslots = 20; else { tree->nslots = nslots + nslots; xassert(tree->nslots > nslots); } tree->slot = xcalloc(1+tree->nslots, sizeof(IOSLOT)); if (save != NULL) { memcpy(&tree->slot[1], &save[1], nslots * sizeof(IOSLOT)); xfree(save); } /* push more free slots into the stack */ for (p = tree->nslots; p > nslots; p--) { tree->slot[p].node = NULL; tree->slot[p].next = tree->avail; tree->avail = p; } } /* pull a free slot from the stack */ p = tree->avail; tree->avail = tree->slot[p].next; xassert(tree->slot[p].node == NULL); tree->slot[p].next = 0; return p; } static IOSNPD *new_node(glp_tree *tree, IOSNPD *parent) { IOSNPD *node; int p; /* pull a free slot for the new node */ p = get_slot(tree); /* create descriptor of the new subproblem */ node = dmp_get_atom(tree->pool, sizeof(IOSNPD)); tree->slot[p].node = node; node->p = p; node->up = parent; node->level = (parent == NULL ? 0 : parent->level + 1); node->count = 0; node->b_ptr = NULL; node->s_ptr = NULL; node->r_ptr = NULL; node->solved = 0; #if 0 node->own_nn = node->own_nc = 0; node->e_ptr = NULL; #endif #if 1 /* 04/X-2008 */ node->lp_obj = (parent == NULL ? (tree->mip->dir == GLP_MIN ? -DBL_MAX : +DBL_MAX) : parent->lp_obj); #endif node->bound = (parent == NULL ? (tree->mip->dir == GLP_MIN ? -DBL_MAX : +DBL_MAX) : parent->bound); node->br_var = 0; node->br_val = 0.0; node->ii_cnt = 0; node->ii_sum = 0.0; #if 1 /* 30/XI-2009 */ node->changed = 0; #endif if (tree->parm->cb_size == 0) node->data = NULL; else { node->data = dmp_get_atom(tree->pool, tree->parm->cb_size); memset(node->data, 0, tree->parm->cb_size); } node->temp = NULL; node->prev = tree->tail; node->next = NULL; /* add the new subproblem to the end of the active list */ if (tree->head == NULL) tree->head = node; else tree->tail->next = node; tree->tail = node; tree->a_cnt++; tree->n_cnt++; tree->t_cnt++; /* increase the number of child subproblems */ if (parent == NULL) xassert(p == 1); else parent->count++; return node; } void ios_clone_node(glp_tree *tree, int p, int nnn, int ref[]) { IOSNPD *node; int k; /* obtain pointer to the subproblem to be cloned */ xassert(1 <= p && p <= tree->nslots); node = tree->slot[p].node; xassert(node != NULL); /* the specified subproblem must be active */ xassert(node->count == 0); /* and must be in the frozen state */ xassert(tree->curr != node); /* remove the specified subproblem from the active list, because it becomes inactive */ if (node->prev == NULL) tree->head = node->next; else node->prev->next = node->next; if (node->next == NULL) tree->tail = node->prev; else node->next->prev = node->prev; node->prev = node->next = NULL; tree->a_cnt--; /* create clone subproblems */ xassert(nnn > 0); for (k = 1; k <= nnn; k++) ref[k] = new_node(tree, node)->p; return; } /*********************************************************************** * NAME * * ios_delete_node - delete specified subproblem * * SYNOPSIS * * #include "glpios.h" * void ios_delete_node(glp_tree *tree, int p); * * DESCRIPTION * * The routine ios_delete_node deletes the specified subproblem, whose * reference number is p. The subproblem must be active and must be in * the frozen state (i.e. it must not be the current subproblem). * * Note that deletion is performed recursively, i.e. if a subproblem to * be deleted is the only child of its parent, the parent subproblem is * also deleted, etc. */ void ios_delete_node(glp_tree *tree, int p) { IOSNPD *node, *temp; /* obtain pointer to the subproblem to be deleted */ xassert(1 <= p && p <= tree->nslots); node = tree->slot[p].node; xassert(node != NULL); /* the specified subproblem must be active */ xassert(node->count == 0); /* and must be in the frozen state */ xassert(tree->curr != node); /* remove the specified subproblem from the active list, because it is gone from the tree */ if (node->prev == NULL) tree->head = node->next; else node->prev->next = node->next; if (node->next == NULL) tree->tail = node->prev; else node->next->prev = node->prev; node->prev = node->next = NULL; tree->a_cnt--; loop: /* recursive deletion starts here */ /* delete the bound change list */ { IOSBND *b; while (node->b_ptr != NULL) { b = node->b_ptr; node->b_ptr = b->next; dmp_free_atom(tree->pool, b, sizeof(IOSBND)); } } /* delete the status change list */ { IOSTAT *s; while (node->s_ptr != NULL) { s = node->s_ptr; node->s_ptr = s->next; dmp_free_atom(tree->pool, s, sizeof(IOSTAT)); } } /* delete the row addition list */ while (node->r_ptr != NULL) { IOSROW *r; r = node->r_ptr; if (r->name != NULL) dmp_free_atom(tree->pool, r->name, strlen(r->name)+1); while (r->ptr != NULL) { IOSAIJ *a; a = r->ptr; r->ptr = a->next; dmp_free_atom(tree->pool, a, sizeof(IOSAIJ)); } node->r_ptr = r->next; dmp_free_atom(tree->pool, r, sizeof(IOSROW)); } #if 0 /* delete the edge addition list */ /* delete the clique addition list */ /* (not implemented yet) */ xassert(node->own_nn == 0); xassert(node->own_nc == 0); xassert(node->e_ptr == NULL); #endif /* free application-specific data */ if (tree->parm->cb_size == 0) xassert(node->data == NULL); else dmp_free_atom(tree->pool, node->data, tree->parm->cb_size); /* free the corresponding node slot */ p = node->p; xassert(tree->slot[p].node == node); tree->slot[p].node = NULL; tree->slot[p].next = tree->avail; tree->avail = p; /* save pointer to the parent subproblem */ temp = node->up; /* delete the subproblem descriptor */ dmp_free_atom(tree->pool, node, sizeof(IOSNPD)); tree->n_cnt--; /* take pointer to the parent subproblem */ node = temp; if (node != NULL) { /* the parent subproblem exists; decrease the number of its child subproblems */ xassert(node->count > 0); node->count--; /* if now the parent subproblem has no childs, it also must be deleted */ if (node->count == 0) goto loop; } return; } /*********************************************************************** * NAME * * ios_delete_tree - delete branch-and-bound tree * * SYNOPSIS * * #include "glpios.h" * void ios_delete_tree(glp_tree *tree); * * DESCRIPTION * * The routine ios_delete_tree deletes the branch-and-bound tree, which * the parameter tree points to, and frees all the memory allocated to * this program object. * * On exit components of the problem object are restored to correspond * to the original MIP passed to the routine ios_create_tree. */ void ios_delete_tree(glp_tree *tree) { glp_prob *mip = tree->mip; int i, j; int m = mip->m; int n = mip->n; xassert(mip->tree == tree); /* remove all additional rows */ if (m != tree->orig_m) { int nrs, *num; nrs = m - tree->orig_m; xassert(nrs > 0); num = xcalloc(1+nrs, sizeof(int)); for (i = 1; i <= nrs; i++) num[i] = tree->orig_m + i; glp_del_rows(mip, nrs, num); xfree(num); } m = tree->orig_m; /* restore original attributes of rows and columns */ xassert(m == tree->orig_m); xassert(n == tree->n); for (i = 1; i <= m; i++) { glp_set_row_bnds(mip, i, tree->orig_type[i], tree->orig_lb[i], tree->orig_ub[i]); glp_set_row_stat(mip, i, tree->orig_stat[i]); mip->row[i]->prim = tree->orig_prim[i]; mip->row[i]->dual = tree->orig_dual[i]; } for (j = 1; j <= n; j++) { glp_set_col_bnds(mip, j, tree->orig_type[m+j], tree->orig_lb[m+j], tree->orig_ub[m+j]); glp_set_col_stat(mip, j, tree->orig_stat[m+j]); mip->col[j]->prim = tree->orig_prim[m+j]; mip->col[j]->dual = tree->orig_dual[m+j]; } mip->pbs_stat = mip->dbs_stat = GLP_FEAS; mip->obj_val = tree->orig_obj; /* delete the branch-and-bound tree */ xassert(tree->local != NULL); ios_delete_pool(tree, tree->local); dmp_delete_pool(tree->pool); xfree(tree->orig_type); xfree(tree->orig_lb); xfree(tree->orig_ub); xfree(tree->orig_stat); xfree(tree->orig_prim); xfree(tree->orig_dual); xfree(tree->slot); if (tree->root_type != NULL) xfree(tree->root_type); if (tree->root_lb != NULL) xfree(tree->root_lb); if (tree->root_ub != NULL) xfree(tree->root_ub); if (tree->root_stat != NULL) xfree(tree->root_stat); xfree(tree->non_int); #if 0 xfree(tree->n_ref); xfree(tree->c_ref); xfree(tree->j_ref); #endif if (tree->pcost != NULL) ios_pcost_free(tree); xfree(tree->iwrk); xfree(tree->dwrk); #if 0 scg_delete_graph(tree->g); #endif if (tree->pred_type != NULL) xfree(tree->pred_type); if (tree->pred_lb != NULL) xfree(tree->pred_lb); if (tree->pred_ub != NULL) xfree(tree->pred_ub); if (tree->pred_stat != NULL) xfree(tree->pred_stat); #if 0 xassert(tree->cut_gen == NULL); #endif xassert(tree->mir_gen == NULL); xassert(tree->clq_gen == NULL); xfree(tree); mip->tree = NULL; return; } /*********************************************************************** * NAME * * ios_eval_degrad - estimate obj. degrad. for down- and up-branches * * SYNOPSIS * * #include "glpios.h" * void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up); * * DESCRIPTION * * Given optimal basis to LP relaxation of the current subproblem the * routine ios_eval_degrad performs the dual ratio test to compute the * objective values in the adjacent basis for down- and up-branches, * which are stored in locations *dn and *up, assuming that x[j] is a * variable chosen to branch upon. */ void ios_eval_degrad(glp_tree *tree, int j, double *dn, double *up) { glp_prob *mip = tree->mip; int m = mip->m, n = mip->n; int len, kase, k, t, stat; double alfa, beta, gamma, delta, dz; int *ind = tree->iwrk; double *val = tree->dwrk; /* current basis must be optimal */ xassert(glp_get_status(mip) == GLP_OPT); /* basis factorization must exist */ xassert(glp_bf_exists(mip)); /* obtain (fractional) value of x[j] in optimal basic solution to LP relaxation of the current subproblem */ xassert(1 <= j && j <= n); beta = mip->col[j]->prim; /* since the value of x[j] is fractional, it is basic; compute corresponding row of the simplex table */ len = lpx_eval_tab_row(mip, m+j, ind, val); /* kase < 0 means down-branch; kase > 0 means up-branch */ for (kase = -1; kase <= +1; kase += 2) { /* for down-branch we introduce new upper bound floor(beta) for x[j]; similarly, for up-branch we introduce new lower bound ceil(beta) for x[j]; in the current basis this new upper/lower bound is violated, so in the adjacent basis x[j] will leave the basis and go to its new upper/lower bound; we need to know which non-basic variable x[k] should enter the basis to keep dual feasibility */ #if 0 /* 23/XI-2009 */ k = lpx_dual_ratio_test(mip, len, ind, val, kase, 1e-7); #else k = lpx_dual_ratio_test(mip, len, ind, val, kase, 1e-9); #endif /* if no variable has been chosen, current basis being primal infeasible due to the new upper/lower bound of x[j] is dual unbounded, therefore, LP relaxation to corresponding branch has no primal feasible solution */ if (k == 0) { if (mip->dir == GLP_MIN) { if (kase < 0) *dn = +DBL_MAX; else *up = +DBL_MAX; } else if (mip->dir == GLP_MAX) { if (kase < 0) *dn = -DBL_MAX; else *up = -DBL_MAX; } else xassert(mip != mip); continue; } xassert(1 <= k && k <= m+n); /* row of the simplex table corresponding to specified basic variable x[j] is the following: x[j] = ... + alfa * x[k] + ... ; we need to know influence coefficient, alfa, at non-basic variable x[k] chosen with the dual ratio test */ for (t = 1; t <= len; t++) if (ind[t] == k) break; xassert(1 <= t && t <= len); alfa = val[t]; /* determine status and reduced cost of variable x[k] */ if (k <= m) { stat = mip->row[k]->stat; gamma = mip->row[k]->dual; } else { stat = mip->col[k-m]->stat; gamma = mip->col[k-m]->dual; } /* x[k] cannot be basic or fixed non-basic */ xassert(stat == GLP_NL || stat == GLP_NU || stat == GLP_NF); /* if the current basis is dual degenerative, some reduced costs, which are close to zero, may have wrong sign due to round-off errors, so correct the sign of gamma */ if (mip->dir == GLP_MIN) { if (stat == GLP_NL && gamma < 0.0 || stat == GLP_NU && gamma > 0.0 || stat == GLP_NF) gamma = 0.0; } else if (mip->dir == GLP_MAX) { if (stat == GLP_NL && gamma > 0.0 || stat == GLP_NU && gamma < 0.0 || stat == GLP_NF) gamma = 0.0; } else xassert(mip != mip); /* determine the change of x[j] in the adjacent basis: delta x[j] = new x[j] - old x[j] */ delta = (kase < 0 ? floor(beta) : ceil(beta)) - beta; /* compute the change of x[k] in the adjacent basis: delta x[k] = new x[k] - old x[k] = delta x[j] / alfa */ delta /= alfa; /* compute the change of the objective in the adjacent basis: delta z = new z - old z = gamma * delta x[k] */ dz = gamma * delta; if (mip->dir == GLP_MIN) xassert(dz >= 0.0); else if (mip->dir == GLP_MAX) xassert(dz <= 0.0); else xassert(mip != mip); /* compute the new objective value in the adjacent basis: new z = old z + delta z */ if (kase < 0) *dn = mip->obj_val + dz; else *up = mip->obj_val + dz; } /*xprintf("obj = %g; dn = %g; up = %g\n", mip->obj_val, *dn, *up);*/ return; } /*********************************************************************** * NAME * * ios_round_bound - improve local bound by rounding * * SYNOPSIS * * #include "glpios.h" * double ios_round_bound(glp_tree *tree, double bound); * * RETURNS * * For the given local bound for any integer feasible solution to the * current subproblem the routine ios_round_bound returns an improved * local bound for the same integer feasible solution. * * BACKGROUND * * Let the current subproblem has the following objective function: * * z = sum c[j] * x[j] + s >= b, (1) * j in J * * where J = {j: c[j] is non-zero and integer, x[j] is integer}, s is * the sum of terms corresponding to fixed variables, b is an initial * local bound (minimization). * * From (1) it follows that: * * d * sum (c[j] / d) * x[j] + s >= b, (2) * j in J * * or, equivalently, * * sum (c[j] / d) * x[j] >= (b - s) / d = h, (3) * j in J * * where d = gcd(c[j]). Since the left-hand side of (3) is integer, * h = (b - s) / d can be rounded up to the nearest integer: * * h' = ceil(h) = (b' - s) / d, (4) * * that gives an rounded, improved local bound: * * b' = d * h' + s. (5) * * In case of maximization '>=' in (1) should be replaced by '<=' that * leads to the following formula: * * h' = floor(h) = (b' - s) / d, (6) * * which should used in the same way as (4). * * NOTE: If b is a valid local bound for a child of the current * subproblem, b' is also valid for that child subproblem. */ double ios_round_bound(glp_tree *tree, double bound) { glp_prob *mip = tree->mip; int n = mip->n; int d, j, nn, *c = tree->iwrk; double s, h; /* determine c[j] and compute s */ nn = 0, s = mip->c0, d = 0; for (j = 1; j <= n; j++) { GLPCOL *col = mip->col[j]; if (col->coef == 0.0) continue; if (col->type == GLP_FX) { /* fixed variable */ s += col->coef * col->prim; } else { /* non-fixed variable */ if (col->kind != GLP_IV) goto skip; if (col->coef != floor(col->coef)) goto skip; if (fabs(col->coef) <= (double)INT_MAX) c[++nn] = (int)fabs(col->coef); else d = 1; } } /* compute d = gcd(c[1],...c[nn]) */ if (d == 0) { if (nn == 0) goto skip; d = gcdn(nn, c); } xassert(d > 0); /* compute new local bound */ if (mip->dir == GLP_MIN) { if (bound != +DBL_MAX) { h = (bound - s) / (double)d; if (h >= floor(h) + 0.001) { /* round up */ h = ceil(h); /*xprintf("d = %d; old = %g; ", d, bound);*/ bound = (double)d * h + s; /*xprintf("new = %g\n", bound);*/ } } } else if (mip->dir == GLP_MAX) { if (bound != -DBL_MAX) { h = (bound - s) / (double)d; if (h <= ceil(h) - 0.001) { /* round down */ h = floor(h); bound = (double)d * h + s; } } } else xassert(mip != mip); skip: return bound; } /*********************************************************************** * NAME * * ios_is_hopeful - check if subproblem is hopeful * * SYNOPSIS * * #include "glpios.h" * int ios_is_hopeful(glp_tree *tree, double bound); * * DESCRIPTION * * Given the local bound of a subproblem the routine ios_is_hopeful * checks if the subproblem can have an integer optimal solution which * is better than the best one currently known. * * RETURNS * * If the subproblem can have a better integer optimal solution, the * routine returns non-zero; otherwise, if the corresponding branch can * be pruned, the routine returns zero. */ int ios_is_hopeful(glp_tree *tree, double bound) { glp_prob *mip = tree->mip; int ret = 1; double eps; if (mip->mip_stat == GLP_FEAS) { eps = tree->parm->tol_obj * (1.0 + fabs(mip->mip_obj)); switch (mip->dir) { case GLP_MIN: if (bound >= mip->mip_obj - eps) ret = 0; break; case GLP_MAX: if (bound <= mip->mip_obj + eps) ret = 0; break; default: xassert(mip != mip); } } else { switch (mip->dir) { case GLP_MIN: if (bound == +DBL_MAX) ret = 0; break; case GLP_MAX: if (bound == -DBL_MAX) ret = 0; break; default: xassert(mip != mip); } } return ret; } /*********************************************************************** * NAME * * ios_best_node - find active node with best local bound * * SYNOPSIS * * #include "glpios.h" * int ios_best_node(glp_tree *tree); * * DESCRIPTION * * The routine ios_best_node finds an active node whose local bound is * best among other active nodes. * * It is understood that the integer optimal solution of the original * mip problem cannot be better than the best bound, so the best bound * is an lower (minimization) or upper (maximization) global bound for * the original problem. * * RETURNS * * The routine ios_best_node returns the subproblem reference number * for the best node. However, if the tree is empty, it returns zero. */ int ios_best_node(glp_tree *tree) { IOSNPD *node, *best = NULL; switch (tree->mip->dir) { case GLP_MIN: /* minimization */ for (node = tree->head; node != NULL; node = node->next) if (best == NULL || best->bound > node->bound) best = node; break; case GLP_MAX: /* maximization */ for (node = tree->head; node != NULL; node = node->next) if (best == NULL || best->bound < node->bound) best = node; break; default: xassert(tree != tree); } return best == NULL ? 0 : best->p; } /*********************************************************************** * NAME * * ios_relative_gap - compute relative mip gap * * SYNOPSIS * * #include "glpios.h" * double ios_relative_gap(glp_tree *tree); * * DESCRIPTION * * The routine ios_relative_gap computes the relative mip gap using the * formula: * * gap = |best_mip - best_bnd| / (|best_mip| + DBL_EPSILON), * * where best_mip is the best integer feasible solution found so far, * best_bnd is the best (global) bound. If no integer feasible solution * has been found yet, rel_gap is set to DBL_MAX. * * RETURNS * * The routine ios_relative_gap returns the relative mip gap. */ double ios_relative_gap(glp_tree *tree) { glp_prob *mip = tree->mip; int p; double best_mip, best_bnd, gap; if (mip->mip_stat == GLP_FEAS) { best_mip = mip->mip_obj; p = ios_best_node(tree); if (p == 0) { /* the tree is empty */ gap = 0.0; } else { best_bnd = tree->slot[p].node->bound; gap = fabs(best_mip - best_bnd) / (fabs(best_mip) + DBL_EPSILON); } } else { /* no integer feasible solution has been found yet */ gap = DBL_MAX; } return gap; } /*********************************************************************** * NAME * * ios_solve_node - solve LP relaxation of current subproblem * * SYNOPSIS * * #include "glpios.h" * int ios_solve_node(glp_tree *tree); * * DESCRIPTION * * The routine ios_solve_node re-optimizes LP relaxation of the current * subproblem using the dual simplex method. * * RETURNS * * The routine returns the code which is reported by glp_simplex. */ int ios_solve_node(glp_tree *tree) { glp_prob *mip = tree->mip; glp_smcp parm; int ret; /* the current subproblem must exist */ xassert(tree->curr != NULL); /* set some control parameters */ glp_init_smcp(&parm); switch (tree->parm->msg_lev) { case GLP_MSG_OFF: parm.msg_lev = GLP_MSG_OFF; break; case GLP_MSG_ERR: parm.msg_lev = GLP_MSG_ERR; break; case GLP_MSG_ON: case GLP_MSG_ALL: parm.msg_lev = GLP_MSG_ON; break; case GLP_MSG_DBG: parm.msg_lev = GLP_MSG_ALL; break; default: xassert(tree != tree); } parm.meth = GLP_DUALP; if (tree->parm->msg_lev < GLP_MSG_DBG) parm.out_dly = tree->parm->out_dly; else parm.out_dly = 0; /* if the incumbent objective value is already known, use it to prematurely terminate the dual simplex search */ if (mip->mip_stat == GLP_FEAS) { switch (tree->mip->dir) { case GLP_MIN: parm.obj_ul = mip->mip_obj; break; case GLP_MAX: parm.obj_ll = mip->mip_obj; break; default: xassert(mip != mip); } } /* try to solve/re-optimize the LP relaxation */ ret = glp_simplex(mip, &parm); tree->curr->solved++; #if 0 xprintf("ret = %d; status = %d; pbs = %d; dbs = %d; some = %d\n", ret, glp_get_status(mip), mip->pbs_stat, mip->dbs_stat, mip->some); lpx_print_sol(mip, "sol"); #endif return ret; } /**********************************************************************/ IOSPOOL *ios_create_pool(glp_tree *tree) { /* create cut pool */ IOSPOOL *pool; #if 0 pool = dmp_get_atom(tree->pool, sizeof(IOSPOOL)); #else xassert(tree == tree); pool = xmalloc(sizeof(IOSPOOL)); #endif pool->size = 0; pool->head = pool->tail = NULL; pool->ord = 0, pool->curr = NULL; return pool; } int ios_add_row(glp_tree *tree, IOSPOOL *pool, const char *name, int klass, int flags, int len, const int ind[], const double val[], int type, double rhs) { /* add row (constraint) to the cut pool */ IOSCUT *cut; IOSAIJ *aij; int k; xassert(pool != NULL); cut = dmp_get_atom(tree->pool, sizeof(IOSCUT)); if (name == NULL || name[0] == '\0') cut->name = NULL; else { for (k = 0; name[k] != '\0'; k++) { if (k == 256) xerror("glp_ios_add_row: cut name too long\n"); if (iscntrl((unsigned char)name[k])) xerror("glp_ios_add_row: cut name contains invalid chara" "cter(s)\n"); } cut->name = dmp_get_atom(tree->pool, strlen(name)+1); strcpy(cut->name, name); } if (!(0 <= klass && klass <= 255)) xerror("glp_ios_add_row: klass = %d; invalid cut class\n", klass); cut->klass = (unsigned char)klass; if (flags != 0) xerror("glp_ios_add_row: flags = %d; invalid cut flags\n", flags); cut->ptr = NULL; if (!(0 <= len && len <= tree->n)) xerror("glp_ios_add_row: len = %d; invalid cut length\n", len); for (k = 1; k <= len; k++) { aij = dmp_get_atom(tree->pool, sizeof(IOSAIJ)); if (!(1 <= ind[k] && ind[k] <= tree->n)) xerror("glp_ios_add_row: ind[%d] = %d; column index out of " "range\n", k, ind[k]); aij->j = ind[k]; aij->val = val[k]; aij->next = cut->ptr; cut->ptr = aij; } if (!(type == GLP_LO || type == GLP_UP || type == GLP_FX)) xerror("glp_ios_add_row: type = %d; invalid cut type\n", type); cut->type = (unsigned char)type; cut->rhs = rhs; cut->prev = pool->tail; cut->next = NULL; if (cut->prev == NULL) pool->head = cut; else cut->prev->next = cut; pool->tail = cut; pool->size++; return pool->size; } IOSCUT *ios_find_row(IOSPOOL *pool, int i) { /* find row (constraint) in the cut pool */ /* (smart linear search) */ xassert(pool != NULL); xassert(1 <= i && i <= pool->size); if (pool->ord == 0) { xassert(pool->curr == NULL); pool->ord = 1; pool->curr = pool->head; } xassert(pool->curr != NULL); if (i < pool->ord) { if (i < pool->ord - i) { pool->ord = 1; pool->curr = pool->head; while (pool->ord != i) { pool->ord++; xassert(pool->curr != NULL); pool->curr = pool->curr->next; } } else { while (pool->ord != i) { pool->ord--; xassert(pool->curr != NULL); pool->curr = pool->curr->prev; } } } else if (i > pool->ord) { if (i - pool->ord < pool->size - i) { while (pool->ord != i) { pool->ord++; xassert(pool->curr != NULL); pool->curr = pool->curr->next; } } else { pool->ord = pool->size; pool->curr = pool->tail; while (pool->ord != i) { pool->ord--; xassert(pool->curr != NULL); pool->curr = pool->curr->prev; } } } xassert(pool->ord == i); xassert(pool->curr != NULL); return pool->curr; } void ios_del_row(glp_tree *tree, IOSPOOL *pool, int i) { /* remove row (constraint) from the cut pool */ IOSCUT *cut; IOSAIJ *aij; xassert(pool != NULL); if (!(1 <= i && i <= pool->size)) xerror("glp_ios_del_row: i = %d; cut number out of range\n", i); cut = ios_find_row(pool, i); xassert(pool->curr == cut); if (cut->next != NULL) pool->curr = cut->next; else if (cut->prev != NULL) pool->ord--, pool->curr = cut->prev; else pool->ord = 0, pool->curr = NULL; if (cut->name != NULL) dmp_free_atom(tree->pool, cut->name, strlen(cut->name)+1); if (cut->prev == NULL) { xassert(pool->head == cut); pool->head = cut->next; } else { xassert(cut->prev->next == cut); cut->prev->next = cut->next; } if (cut->next == NULL) { xassert(pool->tail == cut); pool->tail = cut->prev; } else { xassert(cut->next->prev == cut); cut->next->prev = cut->prev; } while (cut->ptr != NULL) { aij = cut->ptr; cut->ptr = aij->next; dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ)); } dmp_free_atom(tree->pool, cut, sizeof(IOSCUT)); pool->size--; return; } void ios_clear_pool(glp_tree *tree, IOSPOOL *pool) { /* remove all rows (constraints) from the cut pool */ xassert(pool != NULL); while (pool->head != NULL) { IOSCUT *cut = pool->head; pool->head = cut->next; if (cut->name != NULL) dmp_free_atom(tree->pool, cut->name, strlen(cut->name)+1); while (cut->ptr != NULL) { IOSAIJ *aij = cut->ptr; cut->ptr = aij->next; dmp_free_atom(tree->pool, aij, sizeof(IOSAIJ)); } dmp_free_atom(tree->pool, cut, sizeof(IOSCUT)); } pool->size = 0; pool->head = pool->tail = NULL; pool->ord = 0, pool->curr = NULL; return; } void ios_delete_pool(glp_tree *tree, IOSPOOL *pool) { /* delete cut pool */ xassert(pool != NULL); ios_clear_pool(tree, pool); xfree(pool); return; } #if 1 /* 11/VII-2013 */ #include "glpnpp.h" void ios_process_sol(glp_tree *T) { /* process integer feasible solution just found */ if (T->npp != NULL) { /* postprocess solution from transformed mip */ npp_postprocess(T->npp, T->mip); /* store solution to problem passed to glp_intopt */ npp_unload_sol(T->npp, T->P); } xassert(T->P != NULL); /* save solution to text file, if requested */ if (T->save_sol != NULL) { char *fn, *mark; fn = talloc(strlen(T->save_sol) + 50, char); mark = strrchr(T->save_sol, '*'); if (mark == NULL) strcpy(fn, T->save_sol); else { memcpy(fn, T->save_sol, mark - T->save_sol); fn[mark - T->save_sol] = '\0'; sprintf(fn + strlen(fn), "%03d", ++(T->save_cnt)); strcat(fn, &mark[1]); } glp_write_mip(T->P, fn); tfree(fn); } return; } #endif /* eof */ glpk-4.52.1/src/glpios02.c0000644000062000006210000006453312175147600014326 0ustar maomkpasswd/* glpios02.c (preprocess current subproblem) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * prepare_row_info - prepare row info to determine implied bounds * * Given a row (linear form) * * n * sum a[j] * x[j] (1) * j=1 * * and bounds of columns (variables) * * l[j] <= x[j] <= u[j] (2) * * this routine computes f_min, j_min, f_max, j_max needed to determine * implied bounds. * * ALGORITHM * * Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}. * * Parameters f_min and j_min are computed as follows: * * 1) if there is no x[k] such that k in J+ and l[k] = -inf or k in J- * and u[k] = +inf, then * * f_min := sum a[j] * l[j] + sum a[j] * u[j] * j in J+ j in J- * (3) * j_min := 0 * * 2) if there is exactly one x[k] such that k in J+ and l[k] = -inf * or k in J- and u[k] = +inf, then * * f_min := sum a[j] * l[j] + sum a[j] * u[j] * j in J+\{k} j in J-\{k} * (4) * j_min := k * * 3) if there are two or more x[k] such that k in J+ and l[k] = -inf * or k in J- and u[k] = +inf, then * * f_min := -inf * (5) * j_min := 0 * * Parameters f_max and j_max are computed in a similar way as follows: * * 1) if there is no x[k] such that k in J+ and u[k] = +inf or k in J- * and l[k] = -inf, then * * f_max := sum a[j] * u[j] + sum a[j] * l[j] * j in J+ j in J- * (6) * j_max := 0 * * 2) if there is exactly one x[k] such that k in J+ and u[k] = +inf * or k in J- and l[k] = -inf, then * * f_max := sum a[j] * u[j] + sum a[j] * l[j] * j in J+\{k} j in J-\{k} * (7) * j_max := k * * 3) if there are two or more x[k] such that k in J+ and u[k] = +inf * or k in J- and l[k] = -inf, then * * f_max := +inf * (8) * j_max := 0 */ struct f_info { int j_min, j_max; double f_min, f_max; }; static void prepare_row_info(int n, const double a[], const double l[], const double u[], struct f_info *f) { int j, j_min, j_max; double f_min, f_max; xassert(n >= 0); /* determine f_min and j_min */ f_min = 0.0, j_min = 0; for (j = 1; j <= n; j++) { if (a[j] > 0.0) { if (l[j] == -DBL_MAX) { if (j_min == 0) j_min = j; else { f_min = -DBL_MAX, j_min = 0; break; } } else f_min += a[j] * l[j]; } else if (a[j] < 0.0) { if (u[j] == +DBL_MAX) { if (j_min == 0) j_min = j; else { f_min = -DBL_MAX, j_min = 0; break; } } else f_min += a[j] * u[j]; } else xassert(a != a); } f->f_min = f_min, f->j_min = j_min; /* determine f_max and j_max */ f_max = 0.0, j_max = 0; for (j = 1; j <= n; j++) { if (a[j] > 0.0) { if (u[j] == +DBL_MAX) { if (j_max == 0) j_max = j; else { f_max = +DBL_MAX, j_max = 0; break; } } else f_max += a[j] * u[j]; } else if (a[j] < 0.0) { if (l[j] == -DBL_MAX) { if (j_max == 0) j_max = j; else { f_max = +DBL_MAX, j_max = 0; break; } } else f_max += a[j] * l[j]; } else xassert(a != a); } f->f_max = f_max, f->j_max = j_max; return; } /*********************************************************************** * row_implied_bounds - determine row implied bounds * * Given a row (linear form) * * n * sum a[j] * x[j] * j=1 * * and bounds of columns (variables) * * l[j] <= x[j] <= u[j] * * this routine determines implied bounds of the row. * * ALGORITHM * * Let J+ = {j : a[j] > 0} and J- = {j : a[j] < 0}. * * The implied lower bound of the row is computed as follows: * * L' := sum a[j] * l[j] + sum a[j] * u[j] (9) * j in J+ j in J- * * and as it follows from (3), (4), and (5): * * L' := if j_min = 0 then f_min else -inf (10) * * The implied upper bound of the row is computed as follows: * * U' := sum a[j] * u[j] + sum a[j] * l[j] (11) * j in J+ j in J- * * and as it follows from (6), (7), and (8): * * U' := if j_max = 0 then f_max else +inf (12) * * The implied bounds are stored in locations LL and UU. */ static void row_implied_bounds(const struct f_info *f, double *LL, double *UU) { *LL = (f->j_min == 0 ? f->f_min : -DBL_MAX); *UU = (f->j_max == 0 ? f->f_max : +DBL_MAX); return; } /*********************************************************************** * col_implied_bounds - determine column implied bounds * * Given a row (constraint) * * n * L <= sum a[j] * x[j] <= U (13) * j=1 * * and bounds of columns (variables) * * l[j] <= x[j] <= u[j] * * this routine determines implied bounds of variable x[k]. * * It is assumed that if L != -inf, the lower bound of the row can be * active, and if U != +inf, the upper bound of the row can be active. * * ALGORITHM * * From (13) it follows that * * L <= sum a[j] * x[j] + a[k] * x[k] <= U * j!=k * or * * L - sum a[j] * x[j] <= a[k] * x[k] <= U - sum a[j] * x[j] * j!=k j!=k * * Thus, if the row lower bound L can be active, implied lower bound of * term a[k] * x[k] can be determined as follows: * * ilb(a[k] * x[k]) = min(L - sum a[j] * x[j]) = * j!=k * (14) * = L - max sum a[j] * x[j] * j!=k * * where, as it follows from (6), (7), and (8) * * / f_max - a[k] * u[k], j_max = 0, a[k] > 0 * | * | f_max - a[k] * l[k], j_max = 0, a[k] < 0 * max sum a[j] * x[j] = { * j!=k | f_max, j_max = k * | * \ +inf, j_max != 0 * * and if the upper bound U can be active, implied upper bound of term * a[k] * x[k] can be determined as follows: * * iub(a[k] * x[k]) = max(U - sum a[j] * x[j]) = * j!=k * (15) * = U - min sum a[j] * x[j] * j!=k * * where, as it follows from (3), (4), and (5) * * / f_min - a[k] * l[k], j_min = 0, a[k] > 0 * | * | f_min - a[k] * u[k], j_min = 0, a[k] < 0 * min sum a[j] * x[j] = { * j!=k | f_min, j_min = k * | * \ -inf, j_min != 0 * * Since * * ilb(a[k] * x[k]) <= a[k] * x[k] <= iub(a[k] * x[k]) * * implied lower and upper bounds of x[k] are determined as follows: * * l'[k] := if a[k] > 0 then ilb / a[k] else ulb / a[k] (16) * * u'[k] := if a[k] > 0 then ulb / a[k] else ilb / a[k] (17) * * The implied bounds are stored in locations ll and uu. */ static void col_implied_bounds(const struct f_info *f, int n, const double a[], double L, double U, const double l[], const double u[], int k, double *ll, double *uu) { double ilb, iub; xassert(n >= 0); xassert(1 <= k && k <= n); /* determine implied lower bound of term a[k] * x[k] (14) */ if (L == -DBL_MAX || f->f_max == +DBL_MAX) ilb = -DBL_MAX; else if (f->j_max == 0) { if (a[k] > 0.0) { xassert(u[k] != +DBL_MAX); ilb = L - (f->f_max - a[k] * u[k]); } else if (a[k] < 0.0) { xassert(l[k] != -DBL_MAX); ilb = L - (f->f_max - a[k] * l[k]); } else xassert(a != a); } else if (f->j_max == k) ilb = L - f->f_max; else ilb = -DBL_MAX; /* determine implied upper bound of term a[k] * x[k] (15) */ if (U == +DBL_MAX || f->f_min == -DBL_MAX) iub = +DBL_MAX; else if (f->j_min == 0) { if (a[k] > 0.0) { xassert(l[k] != -DBL_MAX); iub = U - (f->f_min - a[k] * l[k]); } else if (a[k] < 0.0) { xassert(u[k] != +DBL_MAX); iub = U - (f->f_min - a[k] * u[k]); } else xassert(a != a); } else if (f->j_min == k) iub = U - f->f_min; else iub = +DBL_MAX; /* determine implied bounds of x[k] (16) and (17) */ #if 1 /* do not use a[k] if it has small magnitude to prevent wrong implied bounds; for example, 1e-15 * x1 >= x2 + x3, where x1 >= -10, x2, x3 >= 0, would lead to wrong conclusion that x1 >= 0 */ if (fabs(a[k]) < 1e-6) *ll = -DBL_MAX, *uu = +DBL_MAX; else #endif if (a[k] > 0.0) { *ll = (ilb == -DBL_MAX ? -DBL_MAX : ilb / a[k]); *uu = (iub == +DBL_MAX ? +DBL_MAX : iub / a[k]); } else if (a[k] < 0.0) { *ll = (iub == +DBL_MAX ? -DBL_MAX : iub / a[k]); *uu = (ilb == -DBL_MAX ? +DBL_MAX : ilb / a[k]); } else xassert(a != a); return; } /*********************************************************************** * check_row_bounds - check and relax original row bounds * * Given a row (constraint) * * n * L <= sum a[j] * x[j] <= U * j=1 * * and bounds of columns (variables) * * l[j] <= x[j] <= u[j] * * this routine checks the original row bounds L and U for feasibility * and redundancy. If the original lower bound L or/and upper bound U * cannot be active due to bounds of variables, the routine remove them * replacing by -inf or/and +inf, respectively. * * If no primal infeasibility is detected, the routine returns zero, * otherwise non-zero. */ static int check_row_bounds(const struct f_info *f, double *L_, double *U_) { int ret = 0; double L = *L_, U = *U_, LL, UU; /* determine implied bounds of the row */ row_implied_bounds(f, &LL, &UU); /* check if the original lower bound is infeasible */ if (L != -DBL_MAX) { double eps = 1e-3 * (1.0 + fabs(L)); if (UU < L - eps) { ret = 1; goto done; } } /* check if the original upper bound is infeasible */ if (U != +DBL_MAX) { double eps = 1e-3 * (1.0 + fabs(U)); if (LL > U + eps) { ret = 1; goto done; } } /* check if the original lower bound is redundant */ if (L != -DBL_MAX) { double eps = 1e-12 * (1.0 + fabs(L)); if (LL > L - eps) { /* it cannot be active, so remove it */ *L_ = -DBL_MAX; } } /* check if the original upper bound is redundant */ if (U != +DBL_MAX) { double eps = 1e-12 * (1.0 + fabs(U)); if (UU < U + eps) { /* it cannot be active, so remove it */ *U_ = +DBL_MAX; } } done: return ret; } /*********************************************************************** * check_col_bounds - check and tighten original column bounds * * Given a row (constraint) * * n * L <= sum a[j] * x[j] <= U * j=1 * * and bounds of columns (variables) * * l[j] <= x[j] <= u[j] * * for column (variable) x[j] this routine checks the original column * bounds l[j] and u[j] for feasibility and redundancy. If the original * lower bound l[j] or/and upper bound u[j] cannot be active due to * bounds of the constraint and other variables, the routine tighten * them replacing by corresponding implied bounds, if possible. * * NOTE: It is assumed that if L != -inf, the row lower bound can be * active, and if U != +inf, the row upper bound can be active. * * The flag means that variable x[j] is required to be integer. * * New actual bounds for x[j] are stored in locations lj and uj. * * If no primal infeasibility is detected, the routine returns zero, * otherwise non-zero. */ static int check_col_bounds(const struct f_info *f, int n, const double a[], double L, double U, const double l[], const double u[], int flag, int j, double *_lj, double *_uj) { int ret = 0; double lj, uj, ll, uu; xassert(n >= 0); xassert(1 <= j && j <= n); lj = l[j], uj = u[j]; /* determine implied bounds of the column */ col_implied_bounds(f, n, a, L, U, l, u, j, &ll, &uu); /* if x[j] is integral, round its implied bounds */ if (flag) { if (ll != -DBL_MAX) ll = (ll - floor(ll) < 1e-3 ? floor(ll) : ceil(ll)); if (uu != +DBL_MAX) uu = (ceil(uu) - uu < 1e-3 ? ceil(uu) : floor(uu)); } /* check if the original lower bound is infeasible */ if (lj != -DBL_MAX) { double eps = 1e-3 * (1.0 + fabs(lj)); if (uu < lj - eps) { ret = 1; goto done; } } /* check if the original upper bound is infeasible */ if (uj != +DBL_MAX) { double eps = 1e-3 * (1.0 + fabs(uj)); if (ll > uj + eps) { ret = 1; goto done; } } /* check if the original lower bound is redundant */ if (ll != -DBL_MAX) { double eps = 1e-3 * (1.0 + fabs(ll)); if (lj < ll - eps) { /* it cannot be active, so tighten it */ lj = ll; } } /* check if the original upper bound is redundant */ if (uu != +DBL_MAX) { double eps = 1e-3 * (1.0 + fabs(uu)); if (uj > uu + eps) { /* it cannot be active, so tighten it */ uj = uu; } } /* due to round-off errors it may happen that lj > uj (although lj < uj + eps, since no primal infeasibility is detected), so adjuct the new actual bounds to provide lj <= uj */ if (!(lj == -DBL_MAX || uj == +DBL_MAX)) { double t1 = fabs(lj), t2 = fabs(uj); double eps = 1e-10 * (1.0 + (t1 <= t2 ? t1 : t2)); if (lj > uj - eps) { if (lj == l[j]) uj = lj; else if (uj == u[j]) lj = uj; else if (t1 <= t2) uj = lj; else lj = uj; } } *_lj = lj, *_uj = uj; done: return ret; } /*********************************************************************** * check_efficiency - check if change in column bounds is efficient * * Given the original bounds of a column l and u and its new actual * bounds l' and u' (possibly tighten by the routine check_col_bounds) * this routine checks if the change in the column bounds is efficient * enough. If so, the routine returns non-zero, otherwise zero. * * The flag means that the variable is required to be integer. */ static int check_efficiency(int flag, double l, double u, double ll, double uu) { int eff = 0; /* check efficiency for lower bound */ if (l < ll) { if (flag || l == -DBL_MAX) eff++; else { double r; if (u == +DBL_MAX) r = 1.0 + fabs(l); else r = 1.0 + (u - l); if (ll - l >= 0.25 * r) eff++; } } /* check efficiency for upper bound */ if (u > uu) { if (flag || u == +DBL_MAX) eff++; else { double r; if (l == -DBL_MAX) r = 1.0 + fabs(u); else r = 1.0 + (u - l); if (u - uu >= 0.25 * r) eff++; } } return eff; } /*********************************************************************** * basic_preprocessing - perform basic preprocessing * * This routine performs basic preprocessing of the specified MIP that * includes relaxing some row bounds and tightening some column bounds. * * On entry the arrays L and U contains original row bounds, and the * arrays l and u contains original column bounds: * * L[0] is the lower bound of the objective row; * L[i], i = 1,...,m, is the lower bound of i-th row; * U[0] is the upper bound of the objective row; * U[i], i = 1,...,m, is the upper bound of i-th row; * l[0] is not used; * l[j], j = 1,...,n, is the lower bound of j-th column; * u[0] is not used; * u[j], j = 1,...,n, is the upper bound of j-th column. * * On exit the arrays L, U, l, and u contain new actual bounds of rows * and column in the same locations. * * The parameters nrs and num specify an initial list of rows to be * processed: * * nrs is the number of rows in the initial list, 0 <= nrs <= m+1; * num[0] is not used; * num[1,...,nrs] are row numbers (0 means the objective row). * * The parameter max_pass specifies the maximal number of times that * each row can be processed, max_pass > 0. * * If no primal infeasibility is detected, the routine returns zero, * otherwise non-zero. */ static int basic_preprocessing(glp_prob *mip, double L[], double U[], double l[], double u[], int nrs, const int num[], int max_pass) { int m = mip->m; int n = mip->n; struct f_info f; int i, j, k, len, size, ret = 0; int *ind, *list, *mark, *pass; double *val, *lb, *ub; xassert(0 <= nrs && nrs <= m+1); xassert(max_pass > 0); /* allocate working arrays */ ind = xcalloc(1+n, sizeof(int)); list = xcalloc(1+m+1, sizeof(int)); mark = xcalloc(1+m+1, sizeof(int)); memset(&mark[0], 0, (m+1) * sizeof(int)); pass = xcalloc(1+m+1, sizeof(int)); memset(&pass[0], 0, (m+1) * sizeof(int)); val = xcalloc(1+n, sizeof(double)); lb = xcalloc(1+n, sizeof(double)); ub = xcalloc(1+n, sizeof(double)); /* initialize the list of rows to be processed */ size = 0; for (k = 1; k <= nrs; k++) { i = num[k]; xassert(0 <= i && i <= m); /* duplicate row numbers are not allowed */ xassert(!mark[i]); list[++size] = i, mark[i] = 1; } xassert(size == nrs); /* process rows in the list until it becomes empty */ while (size > 0) { /* get a next row from the list */ i = list[size--], mark[i] = 0; /* increase the row processing count */ pass[i]++; /* if the row is free, skip it */ if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue; /* obtain coefficients of the row */ len = 0; if (i == 0) { for (j = 1; j <= n; j++) { GLPCOL *col = mip->col[j]; if (col->coef != 0.0) len++, ind[len] = j, val[len] = col->coef; } } else { GLPROW *row = mip->row[i]; GLPAIJ *aij; for (aij = row->ptr; aij != NULL; aij = aij->r_next) len++, ind[len] = aij->col->j, val[len] = aij->val; } /* determine lower and upper bounds of columns corresponding to non-zero row coefficients */ for (k = 1; k <= len; k++) j = ind[k], lb[k] = l[j], ub[k] = u[j]; /* prepare the row info to determine implied bounds */ prepare_row_info(len, val, lb, ub, &f); /* check and relax bounds of the row */ if (check_row_bounds(&f, &L[i], &U[i])) { /* the feasible region is empty */ ret = 1; goto done; } /* if the row became free, drop it */ if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) continue; /* process columns having non-zero coefficients in the row */ for (k = 1; k <= len; k++) { GLPCOL *col; int flag, eff; double ll, uu; /* take a next column in the row */ j = ind[k], col = mip->col[j]; flag = col->kind != GLP_CV; /* check and tighten bounds of the column */ if (check_col_bounds(&f, len, val, L[i], U[i], lb, ub, flag, k, &ll, &uu)) { /* the feasible region is empty */ ret = 1; goto done; } /* check if change in the column bounds is efficient */ eff = check_efficiency(flag, l[j], u[j], ll, uu); /* set new actual bounds of the column */ l[j] = ll, u[j] = uu; /* if the change is efficient, add all rows affected by the corresponding column, to the list */ if (eff > 0) { GLPAIJ *aij; for (aij = col->ptr; aij != NULL; aij = aij->c_next) { int ii = aij->row->i; /* if the row was processed maximal number of times, skip it */ if (pass[ii] >= max_pass) continue; /* if the row is free, skip it */ if (L[ii] == -DBL_MAX && U[ii] == +DBL_MAX) continue; /* put the row into the list */ if (mark[ii] == 0) { xassert(size <= m); list[++size] = ii, mark[ii] = 1; } } } } } done: /* free working arrays */ xfree(ind); xfree(list); xfree(mark); xfree(pass); xfree(val); xfree(lb); xfree(ub); return ret; } /*********************************************************************** * NAME * * ios_preprocess_node - preprocess current subproblem * * SYNOPSIS * * #include "glpios.h" * int ios_preprocess_node(glp_tree *tree, int max_pass); * * DESCRIPTION * * The routine ios_preprocess_node performs basic preprocessing of the * current subproblem. * * RETURNS * * If no primal infeasibility is detected, the routine returns zero, * otherwise non-zero. */ int ios_preprocess_node(glp_tree *tree, int max_pass) { glp_prob *mip = tree->mip; int m = mip->m; int n = mip->n; int i, j, nrs, *num, ret = 0; double *L, *U, *l, *u; /* the current subproblem must exist */ xassert(tree->curr != NULL); /* determine original row bounds */ L = xcalloc(1+m, sizeof(double)); U = xcalloc(1+m, sizeof(double)); switch (mip->mip_stat) { case GLP_UNDEF: L[0] = -DBL_MAX, U[0] = +DBL_MAX; break; case GLP_FEAS: switch (mip->dir) { case GLP_MIN: L[0] = -DBL_MAX, U[0] = mip->mip_obj - mip->c0; break; case GLP_MAX: L[0] = mip->mip_obj - mip->c0, U[0] = +DBL_MAX; break; default: xassert(mip != mip); } break; default: xassert(mip != mip); } for (i = 1; i <= m; i++) { L[i] = glp_get_row_lb(mip, i); U[i] = glp_get_row_ub(mip, i); } /* determine original column bounds */ l = xcalloc(1+n, sizeof(double)); u = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { l[j] = glp_get_col_lb(mip, j); u[j] = glp_get_col_ub(mip, j); } /* build the initial list of rows to be analyzed */ nrs = m + 1; num = xcalloc(1+nrs, sizeof(int)); for (i = 1; i <= nrs; i++) num[i] = i - 1; /* perform basic preprocessing */ if (basic_preprocessing(mip , L, U, l, u, nrs, num, max_pass)) { ret = 1; goto done; } /* set new actual (relaxed) row bounds */ for (i = 1; i <= m; i++) { /* consider only non-active rows to keep dual feasibility */ if (glp_get_row_stat(mip, i) == GLP_BS) { if (L[i] == -DBL_MAX && U[i] == +DBL_MAX) glp_set_row_bnds(mip, i, GLP_FR, 0.0, 0.0); else if (U[i] == +DBL_MAX) glp_set_row_bnds(mip, i, GLP_LO, L[i], 0.0); else if (L[i] == -DBL_MAX) glp_set_row_bnds(mip, i, GLP_UP, 0.0, U[i]); } } /* set new actual (tightened) column bounds */ for (j = 1; j <= n; j++) { int type; if (l[j] == -DBL_MAX && u[j] == +DBL_MAX) type = GLP_FR; else if (u[j] == +DBL_MAX) type = GLP_LO; else if (l[j] == -DBL_MAX) type = GLP_UP; else if (l[j] != u[j]) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(mip, j, type, l[j], u[j]); } done: /* free working arrays and return */ xfree(L); xfree(U); xfree(l); xfree(u); xfree(num); return ret; } /* eof */ glpk-4.52.1/src/glpios03.c0000644000062000006210000014401212175147600014316 0ustar maomkpasswd/* glpios03.c (branch-and-cut driver) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * show_progress - display current progress of the search * * This routine displays some information about current progress of the * search. * * The information includes: * * the current number of iterations performed by the simplex solver; * * the objective value for the best known integer feasible solution, * which is upper (minimization) or lower (maximization) global bound * for optimal solution of the original mip problem; * * the best local bound for active nodes, which is lower (minimization) * or upper (maximization) global bound for optimal solution of the * original mip problem; * * the relative mip gap, in percents; * * the number of open (active) subproblems; * * the number of completely explored subproblems, i.e. whose nodes have * been removed from the tree. */ static void show_progress(glp_tree *T, int bingo) { int p; double temp; char best_mip[50], best_bound[50], *rho, rel_gap[50]; /* format the best known integer feasible solution */ if (T->mip->mip_stat == GLP_FEAS) sprintf(best_mip, "%17.9e", T->mip->mip_obj); else sprintf(best_mip, "%17s", "not found yet"); /* determine reference number of an active subproblem whose local bound is best */ p = ios_best_node(T); /* format the best bound */ if (p == 0) sprintf(best_bound, "%17s", "tree is empty"); else { temp = T->slot[p].node->bound; if (temp == -DBL_MAX) sprintf(best_bound, "%17s", "-inf"); else if (temp == +DBL_MAX) sprintf(best_bound, "%17s", "+inf"); else sprintf(best_bound, "%17.9e", temp); } /* choose the relation sign between global bounds */ if (T->mip->dir == GLP_MIN) rho = ">="; else if (T->mip->dir == GLP_MAX) rho = "<="; else xassert(T != T); /* format the relative mip gap */ temp = ios_relative_gap(T); if (temp == 0.0) sprintf(rel_gap, " 0.0%%"); else if (temp < 0.001) sprintf(rel_gap, "< 0.1%%"); else if (temp <= 9.999) sprintf(rel_gap, "%5.1f%%", 100.0 * temp); else sprintf(rel_gap, "%6s", ""); /* display progress of the search */ xprintf("+%6d: %s %s %s %s %s (%d; %d)\n", T->mip->it_cnt, bingo ? ">>>>>" : "mip =", best_mip, rho, best_bound, rel_gap, T->a_cnt, T->t_cnt - T->n_cnt); T->tm_lag = xtime(); return; } /*********************************************************************** * is_branch_hopeful - check if specified branch is hopeful * * This routine checks if the specified subproblem can have an integer * optimal solution which is better than the best known one. * * The check is based on comparison of the local objective bound stored * in the subproblem descriptor and the incumbent objective value which * is the global objective bound. * * If there is a chance that the specified subproblem can have a better * integer optimal solution, the routine returns non-zero. Otherwise, if * the corresponding branch can pruned, zero is returned. */ static int is_branch_hopeful(glp_tree *T, int p) { xassert(1 <= p && p <= T->nslots); xassert(T->slot[p].node != NULL); return ios_is_hopeful(T, T->slot[p].node->bound); } /*********************************************************************** * check_integrality - check integrality of basic solution * * This routine checks if the basic solution of LP relaxation of the * current subproblem satisfies to integrality conditions, i.e. that all * variables of integer kind have integral primal values. (The solution * is assumed to be optimal.) * * For each variable of integer kind the routine computes the following * quantity: * * ii(x[j]) = min(x[j] - floor(x[j]), ceil(x[j]) - x[j]), (1) * * which is a measure of the integer infeasibility (non-integrality) of * x[j] (for example, ii(2.1) = 0.1, ii(3.7) = 0.3, ii(5.0) = 0). It is * understood that 0 <= ii(x[j]) <= 0.5, and variable x[j] is integer * feasible if ii(x[j]) = 0. However, due to floating-point arithmetic * the routine checks less restrictive condition: * * ii(x[j]) <= tol_int, (2) * * where tol_int is a given tolerance (small positive number) and marks * each variable which does not satisfy to (2) as integer infeasible by * setting its fractionality flag. * * In order to characterize integer infeasibility of the basic solution * in the whole the routine computes two parameters: ii_cnt, which is * the number of variables with the fractionality flag set, and ii_sum, * which is the sum of integer infeasibilities (1). */ static void check_integrality(glp_tree *T) { glp_prob *mip = T->mip; int j, type, ii_cnt = 0; double lb, ub, x, temp1, temp2, ii_sum = 0.0; /* walk through the set of columns (structural variables) */ for (j = 1; j <= mip->n; j++) { GLPCOL *col = mip->col[j]; T->non_int[j] = 0; /* if the column is not integer, skip it */ if (col->kind != GLP_IV) continue; /* if the column is non-basic, it is integer feasible */ if (col->stat != GLP_BS) continue; /* obtain the type and bounds of the column */ type = col->type, lb = col->lb, ub = col->ub; /* obtain value of the column in optimal basic solution */ x = col->prim; /* if the column's primal value is close to the lower bound, the column is integer feasible within given tolerance */ if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { temp1 = lb - T->parm->tol_int; temp2 = lb + T->parm->tol_int; if (temp1 <= x && x <= temp2) continue; #if 0 /* the lower bound must not be violated */ xassert(x >= lb); #else if (x < lb) continue; #endif } /* if the column's primal value is close to the upper bound, the column is integer feasible within given tolerance */ if (type == GLP_UP || type == GLP_DB || type == GLP_FX) { temp1 = ub - T->parm->tol_int; temp2 = ub + T->parm->tol_int; if (temp1 <= x && x <= temp2) continue; #if 0 /* the upper bound must not be violated */ xassert(x <= ub); #else if (x > ub) continue; #endif } /* if the column's primal value is close to nearest integer, the column is integer feasible within given tolerance */ temp1 = floor(x + 0.5) - T->parm->tol_int; temp2 = floor(x + 0.5) + T->parm->tol_int; if (temp1 <= x && x <= temp2) continue; /* otherwise the column is integer infeasible */ T->non_int[j] = 1; /* increase the number of fractional-valued columns */ ii_cnt++; /* compute the sum of integer infeasibilities */ temp1 = x - floor(x); temp2 = ceil(x) - x; xassert(temp1 > 0.0 && temp2 > 0.0); ii_sum += (temp1 <= temp2 ? temp1 : temp2); } /* store ii_cnt and ii_sum to the current problem descriptor */ xassert(T->curr != NULL); T->curr->ii_cnt = ii_cnt; T->curr->ii_sum = ii_sum; /* and also display these parameters */ if (T->parm->msg_lev >= GLP_MSG_DBG) { if (ii_cnt == 0) xprintf("There are no fractional columns\n"); else if (ii_cnt == 1) xprintf("There is one fractional column, integer infeasibil" "ity is %.3e\n", ii_sum); else xprintf("There are %d fractional columns, integer infeasibi" "lity is %.3e\n", ii_cnt, ii_sum); } return; } /*********************************************************************** * record_solution - record better integer feasible solution * * This routine records optimal basic solution of LP relaxation of the * current subproblem, which being integer feasible is better than the * best known integer feasible solution. */ static void record_solution(glp_tree *T) { glp_prob *mip = T->mip; int i, j; mip->mip_stat = GLP_FEAS; mip->mip_obj = mip->obj_val; for (i = 1; i <= mip->m; i++) { GLPROW *row = mip->row[i]; row->mipx = row->prim; } for (j = 1; j <= mip->n; j++) { GLPCOL *col = mip->col[j]; if (col->kind == GLP_CV) col->mipx = col->prim; else if (col->kind == GLP_IV) { /* value of the integer column must be integral */ col->mipx = floor(col->prim + 0.5); } else xassert(col != col); } T->sol_cnt++; return; } /*********************************************************************** * fix_by_red_cost - fix non-basic integer columns by reduced costs * * This routine fixes some non-basic integer columns if their reduced * costs indicate that increasing (decreasing) the column at least by * one involves the objective value becoming worse than the incumbent * objective value. */ static void fix_by_red_cost(glp_tree *T) { glp_prob *mip = T->mip; int j, stat, fixed = 0; double obj, lb, ub, dj; /* the global bound must exist */ xassert(T->mip->mip_stat == GLP_FEAS); /* basic solution of LP relaxation must be optimal */ xassert(mip->pbs_stat == GLP_FEAS && mip->dbs_stat == GLP_FEAS); /* determine the objective function value */ obj = mip->obj_val; /* walk through the column list */ for (j = 1; j <= mip->n; j++) { GLPCOL *col = mip->col[j]; /* if the column is not integer, skip it */ if (col->kind != GLP_IV) continue; /* obtain bounds of j-th column */ lb = col->lb, ub = col->ub; /* and determine its status and reduced cost */ stat = col->stat, dj = col->dual; /* analyze the reduced cost */ switch (mip->dir) { case GLP_MIN: /* minimization */ if (stat == GLP_NL) { /* j-th column is non-basic on its lower bound */ if (dj < 0.0) dj = 0.0; if (obj + dj >= mip->mip_obj) glp_set_col_bnds(mip, j, GLP_FX, lb, lb), fixed++; } else if (stat == GLP_NU) { /* j-th column is non-basic on its upper bound */ if (dj > 0.0) dj = 0.0; if (obj - dj >= mip->mip_obj) glp_set_col_bnds(mip, j, GLP_FX, ub, ub), fixed++; } break; case GLP_MAX: /* maximization */ if (stat == GLP_NL) { /* j-th column is non-basic on its lower bound */ if (dj > 0.0) dj = 0.0; if (obj + dj <= mip->mip_obj) glp_set_col_bnds(mip, j, GLP_FX, lb, lb), fixed++; } else if (stat == GLP_NU) { /* j-th column is non-basic on its upper bound */ if (dj < 0.0) dj = 0.0; if (obj - dj <= mip->mip_obj) glp_set_col_bnds(mip, j, GLP_FX, ub, ub), fixed++; } break; default: xassert(T != T); } } if (T->parm->msg_lev >= GLP_MSG_DBG) { if (fixed == 0) /* nothing to say */; else if (fixed == 1) xprintf("One column has been fixed by reduced cost\n"); else xprintf("%d columns have been fixed by reduced costs\n", fixed); } /* fixing non-basic columns on their current bounds does not change the basic solution */ xassert(mip->pbs_stat == GLP_FEAS && mip->dbs_stat == GLP_FEAS); return; } /*********************************************************************** * branch_on - perform branching on specified variable * * This routine performs branching on j-th column (structural variable) * of the current subproblem. The specified column must be of integer * kind and must have a fractional value in optimal basic solution of * LP relaxation of the current subproblem (i.e. only columns for which * the flag non_int[j] is set are valid candidates to branch on). * * Let x be j-th structural variable, and beta be its primal fractional * value in the current basic solution. Branching on j-th variable is * dividing the current subproblem into two new subproblems, which are * identical to the current subproblem with the following exception: in * the first subproblem that begins the down-branch x has a new upper * bound x <= floor(beta), and in the second subproblem that begins the * up-branch x has a new lower bound x >= ceil(beta). * * Depending on estimation of local bounds for down- and up-branches * this routine returns the following: * * 0 - both branches have been created; * 1 - one branch is hopeless and has been pruned, so now the current * subproblem is other branch; * 2 - both branches are hopeless and have been pruned; new subproblem * selection is needed to continue the search. */ static int branch_on(glp_tree *T, int j, int next) { glp_prob *mip = T->mip; IOSNPD *node; int m = mip->m; int n = mip->n; int type, dn_type, up_type, dn_bad, up_bad, p, ret, clone[1+2]; double lb, ub, beta, new_ub, new_lb, dn_lp, up_lp, dn_bnd, up_bnd; /* determine bounds and value of x[j] in optimal solution to LP relaxation of the current subproblem */ xassert(1 <= j && j <= n); type = mip->col[j]->type; lb = mip->col[j]->lb; ub = mip->col[j]->ub; beta = mip->col[j]->prim; /* determine new bounds of x[j] for down- and up-branches */ new_ub = floor(beta); new_lb = ceil(beta); switch (type) { case GLP_FR: dn_type = GLP_UP; up_type = GLP_LO; break; case GLP_LO: xassert(lb <= new_ub); dn_type = (lb == new_ub ? GLP_FX : GLP_DB); xassert(lb + 1.0 <= new_lb); up_type = GLP_LO; break; case GLP_UP: xassert(new_ub <= ub - 1.0); dn_type = GLP_UP; xassert(new_lb <= ub); up_type = (new_lb == ub ? GLP_FX : GLP_DB); break; case GLP_DB: xassert(lb <= new_ub && new_ub <= ub - 1.0); dn_type = (lb == new_ub ? GLP_FX : GLP_DB); xassert(lb + 1.0 <= new_lb && new_lb <= ub); up_type = (new_lb == ub ? GLP_FX : GLP_DB); break; default: xassert(type != type); } /* compute local bounds to LP relaxation for both branches */ ios_eval_degrad(T, j, &dn_lp, &up_lp); /* and improve them by rounding */ dn_bnd = ios_round_bound(T, dn_lp); up_bnd = ios_round_bound(T, up_lp); /* check local bounds for down- and up-branches */ dn_bad = !ios_is_hopeful(T, dn_bnd); up_bad = !ios_is_hopeful(T, up_bnd); if (dn_bad && up_bad) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Both down- and up-branches are hopeless\n"); ret = 2; goto done; } else if (up_bad) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Up-branch is hopeless\n"); glp_set_col_bnds(mip, j, dn_type, lb, new_ub); T->curr->lp_obj = dn_lp; if (mip->dir == GLP_MIN) { if (T->curr->bound < dn_bnd) T->curr->bound = dn_bnd; } else if (mip->dir == GLP_MAX) { if (T->curr->bound > dn_bnd) T->curr->bound = dn_bnd; } else xassert(mip != mip); ret = 1; goto done; } else if (dn_bad) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Down-branch is hopeless\n"); glp_set_col_bnds(mip, j, up_type, new_lb, ub); T->curr->lp_obj = up_lp; if (mip->dir == GLP_MIN) { if (T->curr->bound < up_bnd) T->curr->bound = up_bnd; } else if (mip->dir == GLP_MAX) { if (T->curr->bound > up_bnd) T->curr->bound = up_bnd; } else xassert(mip != mip); ret = 1; goto done; } /* both down- and up-branches seem to be hopeful */ if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Branching on column %d, primal value is %.9e\n", j, beta); /* determine the reference number of the current subproblem */ xassert(T->curr != NULL); p = T->curr->p; T->curr->br_var = j; T->curr->br_val = beta; /* freeze the current subproblem */ ios_freeze_node(T); /* create two clones of the current subproblem; the first clone begins the down-branch, the second one begins the up-branch */ ios_clone_node(T, p, 2, clone); if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Node %d begins down branch, node %d begins up branch " "\n", clone[1], clone[2]); /* set new upper bound of j-th column in the down-branch */ node = T->slot[clone[1]].node; xassert(node != NULL); xassert(node->up != NULL); xassert(node->b_ptr == NULL); node->b_ptr = dmp_get_atom(T->pool, sizeof(IOSBND)); node->b_ptr->k = m + j; node->b_ptr->type = (unsigned char)dn_type; node->b_ptr->lb = lb; node->b_ptr->ub = new_ub; node->b_ptr->next = NULL; node->lp_obj = dn_lp; if (mip->dir == GLP_MIN) { if (node->bound < dn_bnd) node->bound = dn_bnd; } else if (mip->dir == GLP_MAX) { if (node->bound > dn_bnd) node->bound = dn_bnd; } else xassert(mip != mip); /* set new lower bound of j-th column in the up-branch */ node = T->slot[clone[2]].node; xassert(node != NULL); xassert(node->up != NULL); xassert(node->b_ptr == NULL); node->b_ptr = dmp_get_atom(T->pool, sizeof(IOSBND)); node->b_ptr->k = m + j; node->b_ptr->type = (unsigned char)up_type; node->b_ptr->lb = new_lb; node->b_ptr->ub = ub; node->b_ptr->next = NULL; node->lp_obj = up_lp; if (mip->dir == GLP_MIN) { if (node->bound < up_bnd) node->bound = up_bnd; } else if (mip->dir == GLP_MAX) { if (node->bound > up_bnd) node->bound = up_bnd; } else xassert(mip != mip); /* suggest the subproblem to be solved next */ xassert(T->child == 0); if (next == GLP_NO_BRNCH) T->child = 0; else if (next == GLP_DN_BRNCH) T->child = clone[1]; else if (next == GLP_UP_BRNCH) T->child = clone[2]; else xassert(next != next); ret = 0; done: return ret; } /*********************************************************************** * cleanup_the_tree - prune hopeless branches from the tree * * This routine walks through the active list and checks the local * bound for every active subproblem. If the local bound indicates that * the subproblem cannot have integer optimal solution better than the * incumbent objective value, the routine deletes such subproblem that, * in turn, involves pruning the corresponding branch of the tree. */ static void cleanup_the_tree(glp_tree *T) { IOSNPD *node, *next_node; int count = 0; /* the global bound must exist */ xassert(T->mip->mip_stat == GLP_FEAS); /* walk through the list of active subproblems */ for (node = T->head; node != NULL; node = next_node) { /* deleting some active problem node may involve deleting its parents recursively; however, all its parents being created *before* it are always *precede* it in the node list, so the next problem node is never affected by such deletion */ next_node = node->next; /* if the branch is hopeless, prune it */ if (!is_branch_hopeful(T, node->p)) ios_delete_node(T, node->p), count++; } if (T->parm->msg_lev >= GLP_MSG_DBG) { if (count == 1) xprintf("One hopeless branch has been pruned\n"); else if (count > 1) xprintf("%d hopeless branches have been pruned\n", count); } return; } #if 0 /* 09/VII-2013 */ /*********************************************************************** * round_heur - simple rounding heuristic * * This routine attempts to guess an integer feasible solution by * simple rounding values of all integer variables in basic solution to * nearest integers. */ static int round_heur(glp_tree *T) { glp_prob *P = T->mip; int m = P->m; int n = P->n; int i, j, ret; double *x; /* compute rounded values of variables */ x = talloc(1+n, double); for (j = 1; j <= n; j++) { GLPCOL *col = P->col[j]; if (col->kind == GLP_IV) { /* integer variable */ x[j] = floor(col->prim + 0.5); } else if (col->type == GLP_FX) { /* fixed variable */ x[j] = col->prim; } else { /* non-integer non-fixed variable */ ret = 3; goto done; } } /* check that no constraints are violated */ for (i = 1; i <= m; i++) { GLPROW *row = P->row[i]; int type = row->type; GLPAIJ *aij; double sum; if (type == GLP_FR) continue; /* compute value of linear form */ sum = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) sum += aij->val * x[aij->col->j]; /* check lower bound */ if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { if (sum < row->lb - 1e-9) { /* lower bound is violated */ ret = 2; goto done; } } /* check upper bound */ if (type == GLP_UP || type == GLP_DB || type == GLP_FX) { if (sum > row->ub + 1e-9) { /* upper bound is violated */ ret = 2; goto done; } } } /* rounded solution is integer feasible */ if (glp_ios_heur_sol(T, x) == 0) { /* solution is accepted */ ret = 0; } else { /* solution is rejected */ ret = 1; } done: tfree(x); return ret; } #else /*********************************************************************** * round_heur - simple rounding heuristic * * This routine attempts to guess an integer feasible solution by * simple rounding values of all integer variables in basic solution to * nearest integers. */ static int round_heur(glp_tree *T) { glp_prob *P = T->mip; /*int m = P->m;*/ int n = P->n; int i, j, ret; double *x; /* compute rounded values of variables */ x = talloc(1+n, double); for (j = 1; j <= n; j++) { GLPCOL *col = P->col[j]; if (col->kind == GLP_IV) { /* integer variable */ x[j] = floor(col->prim + 0.5); } else if (col->type == GLP_FX) { /* fixed variable */ x[j] = col->prim; } else { /* non-integer non-fixed variable */ ret = 3; goto done; } } /* check that no constraints are violated */ for (i = 1; i <= T->orig_m; i++) { int type = T->orig_type[i]; GLPAIJ *aij; double sum; if (type == GLP_FR) continue; /* compute value of linear form */ sum = 0.0; for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next) sum += aij->val * x[aij->col->j]; /* check lower bound */ if (type == GLP_LO || type == GLP_DB || type == GLP_FX) { if (sum < T->orig_lb[i] - 1e-9) { /* lower bound is violated */ ret = 2; goto done; } } /* check upper bound */ if (type == GLP_UP || type == GLP_DB || type == GLP_FX) { if (sum > T->orig_ub[i] + 1e-9) { /* upper bound is violated */ ret = 2; goto done; } } } /* rounded solution is integer feasible */ if (glp_ios_heur_sol(T, x) == 0) { /* solution is accepted */ ret = 0; } else { /* solution is rejected */ ret = 1; } done: tfree(x); return ret; } #endif #if 0 #define round_heur round_heur2 static int round_heur(glp_tree *T) { glp_prob *lp; int *ind, ret, i, j, len; double *val; lp = glp_create_prob(); ind = talloc(1+T->mip->n, int); val = talloc(1+T->mip->n, double); glp_add_rows(lp, T->orig_m); glp_add_cols(lp, T->n); for (i = 1; i <= T->orig_m; i++) { glp_set_row_bnds(lp, i, T->orig_type[i], T->orig_lb[i], T->orig_ub[i]); len = glp_get_mat_row(T->mip, i, ind, val); glp_set_mat_row(lp, i, len, ind, val); } for (j = 1; j <= T->n; j++) { GLPCOL *col = T->mip->col[j]; glp_set_obj_coef(lp, j, col->coef); if (col->kind == GLP_IV) { /* integer variable */ glp_set_col_bnds(lp, j, GLP_FX, floor(col->prim + .5), 0); } else { glp_set_col_bnds(lp, j, T->orig_type[T->orig_m+j], T->orig_lb[T->orig_m+j], T->orig_ub[T->orig_m+j]); } } glp_term_out(GLP_OFF); glp_adv_basis(lp, 0); ret = glp_simplex(lp, NULL); glp_term_out(GLP_ON); if (ret != 0) { ret = 1; goto done; } if (glp_get_status(lp) != GLP_OPT) { ret = 2; goto done; } for (j = 1; j <= lp->n; j++) val[j] = lp->col[j]->prim; if (glp_ios_heur_sol(T, val) == 0) ret = 0; else ret = 3; done: glp_delete_prob(lp); tfree(ind); tfree(val); return ret; } #endif /**********************************************************************/ static void generate_cuts(glp_tree *T) { /* generate generic cuts with built-in generators */ if (!(T->parm->mir_cuts == GLP_ON || T->parm->gmi_cuts == GLP_ON || T->parm->cov_cuts == GLP_ON || T->parm->clq_cuts == GLP_ON)) goto done; #if 1 /* 20/IX-2008 */ { int i, max_cuts, added_cuts; max_cuts = T->n; if (max_cuts < 1000) max_cuts = 1000; added_cuts = 0; for (i = T->orig_m+1; i <= T->mip->m; i++) { if (T->mip->row[i]->origin == GLP_RF_CUT) added_cuts++; } /* xprintf("added_cuts = %d\n", added_cuts); */ if (added_cuts >= max_cuts) goto done; } #endif /* generate and add to POOL all cuts violated by x* */ if (T->parm->gmi_cuts == GLP_ON) { if (T->curr->changed < 7) ios_gmi_gen(T); } if (T->parm->mir_cuts == GLP_ON) { xassert(T->mir_gen != NULL); ios_mir_gen(T, T->mir_gen); } if (T->parm->cov_cuts == GLP_ON) { /* cover cuts works well along with mir cuts */ /*if (T->round <= 5)*/ ios_cov_gen(T); } if (T->parm->clq_cuts == GLP_ON) { if (T->clq_gen != NULL) #if 0 /* 29/VI-2013 */ { if (T->curr->level == 0 && T->curr->changed < 50 || T->curr->level > 0 && T->curr->changed < 5) #else /* FIXME */ { if (T->curr->level == 0 && T->curr->changed < 500 || T->curr->level > 0 && T->curr->changed < 50) #endif ios_clq_gen(T, T->clq_gen); } } done: return; } /**********************************************************************/ static void remove_cuts(glp_tree *T) { /* remove inactive cuts (some valueable globally valid cut might be saved in the global cut pool) */ int i, cnt = 0, *num = NULL; xassert(T->curr != NULL); for (i = T->orig_m+1; i <= T->mip->m; i++) { if (T->mip->row[i]->origin == GLP_RF_CUT && T->mip->row[i]->level == T->curr->level && T->mip->row[i]->stat == GLP_BS) { if (num == NULL) num = xcalloc(1+T->mip->m, sizeof(int)); num[++cnt] = i; } } if (cnt > 0) { glp_del_rows(T->mip, cnt, num); #if 0 xprintf("%d inactive cut(s) removed\n", cnt); #endif xfree(num); xassert(glp_factorize(T->mip) == 0); } return; } /**********************************************************************/ static void display_cut_info(glp_tree *T) { glp_prob *mip = T->mip; int i, gmi = 0, mir = 0, cov = 0, clq = 0, app = 0; for (i = mip->m; i > 0; i--) { GLPROW *row; row = mip->row[i]; /* if (row->level < T->curr->level) break; */ if (row->origin == GLP_RF_CUT) { if (row->klass == GLP_RF_GMI) gmi++; else if (row->klass == GLP_RF_MIR) mir++; else if (row->klass == GLP_RF_COV) cov++; else if (row->klass == GLP_RF_CLQ) clq++; else app++; } } xassert(T->curr != NULL); if (gmi + mir + cov + clq + app > 0) { xprintf("Cuts on level %d:", T->curr->level); if (gmi > 0) xprintf(" gmi = %d;", gmi); if (mir > 0) xprintf(" mir = %d;", mir); if (cov > 0) xprintf(" cov = %d;", cov); if (clq > 0) xprintf(" clq = %d;", clq); if (app > 0) xprintf(" app = %d;", app); xprintf("\n"); } return; } /*********************************************************************** * NAME * * ios_driver - branch-and-cut driver * * SYNOPSIS * * #include "glpios.h" * int ios_driver(glp_tree *T); * * DESCRIPTION * * The routine ios_driver is a branch-and-cut driver. It controls the * MIP solution process. * * RETURNS * * 0 The MIP problem instance has been successfully solved. This code * does not necessarily mean that the solver has found optimal * solution. It only means that the solution process was successful. * * GLP_EFAIL * The search was prematurely terminated due to the solver failure. * * GLP_EMIPGAP * The search was prematurely terminated, because the relative mip * gap tolerance has been reached. * * GLP_ETMLIM * The search was prematurely terminated, because the time limit has * been exceeded. * * GLP_ESTOP * The search was prematurely terminated by application. */ int ios_driver(glp_tree *T) { int p, curr_p, p_stat, d_stat, ret; #if 1 /* carry out to glp_tree */ int pred_p = 0; /* if the current subproblem has been just created due to branching, pred_p is the reference number of its parent subproblem, otherwise pred_p is zero */ #endif #if 1 /* 18/VII-2013 */ int bad_cut; double old_obj; #endif #if 0 /* 10/VI-2013 */ glp_long ttt = T->tm_beg; #else double ttt = T->tm_beg; #endif #if 0 ((glp_iocp *)T->parm)->msg_lev = GLP_MSG_DBG; #endif /* on entry to the B&B driver it is assumed that the active list contains the only active (i.e. root) subproblem, which is the original MIP problem to be solved */ loop: /* main loop starts here */ /* at this point the current subproblem does not exist */ xassert(T->curr == NULL); /* if the active list is empty, the search is finished */ if (T->head == NULL) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Active list is empty!\n"); #if 0 /* 10/VI-2013 */ xassert(dmp_in_use(T->pool).lo == 0); #else xassert(dmp_in_use(T->pool) == 0); #endif ret = 0; goto done; } /* select some active subproblem to continue the search */ xassert(T->next_p == 0); /* let the application program select subproblem */ if (T->parm->cb_func != NULL) { xassert(T->reason == 0); T->reason = GLP_ISELECT; T->parm->cb_func(T, T->parm->cb_info); T->reason = 0; if (T->stop) { ret = GLP_ESTOP; goto done; } } if (T->next_p != 0) { /* the application program has selected something */ ; } else if (T->a_cnt == 1) { /* the only active subproblem exists, so select it */ xassert(T->head->next == NULL); T->next_p = T->head->p; } else if (T->child != 0) { /* select one of branching childs suggested by the branching heuristic */ T->next_p = T->child; } else { /* select active subproblem as specified by the backtracking technique option */ T->next_p = ios_choose_node(T); } /* the active subproblem just selected becomes current */ ios_revive_node(T, T->next_p); T->next_p = T->child = 0; /* invalidate pred_p, if it is not the reference number of the parent of the current subproblem */ if (T->curr->up != NULL && T->curr->up->p != pred_p) pred_p = 0; /* determine the reference number of the current subproblem */ p = T->curr->p; if (T->parm->msg_lev >= GLP_MSG_DBG) { xprintf("-----------------------------------------------------" "-------------------\n"); xprintf("Processing node %d at level %d\n", p, T->curr->level); } /* if it is the root subproblem, initialize cut generators */ if (p == 1) { if (T->parm->gmi_cuts == GLP_ON) { if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Gomory's cuts enabled\n"); } if (T->parm->mir_cuts == GLP_ON) { if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("MIR cuts enabled\n"); xassert(T->mir_gen == NULL); T->mir_gen = ios_mir_init(T); } if (T->parm->cov_cuts == GLP_ON) { if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Cover cuts enabled\n"); } if (T->parm->clq_cuts == GLP_ON) { xassert(T->clq_gen == NULL); if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Clique cuts enabled\n"); T->clq_gen = ios_clq_init(T); } } #if 1 /* 18/VII-2013 */ bad_cut = 0; #endif more: /* minor loop starts here */ /* at this point the current subproblem needs either to be solved for the first time or re-optimized due to reformulation */ /* display current progress of the search */ if (T->parm->msg_lev >= GLP_MSG_DBG || T->parm->msg_lev >= GLP_MSG_ON && (double)(T->parm->out_frq - 1) <= 1000.0 * xdifftime(xtime(), T->tm_lag)) show_progress(T, 0); if (T->parm->msg_lev >= GLP_MSG_ALL && xdifftime(xtime(), ttt) >= 60.0) #if 0 /* 16/II-2012 */ { glp_long total; glp_mem_usage(NULL, NULL, &total, NULL); xprintf("Time used: %.1f secs. Memory used: %.1f Mb.\n", xdifftime(xtime(), T->tm_beg), xltod(total) / 1048576.0); ttt = xtime(); } #else { size_t total; glp_mem_usage(NULL, NULL, &total, NULL); xprintf("Time used: %.1f secs. Memory used: %.1f Mb.\n", xdifftime(xtime(), T->tm_beg), (double)total / 1048576.0); ttt = xtime(); } #endif /* check the mip gap */ if (T->parm->mip_gap > 0.0 && ios_relative_gap(T) <= T->parm->mip_gap) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Relative gap tolerance reached; search terminated " "\n"); ret = GLP_EMIPGAP; goto done; } /* check if the time limit has been exhausted */ if (T->parm->tm_lim < INT_MAX && (double)(T->parm->tm_lim - 1) <= 1000.0 * xdifftime(xtime(), T->tm_beg)) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Time limit exhausted; search terminated\n"); ret = GLP_ETMLIM; goto done; } /* let the application program preprocess the subproblem */ if (T->parm->cb_func != NULL) { xassert(T->reason == 0); T->reason = GLP_IPREPRO; T->parm->cb_func(T, T->parm->cb_info); T->reason = 0; if (T->stop) { ret = GLP_ESTOP; goto done; } } /* perform basic preprocessing */ if (T->parm->pp_tech == GLP_PP_NONE) ; else if (T->parm->pp_tech == GLP_PP_ROOT) { if (T->curr->level == 0) { if (ios_preprocess_node(T, 100)) goto fath; } } else if (T->parm->pp_tech == GLP_PP_ALL) { if (ios_preprocess_node(T, T->curr->level == 0 ? 100 : 10)) goto fath; } else xassert(T != T); /* preprocessing may improve the global bound */ if (!is_branch_hopeful(T, p)) { xprintf("*** not tested yet ***\n"); goto fath; } /* solve LP relaxation of the current subproblem */ if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Solving LP relaxation...\n"); ret = ios_solve_node(T); if (!(ret == 0 || ret == GLP_EOBJLL || ret == GLP_EOBJUL)) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("ios_driver: unable to solve current LP relaxation;" " glp_simplex returned %d\n", ret); ret = GLP_EFAIL; goto done; } /* analyze status of the basic solution to LP relaxation found */ p_stat = T->mip->pbs_stat; d_stat = T->mip->dbs_stat; if (p_stat == GLP_FEAS && d_stat == GLP_FEAS) { /* LP relaxation has optimal solution */ if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Found optimal solution to LP relaxation\n"); } else if (d_stat == GLP_NOFEAS) { /* LP relaxation has no dual feasible solution */ /* since the current subproblem cannot have a larger feasible region than its parent, there is something wrong */ if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("ios_driver: current LP relaxation has no dual feas" "ible solution\n"); ret = GLP_EFAIL; goto done; } else if (p_stat == GLP_INFEAS && d_stat == GLP_FEAS) { /* LP relaxation has no primal solution which is better than the incumbent objective value */ xassert(T->mip->mip_stat == GLP_FEAS); if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("LP relaxation has no solution better than incumben" "t objective value\n"); /* prune the branch */ goto fath; } else if (p_stat == GLP_NOFEAS) { /* LP relaxation has no primal feasible solution */ if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("LP relaxation has no feasible solution\n"); /* prune the branch */ goto fath; } else { /* other cases cannot appear */ xassert(T->mip != T->mip); } /* at this point basic solution to LP relaxation of the current subproblem is optimal */ xassert(p_stat == GLP_FEAS && d_stat == GLP_FEAS); xassert(T->curr != NULL); T->curr->lp_obj = T->mip->obj_val; /* thus, it defines a local bound to integer optimal solution of the current subproblem */ { double bound = T->mip->obj_val; /* some local bound to the current subproblem could be already set before, so we should only improve it */ bound = ios_round_bound(T, bound); if (T->mip->dir == GLP_MIN) { if (T->curr->bound < bound) T->curr->bound = bound; } else if (T->mip->dir == GLP_MAX) { if (T->curr->bound > bound) T->curr->bound = bound; } else xassert(T->mip != T->mip); if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Local bound is %.9e\n", bound); } /* if the local bound indicates that integer optimal solution of the current subproblem cannot be better than the global bound, prune the branch */ if (!is_branch_hopeful(T, p)) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Current branch is hopeless and can be pruned\n"); goto fath; } /* let the application program generate additional rows ("lazy" constraints) */ xassert(T->reopt == 0); xassert(T->reinv == 0); if (T->parm->cb_func != NULL) { xassert(T->reason == 0); T->reason = GLP_IROWGEN; T->parm->cb_func(T, T->parm->cb_info); T->reason = 0; if (T->stop) { ret = GLP_ESTOP; goto done; } if (T->reopt) { /* some rows were added; re-optimization is needed */ T->reopt = T->reinv = 0; goto more; } if (T->reinv) { /* no rows were added, however, some inactive rows were removed */ T->reinv = 0; xassert(glp_factorize(T->mip) == 0); } } /* check if the basic solution is integer feasible */ check_integrality(T); /* if the basic solution satisfies to all integrality conditions, it is a new, better integer feasible solution */ if (T->curr->ii_cnt == 0) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("New integer feasible solution found\n"); if (T->parm->msg_lev >= GLP_MSG_ALL) display_cut_info(T); record_solution(T); if (T->parm->msg_lev >= GLP_MSG_ON) show_progress(T, 1); #if 1 /* 11/VII-2013 */ ios_process_sol(T); #endif /* make the application program happy */ if (T->parm->cb_func != NULL) { xassert(T->reason == 0); T->reason = GLP_IBINGO; T->parm->cb_func(T, T->parm->cb_info); T->reason = 0; if (T->stop) { ret = GLP_ESTOP; goto done; } } /* since the current subproblem has been fathomed, prune its branch */ goto fath; } /* at this point basic solution to LP relaxation of the current subproblem is optimal, but integer infeasible */ /* try to fix some non-basic structural variables of integer kind on their current bounds due to reduced costs */ if (T->mip->mip_stat == GLP_FEAS) fix_by_red_cost(T); /* let the application program try to find some solution to the original MIP with a primal heuristic */ if (T->parm->cb_func != NULL) { xassert(T->reason == 0); T->reason = GLP_IHEUR; T->parm->cb_func(T, T->parm->cb_info); T->reason = 0; if (T->stop) { ret = GLP_ESTOP; goto done; } /* check if the current branch became hopeless */ if (!is_branch_hopeful(T, p)) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Current branch became hopeless and can be prune" "d\n"); goto fath; } } /* try to find solution with the feasibility pump heuristic */ if (T->parm->fp_heur) { xassert(T->reason == 0); T->reason = GLP_IHEUR; ios_feas_pump(T); T->reason = 0; /* check if the current branch became hopeless */ if (!is_branch_hopeful(T, p)) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Current branch became hopeless and can be prune" "d\n"); goto fath; } } #if 1 /* 25/V-2013 */ /* try to find solution with the proximity search heuristic */ if (T->parm->ps_heur) { xassert(T->reason == 0); T->reason = GLP_IHEUR; ios_proxy_heur(T); T->reason = 0; /* check if the current branch became hopeless */ if (!is_branch_hopeful(T, p)) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Current branch became hopeless and can be prune" "d\n"); goto fath; } } #endif #if 1 /* 09/VII-2013 */ /* try to find solution with a simple rounding heuristic */ { xassert(T->reason == 0); T->reason = GLP_IHEUR; round_heur(T); T->reason = 0; /* check if the current branch became hopeless */ if (!is_branch_hopeful(T, p)) { if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Current branch became hopeless and can be prune" "d\n"); goto fath; } } #endif /* it's time to generate cutting planes */ xassert(T->local != NULL); xassert(T->local->size == 0); /* let the application program generate some cuts; note that it can add cuts either to the local cut pool or directly to the current subproblem */ if (T->parm->cb_func != NULL) { xassert(T->reason == 0); T->reason = GLP_ICUTGEN; T->parm->cb_func(T, T->parm->cb_info); T->reason = 0; if (T->stop) { ret = GLP_ESTOP; goto done; } } #if 1 /* 18/VII-2013 */ if (T->curr->changed > 0) { double degrad = fabs(T->curr->lp_obj - old_obj); if (degrad < 1e-4 * (1.0 + fabs(old_obj))) bad_cut++; else bad_cut = 0; } old_obj = T->curr->lp_obj; if (bad_cut == 0 || (T->curr->level == 0 && bad_cut <= 3)) #endif /* try to generate generic cuts with built-in generators (as suggested by Prof. Fischetti et al. the built-in cuts are not generated at each branching node; an intense attempt of generating new cuts is only made at the root node, and then a moderate effort is spent after each backtracking step) */ if (T->curr->level == 0 || pred_p == 0) { xassert(T->reason == 0); T->reason = GLP_ICUTGEN; generate_cuts(T); T->reason = 0; } /* if the local cut pool is not empty, select useful cuts and add them to the current subproblem */ if (T->local->size > 0) { xassert(T->reason == 0); T->reason = GLP_ICUTGEN; ios_process_cuts(T); T->reason = 0; } /* clear the local cut pool */ ios_clear_pool(T, T->local); /* perform re-optimization, if necessary */ if (T->reopt) { T->reopt = 0; T->curr->changed++; goto more; } /* no cuts were generated; remove inactive cuts */ remove_cuts(T); if (T->parm->msg_lev >= GLP_MSG_ALL && T->curr->level == 0) display_cut_info(T); /* update history information used on pseudocost branching */ if (T->pcost != NULL) ios_pcost_update(T); /* it's time to perform branching */ xassert(T->br_var == 0); xassert(T->br_sel == 0); /* let the application program choose variable to branch on */ if (T->parm->cb_func != NULL) { xassert(T->reason == 0); xassert(T->br_var == 0); xassert(T->br_sel == 0); T->reason = GLP_IBRANCH; T->parm->cb_func(T, T->parm->cb_info); T->reason = 0; if (T->stop) { ret = GLP_ESTOP; goto done; } } /* if nothing has been chosen, choose some variable as specified by the branching technique option */ if (T->br_var == 0) T->br_var = ios_choose_var(T, &T->br_sel); /* perform actual branching */ curr_p = T->curr->p; ret = branch_on(T, T->br_var, T->br_sel); T->br_var = T->br_sel = 0; if (ret == 0) { /* both branches have been created */ pred_p = curr_p; goto loop; } else if (ret == 1) { /* one branch is hopeless and has been pruned, so now the current subproblem is other branch */ /* the current subproblem should be considered as a new one, since one bound of the branching variable was changed */ T->curr->solved = T->curr->changed = 0; #if 1 /* 18/VII-2013 */ /* bad_cut = 0; */ #endif goto more; } else if (ret == 2) { /* both branches are hopeless and have been pruned; new subproblem selection is needed to continue the search */ goto fath; } else xassert(ret != ret); fath: /* the current subproblem has been fathomed */ if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("Node %d fathomed\n", p); /* freeze the current subproblem */ ios_freeze_node(T); /* and prune the corresponding branch of the tree */ ios_delete_node(T, p); /* if a new integer feasible solution has just been found, other branches may become hopeless and therefore must be pruned */ if (T->mip->mip_stat == GLP_FEAS) cleanup_the_tree(T); /* new subproblem selection is needed due to backtracking */ pred_p = 0; goto loop; done: /* display progress of the search on exit from the solver */ if (T->parm->msg_lev >= GLP_MSG_ON) show_progress(T, 0); if (T->mir_gen != NULL) ios_mir_term(T->mir_gen), T->mir_gen = NULL; if (T->clq_gen != NULL) ios_clq_term(T->clq_gen), T->clq_gen = NULL; /* return to the calling program */ return ret; } /* eof */ glpk-4.52.1/src/glpios04.c0000644000062000006210000001665412175147600014331 0ustar maomkpasswd/* glpios04.c (operations on sparse vectors) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * NAME * * ios_create_vec - create sparse vector * * SYNOPSIS * * #include "glpios.h" * IOSVEC *ios_create_vec(int n); * * DESCRIPTION * * The routine ios_create_vec creates a sparse vector of dimension n, * which initially is a null vector. * * RETURNS * * The routine returns a pointer to the vector created. */ IOSVEC *ios_create_vec(int n) { IOSVEC *v; xassert(n >= 0); v = xmalloc(sizeof(IOSVEC)); v->n = n; v->nnz = 0; v->pos = xcalloc(1+n, sizeof(int)); memset(&v->pos[1], 0, n * sizeof(int)); v->ind = xcalloc(1+n, sizeof(int)); v->val = xcalloc(1+n, sizeof(double)); return v; } /*********************************************************************** * NAME * * ios_check_vec - check that sparse vector has correct representation * * SYNOPSIS * * #include "glpios.h" * void ios_check_vec(IOSVEC *v); * * DESCRIPTION * * The routine ios_check_vec checks that a sparse vector specified by * the parameter v has correct representation. * * NOTE * * Complexity of this operation is O(n). */ void ios_check_vec(IOSVEC *v) { int j, k, nnz; xassert(v->n >= 0); nnz = 0; for (j = v->n; j >= 1; j--) { k = v->pos[j]; xassert(0 <= k && k <= v->nnz); if (k != 0) { xassert(v->ind[k] == j); nnz++; } } xassert(v->nnz == nnz); return; } /*********************************************************************** * NAME * * ios_get_vj - retrieve component of sparse vector * * SYNOPSIS * * #include "glpios.h" * double ios_get_vj(IOSVEC *v, int j); * * RETURNS * * The routine ios_get_vj returns j-th component of a sparse vector * specified by the parameter v. */ double ios_get_vj(IOSVEC *v, int j) { int k; xassert(1 <= j && j <= v->n); k = v->pos[j]; xassert(0 <= k && k <= v->nnz); return (k == 0 ? 0.0 : v->val[k]); } /*********************************************************************** * NAME * * ios_set_vj - set/change component of sparse vector * * SYNOPSIS * * #include "glpios.h" * void ios_set_vj(IOSVEC *v, int j, double val); * * DESCRIPTION * * The routine ios_set_vj assigns val to j-th component of a sparse * vector specified by the parameter v. */ void ios_set_vj(IOSVEC *v, int j, double val) { int k; xassert(1 <= j && j <= v->n); k = v->pos[j]; if (val == 0.0) { if (k != 0) { /* remove j-th component */ v->pos[j] = 0; if (k < v->nnz) { v->pos[v->ind[v->nnz]] = k; v->ind[k] = v->ind[v->nnz]; v->val[k] = v->val[v->nnz]; } v->nnz--; } } else { if (k == 0) { /* create j-th component */ k = ++(v->nnz); v->pos[j] = k; v->ind[k] = j; } v->val[k] = val; } return; } /*********************************************************************** * NAME * * ios_clear_vec - set all components of sparse vector to zero * * SYNOPSIS * * #include "glpios.h" * void ios_clear_vec(IOSVEC *v); * * DESCRIPTION * * The routine ios_clear_vec sets all components of a sparse vector * specified by the parameter v to zero. */ void ios_clear_vec(IOSVEC *v) { int k; for (k = 1; k <= v->nnz; k++) v->pos[v->ind[k]] = 0; v->nnz = 0; return; } /*********************************************************************** * NAME * * ios_clean_vec - remove zero or small components from sparse vector * * SYNOPSIS * * #include "glpios.h" * void ios_clean_vec(IOSVEC *v, double eps); * * DESCRIPTION * * The routine ios_clean_vec removes zero components and components * whose magnitude is less than eps from a sparse vector specified by * the parameter v. If eps is 0.0, only zero components are removed. */ void ios_clean_vec(IOSVEC *v, double eps) { int k, nnz; nnz = 0; for (k = 1; k <= v->nnz; k++) { if (fabs(v->val[k]) == 0.0 || fabs(v->val[k]) < eps) { /* remove component */ v->pos[v->ind[k]] = 0; } else { /* keep component */ nnz++; v->pos[v->ind[k]] = nnz; v->ind[nnz] = v->ind[k]; v->val[nnz] = v->val[k]; } } v->nnz = nnz; return; } /*********************************************************************** * NAME * * ios_copy_vec - copy sparse vector (x := y) * * SYNOPSIS * * #include "glpios.h" * void ios_copy_vec(IOSVEC *x, IOSVEC *y); * * DESCRIPTION * * The routine ios_copy_vec copies a sparse vector specified by the * parameter y to a sparse vector specified by the parameter x. */ void ios_copy_vec(IOSVEC *x, IOSVEC *y) { int j; xassert(x != y); xassert(x->n == y->n); ios_clear_vec(x); x->nnz = y->nnz; memcpy(&x->ind[1], &y->ind[1], x->nnz * sizeof(int)); memcpy(&x->val[1], &y->val[1], x->nnz * sizeof(double)); for (j = 1; j <= x->nnz; j++) x->pos[x->ind[j]] = j; return; } /*********************************************************************** * NAME * * ios_linear_comb - compute linear combination (x := x + a * y) * * SYNOPSIS * * #include "glpios.h" * void ios_linear_comb(IOSVEC *x, double a, IOSVEC *y); * * DESCRIPTION * * The routine ios_linear_comb computes the linear combination * * x := x + a * y, * * where x and y are sparse vectors, a is a scalar. */ void ios_linear_comb(IOSVEC *x, double a, IOSVEC *y) { int j, k; double xj, yj; xassert(x != y); xassert(x->n == y->n); for (k = 1; k <= y->nnz; k++) { j = y->ind[k]; xj = ios_get_vj(x, j); yj = y->val[k]; ios_set_vj(x, j, xj + a * yj); } return; } /*********************************************************************** * NAME * * ios_delete_vec - delete sparse vector * * SYNOPSIS * * #include "glpios.h" * void ios_delete_vec(IOSVEC *v); * * DESCRIPTION * * The routine ios_delete_vec deletes a sparse vector specified by the * parameter v freeing all the memory allocated to this object. */ void ios_delete_vec(IOSVEC *v) { /* delete sparse vector */ xfree(v->pos); xfree(v->ind); xfree(v->val); xfree(v); return; } /* eof */ glpk-4.52.1/src/glpios05.c0000644000062000006210000002363212175147600014324 0ustar maomkpasswd/* glpios05.c (Gomory's mixed integer cut generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * NAME * * ios_gmi_gen - generate Gomory's mixed integer cuts. * * SYNOPSIS * * #include "glpios.h" * void ios_gmi_gen(glp_tree *tree, IOSPOOL *pool); * * DESCRIPTION * * The routine ios_gmi_gen generates Gomory's mixed integer cuts for * the current point and adds them to the cut pool. */ #define MAXCUTS 50 /* maximal number of cuts to be generated for one round */ struct worka { /* Gomory's cut generator working area */ int *ind; /* int ind[1+n]; */ double *val; /* double val[1+n]; */ double *phi; /* double phi[1+m+n]; */ }; #define f(x) ((x) - floor(x)) /* compute fractional part of x */ static void gen_cut(glp_tree *tree, struct worka *worka, int j) { /* this routine tries to generate Gomory's mixed integer cut for specified structural variable x[m+j] of integer kind, which is basic and has fractional value in optimal solution to current LP relaxation */ glp_prob *mip = tree->mip; int m = mip->m; int n = mip->n; int *ind = worka->ind; double *val = worka->val; double *phi = worka->phi; int i, k, len, kind, stat; double lb, ub, alfa, beta, ksi, phi1, rhs; /* compute row of the simplex tableau, which (row) corresponds to specified basic variable xB[i] = x[m+j]; see (23) */ len = glp_eval_tab_row(mip, m+j, ind, val); /* determine beta[i], which a value of xB[i] in optimal solution to current LP relaxation; note that this value is the same as if it would be computed with formula (27); it is assumed that beta[i] is fractional enough */ beta = mip->col[j]->prim; /* compute cut coefficients phi and right-hand side rho, which correspond to formula (30); dense format is used, because rows of the simplex tableau is usually dense */ for (k = 1; k <= m+n; k++) phi[k] = 0.0; rhs = f(beta); /* initial value of rho; see (28), (32) */ for (j = 1; j <= len; j++) { /* determine original number of non-basic variable xN[j] */ k = ind[j]; xassert(1 <= k && k <= m+n); /* determine the kind, bounds and current status of xN[j] in optimal solution to LP relaxation */ if (k <= m) { /* auxiliary variable */ GLPROW *row = mip->row[k]; kind = GLP_CV; lb = row->lb; ub = row->ub; stat = row->stat; } else { /* structural variable */ GLPCOL *col = mip->col[k-m]; kind = col->kind; lb = col->lb; ub = col->ub; stat = col->stat; } /* xN[j] cannot be basic */ xassert(stat != GLP_BS); /* determine row coefficient ksi[i,j] at xN[j]; see (23) */ ksi = val[j]; /* if ksi[i,j] is too large in the magnitude, do not generate the cut */ if (fabs(ksi) > 1e+05) goto fini; /* if ksi[i,j] is too small in the magnitude, skip it */ if (fabs(ksi) < 1e-10) goto skip; /* compute row coefficient alfa[i,j] at y[j]; see (26) */ switch (stat) { case GLP_NF: /* xN[j] is free (unbounded) having non-zero ksi[i,j]; do not generate the cut */ goto fini; case GLP_NL: /* xN[j] has active lower bound */ alfa = - ksi; break; case GLP_NU: /* xN[j] has active upper bound */ alfa = + ksi; break; case GLP_NS: /* xN[j] is fixed; skip it */ goto skip; default: xassert(stat != stat); } /* compute cut coefficient phi'[j] at y[j]; see (21), (28) */ switch (kind) { case GLP_IV: /* y[j] is integer */ if (fabs(alfa - floor(alfa + 0.5)) < 1e-10) { /* alfa[i,j] is close to nearest integer; skip it */ goto skip; } else if (f(alfa) <= f(beta)) phi1 = f(alfa); else phi1 = (f(beta) / (1.0 - f(beta))) * (1.0 - f(alfa)); break; case GLP_CV: /* y[j] is continuous */ if (alfa >= 0.0) phi1 = + alfa; else phi1 = (f(beta) / (1.0 - f(beta))) * (- alfa); break; default: xassert(kind != kind); } /* compute cut coefficient phi[j] at xN[j] and update right- hand side rho; see (31), (32) */ switch (stat) { case GLP_NL: /* xN[j] has active lower bound */ phi[k] = + phi1; rhs += phi1 * lb; break; case GLP_NU: /* xN[j] has active upper bound */ phi[k] = - phi1; rhs -= phi1 * ub; break; default: xassert(stat != stat); } skip: ; } /* now the cut has the form sum_k phi[k] * x[k] >= rho, where cut coefficients are stored in the array phi in dense format; x[1,...,m] are auxiliary variables, x[m+1,...,m+n] are struc- tural variables; see (30) */ /* eliminate auxiliary variables in order to express the cut only through structural variables; see (33) */ for (i = 1; i <= m; i++) { GLPROW *row; GLPAIJ *aij; if (fabs(phi[i]) < 1e-10) continue; /* auxiliary variable x[i] has non-zero cut coefficient */ row = mip->row[i]; /* x[i] cannot be fixed */ xassert(row->type != GLP_FX); /* substitute x[i] = sum_j a[i,j] * x[m+j] */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) phi[m+aij->col->j] += phi[i] * aij->val; } /* convert the final cut to sparse format and substitute fixed (structural) variables */ len = 0; for (j = 1; j <= n; j++) { GLPCOL *col; if (fabs(phi[m+j]) < 1e-10) continue; /* structural variable x[m+j] has non-zero cut coefficient */ col = mip->col[j]; if (col->type == GLP_FX) { /* eliminate x[m+j] */ rhs -= phi[m+j] * col->lb; } else { len++; ind[len] = j; val[len] = phi[m+j]; } } if (fabs(rhs) < 1e-12) rhs = 0.0; /* if the cut inequality seems to be badly scaled, reject it to avoid numeric difficulties */ for (k = 1; k <= len; k++) { if (fabs(val[k]) < 1e-03) goto fini; if (fabs(val[k]) > 1e+03) goto fini; } /* add the cut to the cut pool for further consideration */ #if 0 ios_add_cut_row(tree, pool, GLP_RF_GMI, len, ind, val, GLP_LO, rhs); #else glp_ios_add_row(tree, NULL, GLP_RF_GMI, 0, len, ind, val, GLP_LO, rhs); #endif fini: return; } struct var { int j; double f; }; static int fcmp(const void *p1, const void *p2) { const struct var *v1 = p1, *v2 = p2; if (v1->f > v2->f) return -1; if (v1->f < v2->f) return +1; return 0; } void ios_gmi_gen(glp_tree *tree) { /* main routine to generate Gomory's cuts */ glp_prob *mip = tree->mip; int m = mip->m; int n = mip->n; struct var *var; int k, nv, j, size; struct worka _worka, *worka = &_worka; /* allocate working arrays */ var = xcalloc(1+n, sizeof(struct var)); worka->ind = xcalloc(1+n, sizeof(int)); worka->val = xcalloc(1+n, sizeof(double)); worka->phi = xcalloc(1+m+n, sizeof(double)); /* build the list of integer structural variables, which are basic and have fractional value in optimal solution to current LP relaxation */ nv = 0; for (j = 1; j <= n; j++) { GLPCOL *col = mip->col[j]; double frac; if (col->kind != GLP_IV) continue; if (col->type == GLP_FX) continue; if (col->stat != GLP_BS) continue; frac = f(col->prim); if (!(0.05 <= frac && frac <= 0.95)) continue; /* add variable to the list */ nv++, var[nv].j = j, var[nv].f = frac; } /* order the list by descending fractionality */ qsort(&var[1], nv, sizeof(struct var), fcmp); /* try to generate cuts by one for each variable in the list, but not more than MAXCUTS cuts */ size = glp_ios_pool_size(tree); for (k = 1; k <= nv; k++) { if (glp_ios_pool_size(tree) - size >= MAXCUTS) break; gen_cut(tree, worka, var[k].j); } /* free working arrays */ xfree(var); xfree(worka->ind); xfree(worka->val); xfree(worka->phi); return; } /* eof */ glpk-4.52.1/src/glpios06.c0000644000062000006210000013751412175147600014332 0ustar maomkpasswd/* glpios06.c (MIR cut generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" #define _MIR_DEBUG 0 #define MAXAGGR 5 /* maximal number of rows which can be aggregated */ struct MIR { /* MIR cut generator working area */ /*--------------------------------------------------------------*/ /* global information valid for the root subproblem */ int m; /* number of rows (in the root subproblem) */ int n; /* number of columns */ char *skip; /* char skip[1+m]; */ /* skip[i], 1 <= i <= m, is a flag that means that row i should not be used because (1) it is not suitable, or (2) because it has been used in the aggregated constraint */ char *isint; /* char isint[1+m+n]; */ /* isint[k], 1 <= k <= m+n, is a flag that means that variable x[k] is integer (otherwise, continuous) */ double *lb; /* double lb[1+m+n]; */ /* lb[k], 1 <= k <= m+n, is lower bound of x[k]; -DBL_MAX means that x[k] has no lower bound */ int *vlb; /* int vlb[1+m+n]; */ /* vlb[k] = k', 1 <= k <= m+n, is the number of integer variable, which defines variable lower bound x[k] >= lb[k] * x[k']; zero means that x[k] has simple lower bound */ double *ub; /* double ub[1+m+n]; */ /* ub[k], 1 <= k <= m+n, is upper bound of x[k]; +DBL_MAX means that x[k] has no upper bound */ int *vub; /* int vub[1+m+n]; */ /* vub[k] = k', 1 <= k <= m+n, is the number of integer variable, which defines variable upper bound x[k] <= ub[k] * x[k']; zero means that x[k] has simple upper bound */ /*--------------------------------------------------------------*/ /* current (fractional) point to be separated */ double *x; /* double x[1+m+n]; */ /* x[k] is current value of auxiliary (1 <= k <= m) or structural (m+1 <= k <= m+n) variable */ /*--------------------------------------------------------------*/ /* aggregated constraint sum a[k] * x[k] = b, which is a linear combination of original constraints transformed to equalities by introducing auxiliary variables */ int agg_cnt; /* number of rows (original constraints) used to build aggregated constraint, 1 <= agg_cnt <= MAXAGGR */ int *agg_row; /* int agg_row[1+MAXAGGR]; */ /* agg_row[k], 1 <= k <= agg_cnt, is the row number used to build aggregated constraint */ IOSVEC *agg_vec; /* IOSVEC agg_vec[1:m+n]; */ /* sparse vector of aggregated constraint coefficients, a[k] */ double agg_rhs; /* right-hand side of the aggregated constraint, b */ /*--------------------------------------------------------------*/ /* bound substitution flags for modified constraint */ char *subst; /* char subst[1+m+n]; */ /* subst[k], 1 <= k <= m+n, is a bound substitution flag used for variable x[k]: '?' - x[k] is missing in modified constraint 'L' - x[k] = (lower bound) + x'[k] 'U' - x[k] = (upper bound) - x'[k] */ /*--------------------------------------------------------------*/ /* modified constraint sum a'[k] * x'[k] = b', where x'[k] >= 0, derived from aggregated constraint by substituting bounds; note that due to substitution of variable bounds there may be additional terms in the modified constraint */ IOSVEC *mod_vec; /* IOSVEC mod_vec[1:m+n]; */ /* sparse vector of modified constraint coefficients, a'[k] */ double mod_rhs; /* right-hand side of the modified constraint, b' */ /*--------------------------------------------------------------*/ /* cutting plane sum alpha[k] * x[k] <= beta */ IOSVEC *cut_vec; /* IOSVEC cut_vec[1:m+n]; */ /* sparse vector of cutting plane coefficients, alpha[k] */ double cut_rhs; /* right-hand size of the cutting plane, beta */ }; /*********************************************************************** * NAME * * ios_mir_init - initialize MIR cut generator * * SYNOPSIS * * #include "glpios.h" * void *ios_mir_init(glp_tree *tree); * * DESCRIPTION * * The routine ios_mir_init initializes the MIR cut generator assuming * that the current subproblem is the root subproblem. * * RETURNS * * The routine ios_mir_init returns a pointer to the MIR cut generator * working area. */ static void set_row_attrib(glp_tree *tree, struct MIR *mir) { /* set global row attributes */ glp_prob *mip = tree->mip; int m = mir->m; int k; for (k = 1; k <= m; k++) { GLPROW *row = mip->row[k]; mir->skip[k] = 0; mir->isint[k] = 0; switch (row->type) { case GLP_FR: mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break; case GLP_LO: mir->lb[k] = row->lb, mir->ub[k] = +DBL_MAX; break; case GLP_UP: mir->lb[k] = -DBL_MAX, mir->ub[k] = row->ub; break; case GLP_DB: mir->lb[k] = row->lb, mir->ub[k] = row->ub; break; case GLP_FX: mir->lb[k] = mir->ub[k] = row->lb; break; default: xassert(row != row); } mir->vlb[k] = mir->vub[k] = 0; } return; } static void set_col_attrib(glp_tree *tree, struct MIR *mir) { /* set global column attributes */ glp_prob *mip = tree->mip; int m = mir->m; int n = mir->n; int k; for (k = m+1; k <= m+n; k++) { GLPCOL *col = mip->col[k-m]; switch (col->kind) { case GLP_CV: mir->isint[k] = 0; break; case GLP_IV: mir->isint[k] = 1; break; default: xassert(col != col); } switch (col->type) { case GLP_FR: mir->lb[k] = -DBL_MAX, mir->ub[k] = +DBL_MAX; break; case GLP_LO: mir->lb[k] = col->lb, mir->ub[k] = +DBL_MAX; break; case GLP_UP: mir->lb[k] = -DBL_MAX, mir->ub[k] = col->ub; break; case GLP_DB: mir->lb[k] = col->lb, mir->ub[k] = col->ub; break; case GLP_FX: mir->lb[k] = mir->ub[k] = col->lb; break; default: xassert(col != col); } mir->vlb[k] = mir->vub[k] = 0; } return; } static void set_var_bounds(glp_tree *tree, struct MIR *mir) { /* set variable bounds */ glp_prob *mip = tree->mip; int m = mir->m; GLPAIJ *aij; int i, k1, k2; double a1, a2; for (i = 1; i <= m; i++) { /* we need the row to be '>= 0' or '<= 0' */ if (!(mir->lb[i] == 0.0 && mir->ub[i] == +DBL_MAX || mir->lb[i] == -DBL_MAX && mir->ub[i] == 0.0)) continue; /* take first term */ aij = mip->row[i]->ptr; if (aij == NULL) continue; k1 = m + aij->col->j, a1 = aij->val; /* take second term */ aij = aij->r_next; if (aij == NULL) continue; k2 = m + aij->col->j, a2 = aij->val; /* there must be only two terms */ if (aij->r_next != NULL) continue; /* interchange terms, if needed */ if (!mir->isint[k1] && mir->isint[k2]) ; else if (mir->isint[k1] && !mir->isint[k2]) { k2 = k1, a2 = a1; k1 = m + aij->col->j, a1 = aij->val; } else { /* both terms are either continuous or integer */ continue; } /* x[k2] should be double-bounded */ if (mir->lb[k2] == -DBL_MAX || mir->ub[k2] == +DBL_MAX || mir->lb[k2] == mir->ub[k2]) continue; /* change signs, if necessary */ if (mir->ub[i] == 0.0) a1 = - a1, a2 = - a2; /* now the row has the form a1 * x1 + a2 * x2 >= 0, where x1 is continuous, x2 is integer */ if (a1 > 0.0) { /* x1 >= - (a2 / a1) * x2 */ if (mir->vlb[k1] == 0) { /* set variable lower bound for x1 */ mir->lb[k1] = - a2 / a1; mir->vlb[k1] = k2; /* the row should not be used */ mir->skip[i] = 1; } } else /* a1 < 0.0 */ { /* x1 <= - (a2 / a1) * x2 */ if (mir->vub[k1] == 0) { /* set variable upper bound for x1 */ mir->ub[k1] = - a2 / a1; mir->vub[k1] = k2; /* the row should not be used */ mir->skip[i] = 1; } } } return; } static void mark_useless_rows(glp_tree *tree, struct MIR *mir) { /* mark rows which should not be used */ glp_prob *mip = tree->mip; int m = mir->m; GLPAIJ *aij; int i, k, nv; for (i = 1; i <= m; i++) { /* free rows should not be used */ if (mir->lb[i] == -DBL_MAX && mir->ub[i] == +DBL_MAX) { mir->skip[i] = 1; continue; } nv = 0; for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next) { k = m + aij->col->j; /* rows with free variables should not be used */ if (mir->lb[k] == -DBL_MAX && mir->ub[k] == +DBL_MAX) { mir->skip[i] = 1; break; } /* rows with integer variables having infinite (lower or upper) bound should not be used */ if (mir->isint[k] && mir->lb[k] == -DBL_MAX || mir->isint[k] && mir->ub[k] == +DBL_MAX) { mir->skip[i] = 1; break; } /* count non-fixed variables */ if (!(mir->vlb[k] == 0 && mir->vub[k] == 0 && mir->lb[k] == mir->ub[k])) nv++; } /* rows with all variables fixed should not be used */ if (nv == 0) { mir->skip[i] = 1; continue; } } return; } void *ios_mir_init(glp_tree *tree) { /* initialize MIR cut generator */ glp_prob *mip = tree->mip; int m = mip->m; int n = mip->n; struct MIR *mir; #if _MIR_DEBUG xprintf("ios_mir_init: warning: debug mode enabled\n"); #endif /* allocate working area */ mir = xmalloc(sizeof(struct MIR)); mir->m = m; mir->n = n; mir->skip = xcalloc(1+m, sizeof(char)); mir->isint = xcalloc(1+m+n, sizeof(char)); mir->lb = xcalloc(1+m+n, sizeof(double)); mir->vlb = xcalloc(1+m+n, sizeof(int)); mir->ub = xcalloc(1+m+n, sizeof(double)); mir->vub = xcalloc(1+m+n, sizeof(int)); mir->x = xcalloc(1+m+n, sizeof(double)); mir->agg_row = xcalloc(1+MAXAGGR, sizeof(int)); mir->agg_vec = ios_create_vec(m+n); mir->subst = xcalloc(1+m+n, sizeof(char)); mir->mod_vec = ios_create_vec(m+n); mir->cut_vec = ios_create_vec(m+n); /* set global row attributes */ set_row_attrib(tree, mir); /* set global column attributes */ set_col_attrib(tree, mir); /* set variable bounds */ set_var_bounds(tree, mir); /* mark rows which should not be used */ mark_useless_rows(tree, mir); return mir; } /*********************************************************************** * NAME * * ios_mir_gen - generate MIR cuts * * SYNOPSIS * * #include "glpios.h" * void ios_mir_gen(glp_tree *tree, void *gen, IOSPOOL *pool); * * DESCRIPTION * * The routine ios_mir_gen generates MIR cuts for the current point and * adds them to the cut pool. */ static void get_current_point(glp_tree *tree, struct MIR *mir) { /* obtain current point */ glp_prob *mip = tree->mip; int m = mir->m; int n = mir->n; int k; for (k = 1; k <= m; k++) mir->x[k] = mip->row[k]->prim; for (k = m+1; k <= m+n; k++) mir->x[k] = mip->col[k-m]->prim; return; } #if _MIR_DEBUG static void check_current_point(struct MIR *mir) { /* check current point */ int m = mir->m; int n = mir->n; int k, kk; double lb, ub, eps; for (k = 1; k <= m+n; k++) { /* determine lower bound */ lb = mir->lb[k]; kk = mir->vlb[k]; if (kk != 0) { xassert(lb != -DBL_MAX); xassert(!mir->isint[k]); xassert(mir->isint[kk]); lb *= mir->x[kk]; } /* check lower bound */ if (lb != -DBL_MAX) { eps = 1e-6 * (1.0 + fabs(lb)); xassert(mir->x[k] >= lb - eps); } /* determine upper bound */ ub = mir->ub[k]; kk = mir->vub[k]; if (kk != 0) { xassert(ub != +DBL_MAX); xassert(!mir->isint[k]); xassert(mir->isint[kk]); ub *= mir->x[kk]; } /* check upper bound */ if (ub != +DBL_MAX) { eps = 1e-6 * (1.0 + fabs(ub)); xassert(mir->x[k] <= ub + eps); } } return; } #endif static void initial_agg_row(glp_tree *tree, struct MIR *mir, int i) { /* use original i-th row as initial aggregated constraint */ glp_prob *mip = tree->mip; int m = mir->m; GLPAIJ *aij; xassert(1 <= i && i <= m); xassert(!mir->skip[i]); /* mark i-th row in order not to use it in the same aggregated constraint */ mir->skip[i] = 2; mir->agg_cnt = 1; mir->agg_row[1] = i; /* use x[i] - sum a[i,j] * x[m+j] = 0, where x[i] is auxiliary variable of row i, x[m+j] are structural variables */ ios_clear_vec(mir->agg_vec); ios_set_vj(mir->agg_vec, i, 1.0); for (aij = mip->row[i]->ptr; aij != NULL; aij = aij->r_next) ios_set_vj(mir->agg_vec, m + aij->col->j, - aij->val); mir->agg_rhs = 0.0; #if _MIR_DEBUG ios_check_vec(mir->agg_vec); #endif return; } #if _MIR_DEBUG static void check_agg_row(struct MIR *mir) { /* check aggregated constraint */ int m = mir->m; int n = mir->n; int j, k; double r, big; /* compute the residual r = sum a[k] * x[k] - b and determine big = max(1, |a[k]|, |b|) */ r = 0.0, big = 1.0; for (j = 1; j <= mir->agg_vec->nnz; j++) { k = mir->agg_vec->ind[j]; xassert(1 <= k && k <= m+n); r += mir->agg_vec->val[j] * mir->x[k]; if (big < fabs(mir->agg_vec->val[j])) big = fabs(mir->agg_vec->val[j]); } r -= mir->agg_rhs; if (big < fabs(mir->agg_rhs)) big = fabs(mir->agg_rhs); /* the residual must be close to zero */ xassert(fabs(r) <= 1e-6 * big); return; } #endif static void subst_fixed_vars(struct MIR *mir) { /* substitute fixed variables into aggregated constraint */ int m = mir->m; int n = mir->n; int j, k; for (j = 1; j <= mir->agg_vec->nnz; j++) { k = mir->agg_vec->ind[j]; xassert(1 <= k && k <= m+n); if (mir->vlb[k] == 0 && mir->vub[k] == 0 && mir->lb[k] == mir->ub[k]) { /* x[k] is fixed */ mir->agg_rhs -= mir->agg_vec->val[j] * mir->lb[k]; mir->agg_vec->val[j] = 0.0; } } /* remove terms corresponding to fixed variables */ ios_clean_vec(mir->agg_vec, DBL_EPSILON); #if _MIR_DEBUG ios_check_vec(mir->agg_vec); #endif return; } static void bound_subst_heur(struct MIR *mir) { /* bound substitution heuristic */ int m = mir->m; int n = mir->n; int j, k, kk; double d1, d2; for (j = 1; j <= mir->agg_vec->nnz; j++) { k = mir->agg_vec->ind[j]; xassert(1 <= k && k <= m+n); if (mir->isint[k]) continue; /* skip integer variable */ /* compute distance from x[k] to its lower bound */ kk = mir->vlb[k]; if (kk == 0) { if (mir->lb[k] == -DBL_MAX) d1 = DBL_MAX; else d1 = mir->x[k] - mir->lb[k]; } else { xassert(1 <= kk && kk <= m+n); xassert(mir->isint[kk]); xassert(mir->lb[k] != -DBL_MAX); d1 = mir->x[k] - mir->lb[k] * mir->x[kk]; } /* compute distance from x[k] to its upper bound */ kk = mir->vub[k]; if (kk == 0) { if (mir->vub[k] == +DBL_MAX) d2 = DBL_MAX; else d2 = mir->ub[k] - mir->x[k]; } else { xassert(1 <= kk && kk <= m+n); xassert(mir->isint[kk]); xassert(mir->ub[k] != +DBL_MAX); d2 = mir->ub[k] * mir->x[kk] - mir->x[k]; } /* x[k] cannot be free */ xassert(d1 != DBL_MAX || d2 != DBL_MAX); /* choose the bound which is closer to x[k] */ xassert(mir->subst[k] == '?'); if (d1 <= d2) mir->subst[k] = 'L'; else mir->subst[k] = 'U'; } return; } static void build_mod_row(struct MIR *mir) { /* substitute bounds and build modified constraint */ int m = mir->m; int n = mir->n; int j, jj, k, kk; /* initially modified constraint is aggregated constraint */ ios_copy_vec(mir->mod_vec, mir->agg_vec); mir->mod_rhs = mir->agg_rhs; #if _MIR_DEBUG ios_check_vec(mir->mod_vec); #endif /* substitute bounds for continuous variables; note that due to substitution of variable bounds additional terms may appear in modified constraint */ for (j = mir->mod_vec->nnz; j >= 1; j--) { k = mir->mod_vec->ind[j]; xassert(1 <= k && k <= m+n); if (mir->isint[k]) continue; /* skip integer variable */ if (mir->subst[k] == 'L') { /* x[k] = (lower bound) + x'[k] */ xassert(mir->lb[k] != -DBL_MAX); kk = mir->vlb[k]; if (kk == 0) { /* x[k] = lb[k] + x'[k] */ mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k]; } else { /* x[k] = lb[k] * x[kk] + x'[k] */ xassert(mir->isint[kk]); jj = mir->mod_vec->pos[kk]; if (jj == 0) { ios_set_vj(mir->mod_vec, kk, 1.0); jj = mir->mod_vec->pos[kk]; mir->mod_vec->val[jj] = 0.0; } mir->mod_vec->val[jj] += mir->mod_vec->val[j] * mir->lb[k]; } } else if (mir->subst[k] == 'U') { /* x[k] = (upper bound) - x'[k] */ xassert(mir->ub[k] != +DBL_MAX); kk = mir->vub[k]; if (kk == 0) { /* x[k] = ub[k] - x'[k] */ mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k]; } else { /* x[k] = ub[k] * x[kk] - x'[k] */ xassert(mir->isint[kk]); jj = mir->mod_vec->pos[kk]; if (jj == 0) { ios_set_vj(mir->mod_vec, kk, 1.0); jj = mir->mod_vec->pos[kk]; mir->mod_vec->val[jj] = 0.0; } mir->mod_vec->val[jj] += mir->mod_vec->val[j] * mir->ub[k]; } mir->mod_vec->val[j] = - mir->mod_vec->val[j]; } else xassert(k != k); } #if _MIR_DEBUG ios_check_vec(mir->mod_vec); #endif /* substitute bounds for integer variables */ for (j = 1; j <= mir->mod_vec->nnz; j++) { k = mir->mod_vec->ind[j]; xassert(1 <= k && k <= m+n); if (!mir->isint[k]) continue; /* skip continuous variable */ xassert(mir->subst[k] == '?'); xassert(mir->vlb[k] == 0 && mir->vub[k] == 0); xassert(mir->lb[k] != -DBL_MAX && mir->ub[k] != +DBL_MAX); if (fabs(mir->lb[k]) <= fabs(mir->ub[k])) { /* x[k] = lb[k] + x'[k] */ mir->subst[k] = 'L'; mir->mod_rhs -= mir->mod_vec->val[j] * mir->lb[k]; } else { /* x[k] = ub[k] - x'[k] */ mir->subst[k] = 'U'; mir->mod_rhs -= mir->mod_vec->val[j] * mir->ub[k]; mir->mod_vec->val[j] = - mir->mod_vec->val[j]; } } #if _MIR_DEBUG ios_check_vec(mir->mod_vec); #endif return; } #if _MIR_DEBUG static void check_mod_row(struct MIR *mir) { /* check modified constraint */ int m = mir->m; int n = mir->n; int j, k, kk; double r, big, x; /* compute the residual r = sum a'[k] * x'[k] - b' and determine big = max(1, |a[k]|, |b|) */ r = 0.0, big = 1.0; for (j = 1; j <= mir->mod_vec->nnz; j++) { k = mir->mod_vec->ind[j]; xassert(1 <= k && k <= m+n); if (mir->subst[k] == 'L') { /* x'[k] = x[k] - (lower bound) */ xassert(mir->lb[k] != -DBL_MAX); kk = mir->vlb[k]; if (kk == 0) x = mir->x[k] - mir->lb[k]; else x = mir->x[k] - mir->lb[k] * mir->x[kk]; } else if (mir->subst[k] == 'U') { /* x'[k] = (upper bound) - x[k] */ xassert(mir->ub[k] != +DBL_MAX); kk = mir->vub[k]; if (kk == 0) x = mir->ub[k] - mir->x[k]; else x = mir->ub[k] * mir->x[kk] - mir->x[k]; } else xassert(k != k); r += mir->mod_vec->val[j] * x; if (big < fabs(mir->mod_vec->val[j])) big = fabs(mir->mod_vec->val[j]); } r -= mir->mod_rhs; if (big < fabs(mir->mod_rhs)) big = fabs(mir->mod_rhs); /* the residual must be close to zero */ xassert(fabs(r) <= 1e-6 * big); return; } #endif /*********************************************************************** * mir_ineq - construct MIR inequality * * Given the single constraint mixed integer set * * |N| * X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s}, * + + j in N * * this routine constructs the mixed integer rounding (MIR) inequality * * sum alpha[j] * x[j] <= beta + gamma * s, * j in N * * which is valid for X. * * If the MIR inequality has been successfully constructed, the routine * returns zero. Otherwise, if b is close to nearest integer, there may * be numeric difficulties due to big coefficients; so in this case the * routine returns non-zero. */ static int mir_ineq(const int n, const double a[], const double b, double alpha[], double *beta, double *gamma) { int j; double f, t; if (fabs(b - floor(b + .5)) < 0.01) return 1; f = b - floor(b); for (j = 1; j <= n; j++) { t = (a[j] - floor(a[j])) - f; if (t <= 0.0) alpha[j] = floor(a[j]); else alpha[j] = floor(a[j]) + t / (1.0 - f); } *beta = floor(b); *gamma = 1.0 / (1.0 - f); return 0; } /*********************************************************************** * cmir_ineq - construct c-MIR inequality * * Given the mixed knapsack set * * MK |N| * X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s, * + + j in N * * x[j] <= u[j]}, * * a subset C of variables to be complemented, and a divisor delta > 0, * this routine constructs the complemented MIR (c-MIR) inequality * * sum alpha[j] * x[j] <= beta + gamma * s, * j in N * MK * which is valid for X . * * If the c-MIR inequality has been successfully constructed, the * routine returns zero. Otherwise, if there is a risk of numerical * difficulties due to big coefficients (see comments to the routine * mir_ineq), the routine cmir_ineq returns non-zero. */ static int cmir_ineq(const int n, const double a[], const double b, const double u[], const char cset[], const double delta, double alpha[], double *beta, double *gamma) { int j; double *aa, bb; aa = alpha, bb = b; for (j = 1; j <= n; j++) { aa[j] = a[j] / delta; if (cset[j]) aa[j] = - aa[j], bb -= a[j] * u[j]; } bb /= delta; if (mir_ineq(n, aa, bb, alpha, beta, gamma)) return 1; for (j = 1; j <= n; j++) { if (cset[j]) alpha[j] = - alpha[j], *beta += alpha[j] * u[j]; } *gamma /= delta; return 0; } /*********************************************************************** * cmir_sep - c-MIR separation heuristic * * Given the mixed knapsack set * * MK |N| * X = {(x,s) in Z x R : sum a[j] * x[j] <= b + s, * + + j in N * * x[j] <= u[j]} * * * * * and a fractional point (x , s ), this routine tries to construct * c-MIR inequality * * sum alpha[j] * x[j] <= beta + gamma * s, * j in N * MK * which is valid for X and has (desirably maximal) violation at the * fractional point given. This is attained by choosing an appropriate * set C of variables to be complemented and a divisor delta > 0, which * together define corresponding c-MIR inequality. * * If a violated c-MIR inequality has been successfully constructed, * the routine returns its violation: * * * * * sum alpha[j] * x [j] - beta - gamma * s , * j in N * * which is positive. In case of failure the routine returns zero. */ struct vset { int j; double v; }; static int cmir_cmp(const void *p1, const void *p2) { const struct vset *v1 = p1, *v2 = p2; if (v1->v < v2->v) return -1; if (v1->v > v2->v) return +1; return 0; } static double cmir_sep(const int n, const double a[], const double b, const double u[], const double x[], const double s, double alpha[], double *beta, double *gamma) { int fail, j, k, nv, v; double delta, eps, d_try[1+3], r, r_best; char *cset; struct vset *vset; /* allocate working arrays */ cset = xcalloc(1+n, sizeof(char)); vset = xcalloc(1+n, sizeof(struct vset)); /* choose initial C */ for (j = 1; j <= n; j++) cset[j] = (char)(x[j] >= 0.5 * u[j]); /* choose initial delta */ r_best = delta = 0.0; for (j = 1; j <= n; j++) { xassert(a[j] != 0.0); /* if x[j] is close to its bounds, skip it */ eps = 1e-9 * (1.0 + fabs(u[j])); if (x[j] < eps || x[j] > u[j] - eps) continue; /* try delta = |a[j]| to construct c-MIR inequality */ fail = cmir_ineq(n, a, b, u, cset, fabs(a[j]), alpha, beta, gamma); if (fail) continue; /* compute violation */ r = - (*beta) - (*gamma) * s; for (k = 1; k <= n; k++) r += alpha[k] * x[k]; if (r_best < r) r_best = r, delta = fabs(a[j]); } if (r_best < 0.001) r_best = 0.0; if (r_best == 0.0) goto done; xassert(delta > 0.0); /* try to increase violation by dividing delta by 2, 4, and 8, respectively */ d_try[1] = delta / 2.0; d_try[2] = delta / 4.0; d_try[3] = delta / 8.0; for (j = 1; j <= 3; j++) { /* construct c-MIR inequality */ fail = cmir_ineq(n, a, b, u, cset, d_try[j], alpha, beta, gamma); if (fail) continue; /* compute violation */ r = - (*beta) - (*gamma) * s; for (k = 1; k <= n; k++) r += alpha[k] * x[k]; if (r_best < r) r_best = r, delta = d_try[j]; } /* build subset of variables lying strictly between their bounds and order it by nondecreasing values of |x[j] - u[j]/2| */ nv = 0; for (j = 1; j <= n; j++) { /* if x[j] is close to its bounds, skip it */ eps = 1e-9 * (1.0 + fabs(u[j])); if (x[j] < eps || x[j] > u[j] - eps) continue; /* add x[j] to the subset */ nv++; vset[nv].j = j; vset[nv].v = fabs(x[j] - 0.5 * u[j]); } qsort(&vset[1], nv, sizeof(struct vset), cmir_cmp); /* try to increase violation by successively complementing each variable in the subset */ for (v = 1; v <= nv; v++) { j = vset[v].j; /* replace x[j] by its complement or vice versa */ cset[j] = (char)!cset[j]; /* construct c-MIR inequality */ fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma); /* restore the variable */ cset[j] = (char)!cset[j]; /* do not replace the variable in case of failure */ if (fail) continue; /* compute violation */ r = - (*beta) - (*gamma) * s; for (k = 1; k <= n; k++) r += alpha[k] * x[k]; if (r_best < r) r_best = r, cset[j] = (char)!cset[j]; } /* construct the best c-MIR inequality chosen */ fail = cmir_ineq(n, a, b, u, cset, delta, alpha, beta, gamma); xassert(!fail); done: /* free working arrays */ xfree(cset); xfree(vset); /* return to the calling routine */ return r_best; } static double generate(struct MIR *mir) { /* try to generate violated c-MIR cut for modified constraint */ int m = mir->m; int n = mir->n; int j, k, kk, nint; double s, *u, *x, *alpha, r_best = 0.0, b, beta, gamma; ios_copy_vec(mir->cut_vec, mir->mod_vec); mir->cut_rhs = mir->mod_rhs; /* remove small terms, which can appear due to substitution of variable bounds */ ios_clean_vec(mir->cut_vec, DBL_EPSILON); #if _MIR_DEBUG ios_check_vec(mir->cut_vec); #endif /* remove positive continuous terms to obtain MK relaxation */ for (j = 1; j <= mir->cut_vec->nnz; j++) { k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); if (!mir->isint[k] && mir->cut_vec->val[j] > 0.0) mir->cut_vec->val[j] = 0.0; } ios_clean_vec(mir->cut_vec, 0.0); #if _MIR_DEBUG ios_check_vec(mir->cut_vec); #endif /* move integer terms to the beginning of the sparse vector and determine the number of integer variables */ nint = 0; for (j = 1; j <= mir->cut_vec->nnz; j++) { k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); if (mir->isint[k]) { double temp; nint++; /* interchange elements [nint] and [j] */ kk = mir->cut_vec->ind[nint]; mir->cut_vec->pos[k] = nint; mir->cut_vec->pos[kk] = j; mir->cut_vec->ind[nint] = k; mir->cut_vec->ind[j] = kk; temp = mir->cut_vec->val[nint]; mir->cut_vec->val[nint] = mir->cut_vec->val[j]; mir->cut_vec->val[j] = temp; } } #if _MIR_DEBUG ios_check_vec(mir->cut_vec); #endif /* if there is no integer variable, nothing to generate */ if (nint == 0) goto done; /* allocate working arrays */ u = xcalloc(1+nint, sizeof(double)); x = xcalloc(1+nint, sizeof(double)); alpha = xcalloc(1+nint, sizeof(double)); /* determine u and x */ for (j = 1; j <= nint; j++) { k = mir->cut_vec->ind[j]; xassert(m+1 <= k && k <= m+n); xassert(mir->isint[k]); u[j] = mir->ub[k] - mir->lb[k]; xassert(u[j] >= 1.0); if (mir->subst[k] == 'L') x[j] = mir->x[k] - mir->lb[k]; else if (mir->subst[k] == 'U') x[j] = mir->ub[k] - mir->x[k]; else xassert(k != k); xassert(x[j] >= -0.001); if (x[j] < 0.0) x[j] = 0.0; } /* compute s = - sum of continuous terms */ s = 0.0; for (j = nint+1; j <= mir->cut_vec->nnz; j++) { double x; k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); /* must be continuous */ xassert(!mir->isint[k]); if (mir->subst[k] == 'L') { xassert(mir->lb[k] != -DBL_MAX); kk = mir->vlb[k]; if (kk == 0) x = mir->x[k] - mir->lb[k]; else x = mir->x[k] - mir->lb[k] * mir->x[kk]; } else if (mir->subst[k] == 'U') { xassert(mir->ub[k] != +DBL_MAX); kk = mir->vub[k]; if (kk == 0) x = mir->ub[k] - mir->x[k]; else x = mir->ub[k] * mir->x[kk] - mir->x[k]; } else xassert(k != k); xassert(x >= -0.001); if (x < 0.0) x = 0.0; s -= mir->cut_vec->val[j] * x; } xassert(s >= 0.0); /* apply heuristic to obtain most violated c-MIR inequality */ b = mir->cut_rhs; r_best = cmir_sep(nint, mir->cut_vec->val, b, u, x, s, alpha, &beta, &gamma); if (r_best == 0.0) goto skip; xassert(r_best > 0.0); /* convert to raw cut */ /* sum alpha[j] * x[j] <= beta + gamma * s */ for (j = 1; j <= nint; j++) mir->cut_vec->val[j] = alpha[j]; for (j = nint+1; j <= mir->cut_vec->nnz; j++) { k = mir->cut_vec->ind[j]; if (k <= m+n) mir->cut_vec->val[j] *= gamma; } mir->cut_rhs = beta; #if _MIR_DEBUG ios_check_vec(mir->cut_vec); #endif skip: /* free working arrays */ xfree(u); xfree(x); xfree(alpha); done: return r_best; } #if _MIR_DEBUG static void check_raw_cut(struct MIR *mir, double r_best) { /* check raw cut before back bound substitution */ int m = mir->m; int n = mir->n; int j, k, kk; double r, big, x; /* compute the residual r = sum a[k] * x[k] - b and determine big = max(1, |a[k]|, |b|) */ r = 0.0, big = 1.0; for (j = 1; j <= mir->cut_vec->nnz; j++) { k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); if (mir->subst[k] == 'L') { xassert(mir->lb[k] != -DBL_MAX); kk = mir->vlb[k]; if (kk == 0) x = mir->x[k] - mir->lb[k]; else x = mir->x[k] - mir->lb[k] * mir->x[kk]; } else if (mir->subst[k] == 'U') { xassert(mir->ub[k] != +DBL_MAX); kk = mir->vub[k]; if (kk == 0) x = mir->ub[k] - mir->x[k]; else x = mir->ub[k] * mir->x[kk] - mir->x[k]; } else xassert(k != k); r += mir->cut_vec->val[j] * x; if (big < fabs(mir->cut_vec->val[j])) big = fabs(mir->cut_vec->val[j]); } r -= mir->cut_rhs; if (big < fabs(mir->cut_rhs)) big = fabs(mir->cut_rhs); /* the residual must be close to r_best */ xassert(fabs(r - r_best) <= 1e-6 * big); return; } #endif static void back_subst(struct MIR *mir) { /* back substitution of original bounds */ int m = mir->m; int n = mir->n; int j, jj, k, kk; /* at first, restore bounds of integer variables (because on restoring variable bounds of continuous variables we need original, not shifted, bounds of integer variables) */ for (j = 1; j <= mir->cut_vec->nnz; j++) { k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); if (!mir->isint[k]) continue; /* skip continuous */ if (mir->subst[k] == 'L') { /* x'[k] = x[k] - lb[k] */ xassert(mir->lb[k] != -DBL_MAX); xassert(mir->vlb[k] == 0); mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k]; } else if (mir->subst[k] == 'U') { /* x'[k] = ub[k] - x[k] */ xassert(mir->ub[k] != +DBL_MAX); xassert(mir->vub[k] == 0); mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k]; mir->cut_vec->val[j] = - mir->cut_vec->val[j]; } else xassert(k != k); } /* now restore bounds of continuous variables */ for (j = 1; j <= mir->cut_vec->nnz; j++) { k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); if (mir->isint[k]) continue; /* skip integer */ if (mir->subst[k] == 'L') { /* x'[k] = x[k] - (lower bound) */ xassert(mir->lb[k] != -DBL_MAX); kk = mir->vlb[k]; if (kk == 0) { /* x'[k] = x[k] - lb[k] */ mir->cut_rhs += mir->cut_vec->val[j] * mir->lb[k]; } else { /* x'[k] = x[k] - lb[k] * x[kk] */ jj = mir->cut_vec->pos[kk]; #if 0 xassert(jj != 0); #else if (jj == 0) { ios_set_vj(mir->cut_vec, kk, 1.0); jj = mir->cut_vec->pos[kk]; xassert(jj != 0); mir->cut_vec->val[jj] = 0.0; } #endif mir->cut_vec->val[jj] -= mir->cut_vec->val[j] * mir->lb[k]; } } else if (mir->subst[k] == 'U') { /* x'[k] = (upper bound) - x[k] */ xassert(mir->ub[k] != +DBL_MAX); kk = mir->vub[k]; if (kk == 0) { /* x'[k] = ub[k] - x[k] */ mir->cut_rhs -= mir->cut_vec->val[j] * mir->ub[k]; } else { /* x'[k] = ub[k] * x[kk] - x[k] */ jj = mir->cut_vec->pos[kk]; if (jj == 0) { ios_set_vj(mir->cut_vec, kk, 1.0); jj = mir->cut_vec->pos[kk]; xassert(jj != 0); mir->cut_vec->val[jj] = 0.0; } mir->cut_vec->val[jj] += mir->cut_vec->val[j] * mir->ub[k]; } mir->cut_vec->val[j] = - mir->cut_vec->val[j]; } else xassert(k != k); } #if _MIR_DEBUG ios_check_vec(mir->cut_vec); #endif return; } #if _MIR_DEBUG static void check_cut_row(struct MIR *mir, double r_best) { /* check the cut after back bound substitution or elimination of auxiliary variables */ int m = mir->m; int n = mir->n; int j, k; double r, big; /* compute the residual r = sum a[k] * x[k] - b and determine big = max(1, |a[k]|, |b|) */ r = 0.0, big = 1.0; for (j = 1; j <= mir->cut_vec->nnz; j++) { k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); r += mir->cut_vec->val[j] * mir->x[k]; if (big < fabs(mir->cut_vec->val[j])) big = fabs(mir->cut_vec->val[j]); } r -= mir->cut_rhs; if (big < fabs(mir->cut_rhs)) big = fabs(mir->cut_rhs); /* the residual must be close to r_best */ xassert(fabs(r - r_best) <= 1e-6 * big); return; } #endif static void subst_aux_vars(glp_tree *tree, struct MIR *mir) { /* final substitution to eliminate auxiliary variables */ glp_prob *mip = tree->mip; int m = mir->m; int n = mir->n; GLPAIJ *aij; int j, k, kk, jj; for (j = mir->cut_vec->nnz; j >= 1; j--) { k = mir->cut_vec->ind[j]; xassert(1 <= k && k <= m+n); if (k > m) continue; /* skip structurals */ for (aij = mip->row[k]->ptr; aij != NULL; aij = aij->r_next) { kk = m + aij->col->j; /* structural */ jj = mir->cut_vec->pos[kk]; if (jj == 0) { ios_set_vj(mir->cut_vec, kk, 1.0); jj = mir->cut_vec->pos[kk]; mir->cut_vec->val[jj] = 0.0; } mir->cut_vec->val[jj] += mir->cut_vec->val[j] * aij->val; } mir->cut_vec->val[j] = 0.0; } ios_clean_vec(mir->cut_vec, 0.0); return; } static void add_cut(glp_tree *tree, struct MIR *mir) { /* add constructed cut inequality to the cut pool */ int m = mir->m; int n = mir->n; int j, k, len; int *ind = xcalloc(1+n, sizeof(int)); double *val = xcalloc(1+n, sizeof(double)); len = 0; for (j = mir->cut_vec->nnz; j >= 1; j--) { k = mir->cut_vec->ind[j]; xassert(m+1 <= k && k <= m+n); len++, ind[len] = k - m, val[len] = mir->cut_vec->val[j]; } #if 0 ios_add_cut_row(tree, pool, GLP_RF_MIR, len, ind, val, GLP_UP, mir->cut_rhs); #else glp_ios_add_row(tree, NULL, GLP_RF_MIR, 0, len, ind, val, GLP_UP, mir->cut_rhs); #endif xfree(ind); xfree(val); return; } static int aggregate_row(glp_tree *tree, struct MIR *mir) { /* try to aggregate another row */ glp_prob *mip = tree->mip; int m = mir->m; int n = mir->n; GLPAIJ *aij; IOSVEC *v; int ii, j, jj, k, kk, kappa = 0, ret = 0; double d1, d2, d, d_max = 0.0; /* choose appropriate structural variable in the aggregated row to be substituted */ for (j = 1; j <= mir->agg_vec->nnz; j++) { k = mir->agg_vec->ind[j]; xassert(1 <= k && k <= m+n); if (k <= m) continue; /* skip auxiliary var */ if (mir->isint[k]) continue; /* skip integer var */ if (fabs(mir->agg_vec->val[j]) < 0.001) continue; /* compute distance from x[k] to its lower bound */ kk = mir->vlb[k]; if (kk == 0) { if (mir->lb[k] == -DBL_MAX) d1 = DBL_MAX; else d1 = mir->x[k] - mir->lb[k]; } else { xassert(1 <= kk && kk <= m+n); xassert(mir->isint[kk]); xassert(mir->lb[k] != -DBL_MAX); d1 = mir->x[k] - mir->lb[k] * mir->x[kk]; } /* compute distance from x[k] to its upper bound */ kk = mir->vub[k]; if (kk == 0) { if (mir->vub[k] == +DBL_MAX) d2 = DBL_MAX; else d2 = mir->ub[k] - mir->x[k]; } else { xassert(1 <= kk && kk <= m+n); xassert(mir->isint[kk]); xassert(mir->ub[k] != +DBL_MAX); d2 = mir->ub[k] * mir->x[kk] - mir->x[k]; } /* x[k] cannot be free */ xassert(d1 != DBL_MAX || d2 != DBL_MAX); /* d = min(d1, d2) */ d = (d1 <= d2 ? d1 : d2); xassert(d != DBL_MAX); /* should not be close to corresponding bound */ if (d < 0.001) continue; if (d_max < d) d_max = d, kappa = k; } if (kappa == 0) { /* nothing chosen */ ret = 1; goto done; } /* x[kappa] has been chosen */ xassert(m+1 <= kappa && kappa <= m+n); xassert(!mir->isint[kappa]); /* find another row, which have not been used yet, to eliminate x[kappa] from the aggregated row */ for (ii = 1; ii <= m; ii++) { if (mir->skip[ii]) continue; for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next) if (aij->col->j == kappa - m) break; if (aij != NULL && fabs(aij->val) >= 0.001) break; } if (ii > m) { /* nothing found */ ret = 2; goto done; } /* row ii has been found; include it in the aggregated list */ mir->agg_cnt++; xassert(mir->agg_cnt <= MAXAGGR); mir->agg_row[mir->agg_cnt] = ii; mir->skip[ii] = 2; /* v := new row */ v = ios_create_vec(m+n); ios_set_vj(v, ii, 1.0); for (aij = mip->row[ii]->ptr; aij != NULL; aij = aij->r_next) ios_set_vj(v, m + aij->col->j, - aij->val); #if _MIR_DEBUG ios_check_vec(v); #endif /* perform gaussian elimination to remove x[kappa] */ j = mir->agg_vec->pos[kappa]; xassert(j != 0); jj = v->pos[kappa]; xassert(jj != 0); ios_linear_comb(mir->agg_vec, - mir->agg_vec->val[j] / v->val[jj], v); ios_delete_vec(v); ios_set_vj(mir->agg_vec, kappa, 0.0); #if _MIR_DEBUG ios_check_vec(mir->agg_vec); #endif done: return ret; } void ios_mir_gen(glp_tree *tree, void *gen) { /* main routine to generate MIR cuts */ glp_prob *mip = tree->mip; struct MIR *mir = gen; int m = mir->m; int n = mir->n; int i; double r_best; xassert(mip->m >= m); xassert(mip->n == n); /* obtain current point */ get_current_point(tree, mir); #if _MIR_DEBUG /* check current point */ check_current_point(mir); #endif /* reset bound substitution flags */ memset(&mir->subst[1], '?', m+n); /* try to generate a set of violated MIR cuts */ for (i = 1; i <= m; i++) { if (mir->skip[i]) continue; /* use original i-th row as initial aggregated constraint */ initial_agg_row(tree, mir, i); loop: ; #if _MIR_DEBUG /* check aggregated row */ check_agg_row(mir); #endif /* substitute fixed variables into aggregated constraint */ subst_fixed_vars(mir); #if _MIR_DEBUG /* check aggregated row */ check_agg_row(mir); #endif #if _MIR_DEBUG /* check bound substitution flags */ { int k; for (k = 1; k <= m+n; k++) xassert(mir->subst[k] == '?'); } #endif /* apply bound substitution heuristic */ bound_subst_heur(mir); /* substitute bounds and build modified constraint */ build_mod_row(mir); #if _MIR_DEBUG /* check modified row */ check_mod_row(mir); #endif /* try to generate violated c-MIR cut for modified row */ r_best = generate(mir); if (r_best > 0.0) { /* success */ #if _MIR_DEBUG /* check raw cut before back bound substitution */ check_raw_cut(mir, r_best); #endif /* back substitution of original bounds */ back_subst(mir); #if _MIR_DEBUG /* check the cut after back bound substitution */ check_cut_row(mir, r_best); #endif /* final substitution to eliminate auxiliary variables */ subst_aux_vars(tree, mir); #if _MIR_DEBUG /* check the cut after elimination of auxiliaries */ check_cut_row(mir, r_best); #endif /* add constructed cut inequality to the cut pool */ add_cut(tree, mir); } /* reset bound substitution flags */ { int j, k; for (j = 1; j <= mir->mod_vec->nnz; j++) { k = mir->mod_vec->ind[j]; xassert(1 <= k && k <= m+n); xassert(mir->subst[k] != '?'); mir->subst[k] = '?'; } } if (r_best == 0.0) { /* failure */ if (mir->agg_cnt < MAXAGGR) { /* try to aggregate another row */ if (aggregate_row(tree, mir) == 0) goto loop; } } /* unmark rows used in the aggregated constraint */ { int k, ii; for (k = 1; k <= mir->agg_cnt; k++) { ii = mir->agg_row[k]; xassert(1 <= ii && ii <= m); xassert(mir->skip[ii] == 2); mir->skip[ii] = 0; } } } return; } /*********************************************************************** * NAME * * ios_mir_term - terminate MIR cut generator * * SYNOPSIS * * #include "glpios.h" * void ios_mir_term(void *gen); * * DESCRIPTION * * The routine ios_mir_term deletes the MIR cut generator working area * freeing all the memory allocated to it. */ void ios_mir_term(void *gen) { struct MIR *mir = gen; xfree(mir->skip); xfree(mir->isint); xfree(mir->lb); xfree(mir->vlb); xfree(mir->ub); xfree(mir->vub); xfree(mir->x); xfree(mir->agg_row); ios_delete_vec(mir->agg_vec); xfree(mir->subst); ios_delete_vec(mir->mod_vec); ios_delete_vec(mir->cut_vec); xfree(mir); return; } /* eof */ glpk-4.52.1/src/glpios07.c0000644000062000006210000004524512175147600014332 0ustar maomkpasswd/* glpios07.c (mixed cover cut generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*---------------------------------------------------------------------- -- COVER INEQUALITIES -- -- Consider the set of feasible solutions to 0-1 knapsack problem: -- -- sum a[j]*x[j] <= b, (1) -- j in J -- -- x[j] is binary, (2) -- -- where, wlog, we assume that a[j] > 0 (since 0-1 variables can be -- complemented) and a[j] <= b (since a[j] > b implies x[j] = 0). -- -- A set C within J is called a cover if -- -- sum a[j] > b. (3) -- j in C -- -- For any cover C the inequality -- -- sum x[j] <= |C| - 1 (4) -- j in C -- -- is called a cover inequality and is valid for (1)-(2). -- -- MIXED COVER INEQUALITIES -- -- Consider the set of feasible solutions to mixed knapsack problem: -- -- sum a[j]*x[j] + y <= b, (5) -- j in J -- -- x[j] is binary, (6) -- -- 0 <= y <= u is continuous, (7) -- -- where again we assume that a[j] > 0. -- -- Let C within J be some set. From (1)-(4) it follows that -- -- sum a[j] > b - y (8) -- j in C -- -- implies -- -- sum x[j] <= |C| - 1. (9) -- j in C -- -- Thus, we need to modify the inequality (9) in such a way that it be -- a constraint only if the condition (8) is satisfied. -- -- Consider the following inequality: -- -- sum x[j] <= |C| - t. (10) -- j in C -- -- If 0 < t <= 1, then (10) is equivalent to (9), because all x[j] are -- binary variables. On the other hand, if t <= 0, (10) being satisfied -- for any values of x[j] is not a constraint. -- -- Let -- -- t' = sum a[j] + y - b. (11) -- j in C -- -- It is understood that the condition t' > 0 is equivalent to (8). -- Besides, from (6)-(7) it follows that t' has an implied upper bound: -- -- t'max = sum a[j] + u - b. (12) -- j in C -- -- This allows to express the parameter t having desired properties: -- -- t = t' / t'max. (13) -- -- In fact, t <= 1 by definition, and t > 0 being equivalent to t' > 0 -- is equivalent to (8). -- -- Thus, the inequality (10), where t is given by formula (13) is valid -- for (5)-(7). -- -- Note that if u = 0, then y = 0, so t = 1, and the conditions (8) and -- (10) is transformed to the conditions (3) and (4). -- -- GENERATING MIXED COVER CUTS -- -- To generate a mixed cover cut in the form (10) we need to find such -- set C which satisfies to the inequality (8) and for which, in turn, -- the inequality (10) is violated in the current point. -- -- Substituting t from (13) to (10) gives: -- -- 1 -- sum x[j] <= |C| - ----- (sum a[j] + y - b), (14) -- j in C t'max j in C -- -- and finally we have the cut inequality in the standard form: -- -- sum x[j] + alfa * y <= beta, (15) -- j in C -- -- where: -- -- alfa = 1 / t'max, (16) -- -- beta = |C| - alfa * (sum a[j] - b). (17) -- j in C */ #if 1 #define MAXTRY 1000 #else #define MAXTRY 10000 #endif static int cover2(int n, double a[], double b, double u, double x[], double y, int cov[], double *_alfa, double *_beta) { /* try to generate mixed cover cut using two-element cover */ int i, j, try = 0, ret = 0; double eps, alfa, beta, temp, rmax = 0.001; eps = 0.001 * (1.0 + fabs(b)); for (i = 0+1; i <= n; i++) for (j = i+1; j <= n; j++) { /* C = {i, j} */ try++; if (try > MAXTRY) goto done; /* check if condition (8) is satisfied */ if (a[i] + a[j] + y > b + eps) { /* compute parameters for inequality (15) */ temp = a[i] + a[j] - b; alfa = 1.0 / (temp + u); beta = 2.0 - alfa * temp; /* compute violation of inequality (15) */ temp = x[i] + x[j] + alfa * y - beta; /* choose C providing maximum violation */ if (rmax < temp) { rmax = temp; cov[1] = i; cov[2] = j; *_alfa = alfa; *_beta = beta; ret = 1; } } } done: return ret; } static int cover3(int n, double a[], double b, double u, double x[], double y, int cov[], double *_alfa, double *_beta) { /* try to generate mixed cover cut using three-element cover */ int i, j, k, try = 0, ret = 0; double eps, alfa, beta, temp, rmax = 0.001; eps = 0.001 * (1.0 + fabs(b)); for (i = 0+1; i <= n; i++) for (j = i+1; j <= n; j++) for (k = j+1; k <= n; k++) { /* C = {i, j, k} */ try++; if (try > MAXTRY) goto done; /* check if condition (8) is satisfied */ if (a[i] + a[j] + a[k] + y > b + eps) { /* compute parameters for inequality (15) */ temp = a[i] + a[j] + a[k] - b; alfa = 1.0 / (temp + u); beta = 3.0 - alfa * temp; /* compute violation of inequality (15) */ temp = x[i] + x[j] + x[k] + alfa * y - beta; /* choose C providing maximum violation */ if (rmax < temp) { rmax = temp; cov[1] = i; cov[2] = j; cov[3] = k; *_alfa = alfa; *_beta = beta; ret = 1; } } } done: return ret; } static int cover4(int n, double a[], double b, double u, double x[], double y, int cov[], double *_alfa, double *_beta) { /* try to generate mixed cover cut using four-element cover */ int i, j, k, l, try = 0, ret = 0; double eps, alfa, beta, temp, rmax = 0.001; eps = 0.001 * (1.0 + fabs(b)); for (i = 0+1; i <= n; i++) for (j = i+1; j <= n; j++) for (k = j+1; k <= n; k++) for (l = k+1; l <= n; l++) { /* C = {i, j, k, l} */ try++; if (try > MAXTRY) goto done; /* check if condition (8) is satisfied */ if (a[i] + a[j] + a[k] + a[l] + y > b + eps) { /* compute parameters for inequality (15) */ temp = a[i] + a[j] + a[k] + a[l] - b; alfa = 1.0 / (temp + u); beta = 4.0 - alfa * temp; /* compute violation of inequality (15) */ temp = x[i] + x[j] + x[k] + x[l] + alfa * y - beta; /* choose C providing maximum violation */ if (rmax < temp) { rmax = temp; cov[1] = i; cov[2] = j; cov[3] = k; cov[4] = l; *_alfa = alfa; *_beta = beta; ret = 1; } } } done: return ret; } static int cover(int n, double a[], double b, double u, double x[], double y, int cov[], double *alfa, double *beta) { /* try to generate mixed cover cut; input (see (5)): n is the number of binary variables; a[1:n] are coefficients at binary variables; b is the right-hand side; u is upper bound of continuous variable; x[1:n] are values of binary variables at current point; y is value of continuous variable at current point; output (see (15), (16), (17)): cov[1:r] are indices of binary variables included in cover C, where r is the set cardinality returned on exit; alfa coefficient at continuous variable; beta is the right-hand side; */ int j; /* perform some sanity checks */ xassert(n >= 2); for (j = 1; j <= n; j++) xassert(a[j] > 0.0); #if 1 /* ??? */ xassert(b > -1e-5); #else xassert(b > 0.0); #endif xassert(u >= 0.0); for (j = 1; j <= n; j++) xassert(0.0 <= x[j] && x[j] <= 1.0); xassert(0.0 <= y && y <= u); /* try to generate mixed cover cut */ if (cover2(n, a, b, u, x, y, cov, alfa, beta)) return 2; if (cover3(n, a, b, u, x, y, cov, alfa, beta)) return 3; if (cover4(n, a, b, u, x, y, cov, alfa, beta)) return 4; return 0; } /*---------------------------------------------------------------------- -- lpx_cover_cut - generate mixed cover cut. -- -- SYNOPSIS -- -- #include "glplpx.h" -- int lpx_cover_cut(LPX *lp, int len, int ind[], double val[], -- double work[]); -- -- DESCRIPTION -- -- The routine lpx_cover_cut generates a mixed cover cut for a given -- row of the MIP problem. -- -- The given row of the MIP problem should be explicitly specified in -- the form: -- -- sum{j in J} a[j]*x[j] <= b. (1) -- -- On entry indices (ordinal numbers) of structural variables, which -- have non-zero constraint coefficients, should be placed in locations -- ind[1], ..., ind[len], and corresponding constraint coefficients -- should be placed in locations val[1], ..., val[len]. The right-hand -- side b should be stored in location val[0]. -- -- The working array work should have at least nb locations, where nb -- is the number of binary variables in (1). -- -- The routine generates a mixed cover cut in the same form as (1) and -- stores the cut coefficients and right-hand side in the same way as -- just described above. -- -- RETURNS -- -- If the cutting plane has been successfully generated, the routine -- returns 1 <= len' <= n, which is the number of non-zero coefficients -- in the inequality constraint. Otherwise, the routine returns zero. */ static int lpx_cover_cut(LPX *lp, int len, int ind[], double val[], double work[]) { int cov[1+4], j, k, nb, newlen, r; double f_min, f_max, alfa, beta, u, *x = work, y; /* substitute and remove fixed variables */ newlen = 0; for (k = 1; k <= len; k++) { j = ind[k]; if (lpx_get_col_type(lp, j) == LPX_FX) val[0] -= val[k] * lpx_get_col_lb(lp, j); else { newlen++; ind[newlen] = ind[k]; val[newlen] = val[k]; } } len = newlen; /* move binary variables to the beginning of the list so that elements 1, 2, ..., nb correspond to binary variables, and elements nb+1, nb+2, ..., len correspond to rest variables */ nb = 0; for (k = 1; k <= len; k++) { j = ind[k]; if (lpx_get_col_kind(lp, j) == LPX_IV && lpx_get_col_type(lp, j) == LPX_DB && lpx_get_col_lb(lp, j) == 0.0 && lpx_get_col_ub(lp, j) == 1.0) { /* binary variable */ int ind_k; double val_k; nb++; ind_k = ind[nb], val_k = val[nb]; ind[nb] = ind[k], val[nb] = val[k]; ind[k] = ind_k, val[k] = val_k; } } /* now the specified row has the form: sum a[j]*x[j] + sum a[j]*y[j] <= b, where x[j] are binary variables, y[j] are rest variables */ /* at least two binary variables are needed */ if (nb < 2) return 0; /* compute implied lower and upper bounds for sum a[j]*y[j] */ f_min = f_max = 0.0; for (k = nb+1; k <= len; k++) { j = ind[k]; /* both bounds must be finite */ if (lpx_get_col_type(lp, j) != LPX_DB) return 0; if (val[k] > 0.0) { f_min += val[k] * lpx_get_col_lb(lp, j); f_max += val[k] * lpx_get_col_ub(lp, j); } else { f_min += val[k] * lpx_get_col_ub(lp, j); f_max += val[k] * lpx_get_col_lb(lp, j); } } /* sum a[j]*x[j] + sum a[j]*y[j] <= b ===> sum a[j]*x[j] + (sum a[j]*y[j] - f_min) <= b - f_min ===> sum a[j]*x[j] + y <= b - f_min, where y = sum a[j]*y[j] - f_min; note that 0 <= y <= u, u = f_max - f_min */ /* determine upper bound of y */ u = f_max - f_min; /* determine value of y at the current point */ y = 0.0; for (k = nb+1; k <= len; k++) { j = ind[k]; y += val[k] * lpx_get_col_prim(lp, j); } y -= f_min; if (y < 0.0) y = 0.0; if (y > u) y = u; /* modify the right-hand side b */ val[0] -= f_min; /* now the transformed row has the form: sum a[j]*x[j] + y <= b, where 0 <= y <= u */ /* determine values of x[j] at the current point */ for (k = 1; k <= nb; k++) { j = ind[k]; x[k] = lpx_get_col_prim(lp, j); if (x[k] < 0.0) x[k] = 0.0; if (x[k] > 1.0) x[k] = 1.0; } /* if a[j] < 0, replace x[j] by its complement 1 - x'[j] */ for (k = 1; k <= nb; k++) { if (val[k] < 0.0) { ind[k] = - ind[k]; val[k] = - val[k]; val[0] += val[k]; x[k] = 1.0 - x[k]; } } /* try to generate a mixed cover cut for the transformed row */ r = cover(nb, val, val[0], u, x, y, cov, &alfa, &beta); if (r == 0) return 0; xassert(2 <= r && r <= 4); /* now the cut is in the form: sum{j in C} x[j] + alfa * y <= beta */ /* store the right-hand side beta */ ind[0] = 0, val[0] = beta; /* restore the original ordinal numbers of x[j] */ for (j = 1; j <= r; j++) cov[j] = ind[cov[j]]; /* store cut coefficients at binary variables complementing back the variables having negative row coefficients */ xassert(r <= nb); for (k = 1; k <= r; k++) { if (cov[k] > 0) { ind[k] = +cov[k]; val[k] = +1.0; } else { ind[k] = -cov[k]; val[k] = -1.0; val[0] -= 1.0; } } /* substitute y = sum a[j]*y[j] - f_min */ for (k = nb+1; k <= len; k++) { r++; ind[r] = ind[k]; val[r] = alfa * val[k]; } val[0] += alfa * f_min; xassert(r <= len); len = r; return len; } /*---------------------------------------------------------------------- -- lpx_eval_row - compute explictily specified row. -- -- SYNOPSIS -- -- #include "glplpx.h" -- double lpx_eval_row(LPX *lp, int len, int ind[], double val[]); -- -- DESCRIPTION -- -- The routine lpx_eval_row computes the primal value of an explicitly -- specified row using current values of structural variables. -- -- The explicitly specified row may be thought as a linear form: -- -- y = a[1]*x[m+1] + a[2]*x[m+2] + ... + a[n]*x[m+n], -- -- where y is an auxiliary variable for this row, a[j] are coefficients -- of the linear form, x[m+j] are structural variables. -- -- On entry column indices and numerical values of non-zero elements of -- the row should be stored in locations ind[1], ..., ind[len] and -- val[1], ..., val[len], where len is the number of non-zero elements. -- The array ind and val are not changed on exit. -- -- RETURNS -- -- The routine returns a computed value of y, the auxiliary variable of -- the specified row. */ static double lpx_eval_row(LPX *lp, int len, int ind[], double val[]) { int n = lpx_get_num_cols(lp); int j, k; double sum = 0.0; if (len < 0) xerror("lpx_eval_row: len = %d; invalid row length\n", len); for (k = 1; k <= len; k++) { j = ind[k]; if (!(1 <= j && j <= n)) xerror("lpx_eval_row: j = %d; column number out of range\n", j); sum += val[k] * lpx_get_col_prim(lp, j); } return sum; } /*********************************************************************** * NAME * * ios_cov_gen - generate mixed cover cuts * * SYNOPSIS * * #include "glpios.h" * void ios_cov_gen(glp_tree *tree); * * DESCRIPTION * * The routine ios_cov_gen generates mixed cover cuts for the current * point and adds them to the cut pool. */ void ios_cov_gen(glp_tree *tree) { glp_prob *prob = tree->mip; int m = lpx_get_num_rows(prob); int n = lpx_get_num_cols(prob); int i, k, type, kase, len, *ind; double r, *val, *work; xassert(lpx_get_status(prob) == LPX_OPT); /* allocate working arrays */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); work = xcalloc(1+n, sizeof(double)); /* look through all rows */ for (i = 1; i <= m; i++) for (kase = 1; kase <= 2; kase++) { type = lpx_get_row_type(prob, i); if (kase == 1) { /* consider rows of '<=' type */ if (!(type == LPX_UP || type == LPX_DB)) continue; len = lpx_get_mat_row(prob, i, ind, val); val[0] = lpx_get_row_ub(prob, i); } else { /* consider rows of '>=' type */ if (!(type == LPX_LO || type == LPX_DB)) continue; len = lpx_get_mat_row(prob, i, ind, val); for (k = 1; k <= len; k++) val[k] = - val[k]; val[0] = - lpx_get_row_lb(prob, i); } /* generate mixed cover cut: sum{j in J} a[j] * x[j] <= b */ len = lpx_cover_cut(prob, len, ind, val, work); if (len == 0) continue; /* at the current point the cut inequality is violated, i.e. sum{j in J} a[j] * x[j] - b > 0 */ r = lpx_eval_row(prob, len, ind, val) - val[0]; if (r < 1e-3) continue; /* add the cut to the cut pool */ glp_ios_add_row(tree, NULL, GLP_RF_COV, 0, len, ind, val, GLP_UP, val[0]); } /* free working arrays */ xfree(ind); xfree(val); xfree(work); return; } /* eof */ glpk-4.52.1/src/glpios08.c0000644000062000006210000001043312175147600014322 0ustar maomkpasswd/* glpios08.c (clique cut generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2008, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "cfg.h" #include "glpios.h" void *ios_clq_init(glp_tree *T) { /* initialize clique cut generator */ glp_prob *P = T->mip; CFG *G; int j, n1, n2; xprintf("Constructing conflict graph...\n"); G = cfg_build_graph(P); n1 = n2 = 0; for (j = 1; j <= P->n; j++) { if (G->pos[j]) n1 ++; if (G->neg[j]) n2++; } if (n1 == 0 && n2 == 0) { xprintf("No conflicts found\n"); cfg_delete_graph(G); G = NULL; } else xprintf("Conflict graph has %d + %d = %d vertices\n", n1, n2, G->nv); return G; } void ios_clq_gen(glp_tree *T, void *G_) { /* attempt to generate clique cut */ glp_prob *P = T->mip; int n = P->n; CFG *G = G_; int *pos = G->pos; int *neg = G->neg; int nv = G->nv; int *ref = G->ref; int j, k, v, len, *ind; double rhs, sum, *val; xassert(G->n == n); /* allocate working arrays */ ind = talloc(1+n, int); val = talloc(1+n, double); /* find maximum weight clique in conflict graph */ len = cfg_find_clique(P, G, ind, &sum); #ifdef GLP_DEBUG xprintf("len = %d; sum = %g\n", len, sum); cfg_check_clique(G, len, ind); #endif /* check if clique inequality is violated */ if (sum < 1.07) goto skip; /* expand clique to maximal one */ len = cfg_expand_clique(G, len, ind); #ifdef GLP_DEBUG xprintf("maximal clique size = %d\n", len); cfg_check_clique(G, len, ind); #endif /* construct clique cut (fixed binary variables are removed, so this cut is only locally valid) */ rhs = 1.0; for (j = 1; j <= n; j++) val[j] = 0.0; for (k = 1; k <= len; k++) { /* v is clique vertex */ v = ind[k]; xassert(1 <= v && v <= nv); /* j is number of corresponding binary variable */ j = ref[v]; xassert(1 <= j && j <= n); if (pos[j] == v) { /* v corresponds to x[j] */ if (P->col[j]->type == GLP_FX) { /* x[j] is fixed */ rhs -= P->col[j]->prim; } else { /* x[j] is not fixed */ val[j] += 1.0; } } else if (neg[j] == v) { /* v corresponds to (1 - x[j]) */ if (P->col[j]->type == GLP_FX) { /* x[j] is fixed */ rhs -= (1.0 - P->col[j]->prim); } else { /* x[j] is not fixed */ val[j] -= 1.0; rhs -= 1.0; } } else xassert(v != v); } /* convert cut inequality to sparse format */ len = 0; for (j = 1; j <= n; j++) { if (val[j] != 0.0) { len++; ind[len] = j; val[len] = val[j]; } } /* add cut inequality to local cut pool */ glp_ios_add_row(T, NULL, GLP_RF_CLQ, 0, len, ind, val, GLP_UP, rhs); skip: /* free working arrays */ tfree(ind); tfree(val); return; } void ios_clq_term(void *G_) { /* terminate clique cut generator */ CFG *G = G_; xassert(G != NULL); cfg_delete_graph(G); return; } /* eof */ glpk-4.52.1/src/glpios09.c0000644000062000006210000006324212175147600014331 0ustar maomkpasswd/* glpios09.c (branching heuristics) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * NAME * * ios_choose_var - select variable to branch on * * SYNOPSIS * * #include "glpios.h" * int ios_choose_var(glp_tree *T, int *next); * * The routine ios_choose_var chooses a variable from the candidate * list to branch on. Additionally the routine provides a flag stored * in the location next to suggests which of the child subproblems * should be solved next. * * RETURNS * * The routine ios_choose_var returns the ordinal number of the column * choosen. */ static int branch_first(glp_tree *T, int *next); static int branch_last(glp_tree *T, int *next); static int branch_mostf(glp_tree *T, int *next); static int branch_drtom(glp_tree *T, int *next); int ios_choose_var(glp_tree *T, int *next) { int j; if (T->parm->br_tech == GLP_BR_FFV) { /* branch on first fractional variable */ j = branch_first(T, next); } else if (T->parm->br_tech == GLP_BR_LFV) { /* branch on last fractional variable */ j = branch_last(T, next); } else if (T->parm->br_tech == GLP_BR_MFV) { /* branch on most fractional variable */ j = branch_mostf(T, next); } else if (T->parm->br_tech == GLP_BR_DTH) { /* branch using the heuristic by Dreebeck and Tomlin */ j = branch_drtom(T, next); } else if (T->parm->br_tech == GLP_BR_PCH) { /* hybrid pseudocost heuristic */ j = ios_pcost_branch(T, next); } else xassert(T != T); return j; } /*********************************************************************** * branch_first - choose first branching variable * * This routine looks up the list of structural variables and chooses * the first one, which is of integer kind and has fractional value in * optimal solution to the current LP relaxation. * * This routine also selects the branch to be solved next where integer * infeasibility of the chosen variable is less than in other one. */ static int branch_first(glp_tree *T, int *_next) { int j, next; double beta; /* choose the column to branch on */ for (j = 1; j <= T->n; j++) if (T->non_int[j]) break; xassert(1 <= j && j <= T->n); /* select the branch to be solved next */ beta = glp_get_col_prim(T->mip, j); if (beta - floor(beta) < ceil(beta) - beta) next = GLP_DN_BRNCH; else next = GLP_UP_BRNCH; *_next = next; return j; } /*********************************************************************** * branch_last - choose last branching variable * * This routine looks up the list of structural variables and chooses * the last one, which is of integer kind and has fractional value in * optimal solution to the current LP relaxation. * * This routine also selects the branch to be solved next where integer * infeasibility of the chosen variable is less than in other one. */ static int branch_last(glp_tree *T, int *_next) { int j, next; double beta; /* choose the column to branch on */ for (j = T->n; j >= 1; j--) if (T->non_int[j]) break; xassert(1 <= j && j <= T->n); /* select the branch to be solved next */ beta = glp_get_col_prim(T->mip, j); if (beta - floor(beta) < ceil(beta) - beta) next = GLP_DN_BRNCH; else next = GLP_UP_BRNCH; *_next = next; return j; } /*********************************************************************** * branch_mostf - choose most fractional branching variable * * This routine looks up the list of structural variables and chooses * that one, which is of integer kind and has most fractional value in * optimal solution to the current LP relaxation. * * This routine also selects the branch to be solved next where integer * infeasibility of the chosen variable is less than in other one. * * (Alexander Martin notices that "...most infeasible is as good as * random...".) */ static int branch_mostf(glp_tree *T, int *_next) { int j, jj, next; double beta, most, temp; /* choose the column to branch on */ jj = 0, most = DBL_MAX; for (j = 1; j <= T->n; j++) { if (T->non_int[j]) { beta = glp_get_col_prim(T->mip, j); temp = floor(beta) + 0.5; if (most > fabs(beta - temp)) { jj = j, most = fabs(beta - temp); if (beta < temp) next = GLP_DN_BRNCH; else next = GLP_UP_BRNCH; } } } *_next = next; return jj; } /*********************************************************************** * branch_drtom - choose branching var using Driebeck-Tomlin heuristic * * This routine chooses a structural variable, which is required to be * integral and has fractional value in optimal solution of the current * LP relaxation, using a heuristic proposed by Driebeck and Tomlin. * * The routine also selects the branch to be solved next, again due to * Driebeck and Tomlin. * * This routine is based on the heuristic proposed in: * * Driebeck N.J. An algorithm for the solution of mixed-integer * programming problems, Management Science, 12: 576-87 (1966); * * and improved in: * * Tomlin J.A. Branch and bound methods for integer and non-convex * programming, in J.Abadie (ed.), Integer and Nonlinear Programming, * North-Holland, Amsterdam, pp. 437-50 (1970). * * Must note that this heuristic is time-expensive, because computing * one-step degradation (see the routine below) requires one BTRAN for * each fractional-valued structural variable. */ static int branch_drtom(glp_tree *T, int *_next) { glp_prob *mip = T->mip; int m = mip->m; int n = mip->n; unsigned char *non_int = T->non_int; int j, jj, k, t, next, kase, len, stat, *ind; double x, dk, alfa, delta_j, delta_k, delta_z, dz_dn, dz_up, dd_dn, dd_up, degrad, *val; /* basic solution of LP relaxation must be optimal */ xassert(glp_get_status(mip) == GLP_OPT); /* allocate working arrays */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); /* nothing has been chosen so far */ jj = 0, degrad = -1.0; /* walk through the list of columns (structural variables) */ for (j = 1; j <= n; j++) { /* if j-th column is not marked as fractional, skip it */ if (!non_int[j]) continue; /* obtain (fractional) value of j-th column in basic solution of LP relaxation */ x = glp_get_col_prim(mip, j); /* since the value of j-th column is fractional, the column is basic; compute corresponding row of the simplex table */ len = glp_eval_tab_row(mip, m+j, ind, val); /* the following fragment computes a change in the objective function: delta Z = new Z - old Z, where old Z is the objective value in the current optimal basis, and new Z is the objective value in the adjacent basis, for two cases: 1) if new upper bound ub' = floor(x[j]) is introduced for j-th column (down branch); 2) if new lower bound lb' = ceil(x[j]) is introduced for j-th column (up branch); since in both cases the solution remaining dual feasible becomes primal infeasible, one implicit simplex iteration is performed to determine the change delta Z; it is obvious that new Z, which is never better than old Z, is a lower (minimization) or upper (maximization) bound of the objective function for down- and up-branches. */ for (kase = -1; kase <= +1; kase += 2) { /* if kase < 0, the new upper bound of x[j] is introduced; in this case x[j] should decrease in order to leave the basis and go to its new upper bound */ /* if kase > 0, the new lower bound of x[j] is introduced; in this case x[j] should increase in order to leave the basis and go to its new lower bound */ /* apply the dual ratio test in order to determine which auxiliary or structural variable should enter the basis to keep dual feasibility */ k = glp_dual_rtest(mip, len, ind, val, kase, 1e-9); if (k != 0) k = ind[k]; /* if no non-basic variable has been chosen, LP relaxation of corresponding branch being primal infeasible and dual unbounded has no primal feasible solution; in this case the change delta Z is formally set to infinity */ if (k == 0) { delta_z = (T->mip->dir == GLP_MIN ? +DBL_MAX : -DBL_MAX); goto skip; } /* row of the simplex table that corresponds to non-basic variable x[k] choosen by the dual ratio test is: x[j] = ... + alfa * x[k] + ... where alfa is the influence coefficient (an element of the simplex table row) */ /* determine the coefficient alfa */ for (t = 1; t <= len; t++) if (ind[t] == k) break; xassert(1 <= t && t <= len); alfa = val[t]; /* since in the adjacent basis the variable x[j] becomes non-basic, knowing its value in the current basis we can determine its change delta x[j] = new x[j] - old x[j] */ delta_j = (kase < 0 ? floor(x) : ceil(x)) - x; /* and knowing the coefficient alfa we can determine the corresponding change delta x[k] = new x[k] - old x[k], where old x[k] is a value of x[k] in the current basis, and new x[k] is a value of x[k] in the adjacent basis */ delta_k = delta_j / alfa; /* Tomlin noticed that if the variable x[k] is of integer kind, its change cannot be less (eventually) than one in the magnitude */ if (k > m && glp_get_col_kind(mip, k-m) != GLP_CV) { /* x[k] is structural integer variable */ if (fabs(delta_k - floor(delta_k + 0.5)) > 1e-3) { if (delta_k > 0.0) delta_k = ceil(delta_k); /* +3.14 -> +4 */ else delta_k = floor(delta_k); /* -3.14 -> -4 */ } } /* now determine the status and reduced cost of x[k] in the current basis */ if (k <= m) { stat = glp_get_row_stat(mip, k); dk = glp_get_row_dual(mip, k); } else { stat = glp_get_col_stat(mip, k-m); dk = glp_get_col_dual(mip, k-m); } /* if the current basis is dual degenerate, some reduced costs which are close to zero may have wrong sign due to round-off errors, so correct the sign of d[k] */ switch (T->mip->dir) { case GLP_MIN: if (stat == GLP_NL && dk < 0.0 || stat == GLP_NU && dk > 0.0 || stat == GLP_NF) dk = 0.0; break; case GLP_MAX: if (stat == GLP_NL && dk > 0.0 || stat == GLP_NU && dk < 0.0 || stat == GLP_NF) dk = 0.0; break; default: xassert(T != T); } /* now knowing the change of x[k] and its reduced cost d[k] we can compute the corresponding change in the objective function delta Z = new Z - old Z = d[k] * delta x[k]; note that due to Tomlin's modification new Z can be even worse than in the adjacent basis */ delta_z = dk * delta_k; skip: /* new Z is never better than old Z, therefore the change delta Z is always non-negative (in case of minimization) or non-positive (in case of maximization) */ switch (T->mip->dir) { case GLP_MIN: xassert(delta_z >= 0.0); break; case GLP_MAX: xassert(delta_z <= 0.0); break; default: xassert(T != T); } /* save the change in the objective fnction for down- and up-branches, respectively */ if (kase < 0) dz_dn = delta_z; else dz_up = delta_z; } /* thus, in down-branch no integer feasible solution can be better than Z + dz_dn, and in up-branch no integer feasible solution can be better than Z + dz_up, where Z is value of the objective function in the current basis */ /* following the heuristic by Driebeck and Tomlin we choose a column (i.e. structural variable) which provides largest degradation of the objective function in some of branches; besides, we select the branch with smaller degradation to be solved next and keep other branch with larger degradation in the active list hoping to minimize the number of further backtrackings */ if (degrad < fabs(dz_dn) || degrad < fabs(dz_up)) { jj = j; if (fabs(dz_dn) < fabs(dz_up)) { /* select down branch to be solved next */ next = GLP_DN_BRNCH; degrad = fabs(dz_up); } else { /* select up branch to be solved next */ next = GLP_UP_BRNCH; degrad = fabs(dz_dn); } /* save the objective changes for printing */ dd_dn = dz_dn, dd_up = dz_up; /* if down- or up-branch has no feasible solution, we does not need to consider other candidates (in principle, the corresponding branch could be pruned right now) */ if (degrad == DBL_MAX) break; } } /* free working arrays */ xfree(ind); xfree(val); /* something must be chosen */ xassert(1 <= jj && jj <= n); #if 1 /* 02/XI-2009 */ if (degrad < 1e-6 * (1.0 + 0.001 * fabs(mip->obj_val))) { jj = branch_mostf(T, &next); goto done; } #endif if (T->parm->msg_lev >= GLP_MSG_DBG) { xprintf("branch_drtom: column %d chosen to branch on\n", jj); if (fabs(dd_dn) == DBL_MAX) xprintf("branch_drtom: down-branch is infeasible\n"); else xprintf("branch_drtom: down-branch bound is %.9e\n", lpx_get_obj_val(mip) + dd_dn); if (fabs(dd_up) == DBL_MAX) xprintf("branch_drtom: up-branch is infeasible\n"); else xprintf("branch_drtom: up-branch bound is %.9e\n", lpx_get_obj_val(mip) + dd_up); } done: *_next = next; return jj; } /**********************************************************************/ struct csa { /* common storage area */ int *dn_cnt; /* int dn_cnt[1+n]; */ /* dn_cnt[j] is the number of subproblems, whose LP relaxations have been solved and which are down-branches for variable x[j]; dn_cnt[j] = 0 means the down pseudocost is uninitialized */ double *dn_sum; /* double dn_sum[1+n]; */ /* dn_sum[j] is the sum of per unit degradations of the objective over all dn_cnt[j] subproblems */ int *up_cnt; /* int up_cnt[1+n]; */ /* up_cnt[j] is the number of subproblems, whose LP relaxations have been solved and which are up-branches for variable x[j]; up_cnt[j] = 0 means the up pseudocost is uninitialized */ double *up_sum; /* double up_sum[1+n]; */ /* up_sum[j] is the sum of per unit degradations of the objective over all up_cnt[j] subproblems */ }; void *ios_pcost_init(glp_tree *tree) { /* initialize working data used on pseudocost branching */ struct csa *csa; int n = tree->n, j; csa = xmalloc(sizeof(struct csa)); csa->dn_cnt = xcalloc(1+n, sizeof(int)); csa->dn_sum = xcalloc(1+n, sizeof(double)); csa->up_cnt = xcalloc(1+n, sizeof(int)); csa->up_sum = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { csa->dn_cnt[j] = csa->up_cnt[j] = 0; csa->dn_sum[j] = csa->up_sum[j] = 0.0; } return csa; } static double eval_degrad(glp_prob *P, int j, double bnd) { /* compute degradation of the objective on fixing x[j] at given value with a limited number of dual simplex iterations */ /* this routine fixes column x[j] at specified value bnd, solves resulting LP, and returns a lower bound to degradation of the objective, degrad >= 0 */ glp_prob *lp; glp_smcp parm; int ret; double degrad; /* the current basis must be optimal */ xassert(glp_get_status(P) == GLP_OPT); /* create a copy of P */ lp = glp_create_prob(); glp_copy_prob(lp, P, 0); /* fix column x[j] at specified value */ glp_set_col_bnds(lp, j, GLP_FX, bnd, bnd); /* try to solve resulting LP */ glp_init_smcp(&parm); parm.msg_lev = GLP_MSG_OFF; parm.meth = GLP_DUAL; parm.it_lim = 30; parm.out_dly = 1000; parm.meth = GLP_DUAL; ret = glp_simplex(lp, &parm); if (ret == 0 || ret == GLP_EITLIM) { if (glp_get_prim_stat(lp) == GLP_NOFEAS) { /* resulting LP has no primal feasible solution */ degrad = DBL_MAX; } else if (glp_get_dual_stat(lp) == GLP_FEAS) { /* resulting basis is optimal or at least dual feasible, so we have the correct lower bound to degradation */ if (P->dir == GLP_MIN) degrad = lp->obj_val - P->obj_val; else if (P->dir == GLP_MAX) degrad = P->obj_val - lp->obj_val; else xassert(P != P); /* degradation cannot be negative by definition */ /* note that the lower bound to degradation may be close to zero even if its exact value is zero due to round-off errors on computing the objective value */ if (degrad < 1e-6 * (1.0 + 0.001 * fabs(P->obj_val))) degrad = 0.0; } else { /* the final basis reported by the simplex solver is dual infeasible, so we cannot determine a non-trivial lower bound to degradation */ degrad = 0.0; } } else { /* the simplex solver failed */ degrad = 0.0; } /* delete the copy of P */ glp_delete_prob(lp); return degrad; } void ios_pcost_update(glp_tree *tree) { /* update history information for pseudocost branching */ /* this routine is called every time when LP relaxation of the current subproblem has been solved to optimality with all lazy and cutting plane constraints included */ int j; double dx, dz, psi; struct csa *csa = tree->pcost; xassert(csa != NULL); xassert(tree->curr != NULL); /* if the current subproblem is the root, skip updating */ if (tree->curr->up == NULL) goto skip; /* determine branching variable x[j], which was used in the parent subproblem to create the current subproblem */ j = tree->curr->up->br_var; xassert(1 <= j && j <= tree->n); /* determine the change dx[j] = new x[j] - old x[j], where new x[j] is a value of x[j] in optimal solution to LP relaxation of the current subproblem, old x[j] is a value of x[j] in optimal solution to LP relaxation of the parent subproblem */ dx = tree->mip->col[j]->prim - tree->curr->up->br_val; xassert(dx != 0.0); /* determine corresponding change dz = new dz - old dz in the objective function value */ dz = tree->mip->obj_val - tree->curr->up->lp_obj; /* determine per unit degradation of the objective function */ psi = fabs(dz / dx); /* update history information */ if (dx < 0.0) { /* the current subproblem is down-branch */ csa->dn_cnt[j]++; csa->dn_sum[j] += psi; } else /* dx > 0.0 */ { /* the current subproblem is up-branch */ csa->up_cnt[j]++; csa->up_sum[j] += psi; } skip: return; } void ios_pcost_free(glp_tree *tree) { /* free working area used on pseudocost branching */ struct csa *csa = tree->pcost; xassert(csa != NULL); xfree(csa->dn_cnt); xfree(csa->dn_sum); xfree(csa->up_cnt); xfree(csa->up_sum); xfree(csa); tree->pcost = NULL; return; } static double eval_psi(glp_tree *T, int j, int brnch) { /* compute estimation of pseudocost of variable x[j] for down- or up-branch */ struct csa *csa = T->pcost; double beta, degrad, psi; xassert(csa != NULL); xassert(1 <= j && j <= T->n); if (brnch == GLP_DN_BRNCH) { /* down-branch */ if (csa->dn_cnt[j] == 0) { /* initialize down pseudocost */ beta = T->mip->col[j]->prim; degrad = eval_degrad(T->mip, j, floor(beta)); if (degrad == DBL_MAX) { psi = DBL_MAX; goto done; } csa->dn_cnt[j] = 1; csa->dn_sum[j] = degrad / (beta - floor(beta)); } psi = csa->dn_sum[j] / (double)csa->dn_cnt[j]; } else if (brnch == GLP_UP_BRNCH) { /* up-branch */ if (csa->up_cnt[j] == 0) { /* initialize up pseudocost */ beta = T->mip->col[j]->prim; degrad = eval_degrad(T->mip, j, ceil(beta)); if (degrad == DBL_MAX) { psi = DBL_MAX; goto done; } csa->up_cnt[j] = 1; csa->up_sum[j] = degrad / (ceil(beta) - beta); } psi = csa->up_sum[j] / (double)csa->up_cnt[j]; } else xassert(brnch != brnch); done: return psi; } static void progress(glp_tree *T) { /* display progress of pseudocost initialization */ struct csa *csa = T->pcost; int j, nv = 0, ni = 0; for (j = 1; j <= T->n; j++) { if (glp_ios_can_branch(T, j)) { nv++; if (csa->dn_cnt[j] > 0 && csa->up_cnt[j] > 0) ni++; } } xprintf("Pseudocosts initialized for %d of %d variables\n", ni, nv); return; } int ios_pcost_branch(glp_tree *T, int *_next) { /* choose branching variable with pseudocost branching */ #if 0 /* 10/VI-2013 */ glp_long t = xtime(); #else double t = xtime(); #endif int j, jjj, sel; double beta, psi, d1, d2, d, dmax; /* initialize the working arrays */ if (T->pcost == NULL) T->pcost = ios_pcost_init(T); /* nothing has been chosen so far */ jjj = 0, dmax = -1.0; /* go through the list of branching candidates */ for (j = 1; j <= T->n; j++) { if (!glp_ios_can_branch(T, j)) continue; /* determine primal value of x[j] in optimal solution to LP relaxation of the current subproblem */ beta = T->mip->col[j]->prim; /* estimate pseudocost of x[j] for down-branch */ psi = eval_psi(T, j, GLP_DN_BRNCH); if (psi == DBL_MAX) { /* down-branch has no primal feasible solution */ jjj = j, sel = GLP_DN_BRNCH; goto done; } /* estimate degradation of the objective for down-branch */ d1 = psi * (beta - floor(beta)); /* estimate pseudocost of x[j] for up-branch */ psi = eval_psi(T, j, GLP_UP_BRNCH); if (psi == DBL_MAX) { /* up-branch has no primal feasible solution */ jjj = j, sel = GLP_UP_BRNCH; goto done; } /* estimate degradation of the objective for up-branch */ d2 = psi * (ceil(beta) - beta); /* determine d = max(d1, d2) */ d = (d1 > d2 ? d1 : d2); /* choose x[j] which provides maximal estimated degradation of the objective either in down- or up-branch */ if (dmax < d) { dmax = d; jjj = j; /* continue the search from a subproblem, where degradation is less than in other one */ sel = (d1 <= d2 ? GLP_DN_BRNCH : GLP_UP_BRNCH); } /* display progress of pseudocost initialization */ if (T->parm->msg_lev >= GLP_ON) { if (xdifftime(xtime(), t) >= 10.0) { progress(T); t = xtime(); } } } if (dmax == 0.0) { /* no degradation is indicated; choose a variable having most fractional value */ jjj = branch_mostf(T, &sel); } done: *_next = sel; return jjj; } /* eof */ glpk-4.52.1/src/glpios10.c0000644000062000006210000003003412175147600014312 0ustar maomkpasswd/* glpios10.c (feasibility pump heuristic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" #include "rng.h" /*********************************************************************** * NAME * * ios_feas_pump - feasibility pump heuristic * * SYNOPSIS * * #include "glpios.h" * void ios_feas_pump(glp_tree *T); * * DESCRIPTION * * The routine ios_feas_pump is a simple implementation of the Feasi- * bility Pump heuristic. * * REFERENCES * * M.Fischetti, F.Glover, and A.Lodi. "The feasibility pump." Math. * Program., Ser. A 104, pp. 91-104 (2005). */ struct VAR { /* binary variable */ int j; /* ordinal number */ int x; /* value in the rounded solution (0 or 1) */ double d; /* sorting key */ }; static int fcmp(const void *x, const void *y) { /* comparison routine */ const struct VAR *vx = x, *vy = y; if (vx->d > vy->d) return -1; else if (vx->d < vy->d) return +1; else return 0; } void ios_feas_pump(glp_tree *T) { glp_prob *P = T->mip; int n = P->n; glp_prob *lp = NULL; struct VAR *var = NULL; RNG *rand = NULL; GLPCOL *col; glp_smcp parm; int j, k, new_x, nfail, npass, nv, ret, stalling; double dist, tol; xassert(glp_get_status(P) == GLP_OPT); /* this heuristic is applied only once on the root level */ if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done; /* determine number of binary variables */ nv = 0; for (j = 1; j <= n; j++) { col = P->col[j]; /* if x[j] is continuous, skip it */ if (col->kind == GLP_CV) continue; /* if x[j] is fixed, skip it */ if (col->type == GLP_FX) continue; /* x[j] is non-fixed integer */ xassert(col->kind == GLP_IV); if (col->type == GLP_DB && col->lb == 0.0 && col->ub == 1.0) { /* x[j] is binary */ nv++; } else { /* x[j] is general integer */ if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("FPUMP heuristic cannot be applied due to genera" "l integer variables\n"); goto done; } } /* there must be at least one binary variable */ if (nv == 0) goto done; if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Applying FPUMP heuristic...\n"); /* build the list of binary variables */ var = xcalloc(1+nv, sizeof(struct VAR)); k = 0; for (j = 1; j <= n; j++) { col = P->col[j]; if (col->kind == GLP_IV && col->type == GLP_DB) var[++k].j = j; } xassert(k == nv); /* create working problem object */ lp = glp_create_prob(); more: /* copy the original problem object to keep it intact */ glp_copy_prob(lp, P, GLP_OFF); /* we are interested to find an integer feasible solution, which is better than the best known one */ if (P->mip_stat == GLP_FEAS) { int *ind; double *val, bnd; /* add a row and make it identical to the objective row */ glp_add_rows(lp, 1); ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { ind[j] = j; val[j] = P->col[j]->coef; } glp_set_mat_row(lp, lp->m, n, ind, val); xfree(ind); xfree(val); /* introduce upper (minimization) or lower (maximization) bound to the original objective function; note that this additional constraint is not violated at the optimal point to LP relaxation */ #if 0 /* modified by xypron */ if (P->dir == GLP_MIN) { bnd = P->mip_obj - 0.10 * (1.0 + fabs(P->mip_obj)); if (bnd < P->obj_val) bnd = P->obj_val; glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); } else if (P->dir == GLP_MAX) { bnd = P->mip_obj + 0.10 * (1.0 + fabs(P->mip_obj)); if (bnd > P->obj_val) bnd = P->obj_val; glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); } else xassert(P != P); #else bnd = 0.1 * P->obj_val + 0.9 * P->mip_obj; /* xprintf("bnd = %f\n", bnd); */ if (P->dir == GLP_MIN) glp_set_row_bnds(lp, lp->m, GLP_UP, 0.0, bnd - P->c0); else if (P->dir == GLP_MAX) glp_set_row_bnds(lp, lp->m, GLP_LO, bnd - P->c0, 0.0); else xassert(P != P); #endif } /* reset pass count */ npass = 0; /* invalidate the rounded point */ for (k = 1; k <= nv; k++) var[k].x = -1; pass: /* next pass starts here */ npass++; if (T->parm->msg_lev >= GLP_MSG_ALL) xprintf("Pass %d\n", npass); /* initialize minimal distance between the basic point and the rounded one obtained during this pass */ dist = DBL_MAX; /* reset failure count (the number of succeeded iterations failed to improve the distance) */ nfail = 0; /* if it is not the first pass, perturb the last rounded point rather than construct it from the basic solution */ if (npass > 1) { double rho, temp; if (rand == NULL) rand = rng_create_rand(); for (k = 1; k <= nv; k++) { j = var[k].j; col = lp->col[j]; rho = rng_uniform(rand, -0.3, 0.7); if (rho < 0.0) rho = 0.0; temp = fabs((double)var[k].x - col->prim); if (temp + rho > 0.5) var[k].x = 1 - var[k].x; } goto skip; } loop: /* innermost loop begins here */ /* round basic solution (which is assumed primal feasible) */ stalling = 1; for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; if (col->prim < 0.5) { /* rounded value is 0 */ new_x = 0; } else { /* rounded value is 1 */ new_x = 1; } if (var[k].x != new_x) { stalling = 0; var[k].x = new_x; } } /* if the rounded point has not changed (stalling), choose and flip some its entries heuristically */ if (stalling) { /* compute d[j] = |x[j] - round(x[j])| */ for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; var[k].d = fabs(col->prim - (double)var[k].x); } /* sort the list of binary variables by descending d[j] */ qsort(&var[1], nv, sizeof(struct VAR), fcmp); /* choose and flip some rounded components */ for (k = 1; k <= nv; k++) { if (k >= 5 && var[k].d < 0.35 || k >= 10) break; var[k].x = 1 - var[k].x; } } skip: /* check if the time limit has been exhausted */ if (T->parm->tm_lim < INT_MAX && (double)(T->parm->tm_lim - 1) <= 1000.0 * xdifftime(xtime(), T->tm_beg)) goto done; /* build the objective, which is the distance between the current (basic) point and the rounded one */ lp->dir = GLP_MIN; lp->c0 = 0.0; for (j = 1; j <= n; j++) lp->col[j]->coef = 0.0; for (k = 1; k <= nv; k++) { j = var[k].j; if (var[k].x == 0) lp->col[j]->coef = +1.0; else { lp->col[j]->coef = -1.0; lp->c0 += 1.0; } } /* minimize the distance with the simplex method */ glp_init_smcp(&parm); if (T->parm->msg_lev <= GLP_MSG_ERR) parm.msg_lev = T->parm->msg_lev; else if (T->parm->msg_lev <= GLP_MSG_ALL) { parm.msg_lev = GLP_MSG_ON; parm.out_dly = 10000; } ret = glp_simplex(lp, &parm); if (ret != 0) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_simplex returned %d\n", ret); goto done; } ret = glp_get_status(lp); if (ret != GLP_OPT) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_get_status returned %d\n", ret); goto done; } if (T->parm->msg_lev >= GLP_MSG_DBG) xprintf("delta = %g\n", lp->obj_val); /* check if the basic solution is integer feasible; note that it may be so even if the minimial distance is positive */ tol = 0.3 * T->parm->tol_int; for (k = 1; k <= nv; k++) { col = lp->col[var[k].j]; if (tol < col->prim && col->prim < 1.0 - tol) break; } if (k > nv) { /* okay; the basic solution seems to be integer feasible */ double *x = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) { x[j] = lp->col[j]->prim; if (P->col[j]->kind == GLP_IV) x[j] = floor(x[j] + 0.5); } #if 1 /* modified by xypron */ /* reset direction and right-hand side of objective */ lp->c0 = P->c0; lp->dir = P->dir; /* fix integer variables */ for (k = 1; k <= nv; k++) #if 0 /* 18/VI-2013; fixed by mao * this bug causes numerical instability, because column statuses * are not changed appropriately */ { lp->col[var[k].j]->lb = x[var[k].j]; lp->col[var[k].j]->ub = x[var[k].j]; lp->col[var[k].j]->type = GLP_FX; } #else glp_set_col_bnds(lp, var[k].j, GLP_FX, x[var[k].j], 0.); #endif /* copy original objective function */ for (j = 1; j <= n; j++) lp->col[j]->coef = P->col[j]->coef; /* solve original LP and copy result */ ret = glp_simplex(lp, &parm); if (ret != 0) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_simplex returned %d\n", ret); goto done; } ret = glp_get_status(lp); if (ret != GLP_OPT) { if (T->parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: glp_get_status returned %d\n", ret); goto done; } for (j = 1; j <= n; j++) if (P->col[j]->kind != GLP_IV) x[j] = lp->col[j]->prim; #endif ret = glp_ios_heur_sol(T, x); xfree(x); if (ret == 0) { /* the integer solution is accepted */ if (ios_is_hopeful(T, T->curr->bound)) { /* it is reasonable to apply the heuristic once again */ goto more; } else { /* the best known integer feasible solution just found is close to optimal solution to LP relaxation */ goto done; } } } /* the basic solution is fractional */ if (dist == DBL_MAX || lp->obj_val <= dist - 1e-6 * (1.0 + dist)) { /* the distance is reducing */ nfail = 0, dist = lp->obj_val; } else { /* improving the distance failed */ nfail++; } if (nfail < 3) goto loop; if (npass < 5) goto pass; done: /* delete working objects */ if (lp != NULL) glp_delete_prob(lp); if (var != NULL) xfree(var); if (rand != NULL) rng_delete_rand(rand); return; } /* eof */ glpk-4.52.1/src/glpios11.c0000644000062000006210000002473212175147600014323 0ustar maomkpasswd/* glpios11.c (process cuts stored in the local cut pool) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * NAME * * ios_process_cuts - process cuts stored in the local cut pool * * SYNOPSIS * * #include "glpios.h" * void ios_process_cuts(glp_tree *T); * * DESCRIPTION * * The routine ios_process_cuts analyzes each cut currently stored in * the local cut pool, which must be non-empty, and either adds the cut * to the current subproblem or just discards it. All cuts are assumed * to be locally valid. On exit the local cut pool remains unchanged. * * REFERENCES * * 1. E.Balas, S.Ceria, G.Cornuejols, "Mixed 0-1 Programming by * Lift-and-Project in a Branch-and-Cut Framework", Management Sc., * 42 (1996) 1229-1246. * * 2. G.Andreello, A.Caprara, and M.Fischetti, "Embedding Cuts in * a Branch&Cut Framework: a Computational Study with {0,1/2}-Cuts", * Preliminary Draft, October 28, 2003, pp.6-8. */ struct info { /* estimated cut efficiency */ IOSCUT *cut; /* pointer to cut in the cut pool */ char flag; /* if this flag is set, the cut is included into the current subproblem */ double eff; /* cut efficacy (normalized residual) */ double deg; /* lower bound to objective degradation */ }; static int fcmp(const void *arg1, const void *arg2) { const struct info *info1 = arg1, *info2 = arg2; if (info1->deg == 0.0 && info2->deg == 0.0) { if (info1->eff > info2->eff) return -1; if (info1->eff < info2->eff) return +1; } else { if (info1->deg > info2->deg) return -1; if (info1->deg < info2->deg) return +1; } return 0; } static double parallel(IOSCUT *a, IOSCUT *b, double work[]); void ios_process_cuts(glp_tree *T) { IOSPOOL *pool; IOSCUT *cut; IOSAIJ *aij; struct info *info; int k, kk, max_cuts, len, ret, *ind; double *val, *work; /* the current subproblem must exist */ xassert(T->curr != NULL); /* the pool must exist and be non-empty */ pool = T->local; xassert(pool != NULL); xassert(pool->size > 0); /* allocate working arrays */ info = xcalloc(1+pool->size, sizeof(struct info)); ind = xcalloc(1+T->n, sizeof(int)); val = xcalloc(1+T->n, sizeof(double)); work = xcalloc(1+T->n, sizeof(double)); for (k = 1; k <= T->n; k++) work[k] = 0.0; /* build the list of cuts stored in the cut pool */ for (k = 0, cut = pool->head; cut != NULL; cut = cut->next) k++, info[k].cut = cut, info[k].flag = 0; xassert(k == pool->size); /* estimate efficiency of all cuts in the cut pool */ for (k = 1; k <= pool->size; k++) { double temp, dy, dz; cut = info[k].cut; /* build the vector of cut coefficients and compute its Euclidean norm */ len = 0; temp = 0.0; for (aij = cut->ptr; aij != NULL; aij = aij->next) { xassert(1 <= aij->j && aij->j <= T->n); len++, ind[len] = aij->j, val[len] = aij->val; temp += aij->val * aij->val; } if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; /* transform the cut to express it only through non-basic (auxiliary and structural) variables */ len = glp_transform_row(T->mip, len, ind, val); /* determine change in the cut value and in the objective value for the adjacent basis by simulating one step of the dual simplex */ ret = _glp_analyze_row(T->mip, len, ind, val, cut->type, cut->rhs, 1e-9, NULL, NULL, NULL, NULL, &dy, &dz); /* determine normalized residual and lower bound to objective degradation */ if (ret == 0) { info[k].eff = fabs(dy) / sqrt(temp); /* if some reduced costs violates (slightly) their zero bounds (i.e. have wrong signs) due to round-off errors, dz also may have wrong sign being close to zero */ if (T->mip->dir == GLP_MIN) { if (dz < 0.0) dz = 0.0; info[k].deg = + dz; } else /* GLP_MAX */ { if (dz > 0.0) dz = 0.0; info[k].deg = - dz; } } else if (ret == 1) { /* the constraint is not violated at the current point */ info[k].eff = info[k].deg = 0.0; } else if (ret == 2) { /* no dual feasible adjacent basis exists */ info[k].eff = 1.0; info[k].deg = DBL_MAX; } else xassert(ret != ret); /* if the degradation is too small, just ignore it */ if (info[k].deg < 0.01) info[k].deg = 0.0; } /* sort the list of cuts by decreasing objective degradation and then by decreasing efficacy */ qsort(&info[1], pool->size, sizeof(struct info), fcmp); /* only first (most efficient) max_cuts in the list are qualified as candidates to be added to the current subproblem */ max_cuts = (T->curr->level == 0 ? 90 : 10); if (max_cuts > pool->size) max_cuts = pool->size; /* add cuts to the current subproblem */ #if 0 xprintf("*** adding cuts ***\n"); #endif for (k = 1; k <= max_cuts; k++) { int i, len; /* if this cut seems to be inefficient, skip it */ if (info[k].deg < 0.01 && info[k].eff < 0.01) continue; /* if the angle between this cut and every other cut included in the current subproblem is small, skip this cut */ for (kk = 1; kk < k; kk++) { if (info[kk].flag) { if (parallel(info[k].cut, info[kk].cut, work) > 0.90) break; } } if (kk < k) continue; /* add this cut to the current subproblem */ #if 0 xprintf("eff = %g; deg = %g\n", info[k].eff, info[k].deg); #endif cut = info[k].cut, info[k].flag = 1; i = glp_add_rows(T->mip, 1); if (cut->name != NULL) glp_set_row_name(T->mip, i, cut->name); xassert(T->mip->row[i]->origin == GLP_RF_CUT); T->mip->row[i]->klass = cut->klass; len = 0; for (aij = cut->ptr; aij != NULL; aij = aij->next) len++, ind[len] = aij->j, val[len] = aij->val; glp_set_mat_row(T->mip, i, len, ind, val); xassert(cut->type == GLP_LO || cut->type == GLP_UP); glp_set_row_bnds(T->mip, i, cut->type, cut->rhs, cut->rhs); } /* free working arrays */ xfree(info); xfree(ind); xfree(val); xfree(work); return; } #if 0 /*********************************************************************** * Given a cut a * x >= b (<= b) the routine efficacy computes the cut * efficacy as follows: * * eff = d * (a * x~ - b) / ||a||, * * where d is -1 (in case of '>= b') or +1 (in case of '<= b'), x~ is * the vector of values of structural variables in optimal solution to * LP relaxation of the current subproblem, ||a|| is the Euclidean norm * of the vector of cut coefficients. * * If the cut is violated at point x~, the efficacy eff is positive, * and its value is the Euclidean distance between x~ and the cut plane * a * x = b in the space of structural variables. * * Following geometrical intuition, it is quite natural to consider * this distance as a first-order measure of the expected efficacy of * the cut: the larger the distance the better the cut [1]. */ static double efficacy(glp_tree *T, IOSCUT *cut) { glp_prob *mip = T->mip; IOSAIJ *aij; double s = 0.0, t = 0.0, temp; for (aij = cut->ptr; aij != NULL; aij = aij->next) { xassert(1 <= aij->j && aij->j <= mip->n); s += aij->val * mip->col[aij->j]->prim; t += aij->val * aij->val; } temp = sqrt(t); if (temp < DBL_EPSILON) temp = DBL_EPSILON; if (cut->type == GLP_LO) temp = (s >= cut->rhs ? 0.0 : (cut->rhs - s) / temp); else if (cut->type == GLP_UP) temp = (s <= cut->rhs ? 0.0 : (s - cut->rhs) / temp); else xassert(cut != cut); return temp; } #endif /*********************************************************************** * Given two cuts a1 * x >= b1 (<= b1) and a2 * x >= b2 (<= b2) the * routine parallel computes the cosine of angle between the cut planes * a1 * x = b1 and a2 * x = b2 (which is the acute angle between two * normals to these planes) in the space of structural variables as * follows: * * cos phi = (a1' * a2) / (||a1|| * ||a2||), * * where (a1' * a2) is a dot product of vectors of cut coefficients, * ||a1|| and ||a2|| are Euclidean norms of vectors a1 and a2. * * Note that requirement cos phi = 0 forces the cuts to be orthogonal, * i.e. with disjoint support, while requirement cos phi <= 0.999 means * only avoiding duplicate (parallel) cuts [1]. */ static double parallel(IOSCUT *a, IOSCUT *b, double work[]) { IOSAIJ *aij; double s = 0.0, sa = 0.0, sb = 0.0, temp; for (aij = a->ptr; aij != NULL; aij = aij->next) { work[aij->j] = aij->val; sa += aij->val * aij->val; } for (aij = b->ptr; aij != NULL; aij = aij->next) { s += work[aij->j] * aij->val; sb += aij->val * aij->val; } for (aij = a->ptr; aij != NULL; aij = aij->next) work[aij->j] = 0.0; temp = sqrt(sa) * sqrt(sb); if (temp < DBL_EPSILON * DBL_EPSILON) temp = DBL_EPSILON; return s / temp; } /* eof */ glpk-4.52.1/src/glpios12.c0000644000062000006210000001327412175147600014323 0ustar maomkpasswd/* glpios12.c (node selection heuristics) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpios.h" /*********************************************************************** * NAME * * ios_choose_node - select subproblem to continue the search * * SYNOPSIS * * #include "glpios.h" * int ios_choose_node(glp_tree *T); * * DESCRIPTION * * The routine ios_choose_node selects a subproblem from the active * list to continue the search. The choice depends on the backtracking * technique option. * * RETURNS * * The routine ios_choose_node return the reference number of the * subproblem selected. */ static int most_feas(glp_tree *T); static int best_proj(glp_tree *T); static int best_node(glp_tree *T); int ios_choose_node(glp_tree *T) { int p; if (T->parm->bt_tech == GLP_BT_DFS) { /* depth first search */ xassert(T->tail != NULL); p = T->tail->p; } else if (T->parm->bt_tech == GLP_BT_BFS) { /* breadth first search */ xassert(T->head != NULL); p = T->head->p; } else if (T->parm->bt_tech == GLP_BT_BLB) { /* select node with best local bound */ p = best_node(T); } else if (T->parm->bt_tech == GLP_BT_BPH) { if (T->mip->mip_stat == GLP_UNDEF) { /* "most integer feasible" subproblem */ p = most_feas(T); } else { /* best projection heuristic */ p = best_proj(T); } } else xassert(T != T); return p; } static int most_feas(glp_tree *T) { /* select subproblem whose parent has minimal sum of integer infeasibilities */ IOSNPD *node; int p; double best; p = 0, best = DBL_MAX; for (node = T->head; node != NULL; node = node->next) { xassert(node->up != NULL); if (best > node->up->ii_sum) p = node->p, best = node->up->ii_sum; } return p; } static int best_proj(glp_tree *T) { /* select subproblem using the best projection heuristic */ IOSNPD *root, *node; int p; double best, deg, obj; /* the global bound must exist */ xassert(T->mip->mip_stat == GLP_FEAS); /* obtain pointer to the root node, which must exist */ root = T->slot[1].node; xassert(root != NULL); /* deg estimates degradation of the objective function per unit of the sum of integer infeasibilities */ xassert(root->ii_sum > 0.0); deg = (T->mip->mip_obj - root->bound) / root->ii_sum; /* nothing has been selected so far */ p = 0, best = DBL_MAX; /* walk through the list of active subproblems */ for (node = T->head; node != NULL; node = node->next) { xassert(node->up != NULL); /* obj estimates optimal objective value if the sum of integer infeasibilities were zero */ obj = node->up->bound + deg * node->up->ii_sum; if (T->mip->dir == GLP_MAX) obj = - obj; /* select the subproblem which has the best estimated optimal objective value */ if (best > obj) p = node->p, best = obj; } return p; } static int best_node(glp_tree *T) { /* select subproblem with best local bound */ IOSNPD *node, *best = NULL; double bound, eps; switch (T->mip->dir) { case GLP_MIN: bound = +DBL_MAX; for (node = T->head; node != NULL; node = node->next) if (bound > node->bound) bound = node->bound; xassert(bound != +DBL_MAX); eps = 1e-10 * (1.0 + fabs(bound)); for (node = T->head; node != NULL; node = node->next) { if (node->bound <= bound + eps) { xassert(node->up != NULL); if (best == NULL || #if 1 best->up->ii_sum > node->up->ii_sum) best = node; #else best->lp_obj > node->lp_obj) best = node; #endif } } break; case GLP_MAX: bound = -DBL_MAX; for (node = T->head; node != NULL; node = node->next) if (bound < node->bound) bound = node->bound; xassert(bound != -DBL_MAX); eps = 1e-10 * (1.0 + fabs(bound)); for (node = T->head; node != NULL; node = node->next) { if (node->bound >= bound - eps) { xassert(node->up != NULL); if (best == NULL || #if 1 best->up->ii_sum > node->up->ii_sum) best = node; #else best->lp_obj < node->lp_obj) best = node; #endif } } break; default: xassert(T != T); } xassert(best != NULL); return best->p; } /* eof */ glpk-4.52.1/src/glpipm.c0000644000062000006210000011412312175147600014146 0ustar maomkpasswd/* glpipm.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpipm.h" #include "glpmat.h" #define ITER_MAX 100 /* maximal number of iterations */ struct csa { /* common storage area */ /*--------------------------------------------------------------*/ /* LP data */ int m; /* number of rows (equality constraints) */ int n; /* number of columns (structural variables) */ int *A_ptr; /* int A_ptr[1+m+1]; */ int *A_ind; /* int A_ind[A_ptr[m+1]]; */ double *A_val; /* double A_val[A_ptr[m+1]]; */ /* mxn-matrix A in storage-by-rows format */ double *b; /* double b[1+m]; */ /* m-vector b of right-hand sides */ double *c; /* double c[1+n]; */ /* n-vector c of objective coefficients; c[0] is constant term of the objective function */ /*--------------------------------------------------------------*/ /* LP solution */ double *x; /* double x[1+n]; */ double *y; /* double y[1+m]; */ double *z; /* double z[1+n]; */ /* current point in primal-dual space; the best point on exit */ /*--------------------------------------------------------------*/ /* control parameters */ const glp_iptcp *parm; /*--------------------------------------------------------------*/ /* working arrays and variables */ double *D; /* double D[1+n]; */ /* diagonal nxn-matrix D = X*inv(Z), where X = diag(x[j]) and Z = diag(z[j]) */ int *P; /* int P[1+m+m]; */ /* permutation mxm-matrix P used to minimize fill-in in Cholesky factorization */ int *S_ptr; /* int S_ptr[1+m+1]; */ int *S_ind; /* int S_ind[S_ptr[m+1]]; */ double *S_val; /* double S_val[S_ptr[m+1]]; */ double *S_diag; /* double S_diag[1+m]; */ /* symmetric mxm-matrix S = P*A*D*A'*P' whose upper triangular part without diagonal elements is stored in S_ptr, S_ind, and S_val in storage-by-rows format, diagonal elements are stored in S_diag */ int *U_ptr; /* int U_ptr[1+m+1]; */ int *U_ind; /* int U_ind[U_ptr[m+1]]; */ double *U_val; /* double U_val[U_ptr[m+1]]; */ double *U_diag; /* double U_diag[1+m]; */ /* upper triangular mxm-matrix U defining Cholesky factorization S = U'*U; its non-diagonal elements are stored in U_ptr, U_ind, U_val in storage-by-rows format, diagonal elements are stored in U_diag */ int iter; /* iteration number (0, 1, 2, ...); iter = 0 corresponds to the initial point */ double obj; /* current value of the objective function */ double rpi; /* relative primal infeasibility rpi = ||A*x-b||/(1+||b||) */ double rdi; /* relative dual infeasibility rdi = ||A'*y+z-c||/(1+||c||) */ double gap; /* primal-dual gap = |c'*x-b'*y|/(1+|c'*x|) which is a relative difference between primal and dual objective functions */ double phi; /* merit function phi = ||A*x-b||/max(1,||b||) + + ||A'*y+z-c||/max(1,||c||) + + |c'*x-b'*y|/max(1,||b||,||c||) */ double mu; /* duality measure mu = x'*z/n (used as barrier parameter) */ double rmu; /* rmu = max(||A*x-b||,||A'*y+z-c||)/mu */ double rmu0; /* the initial value of rmu on iteration 0 */ double *phi_min; /* double phi_min[1+ITER_MAX]; */ /* phi_min[k] = min(phi[k]), where phi[k] is the value of phi on k-th iteration, 0 <= k <= iter */ int best_iter; /* iteration number, on which the value of phi reached its best (minimal) value */ double *best_x; /* double best_x[1+n]; */ double *best_y; /* double best_y[1+m]; */ double *best_z; /* double best_z[1+n]; */ /* best point (in the sense of the merit function phi) which has been reached on iteration iter_best */ double best_obj; /* objective value at the best point */ double *dx_aff; /* double dx_aff[1+n]; */ double *dy_aff; /* double dy_aff[1+m]; */ double *dz_aff; /* double dz_aff[1+n]; */ /* affine scaling direction */ double alfa_aff_p, alfa_aff_d; /* maximal primal and dual stepsizes in affine scaling direction, on which x and z are still non-negative */ double mu_aff; /* duality measure mu_aff = x_aff'*z_aff/n in the boundary point x_aff' = x+alfa_aff_p*dx_aff, z_aff' = z+alfa_aff_d*dz_aff */ double sigma; /* Mehrotra's heuristic parameter (0 <= sigma <= 1) */ double *dx_cc; /* double dx_cc[1+n]; */ double *dy_cc; /* double dy_cc[1+m]; */ double *dz_cc; /* double dz_cc[1+n]; */ /* centering corrector direction */ double *dx; /* double dx[1+n]; */ double *dy; /* double dy[1+m]; */ double *dz; /* double dz[1+n]; */ /* final combined direction dx = dx_aff+dx_cc, dy = dy_aff+dy_cc, dz = dz_aff+dz_cc */ double alfa_max_p; double alfa_max_d; /* maximal primal and dual stepsizes in combined direction, on which x and z are still non-negative */ }; /*********************************************************************** * initialize - allocate and initialize common storage area * * This routine allocates and initializes the common storage area (CSA) * used by interior-point method routines. */ static void initialize(struct csa *csa) { int m = csa->m; int n = csa->n; int i; if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Matrix A has %d non-zeros\n", csa->A_ptr[m+1]-1); csa->D = xcalloc(1+n, sizeof(double)); /* P := I */ csa->P = xcalloc(1+m+m, sizeof(int)); for (i = 1; i <= m; i++) csa->P[i] = csa->P[m+i] = i; /* S := A*A', symbolically */ csa->S_ptr = xcalloc(1+m+1, sizeof(int)); csa->S_ind = adat_symbolic(m, n, csa->P, csa->A_ptr, csa->A_ind, csa->S_ptr); if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Matrix S = A*A' has %d non-zeros (upper triangle)\n", csa->S_ptr[m+1]-1 + m); /* determine P using specified ordering algorithm */ if (csa->parm->ord_alg == GLP_ORD_NONE) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Original ordering is being used\n"); for (i = 1; i <= m; i++) csa->P[i] = csa->P[m+i] = i; } else if (csa->parm->ord_alg == GLP_ORD_QMD) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Minimum degree ordering (QMD)...\n"); min_degree(m, csa->S_ptr, csa->S_ind, csa->P); } else if (csa->parm->ord_alg == GLP_ORD_AMD) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Approximate minimum degree ordering (AMD)...\n"); amd_order1(m, csa->S_ptr, csa->S_ind, csa->P); } else if (csa->parm->ord_alg == GLP_ORD_SYMAMD) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Approximate minimum degree ordering (SYMAMD)...\n") ; symamd_ord(m, csa->S_ptr, csa->S_ind, csa->P); } else xassert(csa != csa); /* S := P*A*A'*P', symbolically */ xfree(csa->S_ind); csa->S_ind = adat_symbolic(m, n, csa->P, csa->A_ptr, csa->A_ind, csa->S_ptr); csa->S_val = xcalloc(csa->S_ptr[m+1], sizeof(double)); csa->S_diag = xcalloc(1+m, sizeof(double)); /* compute Cholesky factorization S = U'*U, symbolically */ if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Computing Cholesky factorization S = L*L'...\n"); csa->U_ptr = xcalloc(1+m+1, sizeof(int)); csa->U_ind = chol_symbolic(m, csa->S_ptr, csa->S_ind, csa->U_ptr); if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Matrix L has %d non-zeros\n", csa->U_ptr[m+1]-1 + m); csa->U_val = xcalloc(csa->U_ptr[m+1], sizeof(double)); csa->U_diag = xcalloc(1+m, sizeof(double)); csa->iter = 0; csa->obj = 0.0; csa->rpi = 0.0; csa->rdi = 0.0; csa->gap = 0.0; csa->phi = 0.0; csa->mu = 0.0; csa->rmu = 0.0; csa->rmu0 = 0.0; csa->phi_min = xcalloc(1+ITER_MAX, sizeof(double)); csa->best_iter = 0; csa->best_x = xcalloc(1+n, sizeof(double)); csa->best_y = xcalloc(1+m, sizeof(double)); csa->best_z = xcalloc(1+n, sizeof(double)); csa->best_obj = 0.0; csa->dx_aff = xcalloc(1+n, sizeof(double)); csa->dy_aff = xcalloc(1+m, sizeof(double)); csa->dz_aff = xcalloc(1+n, sizeof(double)); csa->alfa_aff_p = 0.0; csa->alfa_aff_d = 0.0; csa->mu_aff = 0.0; csa->sigma = 0.0; csa->dx_cc = xcalloc(1+n, sizeof(double)); csa->dy_cc = xcalloc(1+m, sizeof(double)); csa->dz_cc = xcalloc(1+n, sizeof(double)); csa->dx = csa->dx_aff; csa->dy = csa->dy_aff; csa->dz = csa->dz_aff; csa->alfa_max_p = 0.0; csa->alfa_max_d = 0.0; return; } /*********************************************************************** * A_by_vec - compute y = A*x * * This routine computes matrix-vector product y = A*x, where A is the * constraint matrix. */ static void A_by_vec(struct csa *csa, double x[], double y[]) { /* compute y = A*x */ int m = csa->m; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int i, t, beg, end; double temp; for (i = 1; i <= m; i++) { temp = 0.0; beg = A_ptr[i], end = A_ptr[i+1]; for (t = beg; t < end; t++) temp += A_val[t] * x[A_ind[t]]; y[i] = temp; } return; } /*********************************************************************** * AT_by_vec - compute y = A'*x * * This routine computes matrix-vector product y = A'*x, where A' is a * matrix transposed to the constraint matrix A. */ static void AT_by_vec(struct csa *csa, double x[], double y[]) { /* compute y = A'*x, where A' is transposed to A */ int m = csa->m; int n = csa->n; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int i, j, t, beg, end; double temp; for (j = 1; j <= n; j++) y[j] = 0.0; for (i = 1; i <= m; i++) { temp = x[i]; if (temp == 0.0) continue; beg = A_ptr[i], end = A_ptr[i+1]; for (t = beg; t < end; t++) y[A_ind[t]] += A_val[t] * temp; } return; } /*********************************************************************** * decomp_NE - numeric factorization of matrix S = P*A*D*A'*P' * * This routine implements numeric phase of Cholesky factorization of * the matrix S = P*A*D*A'*P', which is a permuted matrix of the normal * equation system. Matrix D is assumed to be already computed. */ static void decomp_NE(struct csa *csa) { adat_numeric(csa->m, csa->n, csa->P, csa->A_ptr, csa->A_ind, csa->A_val, csa->D, csa->S_ptr, csa->S_ind, csa->S_val, csa->S_diag); chol_numeric(csa->m, csa->S_ptr, csa->S_ind, csa->S_val, csa->S_diag, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag); return; } /*********************************************************************** * solve_NE - solve normal equation system * * This routine solves the normal equation system: * * A*D*A'*y = h. * * It is assumed that the matrix A*D*A' has been previously factorized * by the routine decomp_NE. * * On entry the array y contains the vector of right-hand sides h. On * exit this array contains the computed vector of unknowns y. * * Once the vector y has been computed the routine checks for numeric * stability. If the residual vector: * * r = A*D*A'*y - h * * is relatively small, the routine returns zero, otherwise non-zero is * returned. */ static int solve_NE(struct csa *csa, double y[]) { int m = csa->m; int n = csa->n; int *P = csa->P; int i, j, ret = 0; double *h, *r, *w; /* save vector of right-hand sides h */ h = xcalloc(1+m, sizeof(double)); for (i = 1; i <= m; i++) h[i] = y[i]; /* solve normal equation system (A*D*A')*y = h */ /* since S = P*A*D*A'*P' = U'*U, then A*D*A' = P'*U'*U*P, so we have inv(A*D*A') = P'*inv(U)*inv(U')*P */ /* w := P*h */ w = xcalloc(1+m, sizeof(double)); for (i = 1; i <= m; i++) w[i] = y[P[i]]; /* w := inv(U')*w */ ut_solve(m, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag, w); /* w := inv(U)*w */ u_solve(m, csa->U_ptr, csa->U_ind, csa->U_val, csa->U_diag, w); /* y := P'*w */ for (i = 1; i <= m; i++) y[i] = w[P[m+i]]; xfree(w); /* compute residual vector r = A*D*A'*y - h */ r = xcalloc(1+m, sizeof(double)); /* w := A'*y */ w = xcalloc(1+n, sizeof(double)); AT_by_vec(csa, y, w); /* w := D*w */ for (j = 1; j <= n; j++) w[j] *= csa->D[j]; /* r := A*w */ A_by_vec(csa, w, r); xfree(w); /* r := r - h */ for (i = 1; i <= m; i++) r[i] -= h[i]; /* check for numeric stability */ for (i = 1; i <= m; i++) { if (fabs(r[i]) / (1.0 + fabs(h[i])) > 1e-4) { ret = 1; break; } } xfree(h); xfree(r); return ret; } /*********************************************************************** * solve_NS - solve Newtonian system * * This routine solves the Newtonian system: * * A*dx = p * * A'*dy + dz = q * * Z*dx + X*dz = r * * where X = diag(x[j]), Z = diag(z[j]), by reducing it to the normal * equation system: * * (A*inv(Z)*X*A')*dy = A*inv(Z)*(X*q-r)+p * * (it is assumed that the matrix A*inv(Z)*X*A' has been factorized by * the routine decomp_NE). * * Once vector dy has been computed the routine computes vectors dx and * dz as follows: * * dx = inv(Z)*(X*(A'*dy-q)+r) * * dz = inv(X)*(r-Z*dx) * * The routine solve_NS returns the same code which was reported by the * routine solve_NE (see above). */ static int solve_NS(struct csa *csa, double p[], double q[], double r[], double dx[], double dy[], double dz[]) { int m = csa->m; int n = csa->n; double *x = csa->x; double *z = csa->z; int i, j, ret; double *w = dx; /* compute the vector of right-hand sides A*inv(Z)*(X*q-r)+p for the normal equation system */ for (j = 1; j <= n; j++) w[j] = (x[j] * q[j] - r[j]) / z[j]; A_by_vec(csa, w, dy); for (i = 1; i <= m; i++) dy[i] += p[i]; /* solve the normal equation system to compute vector dy */ ret = solve_NE(csa, dy); /* compute vectors dx and dz */ AT_by_vec(csa, dy, dx); for (j = 1; j <= n; j++) { dx[j] = (x[j] * (dx[j] - q[j]) + r[j]) / z[j]; dz[j] = (r[j] - z[j] * dx[j]) / x[j]; } return ret; } /*********************************************************************** * initial_point - choose initial point using Mehrotra's heuristic * * This routine chooses a starting point using a heuristic proposed in * the paper: * * S. Mehrotra. On the implementation of a primal-dual interior point * method. SIAM J. on Optim., 2(4), pp. 575-601, 1992. * * The starting point x in the primal space is chosen as a solution of * the following least squares problem: * * minimize ||x|| * * subject to A*x = b * * which can be computed explicitly as follows: * * x = A'*inv(A*A')*b * * Similarly, the starting point (y, z) in the dual space is chosen as * a solution of the following least squares problem: * * minimize ||z|| * * subject to A'*y + z = c * * which can be computed explicitly as follows: * * y = inv(A*A')*A*c * * z = c - A'*y * * However, some components of the vectors x and z may be non-positive * or close to zero, so the routine uses a Mehrotra's heuristic to find * a more appropriate starting point. */ static void initial_point(struct csa *csa) { int m = csa->m; int n = csa->n; double *b = csa->b; double *c = csa->c; double *x = csa->x; double *y = csa->y; double *z = csa->z; double *D = csa->D; int i, j; double dp, dd, ex, ez, xz; /* factorize A*A' */ for (j = 1; j <= n; j++) D[j] = 1.0; decomp_NE(csa); /* x~ = A'*inv(A*A')*b */ for (i = 1; i <= m; i++) y[i] = b[i]; solve_NE(csa, y); AT_by_vec(csa, y, x); /* y~ = inv(A*A')*A*c */ A_by_vec(csa, c, y); solve_NE(csa, y); /* z~ = c - A'*y~ */ AT_by_vec(csa, y,z); for (j = 1; j <= n; j++) z[j] = c[j] - z[j]; /* use Mehrotra's heuristic in order to choose more appropriate starting point with positive components of vectors x and z */ dp = dd = 0.0; for (j = 1; j <= n; j++) { if (dp < -1.5 * x[j]) dp = -1.5 * x[j]; if (dd < -1.5 * z[j]) dd = -1.5 * z[j]; } /* note that b = 0 involves x = 0, and c = 0 involves y = 0 and z = 0, so we need to be careful */ if (dp == 0.0) dp = 1.5; if (dd == 0.0) dd = 1.5; ex = ez = xz = 0.0; for (j = 1; j <= n; j++) { ex += (x[j] + dp); ez += (z[j] + dd); xz += (x[j] + dp) * (z[j] + dd); } dp += 0.5 * (xz / ez); dd += 0.5 * (xz / ex); for (j = 1; j <= n; j++) { x[j] += dp; z[j] += dd; xassert(x[j] > 0.0 && z[j] > 0.0); } return; } /*********************************************************************** * basic_info - perform basic computations at the current point * * This routine computes the following quantities at the current point: * * 1) value of the objective function: * * F = c'*x + c[0] * * 2) relative primal infeasibility: * * rpi = ||A*x-b|| / (1+||b||) * * 3) relative dual infeasibility: * * rdi = ||A'*y+z-c|| / (1+||c||) * * 4) primal-dual gap (relative difference between the primal and the * dual objective function values): * * gap = |c'*x-b'*y| / (1+|c'*x|) * * 5) merit function: * * phi = ||A*x-b|| / max(1,||b||) + ||A'*y+z-c|| / max(1,||c||) + * * + |c'*x-b'*y| / max(1,||b||,||c||) * * 6) duality measure: * * mu = x'*z / n * * 7) the ratio of infeasibility to mu: * * rmu = max(||A*x-b||,||A'*y+z-c||) / mu * * where ||*|| denotes euclidian norm, *' denotes transposition. */ static void basic_info(struct csa *csa) { int m = csa->m; int n = csa->n; double *b = csa->b; double *c = csa->c; double *x = csa->x; double *y = csa->y; double *z = csa->z; int i, j; double norm1, bnorm, norm2, cnorm, cx, by, *work, temp; /* compute value of the objective function */ temp = c[0]; for (j = 1; j <= n; j++) temp += c[j] * x[j]; csa->obj = temp; /* norm1 = ||A*x-b|| */ work = xcalloc(1+m, sizeof(double)); A_by_vec(csa, x, work); norm1 = 0.0; for (i = 1; i <= m; i++) norm1 += (work[i] - b[i]) * (work[i] - b[i]); norm1 = sqrt(norm1); xfree(work); /* bnorm = ||b|| */ bnorm = 0.0; for (i = 1; i <= m; i++) bnorm += b[i] * b[i]; bnorm = sqrt(bnorm); /* compute relative primal infeasibility */ csa->rpi = norm1 / (1.0 + bnorm); /* norm2 = ||A'*y+z-c|| */ work = xcalloc(1+n, sizeof(double)); AT_by_vec(csa, y, work); norm2 = 0.0; for (j = 1; j <= n; j++) norm2 += (work[j] + z[j] - c[j]) * (work[j] + z[j] - c[j]); norm2 = sqrt(norm2); xfree(work); /* cnorm = ||c|| */ cnorm = 0.0; for (j = 1; j <= n; j++) cnorm += c[j] * c[j]; cnorm = sqrt(cnorm); /* compute relative dual infeasibility */ csa->rdi = norm2 / (1.0 + cnorm); /* by = b'*y */ by = 0.0; for (i = 1; i <= m; i++) by += b[i] * y[i]; /* cx = c'*x */ cx = 0.0; for (j = 1; j <= n; j++) cx += c[j] * x[j]; /* compute primal-dual gap */ csa->gap = fabs(cx - by) / (1.0 + fabs(cx)); /* compute merit function */ csa->phi = 0.0; csa->phi += norm1 / (bnorm > 1.0 ? bnorm : 1.0); csa->phi += norm2 / (cnorm > 1.0 ? cnorm : 1.0); temp = 1.0; if (temp < bnorm) temp = bnorm; if (temp < cnorm) temp = cnorm; csa->phi += fabs(cx - by) / temp; /* compute duality measure */ temp = 0.0; for (j = 1; j <= n; j++) temp += x[j] * z[j]; csa->mu = temp / (double)n; /* compute the ratio of infeasibility to mu */ csa->rmu = (norm1 > norm2 ? norm1 : norm2) / csa->mu; return; } /*********************************************************************** * make_step - compute next point using Mehrotra's technique * * This routine computes the next point using the predictor-corrector * technique proposed in the paper: * * S. Mehrotra. On the implementation of a primal-dual interior point * method. SIAM J. on Optim., 2(4), pp. 575-601, 1992. * * At first, the routine computes so called affine scaling (predictor) * direction (dx_aff,dy_aff,dz_aff) which is a solution of the system: * * A*dx_aff = b - A*x * * A'*dy_aff + dz_aff = c - A'*y - z * * Z*dx_aff + X*dz_aff = - X*Z*e * * where (x,y,z) is the current point, X = diag(x[j]), Z = diag(z[j]), * e = (1,...,1)'. * * Then, the routine computes the centering parameter sigma, using the * following Mehrotra's heuristic: * * alfa_aff_p = inf{0 <= alfa <= 1 | x+alfa*dx_aff >= 0} * * alfa_aff_d = inf{0 <= alfa <= 1 | z+alfa*dz_aff >= 0} * * mu_aff = (x+alfa_aff_p*dx_aff)'*(z+alfa_aff_d*dz_aff)/n * * sigma = (mu_aff/mu)^3 * * where alfa_aff_p is the maximal stepsize along the affine scaling * direction in the primal space, alfa_aff_d is the maximal stepsize * along the same direction in the dual space. * * After determining sigma the routine computes so called centering * (corrector) direction (dx_cc,dy_cc,dz_cc) which is the solution of * the system: * * A*dx_cc = 0 * * A'*dy_cc + dz_cc = 0 * * Z*dx_cc + X*dz_cc = sigma*mu*e - X*Z*e * * Finally, the routine computes the combined direction * * (dx,dy,dz) = (dx_aff,dy_aff,dz_aff) + (dx_cc,dy_cc,dz_cc) * * and determines maximal primal and dual stepsizes along the combined * direction: * * alfa_max_p = inf{0 <= alfa <= 1 | x+alfa*dx >= 0} * * alfa_max_d = inf{0 <= alfa <= 1 | z+alfa*dz >= 0} * * In order to prevent the next point to be too close to the boundary * of the positive ortant, the routine decreases maximal stepsizes: * * alfa_p = gamma_p * alfa_max_p * * alfa_d = gamma_d * alfa_max_d * * where gamma_p and gamma_d are scaling factors, and computes the next * point: * * x_new = x + alfa_p * dx * * y_new = y + alfa_d * dy * * z_new = z + alfa_d * dz * * which becomes the current point on the next iteration. */ static int make_step(struct csa *csa) { int m = csa->m; int n = csa->n; double *b = csa->b; double *c = csa->c; double *x = csa->x; double *y = csa->y; double *z = csa->z; double *dx_aff = csa->dx_aff; double *dy_aff = csa->dy_aff; double *dz_aff = csa->dz_aff; double *dx_cc = csa->dx_cc; double *dy_cc = csa->dy_cc; double *dz_cc = csa->dz_cc; double *dx = csa->dx; double *dy = csa->dy; double *dz = csa->dz; int i, j, ret = 0; double temp, gamma_p, gamma_d, *p, *q, *r; /* allocate working arrays */ p = xcalloc(1+m, sizeof(double)); q = xcalloc(1+n, sizeof(double)); r = xcalloc(1+n, sizeof(double)); /* p = b - A*x */ A_by_vec(csa, x, p); for (i = 1; i <= m; i++) p[i] = b[i] - p[i]; /* q = c - A'*y - z */ AT_by_vec(csa, y,q); for (j = 1; j <= n; j++) q[j] = c[j] - q[j] - z[j]; /* r = - X * Z * e */ for (j = 1; j <= n; j++) r[j] = - x[j] * z[j]; /* solve the first Newtonian system */ if (solve_NS(csa, p, q, r, dx_aff, dy_aff, dz_aff)) { ret = 1; goto done; } /* alfa_aff_p = inf{0 <= alfa <= 1 | x + alfa*dx_aff >= 0} */ /* alfa_aff_d = inf{0 <= alfa <= 1 | z + alfa*dz_aff >= 0} */ csa->alfa_aff_p = csa->alfa_aff_d = 1.0; for (j = 1; j <= n; j++) { if (dx_aff[j] < 0.0) { temp = - x[j] / dx_aff[j]; if (csa->alfa_aff_p > temp) csa->alfa_aff_p = temp; } if (dz_aff[j] < 0.0) { temp = - z[j] / dz_aff[j]; if (csa->alfa_aff_d > temp) csa->alfa_aff_d = temp; } } /* mu_aff = (x+alfa_aff_p*dx_aff)' * (z+alfa_aff_d*dz_aff) / n */ temp = 0.0; for (j = 1; j <= n; j++) temp += (x[j] + csa->alfa_aff_p * dx_aff[j]) * (z[j] + csa->alfa_aff_d * dz_aff[j]); csa->mu_aff = temp / (double)n; /* sigma = (mu_aff/mu)^3 */ temp = csa->mu_aff / csa->mu; csa->sigma = temp * temp * temp; /* p = 0 */ for (i = 1; i <= m; i++) p[i] = 0.0; /* q = 0 */ for (j = 1; j <= n; j++) q[j] = 0.0; /* r = sigma * mu * e - X * Z * e */ for (j = 1; j <= n; j++) r[j] = csa->sigma * csa->mu - dx_aff[j] * dz_aff[j]; /* solve the second Newtonian system with the same coefficients but with altered right-hand sides */ if (solve_NS(csa, p, q, r, dx_cc, dy_cc, dz_cc)) { ret = 1; goto done; } /* (dx,dy,dz) = (dx_aff,dy_aff,dz_aff) + (dx_cc,dy_cc,dz_cc) */ for (j = 1; j <= n; j++) dx[j] = dx_aff[j] + dx_cc[j]; for (i = 1; i <= m; i++) dy[i] = dy_aff[i] + dy_cc[i]; for (j = 1; j <= n; j++) dz[j] = dz_aff[j] + dz_cc[j]; /* alfa_max_p = inf{0 <= alfa <= 1 | x + alfa*dx >= 0} */ /* alfa_max_d = inf{0 <= alfa <= 1 | z + alfa*dz >= 0} */ csa->alfa_max_p = csa->alfa_max_d = 1.0; for (j = 1; j <= n; j++) { if (dx[j] < 0.0) { temp = - x[j] / dx[j]; if (csa->alfa_max_p > temp) csa->alfa_max_p = temp; } if (dz[j] < 0.0) { temp = - z[j] / dz[j]; if (csa->alfa_max_d > temp) csa->alfa_max_d = temp; } } /* determine scale factors (not implemented yet) */ gamma_p = 0.90; gamma_d = 0.90; /* compute the next point */ for (j = 1; j <= n; j++) { x[j] += gamma_p * csa->alfa_max_p * dx[j]; xassert(x[j] > 0.0); } for (i = 1; i <= m; i++) y[i] += gamma_d * csa->alfa_max_d * dy[i]; for (j = 1; j <= n; j++) { z[j] += gamma_d * csa->alfa_max_d * dz[j]; xassert(z[j] > 0.0); } done: /* free working arrays */ xfree(p); xfree(q); xfree(r); return ret; } /*********************************************************************** * terminate - deallocate common storage area * * This routine frees all memory allocated to the common storage area * used by interior-point method routines. */ static void terminate(struct csa *csa) { xfree(csa->D); xfree(csa->P); xfree(csa->S_ptr); xfree(csa->S_ind); xfree(csa->S_val); xfree(csa->S_diag); xfree(csa->U_ptr); xfree(csa->U_ind); xfree(csa->U_val); xfree(csa->U_diag); xfree(csa->phi_min); xfree(csa->best_x); xfree(csa->best_y); xfree(csa->best_z); xfree(csa->dx_aff); xfree(csa->dy_aff); xfree(csa->dz_aff); xfree(csa->dx_cc); xfree(csa->dy_cc); xfree(csa->dz_cc); return; } /*********************************************************************** * ipm_main - main interior-point method routine * * This is a main routine of the primal-dual interior-point method. * * The routine ipm_main returns one of the following codes: * * 0 - optimal solution found; * 1 - problem has no feasible (primal or dual) solution; * 2 - no convergence; * 3 - iteration limit exceeded; * 4 - numeric instability on solving Newtonian system. * * In case of non-zero return code the routine returns the best point, * which has been reached during optimization. */ static int ipm_main(struct csa *csa) { int m = csa->m; int n = csa->n; int i, j, status; double temp; /* choose initial point using Mehrotra's heuristic */ if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Guessing initial point...\n"); initial_point(csa); /* main loop starts here */ if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Optimization begins...\n"); for (;;) { /* perform basic computations at the current point */ basic_info(csa); /* save initial value of rmu */ if (csa->iter == 0) csa->rmu0 = csa->rmu; /* accumulate values of min(phi[k]) and save the best point */ xassert(csa->iter <= ITER_MAX); if (csa->iter == 0 || csa->phi_min[csa->iter-1] > csa->phi) { csa->phi_min[csa->iter] = csa->phi; csa->best_iter = csa->iter; for (j = 1; j <= n; j++) csa->best_x[j] = csa->x[j]; for (i = 1; i <= m; i++) csa->best_y[i] = csa->y[i]; for (j = 1; j <= n; j++) csa->best_z[j] = csa->z[j]; csa->best_obj = csa->obj; } else csa->phi_min[csa->iter] = csa->phi_min[csa->iter-1]; /* display information at the current point */ if (csa->parm->msg_lev >= GLP_MSG_ON) xprintf("%3d: obj = %17.9e; rpi = %8.1e; rdi = %8.1e; gap =" " %8.1e\n", csa->iter, csa->obj, csa->rpi, csa->rdi, csa->gap); /* check if the current point is optimal */ if (csa->rpi < 1e-8 && csa->rdi < 1e-8 && csa->gap < 1e-8) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("OPTIMAL SOLUTION FOUND\n"); status = 0; break; } /* check if the problem has no feasible solution */ temp = 1e5 * csa->phi_min[csa->iter]; if (temp < 1e-8) temp = 1e-8; if (csa->phi >= temp) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("PROBLEM HAS NO FEASIBLE PRIMAL/DUAL SOLUTION\n") ; status = 1; break; } /* check for very slow convergence or divergence */ if (((csa->rpi >= 1e-8 || csa->rdi >= 1e-8) && csa->rmu / csa->rmu0 >= 1e6) || (csa->iter >= 30 && csa->phi_min[csa->iter] >= 0.5 * csa->phi_min[csa->iter - 30])) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("NO CONVERGENCE; SEARCH TERMINATED\n"); status = 2; break; } /* check for maximal number of iterations */ if (csa->iter == ITER_MAX) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); status = 3; break; } /* start the next iteration */ csa->iter++; /* factorize normal equation system */ for (j = 1; j <= n; j++) csa->D[j] = csa->x[j] / csa->z[j]; decomp_NE(csa); /* compute the next point using Mehrotra's predictor-corrector technique */ if (make_step(csa)) { if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("NUMERIC INSTABILITY; SEARCH TERMINATED\n"); status = 4; break; } } /* restore the best point */ if (status != 0) { for (j = 1; j <= n; j++) csa->x[j] = csa->best_x[j]; for (i = 1; i <= m; i++) csa->y[i] = csa->best_y[i]; for (j = 1; j <= n; j++) csa->z[j] = csa->best_z[j]; if (csa->parm->msg_lev >= GLP_MSG_ALL) xprintf("Best point %17.9e was reached on iteration %d\n", csa->best_obj, csa->best_iter); } /* return to the calling program */ return status; } /*********************************************************************** * NAME * * ipm_solve - core LP solver based on the interior-point method * * SYNOPSIS * * #include "glpipm.h" * int ipm_solve(glp_prob *P, const glp_iptcp *parm); * * DESCRIPTION * * The routine ipm_solve is a core LP solver based on the primal-dual * interior-point method. * * The routine assumes the following standard formulation of LP problem * to be solved: * * minimize * * F = c[0] + c[1]*x[1] + c[2]*x[2] + ... + c[n]*x[n] * * subject to linear constraints * * a[1,1]*x[1] + a[1,2]*x[2] + ... + a[1,n]*x[n] = b[1] * * a[2,1]*x[1] + a[2,2]*x[2] + ... + a[2,n]*x[n] = b[2] * * . . . . . . * * a[m,1]*x[1] + a[m,2]*x[2] + ... + a[m,n]*x[n] = b[m] * * and non-negative variables * * x[1] >= 0, x[2] >= 0, ..., x[n] >= 0 * * where: * F is the objective function; * x[1], ..., x[n] are (structural) variables; * c[0] is a constant term of the objective function; * c[1], ..., c[n] are objective coefficients; * a[1,1], ..., a[m,n] are constraint coefficients; * b[1], ..., b[n] are right-hand sides. * * The solution is three vectors x, y, and z, which are stored by the * routine in the arrays x, y, and z, respectively. These vectors * correspond to the best primal-dual point found during optimization. * They are approximate solution of the following system (which is the * Karush-Kuhn-Tucker optimality conditions): * * A*x = b (primal feasibility condition) * * A'*y + z = c (dual feasibility condition) * * x'*z = 0 (primal-dual complementarity condition) * * x >= 0, z >= 0 (non-negativity condition) * * where: * x[1], ..., x[n] are primal (structural) variables; * y[1], ..., y[m] are dual variables (Lagrange multipliers) for * equality constraints; * z[1], ..., z[n] are dual variables (Lagrange multipliers) for * non-negativity constraints. * * RETURNS * * 0 LP has been successfully solved. * * GLP_ENOCVG * No convergence. * * GLP_EITLIM * Iteration limit exceeded. * * GLP_EINSTAB * Numeric instability on solving Newtonian system. * * In case of non-zero return code the routine returns the best point, * which has been reached during optimization. */ int ipm_solve(glp_prob *P, const glp_iptcp *parm) { struct csa _dsa, *csa = &_dsa; int m = P->m; int n = P->n; int nnz = P->nnz; GLPROW *row; GLPCOL *col; GLPAIJ *aij; int i, j, loc, ret, *A_ind, *A_ptr; double dir, *A_val, *b, *c, *x, *y, *z; xassert(m > 0); xassert(n > 0); /* allocate working arrays */ A_ptr = xcalloc(1+m+1, sizeof(int)); A_ind = xcalloc(1+nnz, sizeof(int)); A_val = xcalloc(1+nnz, sizeof(double)); b = xcalloc(1+m, sizeof(double)); c = xcalloc(1+n, sizeof(double)); x = xcalloc(1+n, sizeof(double)); y = xcalloc(1+m, sizeof(double)); z = xcalloc(1+n, sizeof(double)); /* prepare rows and constraint coefficients */ loc = 1; for (i = 1; i <= m; i++) { row = P->row[i]; xassert(row->type == GLP_FX); b[i] = row->lb * row->rii; A_ptr[i] = loc; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { A_ind[loc] = aij->col->j; A_val[loc] = row->rii * aij->val * aij->col->sjj; loc++; } } A_ptr[m+1] = loc; xassert(loc-1 == nnz); /* prepare columns and objective coefficients */ if (P->dir == GLP_MIN) dir = +1.0; else if (P->dir == GLP_MAX) dir = -1.0; else xassert(P != P); c[0] = dir * P->c0; for (j = 1; j <= n; j++) { col = P->col[j]; xassert(col->type == GLP_LO && col->lb == 0.0); c[j] = dir * col->coef * col->sjj; } /* allocate and initialize the common storage area */ csa->m = m; csa->n = n; csa->A_ptr = A_ptr; csa->A_ind = A_ind; csa->A_val = A_val; csa->b = b; csa->c = c; csa->x = x; csa->y = y; csa->z = z; csa->parm = parm; initialize(csa); /* solve LP with the interior-point method */ ret = ipm_main(csa); /* deallocate the common storage area */ terminate(csa); /* determine solution status */ if (ret == 0) { /* optimal solution found */ P->ipt_stat = GLP_OPT; ret = 0; } else if (ret == 1) { /* problem has no feasible (primal or dual) solution */ P->ipt_stat = GLP_NOFEAS; ret = 0; } else if (ret == 2) { /* no convergence */ P->ipt_stat = GLP_INFEAS; ret = GLP_ENOCVG; } else if (ret == 3) { /* iteration limit exceeded */ P->ipt_stat = GLP_INFEAS; ret = GLP_EITLIM; } else if (ret == 4) { /* numeric instability on solving Newtonian system */ P->ipt_stat = GLP_INFEAS; ret = GLP_EINSTAB; } else xassert(ret != ret); /* store row solution components */ for (i = 1; i <= m; i++) { row = P->row[i]; row->pval = row->lb; row->dval = dir * y[i] * row->rii; } /* store column solution components */ P->ipt_obj = P->c0; for (j = 1; j <= n; j++) { col = P->col[j]; col->pval = x[j] * col->sjj; col->dval = dir * z[j] / col->sjj; P->ipt_obj += col->coef * col->pval; } /* free working arrays */ xfree(A_ptr); xfree(A_ind); xfree(A_val); xfree(b); xfree(c); xfree(x); xfree(y); xfree(z); return ret; } /* eof */ glpk-4.52.1/src/glpipm.h0000644000062000006210000000247212175147600014156 0ustar maomkpasswd/* glpipm.h (primal-dual interior-point method) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPIPM_H #define GLPIPM_H #include "glpapi.h" #define ipm_solve _glp_ipm_solve int ipm_solve(glp_prob *P, const glp_iptcp *parm); /* core LP solver based on the interior-point method */ #endif /* eof */ glpk-4.52.1/src/glpk.h0000644000062000006210000010716112175147600013624 0ustar maomkpasswd/* glpk.h */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPK_H #define GLPK_H #include #include #ifdef __cplusplus extern "C" { #endif /* library version numbers: */ #define GLP_MAJOR_VERSION 4 #define GLP_MINOR_VERSION 52 typedef struct glp_prob glp_prob; /* LP/MIP problem object */ /* optimization direction flag: */ #define GLP_MIN 1 /* minimization */ #define GLP_MAX 2 /* maximization */ /* kind of structural variable: */ #define GLP_CV 1 /* continuous variable */ #define GLP_IV 2 /* integer variable */ #define GLP_BV 3 /* binary variable */ /* type of auxiliary/structural variable: */ #define GLP_FR 1 /* free (unbounded) variable */ #define GLP_LO 2 /* variable with lower bound */ #define GLP_UP 3 /* variable with upper bound */ #define GLP_DB 4 /* double-bounded variable */ #define GLP_FX 5 /* fixed variable */ /* status of auxiliary/structural variable: */ #define GLP_BS 1 /* basic variable */ #define GLP_NL 2 /* non-basic variable on lower bound */ #define GLP_NU 3 /* non-basic variable on upper bound */ #define GLP_NF 4 /* non-basic free (unbounded) variable */ #define GLP_NS 5 /* non-basic fixed variable */ /* scaling options: */ #define GLP_SF_GM 0x01 /* perform geometric mean scaling */ #define GLP_SF_EQ 0x10 /* perform equilibration scaling */ #define GLP_SF_2N 0x20 /* round scale factors to power of two */ #define GLP_SF_SKIP 0x40 /* skip if problem is well scaled */ #define GLP_SF_AUTO 0x80 /* choose scaling options automatically */ /* solution indicator: */ #define GLP_SOL 1 /* basic solution */ #define GLP_IPT 2 /* interior-point solution */ #define GLP_MIP 3 /* mixed integer solution */ /* solution status: */ #define GLP_UNDEF 1 /* solution is undefined */ #define GLP_FEAS 2 /* solution is feasible */ #define GLP_INFEAS 3 /* solution is infeasible */ #define GLP_NOFEAS 4 /* no feasible solution exists */ #define GLP_OPT 5 /* solution is optimal */ #define GLP_UNBND 6 /* solution is unbounded */ typedef struct { /* basis factorization control parameters */ int msg_lev; /* (reserved) */ int type; /* factorization type: */ #define GLP_BF_FT 1 /* LUF + Forrest-Tomlin */ #define GLP_BF_BG 2 /* LUF + Schur compl. + Bartels-Golub */ #define GLP_BF_GR 3 /* LUF + Schur compl. + Givens rotation */ int lu_size; /* luf.sv_size */ double piv_tol; /* luf.piv_tol */ int piv_lim; /* luf.piv_lim */ int suhl; /* luf.suhl */ double eps_tol; /* luf.eps_tol */ double max_gro; /* luf.max_gro */ int nfs_max; /* fhv.hh_max */ double upd_tol; /* fhv.upd_tol */ int nrs_max; /* lpf.n_max */ int rs_size; /* lpf.v_size */ double foo_bar[38]; /* (reserved) */ } glp_bfcp; typedef struct { /* simplex method control parameters */ int msg_lev; /* message level: */ #define GLP_MSG_OFF 0 /* no output */ #define GLP_MSG_ERR 1 /* warning and error messages only */ #define GLP_MSG_ON 2 /* normal output */ #define GLP_MSG_ALL 3 /* full output */ #define GLP_MSG_DBG 4 /* debug output */ int meth; /* simplex method option: */ #define GLP_PRIMAL 1 /* use primal simplex */ #define GLP_DUALP 2 /* use dual; if it fails, use primal */ #define GLP_DUAL 3 /* use dual simplex */ int pricing; /* pricing technique: */ #define GLP_PT_STD 0x11 /* standard (Dantzig rule) */ #define GLP_PT_PSE 0x22 /* projected steepest edge */ int r_test; /* ratio test technique: */ #define GLP_RT_STD 0x11 /* standard (textbook) */ #define GLP_RT_HAR 0x22 /* two-pass Harris' ratio test */ double tol_bnd; /* spx.tol_bnd */ double tol_dj; /* spx.tol_dj */ double tol_piv; /* spx.tol_piv */ double obj_ll; /* spx.obj_ll */ double obj_ul; /* spx.obj_ul */ int it_lim; /* spx.it_lim */ int tm_lim; /* spx.tm_lim (milliseconds) */ int out_frq; /* spx.out_frq */ int out_dly; /* spx.out_dly (milliseconds) */ int presolve; /* enable/disable using LP presolver */ double foo_bar[36]; /* (reserved) */ } glp_smcp; typedef struct { /* interior-point solver control parameters */ int msg_lev; /* message level (see glp_smcp) */ int ord_alg; /* ordering algorithm: */ #define GLP_ORD_NONE 0 /* natural (original) ordering */ #define GLP_ORD_QMD 1 /* quotient minimum degree (QMD) */ #define GLP_ORD_AMD 2 /* approx. minimum degree (AMD) */ #define GLP_ORD_SYMAMD 3 /* approx. minimum degree (SYMAMD) */ double foo_bar[48]; /* (reserved) */ } glp_iptcp; typedef struct glp_tree glp_tree; /* branch-and-bound tree */ typedef struct { /* integer optimizer control parameters */ int msg_lev; /* message level (see glp_smcp) */ int br_tech; /* branching technique: */ #define GLP_BR_FFV 1 /* first fractional variable */ #define GLP_BR_LFV 2 /* last fractional variable */ #define GLP_BR_MFV 3 /* most fractional variable */ #define GLP_BR_DTH 4 /* heuristic by Driebeck and Tomlin */ #define GLP_BR_PCH 5 /* hybrid pseudocost heuristic */ int bt_tech; /* backtracking technique: */ #define GLP_BT_DFS 1 /* depth first search */ #define GLP_BT_BFS 2 /* breadth first search */ #define GLP_BT_BLB 3 /* best local bound */ #define GLP_BT_BPH 4 /* best projection heuristic */ double tol_int; /* mip.tol_int */ double tol_obj; /* mip.tol_obj */ int tm_lim; /* mip.tm_lim (milliseconds) */ int out_frq; /* mip.out_frq (milliseconds) */ int out_dly; /* mip.out_dly (milliseconds) */ void (*cb_func)(glp_tree *T, void *info); /* mip.cb_func */ void *cb_info; /* mip.cb_info */ int cb_size; /* mip.cb_size */ int pp_tech; /* preprocessing technique: */ #define GLP_PP_NONE 0 /* disable preprocessing */ #define GLP_PP_ROOT 1 /* preprocessing only on root level */ #define GLP_PP_ALL 2 /* preprocessing on all levels */ double mip_gap; /* relative MIP gap tolerance */ int mir_cuts; /* MIR cuts (GLP_ON/GLP_OFF) */ int gmi_cuts; /* Gomory's cuts (GLP_ON/GLP_OFF) */ int cov_cuts; /* cover cuts (GLP_ON/GLP_OFF) */ int clq_cuts; /* clique cuts (GLP_ON/GLP_OFF) */ int presolve; /* enable/disable using MIP presolver */ int binarize; /* try to binarize integer variables */ int fp_heur; /* feasibility pump heuristic */ #if 1 /* 25/V-2013 */ int ps_heur; /* proximity search heuristic */ #endif #if 1 /* 29/VI-2013 */ int ps_tm_lim; /* proxy time limit, milliseconds */ #endif #if 1 /* 11/VII-2013 */ int use_sol; /* use existing solution */ const char *save_sol; /* filename to save every new solution */ #endif #if 1 /* 28/V-2010 */ int alien; /* use alien solver */ #endif double foo_bar[25]; /* (reserved) */ } glp_iocp; typedef struct { /* additional row attributes */ int level; /* subproblem level at which the row was added */ int origin; /* row origin flag: */ #define GLP_RF_REG 0 /* regular constraint */ #define GLP_RF_LAZY 1 /* "lazy" constraint */ #define GLP_RF_CUT 2 /* cutting plane constraint */ int klass; /* row class descriptor: */ #define GLP_RF_GMI 1 /* Gomory's mixed integer cut */ #define GLP_RF_MIR 2 /* mixed integer rounding cut */ #define GLP_RF_COV 3 /* mixed cover cut */ #define GLP_RF_CLQ 4 /* clique cut */ double foo_bar[7]; /* (reserved) */ } glp_attr; /* enable/disable flag: */ #define GLP_ON 1 /* enable something */ #define GLP_OFF 0 /* disable something */ /* reason codes: */ #define GLP_IROWGEN 0x01 /* request for row generation */ #define GLP_IBINGO 0x02 /* better integer solution found */ #define GLP_IHEUR 0x03 /* request for heuristic solution */ #define GLP_ICUTGEN 0x04 /* request for cut generation */ #define GLP_IBRANCH 0x05 /* request for branching */ #define GLP_ISELECT 0x06 /* request for subproblem selection */ #define GLP_IPREPRO 0x07 /* request for preprocessing */ /* branch selection indicator: */ #define GLP_NO_BRNCH 0 /* select no branch */ #define GLP_DN_BRNCH 1 /* select down-branch */ #define GLP_UP_BRNCH 2 /* select up-branch */ /* return codes: */ #define GLP_EBADB 0x01 /* invalid basis */ #define GLP_ESING 0x02 /* singular matrix */ #define GLP_ECOND 0x03 /* ill-conditioned matrix */ #define GLP_EBOUND 0x04 /* invalid bounds */ #define GLP_EFAIL 0x05 /* solver failed */ #define GLP_EOBJLL 0x06 /* objective lower limit reached */ #define GLP_EOBJUL 0x07 /* objective upper limit reached */ #define GLP_EITLIM 0x08 /* iteration limit exceeded */ #define GLP_ETMLIM 0x09 /* time limit exceeded */ #define GLP_ENOPFS 0x0A /* no primal feasible solution */ #define GLP_ENODFS 0x0B /* no dual feasible solution */ #define GLP_EROOT 0x0C /* root LP optimum not provided */ #define GLP_ESTOP 0x0D /* search terminated by application */ #define GLP_EMIPGAP 0x0E /* relative mip gap tolerance reached */ #define GLP_ENOFEAS 0x0F /* no primal/dual feasible solution */ #define GLP_ENOCVG 0x10 /* no convergence */ #define GLP_EINSTAB 0x11 /* numerical instability */ #define GLP_EDATA 0x12 /* invalid data */ #define GLP_ERANGE 0x13 /* result out of range */ /* condition indicator: */ #define GLP_KKT_PE 1 /* primal equalities */ #define GLP_KKT_PB 2 /* primal bounds */ #define GLP_KKT_DE 3 /* dual equalities */ #define GLP_KKT_DB 4 /* dual bounds */ #define GLP_KKT_CS 5 /* complementary slackness */ /* MPS file format: */ #define GLP_MPS_DECK 1 /* fixed (ancient) */ #define GLP_MPS_FILE 2 /* free (modern) */ typedef struct { /* MPS format control parameters */ int blank; /* character code to replace blanks in symbolic names */ char *obj_name; /* objective row name */ double tol_mps; /* zero tolerance for MPS data */ double foo_bar[17]; /* (reserved for use in the future) */ } glp_mpscp; typedef struct { /* CPLEX LP format control parameters */ double foo_bar[20]; /* (reserved for use in the future) */ } glp_cpxcp; typedef struct glp_tran glp_tran; /* MathProg translator workspace */ glp_prob *glp_create_prob(void); /* create problem object */ void glp_set_prob_name(glp_prob *P, const char *name); /* assign (change) problem name */ void glp_set_obj_name(glp_prob *P, const char *name); /* assign (change) objective function name */ void glp_set_obj_dir(glp_prob *P, int dir); /* set (change) optimization direction flag */ int glp_add_rows(glp_prob *P, int nrs); /* add new rows to problem object */ int glp_add_cols(glp_prob *P, int ncs); /* add new columns to problem object */ void glp_set_row_name(glp_prob *P, int i, const char *name); /* assign (change) row name */ void glp_set_col_name(glp_prob *P, int j, const char *name); /* assign (change) column name */ void glp_set_row_bnds(glp_prob *P, int i, int type, double lb, double ub); /* set (change) row bounds */ void glp_set_col_bnds(glp_prob *P, int j, int type, double lb, double ub); /* set (change) column bounds */ void glp_set_obj_coef(glp_prob *P, int j, double coef); /* set (change) obj. coefficient or constant term */ void glp_set_mat_row(glp_prob *P, int i, int len, const int ind[], const double val[]); /* set (replace) row of the constraint matrix */ void glp_set_mat_col(glp_prob *P, int j, int len, const int ind[], const double val[]); /* set (replace) column of the constraint matrix */ void glp_load_matrix(glp_prob *P, int ne, const int ia[], const int ja[], const double ar[]); /* load (replace) the whole constraint matrix */ int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[]); /* check for duplicate elements in sparse matrix */ void glp_sort_matrix(glp_prob *P); /* sort elements of the constraint matrix */ void glp_del_rows(glp_prob *P, int nrs, const int num[]); /* delete specified rows from problem object */ void glp_del_cols(glp_prob *P, int ncs, const int num[]); /* delete specified columns from problem object */ void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names); /* copy problem object content */ void glp_erase_prob(glp_prob *P); /* erase problem object content */ void glp_delete_prob(glp_prob *P); /* delete problem object */ const char *glp_get_prob_name(glp_prob *P); /* retrieve problem name */ const char *glp_get_obj_name(glp_prob *P); /* retrieve objective function name */ int glp_get_obj_dir(glp_prob *P); /* retrieve optimization direction flag */ int glp_get_num_rows(glp_prob *P); /* retrieve number of rows */ int glp_get_num_cols(glp_prob *P); /* retrieve number of columns */ const char *glp_get_row_name(glp_prob *P, int i); /* retrieve row name */ const char *glp_get_col_name(glp_prob *P, int j); /* retrieve column name */ int glp_get_row_type(glp_prob *P, int i); /* retrieve row type */ double glp_get_row_lb(glp_prob *P, int i); /* retrieve row lower bound */ double glp_get_row_ub(glp_prob *P, int i); /* retrieve row upper bound */ int glp_get_col_type(glp_prob *P, int j); /* retrieve column type */ double glp_get_col_lb(glp_prob *P, int j); /* retrieve column lower bound */ double glp_get_col_ub(glp_prob *P, int j); /* retrieve column upper bound */ double glp_get_obj_coef(glp_prob *P, int j); /* retrieve obj. coefficient or constant term */ int glp_get_num_nz(glp_prob *P); /* retrieve number of constraint coefficients */ int glp_get_mat_row(glp_prob *P, int i, int ind[], double val[]); /* retrieve row of the constraint matrix */ int glp_get_mat_col(glp_prob *P, int j, int ind[], double val[]); /* retrieve column of the constraint matrix */ void glp_create_index(glp_prob *P); /* create the name index */ int glp_find_row(glp_prob *P, const char *name); /* find row by its name */ int glp_find_col(glp_prob *P, const char *name); /* find column by its name */ void glp_delete_index(glp_prob *P); /* delete the name index */ void glp_set_rii(glp_prob *P, int i, double rii); /* set (change) row scale factor */ void glp_set_sjj(glp_prob *P, int j, double sjj); /* set (change) column scale factor */ double glp_get_rii(glp_prob *P, int i); /* retrieve row scale factor */ double glp_get_sjj(glp_prob *P, int j); /* retrieve column scale factor */ void glp_scale_prob(glp_prob *P, int flags); /* scale problem data */ void glp_unscale_prob(glp_prob *P); /* unscale problem data */ void glp_set_row_stat(glp_prob *P, int i, int stat); /* set (change) row status */ void glp_set_col_stat(glp_prob *P, int j, int stat); /* set (change) column status */ void glp_std_basis(glp_prob *P); /* construct standard initial LP basis */ void glp_adv_basis(glp_prob *P, int flags); /* construct advanced initial LP basis */ void glp_cpx_basis(glp_prob *P); /* construct Bixby's initial LP basis */ int glp_simplex(glp_prob *P, const glp_smcp *parm); /* solve LP problem with the simplex method */ int glp_exact(glp_prob *P, const glp_smcp *parm); /* solve LP problem in exact arithmetic */ void glp_init_smcp(glp_smcp *parm); /* initialize simplex method control parameters */ int glp_get_status(glp_prob *P); /* retrieve generic status of basic solution */ int glp_get_prim_stat(glp_prob *P); /* retrieve status of primal basic solution */ int glp_get_dual_stat(glp_prob *P); /* retrieve status of dual basic solution */ double glp_get_obj_val(glp_prob *P); /* retrieve objective value (basic solution) */ int glp_get_row_stat(glp_prob *P, int i); /* retrieve row status */ double glp_get_row_prim(glp_prob *P, int i); /* retrieve row primal value (basic solution) */ double glp_get_row_dual(glp_prob *P, int i); /* retrieve row dual value (basic solution) */ int glp_get_col_stat(glp_prob *P, int j); /* retrieve column status */ double glp_get_col_prim(glp_prob *P, int j); /* retrieve column primal value (basic solution) */ double glp_get_col_dual(glp_prob *P, int j); /* retrieve column dual value (basic solution) */ int glp_get_unbnd_ray(glp_prob *P); /* determine variable causing unboundedness */ int glp_interior(glp_prob *P, const glp_iptcp *parm); /* solve LP problem with the interior-point method */ void glp_init_iptcp(glp_iptcp *parm); /* initialize interior-point solver control parameters */ int glp_ipt_status(glp_prob *P); /* retrieve status of interior-point solution */ double glp_ipt_obj_val(glp_prob *P); /* retrieve objective value (interior point) */ double glp_ipt_row_prim(glp_prob *P, int i); /* retrieve row primal value (interior point) */ double glp_ipt_row_dual(glp_prob *P, int i); /* retrieve row dual value (interior point) */ double glp_ipt_col_prim(glp_prob *P, int j); /* retrieve column primal value (interior point) */ double glp_ipt_col_dual(glp_prob *P, int j); /* retrieve column dual value (interior point) */ void glp_set_col_kind(glp_prob *P, int j, int kind); /* set (change) column kind */ int glp_get_col_kind(glp_prob *P, int j); /* retrieve column kind */ int glp_get_num_int(glp_prob *P); /* retrieve number of integer columns */ int glp_get_num_bin(glp_prob *P); /* retrieve number of binary columns */ int glp_intopt(glp_prob *P, const glp_iocp *parm); /* solve MIP problem with the branch-and-bound method */ void glp_init_iocp(glp_iocp *parm); /* initialize integer optimizer control parameters */ int glp_mip_status(glp_prob *P); /* retrieve status of MIP solution */ double glp_mip_obj_val(glp_prob *P); /* retrieve objective value (MIP solution) */ double glp_mip_row_val(glp_prob *P, int i); /* retrieve row value (MIP solution) */ double glp_mip_col_val(glp_prob *P, int j); /* retrieve column value (MIP solution) */ void glp_check_kkt(glp_prob *P, int sol, int cond, double *ae_max, int *ae_ind, double *re_max, int *re_ind); /* check feasibility/optimality conditions */ int glp_print_sol(glp_prob *P, const char *fname); /* write basic solution in printable format */ int glp_read_sol(glp_prob *P, const char *fname); /* read basic solution from text file */ int glp_write_sol(glp_prob *P, const char *fname); /* write basic solution to text file */ int glp_print_ranges(glp_prob *P, int len, const int list[], int flags, const char *fname); /* print sensitivity analysis report */ int glp_print_ipt(glp_prob *P, const char *fname); /* write interior-point solution in printable format */ int glp_read_ipt(glp_prob *P, const char *fname); /* read interior-point solution from text file */ int glp_write_ipt(glp_prob *P, const char *fname); /* write interior-point solution to text file */ int glp_print_mip(glp_prob *P, const char *fname); /* write MIP solution in printable format */ int glp_read_mip(glp_prob *P, const char *fname); /* read MIP solution from text file */ int glp_write_mip(glp_prob *P, const char *fname); /* write MIP solution to text file */ int glp_bf_exists(glp_prob *P); /* check if the basis factorization exists */ int glp_factorize(glp_prob *P); /* compute the basis factorization */ int glp_bf_updated(glp_prob *P); /* check if the basis factorization has been updated */ void glp_get_bfcp(glp_prob *P, glp_bfcp *parm); /* retrieve basis factorization control parameters */ void glp_set_bfcp(glp_prob *P, const glp_bfcp *parm); /* change basis factorization control parameters */ int glp_get_bhead(glp_prob *P, int k); /* retrieve the basis header information */ int glp_get_row_bind(glp_prob *P, int i); /* retrieve row index in the basis header */ int glp_get_col_bind(glp_prob *P, int j); /* retrieve column index in the basis header */ void glp_ftran(glp_prob *P, double x[]); /* perform forward transformation (solve system B*x = b) */ void glp_btran(glp_prob *P, double x[]); /* perform backward transformation (solve system B'*x = b) */ int glp_warm_up(glp_prob *P); /* "warm up" LP basis */ int glp_eval_tab_row(glp_prob *P, int k, int ind[], double val[]); /* compute row of the simplex tableau */ int glp_eval_tab_col(glp_prob *P, int k, int ind[], double val[]); /* compute column of the simplex tableau */ int glp_transform_row(glp_prob *P, int len, int ind[], double val[]); /* transform explicitly specified row */ int glp_transform_col(glp_prob *P, int len, int ind[], double val[]); /* transform explicitly specified column */ int glp_prim_rtest(glp_prob *P, int len, const int ind[], const double val[], int dir, double eps); /* perform primal ratio test */ int glp_dual_rtest(glp_prob *P, int len, const int ind[], const double val[], int dir, double eps); /* perform dual ratio test */ void glp_analyze_bound(glp_prob *P, int k, double *value1, int *var1, double *value2, int *var2); /* analyze active bound of non-basic variable */ void glp_analyze_coef(glp_prob *P, int k, double *coef1, int *var1, double *value1, double *coef2, int *var2, double *value2); /* analyze objective coefficient at basic variable */ int glp_ios_reason(glp_tree *T); /* determine reason for calling the callback routine */ glp_prob *glp_ios_get_prob(glp_tree *T); /* access the problem object */ void glp_ios_tree_size(glp_tree *T, int *a_cnt, int *n_cnt, int *t_cnt); /* determine size of the branch-and-bound tree */ int glp_ios_curr_node(glp_tree *T); /* determine current active subproblem */ int glp_ios_next_node(glp_tree *T, int p); /* determine next active subproblem */ int glp_ios_prev_node(glp_tree *T, int p); /* determine previous active subproblem */ int glp_ios_up_node(glp_tree *T, int p); /* determine parent subproblem */ int glp_ios_node_level(glp_tree *T, int p); /* determine subproblem level */ double glp_ios_node_bound(glp_tree *T, int p); /* determine subproblem local bound */ int glp_ios_best_node(glp_tree *T); /* find active subproblem with best local bound */ double glp_ios_mip_gap(glp_tree *T); /* compute relative MIP gap */ void *glp_ios_node_data(glp_tree *T, int p); /* access subproblem application-specific data */ void glp_ios_row_attr(glp_tree *T, int i, glp_attr *attr); /* retrieve additional row attributes */ int glp_ios_pool_size(glp_tree *T); /* determine current size of the cut pool */ int glp_ios_add_row(glp_tree *T, const char *name, int klass, int flags, int len, const int ind[], const double val[], int type, double rhs); /* add row (constraint) to the cut pool */ void glp_ios_del_row(glp_tree *T, int i); /* remove row (constraint) from the cut pool */ void glp_ios_clear_pool(glp_tree *T); /* remove all rows (constraints) from the cut pool */ int glp_ios_can_branch(glp_tree *T, int j); /* check if can branch upon specified variable */ void glp_ios_branch_upon(glp_tree *T, int j, int sel); /* choose variable to branch upon */ void glp_ios_select_node(glp_tree *T, int p); /* select subproblem to continue the search */ int glp_ios_heur_sol(glp_tree *T, const double x[]); /* provide solution found by heuristic */ void glp_ios_terminate(glp_tree *T); /* terminate the solution process */ void glp_init_mpscp(glp_mpscp *parm); /* initialize MPS format control parameters */ int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, const char *fname); /* read problem data in MPS format */ int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, const char *fname); /* write problem data in MPS format */ void glp_init_cpxcp(glp_cpxcp *parm); /* initialize CPLEX LP format control parameters */ int glp_read_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname); /* read problem data in CPLEX LP format */ int glp_write_lp(glp_prob *P, const glp_cpxcp *parm, const char *fname); /* write problem data in CPLEX LP format */ int glp_read_prob(glp_prob *P, int flags, const char *fname); /* read problem data in GLPK format */ int glp_write_prob(glp_prob *P, int flags, const char *fname); /* write problem data in GLPK format */ glp_tran *glp_mpl_alloc_wksp(void); /* allocate the MathProg translator workspace */ int glp_mpl_read_model(glp_tran *tran, const char *fname, int skip); /* read and translate model section */ int glp_mpl_read_data(glp_tran *tran, const char *fname); /* read and translate data section */ int glp_mpl_generate(glp_tran *tran, const char *fname); /* generate the model */ void glp_mpl_build_prob(glp_tran *tran, glp_prob *prob); /* build LP/MIP problem instance from the model */ int glp_mpl_postsolve(glp_tran *tran, glp_prob *prob, int sol); /* postsolve the model */ void glp_mpl_free_wksp(glp_tran *tran); /* free the MathProg translator workspace */ int glp_main(int argc, const char *argv[]); /* stand-alone LP/MIP solver */ int glp_read_cnfsat(glp_prob *P, const char *fname); /* read CNF-SAT problem data in DIMACS format */ int glp_check_cnfsat(glp_prob *P); /* check for CNF-SAT problem instance */ int glp_write_cnfsat(glp_prob *P, const char *fname); /* write CNF-SAT problem data in DIMACS format */ int glp_minisat1(glp_prob *P); /* solve CNF-SAT problem with MiniSat solver */ int glp_intfeas1(glp_prob *P, int use_bound, int obj_bound); /* solve integer feasibility problem */ int glp_init_env(void); /* initialize GLPK environment */ const char *glp_version(void); /* determine library version */ int glp_free_env(void); /* free GLPK environment */ void glp_puts(const char *s); /* write string on terminal */ void glp_printf(const char *fmt, ...); /* write formatted output on terminal */ void glp_vprintf(const char *fmt, va_list arg); /* write formatted output on terminal */ int glp_term_out(int flag); /* enable/disable terminal output */ void glp_term_hook(int (*func)(void *info, const char *s), void *info); /* install hook to intercept terminal output */ int glp_open_tee(const char *name); /* start copying terminal output to text file */ int glp_close_tee(void); /* stop copying terminal output to text file */ #ifndef GLP_ERRFUNC_DEFINED #define GLP_ERRFUNC_DEFINED typedef void (*glp_errfunc)(const char *fmt, ...); #endif #define glp_error glp_error_(__FILE__, __LINE__) glp_errfunc glp_error_(const char *file, int line); /* display fatal error message and terminate execution */ #define glp_assert(expr) \ ((void)((expr) || (glp_assert_(#expr, __FILE__, __LINE__), 1))) void glp_assert_(const char *expr, const char *file, int line); /* check for logical condition */ void glp_error_hook(void (*func)(void *info), void *info); /* install hook to intercept abnormal termination */ #define glp_malloc(size) glp_alloc(1, size) /* allocate memory block (obsolete) */ #define glp_calloc(n, size) glp_alloc(n, size) /* allocate memory block (obsolete) */ void *glp_alloc(int n, int size); /* allocate memory block */ void *glp_realloc(void *ptr, int n, int size); /* reallocate memory block */ void glp_free(void *ptr); /* free (deallocate) memory block */ void glp_mem_limit(int limit); /* set memory usage limit */ void glp_mem_usage(int *count, int *cpeak, size_t *total, size_t *tpeak); /* get memory usage information */ typedef struct glp_graph glp_graph; typedef struct glp_vertex glp_vertex; typedef struct glp_arc glp_arc; struct glp_graph { /* graph descriptor */ void *pool; /* DMP *pool; */ /* memory pool to store graph components */ char *name; /* graph name (1 to 255 chars); NULL means no name is assigned to the graph */ int nv_max; /* length of the vertex list (enlarged automatically) */ int nv; /* number of vertices in the graph, 0 <= nv <= nv_max */ int na; /* number of arcs in the graph, na >= 0 */ glp_vertex **v; /* glp_vertex *v[1+nv_max]; */ /* v[i], 1 <= i <= nv, is a pointer to i-th vertex */ void *index; /* AVL *index; */ /* vertex index to find vertices by their names; NULL means the index does not exist */ int v_size; /* size of data associated with each vertex (0 to 256 bytes) */ int a_size; /* size of data associated with each arc (0 to 256 bytes) */ }; struct glp_vertex { /* vertex descriptor */ int i; /* vertex ordinal number, 1 <= i <= nv */ char *name; /* vertex name (1 to 255 chars); NULL means no name is assigned to the vertex */ void *entry; /* AVLNODE *entry; */ /* pointer to corresponding entry in the vertex index; NULL means that either the index does not exist or the vertex has no name assigned */ void *data; /* pointer to data associated with the vertex */ void *temp; /* working pointer */ glp_arc *in; /* pointer to the (unordered) list of incoming arcs */ glp_arc *out; /* pointer to the (unordered) list of outgoing arcs */ }; struct glp_arc { /* arc descriptor */ glp_vertex *tail; /* pointer to the tail endpoint */ glp_vertex *head; /* pointer to the head endpoint */ void *data; /* pointer to data associated with the arc */ void *temp; /* working pointer */ glp_arc *t_prev; /* pointer to previous arc having the same tail endpoint */ glp_arc *t_next; /* pointer to next arc having the same tail endpoint */ glp_arc *h_prev; /* pointer to previous arc having the same head endpoint */ glp_arc *h_next; /* pointer to next arc having the same head endpoint */ }; glp_graph *glp_create_graph(int v_size, int a_size); /* create graph */ void glp_set_graph_name(glp_graph *G, const char *name); /* assign (change) graph name */ int glp_add_vertices(glp_graph *G, int nadd); /* add new vertices to graph */ void glp_set_vertex_name(glp_graph *G, int i, const char *name); /* assign (change) vertex name */ glp_arc *glp_add_arc(glp_graph *G, int i, int j); /* add new arc to graph */ void glp_del_vertices(glp_graph *G, int ndel, const int num[]); /* delete vertices from graph */ void glp_del_arc(glp_graph *G, glp_arc *a); /* delete arc from graph */ void glp_erase_graph(glp_graph *G, int v_size, int a_size); /* erase graph content */ void glp_delete_graph(glp_graph *G); /* delete graph */ void glp_create_v_index(glp_graph *G); /* create vertex name index */ int glp_find_vertex(glp_graph *G, const char *name); /* find vertex by its name */ void glp_delete_v_index(glp_graph *G); /* delete vertex name index */ int glp_read_graph(glp_graph *G, const char *fname); /* read graph from plain text file */ int glp_write_graph(glp_graph *G, const char *fname); /* write graph to plain text file */ void glp_mincost_lp(glp_prob *P, glp_graph *G, int names, int v_rhs, int a_low, int a_cap, int a_cost); /* convert minimum cost flow problem to LP */ int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, double *sol, int a_x, int v_pi); /* find minimum-cost flow with out-of-kilter algorithm */ int glp_mincost_relax4(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, int crash, double *sol, int a_x, int a_rc); /* find minimum-cost flow with Bertsekas-Tseng relaxation method */ void glp_maxflow_lp(glp_prob *P, glp_graph *G, int names, int s, int t, int a_cap); /* convert maximum flow problem to LP */ int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap, double *sol, int a_x, int v_cut); /* find maximal flow with Ford-Fulkerson algorithm */ int glp_check_asnprob(glp_graph *G, int v_set); /* check correctness of assignment problem data */ /* assignment problem formulation: */ #define GLP_ASN_MIN 1 /* perfect matching (minimization) */ #define GLP_ASN_MAX 2 /* perfect matching (maximization) */ #define GLP_ASN_MMP 3 /* maximum matching */ int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names, int v_set, int a_cost); /* convert assignment problem to LP */ int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost, double *sol, int a_x); /* solve assignment problem with out-of-kilter algorithm */ int glp_asnprob_hall(glp_graph *G, int v_set, int a_x); /* find bipartite matching of maximum cardinality */ double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls); /* solve critical path problem */ int glp_read_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, const char *fname); /* read min-cost flow problem data in DIMACS format */ int glp_write_mincost(glp_graph *G, int v_rhs, int a_low, int a_cap, int a_cost, const char *fname); /* write min-cost flow problem data in DIMACS format */ int glp_read_maxflow(glp_graph *G, int *s, int *t, int a_cap, const char *fname); /* read maximum flow problem data in DIMACS format */ int glp_write_maxflow(glp_graph *G, int s, int t, int a_cap, const char *fname); /* write maximum flow problem data in DIMACS format */ int glp_read_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); /* read assignment problem data in DIMACS format */ int glp_write_asnprob(glp_graph *G, int v_set, int a_cost, const char *fname); /* write assignment problem data in DIMACS format */ int glp_read_ccdata(glp_graph *G, int v_wgt, const char *fname); /* read graph in DIMACS clique/coloring format */ int glp_write_ccdata(glp_graph *G, int v_wgt, const char *fname); /* write graph in DIMACS clique/coloring format */ int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, const int parm[1+15]); /* Klingman's network problem generator */ void glp_netgen_prob(int nprob, int parm[1+15]); /* Klingman's standard network problem instance */ int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, const int parm[1+14]); /* grid-like network problem generator */ int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, const int parm[1+5]); /* Goldfarb's maximum flow problem generator */ int glp_weak_comp(glp_graph *G, int v_num); /* find all weakly connected components of graph */ int glp_strong_comp(glp_graph *G, int v_num); /* find all strongly connected components of graph */ int glp_top_sort(glp_graph *G, int v_num); /* topological sorting of acyclic digraph */ int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set); /* find maximum weight clique with exact algorithm */ #ifdef __cplusplus } #endif #endif /* eof */ glpk-4.52.1/src/glplib.h0000644000062000006210000000453212175147600014136 0ustar maomkpasswd/* glplib.h (miscellaneous library routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPLIB_H #define GLPLIB_H #define str2int _glp_lib_str2int int str2int(const char *str, int *val); /* convert character string to value of int type */ #define str2num _glp_lib_str2num int str2num(const char *str, double *val); /* convert character string to value of double type */ #define strspx _glp_lib_strspx char *strspx(char *str); /* remove all spaces from character string */ #define strtrim _glp_lib_strtrim char *strtrim(char *str); /* remove trailing spaces from character string */ #define strrev _glp_lib_strrev char *strrev(char *s); /* reverse character string */ #define gcd _glp_lib_gcd int gcd(int x, int y); /* find greatest common divisor of two integers */ #define gcdn _glp_lib_gcdn int gcdn(int n, int x[]); /* find greatest common divisor of n integers */ #define lcm _glp_lib_lcm int lcm(int x, int y); /* find least common multiple of two integers */ #define lcmn _glp_lib_lcmn int lcmn(int n, int x[]); /* find least common multiple of n integers */ #define round2n _glp_lib_round2n double round2n(double x); /* round floating-point number to nearest power of two */ #define fp2rat _glp_lib_fp2rat int fp2rat(double x, double eps, double *p, double *q); /* convert floating-point number to rational number */ #endif /* eof */ glpk-4.52.1/src/glplib03.c0000644000062000006210000003554212175147600014301 0ustar maomkpasswd/* glplib03.c (miscellaneous library routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "glplib.h" /*********************************************************************** * NAME * * str2int - convert character string to value of int type * * SYNOPSIS * * #include "glplib.h" * int str2int(const char *str, int *val); * * DESCRIPTION * * The routine str2int converts the character string str to a value of * integer type and stores the value into location, which the parameter * val points to (in the case of error content of this location is not * changed). * * RETURNS * * The routine returns one of the following error codes: * * 0 - no error; * 1 - value out of range; * 2 - character string is syntactically incorrect. */ int str2int(const char *str, int *_val) { int d, k, s, val = 0; /* scan optional sign */ if (str[0] == '+') s = +1, k = 1; else if (str[0] == '-') s = -1, k = 1; else s = +1, k = 0; /* check for the first digit */ if (!isdigit((unsigned char)str[k])) return 2; /* scan digits */ while (isdigit((unsigned char)str[k])) { d = str[k++] - '0'; if (s > 0) { if (val > INT_MAX / 10) return 1; val *= 10; if (val > INT_MAX - d) return 1; val += d; } else { if (val < INT_MIN / 10) return 1; val *= 10; if (val < INT_MIN + d) return 1; val -= d; } } /* check for terminator */ if (str[k] != '\0') return 2; /* conversion has been done */ *_val = val; return 0; } /*********************************************************************** * NAME * * str2num - convert character string to value of double type * * SYNOPSIS * * #include "glplib.h" * int str2num(const char *str, double *val); * * DESCRIPTION * * The routine str2num converts the character string str to a value of * double type and stores the value into location, which the parameter * val points to (in the case of error content of this location is not * changed). * * RETURNS * * The routine returns one of the following error codes: * * 0 - no error; * 1 - value out of range; * 2 - character string is syntactically incorrect. */ int str2num(const char *str, double *_val) { int k; double val; /* scan optional sign */ k = (str[0] == '+' || str[0] == '-' ? 1 : 0); /* check for decimal point */ if (str[k] == '.') { k++; /* a digit should follow it */ if (!isdigit((unsigned char)str[k])) return 2; k++; goto frac; } /* integer part should start with a digit */ if (!isdigit((unsigned char)str[k])) return 2; /* scan integer part */ while (isdigit((unsigned char)str[k])) k++; /* check for decimal point */ if (str[k] == '.') k++; frac: /* scan optional fraction part */ while (isdigit((unsigned char)str[k])) k++; /* check for decimal exponent */ if (str[k] == 'E' || str[k] == 'e') { k++; /* scan optional sign */ if (str[k] == '+' || str[k] == '-') k++; /* a digit should follow E, E+ or E- */ if (!isdigit((unsigned char)str[k])) return 2; } /* scan optional exponent part */ while (isdigit((unsigned char)str[k])) k++; /* check for terminator */ if (str[k] != '\0') return 2; /* perform conversion */ { char *endptr; val = strtod(str, &endptr); if (*endptr != '\0') return 2; } /* check for overflow */ if (!(-DBL_MAX <= val && val <= +DBL_MAX)) return 1; /* check for underflow */ if (-DBL_MIN < val && val < +DBL_MIN) val = 0.0; /* conversion has been done */ *_val = val; return 0; } /*********************************************************************** * NAME * * strspx - remove all spaces from character string * * SYNOPSIS * * #include "glplib.h" * char *strspx(char *str); * * DESCRIPTION * * The routine strspx removes all spaces from the character string str. * * RETURNS * * The routine returns a pointer to the character string. * * EXAMPLES * * strspx(" Errare humanum est ") => "Errarehumanumest" * * strspx(" ") => "" */ char *strspx(char *str) { char *s, *t; for (s = t = str; *s; s++) if (*s != ' ') *t++ = *s; *t = '\0'; return str; } /*********************************************************************** * NAME * * strtrim - remove trailing spaces from character string * * SYNOPSIS * * #include "glplib.h" * char *strtrim(char *str); * * DESCRIPTION * * The routine strtrim removes trailing spaces from the character * string str. * * RETURNS * * The routine returns a pointer to the character string. * * EXAMPLES * * strtrim("Errare humanum est ") => "Errare humanum est" * * strtrim(" ") => "" */ char *strtrim(char *str) { char *t; for (t = strrchr(str, '\0') - 1; t >= str; t--) { if (*t != ' ') break; *t = '\0'; } return str; } /*********************************************************************** * NAME * * strrev - reverse character string * * SYNOPSIS * * #include "glplib.h" * char *strrev(char *s); * * DESCRIPTION * * The routine strrev changes characters in a character string s to the * reverse order, except the terminating null character. * * RETURNS * * The routine returns the pointer s. * * EXAMPLES * * strrev("") => "" * * strrev("Today is Monday") => "yadnoM si yadoT" */ char *strrev(char *s) { int i, j; char t; for (i = 0, j = strlen(s)-1; i < j; i++, j--) t = s[i], s[i] = s[j], s[j] = t; return s; } /*********************************************************************** * NAME * * gcd - find greatest common divisor of two integers * * SYNOPSIS * * #include "glplib.h" * int gcd(int x, int y); * * RETURNS * * The routine gcd returns gcd(x, y), the greatest common divisor of * the two positive integers given. * * ALGORITHM * * The routine gcd is based on Euclid's algorithm. * * REFERENCES * * Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical * Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The * Greatest Common Divisor, pp. 333-56. */ int gcd(int x, int y) { int r; xassert(x > 0 && y > 0); while (y > 0) r = x % y, x = y, y = r; return x; } /*********************************************************************** * NAME * * gcdn - find greatest common divisor of n integers * * SYNOPSIS * * #include "glplib.h" * int gcdn(int n, int x[]); * * RETURNS * * The routine gcdn returns gcd(x[1], x[2], ..., x[n]), the greatest * common divisor of n positive integers given, n > 0. * * BACKGROUND * * The routine gcdn is based on the following identity: * * gcd(x, y, z) = gcd(gcd(x, y), z). * * REFERENCES * * Don Knuth, The Art of Computer Programming, Vol.2: Seminumerical * Algorithms, 3rd Edition, Addison-Wesley, 1997. Section 4.5.2: The * Greatest Common Divisor, pp. 333-56. */ int gcdn(int n, int x[]) { int d, j; xassert(n > 0); for (j = 1; j <= n; j++) { xassert(x[j] > 0); if (j == 1) d = x[1]; else d = gcd(d, x[j]); if (d == 1) break; } return d; } /*********************************************************************** * NAME * * lcm - find least common multiple of two integers * * SYNOPSIS * * #include "glplib.h" * int lcm(int x, int y); * * RETURNS * * The routine lcm returns lcm(x, y), the least common multiple of the * two positive integers given. In case of integer overflow the routine * returns zero. * * BACKGROUND * * The routine lcm is based on the following identity: * * lcm(x, y) = (x * y) / gcd(x, y) = x * [y / gcd(x, y)], * * where gcd(x, y) is the greatest common divisor of x and y. */ int lcm(int x, int y) { xassert(x > 0); xassert(y > 0); y /= gcd(x, y); if (x > INT_MAX / y) return 0; return x * y; } /*********************************************************************** * NAME * * lcmn - find least common multiple of n integers * * SYNOPSIS * * #include "glplib.h" * int lcmn(int n, int x[]); * * RETURNS * * The routine lcmn returns lcm(x[1], x[2], ..., x[n]), the least * common multiple of n positive integers given, n > 0. In case of * integer overflow the routine returns zero. * * BACKGROUND * * The routine lcmn is based on the following identity: * * lcmn(x, y, z) = lcm(lcm(x, y), z), * * where lcm(x, y) is the least common multiple of x and y. */ int lcmn(int n, int x[]) { int m, j; xassert(n > 0); for (j = 1; j <= n; j++) { xassert(x[j] > 0); if (j == 1) m = x[1]; else m = lcm(m, x[j]); if (m == 0) break; } return m; } /*********************************************************************** * NAME * * round2n - round floating-point number to nearest power of two * * SYNOPSIS * * #include "glplib.h" * double round2n(double x); * * RETURNS * * Given a positive floating-point value x the routine round2n returns * 2^n such that |x - 2^n| is minimal. * * EXAMPLES * * round2n(10.1) = 2^3 = 8 * round2n(15.3) = 2^4 = 16 * round2n(0.01) = 2^(-7) = 0.0078125 * * BACKGROUND * * Let x = f * 2^e, where 0.5 <= f < 1 is a normalized fractional part, * e is an integer exponent. Then, obviously, 0.5 * 2^e <= x < 2^e, so * if x - 0.5 * 2^e <= 2^e - x, we choose 0.5 * 2^e = 2^(e-1), and 2^e * otherwise. The latter condition can be written as 2 * x <= 1.5 * 2^e * or 2 * f * 2^e <= 1.5 * 2^e or, finally, f <= 0.75. */ double round2n(double x) { int e; double f; xassert(x > 0.0); f = frexp(x, &e); return ldexp(1.0, f <= 0.75 ? e-1 : e); } /*********************************************************************** * NAME * * fp2rat - convert floating-point number to rational number * * SYNOPSIS * * #include "glplib.h" * int fp2rat(double x, double eps, double *p, double *q); * * DESCRIPTION * * Given a floating-point number 0 <= x < 1 the routine fp2rat finds * its "best" rational approximation p / q, where p >= 0 and q > 0 are * integer numbers, such that |x - p / q| <= eps. * * RETURNS * * The routine fp2rat returns the number of iterations used to achieve * the specified precision eps. * * EXAMPLES * * For x = sqrt(2) - 1 = 0.414213562373095 and eps = 1e-6 the routine * gives p = 408 and q = 985, where 408 / 985 = 0.414213197969543. * * BACKGROUND * * It is well known that every positive real number x can be expressed * as the following continued fraction: * * x = b[0] + a[1] * ------------------------ * b[1] + a[2] * ----------------- * b[2] + a[3] * ---------- * b[3] + ... * * where: * * a[k] = 1, k = 0, 1, 2, ... * * b[k] = floor(x[k]), k = 0, 1, 2, ... * * x[0] = x, * * x[k] = 1 / frac(x[k-1]), k = 1, 2, 3, ... * * To find the "best" rational approximation of x the routine computes * partial fractions f[k] by dropping after k terms as follows: * * f[k] = A[k] / B[k], * * where: * * A[-1] = 1, A[0] = b[0], B[-1] = 0, B[0] = 1, * * A[k] = b[k] * A[k-1] + a[k] * A[k-2], * * B[k] = b[k] * B[k-1] + a[k] * B[k-2]. * * Once the condition * * |x - f[k]| <= eps * * has been satisfied, the routine reports p = A[k] and q = B[k] as the * final answer. * * In the table below here is some statistics obtained for one million * random numbers uniformly distributed in the range [0, 1). * * eps max p mean p max q mean q max k mean k * ------------------------------------------------------------- * 1e-1 8 1.6 9 3.2 3 1.4 * 1e-2 98 6.2 99 12.4 5 2.4 * 1e-3 997 20.7 998 41.5 8 3.4 * 1e-4 9959 66.6 9960 133.5 10 4.4 * 1e-5 97403 211.7 97404 424.2 13 5.3 * 1e-6 479669 669.9 479670 1342.9 15 6.3 * 1e-7 1579030 2127.3 3962146 4257.8 16 7.3 * 1e-8 26188823 6749.4 26188824 13503.4 19 8.2 * * REFERENCES * * W. B. Jones and W. J. Thron, "Continued Fractions: Analytic Theory * and Applications," Encyclopedia on Mathematics and Its Applications, * Addison-Wesley, 1980. */ int fp2rat(double x, double eps, double *p, double *q) { int k; double xk, Akm1, Ak, Bkm1, Bk, ak, bk, fk, temp; if (!(0.0 <= x && x < 1.0)) xerror("fp2rat: x = %g; number out of range\n", x); for (k = 0; ; k++) { xassert(k <= 100); if (k == 0) { /* x[0] = x */ xk = x; /* A[-1] = 1 */ Akm1 = 1.0; /* A[0] = b[0] = floor(x[0]) = 0 */ Ak = 0.0; /* B[-1] = 0 */ Bkm1 = 0.0; /* B[0] = 1 */ Bk = 1.0; } else { /* x[k] = 1 / frac(x[k-1]) */ temp = xk - floor(xk); xassert(temp != 0.0); xk = 1.0 / temp; /* a[k] = 1 */ ak = 1.0; /* b[k] = floor(x[k]) */ bk = floor(xk); /* A[k] = b[k] * A[k-1] + a[k] * A[k-2] */ temp = bk * Ak + ak * Akm1; Akm1 = Ak, Ak = temp; /* B[k] = b[k] * B[k-1] + a[k] * B[k-2] */ temp = bk * Bk + ak * Bkm1; Bkm1 = Bk, Bk = temp; } /* f[k] = A[k] / B[k] */ fk = Ak / Bk; #if 0 print("%.*g / %.*g = %.*g", DBL_DIG, Ak, DBL_DIG, Bk, DBL_DIG, fk); #endif if (fabs(x - fk) <= eps) break; } *p = Ak; *q = Bk; return k; } /* eof */ glpk-4.52.1/src/glplpf.c0000644000062000006210000007745312175147600014160 0ustar maomkpasswd/* glplpf.c (LP basis factorization, Schur complement version) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glplpf.h" #include "env.h" #define xfault xerror #define GLPLPF_DEBUG 0 /* CAUTION: DO NOT CHANGE THE LIMIT BELOW */ #define M_MAX 100000000 /* = 100*10^6 */ /* maximal order of the basis matrix */ /*********************************************************************** * NAME * * lpf_create_it - create LP basis factorization * * SYNOPSIS * * #include "glplpf.h" * LPF *lpf_create_it(void); * * DESCRIPTION * * The routine lpf_create_it creates a program object, which represents * a factorization of LP basis. * * RETURNS * * The routine lpf_create_it returns a pointer to the object created. */ LPF *lpf_create_it(void) { LPF *lpf; #if GLPLPF_DEBUG xprintf("lpf_create_it: warning: debug mode enabled\n"); #endif lpf = xmalloc(sizeof(LPF)); lpf->valid = 0; lpf->m0_max = lpf->m0 = 0; #if 0 /* 06/VI-2013 */ lpf->luf = luf_create_it(); #else lpf->lufint = lufint_create(); #endif lpf->m = 0; lpf->B = NULL; lpf->n_max = 50; lpf->n = 0; lpf->R_ptr = lpf->R_len = NULL; lpf->S_ptr = lpf->S_len = NULL; lpf->scf = NULL; lpf->P_row = lpf->P_col = NULL; lpf->Q_row = lpf->Q_col = NULL; lpf->v_size = 1000; lpf->v_ptr = 0; lpf->v_ind = NULL; lpf->v_val = NULL; lpf->work1 = lpf->work2 = NULL; return lpf; } /*********************************************************************** * NAME * * lpf_factorize - compute LP basis factorization * * SYNOPSIS * * #include "glplpf.h" * int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) * (void *info, int j, int ind[], double val[]), void *info); * * DESCRIPTION * * The routine lpf_factorize computes the factorization of the basis * matrix B specified by the routine col. * * The parameter lpf specified the basis factorization data structure * created with the routine lpf_create_it. * * The parameter m specifies the order of B, m > 0. * * The array bh specifies the basis header: bh[j], 1 <= j <= m, is the * number of j-th column of B in some original matrix. The array bh is * optional and can be specified as NULL. * * The formal routine col specifies the matrix B to be factorized. To * obtain j-th column of A the routine lpf_factorize calls the routine * col with the parameter j (1 <= j <= n). In response the routine col * should store row indices and numerical values of non-zero elements * of j-th column of B to locations ind[1,...,len] and val[1,...,len], * respectively, where len is the number of non-zeros in j-th column * returned on exit. Neither zero nor duplicate elements are allowed. * * The parameter info is a transit pointer passed to the routine col. * * RETURNS * * 0 The factorization has been successfully computed. * * LPF_ESING * The specified matrix is singular within the working precision. * * LPF_ECOND * The specified matrix is ill-conditioned. * * For more details see comments to the routine luf_factorize. */ int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) (void *info, int j, int ind[], double val[]), void *info) { int k, ret; #if GLPLPF_DEBUG int i, j, len, *ind; double *B, *val; #endif xassert(bh == bh); if (m < 1) xfault("lpf_factorize: m = %d; invalid parameter\n", m); if (m > M_MAX) xfault("lpf_factorize: m = %d; matrix too big\n", m); lpf->m0 = lpf->m = m; /* invalidate the factorization */ lpf->valid = 0; /* allocate/reallocate arrays, if necessary */ if (lpf->R_ptr == NULL) lpf->R_ptr = xcalloc(1+lpf->n_max, sizeof(int)); if (lpf->R_len == NULL) lpf->R_len = xcalloc(1+lpf->n_max, sizeof(int)); if (lpf->S_ptr == NULL) lpf->S_ptr = xcalloc(1+lpf->n_max, sizeof(int)); if (lpf->S_len == NULL) lpf->S_len = xcalloc(1+lpf->n_max, sizeof(int)); if (lpf->scf == NULL) lpf->scf = scf_create_it(lpf->n_max); if (lpf->v_ind == NULL) lpf->v_ind = xcalloc(1+lpf->v_size, sizeof(int)); if (lpf->v_val == NULL) lpf->v_val = xcalloc(1+lpf->v_size, sizeof(double)); if (lpf->m0_max < m) { if (lpf->P_row != NULL) xfree(lpf->P_row); if (lpf->P_col != NULL) xfree(lpf->P_col); if (lpf->Q_row != NULL) xfree(lpf->Q_row); if (lpf->Q_col != NULL) xfree(lpf->Q_col); if (lpf->work1 != NULL) xfree(lpf->work1); if (lpf->work2 != NULL) xfree(lpf->work2); lpf->m0_max = m + 100; lpf->P_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); lpf->P_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); lpf->Q_row = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); lpf->Q_col = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(int)); lpf->work1 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double)); lpf->work2 = xcalloc(1+lpf->m0_max+lpf->n_max, sizeof(double)); } /* try to factorize the basis matrix */ #if 0 /* 06/VI-2013 */ switch (luf_factorize(lpf->luf, m, col, info)) { case 0: break; case LUF_ESING: ret = LPF_ESING; goto done; case LUF_ECOND: ret = LPF_ECOND; goto done; default: xassert(lpf != lpf); } #else if (lufint_factorize(lpf->lufint, m, col, info) != 0) { ret = LPF_ESING; goto done; } #endif /* the basis matrix has been successfully factorized */ lpf->valid = 1; #if GLPLPF_DEBUG /* store the basis matrix for debugging */ if (lpf->B != NULL) xfree(lpf->B); xassert(m <= 32767); lpf->B = B = xcalloc(1+m*m, sizeof(double)); ind = xcalloc(1+m, sizeof(int)); val = xcalloc(1+m, sizeof(double)); for (k = 1; k <= m * m; k++) B[k] = 0.0; for (j = 1; j <= m; j++) { len = col(info, j, ind, val); xassert(0 <= len && len <= m); for (k = 1; k <= len; k++) { i = ind[k]; xassert(1 <= i && i <= m); xassert(B[(i - 1) * m + j] == 0.0); xassert(val[k] != 0.0); B[(i - 1) * m + j] = val[k]; } } xfree(ind); xfree(val); #endif /* B = B0, so there are no additional rows/columns */ lpf->n = 0; /* reset the Schur complement factorization */ scf_reset_it(lpf->scf); /* P := Q := I */ for (k = 1; k <= m; k++) { lpf->P_row[k] = lpf->P_col[k] = k; lpf->Q_row[k] = lpf->Q_col[k] = k; } /* make all SVA locations free */ lpf->v_ptr = 1; ret = 0; done: /* return to the calling program */ return ret; } /*********************************************************************** * The routine r_prod computes the product y := y + alpha * R * x, * where x is a n-vector, alpha is a scalar, y is a m0-vector. * * Since matrix R is available by columns, the product is computed as * a linear combination: * * y := y + alpha * (R[1] * x[1] + ... + R[n] * x[n]), * * where R[j] is j-th column of R. */ static void r_prod(LPF *lpf, double y[], double a, const double x[]) { int n = lpf->n; int *R_ptr = lpf->R_ptr; int *R_len = lpf->R_len; int *v_ind = lpf->v_ind; double *v_val = lpf->v_val; int j, beg, end, ptr; double t; for (j = 1; j <= n; j++) { if (x[j] == 0.0) continue; /* y := y + alpha * R[j] * x[j] */ t = a * x[j]; beg = R_ptr[j]; end = beg + R_len[j]; for (ptr = beg; ptr < end; ptr++) y[v_ind[ptr]] += t * v_val[ptr]; } return; } /*********************************************************************** * The routine rt_prod computes the product y := y + alpha * R' * x, * where R' is a matrix transposed to R, x is a m0-vector, alpha is a * scalar, y is a n-vector. * * Since matrix R is available by columns, the product components are * computed as inner products: * * y[j] := y[j] + alpha * (j-th column of R) * x * * for j = 1, 2, ..., n. */ static void rt_prod(LPF *lpf, double y[], double a, const double x[]) { int n = lpf->n; int *R_ptr = lpf->R_ptr; int *R_len = lpf->R_len; int *v_ind = lpf->v_ind; double *v_val = lpf->v_val; int j, beg, end, ptr; double t; for (j = 1; j <= n; j++) { /* t := (j-th column of R) * x */ t = 0.0; beg = R_ptr[j]; end = beg + R_len[j]; for (ptr = beg; ptr < end; ptr++) t += v_val[ptr] * x[v_ind[ptr]]; /* y[j] := y[j] + alpha * t */ y[j] += a * t; } return; } /*********************************************************************** * The routine s_prod computes the product y := y + alpha * S * x, * where x is a m0-vector, alpha is a scalar, y is a n-vector. * * Since matrix S is available by rows, the product components are * computed as inner products: * * y[i] = y[i] + alpha * (i-th row of S) * x * * for i = 1, 2, ..., n. */ static void s_prod(LPF *lpf, double y[], double a, const double x[]) { int n = lpf->n; int *S_ptr = lpf->S_ptr; int *S_len = lpf->S_len; int *v_ind = lpf->v_ind; double *v_val = lpf->v_val; int i, beg, end, ptr; double t; for (i = 1; i <= n; i++) { /* t := (i-th row of S) * x */ t = 0.0; beg = S_ptr[i]; end = beg + S_len[i]; for (ptr = beg; ptr < end; ptr++) t += v_val[ptr] * x[v_ind[ptr]]; /* y[i] := y[i] + alpha * t */ y[i] += a * t; } return; } /*********************************************************************** * The routine st_prod computes the product y := y + alpha * S' * x, * where S' is a matrix transposed to S, x is a n-vector, alpha is a * scalar, y is m0-vector. * * Since matrix R is available by rows, the product is computed as a * linear combination: * * y := y + alpha * (S'[1] * x[1] + ... + S'[n] * x[n]), * * where S'[i] is i-th row of S. */ static void st_prod(LPF *lpf, double y[], double a, const double x[]) { int n = lpf->n; int *S_ptr = lpf->S_ptr; int *S_len = lpf->S_len; int *v_ind = lpf->v_ind; double *v_val = lpf->v_val; int i, beg, end, ptr; double t; for (i = 1; i <= n; i++) { if (x[i] == 0.0) continue; /* y := y + alpha * S'[i] * x[i] */ t = a * x[i]; beg = S_ptr[i]; end = beg + S_len[i]; for (ptr = beg; ptr < end; ptr++) y[v_ind[ptr]] += t * v_val[ptr]; } return; } #if GLPLPF_DEBUG /*********************************************************************** * The routine check_error computes the maximal relative error between * left- and right-hand sides for the system B * x = b (if tr is zero) * or B' * x = b (if tr is non-zero), where B' is a matrix transposed * to B. (This routine is intended for debugging only.) */ static void check_error(LPF *lpf, int tr, const double x[], const double b[]) { int m = lpf->m; double *B = lpf->B; int i, j; double d, dmax = 0.0, s, t, tmax; for (i = 1; i <= m; i++) { s = 0.0; tmax = 1.0; for (j = 1; j <= m; j++) { if (!tr) t = B[m * (i - 1) + j] * x[j]; else t = B[m * (j - 1) + i] * x[j]; if (tmax < fabs(t)) tmax = fabs(t); s += t; } d = fabs(s - b[i]) / tmax; if (dmax < d) dmax = d; } if (dmax > 1e-8) xprintf("%s: dmax = %g; relative error too large\n", !tr ? "lpf_ftran" : "lpf_btran", dmax); return; } #endif /*********************************************************************** * NAME * * lpf_ftran - perform forward transformation (solve system B*x = b) * * SYNOPSIS * * #include "glplpf.h" * void lpf_ftran(LPF *lpf, double x[]); * * DESCRIPTION * * The routine lpf_ftran performs forward transformation, i.e. solves * the system B*x = b, where B is the basis matrix, x is the vector of * unknowns to be computed, b is the vector of right-hand sides. * * On entry elements of the vector b should be stored in dense format * in locations x[1], ..., x[m], where m is the number of rows. On exit * the routine stores elements of the vector x in the same locations. * * BACKGROUND * * Solution of the system B * x = b can be obtained by solving the * following augmented system: * * ( B F^) ( x ) ( b ) * ( ) ( ) = ( ) * ( G^ H^) ( y ) ( 0 ) * * which, using the main equality, can be written as follows: * * ( L0 0 ) ( U0 R ) ( x ) ( b ) * P ( ) ( ) Q ( ) = ( ) * ( S I ) ( 0 C ) ( y ) ( 0 ) * * therefore, * * ( x ) ( U0 R )-1 ( L0 0 )-1 ( b ) * ( ) = Q' ( ) ( ) P' ( ) * ( y ) ( 0 C ) ( S I ) ( 0 ) * * Thus, computing the solution includes the following steps: * * 1. Compute * * ( f ) ( b ) * ( ) = P' ( ) * ( g ) ( 0 ) * * 2. Solve the system * * ( f1 ) ( L0 0 )-1 ( f ) ( L0 0 ) ( f1 ) ( f ) * ( ) = ( ) ( ) => ( ) ( ) = ( ) * ( g1 ) ( S I ) ( g ) ( S I ) ( g1 ) ( g ) * * from which it follows that: * * { L0 * f1 = f f1 = inv(L0) * f * { => * { S * f1 + g1 = g g1 = g - S * f1 * * 3. Solve the system * * ( f2 ) ( U0 R )-1 ( f1 ) ( U0 R ) ( f2 ) ( f1 ) * ( ) = ( ) ( ) => ( ) ( ) = ( ) * ( g2 ) ( 0 C ) ( g1 ) ( 0 C ) ( g2 ) ( g1 ) * * from which it follows that: * * { U0 * f2 + R * g2 = f1 f2 = inv(U0) * (f1 - R * g2) * { => * { C * g2 = g1 g2 = inv(C) * g1 * * 4. Compute * * ( x ) ( f2 ) * ( ) = Q' ( ) * ( y ) ( g2 ) */ void lpf_ftran(LPF *lpf, double x[]) { int m0 = lpf->m0; int m = lpf->m; int n = lpf->n; int *P_col = lpf->P_col; int *Q_col = lpf->Q_col; double *fg = lpf->work1; double *f = fg; double *g = fg + m0; int i, ii; #if GLPLPF_DEBUG double *b; #endif if (!lpf->valid) xfault("lpf_ftran: the factorization is not valid\n"); xassert(0 <= m && m <= m0 + n); #if GLPLPF_DEBUG /* save the right-hand side vector */ b = xcalloc(1+m, sizeof(double)); for (i = 1; i <= m; i++) b[i] = x[i]; #endif /* (f g) := inv(P) * (b 0) */ for (i = 1; i <= m0 + n; i++) fg[i] = ((ii = P_col[i]) <= m ? x[ii] : 0.0); /* f1 := inv(L0) * f */ #if 0 /* 06/VI-2013 */ luf_f_solve(lpf->luf, 0, f); #else luf_f_solve(lpf->lufint->luf, f); #endif /* g1 := g - S * f1 */ s_prod(lpf, g, -1.0, f); /* g2 := inv(C) * g1 */ scf_solve_it(lpf->scf, 0, g); /* f2 := inv(U0) * (f1 - R * g2) */ r_prod(lpf, f, -1.0, g); #if 0 /* 06/VI-2013 */ luf_v_solve(lpf->luf, 0, f); #else { double *work = lpf->lufint->sgf->work; luf_v_solve(lpf->lufint->luf, f, work); memcpy(&f[1], &work[1], m0 * sizeof(double)); } #endif /* (x y) := inv(Q) * (f2 g2) */ for (i = 1; i <= m; i++) x[i] = fg[Q_col[i]]; #if GLPLPF_DEBUG /* check relative error in solution */ check_error(lpf, 0, x, b); xfree(b); #endif return; } /*********************************************************************** * NAME * * lpf_btran - perform backward transformation (solve system B'*x = b) * * SYNOPSIS * * #include "glplpf.h" * void lpf_btran(LPF *lpf, double x[]); * * DESCRIPTION * * The routine lpf_btran performs backward transformation, i.e. solves * the system B'*x = b, where B' is a matrix transposed to the basis * matrix B, x is the vector of unknowns to be computed, b is the vector * of right-hand sides. * * On entry elements of the vector b should be stored in dense format * in locations x[1], ..., x[m], where m is the number of rows. On exit * the routine stores elements of the vector x in the same locations. * * BACKGROUND * * Solution of the system B' * x = b, where B' is a matrix transposed * to B, can be obtained by solving the following augmented system: * * ( B F^)T ( x ) ( b ) * ( ) ( ) = ( ) * ( G^ H^) ( y ) ( 0 ) * * which, using the main equality, can be written as follows: * * T ( U0 R )T ( L0 0 )T T ( x ) ( b ) * Q ( ) ( ) P ( ) = ( ) * ( 0 C ) ( S I ) ( y ) ( 0 ) * * or, equivalently, as follows: * * ( U'0 0 ) ( L'0 S') ( x ) ( b ) * Q' ( ) ( ) P' ( ) = ( ) * ( R' C') ( 0 I ) ( y ) ( 0 ) * * therefore, * * ( x ) ( L'0 S')-1 ( U'0 0 )-1 ( b ) * ( ) = P ( ) ( ) Q ( ) * ( y ) ( 0 I ) ( R' C') ( 0 ) * * Thus, computing the solution includes the following steps: * * 1. Compute * * ( f ) ( b ) * ( ) = Q ( ) * ( g ) ( 0 ) * * 2. Solve the system * * ( f1 ) ( U'0 0 )-1 ( f ) ( U'0 0 ) ( f1 ) ( f ) * ( ) = ( ) ( ) => ( ) ( ) = ( ) * ( g1 ) ( R' C') ( g ) ( R' C') ( g1 ) ( g ) * * from which it follows that: * * { U'0 * f1 = f f1 = inv(U'0) * f * { => * { R' * f1 + C' * g1 = g g1 = inv(C') * (g - R' * f1) * * 3. Solve the system * * ( f2 ) ( L'0 S')-1 ( f1 ) ( L'0 S') ( f2 ) ( f1 ) * ( ) = ( ) ( ) => ( ) ( ) = ( ) * ( g2 ) ( 0 I ) ( g1 ) ( 0 I ) ( g2 ) ( g1 ) * * from which it follows that: * * { L'0 * f2 + S' * g2 = f1 * { => f2 = inv(L'0) * ( f1 - S' * g2) * { g2 = g1 * * 4. Compute * * ( x ) ( f2 ) * ( ) = P ( ) * ( y ) ( g2 ) */ void lpf_btran(LPF *lpf, double x[]) { int m0 = lpf->m0; int m = lpf->m; int n = lpf->n; int *P_row = lpf->P_row; int *Q_row = lpf->Q_row; double *fg = lpf->work1; double *f = fg; double *g = fg + m0; int i, ii; #if GLPLPF_DEBUG double *b; #endif if (!lpf->valid) xfault("lpf_btran: the factorization is not valid\n"); xassert(0 <= m && m <= m0 + n); #if GLPLPF_DEBUG /* save the right-hand side vector */ b = xcalloc(1+m, sizeof(double)); for (i = 1; i <= m; i++) b[i] = x[i]; #endif /* (f g) := Q * (b 0) */ for (i = 1; i <= m0 + n; i++) fg[i] = ((ii = Q_row[i]) <= m ? x[ii] : 0.0); /* f1 := inv(U'0) * f */ #if 0 /* 06/VI-2013 */ luf_v_solve(lpf->luf, 1, f); #else { double *work = lpf->lufint->sgf->work; luf_vt_solve(lpf->lufint->luf, f, work); memcpy(&f[1], &work[1], m0 * sizeof(double)); } #endif /* g1 := inv(C') * (g - R' * f1) */ rt_prod(lpf, g, -1.0, f); scf_solve_it(lpf->scf, 1, g); /* g2 := g1 */ g = g; /* f2 := inv(L'0) * (f1 - S' * g2) */ st_prod(lpf, f, -1.0, g); #if 0 /* 06/VI-2013 */ luf_f_solve(lpf->luf, 1, f); #else luf_ft_solve(lpf->lufint->luf, f); #endif /* (x y) := P * (f2 g2) */ for (i = 1; i <= m; i++) x[i] = fg[P_row[i]]; #if GLPLPF_DEBUG /* check relative error in solution */ check_error(lpf, 1, x, b); xfree(b); #endif return; } /*********************************************************************** * The routine enlarge_sva enlarges the Sparse Vector Area to new_size * locations by reallocating the arrays v_ind and v_val. */ static void enlarge_sva(LPF *lpf, int new_size) { int v_size = lpf->v_size; int used = lpf->v_ptr - 1; int *v_ind = lpf->v_ind; double *v_val = lpf->v_val; xassert(v_size < new_size); while (v_size < new_size) v_size += v_size; lpf->v_size = v_size; lpf->v_ind = xcalloc(1+v_size, sizeof(int)); lpf->v_val = xcalloc(1+v_size, sizeof(double)); xassert(used >= 0); memcpy(&lpf->v_ind[1], &v_ind[1], used * sizeof(int)); memcpy(&lpf->v_val[1], &v_val[1], used * sizeof(double)); xfree(v_ind); xfree(v_val); return; } /*********************************************************************** * NAME * * lpf_update_it - update LP basis factorization * * SYNOPSIS * * #include "glplpf.h" * int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], * const double val[]); * * DESCRIPTION * * The routine lpf_update_it updates the factorization of the basis * matrix B after replacing its j-th column by a new vector. * * The parameter j specifies the number of column of B, which has been * replaced, 1 <= j <= m, where m is the order of B. * * The parameter bh specifies the basis header entry for the new column * of B, which is the number of the new column in some original matrix. * This parameter is optional and can be specified as 0. * * Row indices and numerical values of non-zero elements of the new * column of B should be placed in locations ind[1], ..., ind[len] and * val[1], ..., val[len], resp., where len is the number of non-zeros * in the column. Neither zero nor duplicate elements are allowed. * * RETURNS * * 0 The factorization has been successfully updated. * * LPF_ESING * New basis B is singular within the working precision. * * LPF_ELIMIT * Maximal number of additional rows and columns has been reached. * * BACKGROUND * * Let j-th column of the current basis matrix B have to be replaced by * a new column a. This replacement is equivalent to removing the old * j-th column by fixing it at zero and introducing the new column as * follows: * * ( B F^| a ) * ( B F^) ( | ) * ( ) ---> ( G^ H^| 0 ) * ( G^ H^) (-------+---) * ( e'j 0 | 0 ) * * where ej is a unit vector with 1 in j-th position which used to fix * the old j-th column of B (at zero). Then using the main equality we * have: * * ( B F^| a ) ( B0 F | f ) * ( | ) ( P 0 ) ( | ) ( Q 0 ) * ( G^ H^| 0 ) = ( ) ( G H | g ) ( ) = * (-------+---) ( 0 1 ) (-------+---) ( 0 1 ) * ( e'j 0 | 0 ) ( v' w'| 0 ) * * [ ( B0 F )| ( f ) ] [ ( B0 F ) | ( f ) ] * [ P ( )| P ( ) ] ( Q 0 ) [ P ( ) Q| P ( ) ] * = [ ( G H )| ( g ) ] ( ) = [ ( G H ) | ( g ) ] * [------------+-------- ] ( 0 1 ) [-------------+---------] * [ ( v' w')| 0 ] [ ( v' w') Q| 0 ] * * where: * * ( a ) ( f ) ( f ) ( a ) * ( ) = P ( ) => ( ) = P' * ( ) * ( 0 ) ( g ) ( g ) ( 0 ) * * ( ej ) ( v ) ( v ) ( ej ) * ( e'j 0 ) = ( v' w' ) Q => ( ) = Q' ( ) => ( ) = Q ( ) * ( 0 ) ( w ) ( w ) ( 0 ) * * On the other hand: * * ( B0| F f ) * ( P 0 ) (---+------) ( Q 0 ) ( B0 new F ) * ( ) ( G | H g ) ( ) = new P ( ) new Q * ( 0 1 ) ( | ) ( 0 1 ) ( new G new H ) * ( v'| w' 0 ) * * where: * ( G ) ( H g ) * new F = ( F f ), new G = ( ), new H = ( ), * ( v') ( w' 0 ) * * ( P 0 ) ( Q 0 ) * new P = ( ) , new Q = ( ) . * ( 0 1 ) ( 0 1 ) * * The factorization structure for the new augmented matrix remains the * same, therefore: * * ( B0 new F ) ( L0 0 ) ( U0 new R ) * new P ( ) new Q = ( ) ( ) * ( new G new H ) ( new S I ) ( 0 new C ) * * where: * * new F = L0 * new R => * * new R = inv(L0) * new F = inv(L0) * (F f) = ( R inv(L0)*f ) * * new G = new S * U0 => * * ( G ) ( S ) * new S = new G * inv(U0) = ( ) * inv(U0) = ( ) * ( v') ( v'*inv(U0) ) * * new H = new S * new R + new C => * * new C = new H - new S * new R = * * ( H g ) ( S ) * = ( ) - ( ) * ( R inv(L0)*f ) = * ( w' 0 ) ( v'*inv(U0) ) * * ( H - S*R g - S*inv(L0)*f ) ( C x ) * = ( ) = ( ) * ( w'- v'*inv(U0)*R -v'*inv(U0)*inv(L0)*f) ( y' z ) * * Note that new C is resulted by expanding old C with new column x, * row y', and diagonal element z, where: * * x = g - S * inv(L0) * f = g - S * (new column of R) * * y = w - R'* inv(U'0)* v = w - R'* (new row of S) * * z = - (new row of S) * (new column of R) * * Finally, to replace old B by new B we have to permute j-th and last * (just added) columns of the matrix * * ( B F^| a ) * ( | ) * ( G^ H^| 0 ) * (-------+---) * ( e'j 0 | 0 ) * * and to keep the main equality do the same for matrix Q. */ int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], const double val[]) { int m0 = lpf->m0; int m = lpf->m; #if GLPLPF_DEBUG double *B = lpf->B; #endif int n = lpf->n; int *R_ptr = lpf->R_ptr; int *R_len = lpf->R_len; int *S_ptr = lpf->S_ptr; int *S_len = lpf->S_len; int *P_row = lpf->P_row; int *P_col = lpf->P_col; int *Q_row = lpf->Q_row; int *Q_col = lpf->Q_col; int v_ptr = lpf->v_ptr; int *v_ind = lpf->v_ind; double *v_val = lpf->v_val; double *a = lpf->work2; /* new column */ double *fg = lpf->work1, *f = fg, *g = fg + m0; double *vw = lpf->work2, *v = vw, *w = vw + m0; double *x = g, *y = w, z; int i, ii, k, ret; xassert(bh == bh); if (!lpf->valid) xfault("lpf_update_it: the factorization is not valid\n"); if (!(1 <= j && j <= m)) xfault("lpf_update_it: j = %d; column number out of range\n", j); xassert(0 <= m && m <= m0 + n); /* check if the basis factorization can be expanded */ if (n == lpf->n_max) { lpf->valid = 0; ret = LPF_ELIMIT; goto done; } /* convert new j-th column of B to dense format */ for (i = 1; i <= m; i++) a[i] = 0.0; for (k = 1; k <= len; k++) { i = ind[k]; if (!(1 <= i && i <= m)) xfault("lpf_update_it: ind[%d] = %d; row number out of rang" "e\n", k, i); if (a[i] != 0.0) xfault("lpf_update_it: ind[%d] = %d; duplicate row index no" "t allowed\n", k, i); if (val[k] == 0.0) xfault("lpf_update_it: val[%d] = %g; zero element not allow" "ed\n", k, val[k]); a[i] = val[k]; } #if GLPLPF_DEBUG /* change column in the basis matrix for debugging */ for (i = 1; i <= m; i++) B[(i - 1) * m + j] = a[i]; #endif /* (f g) := inv(P) * (a 0) */ for (i = 1; i <= m0+n; i++) fg[i] = ((ii = P_col[i]) <= m ? a[ii] : 0.0); /* (v w) := Q * (ej 0) */ for (i = 1; i <= m0+n; i++) vw[i] = 0.0; vw[Q_col[j]] = 1.0; /* f1 := inv(L0) * f (new column of R) */ #if 0 /* 06/VI-2013 */ luf_f_solve(lpf->luf, 0, f); #else luf_f_solve(lpf->lufint->luf, f); #endif /* v1 := inv(U'0) * v (new row of S) */ #if 0 /* 06/VI-2013 */ luf_v_solve(lpf->luf, 1, v); #else { double *work = lpf->lufint->sgf->work; luf_vt_solve(lpf->lufint->luf, v, work); memcpy(&v[1], &work[1], m0 * sizeof(double)); } #endif /* we need at most 2 * m0 available locations in the SVA to store new column of matrix R and new row of matrix S */ if (lpf->v_size < v_ptr + m0 + m0) { enlarge_sva(lpf, v_ptr + m0 + m0); v_ind = lpf->v_ind; v_val = lpf->v_val; } /* store new column of R */ R_ptr[n+1] = v_ptr; for (i = 1; i <= m0; i++) { if (f[i] != 0.0) v_ind[v_ptr] = i, v_val[v_ptr] = f[i], v_ptr++; } R_len[n+1] = v_ptr - lpf->v_ptr; lpf->v_ptr = v_ptr; /* store new row of S */ S_ptr[n+1] = v_ptr; for (i = 1; i <= m0; i++) { if (v[i] != 0.0) v_ind[v_ptr] = i, v_val[v_ptr] = v[i], v_ptr++; } S_len[n+1] = v_ptr - lpf->v_ptr; lpf->v_ptr = v_ptr; /* x := g - S * f1 (new column of C) */ s_prod(lpf, x, -1.0, f); /* y := w - R' * v1 (new row of C) */ rt_prod(lpf, y, -1.0, v); /* z := - v1 * f1 (new diagonal element of C) */ z = 0.0; for (i = 1; i <= m0; i++) z -= v[i] * f[i]; /* update factorization of new matrix C */ switch (scf_update_exp(lpf->scf, x, y, z)) { case 0: break; case SCF_ESING: lpf->valid = 0; ret = LPF_ESING; goto done; case SCF_ELIMIT: xassert(lpf != lpf); default: xassert(lpf != lpf); } /* expand matrix P */ P_row[m0+n+1] = P_col[m0+n+1] = m0+n+1; /* expand matrix Q */ Q_row[m0+n+1] = Q_col[m0+n+1] = m0+n+1; /* permute j-th and last (just added) column of matrix Q */ i = Q_col[j], ii = Q_col[m0+n+1]; Q_row[i] = m0+n+1, Q_col[m0+n+1] = i; Q_row[ii] = j, Q_col[j] = ii; /* increase the number of additional rows and columns */ lpf->n++; xassert(lpf->n <= lpf->n_max); /* the factorization has been successfully updated */ ret = 0; done: /* return to the calling program */ return ret; } /*********************************************************************** * NAME * * lpf_delete_it - delete LP basis factorization * * SYNOPSIS * * #include "glplpf.h" * void lpf_delete_it(LPF *lpf) * * DESCRIPTION * * The routine lpf_delete_it deletes LP basis factorization specified * by the parameter lpf and frees all memory allocated to this program * object. */ void lpf_delete_it(LPF *lpf) #if 0 /* 06/VI-2013 */ { luf_delete_it(lpf->luf); #else { lufint_delete(lpf->lufint); #endif #if GLPLPF_DEBUG if (lpf->B != NULL) xfree(lpf->B); #else xassert(lpf->B == NULL); #endif if (lpf->R_ptr != NULL) xfree(lpf->R_ptr); if (lpf->R_len != NULL) xfree(lpf->R_len); if (lpf->S_ptr != NULL) xfree(lpf->S_ptr); if (lpf->S_len != NULL) xfree(lpf->S_len); if (lpf->scf != NULL) scf_delete_it(lpf->scf); if (lpf->P_row != NULL) xfree(lpf->P_row); if (lpf->P_col != NULL) xfree(lpf->P_col); if (lpf->Q_row != NULL) xfree(lpf->Q_row); if (lpf->Q_col != NULL) xfree(lpf->Q_col); if (lpf->v_ind != NULL) xfree(lpf->v_ind); if (lpf->v_val != NULL) xfree(lpf->v_val); if (lpf->work1 != NULL) xfree(lpf->work1); if (lpf->work2 != NULL) xfree(lpf->work2); xfree(lpf); return; } /* eof */ glpk-4.52.1/src/glplpf.h0000644000062000006210000001732012175147600014150 0ustar maomkpasswd/* glplpf.h (LP basis factorization, Schur complement version) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPLPF_H #define GLPLPF_H #include "glpscf.h" #if 0 /* 06/VI-2013 */ #include "glpluf.h" #else #include "lufint.h" #endif /*********************************************************************** * The structure LPF defines the factorization of the basis mxm matrix * B, where m is the number of rows in corresponding problem instance. * * This factorization is the following septet: * * [B] = (L0, U0, R, S, C, P, Q), (1) * * and is based on the following main equality: * * ( B F^) ( B0 F ) ( L0 0 ) ( U0 R ) * ( ) = P ( ) Q = P ( ) ( ) Q, (2) * ( G^ H^) ( G H ) ( S I ) ( 0 C ) * * where: * * B is the current basis matrix (not stored); * * F^, G^, H^ are some additional matrices (not stored); * * B0 is some initial basis matrix (not stored); * * F, G, H are some additional matrices (not stored); * * P, Q are permutation matrices (stored in both row- and column-like * formats); * * L0, U0 are some matrices that defines a factorization of the initial * basis matrix B0 = L0 * U0 (stored in an invertable form); * * R is a matrix defined from L0 * R = F, so R = inv(L0) * F (stored in * a column-wise sparse format); * * S is a matrix defined from S * U0 = G, so S = G * inv(U0) (stored in * a row-wise sparse format); * * C is the Schur complement for matrix (B0 F G H). It is defined from * S * R + C = H, so C = H - S * R = H - G * inv(U0) * inv(L0) * F = * = H - G * inv(B0) * F. Matrix C is stored in an invertable form. * * REFERENCES * * 1. M.A.Saunders, "LUSOL: A basis package for constrained optimiza- * tion," SCCM, Stanford University, 2006. * * 2. M.A.Saunders, "Notes 5: Basis Updates," CME 318, Stanford Univer- * sity, Spring 2006. * * 3. M.A.Saunders, "Notes 6: LUSOL---a Basis Factorization Package," * ibid. */ typedef struct LPF LPF; struct LPF { /* LP basis factorization */ int valid; /* the factorization is valid only if this flag is set */ /*--------------------------------------------------------------*/ /* initial basis matrix B0 */ int m0_max; /* maximal value of m0 (increased automatically, if necessary) */ int m0; /* the order of B0 */ #if 0 /* 06/VI-2013 */ LUF *luf; #else LUFINT *lufint; #endif /* LU-factorization of B0 */ /*--------------------------------------------------------------*/ /* current basis matrix B */ int m; /* the order of B */ double *B; /* double B[1+m*m]; */ /* B in dense format stored by rows and used only for debugging; normally this array is not allocated */ /*--------------------------------------------------------------*/ /* augmented matrix (B0 F G H) of the order m0+n */ int n_max; /* maximal number of additional rows and columns */ int n; /* current number of additional rows and columns */ /*--------------------------------------------------------------*/ /* m0xn matrix R in column-wise format */ int *R_ptr; /* int R_ptr[1+n_max]; */ /* R_ptr[j], 1 <= j <= n, is a pointer to j-th column */ int *R_len; /* int R_len[1+n_max]; */ /* R_len[j], 1 <= j <= n, is the length of j-th column */ /*--------------------------------------------------------------*/ /* nxm0 matrix S in row-wise format */ int *S_ptr; /* int S_ptr[1+n_max]; */ /* S_ptr[i], 1 <= i <= n, is a pointer to i-th row */ int *S_len; /* int S_len[1+n_max]; */ /* S_len[i], 1 <= i <= n, is the length of i-th row */ /*--------------------------------------------------------------*/ /* Schur complement C of the order n */ SCF *scf; /* SCF scf[1:n_max]; */ /* factorization of the Schur complement */ /*--------------------------------------------------------------*/ /* matrix P of the order m0+n */ int *P_row; /* int P_row[1+m0_max+n_max]; */ /* P_row[i] = j means that P[i,j] = 1 */ int *P_col; /* int P_col[1+m0_max+n_max]; */ /* P_col[j] = i means that P[i,j] = 1 */ /*--------------------------------------------------------------*/ /* matrix Q of the order m0+n */ int *Q_row; /* int Q_row[1+m0_max+n_max]; */ /* Q_row[i] = j means that Q[i,j] = 1 */ int *Q_col; /* int Q_col[1+m0_max+n_max]; */ /* Q_col[j] = i means that Q[i,j] = 1 */ /*--------------------------------------------------------------*/ /* Sparse Vector Area (SVA) is a set of locations intended to store sparse vectors which represent columns of matrix R and rows of matrix S; each location is a doublet (ind, val), where ind is an index, val is a numerical value of a sparse vector element; in the whole each sparse vector is a set of adjacent locations defined by a pointer to its first element and its length, i.e. the number of its elements */ int v_size; /* the SVA size, in locations; locations are numbered by integers 1, 2, ..., v_size, and location 0 is not used */ int v_ptr; /* pointer to the first available location */ int *v_ind; /* int v_ind[1+v_size]; */ /* v_ind[k], 1 <= k <= v_size, is the index field of location k */ double *v_val; /* double v_val[1+v_size]; */ /* v_val[k], 1 <= k <= v_size, is the value field of location k */ /*--------------------------------------------------------------*/ double *work1; /* double work1[1+m0+n_max]; */ /* working array */ double *work2; /* double work2[1+m0+n_max]; */ /* working array */ }; /* return codes: */ #define LPF_ESING 1 /* singular matrix */ #define LPF_ECOND 2 /* ill-conditioned matrix */ #define LPF_ELIMIT 3 /* update limit reached */ #define lpf_create_it _glp_lpf_create_it LPF *lpf_create_it(void); /* create LP basis factorization */ #define lpf_factorize _glp_lpf_factorize int lpf_factorize(LPF *lpf, int m, const int bh[], int (*col) (void *info, int j, int ind[], double val[]), void *info); /* compute LP basis factorization */ #define lpf_ftran _glp_lpf_ftran void lpf_ftran(LPF *lpf, double x[]); /* perform forward transformation (solve system B*x = b) */ #define lpf_btran _glp_lpf_btran void lpf_btran(LPF *lpf, double x[]); /* perform backward transformation (solve system B'*x = b) */ #define lpf_update_it _glp_lpf_update_it int lpf_update_it(LPF *lpf, int j, int bh, int len, const int ind[], const double val[]); /* update LP basis factorization */ #define lpf_delete_it _glp_lpf_delete_it void lpf_delete_it(LPF *lpf); /* delete LP basis factorization */ #endif /* eof */ glpk-4.52.1/src/glplpx.h0000644000062000006210000005760012175147600014177 0ustar maomkpasswd/* glplpx.h (obsolete API routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPLPX_H #define GLPLPX_H #define LPX glp_prob /* problem class: */ #define LPX_LP 100 /* linear programming (LP) */ #define LPX_MIP 101 /* mixed integer programming (MIP) */ /* type of auxiliary/structural variable: */ #define LPX_FR 110 /* free variable */ #define LPX_LO 111 /* variable with lower bound */ #define LPX_UP 112 /* variable with upper bound */ #define LPX_DB 113 /* double-bounded variable */ #define LPX_FX 114 /* fixed variable */ /* optimization direction flag: */ #define LPX_MIN 120 /* minimization */ #define LPX_MAX 121 /* maximization */ /* status of primal basic solution: */ #define LPX_P_UNDEF 132 /* primal solution is undefined */ #define LPX_P_FEAS 133 /* solution is primal feasible */ #define LPX_P_INFEAS 134 /* solution is primal infeasible */ #define LPX_P_NOFEAS 135 /* no primal feasible solution exists */ /* status of dual basic solution: */ #define LPX_D_UNDEF 136 /* dual solution is undefined */ #define LPX_D_FEAS 137 /* solution is dual feasible */ #define LPX_D_INFEAS 138 /* solution is dual infeasible */ #define LPX_D_NOFEAS 139 /* no dual feasible solution exists */ /* status of auxiliary/structural variable: */ #define LPX_BS 140 /* basic variable */ #define LPX_NL 141 /* non-basic variable on lower bound */ #define LPX_NU 142 /* non-basic variable on upper bound */ #define LPX_NF 143 /* non-basic free variable */ #define LPX_NS 144 /* non-basic fixed variable */ /* status of interior-point solution: */ #define LPX_T_UNDEF 150 /* interior solution is undefined */ #define LPX_T_OPT 151 /* interior solution is optimal */ /* kind of structural variable: */ #define LPX_CV 160 /* continuous variable */ #define LPX_IV 161 /* integer variable */ /* status of integer solution: */ #define LPX_I_UNDEF 170 /* integer solution is undefined */ #define LPX_I_OPT 171 /* integer solution is optimal */ #define LPX_I_FEAS 172 /* integer solution is feasible */ #define LPX_I_NOFEAS 173 /* no integer solution exists */ /* status codes reported by the routine lpx_get_status: */ #define LPX_OPT 180 /* optimal */ #define LPX_FEAS 181 /* feasible */ #define LPX_INFEAS 182 /* infeasible */ #define LPX_NOFEAS 183 /* no feasible */ #define LPX_UNBND 184 /* unbounded */ #define LPX_UNDEF 185 /* undefined */ /* exit codes returned by solver routines: */ #define LPX_E_OK 200 /* success */ #define LPX_E_EMPTY 201 /* empty problem */ #define LPX_E_BADB 202 /* invalid initial basis */ #define LPX_E_INFEAS 203 /* infeasible initial solution */ #define LPX_E_FAULT 204 /* unable to start the search */ #define LPX_E_OBJLL 205 /* objective lower limit reached */ #define LPX_E_OBJUL 206 /* objective upper limit reached */ #define LPX_E_ITLIM 207 /* iterations limit exhausted */ #define LPX_E_TMLIM 208 /* time limit exhausted */ #define LPX_E_NOFEAS 209 /* no feasible solution */ #define LPX_E_INSTAB 210 /* numerical instability */ #define LPX_E_SING 211 /* problems with basis matrix */ #define LPX_E_NOCONV 212 /* no convergence (interior) */ #define LPX_E_NOPFS 213 /* no primal feas. sol. (LP presolver) */ #define LPX_E_NODFS 214 /* no dual feas. sol. (LP presolver) */ #define LPX_E_MIPGAP 215 /* relative mip gap tolerance reached */ /* control parameter identifiers: */ #define LPX_K_MSGLEV 300 /* lp->msg_lev */ #define LPX_K_SCALE 301 /* lp->scale */ #define LPX_K_DUAL 302 /* lp->dual */ #define LPX_K_PRICE 303 /* lp->price */ #define LPX_K_RELAX 304 /* lp->relax */ #define LPX_K_TOLBND 305 /* lp->tol_bnd */ #define LPX_K_TOLDJ 306 /* lp->tol_dj */ #define LPX_K_TOLPIV 307 /* lp->tol_piv */ #define LPX_K_ROUND 308 /* lp->round */ #define LPX_K_OBJLL 309 /* lp->obj_ll */ #define LPX_K_OBJUL 310 /* lp->obj_ul */ #define LPX_K_ITLIM 311 /* lp->it_lim */ #define LPX_K_ITCNT 312 /* lp->it_cnt */ #define LPX_K_TMLIM 313 /* lp->tm_lim */ #define LPX_K_OUTFRQ 314 /* lp->out_frq */ #define LPX_K_OUTDLY 315 /* lp->out_dly */ #define LPX_K_BRANCH 316 /* lp->branch */ #define LPX_K_BTRACK 317 /* lp->btrack */ #define LPX_K_TOLINT 318 /* lp->tol_int */ #define LPX_K_TOLOBJ 319 /* lp->tol_obj */ #define LPX_K_MPSINFO 320 /* lp->mps_info */ #define LPX_K_MPSOBJ 321 /* lp->mps_obj */ #define LPX_K_MPSORIG 322 /* lp->mps_orig */ #define LPX_K_MPSWIDE 323 /* lp->mps_wide */ #define LPX_K_MPSFREE 324 /* lp->mps_free */ #define LPX_K_MPSSKIP 325 /* lp->mps_skip */ #define LPX_K_LPTORIG 326 /* lp->lpt_orig */ #define LPX_K_PRESOL 327 /* lp->presol */ #define LPX_K_BINARIZE 328 /* lp->binarize */ #define LPX_K_USECUTS 329 /* lp->use_cuts */ #define LPX_K_BFTYPE 330 /* lp->bfcp->type */ #define LPX_K_MIPGAP 331 /* lp->mip_gap */ #define LPX_C_COVER 0x01 /* mixed cover cuts */ #define LPX_C_CLIQUE 0x02 /* clique cuts */ #define LPX_C_GOMORY 0x04 /* Gomory's mixed integer cuts */ #define LPX_C_MIR 0x08 /* mixed integer rounding cuts */ #define LPX_C_ALL 0xFF /* all cuts */ typedef struct { /* this structure contains results reported by the routines which checks Karush-Kuhn-Tucker conditions (for details see comments to those routines) */ /*--------------------------------------------------------------*/ /* xR - A * xS = 0 (KKT.PE) */ double pe_ae_max; /* largest absolute error */ int pe_ae_row; /* number of row with largest absolute error */ double pe_re_max; /* largest relative error */ int pe_re_row; /* number of row with largest relative error */ int pe_quality; /* quality of primal solution: 'H' - high 'M' - medium 'L' - low '?' - primal solution is wrong */ /*--------------------------------------------------------------*/ /* l[k] <= x[k] <= u[k] (KKT.PB) */ double pb_ae_max; /* largest absolute error */ int pb_ae_ind; /* number of variable with largest absolute error */ double pb_re_max; /* largest relative error */ int pb_re_ind; /* number of variable with largest relative error */ int pb_quality; /* quality of primal feasibility: 'H' - high 'M' - medium 'L' - low '?' - primal solution is infeasible */ /*--------------------------------------------------------------*/ /* A' * (dR - cR) + (dS - cS) = 0 (KKT.DE) */ double de_ae_max; /* largest absolute error */ int de_ae_col; /* number of column with largest absolute error */ double de_re_max; /* largest relative error */ int de_re_col; /* number of column with largest relative error */ int de_quality; /* quality of dual solution: 'H' - high 'M' - medium 'L' - low '?' - dual solution is wrong */ /*--------------------------------------------------------------*/ /* d[k] >= 0 or d[k] <= 0 (KKT.DB) */ double db_ae_max; /* largest absolute error */ int db_ae_ind; /* number of variable with largest absolute error */ double db_re_max; /* largest relative error */ int db_re_ind; /* number of variable with largest relative error */ int db_quality; /* quality of dual feasibility: 'H' - high 'M' - medium 'L' - low '?' - dual solution is infeasible */ /*--------------------------------------------------------------*/ /* (x[k] - bound of x[k]) * d[k] = 0 (KKT.CS) */ double cs_ae_max; /* largest absolute error */ int cs_ae_ind; /* number of variable with largest absolute error */ double cs_re_max; /* largest relative error */ int cs_re_ind; /* number of variable with largest relative error */ int cs_quality; /* quality of complementary slackness: 'H' - high 'M' - medium 'L' - low '?' - primal and dual solutions are not complementary */ } LPXKKT; #define lpx_create_prob _glp_lpx_create_prob LPX *lpx_create_prob(void); /* create problem object */ #define lpx_set_prob_name _glp_lpx_set_prob_name void lpx_set_prob_name(LPX *lp, const char *name); /* assign (change) problem name */ #define lpx_set_obj_name _glp_lpx_set_obj_name void lpx_set_obj_name(LPX *lp, const char *name); /* assign (change) objective function name */ #define lpx_set_obj_dir _glp_lpx_set_obj_dir void lpx_set_obj_dir(LPX *lp, int dir); /* set (change) optimization direction flag */ #define lpx_add_rows _glp_lpx_add_rows int lpx_add_rows(LPX *lp, int nrs); /* add new rows to problem object */ #define lpx_add_cols _glp_lpx_add_cols int lpx_add_cols(LPX *lp, int ncs); /* add new columns to problem object */ #define lpx_set_row_name _glp_lpx_set_row_name void lpx_set_row_name(LPX *lp, int i, const char *name); /* assign (change) row name */ #define lpx_set_col_name _glp_lpx_set_col_name void lpx_set_col_name(LPX *lp, int j, const char *name); /* assign (change) column name */ #define lpx_set_row_bnds _glp_lpx_set_row_bnds void lpx_set_row_bnds(LPX *lp, int i, int type, double lb, double ub); /* set (change) row bounds */ #define lpx_set_col_bnds _glp_lpx_set_col_bnds void lpx_set_col_bnds(LPX *lp, int j, int type, double lb, double ub); /* set (change) column bounds */ #define lpx_set_obj_coef _glp_lpx_set_obj_coef void lpx_set_obj_coef(glp_prob *lp, int j, double coef); /* set (change) obj. coefficient or constant term */ #define lpx_set_mat_row _glp_lpx_set_mat_row void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[], const double val[]); /* set (replace) row of the constraint matrix */ #define lpx_set_mat_col _glp_lpx_set_mat_col void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[], const double val[]); /* set (replace) column of the constraint matrix */ #define lpx_load_matrix _glp_lpx_load_matrix void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[], const double ar[]); /* load (replace) the whole constraint matrix */ #define lpx_del_rows _glp_lpx_del_rows void lpx_del_rows(LPX *lp, int nrs, const int num[]); /* delete specified rows from problem object */ #define lpx_del_cols _glp_lpx_del_cols void lpx_del_cols(LPX *lp, int ncs, const int num[]); /* delete specified columns from problem object */ #define lpx_delete_prob _glp_lpx_delete_prob void lpx_delete_prob(LPX *lp); /* delete problem object */ #define lpx_get_prob_name _glp_lpx_get_prob_name const char *lpx_get_prob_name(LPX *lp); /* retrieve problem name */ #define lpx_get_obj_name _glp_lpx_get_obj_name const char *lpx_get_obj_name(LPX *lp); /* retrieve objective function name */ #define lpx_get_obj_dir _glp_lpx_get_obj_dir int lpx_get_obj_dir(LPX *lp); /* retrieve optimization direction flag */ #define lpx_get_num_rows _glp_lpx_get_num_rows int lpx_get_num_rows(LPX *lp); /* retrieve number of rows */ #define lpx_get_num_cols _glp_lpx_get_num_cols int lpx_get_num_cols(LPX *lp); /* retrieve number of columns */ #define lpx_get_row_name _glp_lpx_get_row_name const char *lpx_get_row_name(LPX *lp, int i); /* retrieve row name */ #define lpx_get_col_name _glp_lpx_get_col_name const char *lpx_get_col_name(LPX *lp, int j); /* retrieve column name */ #define lpx_get_row_type _glp_lpx_get_row_type int lpx_get_row_type(LPX *lp, int i); /* retrieve row type */ #define lpx_get_row_lb _glp_lpx_get_row_lb double lpx_get_row_lb(LPX *lp, int i); /* retrieve row lower bound */ #define lpx_get_row_ub _glp_lpx_get_row_ub double lpx_get_row_ub(LPX *lp, int i); /* retrieve row upper bound */ #define lpx_get_row_bnds _glp_lpx_get_row_bnds void lpx_get_row_bnds(LPX *lp, int i, int *typx, double *lb, double *ub); /* retrieve row bounds */ #define lpx_get_col_type _glp_lpx_get_col_type int lpx_get_col_type(LPX *lp, int j); /* retrieve column type */ #define lpx_get_col_lb _glp_lpx_get_col_lb double lpx_get_col_lb(LPX *lp, int j); /* retrieve column lower bound */ #define lpx_get_col_ub _glp_lpx_get_col_ub double lpx_get_col_ub(LPX *lp, int j); /* retrieve column upper bound */ #define lpx_get_col_bnds _glp_lpx_get_col_bnds void lpx_get_col_bnds(LPX *lp, int j, int *typx, double *lb, double *ub); /* retrieve column bounds */ #define lpx_get_obj_coef _glp_lpx_get_obj_coef double lpx_get_obj_coef(LPX *lp, int j); /* retrieve obj. coefficient or constant term */ #define lpx_get_num_nz _glp_lpx_get_num_nz int lpx_get_num_nz(LPX *lp); /* retrieve number of constraint coefficients */ #define lpx_get_mat_row _glp_lpx_get_mat_row int lpx_get_mat_row(LPX *lp, int i, int ind[], double val[]); /* retrieve row of the constraint matrix */ #define lpx_get_mat_col _glp_lpx_get_mat_col int lpx_get_mat_col(LPX *lp, int j, int ind[], double val[]); /* retrieve column of the constraint matrix */ #define lpx_create_index _glp_lpx_create_index void lpx_create_index(LPX *lp); /* create the name index */ #define lpx_find_row _glp_lpx_find_row int lpx_find_row(LPX *lp, const char *name); /* find row by its name */ #define lpx_find_col _glp_lpx_find_col int lpx_find_col(LPX *lp, const char *name); /* find column by its name */ #define lpx_delete_index _glp_lpx_delete_index void lpx_delete_index(LPX *lp); /* delete the name index */ #define lpx_scale_prob _glp_lpx_scale_prob void lpx_scale_prob(LPX *lp); /* scale problem data */ #define lpx_unscale_prob _glp_lpx_unscale_prob void lpx_unscale_prob(LPX *lp); /* unscale problem data */ #define lpx_set_row_stat _glp_lpx_set_row_stat void lpx_set_row_stat(LPX *lp, int i, int stat); /* set (change) row status */ #define lpx_set_col_stat _glp_lpx_set_col_stat void lpx_set_col_stat(LPX *lp, int j, int stat); /* set (change) column status */ #define lpx_std_basis _glp_lpx_std_basis void lpx_std_basis(LPX *lp); /* construct standard initial LP basis */ #define lpx_adv_basis _glp_lpx_adv_basis void lpx_adv_basis(LPX *lp); /* construct advanced initial LP basis */ #define lpx_cpx_basis _glp_lpx_cpx_basis void lpx_cpx_basis(LPX *lp); /* construct Bixby's initial LP basis */ #define lpx_simplex _glp_lpx_simplex int lpx_simplex(LPX *lp); /* easy-to-use driver to the simplex method */ #define lpx_exact _glp_lpx_exact int lpx_exact(LPX *lp); /* easy-to-use driver to the exact simplex method */ #define lpx_get_status _glp_lpx_get_status int lpx_get_status(LPX *lp); /* retrieve generic status of basic solution */ #define lpx_get_prim_stat _glp_lpx_get_prim_stat int lpx_get_prim_stat(LPX *lp); /* retrieve primal status of basic solution */ #define lpx_get_dual_stat _glp_lpx_get_dual_stat int lpx_get_dual_stat(LPX *lp); /* retrieve dual status of basic solution */ #define lpx_get_obj_val _glp_lpx_get_obj_val double lpx_get_obj_val(LPX *lp); /* retrieve objective value (basic solution) */ #define lpx_get_row_stat _glp_lpx_get_row_stat int lpx_get_row_stat(LPX *lp, int i); /* retrieve row status (basic solution) */ #define lpx_get_row_prim _glp_lpx_get_row_prim double lpx_get_row_prim(LPX *lp, int i); /* retrieve row primal value (basic solution) */ #define lpx_get_row_dual _glp_lpx_get_row_dual double lpx_get_row_dual(LPX *lp, int i); /* retrieve row dual value (basic solution) */ #define lpx_get_row_info _glp_lpx_get_row_info void lpx_get_row_info(LPX *lp, int i, int *tagx, double *vx, double *dx); /* obtain row solution information */ #define lpx_get_col_stat _glp_lpx_get_col_stat int lpx_get_col_stat(LPX *lp, int j); /* retrieve column status (basic solution) */ #define lpx_get_col_prim _glp_lpx_get_col_prim double lpx_get_col_prim(LPX *lp, int j); /* retrieve column primal value (basic solution) */ #define lpx_get_col_dual _glp_lpx_get_col_dual double lpx_get_col_dual(glp_prob *lp, int j); /* retrieve column dual value (basic solution) */ #define lpx_get_col_info _glp_lpx_get_col_info void lpx_get_col_info(LPX *lp, int j, int *tagx, double *vx, double *dx); /* obtain column solution information (obsolete) */ #define lpx_get_ray_info _glp_lpx_get_ray_info int lpx_get_ray_info(LPX *lp); /* determine what causes primal unboundness */ #define lpx_check_kkt _glp_lpx_check_kkt void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt); /* check Karush-Kuhn-Tucker conditions */ #define lpx_warm_up _glp_lpx_warm_up int lpx_warm_up(LPX *lp); /* "warm up" LP basis */ #define lpx_eval_tab_row _glp_lpx_eval_tab_row int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[]); /* compute row of the simplex table */ #define lpx_eval_tab_col _glp_lpx_eval_tab_col int lpx_eval_tab_col(LPX *lp, int k, int ind[], double val[]); /* compute column of the simplex table */ #define lpx_transform_row _glp_lpx_transform_row int lpx_transform_row(LPX *lp, int len, int ind[], double val[]); /* transform explicitly specified row */ #define lpx_transform_col _glp_lpx_transform_col int lpx_transform_col(LPX *lp, int len, int ind[], double val[]); /* transform explicitly specified column */ #define lpx_prim_ratio_test _glp_lpx_prim_ratio_test int lpx_prim_ratio_test(LPX *lp, int len, const int ind[], const double val[], int how, double tol); /* perform primal ratio test */ #define lpx_dual_ratio_test _glp_lpx_dual_ratio_test int lpx_dual_ratio_test(LPX *lp, int len, const int ind[], const double val[], int how, double tol); /* perform dual ratio test */ #define lpx_interior _glp_lpx_interior int lpx_interior(LPX *lp); /* easy-to-use driver to the interior point method */ #define lpx_ipt_status _glp_lpx_ipt_status int lpx_ipt_status(LPX *lp); /* retrieve status of interior-point solution */ #define lpx_ipt_obj_val _glp_lpx_ipt_obj_val double lpx_ipt_obj_val(LPX *lp); /* retrieve objective value (interior point) */ #define lpx_ipt_row_prim _glp_lpx_ipt_row_prim double lpx_ipt_row_prim(LPX *lp, int i); /* retrieve row primal value (interior point) */ #define lpx_ipt_row_dual _glp_lpx_ipt_row_dual double lpx_ipt_row_dual(LPX *lp, int i); /* retrieve row dual value (interior point) */ #define lpx_ipt_col_prim _glp_lpx_ipt_col_prim double lpx_ipt_col_prim(LPX *lp, int j); /* retrieve column primal value (interior point) */ #define lpx_ipt_col_dual _glp_lpx_ipt_col_dual double lpx_ipt_col_dual(LPX *lp, int j); /* retrieve column dual value (interior point) */ #define lpx_set_class _glp_lpx_set_class void lpx_set_class(LPX *lp, int klass); /* set problem class */ #define lpx_get_class _glp_lpx_get_class int lpx_get_class(LPX *lp); /* determine problem klass */ #define lpx_set_col_kind _glp_lpx_set_col_kind void lpx_set_col_kind(LPX *lp, int j, int kind); /* set (change) column kind */ #define lpx_get_col_kind _glp_lpx_get_col_kind int lpx_get_col_kind(LPX *lp, int j); /* retrieve column kind */ #define lpx_get_num_int _glp_lpx_get_num_int int lpx_get_num_int(LPX *lp); /* retrieve number of integer columns */ #define lpx_get_num_bin _glp_lpx_get_num_bin int lpx_get_num_bin(LPX *lp); /* retrieve number of binary columns */ #define lpx_integer _glp_lpx_integer int lpx_integer(LPX *lp); /* easy-to-use driver to the branch-and-bound method */ #define lpx_intopt _glp_lpx_intopt int lpx_intopt(LPX *lp); /* easy-to-use driver to the branch-and-bound method */ #define lpx_mip_status _glp_lpx_mip_status int lpx_mip_status(LPX *lp); /* retrieve status of MIP solution */ #define lpx_mip_obj_val _glp_lpx_mip_obj_val double lpx_mip_obj_val(LPX *lp); /* retrieve objective value (MIP solution) */ #define lpx_mip_row_val _glp_lpx_mip_row_val double lpx_mip_row_val(LPX *lp, int i); /* retrieve row value (MIP solution) */ #define lpx_mip_col_val _glp_lpx_mip_col_val double lpx_mip_col_val(LPX *lp, int j); /* retrieve column value (MIP solution) */ #define lpx_check_int _glp_lpx_check_int void lpx_check_int(LPX *lp, LPXKKT *kkt); /* check integer feasibility conditions */ #define lpx_reset_parms _glp_lpx_reset_parms void lpx_reset_parms(LPX *lp); /* reset control parameters to default values */ #define lpx_set_int_parm _glp_lpx_set_int_parm void lpx_set_int_parm(LPX *lp, int parm, int val); /* set (change) integer control parameter */ #define lpx_get_int_parm _glp_lpx_get_int_parm int lpx_get_int_parm(LPX *lp, int parm); /* query integer control parameter */ #define lpx_set_real_parm _glp_lpx_set_real_parm void lpx_set_real_parm(LPX *lp, int parm, double val); /* set (change) real control parameter */ #define lpx_get_real_parm _glp_lpx_get_real_parm double lpx_get_real_parm(LPX *lp, int parm); /* query real control parameter */ #define lpx_read_mps _glp_lpx_read_mps LPX *lpx_read_mps(const char *fname); /* read problem data in fixed MPS format */ #define lpx_write_mps _glp_lpx_write_mps int lpx_write_mps(LPX *lp, const char *fname); /* write problem data in fixed MPS format */ #define lpx_read_bas _glp_lpx_read_bas int lpx_read_bas(LPX *lp, const char *fname); /* read LP basis in fixed MPS format */ #define lpx_write_bas _glp_lpx_write_bas int lpx_write_bas(LPX *lp, const char *fname); /* write LP basis in fixed MPS format */ #define lpx_read_freemps _glp_lpx_read_freemps LPX *lpx_read_freemps(const char *fname); /* read problem data in free MPS format */ #define lpx_write_freemps _glp_lpx_write_freemps int lpx_write_freemps(LPX *lp, const char *fname); /* write problem data in free MPS format */ #define lpx_read_cpxlp _glp_lpx_read_cpxlp LPX *lpx_read_cpxlp(const char *fname); /* read problem data in CPLEX LP format */ #define lpx_write_cpxlp _glp_lpx_write_cpxlp int lpx_write_cpxlp(LPX *lp, const char *fname); /* write problem data in CPLEX LP format */ #define lpx_read_model _glp_lpx_read_model LPX *lpx_read_model(const char *model, const char *data, const char *output); /* read LP/MIP model written in GNU MathProg language */ #define lpx_print_prob _glp_lpx_print_prob int lpx_print_prob(LPX *lp, const char *fname); /* write problem data in plain text format */ #define lpx_print_sol _glp_lpx_print_sol int lpx_print_sol(LPX *lp, const char *fname); /* write LP problem solution in printable format */ #define lpx_print_sens_bnds _glp_lpx_print_sens_bnds int lpx_print_sens_bnds(LPX *lp, const char *fname); /* write bounds sensitivity information */ #define lpx_print_ips _glp_lpx_print_ips int lpx_print_ips(LPX *lp, const char *fname); /* write interior point solution in printable format */ #define lpx_print_mip _glp_lpx_print_mip int lpx_print_mip(LPX *lp, const char *fname); /* write MIP problem solution in printable format */ #define lpx_is_b_avail _glp_lpx_is_b_avail int lpx_is_b_avail(LPX *lp); /* check if LP basis is available */ #define lpx_write_pb _glp_lpx_write_pb int lpx_write_pb(LPX *lp, const char *fname, int normalized, int binarize); /* write problem data in (normalized) OPB format */ #define lpx_main _glp_lpx_main int lpx_main(int argc, const char *argv[]); /* stand-alone LP/MIP solver */ #endif /* eof */ glpk-4.52.1/src/glplpx01.c0000644000062000006210000013756512175147600014344 0ustar maomkpasswd/* glplpx01.c (obsolete API routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" struct LPXCPS { /* control parameters and statistics */ int msg_lev; /* level of messages output by the solver: 0 - no output 1 - error messages only 2 - normal output 3 - full output (includes informational messages) */ int scale; /* scaling option: 0 - no scaling 1 - equilibration scaling 2 - geometric mean scaling 3 - geometric mean scaling, then equilibration scaling */ int dual; /* dual simplex option: 0 - use primal simplex 1 - use dual simplex */ int price; /* pricing option (for both primal and dual simplex): 0 - textbook pricing 1 - steepest edge pricing */ double relax; /* relaxation parameter used in the ratio test; if it is zero, the textbook ratio test is used; if it is non-zero (should be positive), Harris' two-pass ratio test is used; in the latter case on the first pass basic variables (in the case of primal simplex) or reduced costs of non-basic variables (in the case of dual simplex) are allowed to slightly violate their bounds, but not more than (relax * tol_bnd) or (relax * tol_dj) (thus, relax is a percentage of tol_bnd or tol_dj) */ double tol_bnd; /* relative tolerance used to check if the current basic solution is primal feasible */ double tol_dj; /* absolute tolerance used to check if the current basic solution is dual feasible */ double tol_piv; /* relative tolerance used to choose eligible pivotal elements of the simplex table in the ratio test */ int round; /* solution rounding option: 0 - report all computed values and reduced costs "as is" 1 - if possible (allowed by the tolerances), replace computed values and reduced costs which are close to zero by exact zeros */ double obj_ll; /* lower limit of the objective function; if on the phase II the objective function reaches this limit and continues decreasing, the solver stops the search */ double obj_ul; /* upper limit of the objective function; if on the phase II the objective function reaches this limit and continues increasing, the solver stops the search */ int it_lim; /* simplex iterations limit; if this value is positive, it is decreased by one each time when one simplex iteration has been performed, and reaching zero value signals the solver to stop the search; negative value means no iterations limit */ double tm_lim; /* searching time limit, in seconds; if this value is positive, it is decreased each time when one simplex iteration has been performed by the amount of time spent for the iteration, and reaching zero value signals the solver to stop the search; negative value means no time limit */ int out_frq; /* output frequency, in iterations; this parameter specifies how frequently the solver sends information about the solution to the standard output */ double out_dly; /* output delay, in seconds; this parameter specifies how long the solver should delay sending information about the solution to the standard output; zero value means no delay */ int branch; /* MIP */ /* branching heuristic: 0 - branch on first variable 1 - branch on last variable 2 - branch using heuristic by Driebeck and Tomlin 3 - branch on most fractional variable */ int btrack; /* MIP */ /* backtracking heuristic: 0 - select most recent node (depth first search) 1 - select earliest node (breadth first search) 2 - select node using the best projection heuristic 3 - select node with best local bound */ double tol_int; /* MIP */ /* absolute tolerance used to check if the current basic solution is integer feasible */ double tol_obj; /* MIP */ /* relative tolerance used to check if the value of the objective function is not better than in the best known integer feasible solution */ int mps_info; /* lpx_write_mps */ /* if this flag is set, the routine lpx_write_mps outputs several comment cards that contains some information about the problem; otherwise the routine outputs no comment cards */ int mps_obj; /* lpx_write_mps */ /* this parameter tells the routine lpx_write_mps how to output the objective function row: 0 - never output objective function row 1 - always output objective function row 2 - output objective function row if and only if the problem has no free rows */ int mps_orig; /* lpx_write_mps */ /* if this flag is set, the routine lpx_write_mps uses original row and column symbolic names; otherwise the routine generates plain names using ordinal numbers of rows and columns */ int mps_wide; /* lpx_write_mps */ /* if this flag is set, the routine lpx_write_mps uses all data fields; otherwise the routine keeps fields 5 and 6 empty */ int mps_free; /* lpx_write_mps */ /* if this flag is set, the routine lpx_write_mps omits column and vector names everytime if possible (free style); otherwise the routine never omits these names (pedantic style) */ int mps_skip; /* lpx_write_mps */ /* if this flag is set, the routine lpx_write_mps skips empty columns (i.e. which has no constraint coefficients); otherwise the routine outputs all columns */ int lpt_orig; /* lpx_write_lpt */ /* if this flag is set, the routine lpx_write_lpt uses original row and column symbolic names; otherwise the routine generates plain names using ordinal numbers of rows and columns */ int presol; /* lpx_simplex */ /* LP presolver option: 0 - do not use LP presolver 1 - use LP presolver */ int binarize; /* lpx_intopt */ /* if this flag is set, the routine lpx_intopt replaces integer columns by binary ones */ int use_cuts; /* lpx_intopt */ /* if this flag is set, the routine lpx_intopt tries generating cutting planes: LPX_C_COVER - mixed cover cuts LPX_C_CLIQUE - clique cuts LPX_C_GOMORY - Gomory's mixed integer cuts LPX_C_ALL - all cuts */ double mip_gap; /* MIP */ /* relative MIP gap tolerance */ }; LPX *lpx_create_prob(void) { /* create problem object */ return glp_create_prob(); } void lpx_set_prob_name(LPX *lp, const char *name) { /* assign (change) problem name */ glp_set_prob_name(lp, name); return; } void lpx_set_obj_name(LPX *lp, const char *name) { /* assign (change) objective function name */ glp_set_obj_name(lp, name); return; } void lpx_set_obj_dir(LPX *lp, int dir) { /* set (change) optimization direction flag */ glp_set_obj_dir(lp, dir - LPX_MIN + GLP_MIN); return; } int lpx_add_rows(LPX *lp, int nrs) { /* add new rows to problem object */ return glp_add_rows(lp, nrs); } int lpx_add_cols(LPX *lp, int ncs) { /* add new columns to problem object */ return glp_add_cols(lp, ncs); } void lpx_set_row_name(LPX *lp, int i, const char *name) { /* assign (change) row name */ glp_set_row_name(lp, i, name); return; } void lpx_set_col_name(LPX *lp, int j, const char *name) { /* assign (change) column name */ glp_set_col_name(lp, j, name); return; } void lpx_set_row_bnds(LPX *lp, int i, int type, double lb, double ub) { /* set (change) row bounds */ glp_set_row_bnds(lp, i, type - LPX_FR + GLP_FR, lb, ub); return; } void lpx_set_col_bnds(LPX *lp, int j, int type, double lb, double ub) { /* set (change) column bounds */ glp_set_col_bnds(lp, j, type - LPX_FR + GLP_FR, lb, ub); return; } void lpx_set_obj_coef(glp_prob *lp, int j, double coef) { /* set (change) obj. coefficient or constant term */ glp_set_obj_coef(lp, j, coef); return; } void lpx_set_mat_row(LPX *lp, int i, int len, const int ind[], const double val[]) { /* set (replace) row of the constraint matrix */ glp_set_mat_row(lp, i, len, ind, val); return; } void lpx_set_mat_col(LPX *lp, int j, int len, const int ind[], const double val[]) { /* set (replace) column of the constraint matrix */ glp_set_mat_col(lp, j, len, ind, val); return; } void lpx_load_matrix(LPX *lp, int ne, const int ia[], const int ja[], const double ar[]) { /* load (replace) the whole constraint matrix */ glp_load_matrix(lp, ne, ia, ja, ar); return; } void lpx_del_rows(LPX *lp, int nrs, const int num[]) { /* delete specified rows from problem object */ glp_del_rows(lp, nrs, num); return; } void lpx_del_cols(LPX *lp, int ncs, const int num[]) { /* delete specified columns from problem object */ glp_del_cols(lp, ncs, num); return; } void lpx_delete_prob(LPX *lp) { /* delete problem object */ glp_delete_prob(lp); return; } const char *lpx_get_prob_name(LPX *lp) { /* retrieve problem name */ return glp_get_prob_name(lp); } const char *lpx_get_obj_name(LPX *lp) { /* retrieve objective function name */ return glp_get_obj_name(lp); } int lpx_get_obj_dir(LPX *lp) { /* retrieve optimization direction flag */ return glp_get_obj_dir(lp) - GLP_MIN + LPX_MIN; } int lpx_get_num_rows(LPX *lp) { /* retrieve number of rows */ return glp_get_num_rows(lp); } int lpx_get_num_cols(LPX *lp) { /* retrieve number of columns */ return glp_get_num_cols(lp); } const char *lpx_get_row_name(LPX *lp, int i) { /* retrieve row name */ return glp_get_row_name(lp, i); } const char *lpx_get_col_name(LPX *lp, int j) { /* retrieve column name */ return glp_get_col_name(lp, j); } int lpx_get_row_type(LPX *lp, int i) { /* retrieve row type */ return glp_get_row_type(lp, i) - GLP_FR + LPX_FR; } double lpx_get_row_lb(glp_prob *lp, int i) { /* retrieve row lower bound */ double lb; lb = glp_get_row_lb(lp, i); if (lb == -DBL_MAX) lb = 0.0; return lb; } double lpx_get_row_ub(glp_prob *lp, int i) { /* retrieve row upper bound */ double ub; ub = glp_get_row_ub(lp, i); if (ub == +DBL_MAX) ub = 0.0; return ub; } void lpx_get_row_bnds(glp_prob *lp, int i, int *typx, double *lb, double *ub) { /* retrieve row bounds */ if (typx != NULL) *typx = lpx_get_row_type(lp, i); if (lb != NULL) *lb = lpx_get_row_lb(lp, i); if (ub != NULL) *ub = lpx_get_row_ub(lp, i); return; } int lpx_get_col_type(LPX *lp, int j) { /* retrieve column type */ return glp_get_col_type(lp, j) - GLP_FR + LPX_FR; } double lpx_get_col_lb(glp_prob *lp, int j) { /* retrieve column lower bound */ double lb; lb = glp_get_col_lb(lp, j); if (lb == -DBL_MAX) lb = 0.0; return lb; } double lpx_get_col_ub(glp_prob *lp, int j) { /* retrieve column upper bound */ double ub; ub = glp_get_col_ub(lp, j); if (ub == +DBL_MAX) ub = 0.0; return ub; } void lpx_get_col_bnds(glp_prob *lp, int j, int *typx, double *lb, double *ub) { /* retrieve column bounds */ if (typx != NULL) *typx = lpx_get_col_type(lp, j); if (lb != NULL) *lb = lpx_get_col_lb(lp, j); if (ub != NULL) *ub = lpx_get_col_ub(lp, j); return; } double lpx_get_obj_coef(LPX *lp, int j) { /* retrieve obj. coefficient or constant term */ return glp_get_obj_coef(lp, j); } int lpx_get_num_nz(LPX *lp) { /* retrieve number of constraint coefficients */ return glp_get_num_nz(lp); } int lpx_get_mat_row(LPX *lp, int i, int ind[], double val[]) { /* retrieve row of the constraint matrix */ return glp_get_mat_row(lp, i, ind, val); } int lpx_get_mat_col(LPX *lp, int j, int ind[], double val[]) { /* retrieve column of the constraint matrix */ return glp_get_mat_col(lp, j, ind, val); } void lpx_create_index(LPX *lp) { /* create the name index */ glp_create_index(lp); return; } int lpx_find_row(LPX *lp, const char *name) { /* find row by its name */ return glp_find_row(lp, name); } int lpx_find_col(LPX *lp, const char *name) { /* find column by its name */ return glp_find_col(lp, name); } void lpx_delete_index(LPX *lp) { /* delete the name index */ glp_delete_index(lp); return; } void lpx_scale_prob(LPX *lp) { /* scale problem data */ switch (lpx_get_int_parm(lp, LPX_K_SCALE)) { case 0: /* no scaling */ glp_unscale_prob(lp); break; case 1: /* equilibration scaling */ glp_scale_prob(lp, GLP_SF_EQ); break; case 2: /* geometric mean scaling */ glp_scale_prob(lp, GLP_SF_GM); break; case 3: /* geometric mean scaling, then equilibration scaling */ glp_scale_prob(lp, GLP_SF_GM | GLP_SF_EQ); break; default: xassert(lp != lp); } return; } void lpx_unscale_prob(LPX *lp) { /* unscale problem data */ glp_unscale_prob(lp); return; } void lpx_set_row_stat(LPX *lp, int i, int stat) { /* set (change) row status */ glp_set_row_stat(lp, i, stat - LPX_BS + GLP_BS); return; } void lpx_set_col_stat(LPX *lp, int j, int stat) { /* set (change) column status */ glp_set_col_stat(lp, j, stat - LPX_BS + GLP_BS); return; } void lpx_std_basis(LPX *lp) { /* construct standard initial LP basis */ glp_std_basis(lp); return; } void lpx_adv_basis(LPX *lp) { /* construct advanced initial LP basis */ glp_adv_basis(lp, 0); return; } void lpx_cpx_basis(LPX *lp) { /* construct Bixby's initial LP basis */ glp_cpx_basis(lp); return; } static void fill_smcp(LPX *lp, glp_smcp *parm) { glp_init_smcp(parm); switch (lpx_get_int_parm(lp, LPX_K_MSGLEV)) { case 0: parm->msg_lev = GLP_MSG_OFF; break; case 1: parm->msg_lev = GLP_MSG_ERR; break; case 2: parm->msg_lev = GLP_MSG_ON; break; case 3: parm->msg_lev = GLP_MSG_ALL; break; default: xassert(lp != lp); } switch (lpx_get_int_parm(lp, LPX_K_DUAL)) { case 0: parm->meth = GLP_PRIMAL; break; case 1: parm->meth = GLP_DUAL; break; default: xassert(lp != lp); } switch (lpx_get_int_parm(lp, LPX_K_PRICE)) { case 0: parm->pricing = GLP_PT_STD; break; case 1: parm->pricing = GLP_PT_PSE; break; default: xassert(lp != lp); } if (lpx_get_real_parm(lp, LPX_K_RELAX) == 0.0) parm->r_test = GLP_RT_STD; else parm->r_test = GLP_RT_HAR; parm->tol_bnd = lpx_get_real_parm(lp, LPX_K_TOLBND); parm->tol_dj = lpx_get_real_parm(lp, LPX_K_TOLDJ); parm->tol_piv = lpx_get_real_parm(lp, LPX_K_TOLPIV); parm->obj_ll = lpx_get_real_parm(lp, LPX_K_OBJLL); parm->obj_ul = lpx_get_real_parm(lp, LPX_K_OBJUL); if (lpx_get_int_parm(lp, LPX_K_ITLIM) < 0) parm->it_lim = INT_MAX; else parm->it_lim = lpx_get_int_parm(lp, LPX_K_ITLIM); if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0) parm->tm_lim = INT_MAX; else parm->tm_lim = (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM)); parm->out_frq = lpx_get_int_parm(lp, LPX_K_OUTFRQ); parm->out_dly = (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_OUTDLY)); switch (lpx_get_int_parm(lp, LPX_K_PRESOL)) { case 0: parm->presolve = GLP_OFF; break; case 1: parm->presolve = GLP_ON; break; default: xassert(lp != lp); } return; } int lpx_simplex(LPX *lp) { /* easy-to-use driver to the simplex method */ glp_smcp parm; int ret; fill_smcp(lp, &parm); ret = glp_simplex(lp, &parm); switch (ret) { case 0: ret = LPX_E_OK; break; case GLP_EBADB: case GLP_ESING: case GLP_ECOND: case GLP_EBOUND: ret = LPX_E_FAULT; break; case GLP_EFAIL: ret = LPX_E_SING; break; case GLP_EOBJLL: ret = LPX_E_OBJLL; break; case GLP_EOBJUL: ret = LPX_E_OBJUL; break; case GLP_EITLIM: ret = LPX_E_ITLIM; break; case GLP_ETMLIM: ret = LPX_E_TMLIM; break; case GLP_ENOPFS: ret = LPX_E_NOPFS; break; case GLP_ENODFS: ret = LPX_E_NODFS; break; default: xassert(ret != ret); } return ret; } int lpx_exact(LPX *lp) { /* easy-to-use driver to the exact simplex method */ glp_smcp parm; int ret; fill_smcp(lp, &parm); ret = glp_exact(lp, &parm); switch (ret) { case 0: ret = LPX_E_OK; break; case GLP_EBADB: case GLP_ESING: case GLP_EBOUND: case GLP_EFAIL: ret = LPX_E_FAULT; break; case GLP_EITLIM: ret = LPX_E_ITLIM; break; case GLP_ETMLIM: ret = LPX_E_TMLIM; break; default: xassert(ret != ret); } return ret; } int lpx_get_status(glp_prob *lp) { /* retrieve generic status of basic solution */ int status; switch (glp_get_status(lp)) { case GLP_OPT: status = LPX_OPT; break; case GLP_FEAS: status = LPX_FEAS; break; case GLP_INFEAS: status = LPX_INFEAS; break; case GLP_NOFEAS: status = LPX_NOFEAS; break; case GLP_UNBND: status = LPX_UNBND; break; case GLP_UNDEF: status = LPX_UNDEF; break; default: xassert(lp != lp); } return status; } int lpx_get_prim_stat(glp_prob *lp) { /* retrieve status of primal basic solution */ return glp_get_prim_stat(lp) - GLP_UNDEF + LPX_P_UNDEF; } int lpx_get_dual_stat(glp_prob *lp) { /* retrieve status of dual basic solution */ return glp_get_dual_stat(lp) - GLP_UNDEF + LPX_D_UNDEF; } double lpx_get_obj_val(LPX *lp) { /* retrieve objective value (basic solution) */ return glp_get_obj_val(lp); } int lpx_get_row_stat(LPX *lp, int i) { /* retrieve row status (basic solution) */ return glp_get_row_stat(lp, i) - GLP_BS + LPX_BS; } double lpx_get_row_prim(LPX *lp, int i) { /* retrieve row primal value (basic solution) */ return glp_get_row_prim(lp, i); } double lpx_get_row_dual(LPX *lp, int i) { /* retrieve row dual value (basic solution) */ return glp_get_row_dual(lp, i); } void lpx_get_row_info(glp_prob *lp, int i, int *tagx, double *vx, double *dx) { /* obtain row solution information */ if (tagx != NULL) *tagx = lpx_get_row_stat(lp, i); if (vx != NULL) *vx = lpx_get_row_prim(lp, i); if (dx != NULL) *dx = lpx_get_row_dual(lp, i); return; } int lpx_get_col_stat(LPX *lp, int j) { /* retrieve column status (basic solution) */ return glp_get_col_stat(lp, j) - GLP_BS + LPX_BS; } double lpx_get_col_prim(LPX *lp, int j) { /* retrieve column primal value (basic solution) */ return glp_get_col_prim(lp, j); } double lpx_get_col_dual(glp_prob *lp, int j) { /* retrieve column dual value (basic solution) */ return glp_get_col_dual(lp, j); } void lpx_get_col_info(glp_prob *lp, int j, int *tagx, double *vx, double *dx) { /* obtain column solution information */ if (tagx != NULL) *tagx = lpx_get_col_stat(lp, j); if (vx != NULL) *vx = lpx_get_col_prim(lp, j); if (dx != NULL) *dx = lpx_get_col_dual(lp, j); return; } int lpx_get_ray_info(LPX *lp) { /* determine what causes primal unboundness */ return glp_get_unbnd_ray(lp); } void lpx_check_kkt(LPX *lp, int scaled, LPXKKT *kkt) { /* check Karush-Kuhn-Tucker conditions */ int ae_ind, re_ind; double ae_max, re_max; xassert(scaled == scaled); glp_check_kkt(lp, GLP_SOL, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, &re_ind); kkt->pe_ae_max = ae_max; kkt->pe_ae_row = ae_ind; kkt->pe_re_max = re_max; kkt->pe_re_row = re_ind; if (re_max <= 1e-9) kkt->pe_quality = 'H'; else if (re_max <= 1e-6) kkt->pe_quality = 'M'; else if (re_max <= 1e-3) kkt->pe_quality = 'L'; else kkt->pe_quality = '?'; glp_check_kkt(lp, GLP_SOL, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, &re_ind); kkt->pb_ae_max = ae_max; kkt->pb_ae_ind = ae_ind; kkt->pb_re_max = re_max; kkt->pb_re_ind = re_ind; if (re_max <= 1e-9) kkt->pb_quality = 'H'; else if (re_max <= 1e-6) kkt->pb_quality = 'M'; else if (re_max <= 1e-3) kkt->pb_quality = 'L'; else kkt->pb_quality = '?'; glp_check_kkt(lp, GLP_SOL, GLP_KKT_DE, &ae_max, &ae_ind, &re_max, &re_ind); kkt->de_ae_max = ae_max; if (ae_ind == 0) kkt->de_ae_col = 0; else kkt->de_ae_col = ae_ind - lp->m; kkt->de_re_max = re_max; if (re_ind == 0) kkt->de_re_col = 0; else kkt->de_re_col = ae_ind - lp->m; if (re_max <= 1e-9) kkt->de_quality = 'H'; else if (re_max <= 1e-6) kkt->de_quality = 'M'; else if (re_max <= 1e-3) kkt->de_quality = 'L'; else kkt->de_quality = '?'; glp_check_kkt(lp, GLP_SOL, GLP_KKT_DB, &ae_max, &ae_ind, &re_max, &re_ind); kkt->db_ae_max = ae_max; kkt->db_ae_ind = ae_ind; kkt->db_re_max = re_max; kkt->db_re_ind = re_ind; if (re_max <= 1e-9) kkt->db_quality = 'H'; else if (re_max <= 1e-6) kkt->db_quality = 'M'; else if (re_max <= 1e-3) kkt->db_quality = 'L'; else kkt->db_quality = '?'; kkt->cs_ae_max = 0.0, kkt->cs_ae_ind = 0; kkt->cs_re_max = 0.0, kkt->cs_re_ind = 0; kkt->cs_quality = 'H'; return; } int lpx_warm_up(LPX *lp) { /* "warm up" LP basis */ int ret; ret = glp_warm_up(lp); if (ret == 0) ret = LPX_E_OK; else if (ret == GLP_EBADB) ret = LPX_E_BADB; else if (ret == GLP_ESING) ret = LPX_E_SING; else if (ret == GLP_ECOND) ret = LPX_E_SING; else xassert(ret != ret); return ret; } int lpx_eval_tab_row(LPX *lp, int k, int ind[], double val[]) { /* compute row of the simplex tableau */ return glp_eval_tab_row(lp, k, ind, val); } int lpx_eval_tab_col(LPX *lp, int k, int ind[], double val[]) { /* compute column of the simplex tableau */ return glp_eval_tab_col(lp, k, ind, val); } int lpx_transform_row(LPX *lp, int len, int ind[], double val[]) { /* transform explicitly specified row */ return glp_transform_row(lp, len, ind, val); } int lpx_transform_col(LPX *lp, int len, int ind[], double val[]) { /* transform explicitly specified column */ return glp_transform_col(lp, len, ind, val); } int lpx_prim_ratio_test(LPX *lp, int len, const int ind[], const double val[], int how, double tol) { /* perform primal ratio test */ int piv; piv = glp_prim_rtest(lp, len, ind, val, how, tol); xassert(0 <= piv && piv <= len); return piv == 0 ? 0 : ind[piv]; } int lpx_dual_ratio_test(LPX *lp, int len, const int ind[], const double val[], int how, double tol) { /* perform dual ratio test */ int piv; piv = glp_dual_rtest(lp, len, ind, val, how, tol); xassert(0 <= piv && piv <= len); return piv == 0 ? 0 : ind[piv]; } int lpx_interior(LPX *lp) { /* easy-to-use driver to the interior-point method */ int ret; ret = glp_interior(lp, NULL); switch (ret) { case 0: ret = LPX_E_OK; break; case GLP_EFAIL: ret = LPX_E_FAULT; break; case GLP_ENOFEAS: ret = LPX_E_NOFEAS; break; case GLP_ENOCVG: ret = LPX_E_NOCONV; break; case GLP_EITLIM: ret = LPX_E_ITLIM; break; case GLP_EINSTAB: ret = LPX_E_INSTAB; break; default: xassert(ret != ret); } return ret; } int lpx_ipt_status(glp_prob *lp) { /* retrieve status of interior-point solution */ int status; switch (glp_ipt_status(lp)) { case GLP_UNDEF: status = LPX_T_UNDEF; break; case GLP_OPT: status = LPX_T_OPT; break; default: xassert(lp != lp); } return status; } double lpx_ipt_obj_val(LPX *lp) { /* retrieve objective value (interior point) */ return glp_ipt_obj_val(lp); } double lpx_ipt_row_prim(LPX *lp, int i) { /* retrieve row primal value (interior point) */ return glp_ipt_row_prim(lp, i); } double lpx_ipt_row_dual(LPX *lp, int i) { /* retrieve row dual value (interior point) */ return glp_ipt_row_dual(lp, i); } double lpx_ipt_col_prim(LPX *lp, int j) { /* retrieve column primal value (interior point) */ return glp_ipt_col_prim(lp, j); } double lpx_ipt_col_dual(LPX *lp, int j) { /* retrieve column dual value (interior point) */ return glp_ipt_col_dual(lp, j); } void lpx_set_class(LPX *lp, int klass) { /* set problem class */ xassert(lp == lp); if (!(klass == LPX_LP || klass == LPX_MIP)) xerror("lpx_set_class: invalid problem class\n"); return; } int lpx_get_class(LPX *lp) { /* determine problem klass */ return glp_get_num_int(lp) == 0 ? LPX_LP : LPX_MIP; } void lpx_set_col_kind(LPX *lp, int j, int kind) { /* set (change) column kind */ glp_set_col_kind(lp, j, kind - LPX_CV + GLP_CV); return; } int lpx_get_col_kind(LPX *lp, int j) { /* retrieve column kind */ return glp_get_col_kind(lp, j) == GLP_CV ? LPX_CV : LPX_IV; } int lpx_get_num_int(LPX *lp) { /* retrieve number of integer columns */ return glp_get_num_int(lp); } int lpx_get_num_bin(LPX *lp) { /* retrieve number of binary columns */ return glp_get_num_bin(lp); } static int solve_mip(LPX *lp, int presolve) { glp_iocp parm; int ret; glp_init_iocp(&parm); switch (lpx_get_int_parm(lp, LPX_K_MSGLEV)) { case 0: parm.msg_lev = GLP_MSG_OFF; break; case 1: parm.msg_lev = GLP_MSG_ERR; break; case 2: parm.msg_lev = GLP_MSG_ON; break; case 3: parm.msg_lev = GLP_MSG_ALL; break; default: xassert(lp != lp); } switch (lpx_get_int_parm(lp, LPX_K_BRANCH)) { case 0: parm.br_tech = GLP_BR_FFV; break; case 1: parm.br_tech = GLP_BR_LFV; break; case 2: parm.br_tech = GLP_BR_DTH; break; case 3: parm.br_tech = GLP_BR_MFV; break; default: xassert(lp != lp); } switch (lpx_get_int_parm(lp, LPX_K_BTRACK)) { case 0: parm.bt_tech = GLP_BT_DFS; break; case 1: parm.bt_tech = GLP_BT_BFS; break; case 2: parm.bt_tech = GLP_BT_BPH; break; case 3: parm.bt_tech = GLP_BT_BLB; break; default: xassert(lp != lp); } parm.tol_int = lpx_get_real_parm(lp, LPX_K_TOLINT); parm.tol_obj = lpx_get_real_parm(lp, LPX_K_TOLOBJ); if (lpx_get_real_parm(lp, LPX_K_TMLIM) < 0.0 || lpx_get_real_parm(lp, LPX_K_TMLIM) > 1e6) parm.tm_lim = INT_MAX; else parm.tm_lim = (int)(1000.0 * lpx_get_real_parm(lp, LPX_K_TMLIM)); parm.mip_gap = lpx_get_real_parm(lp, LPX_K_MIPGAP); if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_GOMORY) parm.gmi_cuts = GLP_ON; else parm.gmi_cuts = GLP_OFF; if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_MIR) parm.mir_cuts = GLP_ON; else parm.mir_cuts = GLP_OFF; if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_COVER) parm.cov_cuts = GLP_ON; else parm.cov_cuts = GLP_OFF; if (lpx_get_int_parm(lp, LPX_K_USECUTS) & LPX_C_CLIQUE) parm.clq_cuts = GLP_ON; else parm.clq_cuts = GLP_OFF; parm.presolve = presolve; if (lpx_get_int_parm(lp, LPX_K_BINARIZE)) parm.binarize = GLP_ON; ret = glp_intopt(lp, &parm); switch (ret) { case 0: ret = LPX_E_OK; break; case GLP_ENOPFS: ret = LPX_E_NOPFS; break; case GLP_ENODFS: ret = LPX_E_NODFS; break; case GLP_EBOUND: case GLP_EROOT: ret = LPX_E_FAULT; break; case GLP_EFAIL: ret = LPX_E_SING; break; case GLP_EMIPGAP: ret = LPX_E_MIPGAP; break; case GLP_ETMLIM: ret = LPX_E_TMLIM; break; default: xassert(ret != ret); } return ret; } int lpx_integer(LPX *lp) { /* easy-to-use driver to the branch-and-bound method */ return solve_mip(lp, GLP_OFF); } int lpx_intopt(LPX *lp) { /* easy-to-use driver to the branch-and-bound method */ return solve_mip(lp, GLP_ON); } int lpx_mip_status(glp_prob *lp) { /* retrieve status of MIP solution */ int status; switch (glp_mip_status(lp)) { case GLP_UNDEF: status = LPX_I_UNDEF; break; case GLP_OPT: status = LPX_I_OPT; break; case GLP_FEAS: status = LPX_I_FEAS; break; case GLP_NOFEAS: status = LPX_I_NOFEAS; break; default: xassert(lp != lp); } return status; } double lpx_mip_obj_val(LPX *lp) { /* retrieve objective value (MIP solution) */ return glp_mip_obj_val(lp); } double lpx_mip_row_val(LPX *lp, int i) { /* retrieve row value (MIP solution) */ return glp_mip_row_val(lp, i); } double lpx_mip_col_val(LPX *lp, int j) { /* retrieve column value (MIP solution) */ return glp_mip_col_val(lp, j); } void lpx_check_int(LPX *lp, LPXKKT *kkt) { /* check integer feasibility conditions */ int ae_ind, re_ind; double ae_max, re_max; glp_check_kkt(lp, GLP_MIP, GLP_KKT_PE, &ae_max, &ae_ind, &re_max, &re_ind); kkt->pe_ae_max = ae_max; kkt->pe_ae_row = ae_ind; kkt->pe_re_max = re_max; kkt->pe_re_row = re_ind; if (re_max <= 1e-9) kkt->pe_quality = 'H'; else if (re_max <= 1e-6) kkt->pe_quality = 'M'; else if (re_max <= 1e-3) kkt->pe_quality = 'L'; else kkt->pe_quality = '?'; glp_check_kkt(lp, GLP_MIP, GLP_KKT_PB, &ae_max, &ae_ind, &re_max, &re_ind); kkt->pb_ae_max = ae_max; kkt->pb_ae_ind = ae_ind; kkt->pb_re_max = re_max; kkt->pb_re_ind = re_ind; if (re_max <= 1e-9) kkt->pb_quality = 'H'; else if (re_max <= 1e-6) kkt->pb_quality = 'M'; else if (re_max <= 1e-3) kkt->pb_quality = 'L'; else kkt->pb_quality = '?'; return; } #if 1 /* 17/XI-2009 */ static void reset_parms(LPX *lp) { /* reset control parameters to default values */ struct LPXCPS *cps = lp->parms; xassert(cps != NULL); cps->msg_lev = 3; cps->scale = 1; cps->dual = 0; cps->price = 1; cps->relax = 0.07; cps->tol_bnd = 1e-7; cps->tol_dj = 1e-7; cps->tol_piv = 1e-9; cps->round = 0; cps->obj_ll = -DBL_MAX; cps->obj_ul = +DBL_MAX; cps->it_lim = -1; #if 0 /* 02/XII-2010 */ lp->it_cnt = 0; #endif cps->tm_lim = -1.0; cps->out_frq = 200; cps->out_dly = 0.0; cps->branch = 2; cps->btrack = 3; cps->tol_int = 1e-5; cps->tol_obj = 1e-7; cps->mps_info = 1; cps->mps_obj = 2; cps->mps_orig = 0; cps->mps_wide = 1; cps->mps_free = 0; cps->mps_skip = 0; cps->lpt_orig = 0; cps->presol = 0; cps->binarize = 0; cps->use_cuts = 0; cps->mip_gap = 0.0; return; } #endif #if 1 /* 17/XI-2009 */ static struct LPXCPS *access_parms(LPX *lp) { /* allocate and initialize control parameters, if necessary */ if (lp->parms == NULL) { lp->parms = xmalloc(sizeof(struct LPXCPS)); reset_parms(lp); } return lp->parms; } #endif #if 1 /* 17/XI-2009 */ void lpx_reset_parms(LPX *lp) { /* reset control parameters to default values */ access_parms(lp); reset_parms(lp); return; } #endif void lpx_set_int_parm(LPX *lp, int parm, int val) { /* set (change) integer control parameter */ #if 0 /* 17/XI-2009 */ struct LPXCPS *cps = lp->cps; #else struct LPXCPS *cps = access_parms(lp); #endif switch (parm) { case LPX_K_MSGLEV: if (!(0 <= val && val <= 3)) xerror("lpx_set_int_parm: MSGLEV = %d; invalid value\n", val); cps->msg_lev = val; break; case LPX_K_SCALE: if (!(0 <= val && val <= 3)) xerror("lpx_set_int_parm: SCALE = %d; invalid value\n", val); cps->scale = val; break; case LPX_K_DUAL: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: DUAL = %d; invalid value\n", val); cps->dual = val; break; case LPX_K_PRICE: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: PRICE = %d; invalid value\n", val); cps->price = val; break; case LPX_K_ROUND: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: ROUND = %d; invalid value\n", val); cps->round = val; break; case LPX_K_ITLIM: cps->it_lim = val; break; case LPX_K_ITCNT: lp->it_cnt = val; break; case LPX_K_OUTFRQ: if (!(val > 0)) xerror("lpx_set_int_parm: OUTFRQ = %d; invalid value\n", val); cps->out_frq = val; break; case LPX_K_BRANCH: if (!(val == 0 || val == 1 || val == 2 || val == 3)) xerror("lpx_set_int_parm: BRANCH = %d; invalid value\n", val); cps->branch = val; break; case LPX_K_BTRACK: if (!(val == 0 || val == 1 || val == 2 || val == 3)) xerror("lpx_set_int_parm: BTRACK = %d; invalid value\n", val); cps->btrack = val; break; case LPX_K_MPSINFO: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: MPSINFO = %d; invalid value\n", val); cps->mps_info = val; break; case LPX_K_MPSOBJ: if (!(val == 0 || val == 1 || val == 2)) xerror("lpx_set_int_parm: MPSOBJ = %d; invalid value\n", val); cps->mps_obj = val; break; case LPX_K_MPSORIG: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: MPSORIG = %d; invalid value\n", val); cps->mps_orig = val; break; case LPX_K_MPSWIDE: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: MPSWIDE = %d; invalid value\n", val); cps->mps_wide = val; break; case LPX_K_MPSFREE: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: MPSFREE = %d; invalid value\n", val); cps->mps_free = val; break; case LPX_K_MPSSKIP: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: MPSSKIP = %d; invalid value\n", val); cps->mps_skip = val; break; case LPX_K_LPTORIG: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: LPTORIG = %d; invalid value\n", val); cps->lpt_orig = val; break; case LPX_K_PRESOL: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: PRESOL = %d; invalid value\n", val); cps->presol = val; break; case LPX_K_BINARIZE: if (!(val == 0 || val == 1)) xerror("lpx_set_int_parm: BINARIZE = %d; invalid value\n" , val); cps->binarize = val; break; case LPX_K_USECUTS: if (val & ~LPX_C_ALL) xerror("lpx_set_int_parm: USECUTS = 0x%X; invalid value\n", val); cps->use_cuts = val; break; case LPX_K_BFTYPE: #if 0 if (!(1 <= val && val <= 3)) xerror("lpx_set_int_parm: BFTYPE = %d; invalid value\n", val); cps->bf_type = val; #else { glp_bfcp parm; glp_get_bfcp(lp, &parm); switch (val) { case 1: parm.type = GLP_BF_FT; break; case 2: parm.type = GLP_BF_BG; break; case 3: parm.type = GLP_BF_GR; break; default: xerror("lpx_set_int_parm: BFTYPE = %d; invalid val" "ue\n", val); } glp_set_bfcp(lp, &parm); } #endif break; default: xerror("lpx_set_int_parm: parm = %d; invalid parameter\n", parm); } return; } int lpx_get_int_parm(LPX *lp, int parm) { /* query integer control parameter */ #if 0 /* 17/XI-2009 */ struct LPXCPS *cps = lp->cps; #else struct LPXCPS *cps = access_parms(lp); #endif int val = 0; switch (parm) { case LPX_K_MSGLEV: val = cps->msg_lev; break; case LPX_K_SCALE: val = cps->scale; break; case LPX_K_DUAL: val = cps->dual; break; case LPX_K_PRICE: val = cps->price; break; case LPX_K_ROUND: val = cps->round; break; case LPX_K_ITLIM: val = cps->it_lim; break; case LPX_K_ITCNT: val = lp->it_cnt; break; case LPX_K_OUTFRQ: val = cps->out_frq; break; case LPX_K_BRANCH: val = cps->branch; break; case LPX_K_BTRACK: val = cps->btrack; break; case LPX_K_MPSINFO: val = cps->mps_info; break; case LPX_K_MPSOBJ: val = cps->mps_obj; break; case LPX_K_MPSORIG: val = cps->mps_orig; break; case LPX_K_MPSWIDE: val = cps->mps_wide; break; case LPX_K_MPSFREE: val = cps->mps_free; break; case LPX_K_MPSSKIP: val = cps->mps_skip; break; case LPX_K_LPTORIG: val = cps->lpt_orig; break; case LPX_K_PRESOL: val = cps->presol; break; case LPX_K_BINARIZE: val = cps->binarize; break; case LPX_K_USECUTS: val = cps->use_cuts; break; case LPX_K_BFTYPE: #if 0 val = cps->bf_type; break; #else { glp_bfcp parm; glp_get_bfcp(lp, &parm); switch (parm.type) { case GLP_BF_FT: val = 1; break; case GLP_BF_BG: val = 2; break; case GLP_BF_GR: val = 3; break; default: xassert(lp != lp); } } break; #endif default: xerror("lpx_get_int_parm: parm = %d; invalid parameter\n", parm); } return val; } void lpx_set_real_parm(LPX *lp, int parm, double val) { /* set (change) real control parameter */ #if 0 /* 17/XI-2009 */ struct LPXCPS *cps = lp->cps; #else struct LPXCPS *cps = access_parms(lp); #endif switch (parm) { case LPX_K_RELAX: if (!(0.0 <= val && val <= 1.0)) xerror("lpx_set_real_parm: RELAX = %g; invalid value\n", val); cps->relax = val; break; case LPX_K_TOLBND: if (!(DBL_EPSILON <= val && val <= 0.001)) xerror("lpx_set_real_parm: TOLBND = %g; invalid value\n", val); #if 0 if (cps->tol_bnd > val) { /* invalidate the basic solution */ lp->p_stat = LPX_P_UNDEF; lp->d_stat = LPX_D_UNDEF; } #endif cps->tol_bnd = val; break; case LPX_K_TOLDJ: if (!(DBL_EPSILON <= val && val <= 0.001)) xerror("lpx_set_real_parm: TOLDJ = %g; invalid value\n", val); #if 0 if (cps->tol_dj > val) { /* invalidate the basic solution */ lp->p_stat = LPX_P_UNDEF; lp->d_stat = LPX_D_UNDEF; } #endif cps->tol_dj = val; break; case LPX_K_TOLPIV: if (!(DBL_EPSILON <= val && val <= 0.001)) xerror("lpx_set_real_parm: TOLPIV = %g; invalid value\n", val); cps->tol_piv = val; break; case LPX_K_OBJLL: cps->obj_ll = val; break; case LPX_K_OBJUL: cps->obj_ul = val; break; case LPX_K_TMLIM: cps->tm_lim = val; break; case LPX_K_OUTDLY: cps->out_dly = val; break; case LPX_K_TOLINT: if (!(DBL_EPSILON <= val && val <= 0.001)) xerror("lpx_set_real_parm: TOLINT = %g; invalid value\n", val); cps->tol_int = val; break; case LPX_K_TOLOBJ: if (!(DBL_EPSILON <= val && val <= 0.001)) xerror("lpx_set_real_parm: TOLOBJ = %g; invalid value\n", val); cps->tol_obj = val; break; case LPX_K_MIPGAP: if (val < 0.0) xerror("lpx_set_real_parm: MIPGAP = %g; invalid value\n", val); cps->mip_gap = val; break; default: xerror("lpx_set_real_parm: parm = %d; invalid parameter\n", parm); } return; } double lpx_get_real_parm(LPX *lp, int parm) { /* query real control parameter */ #if 0 /* 17/XI-2009 */ struct LPXCPS *cps = lp->cps; #else struct LPXCPS *cps = access_parms(lp); #endif double val = 0.0; switch (parm) { case LPX_K_RELAX: val = cps->relax; break; case LPX_K_TOLBND: val = cps->tol_bnd; break; case LPX_K_TOLDJ: val = cps->tol_dj; break; case LPX_K_TOLPIV: val = cps->tol_piv; break; case LPX_K_OBJLL: val = cps->obj_ll; break; case LPX_K_OBJUL: val = cps->obj_ul; break; case LPX_K_TMLIM: val = cps->tm_lim; break; case LPX_K_OUTDLY: val = cps->out_dly; break; case LPX_K_TOLINT: val = cps->tol_int; break; case LPX_K_TOLOBJ: val = cps->tol_obj; break; case LPX_K_MIPGAP: val = cps->mip_gap; break; default: xerror("lpx_get_real_parm: parm = %d; invalid parameter\n", parm); } return val; } LPX *lpx_read_mps(const char *fname) { /* read problem data in fixed MPS format */ LPX *lp = lpx_create_prob(); if (glp_read_mps(lp, GLP_MPS_DECK, NULL, fname)) lpx_delete_prob(lp), lp = NULL; return lp; } int lpx_write_mps(LPX *lp, const char *fname) { /* write problem data in fixed MPS format */ return glp_write_mps(lp, GLP_MPS_DECK, NULL, fname); } int lpx_read_bas(LPX *lp, const char *fname) { /* read LP basis in fixed MPS format */ #if 0 /* 13/IV-2009 */ return read_bas(lp, fname); #else xassert(lp == lp); xassert(fname == fname); xerror("lpx_read_bas: operation not supported\n"); return 0; #endif } int lpx_write_bas(LPX *lp, const char *fname) { /* write LP basis in fixed MPS format */ #if 0 /* 13/IV-2009 */ return write_bas(lp, fname); #else xassert(lp == lp); xassert(fname == fname); xerror("lpx_write_bas: operation not supported\n"); return 0; #endif } LPX *lpx_read_freemps(const char *fname) { /* read problem data in free MPS format */ LPX *lp = lpx_create_prob(); if (glp_read_mps(lp, GLP_MPS_FILE, NULL, fname)) lpx_delete_prob(lp), lp = NULL; return lp; } int lpx_write_freemps(LPX *lp, const char *fname) { /* write problem data in free MPS format */ return glp_write_mps(lp, GLP_MPS_FILE, NULL, fname); } LPX *lpx_read_cpxlp(const char *fname) { /* read problem data in CPLEX LP format */ LPX *lp; lp = lpx_create_prob(); if (glp_read_lp(lp, NULL, fname)) lpx_delete_prob(lp), lp = NULL; return lp; } int lpx_write_cpxlp(LPX *lp, const char *fname) { /* write problem data in CPLEX LP format */ return glp_write_lp(lp, NULL, fname); } LPX *lpx_read_model(const char *model, const char *data, const char *output) { /* read LP/MIP model written in GNU MathProg language */ LPX *lp = NULL; glp_tran *tran; /* allocate the translator workspace */ tran = glp_mpl_alloc_wksp(); /* read model section and optional data section */ if (glp_mpl_read_model(tran, model, data != NULL)) goto done; /* read separate data section, if required */ if (data != NULL) if (glp_mpl_read_data(tran, data)) goto done; /* generate the model */ if (glp_mpl_generate(tran, output)) goto done; /* build the problem instance from the model */ lp = glp_create_prob(); glp_mpl_build_prob(tran, lp); done: /* free the translator workspace */ glp_mpl_free_wksp(tran); /* bring the problem object to the calling program */ return lp; } int lpx_print_prob(LPX *lp, const char *fname) { /* write problem data in plain text format */ return glp_write_lp(lp, NULL, fname); } int lpx_print_sol(LPX *lp, const char *fname) { /* write LP problem solution in printable format */ return glp_print_sol(lp, fname); } int lpx_print_sens_bnds(LPX *lp, const char *fname) { /* write bounds sensitivity information */ if (glp_get_status(lp) == GLP_OPT && !glp_bf_exists(lp)) glp_factorize(lp); return glp_print_ranges(lp, 0, NULL, 0, fname); } int lpx_print_ips(LPX *lp, const char *fname) { /* write interior point solution in printable format */ return glp_print_ipt(lp, fname); } int lpx_print_mip(LPX *lp, const char *fname) { /* write MIP problem solution in printable format */ return glp_print_mip(lp, fname); } int lpx_is_b_avail(glp_prob *lp) { /* check if LP basis is available */ return glp_bf_exists(lp); } int lpx_main(int argc, const char *argv[]) { /* stand-alone LP/MIP solver */ return glp_main(argc, argv); } /* eof */ glpk-4.52.1/src/glplpx02.c0000644000062000006210000002377712175147600014344 0ustar maomkpasswd/* glplpx02.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * lpx_put_solution - store basic solution components * * SYNOPSIS * * void lpx_put_solution(glp_prob *lp, int inval, const int *p_stat, * const int *d_stat, const double *obj_val, const int r_stat[], * const double r_prim[], const double r_dual[], const int c_stat[], * const double c_prim[], const double c_dual[]) * * DESCRIPTION * * The routine lpx_put_solution stores basic solution components to the * specified problem object. * * The parameter inval is the basis factorization invalidity flag. * If this flag is clear, the current status of the basis factorization * remains unchanged. If this flag is set, the routine invalidates the * basis factorization. * * The parameter p_stat is a pointer to the status of primal basic * solution, which should be specified as follows: * * GLP_UNDEF - primal solution is undefined; * GLP_FEAS - primal solution is feasible; * GLP_INFEAS - primal solution is infeasible; * GLP_NOFEAS - no primal feasible solution exists. * * If the parameter p_stat is NULL, the current status of primal basic * solution remains unchanged. * * The parameter d_stat is a pointer to the status of dual basic * solution, which should be specified as follows: * * GLP_UNDEF - dual solution is undefined; * GLP_FEAS - dual solution is feasible; * GLP_INFEAS - dual solution is infeasible; * GLP_NOFEAS - no dual feasible solution exists. * * If the parameter d_stat is NULL, the current status of dual basic * solution remains unchanged. * * The parameter obj_val is a pointer to the objective function value. * If it is NULL, the current value of the objective function remains * unchanged. * * The array element r_stat[i], 1 <= i <= m (where m is the number of * rows in the problem object), specifies the status of i-th auxiliary * variable, which should be specified as follows: * * GLP_BS - basic variable; * GLP_NL - non-basic variable on lower bound; * GLP_NU - non-basic variable on upper bound; * GLP_NF - non-basic free variable; * GLP_NS - non-basic fixed variable. * * If the parameter r_stat is NULL, the current statuses of auxiliary * variables remain unchanged. * * The array element r_prim[i], 1 <= i <= m (where m is the number of * rows in the problem object), specifies a primal value of i-th * auxiliary variable. If the parameter r_prim is NULL, the current * primal values of auxiliary variables remain unchanged. * * The array element r_dual[i], 1 <= i <= m (where m is the number of * rows in the problem object), specifies a dual value (reduced cost) * of i-th auxiliary variable. If the parameter r_dual is NULL, the * current dual values of auxiliary variables remain unchanged. * * The array element c_stat[j], 1 <= j <= n (where n is the number of * columns in the problem object), specifies the status of j-th * structural variable, which should be specified as follows: * * GLP_BS - basic variable; * GLP_NL - non-basic variable on lower bound; * GLP_NU - non-basic variable on upper bound; * GLP_NF - non-basic free variable; * GLP_NS - non-basic fixed variable. * * If the parameter c_stat is NULL, the current statuses of structural * variables remain unchanged. * * The array element c_prim[j], 1 <= j <= n (where n is the number of * columns in the problem object), specifies a primal value of j-th * structural variable. If the parameter c_prim is NULL, the current * primal values of structural variables remain unchanged. * * The array element c_dual[j], 1 <= j <= n (where n is the number of * columns in the problem object), specifies a dual value (reduced cost) * of j-th structural variable. If the parameter c_dual is NULL, the * current dual values of structural variables remain unchanged. */ void lpx_put_solution(glp_prob *lp, int inval, const int *p_stat, const int *d_stat, const double *obj_val, const int r_stat[], const double r_prim[], const double r_dual[], const int c_stat[], const double c_prim[], const double c_dual[]) { GLPROW *row; GLPCOL *col; int i, j; /* invalidate the basis factorization, if required */ if (inval) lp->valid = 0; /* store primal status */ if (p_stat != NULL) { if (!(*p_stat == GLP_UNDEF || *p_stat == GLP_FEAS || *p_stat == GLP_INFEAS || *p_stat == GLP_NOFEAS)) xerror("lpx_put_solution: p_stat = %d; invalid primal statu" "s\n", *p_stat); lp->pbs_stat = *p_stat; } /* store dual status */ if (d_stat != NULL) { if (!(*d_stat == GLP_UNDEF || *d_stat == GLP_FEAS || *d_stat == GLP_INFEAS || *d_stat == GLP_NOFEAS)) xerror("lpx_put_solution: d_stat = %d; invalid dual status " "\n", *d_stat); lp->dbs_stat = *d_stat; } /* store objective function value */ if (obj_val != NULL) lp->obj_val = *obj_val; /* store row solution components */ for (i = 1; i <= lp->m; i++) { row = lp->row[i]; if (r_stat != NULL) { if (!(r_stat[i] == GLP_BS || row->type == GLP_FR && r_stat[i] == GLP_NF || row->type == GLP_LO && r_stat[i] == GLP_NL || row->type == GLP_UP && r_stat[i] == GLP_NU || row->type == GLP_DB && r_stat[i] == GLP_NL || row->type == GLP_DB && r_stat[i] == GLP_NU || row->type == GLP_FX && r_stat[i] == GLP_NS)) xerror("lpx_put_solution: r_stat[%d] = %d; invalid row s" "tatus\n", i, r_stat[i]); row->stat = r_stat[i]; } if (r_prim != NULL) row->prim = r_prim[i]; if (r_dual != NULL) row->dual = r_dual[i]; } /* store column solution components */ for (j = 1; j <= lp->n; j++) { col = lp->col[j]; if (c_stat != NULL) { if (!(c_stat[j] == GLP_BS || col->type == GLP_FR && c_stat[j] == GLP_NF || col->type == GLP_LO && c_stat[j] == GLP_NL || col->type == GLP_UP && c_stat[j] == GLP_NU || col->type == GLP_DB && c_stat[j] == GLP_NL || col->type == GLP_DB && c_stat[j] == GLP_NU || col->type == GLP_FX && c_stat[j] == GLP_NS)) xerror("lpx_put_solution: c_stat[%d] = %d; invalid colum" "n status\n", j, c_stat[j]); col->stat = c_stat[j]; } if (c_prim != NULL) col->prim = c_prim[j]; if (c_dual != NULL) col->dual = c_dual[j]; } return; } /*---------------------------------------------------------------------- -- lpx_put_mip_soln - store mixed integer solution components. -- -- *Synopsis* -- -- #include "glplpx.h" -- void lpx_put_mip_soln(glp_prob *lp, int i_stat, double row_mipx[], -- double col_mipx[]); -- -- *Description* -- -- The routine lpx_put_mip_soln stores solution components obtained by -- branch-and-bound solver into the specified problem object. -- -- NOTE: This routine is intended for internal use only. */ void lpx_put_mip_soln(glp_prob *lp, int i_stat, double row_mipx[], double col_mipx[]) { GLPROW *row; GLPCOL *col; int i, j; double sum; /* store mixed integer status */ #if 0 if (!(i_stat == LPX_I_UNDEF || i_stat == LPX_I_OPT || i_stat == LPX_I_FEAS || i_stat == LPX_I_NOFEAS)) fault("lpx_put_mip_soln: i_stat = %d; invalid mixed integer st" "atus", i_stat); lp->i_stat = i_stat; #else switch (i_stat) { case LPX_I_UNDEF: lp->mip_stat = GLP_UNDEF; break; case LPX_I_OPT: lp->mip_stat = GLP_OPT; break; case LPX_I_FEAS: lp->mip_stat = GLP_FEAS; break; case LPX_I_NOFEAS: lp->mip_stat = GLP_NOFEAS; break; default: xerror("lpx_put_mip_soln: i_stat = %d; invalid mixed intege" "r status\n", i_stat); } #endif /* store row solution components */ if (row_mipx != NULL) { for (i = 1; i <= lp->m; i++) { row = lp->row[i]; row->mipx = row_mipx[i]; } } /* store column solution components */ if (col_mipx != NULL) { for (j = 1; j <= lp->n; j++) { col = lp->col[j]; col->mipx = col_mipx[j]; } } /* if the solution is claimed to be integer feasible, check it */ if (lp->mip_stat == GLP_OPT || lp->mip_stat == GLP_FEAS) { for (j = 1; j <= lp->n; j++) { col = lp->col[j]; if (col->kind == GLP_IV && col->mipx != floor(col->mipx)) xerror("lpx_put_mip_soln: col_mipx[%d] = %.*g; must be i" "ntegral\n", j, DBL_DIG, col->mipx); } } /* compute the objective function value */ sum = lp->c0; for (j = 1; j <= lp->n; j++) { col = lp->col[j]; sum += col->coef * col->mipx; } lp->mip_obj = sum; return; } /* eof */ glpk-4.52.1/src/glplpx03.c0000644000062000006210000002130512175147600014326 0ustar maomkpasswd/* glplpx03.c (OPB format) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Author: Oscar Gustafsson . * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_ERRNO #define _GLPSTD_STDIO #include "glpapi.h" #if 0 /* 24/XII-2009; by mao */ #include "glpipp.h" #endif /*---------------------------------------------------------------------- -- lpx_write_pb - write problem data in (normalized) OPB format. -- -- *Synopsis* -- -- #include "glplpx.h" -- int lpx_write_pb(LPX *lp, const char *fname, int normalized, -- int binarize); -- -- *Description* -- -- The routine lpx_write_pb writes problem data in OPB format -- to an output text file whose name is the character string fname. -- If normalized is non-zero the output will be generated in a -- normalized form with sequentially numbered variables, x1, x2 etc. -- If binarize, any integer variable will be repalzec by binary ones, -- see ipp_binarize -- -- *Returns* -- -- If the operation was successful, the routine returns zero. Otherwise -- the routine prints an error message and returns non-zero. */ #if 1 /* 24/XII-2009; by mao (disabled, because IPP was removed) */ int lpx_write_pb(LPX *lp, const char *fname, int normalized, int binarize) { xassert(lp == lp); xassert(fname == fname); xassert(normalized == normalized); xassert(binarize == binarize); xprintf("lpx_write_pb: sorry, currently this operation is not ava" "ilable\n"); return 1; } #else int lpx_write_pb(LPX *lp, const char *fname, int normalized, int binarize) { FILE* fp; int m,n,i,j,k,o,nonfree=0, obj_dir, dbl, *ndx, row_type, emptylhs=0; double coeff, *val, bound, constant/*=0.0*/; char* objconstname = "dummy_one"; char* emptylhsname = "dummy_zero"; /* Variables needed for possible binarization */ /*LPX* tlp;*/ IPP *ipp = NULL; /*tlp=lp;*/ if(binarize) /* Transform integer variables to binary ones */ { ipp = ipp_create_wksp(); ipp_load_orig(ipp, lp); ipp_binarize(ipp); lp = ipp_build_prob(ipp); } fp = fopen(fname, "w"); if(fp!= NULL) { xprintf( "lpx_write_pb: writing problem in %sOPB format to `%s'...\n", (normalized?"normalized ":""), fname); m = glp_get_num_rows(lp); n = glp_get_num_cols(lp); for(i=1;i<=m;i++) { switch(glp_get_row_type(lp,i)) { case GLP_LO: case GLP_UP: case GLP_FX: { nonfree += 1; break; } case GLP_DB: { nonfree += 2; break; } } } constant=glp_get_obj_coef(lp,0); fprintf(fp,"* #variables = %d #constraints = %d\n", n + (constant == 0?1:0), nonfree + (constant == 0?1:0)); /* Objective function */ obj_dir = glp_get_obj_dir(lp); fprintf(fp,"min: "); for(i=1;i<=n;i++) { coeff = glp_get_obj_coef(lp,i); if(coeff != 0.0) { if(obj_dir == GLP_MAX) coeff=-coeff; if(normalized) fprintf(fp, " %d x%d", (int)coeff, i); else fprintf(fp, " %d*%s", (int)coeff, glp_get_col_name(lp,i)); } } if(constant) { if(normalized) fprintf(fp, " %d x%d", (int)constant, n+1); else fprintf(fp, " %d*%s", (int)constant, objconstname); } fprintf(fp,";\n"); if(normalized && !binarize) /* Name substitution */ { fprintf(fp,"* Variable name substitution:\n"); for(j=1;j<=n;j++) { fprintf(fp, "* x%d = %s\n", j, glp_get_col_name(lp,j)); } if(constant) fprintf(fp, "* x%d = %s\n", n+1, objconstname); } ndx = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(double)); /* Constraints */ for(j=1;j<=m;j++) { row_type=glp_get_row_type(lp,j); if(row_type!=GLP_FR) { if(row_type == GLP_DB) { dbl=2; row_type = GLP_UP; } else { dbl=1; } k=glp_get_mat_row(lp, j, ndx, val); for(o=1;o<=dbl;o++) { if(o==2) { row_type = GLP_LO; } if(k==0) /* Empty LHS */ { emptylhs = 1; if(normalized) { fprintf(fp, "0 x%d ", n+2); } else { fprintf(fp, "0*%s ", emptylhsname); } } for(i=1;i<=k;i++) { if(val[i] != 0.0) { if(normalized) { fprintf(fp, "%d x%d ", (row_type==GLP_UP)?(-(int)val[i]):((int)val[i]), ndx[i]); } else { fprintf(fp, "%d*%s ", (int)val[i], glp_get_col_name(lp,ndx[i])); } } } switch(row_type) { case GLP_LO: { fprintf(fp, ">="); bound = glp_get_row_lb(lp,j); break; } case GLP_UP: { if(normalized) { fprintf(fp, ">="); bound = -glp_get_row_ub(lp,j); } else { fprintf(fp, "<="); bound = glp_get_row_ub(lp,j); } break; } case GLP_FX: { fprintf(fp, "="); bound = glp_get_row_lb(lp,j); break; } } fprintf(fp," %d;\n",(int)bound); } } } xfree(ndx); xfree(val); if(constant) { xprintf( "lpx_write_pb: adding constant objective function variable\n"); if(normalized) fprintf(fp, "1 x%d = 1;\n", n+1); else fprintf(fp, "1*%s = 1;\n", objconstname); } if(emptylhs) { xprintf( "lpx_write_pb: adding dummy variable for empty left-hand si" "de constraint\n"); if(normalized) fprintf(fp, "1 x%d = 0;\n", n+2); else fprintf(fp, "1*%s = 0;\n", emptylhsname); } } else { xprintf("Problems opening file for writing: %s\n", fname); return(1); } fflush(fp); if (ferror(fp)) { xprintf("lpx_write_pb: can't write to `%s' - %s\n", fname, strerror(errno)); goto fail; } fclose(fp); if(binarize) { /* delete the resultant problem object */ if (lp != NULL) lpx_delete_prob(lp); /* delete MIP presolver workspace */ if (ipp != NULL) ipp_delete_wksp(ipp); /*lp=tlp;*/ } return 0; fail: if (fp != NULL) fclose(fp); return 1; } #endif /* eof */ glpk-4.52.1/src/glplux.c0000644000062000006210000011403512175147600014173 0ustar maomkpasswd/* glplux.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glplux.h" #include "env.h" #define xfault xerror #define dmp_create_poolx(size) dmp_create_pool() /*---------------------------------------------------------------------- // lux_create - create LU-factorization. // // SYNOPSIS // // #include "glplux.h" // LUX *lux_create(int n); // // DESCRIPTION // // The routine lux_create creates LU-factorization data structure for // a matrix of the order n. Initially the factorization corresponds to // the unity matrix (F = V = P = Q = I, so A = I). // // RETURNS // // The routine returns a pointer to the created LU-factorization data // structure, which represents the unity matrix of the order n. */ LUX *lux_create(int n) { LUX *lux; int k; if (n < 1) xfault("lux_create: n = %d; invalid parameter\n", n); lux = xmalloc(sizeof(LUX)); lux->n = n; lux->pool = dmp_create_poolx(sizeof(LUXELM)); lux->F_row = xcalloc(1+n, sizeof(LUXELM *)); lux->F_col = xcalloc(1+n, sizeof(LUXELM *)); lux->V_piv = xcalloc(1+n, sizeof(mpq_t)); lux->V_row = xcalloc(1+n, sizeof(LUXELM *)); lux->V_col = xcalloc(1+n, sizeof(LUXELM *)); lux->P_row = xcalloc(1+n, sizeof(int)); lux->P_col = xcalloc(1+n, sizeof(int)); lux->Q_row = xcalloc(1+n, sizeof(int)); lux->Q_col = xcalloc(1+n, sizeof(int)); for (k = 1; k <= n; k++) { lux->F_row[k] = lux->F_col[k] = NULL; mpq_init(lux->V_piv[k]); mpq_set_si(lux->V_piv[k], 1, 1); lux->V_row[k] = lux->V_col[k] = NULL; lux->P_row[k] = lux->P_col[k] = k; lux->Q_row[k] = lux->Q_col[k] = k; } lux->rank = n; return lux; } /*---------------------------------------------------------------------- // initialize - initialize LU-factorization data structures. // // This routine initializes data structures for subsequent computing // the LU-factorization of a given matrix A, which is specified by the // formal routine col. On exit V = A and F = P = Q = I, where I is the // unity matrix. */ static void initialize(LUX *lux, int (*col)(void *info, int j, int ind[], mpq_t val[]), void *info, LUXWKA *wka) { int n = lux->n; DMP *pool = lux->pool; LUXELM **F_row = lux->F_row; LUXELM **F_col = lux->F_col; mpq_t *V_piv = lux->V_piv; LUXELM **V_row = lux->V_row; LUXELM **V_col = lux->V_col; int *P_row = lux->P_row; int *P_col = lux->P_col; int *Q_row = lux->Q_row; int *Q_col = lux->Q_col; int *R_len = wka->R_len; int *R_head = wka->R_head; int *R_prev = wka->R_prev; int *R_next = wka->R_next; int *C_len = wka->C_len; int *C_head = wka->C_head; int *C_prev = wka->C_prev; int *C_next = wka->C_next; LUXELM *fij, *vij; int i, j, k, len, *ind; mpq_t *val; /* F := I */ for (i = 1; i <= n; i++) { while (F_row[i] != NULL) { fij = F_row[i], F_row[i] = fij->r_next; mpq_clear(fij->val); dmp_free_atom(pool, fij, sizeof(LUXELM)); } } for (j = 1; j <= n; j++) F_col[j] = NULL; /* V := 0 */ for (k = 1; k <= n; k++) mpq_set_si(V_piv[k], 0, 1); for (i = 1; i <= n; i++) { while (V_row[i] != NULL) { vij = V_row[i], V_row[i] = vij->r_next; mpq_clear(vij->val); dmp_free_atom(pool, vij, sizeof(LUXELM)); } } for (j = 1; j <= n; j++) V_col[j] = NULL; /* V := A */ ind = xcalloc(1+n, sizeof(int)); val = xcalloc(1+n, sizeof(mpq_t)); for (k = 1; k <= n; k++) mpq_init(val[k]); for (j = 1; j <= n; j++) { /* obtain j-th column of matrix A */ len = col(info, j, ind, val); if (!(0 <= len && len <= n)) xfault("lux_decomp: j = %d: len = %d; invalid column length" "\n", j, len); /* copy elements of j-th column to matrix V */ for (k = 1; k <= len; k++) { /* get row index of a[i,j] */ i = ind[k]; if (!(1 <= i && i <= n)) xfault("lux_decomp: j = %d: i = %d; row index out of ran" "ge\n", j, i); /* check for duplicate indices */ if (V_row[i] != NULL && V_row[i]->j == j) xfault("lux_decomp: j = %d: i = %d; duplicate row indice" "s not allowed\n", j, i); /* check for zero value */ if (mpq_sgn(val[k]) == 0) xfault("lux_decomp: j = %d: i = %d; zero elements not al" "lowed\n", j, i); /* add new element v[i,j] = a[i,j] to V */ vij = dmp_get_atom(pool, sizeof(LUXELM)); vij->i = i, vij->j = j; mpq_init(vij->val); mpq_set(vij->val, val[k]); vij->r_prev = NULL; vij->r_next = V_row[i]; vij->c_prev = NULL; vij->c_next = V_col[j]; if (vij->r_next != NULL) vij->r_next->r_prev = vij; if (vij->c_next != NULL) vij->c_next->c_prev = vij; V_row[i] = V_col[j] = vij; } } xfree(ind); for (k = 1; k <= n; k++) mpq_clear(val[k]); xfree(val); /* P := Q := I */ for (k = 1; k <= n; k++) P_row[k] = P_col[k] = Q_row[k] = Q_col[k] = k; /* the rank of A and V is not determined yet */ lux->rank = -1; /* initially the entire matrix V is active */ /* determine its row lengths */ for (i = 1; i <= n; i++) { len = 0; for (vij = V_row[i]; vij != NULL; vij = vij->r_next) len++; R_len[i] = len; } /* build linked lists of active rows */ for (len = 0; len <= n; len++) R_head[len] = 0; for (i = 1; i <= n; i++) { len = R_len[i]; R_prev[i] = 0; R_next[i] = R_head[len]; if (R_next[i] != 0) R_prev[R_next[i]] = i; R_head[len] = i; } /* determine its column lengths */ for (j = 1; j <= n; j++) { len = 0; for (vij = V_col[j]; vij != NULL; vij = vij->c_next) len++; C_len[j] = len; } /* build linked lists of active columns */ for (len = 0; len <= n; len++) C_head[len] = 0; for (j = 1; j <= n; j++) { len = C_len[j]; C_prev[j] = 0; C_next[j] = C_head[len]; if (C_next[j] != 0) C_prev[C_next[j]] = j; C_head[len] = j; } return; } /*---------------------------------------------------------------------- // find_pivot - choose a pivot element. // // This routine chooses a pivot element v[p,q] in the active submatrix // of matrix U = P*V*Q. // // It is assumed that on entry the matrix U has the following partially // triangularized form: // // 1 k n // 1 x x x x x x x x x x // . x x x x x x x x x // . . x x x x x x x x // . . . x x x x x x x // k . . . . * * * * * * // . . . . * * * * * * // . . . . * * * * * * // . . . . * * * * * * // . . . . * * * * * * // n . . . . * * * * * * // // where rows and columns k, k+1, ..., n belong to the active submatrix // (elements of the active submatrix are marked by '*'). // // Since the matrix U = P*V*Q is not stored, the routine works with the // matrix V. It is assumed that the row-wise representation corresponds // to the matrix V, but the column-wise representation corresponds to // the active submatrix of the matrix V, i.e. elements of the matrix V, // which does not belong to the active submatrix, are missing from the // column linked lists. It is also assumed that each active row of the // matrix V is in the set R[len], where len is number of non-zeros in // the row, and each active column of the matrix V is in the set C[len], // where len is number of non-zeros in the column (in the latter case // only elements of the active submatrix are counted; such elements are // marked by '*' on the figure above). // // Due to exact arithmetic any non-zero element of the active submatrix // can be chosen as a pivot. However, to keep sparsity of the matrix V // the routine uses Markowitz strategy, trying to choose such element // v[p,q], which has smallest Markowitz cost (nr[p]-1) * (nc[q]-1), // where nr[p] and nc[q] are the number of non-zero elements, resp., in // p-th row and in q-th column of the active submatrix. // // In order to reduce the search, i.e. not to walk through all elements // of the active submatrix, the routine exploits a technique proposed by // I.Duff. This technique is based on using the sets R[len] and C[len] // of active rows and columns. // // On exit the routine returns a pointer to a pivot v[p,q] chosen, or // NULL, if the active submatrix is empty. */ static LUXELM *find_pivot(LUX *lux, LUXWKA *wka) { int n = lux->n; LUXELM **V_row = lux->V_row; LUXELM **V_col = lux->V_col; int *R_len = wka->R_len; int *R_head = wka->R_head; int *R_next = wka->R_next; int *C_len = wka->C_len; int *C_head = wka->C_head; int *C_next = wka->C_next; LUXELM *piv, *some, *vij; int i, j, len, min_len, ncand, piv_lim = 5; double best, cost; /* nothing is chosen so far */ piv = NULL, best = DBL_MAX, ncand = 0; /* if in the active submatrix there is a column that has the only non-zero (column singleton), choose it as a pivot */ j = C_head[1]; if (j != 0) { xassert(C_len[j] == 1); piv = V_col[j]; xassert(piv != NULL && piv->c_next == NULL); goto done; } /* if in the active submatrix there is a row that has the only non-zero (row singleton), choose it as a pivot */ i = R_head[1]; if (i != 0) { xassert(R_len[i] == 1); piv = V_row[i]; xassert(piv != NULL && piv->r_next == NULL); goto done; } /* there are no singletons in the active submatrix; walk through other non-empty rows and columns */ for (len = 2; len <= n; len++) { /* consider active columns having len non-zeros */ for (j = C_head[len]; j != 0; j = C_next[j]) { /* j-th column has len non-zeros */ /* find an element in the row of minimal length */ some = NULL, min_len = INT_MAX; for (vij = V_col[j]; vij != NULL; vij = vij->c_next) { if (min_len > R_len[vij->i]) some = vij, min_len = R_len[vij->i]; /* if Markowitz cost of this element is not greater than (len-1)**2, it can be chosen right now; this heuristic reduces the search and works well in many cases */ if (min_len <= len) { piv = some; goto done; } } /* j-th column has been scanned */ /* the minimal element found is a next pivot candidate */ xassert(some != NULL); ncand++; /* compute its Markowitz cost */ cost = (double)(min_len - 1) * (double)(len - 1); /* choose between the current candidate and this element */ if (cost < best) piv = some, best = cost; /* if piv_lim candidates have been considered, there is a doubt that a much better candidate exists; therefore it is the time to terminate the search */ if (ncand == piv_lim) goto done; } /* now consider active rows having len non-zeros */ for (i = R_head[len]; i != 0; i = R_next[i]) { /* i-th row has len non-zeros */ /* find an element in the column of minimal length */ some = NULL, min_len = INT_MAX; for (vij = V_row[i]; vij != NULL; vij = vij->r_next) { if (min_len > C_len[vij->j]) some = vij, min_len = C_len[vij->j]; /* if Markowitz cost of this element is not greater than (len-1)**2, it can be chosen right now; this heuristic reduces the search and works well in many cases */ if (min_len <= len) { piv = some; goto done; } } /* i-th row has been scanned */ /* the minimal element found is a next pivot candidate */ xassert(some != NULL); ncand++; /* compute its Markowitz cost */ cost = (double)(len - 1) * (double)(min_len - 1); /* choose between the current candidate and this element */ if (cost < best) piv = some, best = cost; /* if piv_lim candidates have been considered, there is a doubt that a much better candidate exists; therefore it is the time to terminate the search */ if (ncand == piv_lim) goto done; } } done: /* bring the pivot v[p,q] to the factorizing routine */ return piv; } /*---------------------------------------------------------------------- // eliminate - perform gaussian elimination. // // This routine performs elementary gaussian transformations in order // to eliminate subdiagonal elements in the k-th column of the matrix // U = P*V*Q using the pivot element u[k,k], where k is the number of // the current elimination step. // // The parameter piv specifies the pivot element v[p,q] = u[k,k]. // // Each time when the routine applies the elementary transformation to // a non-pivot row of the matrix V, it stores the corresponding element // to the matrix F in order to keep the main equality A = F*V. // // The routine assumes that on entry the matrices L = P*F*inv(P) and // U = P*V*Q are the following: // // 1 k 1 k n // 1 1 . . . . . . . . . 1 x x x x x x x x x x // x 1 . . . . . . . . . x x x x x x x x x // x x 1 . . . . . . . . . x x x x x x x x // x x x 1 . . . . . . . . . x x x x x x x // k x x x x 1 . . . . . k . . . . * * * * * * // x x x x _ 1 . . . . . . . . # * * * * * // x x x x _ . 1 . . . . . . . # * * * * * // x x x x _ . . 1 . . . . . . # * * * * * // x x x x _ . . . 1 . . . . . # * * * * * // n x x x x _ . . . . 1 n . . . . # * * * * * // // matrix L matrix U // // where rows and columns of the matrix U with numbers k, k+1, ..., n // form the active submatrix (eliminated elements are marked by '#' and // other elements of the active submatrix are marked by '*'). Note that // each eliminated non-zero element u[i,k] of the matrix U gives the // corresponding element l[i,k] of the matrix L (marked by '_'). // // Actually all operations are performed on the matrix V. Should note // that the row-wise representation corresponds to the matrix V, but the // column-wise representation corresponds to the active submatrix of the // matrix V, i.e. elements of the matrix V, which doesn't belong to the // active submatrix, are missing from the column linked lists. // // Let u[k,k] = v[p,q] be the pivot. In order to eliminate subdiagonal // elements u[i',k] = v[i,q], i' = k+1, k+2, ..., n, the routine applies // the following elementary gaussian transformations: // // (i-th row of V) := (i-th row of V) - f[i,p] * (p-th row of V), // // where f[i,p] = v[i,q] / v[p,q] is a gaussian multiplier. // // Additionally, in order to keep the main equality A = F*V, each time // when the routine applies the transformation to i-th row of the matrix // V, it also adds f[i,p] as a new element to the matrix F. // // IMPORTANT: On entry the working arrays flag and work should contain // zeros. This status is provided by the routine on exit. */ static void eliminate(LUX *lux, LUXWKA *wka, LUXELM *piv, int flag[], mpq_t work[]) { DMP *pool = lux->pool; LUXELM **F_row = lux->F_row; LUXELM **F_col = lux->F_col; mpq_t *V_piv = lux->V_piv; LUXELM **V_row = lux->V_row; LUXELM **V_col = lux->V_col; int *R_len = wka->R_len; int *R_head = wka->R_head; int *R_prev = wka->R_prev; int *R_next = wka->R_next; int *C_len = wka->C_len; int *C_head = wka->C_head; int *C_prev = wka->C_prev; int *C_next = wka->C_next; LUXELM *fip, *vij, *vpj, *viq, *next; mpq_t temp; int i, j, p, q; mpq_init(temp); /* determine row and column indices of the pivot v[p,q] */ xassert(piv != NULL); p = piv->i, q = piv->j; /* remove p-th (pivot) row from the active set; it will never return there */ if (R_prev[p] == 0) R_head[R_len[p]] = R_next[p]; else R_next[R_prev[p]] = R_next[p]; if (R_next[p] == 0) ; else R_prev[R_next[p]] = R_prev[p]; /* remove q-th (pivot) column from the active set; it will never return there */ if (C_prev[q] == 0) C_head[C_len[q]] = C_next[q]; else C_next[C_prev[q]] = C_next[q]; if (C_next[q] == 0) ; else C_prev[C_next[q]] = C_prev[q]; /* store the pivot value in a separate array */ mpq_set(V_piv[p], piv->val); /* remove the pivot from p-th row */ if (piv->r_prev == NULL) V_row[p] = piv->r_next; else piv->r_prev->r_next = piv->r_next; if (piv->r_next == NULL) ; else piv->r_next->r_prev = piv->r_prev; R_len[p]--; /* remove the pivot from q-th column */ if (piv->c_prev == NULL) V_col[q] = piv->c_next; else piv->c_prev->c_next = piv->c_next; if (piv->c_next == NULL) ; else piv->c_next->c_prev = piv->c_prev; C_len[q]--; /* free the space occupied by the pivot */ mpq_clear(piv->val); dmp_free_atom(pool, piv, sizeof(LUXELM)); /* walk through p-th (pivot) row, which already does not contain the pivot v[p,q], and do the following... */ for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) { /* get column index of v[p,j] */ j = vpj->j; /* store v[p,j] in the working array */ flag[j] = 1; mpq_set(work[j], vpj->val); /* remove j-th column from the active set; it will return there later with a new length */ if (C_prev[j] == 0) C_head[C_len[j]] = C_next[j]; else C_next[C_prev[j]] = C_next[j]; if (C_next[j] == 0) ; else C_prev[C_next[j]] = C_prev[j]; /* v[p,j] leaves the active submatrix, so remove it from j-th column; however, v[p,j] is kept in p-th row */ if (vpj->c_prev == NULL) V_col[j] = vpj->c_next; else vpj->c_prev->c_next = vpj->c_next; if (vpj->c_next == NULL) ; else vpj->c_next->c_prev = vpj->c_prev; C_len[j]--; } /* now walk through q-th (pivot) column, which already does not contain the pivot v[p,q], and perform gaussian elimination */ while (V_col[q] != NULL) { /* element v[i,q] has to be eliminated */ viq = V_col[q]; /* get row index of v[i,q] */ i = viq->i; /* remove i-th row from the active set; later it will return there with a new length */ if (R_prev[i] == 0) R_head[R_len[i]] = R_next[i]; else R_next[R_prev[i]] = R_next[i]; if (R_next[i] == 0) ; else R_prev[R_next[i]] = R_prev[i]; /* compute gaussian multiplier f[i,p] = v[i,q] / v[p,q] and store it in the matrix F */ fip = dmp_get_atom(pool, sizeof(LUXELM)); fip->i = i, fip->j = p; mpq_init(fip->val); mpq_div(fip->val, viq->val, V_piv[p]); fip->r_prev = NULL; fip->r_next = F_row[i]; fip->c_prev = NULL; fip->c_next = F_col[p]; if (fip->r_next != NULL) fip->r_next->r_prev = fip; if (fip->c_next != NULL) fip->c_next->c_prev = fip; F_row[i] = F_col[p] = fip; /* v[i,q] has to be eliminated, so remove it from i-th row */ if (viq->r_prev == NULL) V_row[i] = viq->r_next; else viq->r_prev->r_next = viq->r_next; if (viq->r_next == NULL) ; else viq->r_next->r_prev = viq->r_prev; R_len[i]--; /* and also from q-th column */ V_col[q] = viq->c_next; C_len[q]--; /* free the space occupied by v[i,q] */ mpq_clear(viq->val); dmp_free_atom(pool, viq, sizeof(LUXELM)); /* perform gaussian transformation: (i-th row) := (i-th row) - f[i,p] * (p-th row) note that now p-th row, which is in the working array, does not contain the pivot v[p,q], and i-th row does not contain the element v[i,q] to be eliminated */ /* walk through i-th row and transform existing non-zero elements */ for (vij = V_row[i]; vij != NULL; vij = next) { next = vij->r_next; /* get column index of v[i,j] */ j = vij->j; /* v[i,j] := v[i,j] - f[i,p] * v[p,j] */ if (flag[j]) { /* v[p,j] != 0 */ flag[j] = 0; mpq_mul(temp, fip->val, work[j]); mpq_sub(vij->val, vij->val, temp); if (mpq_sgn(vij->val) == 0) { /* new v[i,j] is zero, so remove it from the active submatrix */ /* remove v[i,j] from i-th row */ if (vij->r_prev == NULL) V_row[i] = vij->r_next; else vij->r_prev->r_next = vij->r_next; if (vij->r_next == NULL) ; else vij->r_next->r_prev = vij->r_prev; R_len[i]--; /* remove v[i,j] from j-th column */ if (vij->c_prev == NULL) V_col[j] = vij->c_next; else vij->c_prev->c_next = vij->c_next; if (vij->c_next == NULL) ; else vij->c_next->c_prev = vij->c_prev; C_len[j]--; /* free the space occupied by v[i,j] */ mpq_clear(vij->val); dmp_free_atom(pool, vij, sizeof(LUXELM)); } } } /* now flag is the pattern of the set v[p,*] \ v[i,*] */ /* walk through p-th (pivot) row and create new elements in i-th row, which appear due to fill-in */ for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) { j = vpj->j; if (flag[j]) { /* create new non-zero v[i,j] = 0 - f[i,p] * v[p,j] and add it to i-th row and j-th column */ vij = dmp_get_atom(pool, sizeof(LUXELM)); vij->i = i, vij->j = j; mpq_init(vij->val); mpq_mul(vij->val, fip->val, work[j]); mpq_neg(vij->val, vij->val); vij->r_prev = NULL; vij->r_next = V_row[i]; vij->c_prev = NULL; vij->c_next = V_col[j]; if (vij->r_next != NULL) vij->r_next->r_prev = vij; if (vij->c_next != NULL) vij->c_next->c_prev = vij; V_row[i] = V_col[j] = vij; R_len[i]++, C_len[j]++; } else { /* there is no fill-in, because v[i,j] already exists in i-th row; restore the flag, which was reset before */ flag[j] = 1; } } /* now i-th row has been completely transformed and can return to the active set with a new length */ R_prev[i] = 0; R_next[i] = R_head[R_len[i]]; if (R_next[i] != 0) R_prev[R_next[i]] = i; R_head[R_len[i]] = i; } /* at this point q-th (pivot) column must be empty */ xassert(C_len[q] == 0); /* walk through p-th (pivot) row again and do the following... */ for (vpj = V_row[p]; vpj != NULL; vpj = vpj->r_next) { /* get column index of v[p,j] */ j = vpj->j; /* erase v[p,j] from the working array */ flag[j] = 0; mpq_set_si(work[j], 0, 1); /* now j-th column has been completely transformed, so it can return to the active list with a new length */ C_prev[j] = 0; C_next[j] = C_head[C_len[j]]; if (C_next[j] != 0) C_prev[C_next[j]] = j; C_head[C_len[j]] = j; } mpq_clear(temp); /* return to the factorizing routine */ return; } /*---------------------------------------------------------------------- // lux_decomp - compute LU-factorization. // // SYNOPSIS // // #include "glplux.h" // int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], // mpq_t val[]), void *info); // // DESCRIPTION // // The routine lux_decomp computes LU-factorization of a given square // matrix A. // // The parameter lux specifies LU-factorization data structure built by // means of the routine lux_create. // // The formal routine col specifies the original matrix A. In order to // obtain j-th column of the matrix A the routine lux_decomp calls the // routine col with the parameter j (1 <= j <= n, where n is the order // of A). In response the routine col should store row indices and // numerical values of non-zero elements of j-th column of A to the // locations ind[1], ..., ind[len] and val[1], ..., val[len], resp., // where len is the number of non-zeros in j-th column, which should be // returned on exit. Neiter zero nor duplicate elements are allowed. // // The parameter info is a transit pointer passed to the formal routine // col; it can be used for various purposes. // // RETURNS // // The routine lux_decomp returns the singularity flag. Zero flag means // that the original matrix A is non-singular while non-zero flag means // that A is (exactly!) singular. // // Note that LU-factorization is valid in both cases, however, in case // of singularity some rows of the matrix V (including pivot elements) // will be empty. // // REPAIRING SINGULAR MATRIX // // If the routine lux_decomp returns non-zero flag, it provides all // necessary information that can be used for "repairing" the matrix A, // where "repairing" means replacing linearly dependent columns of the // matrix A by appropriate columns of the unity matrix. This feature is // needed when the routine lux_decomp is used for reinverting the basis // matrix within the simplex method procedure. // // On exit linearly dependent columns of the matrix U have the numbers // rank+1, rank+2, ..., n, where rank is the exact rank of the matrix A // stored by the routine to the member lux->rank. The correspondence // between columns of A and U is the same as between columns of V and U. // Thus, linearly dependent columns of the matrix A have the numbers // Q_col[rank+1], Q_col[rank+2], ..., Q_col[n], where Q_col is an array // representing the permutation matrix Q in column-like format. It is // understood that each j-th linearly dependent column of the matrix U // should be replaced by the unity vector, where all elements are zero // except the unity diagonal element u[j,j]. On the other hand j-th row // of the matrix U corresponds to the row of the matrix V (and therefore // of the matrix A) with the number P_row[j], where P_row is an array // representing the permutation matrix P in row-like format. Thus, each // j-th linearly dependent column of the matrix U should be replaced by // a column of the unity matrix with the number P_row[j]. // // The code that repairs the matrix A may look like follows: // // for (j = rank+1; j <= n; j++) // { replace column Q_col[j] of the matrix A by column P_row[j] of // the unity matrix; // } // // where rank, P_row, and Q_col are members of the structure LUX. */ int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], mpq_t val[]), void *info) { int n = lux->n; LUXELM **V_row = lux->V_row; LUXELM **V_col = lux->V_col; int *P_row = lux->P_row; int *P_col = lux->P_col; int *Q_row = lux->Q_row; int *Q_col = lux->Q_col; LUXELM *piv, *vij; LUXWKA *wka; int i, j, k, p, q, t, *flag; mpq_t *work; /* allocate working area */ wka = xmalloc(sizeof(LUXWKA)); wka->R_len = xcalloc(1+n, sizeof(int)); wka->R_head = xcalloc(1+n, sizeof(int)); wka->R_prev = xcalloc(1+n, sizeof(int)); wka->R_next = xcalloc(1+n, sizeof(int)); wka->C_len = xcalloc(1+n, sizeof(int)); wka->C_head = xcalloc(1+n, sizeof(int)); wka->C_prev = xcalloc(1+n, sizeof(int)); wka->C_next = xcalloc(1+n, sizeof(int)); /* initialize LU-factorization data structures */ initialize(lux, col, info, wka); /* allocate working arrays */ flag = xcalloc(1+n, sizeof(int)); work = xcalloc(1+n, sizeof(mpq_t)); for (k = 1; k <= n; k++) { flag[k] = 0; mpq_init(work[k]); } /* main elimination loop */ for (k = 1; k <= n; k++) { /* choose a pivot element v[p,q] */ piv = find_pivot(lux, wka); if (piv == NULL) { /* no pivot can be chosen, because the active submatrix is empty */ break; } /* determine row and column indices of the pivot element */ p = piv->i, q = piv->j; /* let v[p,q] correspond to u[i',j']; permute k-th and i'-th rows and k-th and j'-th columns of the matrix U = P*V*Q to move the element u[i',j'] to the position u[k,k] */ i = P_col[p], j = Q_row[q]; xassert(k <= i && i <= n && k <= j && j <= n); /* permute k-th and i-th rows of the matrix U */ t = P_row[k]; P_row[i] = t, P_col[t] = i; P_row[k] = p, P_col[p] = k; /* permute k-th and j-th columns of the matrix U */ t = Q_col[k]; Q_col[j] = t, Q_row[t] = j; Q_col[k] = q, Q_row[q] = k; /* eliminate subdiagonal elements of k-th column of the matrix U = P*V*Q using the pivot element u[k,k] = v[p,q] */ eliminate(lux, wka, piv, flag, work); } /* determine the rank of A (and V) */ lux->rank = k - 1; /* free working arrays */ xfree(flag); for (k = 1; k <= n; k++) mpq_clear(work[k]); xfree(work); /* build column lists of the matrix V using its row lists */ for (j = 1; j <= n; j++) xassert(V_col[j] == NULL); for (i = 1; i <= n; i++) { for (vij = V_row[i]; vij != NULL; vij = vij->r_next) { j = vij->j; vij->c_prev = NULL; vij->c_next = V_col[j]; if (vij->c_next != NULL) vij->c_next->c_prev = vij; V_col[j] = vij; } } /* free working area */ xfree(wka->R_len); xfree(wka->R_head); xfree(wka->R_prev); xfree(wka->R_next); xfree(wka->C_len); xfree(wka->C_head); xfree(wka->C_prev); xfree(wka->C_next); xfree(wka); /* return to the calling program */ return (lux->rank < n); } /*---------------------------------------------------------------------- // lux_f_solve - solve system F*x = b or F'*x = b. // // SYNOPSIS // // #include "glplux.h" // void lux_f_solve(LUX *lux, int tr, mpq_t x[]); // // DESCRIPTION // // The routine lux_f_solve solves either the system F*x = b (if the // flag tr is zero) or the system F'*x = b (if the flag tr is non-zero), // where the matrix F is a component of LU-factorization specified by // the parameter lux, F' is a matrix transposed to F. // // On entry the array x should contain elements of the right-hand side // vector b in locations x[1], ..., x[n], where n is the order of the // matrix F. On exit this array will contain elements of the solution // vector x in the same locations. */ void lux_f_solve(LUX *lux, int tr, mpq_t x[]) { int n = lux->n; LUXELM **F_row = lux->F_row; LUXELM **F_col = lux->F_col; int *P_row = lux->P_row; LUXELM *fik, *fkj; int i, j, k; mpq_t temp; mpq_init(temp); if (!tr) { /* solve the system F*x = b */ for (j = 1; j <= n; j++) { k = P_row[j]; if (mpq_sgn(x[k]) != 0) { for (fik = F_col[k]; fik != NULL; fik = fik->c_next) { mpq_mul(temp, fik->val, x[k]); mpq_sub(x[fik->i], x[fik->i], temp); } } } } else { /* solve the system F'*x = b */ for (i = n; i >= 1; i--) { k = P_row[i]; if (mpq_sgn(x[k]) != 0) { for (fkj = F_row[k]; fkj != NULL; fkj = fkj->r_next) { mpq_mul(temp, fkj->val, x[k]); mpq_sub(x[fkj->j], x[fkj->j], temp); } } } } mpq_clear(temp); return; } /*---------------------------------------------------------------------- // lux_v_solve - solve system V*x = b or V'*x = b. // // SYNOPSIS // // #include "glplux.h" // void lux_v_solve(LUX *lux, int tr, double x[]); // // DESCRIPTION // // The routine lux_v_solve solves either the system V*x = b (if the // flag tr is zero) or the system V'*x = b (if the flag tr is non-zero), // where the matrix V is a component of LU-factorization specified by // the parameter lux, V' is a matrix transposed to V. // // On entry the array x should contain elements of the right-hand side // vector b in locations x[1], ..., x[n], where n is the order of the // matrix V. On exit this array will contain elements of the solution // vector x in the same locations. */ void lux_v_solve(LUX *lux, int tr, mpq_t x[]) { int n = lux->n; mpq_t *V_piv = lux->V_piv; LUXELM **V_row = lux->V_row; LUXELM **V_col = lux->V_col; int *P_row = lux->P_row; int *Q_col = lux->Q_col; LUXELM *vij; int i, j, k; mpq_t *b, temp; b = xcalloc(1+n, sizeof(mpq_t)); for (k = 1; k <= n; k++) mpq_init(b[k]), mpq_set(b[k], x[k]), mpq_set_si(x[k], 0, 1); mpq_init(temp); if (!tr) { /* solve the system V*x = b */ for (k = n; k >= 1; k--) { i = P_row[k], j = Q_col[k]; if (mpq_sgn(b[i]) != 0) { mpq_set(x[j], b[i]); mpq_div(x[j], x[j], V_piv[i]); for (vij = V_col[j]; vij != NULL; vij = vij->c_next) { mpq_mul(temp, vij->val, x[j]); mpq_sub(b[vij->i], b[vij->i], temp); } } } } else { /* solve the system V'*x = b */ for (k = 1; k <= n; k++) { i = P_row[k], j = Q_col[k]; if (mpq_sgn(b[j]) != 0) { mpq_set(x[i], b[j]); mpq_div(x[i], x[i], V_piv[i]); for (vij = V_row[i]; vij != NULL; vij = vij->r_next) { mpq_mul(temp, vij->val, x[i]); mpq_sub(b[vij->j], b[vij->j], temp); } } } } for (k = 1; k <= n; k++) mpq_clear(b[k]); mpq_clear(temp); xfree(b); return; } /*---------------------------------------------------------------------- // lux_solve - solve system A*x = b or A'*x = b. // // SYNOPSIS // // #include "glplux.h" // void lux_solve(LUX *lux, int tr, mpq_t x[]); // // DESCRIPTION // // The routine lux_solve solves either the system A*x = b (if the flag // tr is zero) or the system A'*x = b (if the flag tr is non-zero), // where the parameter lux specifies LU-factorization of the matrix A, // A' is a matrix transposed to A. // // On entry the array x should contain elements of the right-hand side // vector b in locations x[1], ..., x[n], where n is the order of the // matrix A. On exit this array will contain elements of the solution // vector x in the same locations. */ void lux_solve(LUX *lux, int tr, mpq_t x[]) { if (lux->rank < lux->n) xfault("lux_solve: LU-factorization has incomplete rank\n"); if (!tr) { /* A = F*V, therefore inv(A) = inv(V)*inv(F) */ lux_f_solve(lux, 0, x); lux_v_solve(lux, 0, x); } else { /* A' = V'*F', therefore inv(A') = inv(F')*inv(V') */ lux_v_solve(lux, 1, x); lux_f_solve(lux, 1, x); } return; } /*---------------------------------------------------------------------- // lux_delete - delete LU-factorization. // // SYNOPSIS // // #include "glplux.h" // void lux_delete(LUX *lux); // // DESCRIPTION // // The routine lux_delete deletes LU-factorization data structure, // which the parameter lux points to, freeing all the memory allocated // to this object. */ void lux_delete(LUX *lux) { int n = lux->n; LUXELM *fij, *vij; int i; for (i = 1; i <= n; i++) { for (fij = lux->F_row[i]; fij != NULL; fij = fij->r_next) mpq_clear(fij->val); mpq_clear(lux->V_piv[i]); for (vij = lux->V_row[i]; vij != NULL; vij = vij->r_next) mpq_clear(vij->val); } dmp_delete_pool(lux->pool); xfree(lux->F_row); xfree(lux->F_col); xfree(lux->V_piv); xfree(lux->V_row); xfree(lux->V_col); xfree(lux->P_row); xfree(lux->P_col); xfree(lux->Q_row); xfree(lux->Q_col); xfree(lux); return; } /* eof */ glpk-4.52.1/src/glplux.h0000644000062000006210000002123312175147600014175 0ustar maomkpasswd/* glplux.h (LU-factorization, bignum arithmetic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPLUX_H #define GLPLUX_H #include "dmp.h" #include "glpgmp.h" /*---------------------------------------------------------------------- // The structure LUX defines LU-factorization of a square matrix A, // which is the following quartet: // // [A] = (F, V, P, Q), (1) // // where F and V are such matrices that // // A = F * V, (2) // // and P and Q are such permutation matrices that the matrix // // L = P * F * inv(P) (3) // // is lower triangular with unity diagonal, and the matrix // // U = P * V * Q (4) // // is upper triangular. All the matrices have the order n. // // The matrices F and V are stored in row/column-wise sparse format as // row and column linked lists of non-zero elements. Unity elements on // the main diagonal of the matrix F are not stored. Pivot elements of // the matrix V (that correspond to diagonal elements of the matrix U) // are also missing from the row and column lists and stored separately // in an ordinary array. // // The permutation matrices P and Q are stored as ordinary arrays using // both row- and column-like formats. // // The matrices L and U being completely defined by the matrices F, V, // P, and Q are not stored explicitly. // // It is easy to show that the factorization (1)-(3) is some version of // LU-factorization. Indeed, from (3) and (4) it follows that: // // F = inv(P) * L * P, // // V = inv(P) * U * inv(Q), // // and substitution into (2) gives: // // A = F * V = inv(P) * L * U * inv(Q). // // For more details see the program documentation. */ typedef struct LUX LUX; typedef struct LUXELM LUXELM; typedef struct LUXWKA LUXWKA; struct LUX { /* LU-factorization of a square matrix */ int n; /* the order of matrices A, F, V, P, Q */ DMP *pool; /* memory pool for elements of matrices F and V */ LUXELM **F_row; /* LUXELM *F_row[1+n]; */ /* F_row[0] is not used; F_row[i], 1 <= i <= n, is a pointer to the list of elements in i-th row of matrix F (diagonal elements are not stored) */ LUXELM **F_col; /* LUXELM *F_col[1+n]; */ /* F_col[0] is not used; F_col[j], 1 <= j <= n, is a pointer to the list of elements in j-th column of matrix F (diagonal elements are not stored) */ mpq_t *V_piv; /* mpq_t V_piv[1+n]; */ /* V_piv[0] is not used; V_piv[p], 1 <= p <= n, is a pivot element v[p,q] corresponding to a diagonal element u[k,k] of matrix U = P*V*Q (used on k-th elimination step, k = 1, 2, ..., n) */ LUXELM **V_row; /* LUXELM *V_row[1+n]; */ /* V_row[0] is not used; V_row[i], 1 <= i <= n, is a pointer to the list of elements in i-th row of matrix V (except pivot elements) */ LUXELM **V_col; /* LUXELM *V_col[1+n]; */ /* V_col[0] is not used; V_col[j], 1 <= j <= n, is a pointer to the list of elements in j-th column of matrix V (except pivot elements) */ int *P_row; /* int P_row[1+n]; */ /* P_row[0] is not used; P_row[i] = j means that p[i,j] = 1, where p[i,j] is an element of permutation matrix P */ int *P_col; /* int P_col[1+n]; */ /* P_col[0] is not used; P_col[j] = i means that p[i,j] = 1, where p[i,j] is an element of permutation matrix P */ /* if i-th row or column of matrix F is i'-th row or column of matrix L = P*F*inv(P), or if i-th row of matrix V is i'-th row of matrix U = P*V*Q, then P_row[i'] = i and P_col[i] = i' */ int *Q_row; /* int Q_row[1+n]; */ /* Q_row[0] is not used; Q_row[i] = j means that q[i,j] = 1, where q[i,j] is an element of permutation matrix Q */ int *Q_col; /* int Q_col[1+n]; */ /* Q_col[0] is not used; Q_col[j] = i means that q[i,j] = 1, where q[i,j] is an element of permutation matrix Q */ /* if j-th column of matrix V is j'-th column of matrix U = P*V*Q, then Q_row[j] = j' and Q_col[j'] = j */ int rank; /* the (exact) rank of matrices A and V */ }; struct LUXELM { /* element of matrix F or V */ int i; /* row index, 1 <= i <= m */ int j; /* column index, 1 <= j <= n */ mpq_t val; /* numeric (non-zero) element value */ LUXELM *r_prev; /* pointer to previous element in the same row */ LUXELM *r_next; /* pointer to next element in the same row */ LUXELM *c_prev; /* pointer to previous element in the same column */ LUXELM *c_next; /* pointer to next element in the same column */ }; struct LUXWKA { /* working area (used only during factorization) */ /* in order to efficiently implement Markowitz strategy and Duff search technique there are two families {R[0], R[1], ..., R[n]} and {C[0], C[1], ..., C[n]}; member R[k] is a set of active rows of matrix V having k non-zeros, and member C[k] is a set of active columns of matrix V having k non-zeros (in the active submatrix); each set R[k] and C[k] is implemented as a separate doubly linked list */ int *R_len; /* int R_len[1+n]; */ /* R_len[0] is not used; R_len[i], 1 <= i <= n, is the number of non-zero elements in i-th row of matrix V (that is the length of i-th row) */ int *R_head; /* int R_head[1+n]; */ /* R_head[k], 0 <= k <= n, is the number of a first row, which is active and whose length is k */ int *R_prev; /* int R_prev[1+n]; */ /* R_prev[0] is not used; R_prev[i], 1 <= i <= n, is the number of a previous row, which is active and has the same length as i-th row */ int *R_next; /* int R_next[1+n]; */ /* R_prev[0] is not used; R_prev[i], 1 <= i <= n, is the number of a next row, which is active and has the same length as i-th row */ int *C_len; /* int C_len[1+n]; */ /* C_len[0] is not used; C_len[j], 1 <= j <= n, is the number of non-zero elements in j-th column of the active submatrix of matrix V (that is the length of j-th column in the active submatrix) */ int *C_head; /* int C_head[1+n]; */ /* C_head[k], 0 <= k <= n, is the number of a first column, which is active and whose length is k */ int *C_prev; /* int C_prev[1+n]; */ /* C_prev[0] is not used; C_prev[j], 1 <= j <= n, is the number of a previous column, which is active and has the same length as j-th column */ int *C_next; /* int C_next[1+n]; */ /* C_next[0] is not used; C_next[j], 1 <= j <= n, is the number of a next column, which is active and has the same length as j-th column */ }; #define lux_create _glp_lux_create #define lux_decomp _glp_lux_decomp #define lux_f_solve _glp_lux_f_solve #define lux_v_solve _glp_lux_v_solve #define lux_solve _glp_lux_solve #define lux_delete _glp_lux_delete LUX *lux_create(int n); /* create LU-factorization */ int lux_decomp(LUX *lux, int (*col)(void *info, int j, int ind[], mpq_t val[]), void *info); /* compute LU-factorization */ void lux_f_solve(LUX *lux, int tr, mpq_t x[]); /* solve system F*x = b or F'*x = b */ void lux_v_solve(LUX *lux, int tr, mpq_t x[]); /* solve system V*x = b or V'*x = b */ void lux_solve(LUX *lux, int tr, mpq_t x[]); /* solve system A*x = b or A'*x = b */ void lux_delete(LUX *lux); /* delete LU-factorization */ #endif /* eof */ glpk-4.52.1/src/glpmat.c0000644000062000006210000010035112175147600014140 0ustar maomkpasswd/* glpmat.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "glpmat.h" #include "qmd.h" #include "amd.h" #include "colamd.h" /*---------------------------------------------------------------------- -- check_fvs - check sparse vector in full-vector storage format. -- -- SYNOPSIS -- -- #include "glpmat.h" -- int check_fvs(int n, int nnz, int ind[], double vec[]); -- -- DESCRIPTION -- -- The routine check_fvs checks if a given vector of dimension n in -- full-vector storage format has correct representation. -- -- RETURNS -- -- The routine returns one of the following codes: -- -- 0 - the vector is correct; -- 1 - the number of elements (n) is negative; -- 2 - the number of non-zero elements (nnz) is negative; -- 3 - some element index is out of range; -- 4 - some element index is duplicate; -- 5 - some non-zero element is out of pattern. */ int check_fvs(int n, int nnz, int ind[], double vec[]) { int i, t, ret, *flag = NULL; /* check the number of elements */ if (n < 0) { ret = 1; goto done; } /* check the number of non-zero elements */ if (nnz < 0) { ret = 2; goto done; } /* check vector indices */ flag = xcalloc(1+n, sizeof(int)); for (i = 1; i <= n; i++) flag[i] = 0; for (t = 1; t <= nnz; t++) { i = ind[t]; if (!(1 <= i && i <= n)) { ret = 3; goto done; } if (flag[i]) { ret = 4; goto done; } flag[i] = 1; } /* check vector elements */ for (i = 1; i <= n; i++) { if (!flag[i] && vec[i] != 0.0) { ret = 5; goto done; } } /* the vector is ok */ ret = 0; done: if (flag != NULL) xfree(flag); return ret; } /*---------------------------------------------------------------------- -- check_pattern - check pattern of sparse matrix. -- -- SYNOPSIS -- -- #include "glpmat.h" -- int check_pattern(int m, int n, int A_ptr[], int A_ind[]); -- -- DESCRIPTION -- -- The routine check_pattern checks the pattern of a given mxn matrix -- in storage-by-rows format. -- -- RETURNS -- -- The routine returns one of the following codes: -- -- 0 - the pattern is correct; -- 1 - the number of rows (m) is negative; -- 2 - the number of columns (n) is negative; -- 3 - A_ptr[1] is not 1; -- 4 - some column index is out of range; -- 5 - some column indices are duplicate. */ int check_pattern(int m, int n, int A_ptr[], int A_ind[]) { int i, j, ptr, ret, *flag = NULL; /* check the number of rows */ if (m < 0) { ret = 1; goto done; } /* check the number of columns */ if (n < 0) { ret = 2; goto done; } /* check location A_ptr[1] */ if (A_ptr[1] != 1) { ret = 3; goto done; } /* check row patterns */ flag = xcalloc(1+n, sizeof(int)); for (j = 1; j <= n; j++) flag[j] = 0; for (i = 1; i <= m; i++) { /* check pattern of row i */ for (ptr = A_ptr[i]; ptr < A_ptr[i+1]; ptr++) { j = A_ind[ptr]; /* check column index */ if (!(1 <= j && j <= n)) { ret = 4; goto done; } /* check for duplication */ if (flag[j]) { ret = 5; goto done; } flag[j] = 1; } /* clear flags */ for (ptr = A_ptr[i]; ptr < A_ptr[i+1]; ptr++) { j = A_ind[ptr]; flag[j] = 0; } } /* the pattern is ok */ ret = 0; done: if (flag != NULL) xfree(flag); return ret; } /*---------------------------------------------------------------------- -- transpose - transpose sparse matrix. -- -- *Synopsis* -- -- #include "glpmat.h" -- void transpose(int m, int n, int A_ptr[], int A_ind[], -- double A_val[], int AT_ptr[], int AT_ind[], double AT_val[]); -- -- *Description* -- -- For a given mxn sparse matrix A the routine transpose builds a nxm -- sparse matrix A' which is a matrix transposed to A. -- -- The arrays A_ptr, A_ind, and A_val specify a given mxn matrix A to -- be transposed in storage-by-rows format. The parameter A_val can be -- NULL, in which case numeric values are not copied. The arrays A_ptr, -- A_ind, and A_val are not changed on exit. -- -- On entry the arrays AT_ptr, AT_ind, and AT_val must be allocated, -- but their content is ignored. On exit the routine stores a resultant -- nxm matrix A' in these arrays in storage-by-rows format. Note that -- if the parameter A_val is NULL, the array AT_val is not used. -- -- The routine transpose has a side effect that elements in rows of the -- resultant matrix A' follow in ascending their column indices. */ void transpose(int m, int n, int A_ptr[], int A_ind[], double A_val[], int AT_ptr[], int AT_ind[], double AT_val[]) { int i, j, t, beg, end, pos, len; /* determine row lengths of resultant matrix */ for (j = 1; j <= n; j++) AT_ptr[j] = 0; for (i = 1; i <= m; i++) { beg = A_ptr[i], end = A_ptr[i+1]; for (t = beg; t < end; t++) AT_ptr[A_ind[t]]++; } /* set up row pointers of resultant matrix */ pos = 1; for (j = 1; j <= n; j++) len = AT_ptr[j], pos += len, AT_ptr[j] = pos; AT_ptr[n+1] = pos; /* build resultant matrix */ for (i = m; i >= 1; i--) { beg = A_ptr[i], end = A_ptr[i+1]; for (t = beg; t < end; t++) { pos = --AT_ptr[A_ind[t]]; AT_ind[pos] = i; if (A_val != NULL) AT_val[pos] = A_val[t]; } } return; } /*---------------------------------------------------------------------- -- adat_symbolic - compute S = P*A*D*A'*P' (symbolic phase). -- -- *Synopsis* -- -- #include "glpmat.h" -- int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], -- int A_ind[], int S_ptr[]); -- -- *Description* -- -- The routine adat_symbolic implements the symbolic phase to compute -- symmetric matrix S = P*A*D*A'*P', where P is a permutation matrix, -- A is a given sparse matrix, D is a diagonal matrix, A' is a matrix -- transposed to A, P' is an inverse of P. -- -- The parameter m is the number of rows in A and the order of P. -- -- The parameter n is the number of columns in A and the order of D. -- -- The array P_per specifies permutation matrix P. It is not changed on -- exit. -- -- The arrays A_ptr and A_ind specify the pattern of matrix A. They are -- not changed on exit. -- -- On exit the routine stores the pattern of upper triangular part of -- matrix S without diagonal elements in the arrays S_ptr and S_ind in -- storage-by-rows format. The array S_ptr should be allocated on entry, -- however, its content is ignored. The array S_ind is allocated by the -- routine itself which returns a pointer to it. -- -- *Returns* -- -- The routine returns a pointer to the array S_ind. */ int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], int A_ind[], int S_ptr[]) { int i, j, t, ii, jj, tt, k, size, len; int *S_ind, *AT_ptr, *AT_ind, *ind, *map, *temp; /* build the pattern of A', which is a matrix transposed to A, to efficiently access A in column-wise manner */ AT_ptr = xcalloc(1+n+1, sizeof(int)); AT_ind = xcalloc(A_ptr[m+1], sizeof(int)); transpose(m, n, A_ptr, A_ind, NULL, AT_ptr, AT_ind, NULL); /* allocate the array S_ind */ size = A_ptr[m+1] - 1; if (size < m) size = m; S_ind = xcalloc(1+size, sizeof(int)); /* allocate and initialize working arrays */ ind = xcalloc(1+m, sizeof(int)); map = xcalloc(1+m, sizeof(int)); for (jj = 1; jj <= m; jj++) map[jj] = 0; /* compute pattern of S; note that symbolically S = B*B', where B = P*A, B' is matrix transposed to B */ S_ptr[1] = 1; for (ii = 1; ii <= m; ii++) { /* compute pattern of ii-th row of S */ len = 0; i = P_per[ii]; /* i-th row of A = ii-th row of B */ for (t = A_ptr[i]; t < A_ptr[i+1]; t++) { k = A_ind[t]; /* walk through k-th column of A */ for (tt = AT_ptr[k]; tt < AT_ptr[k+1]; tt++) { j = AT_ind[tt]; jj = P_per[m+j]; /* j-th row of A = jj-th row of B */ /* a[i,k] != 0 and a[j,k] != 0 ergo s[ii,jj] != 0 */ if (ii < jj && !map[jj]) ind[++len] = jj, map[jj] = 1; } } /* now (ind) is pattern of ii-th row of S */ S_ptr[ii+1] = S_ptr[ii] + len; /* at least (S_ptr[ii+1] - 1) locations should be available in the array S_ind */ if (S_ptr[ii+1] - 1 > size) { temp = S_ind; size += size; S_ind = xcalloc(1+size, sizeof(int)); memcpy(&S_ind[1], &temp[1], (S_ptr[ii] - 1) * sizeof(int)); xfree(temp); } xassert(S_ptr[ii+1] - 1 <= size); /* (ii-th row of S) := (ind) */ memcpy(&S_ind[S_ptr[ii]], &ind[1], len * sizeof(int)); /* clear the row pattern map */ for (t = 1; t <= len; t++) map[ind[t]] = 0; } /* free working arrays */ xfree(AT_ptr); xfree(AT_ind); xfree(ind); xfree(map); /* reallocate the array S_ind to free unused locations */ temp = S_ind; size = S_ptr[m+1] - 1; S_ind = xcalloc(1+size, sizeof(int)); memcpy(&S_ind[1], &temp[1], size * sizeof(int)); xfree(temp); return S_ind; } /*---------------------------------------------------------------------- -- adat_numeric - compute S = P*A*D*A'*P' (numeric phase). -- -- *Synopsis* -- -- #include "glpmat.h" -- void adat_numeric(int m, int n, int P_per[], -- int A_ptr[], int A_ind[], double A_val[], double D_diag[], -- int S_ptr[], int S_ind[], double S_val[], double S_diag[]); -- -- *Description* -- -- The routine adat_numeric implements the numeric phase to compute -- symmetric matrix S = P*A*D*A'*P', where P is a permutation matrix, -- A is a given sparse matrix, D is a diagonal matrix, A' is a matrix -- transposed to A, P' is an inverse of P. -- -- The parameter m is the number of rows in A and the order of P. -- -- The parameter n is the number of columns in A and the order of D. -- -- The matrix P is specified in the array P_per, which is not changed -- on exit. -- -- The matrix A is specified in the arrays A_ptr, A_ind, and A_val in -- storage-by-rows format. These arrays are not changed on exit. -- -- Diagonal elements of the matrix D are specified in the array D_diag, -- where D_diag[0] is not used, D_diag[i] = d[i,i] for i = 1, ..., n. -- The array D_diag is not changed on exit. -- -- The pattern of the upper triangular part of the matrix S without -- diagonal elements (previously computed by the routine adat_symbolic) -- is specified in the arrays S_ptr and S_ind, which are not changed on -- exit. Numeric values of non-diagonal elements of S are stored in -- corresponding locations of the array S_val, and values of diagonal -- elements of S are stored in locations S_diag[1], ..., S_diag[n]. */ void adat_numeric(int m, int n, int P_per[], int A_ptr[], int A_ind[], double A_val[], double D_diag[], int S_ptr[], int S_ind[], double S_val[], double S_diag[]) { int i, j, t, ii, jj, tt, beg, end, beg1, end1, k; double sum, *work; work = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) work[j] = 0.0; /* compute S = B*D*B', where B = P*A, B' is a matrix transposed to B */ for (ii = 1; ii <= m; ii++) { i = P_per[ii]; /* i-th row of A = ii-th row of B */ /* (work) := (i-th row of A) */ beg = A_ptr[i], end = A_ptr[i+1]; for (t = beg; t < end; t++) work[A_ind[t]] = A_val[t]; /* compute ii-th row of S */ beg = S_ptr[ii], end = S_ptr[ii+1]; for (t = beg; t < end; t++) { jj = S_ind[t]; j = P_per[jj]; /* j-th row of A = jj-th row of B */ /* s[ii,jj] := sum a[i,k] * d[k,k] * a[j,k] */ sum = 0.0; beg1 = A_ptr[j], end1 = A_ptr[j+1]; for (tt = beg1; tt < end1; tt++) { k = A_ind[tt]; sum += work[k] * D_diag[k] * A_val[tt]; } S_val[t] = sum; } /* s[ii,ii] := sum a[i,k] * d[k,k] * a[i,k] */ sum = 0.0; beg = A_ptr[i], end = A_ptr[i+1]; for (t = beg; t < end; t++) { k = A_ind[t]; sum += A_val[t] * D_diag[k] * A_val[t]; work[k] = 0.0; } S_diag[ii] = sum; } xfree(work); return; } /*---------------------------------------------------------------------- -- min_degree - minimum degree ordering. -- -- *Synopsis* -- -- #include "glpmat.h" -- void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]); -- -- *Description* -- -- The routine min_degree uses the minimum degree ordering algorithm -- to find a permutation matrix P for a given sparse symmetric positive -- matrix A which minimizes the number of non-zeros in upper triangular -- factor U for Cholesky factorization P*A*P' = U'*U. -- -- The parameter n is the order of matrices A and P. -- -- The pattern of the given matrix A is specified on entry in the arrays -- A_ptr and A_ind in storage-by-rows format. Only the upper triangular -- part without diagonal elements (which all are assumed to be non-zero) -- should be specified as if A were upper triangular. The arrays A_ptr -- and A_ind are not changed on exit. -- -- The permutation matrix P is stored by the routine in the array P_per -- on exit. -- -- *Algorithm* -- -- The routine min_degree is based on some subroutines from the package -- SPARSPAK (see comments in the module glpqmd). */ void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]) { int i, j, ne, t, pos, len; int *xadj, *adjncy, *deg, *marker, *rchset, *nbrhd, *qsize, *qlink, nofsub; /* determine number of non-zeros in complete pattern */ ne = A_ptr[n+1] - 1; ne += ne; /* allocate working arrays */ xadj = xcalloc(1+n+1, sizeof(int)); adjncy = xcalloc(1+ne, sizeof(int)); deg = xcalloc(1+n, sizeof(int)); marker = xcalloc(1+n, sizeof(int)); rchset = xcalloc(1+n, sizeof(int)); nbrhd = xcalloc(1+n, sizeof(int)); qsize = xcalloc(1+n, sizeof(int)); qlink = xcalloc(1+n, sizeof(int)); /* determine row lengths in complete pattern */ for (i = 1; i <= n; i++) xadj[i] = 0; for (i = 1; i <= n; i++) { for (t = A_ptr[i]; t < A_ptr[i+1]; t++) { j = A_ind[t]; xassert(i < j && j <= n); xadj[i]++, xadj[j]++; } } /* set up row pointers for complete pattern */ pos = 1; for (i = 1; i <= n; i++) len = xadj[i], pos += len, xadj[i] = pos; xadj[n+1] = pos; xassert(pos - 1 == ne); /* construct complete pattern */ for (i = 1; i <= n; i++) { for (t = A_ptr[i]; t < A_ptr[i+1]; t++) { j = A_ind[t]; adjncy[--xadj[i]] = j, adjncy[--xadj[j]] = i; } } /* call the main minimimum degree ordering routine */ genqmd(&n, xadj, adjncy, P_per, P_per + n, deg, marker, rchset, nbrhd, qsize, qlink, &nofsub); /* make sure that permutation matrix P is correct */ for (i = 1; i <= n; i++) { j = P_per[i]; xassert(1 <= j && j <= n); xassert(P_per[n+j] == i); } /* free working arrays */ xfree(xadj); xfree(adjncy); xfree(deg); xfree(marker); xfree(rchset); xfree(nbrhd); xfree(qsize); xfree(qlink); return; } /**********************************************************************/ void amd_order1(int n, int A_ptr[], int A_ind[], int P_per[]) { /* approximate minimum degree ordering (AMD) */ int k, ret; double Control[AMD_CONTROL], Info[AMD_INFO]; /* get the default parameters */ amd_defaults(Control); #if 0 /* and print them */ amd_control(Control); #endif /* make all indices 0-based */ for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]--; for (k = 1; k <= n+1; k++) A_ptr[k]--; /* call the ordering routine */ ret = amd_order(n, &A_ptr[1], &A_ind[1], &P_per[1], Control, Info) ; #if 0 amd_info(Info); #endif xassert(ret == AMD_OK || ret == AMD_OK_BUT_JUMBLED); /* retsore 1-based indices */ for (k = 1; k <= n+1; k++) A_ptr[k]++; for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]++; /* patch up permutation matrix */ memset(&P_per[n+1], 0, n * sizeof(int)); for (k = 1; k <= n; k++) { P_per[k]++; xassert(1 <= P_per[k] && P_per[k] <= n); xassert(P_per[n+P_per[k]] == 0); P_per[n+P_per[k]] = k; } return; } /**********************************************************************/ static void *allocate(size_t n, size_t size) { void *ptr; ptr = xcalloc(n, size); memset(ptr, 0, n * size); return ptr; } static void release(void *ptr) { xfree(ptr); return; } void symamd_ord(int n, int A_ptr[], int A_ind[], int P_per[]) { /* approximate minimum degree ordering (SYMAMD) */ int k, ok; int stats[COLAMD_STATS]; /* make all indices 0-based */ for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]--; for (k = 1; k <= n+1; k++) A_ptr[k]--; /* call the ordering routine */ ok = symamd(n, &A_ind[1], &A_ptr[1], &P_per[1], NULL, stats, allocate, release); #if 0 symamd_report(stats); #endif xassert(ok); /* restore 1-based indices */ for (k = 1; k <= n+1; k++) A_ptr[k]++; for (k = 1; k < A_ptr[n+1]; k++) A_ind[k]++; /* patch up permutation matrix */ memset(&P_per[n+1], 0, n * sizeof(int)); for (k = 1; k <= n; k++) { P_per[k]++; xassert(1 <= P_per[k] && P_per[k] <= n); xassert(P_per[n+P_per[k]] == 0); P_per[n+P_per[k]] = k; } return; } /*---------------------------------------------------------------------- -- chol_symbolic - compute Cholesky factorization (symbolic phase). -- -- *Synopsis* -- -- #include "glpmat.h" -- int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]); -- -- *Description* -- -- The routine chol_symbolic implements the symbolic phase of Cholesky -- factorization A = U'*U, where A is a given sparse symmetric positive -- definite matrix, U is a resultant upper triangular factor, U' is a -- matrix transposed to U. -- -- The parameter n is the order of matrices A and U. -- -- The pattern of the given matrix A is specified on entry in the arrays -- A_ptr and A_ind in storage-by-rows format. Only the upper triangular -- part without diagonal elements (which all are assumed to be non-zero) -- should be specified as if A were upper triangular. The arrays A_ptr -- and A_ind are not changed on exit. -- -- The pattern of the matrix U without diagonal elements (which all are -- assumed to be non-zero) is stored on exit from the routine in the -- arrays U_ptr and U_ind in storage-by-rows format. The array U_ptr -- should be allocated on entry, however, its content is ignored. The -- array U_ind is allocated by the routine which returns a pointer to it -- on exit. -- -- *Returns* -- -- The routine returns a pointer to the array U_ind. -- -- *Method* -- -- The routine chol_symbolic computes the pattern of the matrix U in a -- row-wise manner. No pivoting is used. -- -- It is known that to compute the pattern of row k of the matrix U we -- need to merge the pattern of row k of the matrix A and the patterns -- of each row i of U, where u[i,k] is non-zero (these rows are already -- computed and placed above row k). -- -- However, to reduce the number of rows to be merged the routine uses -- an advanced algorithm proposed in: -- -- D.J.Rose, R.E.Tarjan, and G.S.Lueker. Algorithmic aspects of vertex -- elimination on graphs. SIAM J. Comput. 5, 1976, 266-83. -- -- The authors of the cited paper show that we have the same result if -- we merge row k of the matrix A and such rows of the matrix U (among -- rows 1, ..., k-1) whose leftmost non-diagonal non-zero element is -- placed in k-th column. This feature signficantly reduces the number -- of rows to be merged, especially on the final steps, where rows of -- the matrix U become quite dense. -- -- To determine rows, which should be merged on k-th step, for a fixed -- time the routine uses linked lists of row numbers of the matrix U. -- Location head[k] contains the number of a first row, whose leftmost -- non-diagonal non-zero element is placed in column k, and location -- next[i] contains the number of a next row with the same property as -- row i. */ int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]) { int i, j, k, t, len, size, beg, end, min_j, *U_ind, *head, *next, *ind, *map, *temp; /* initially we assume that on computing the pattern of U fill-in will double the number of non-zeros in A */ size = A_ptr[n+1] - 1; if (size < n) size = n; size += size; U_ind = xcalloc(1+size, sizeof(int)); /* allocate and initialize working arrays */ head = xcalloc(1+n, sizeof(int)); for (i = 1; i <= n; i++) head[i] = 0; next = xcalloc(1+n, sizeof(int)); ind = xcalloc(1+n, sizeof(int)); map = xcalloc(1+n, sizeof(int)); for (j = 1; j <= n; j++) map[j] = 0; /* compute the pattern of matrix U */ U_ptr[1] = 1; for (k = 1; k <= n; k++) { /* compute the pattern of k-th row of U, which is the union of k-th row of A and those rows of U (among 1, ..., k-1) whose leftmost non-diagonal non-zero is placed in k-th column */ /* (ind) := (k-th row of A) */ len = A_ptr[k+1] - A_ptr[k]; memcpy(&ind[1], &A_ind[A_ptr[k]], len * sizeof(int)); for (t = 1; t <= len; t++) { j = ind[t]; xassert(k < j && j <= n); map[j] = 1; } /* walk through rows of U whose leftmost non-diagonal non-zero is placed in k-th column */ for (i = head[k]; i != 0; i = next[i]) { /* (ind) := (ind) union (i-th row of U) */ beg = U_ptr[i], end = U_ptr[i+1]; for (t = beg; t < end; t++) { j = U_ind[t]; if (j > k && !map[j]) ind[++len] = j, map[j] = 1; } } /* now (ind) is the pattern of k-th row of U */ U_ptr[k+1] = U_ptr[k] + len; /* at least (U_ptr[k+1] - 1) locations should be available in the array U_ind */ if (U_ptr[k+1] - 1 > size) { temp = U_ind; size += size; U_ind = xcalloc(1+size, sizeof(int)); memcpy(&U_ind[1], &temp[1], (U_ptr[k] - 1) * sizeof(int)); xfree(temp); } xassert(U_ptr[k+1] - 1 <= size); /* (k-th row of U) := (ind) */ memcpy(&U_ind[U_ptr[k]], &ind[1], len * sizeof(int)); /* determine column index of leftmost non-diagonal non-zero in k-th row of U and clear the row pattern map */ min_j = n + 1; for (t = 1; t <= len; t++) { j = ind[t], map[j] = 0; if (min_j > j) min_j = j; } /* include k-th row into corresponding linked list */ if (min_j <= n) next[k] = head[min_j], head[min_j] = k; } /* free working arrays */ xfree(head); xfree(next); xfree(ind); xfree(map); /* reallocate the array U_ind to free unused locations */ temp = U_ind; size = U_ptr[n+1] - 1; U_ind = xcalloc(1+size, sizeof(int)); memcpy(&U_ind[1], &temp[1], size * sizeof(int)); xfree(temp); return U_ind; } /*---------------------------------------------------------------------- -- chol_numeric - compute Cholesky factorization (numeric phase). -- -- *Synopsis* -- -- #include "glpmat.h" -- int chol_numeric(int n, -- int A_ptr[], int A_ind[], double A_val[], double A_diag[], -- int U_ptr[], int U_ind[], double U_val[], double U_diag[]); -- -- *Description* -- -- The routine chol_symbolic implements the numeric phase of Cholesky -- factorization A = U'*U, where A is a given sparse symmetric positive -- definite matrix, U is a resultant upper triangular factor, U' is a -- matrix transposed to U. -- -- The parameter n is the order of matrices A and U. -- -- Upper triangular part of the matrix A without diagonal elements is -- specified in the arrays A_ptr, A_ind, and A_val in storage-by-rows -- format. Diagonal elements of A are specified in the array A_diag, -- where A_diag[0] is not used, A_diag[i] = a[i,i] for i = 1, ..., n. -- The arrays A_ptr, A_ind, A_val, and A_diag are not changed on exit. -- -- The pattern of the matrix U without diagonal elements (previously -- computed with the routine chol_symbolic) is specified in the arrays -- U_ptr and U_ind, which are not changed on exit. Numeric values of -- non-diagonal elements of U are stored in corresponding locations of -- the array U_val, and values of diagonal elements of U are stored in -- locations U_diag[1], ..., U_diag[n]. -- -- *Returns* -- -- The routine returns the number of non-positive diagonal elements of -- the matrix U which have been replaced by a huge positive number (see -- the method description below). Zero return code means the matrix A -- has been successfully factorized. -- -- *Method* -- -- The routine chol_numeric computes the matrix U in a row-wise manner -- using standard gaussian elimination technique. No pivoting is used. -- -- Initially the routine sets U = A, and before k-th elimination step -- the matrix U is the following: -- -- 1 k n -- 1 x x x x x x x x x x -- . x x x x x x x x x -- . . x x x x x x x x -- . . . x x x x x x x -- k . . . . * * * * * * -- . . . . * * * * * * -- . . . . * * * * * * -- . . . . * * * * * * -- . . . . * * * * * * -- n . . . . * * * * * * -- -- where 'x' are elements of already computed rows, '*' are elements of -- the active submatrix. (Note that the lower triangular part of the -- active submatrix being symmetric is not stored and diagonal elements -- are stored separately in the array U_diag.) -- -- The matrix A is assumed to be positive definite. However, if it is -- close to semi-definite, on some elimination step a pivot u[k,k] may -- happen to be non-positive due to round-off errors. In this case the -- routine uses a technique proposed in: -- -- S.J.Wright. The Cholesky factorization in interior-point and barrier -- methods. Preprint MCS-P600-0596, Mathematics and Computer Science -- Division, Argonne National Laboratory, Argonne, Ill., May 1996. -- -- The routine just replaces non-positive u[k,k] by a huge positive -- number. This involves non-diagonal elements in k-th row of U to be -- close to zero that, in turn, involves k-th component of a solution -- vector to be close to zero. Note, however, that this technique works -- only if the system A*x = b is consistent. */ int chol_numeric(int n, int A_ptr[], int A_ind[], double A_val[], double A_diag[], int U_ptr[], int U_ind[], double U_val[], double U_diag[]) { int i, j, k, t, t1, beg, end, beg1, end1, count = 0; double ukk, uki, *work; work = xcalloc(1+n, sizeof(double)); for (j = 1; j <= n; j++) work[j] = 0.0; /* U := (upper triangle of A) */ /* note that the upper traingle of A is a subset of U */ for (i = 1; i <= n; i++) { beg = A_ptr[i], end = A_ptr[i+1]; for (t = beg; t < end; t++) j = A_ind[t], work[j] = A_val[t]; beg = U_ptr[i], end = U_ptr[i+1]; for (t = beg; t < end; t++) j = U_ind[t], U_val[t] = work[j], work[j] = 0.0; U_diag[i] = A_diag[i]; } /* main elimination loop */ for (k = 1; k <= n; k++) { /* transform k-th row of U */ ukk = U_diag[k]; if (ukk > 0.0) U_diag[k] = ukk = sqrt(ukk); else U_diag[k] = ukk = DBL_MAX, count++; /* (work) := (transformed k-th row) */ beg = U_ptr[k], end = U_ptr[k+1]; for (t = beg; t < end; t++) work[U_ind[t]] = (U_val[t] /= ukk); /* transform other rows of U */ for (t = beg; t < end; t++) { i = U_ind[t]; xassert(i > k); /* (i-th row) := (i-th row) - u[k,i] * (k-th row) */ uki = work[i]; beg1 = U_ptr[i], end1 = U_ptr[i+1]; for (t1 = beg1; t1 < end1; t1++) U_val[t1] -= uki * work[U_ind[t1]]; U_diag[i] -= uki * uki; } /* (work) := 0 */ for (t = beg; t < end; t++) work[U_ind[t]] = 0.0; } xfree(work); return count; } /*---------------------------------------------------------------------- -- u_solve - solve upper triangular system U*x = b. -- -- *Synopsis* -- -- #include "glpmat.h" -- void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], -- double U_diag[], double x[]); -- -- *Description* -- -- The routine u_solve solves an linear system U*x = b, where U is an -- upper triangular matrix. -- -- The parameter n is the order of matrix U. -- -- The matrix U without diagonal elements is specified in the arrays -- U_ptr, U_ind, and U_val in storage-by-rows format. Diagonal elements -- of U are specified in the array U_diag, where U_diag[0] is not used, -- U_diag[i] = u[i,i] for i = 1, ..., n. All these four arrays are not -- changed on exit. -- -- The right-hand side vector b is specified on entry in the array x, -- where x[0] is not used, and x[i] = b[i] for i = 1, ..., n. On exit -- the routine stores computed components of the vector of unknowns x -- in the array x in the same manner. */ void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], double U_diag[], double x[]) { int i, t, beg, end; double temp; for (i = n; i >= 1; i--) { temp = x[i]; beg = U_ptr[i], end = U_ptr[i+1]; for (t = beg; t < end; t++) temp -= U_val[t] * x[U_ind[t]]; xassert(U_diag[i] != 0.0); x[i] = temp / U_diag[i]; } return; } /*---------------------------------------------------------------------- -- ut_solve - solve lower triangular system U'*x = b. -- -- *Synopsis* -- -- #include "glpmat.h" -- void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], -- double U_diag[], double x[]); -- -- *Description* -- -- The routine ut_solve solves an linear system U'*x = b, where U is a -- matrix transposed to an upper triangular matrix. -- -- The parameter n is the order of matrix U. -- -- The matrix U without diagonal elements is specified in the arrays -- U_ptr, U_ind, and U_val in storage-by-rows format. Diagonal elements -- of U are specified in the array U_diag, where U_diag[0] is not used, -- U_diag[i] = u[i,i] for i = 1, ..., n. All these four arrays are not -- changed on exit. -- -- The right-hand side vector b is specified on entry in the array x, -- where x[0] is not used, and x[i] = b[i] for i = 1, ..., n. On exit -- the routine stores computed components of the vector of unknowns x -- in the array x in the same manner. */ void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], double U_diag[], double x[]) { int i, t, beg, end; double temp; for (i = 1; i <= n; i++) { xassert(U_diag[i] != 0.0); temp = (x[i] /= U_diag[i]); if (temp == 0.0) continue; beg = U_ptr[i], end = U_ptr[i+1]; for (t = beg; t < end; t++) x[U_ind[t]] -= U_val[t] * temp; } return; } /* eof */ glpk-4.52.1/src/glpmat.h0000644000062000006210000001643412175147600014155 0ustar maomkpasswd/* glpmat.h (linear algebra routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPMAT_H #define GLPMAT_H /*********************************************************************** * FULL-VECTOR STORAGE * * For a sparse vector x having n elements, ne of which are non-zero, * the full-vector storage format uses two arrays x_ind and x_vec, which * are set up as follows: * * x_ind is an integer array of length [1+ne]. Location x_ind[0] is * not used, and locations x_ind[1], ..., x_ind[ne] contain indices of * non-zero elements in vector x. * * x_vec is a floating-point array of length [1+n]. Location x_vec[0] * is not used, and locations x_vec[1], ..., x_vec[n] contain numeric * values of ALL elements in vector x, including its zero elements. * * Let, for example, the following sparse vector x be given: * * (0, 1, 0, 0, 2, 3, 0, 4) * * Then the arrays are: * * x_ind = { X; 2, 5, 6, 8 } * * x_vec = { X; 0, 1, 0, 0, 2, 3, 0, 4 } * * COMPRESSED-VECTOR STORAGE * * For a sparse vector x having n elements, ne of which are non-zero, * the compressed-vector storage format uses two arrays x_ind and x_vec, * which are set up as follows: * * x_ind is an integer array of length [1+ne]. Location x_ind[0] is * not used, and locations x_ind[1], ..., x_ind[ne] contain indices of * non-zero elements in vector x. * * x_vec is a floating-point array of length [1+ne]. Location x_vec[0] * is not used, and locations x_vec[1], ..., x_vec[ne] contain numeric * values of corresponding non-zero elements in vector x. * * Let, for example, the following sparse vector x be given: * * (0, 1, 0, 0, 2, 3, 0, 4) * * Then the arrays are: * * x_ind = { X; 2, 5, 6, 8 } * * x_vec = { X; 1, 2, 3, 4 } * * STORAGE-BY-ROWS * * For a sparse matrix A, which has m rows, n columns, and ne non-zero * elements the storage-by-rows format uses three arrays A_ptr, A_ind, * and A_val, which are set up as follows: * * A_ptr is an integer array of length [1+m+1] also called "row pointer * array". It contains the relative starting positions of each row of A * in the arrays A_ind and A_val, i.e. element A_ptr[i], 1 <= i <= m, * indicates where row i begins in the arrays A_ind and A_val. If all * elements in row i are zero, then A_ptr[i] = A_ptr[i+1]. Location * A_ptr[0] is not used, location A_ptr[1] must contain 1, and location * A_ptr[m+1] must contain ne+1 that indicates the position after the * last element in the arrays A_ind and A_val. * * A_ind is an integer array of length [1+ne]. Location A_ind[0] is not * used, and locations A_ind[1], ..., A_ind[ne] contain column indices * of (non-zero) elements in matrix A. * * A_val is a floating-point array of length [1+ne]. Location A_val[0] * is not used, and locations A_val[1], ..., A_val[ne] contain numeric * values of non-zero elements in matrix A. * * Non-zero elements of matrix A are stored contiguously, and the rows * of matrix A are stored consecutively from 1 to m in the arrays A_ind * and A_val. The elements in each row of A may be stored in any order * in A_ind and A_val. Note that elements with duplicate column indices * are not allowed. * * Let, for example, the following sparse matrix A be given: * * | 11 . 13 . . . | * | 21 22 . 24 . . | * | . 32 33 . . . | * | . . 43 44 . 46 | * | . . . . . . | * | 61 62 . . . 66 | * * Then the arrays are: * * A_ptr = { X; 1, 3, 6, 8, 11, 11; 14 } * * A_ind = { X; 1, 3; 4, 2, 1; 2, 3; 4, 3, 6; 1, 2, 6 } * * A_val = { X; 11, 13; 24, 22, 21; 32, 33; 44, 43, 46; 61, 62, 66 } * * PERMUTATION MATRICES * * Let P be a permutation matrix of the order n. It is represented as * an integer array P_per of length [1+n+n] as follows: if p[i,j] = 1, * then P_per[i] = j and P_per[n+j] = i. Location P_per[0] is not used. * * Let A' = P*A. If i-th row of A corresponds to i'-th row of A', then * P_per[i'] = i and P_per[n+i] = i'. * * References: * * 1. Gustavson F.G. Some basic techniques for solving sparse systems of * linear equations. In Rose and Willoughby (1972), pp. 41-52. * * 2. Basic Linear Algebra Subprograms Technical (BLAST) Forum Standard. * University of Tennessee (2001). */ #define check_fvs _glp_mat_check_fvs int check_fvs(int n, int nnz, int ind[], double vec[]); /* check sparse vector in full-vector storage format */ #define check_pattern _glp_mat_check_pattern int check_pattern(int m, int n, int A_ptr[], int A_ind[]); /* check pattern of sparse matrix */ #define transpose _glp_mat_transpose void transpose(int m, int n, int A_ptr[], int A_ind[], double A_val[], int AT_ptr[], int AT_ind[], double AT_val[]); /* transpose sparse matrix */ #define adat_symbolic _glp_mat_adat_symbolic int *adat_symbolic(int m, int n, int P_per[], int A_ptr[], int A_ind[], int S_ptr[]); /* compute S = P*A*D*A'*P' (symbolic phase) */ #define adat_numeric _glp_mat_adat_numeric void adat_numeric(int m, int n, int P_per[], int A_ptr[], int A_ind[], double A_val[], double D_diag[], int S_ptr[], int S_ind[], double S_val[], double S_diag[]); /* compute S = P*A*D*A'*P' (numeric phase) */ #define min_degree _glp_mat_min_degree void min_degree(int n, int A_ptr[], int A_ind[], int P_per[]); /* minimum degree ordering */ #define amd_order1 _glp_mat_amd_order1 void amd_order1(int n, int A_ptr[], int A_ind[], int P_per[]); /* approximate minimum degree ordering (AMD) */ #define symamd_ord _glp_mat_symamd_ord void symamd_ord(int n, int A_ptr[], int A_ind[], int P_per[]); /* approximate minimum degree ordering (SYMAMD) */ #define chol_symbolic _glp_mat_chol_symbolic int *chol_symbolic(int n, int A_ptr[], int A_ind[], int U_ptr[]); /* compute Cholesky factorization (symbolic phase) */ #define chol_numeric _glp_mat_chol_numeric int chol_numeric(int n, int A_ptr[], int A_ind[], double A_val[], double A_diag[], int U_ptr[], int U_ind[], double U_val[], double U_diag[]); /* compute Cholesky factorization (numeric phase) */ #define u_solve _glp_mat_u_solve void u_solve(int n, int U_ptr[], int U_ind[], double U_val[], double U_diag[], double x[]); /* solve upper triangular system U*x = b */ #define ut_solve _glp_mat_ut_solve void ut_solve(int n, int U_ptr[], int U_ind[], double U_val[], double U_diag[], double x[]); /* solve lower triangular system U'*x = b */ #endif /* eof */ glpk-4.52.1/src/glpmpl.h0000644000062000006210000025744712175147600014177 0ustar maomkpasswd/* glpmpl.h (GNU MathProg translator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPMPL_H #define GLPMPL_H #if 1 /* 11/VI-2013 */ #include "env2.h" #endif #include "glpavl.h" #include "glplib.h" #include "rng.h" #if 0 /* 22/I-2013 */ typedef struct MPL MPL; #else typedef struct glp_tran MPL; #endif typedef char STRING; typedef struct SYMBOL SYMBOL; typedef struct TUPLE TUPLE; typedef struct ARRAY ELEMSET; typedef struct ELEMVAR ELEMVAR; typedef struct FORMULA FORMULA; typedef struct ELEMCON ELEMCON; typedef union VALUE VALUE; typedef struct ARRAY ARRAY; typedef struct MEMBER MEMBER; #if 1 /* many C compilers have DOMAIN declared in :( */ #undef DOMAIN #define DOMAIN DOMAIN1 #endif typedef struct DOMAIN DOMAIN; typedef struct DOMAIN_BLOCK DOMAIN_BLOCK; typedef struct DOMAIN_SLOT DOMAIN_SLOT; typedef struct SET SET; typedef struct WITHIN WITHIN; typedef struct GADGET GADGET; typedef struct PARAMETER PARAMETER; typedef struct CONDITION CONDITION; typedef struct VARIABLE VARIABLE; typedef struct CONSTRAINT CONSTRAINT; typedef struct TABLE TABLE; typedef struct TABARG TABARG; typedef struct TABFLD TABFLD; typedef struct TABIN TABIN; typedef struct TABOUT TABOUT; typedef struct TABDCA TABDCA; typedef union OPERANDS OPERANDS; typedef struct ARG_LIST ARG_LIST; typedef struct CODE CODE; typedef struct CHECK CHECK; typedef struct DISPLAY DISPLAY; typedef struct DISPLAY1 DISPLAY1; typedef struct PRINTF PRINTF; typedef struct PRINTF1 PRINTF1; typedef struct FOR FOR; typedef struct STATEMENT STATEMENT; typedef struct TUPLE SLICE; /**********************************************************************/ /* * * TRANSLATOR DATABASE * * */ /**********************************************************************/ #define A_BINARY 101 /* something binary */ #define A_CHECK 102 /* check statement */ #define A_CONSTRAINT 103 /* model constraint */ #define A_DISPLAY 104 /* display statement */ #define A_ELEMCON 105 /* elemental constraint/objective */ #define A_ELEMSET 106 /* elemental set */ #define A_ELEMVAR 107 /* elemental variable */ #define A_EXPRESSION 108 /* expression */ #define A_FOR 109 /* for statement */ #define A_FORMULA 110 /* formula */ #define A_INDEX 111 /* dummy index */ #define A_INPUT 112 /* input table */ #define A_INTEGER 113 /* something integer */ #define A_LOGICAL 114 /* something logical */ #define A_MAXIMIZE 115 /* objective has to be maximized */ #define A_MINIMIZE 116 /* objective has to be minimized */ #define A_NONE 117 /* nothing */ #define A_NUMERIC 118 /* something numeric */ #define A_OUTPUT 119 /* output table */ #define A_PARAMETER 120 /* model parameter */ #define A_PRINTF 121 /* printf statement */ #define A_SET 122 /* model set */ #define A_SOLVE 123 /* solve statement */ #define A_SYMBOLIC 124 /* something symbolic */ #define A_TABLE 125 /* data table */ #define A_TUPLE 126 /* n-tuple */ #define A_VARIABLE 127 /* model variable */ #define MAX_LENGTH 100 /* maximal length of any symbolic value (this includes symbolic names, numeric and string literals, and all symbolic values that may appear during the evaluation phase) */ #define CONTEXT_SIZE 60 /* size of the context queue, in characters */ #define OUTBUF_SIZE 1024 /* size of the output buffer, in characters */ #if 0 /* 22/I-2013 */ struct MPL #else struct glp_tran #endif { /* translator database */ /*--------------------------------------------------------------*/ /* scanning segment */ int line; /* number of the current text line */ int c; /* the current character or EOF */ int token; /* the current token: */ #define T_EOF 201 /* end of file */ #define T_NAME 202 /* symbolic name (model section only) */ #define T_SYMBOL 203 /* symbol (data section only) */ #define T_NUMBER 204 /* numeric literal */ #define T_STRING 205 /* string literal */ #define T_AND 206 /* and && */ #define T_BY 207 /* by */ #define T_CROSS 208 /* cross */ #define T_DIFF 209 /* diff */ #define T_DIV 210 /* div */ #define T_ELSE 211 /* else */ #define T_IF 212 /* if */ #define T_IN 213 /* in */ #define T_INFINITY 214 /* Infinity */ #define T_INTER 215 /* inter */ #define T_LESS 216 /* less */ #define T_MOD 217 /* mod */ #define T_NOT 218 /* not ! */ #define T_OR 219 /* or || */ #define T_SPTP 220 /* s.t. */ #define T_SYMDIFF 221 /* symdiff */ #define T_THEN 222 /* then */ #define T_UNION 223 /* union */ #define T_WITHIN 224 /* within */ #define T_PLUS 225 /* + */ #define T_MINUS 226 /* - */ #define T_ASTERISK 227 /* * */ #define T_SLASH 228 /* / */ #define T_POWER 229 /* ^ ** */ #define T_LT 230 /* < */ #define T_LE 231 /* <= */ #define T_EQ 232 /* = == */ #define T_GE 233 /* >= */ #define T_GT 234 /* > */ #define T_NE 235 /* <> != */ #define T_CONCAT 236 /* & */ #define T_BAR 237 /* | */ #define T_POINT 238 /* . */ #define T_COMMA 239 /* , */ #define T_COLON 240 /* : */ #define T_SEMICOLON 241 /* ; */ #define T_ASSIGN 242 /* := */ #define T_DOTS 243 /* .. */ #define T_LEFT 244 /* ( */ #define T_RIGHT 245 /* ) */ #define T_LBRACKET 246 /* [ */ #define T_RBRACKET 247 /* ] */ #define T_LBRACE 248 /* { */ #define T_RBRACE 249 /* } */ #define T_APPEND 250 /* >> */ #define T_TILDE 251 /* ~ */ #define T_INPUT 252 /* <- */ int imlen; /* length of the current token */ char *image; /* char image[MAX_LENGTH+1]; */ /* image of the current token */ double value; /* value of the current token (for T_NUMBER only) */ int b_token; /* the previous token */ int b_imlen; /* length of the previous token */ char *b_image; /* char b_image[MAX_LENGTH+1]; */ /* image of the previous token */ double b_value; /* value of the previous token (if token is T_NUMBER) */ int f_dots; /* if this flag is set, the next token should be recognized as T_DOTS, not as T_POINT */ int f_scan; /* if this flag is set, the next token is already scanned */ int f_token; /* the next token */ int f_imlen; /* length of the next token */ char *f_image; /* char f_image[MAX_LENGTH+1]; */ /* image of the next token */ double f_value; /* value of the next token (if token is T_NUMBER) */ char *context; /* char context[CONTEXT_SIZE]; */ /* context circular queue (not null-terminated!) */ int c_ptr; /* pointer to the current position in the context queue */ int flag_d; /* if this flag is set, the data section is being processed */ /*--------------------------------------------------------------*/ /* translating segment */ DMP *pool; /* memory pool used to allocate all data instances created during the translation phase */ AVL *tree; /* symbolic name table: node.type = A_INDEX => node.link -> DOMAIN_SLOT node.type = A_SET => node.link -> SET node.type = A_PARAMETER => node.link -> PARAMETER node.type = A_VARIABLE => node.link -> VARIABLE node.type = A_CONSTRANT => node.link -> CONSTRAINT */ STATEMENT *model; /* linked list of model statements in the original order */ int flag_x; /* if this flag is set, the current token being left parenthesis begins a slice that allows recognizing any undeclared symbolic names as dummy indices; this flag is automatically reset once the next token has been scanned */ int as_within; /* the warning "in understood as within" has been issued */ int as_in; /* the warning "within understood as in" has been issued */ int as_binary; /* the warning "logical understood as binary" has been issued */ int flag_s; /* if this flag is set, the solve statement has been parsed */ /*--------------------------------------------------------------*/ /* common segment */ DMP *strings; /* memory pool to allocate STRING data structures */ DMP *symbols; /* memory pool to allocate SYMBOL data structures */ DMP *tuples; /* memory pool to allocate TUPLE data structures */ DMP *arrays; /* memory pool to allocate ARRAY data structures */ DMP *members; /* memory pool to allocate MEMBER data structures */ DMP *elemvars; /* memory pool to allocate ELEMVAR data structures */ DMP *formulae; /* memory pool to allocate FORMULA data structures */ DMP *elemcons; /* memory pool to allocate ELEMCON data structures */ ARRAY *a_list; /* linked list of all arrays in the database */ char *sym_buf; /* char sym_buf[255+1]; */ /* working buffer used by the routine format_symbol */ char *tup_buf; /* char tup_buf[255+1]; */ /* working buffer used by the routine format_tuple */ /*--------------------------------------------------------------*/ /* generating/postsolving segment */ RNG *rand; /* pseudo-random number generator */ int flag_p; /* if this flag is set, the postsolving phase is in effect */ STATEMENT *stmt; /* model statement being currently executed */ TABDCA *dca; /* pointer to table driver communication area for table statement currently executed */ int m; /* number of rows in the problem, m >= 0 */ int n; /* number of columns in the problem, n >= 0 */ ELEMCON **row; /* ELEMCON *row[1+m]; */ /* row[0] is not used; row[i] is elemental constraint or objective, which corresponds to i-th row of the problem, 1 <= i <= m */ ELEMVAR **col; /* ELEMVAR *col[1+n]; */ /* col[0] is not used; col[j] is elemental variable, which corresponds to j-th column of the problem, 1 <= j <= n */ /*--------------------------------------------------------------*/ /* input/output segment */ XFILE *in_fp; /* stream assigned to the input text file */ char *in_file; /* name of the input text file */ XFILE *out_fp; /* stream assigned to the output text file used to write all data produced by display and printf statements; NULL means the data should be sent to stdout via the routine xprintf */ char *out_file; /* name of the output text file */ #if 0 /* 08/XI-2009 */ char *out_buf; /* char out_buf[OUTBUF_SIZE] */ /* buffer to accumulate output data */ int out_cnt; /* count of data bytes stored in the output buffer */ #endif XFILE *prt_fp; /* stream assigned to the print text file; may be NULL */ char *prt_file; /* name of the output print file */ /*--------------------------------------------------------------*/ /* solver interface segment */ jmp_buf jump; /* jump address for non-local go to in case of error */ int phase; /* phase of processing: 0 - database is being or has been initialized 1 - model section is being or has been read 2 - data section is being or has been read 3 - model is being or has been generated/postsolved 4 - model processing error has occurred */ char *mod_file; /* name of the input text file, which contains model section */ char *mpl_buf; /* char mpl_buf[255+1]; */ /* working buffer used by some interface routines */ }; /**********************************************************************/ /* * * PROCESSING MODEL SECTION * * */ /**********************************************************************/ #define alloc(type) ((type *)dmp_get_atomv(mpl->pool, sizeof(type))) /* allocate atom of given type */ #define enter_context _glp_mpl_enter_context void enter_context(MPL *mpl); /* enter current token into context queue */ #define print_context _glp_mpl_print_context void print_context(MPL *mpl); /* print current content of context queue */ #define get_char _glp_mpl_get_char void get_char(MPL *mpl); /* scan next character from input text file */ #define append_char _glp_mpl_append_char void append_char(MPL *mpl); /* append character to current token */ #define get_token _glp_mpl_get_token void get_token(MPL *mpl); /* scan next token from input text file */ #define unget_token _glp_mpl_unget_token void unget_token(MPL *mpl); /* return current token back to input stream */ #define is_keyword _glp_mpl_is_keyword int is_keyword(MPL *mpl, char *keyword); /* check if current token is given non-reserved keyword */ #define is_reserved _glp_mpl_is_reserved int is_reserved(MPL *mpl); /* check if current token is reserved keyword */ #define make_code _glp_mpl_make_code CODE *make_code(MPL *mpl, int op, OPERANDS *arg, int type, int dim); /* generate pseudo-code (basic routine) */ #define make_unary _glp_mpl_make_unary CODE *make_unary(MPL *mpl, int op, CODE *x, int type, int dim); /* generate pseudo-code for unary operation */ #define make_binary _glp_mpl_make_binary CODE *make_binary(MPL *mpl, int op, CODE *x, CODE *y, int type, int dim); /* generate pseudo-code for binary operation */ #define make_ternary _glp_mpl_make_ternary CODE *make_ternary(MPL *mpl, int op, CODE *x, CODE *y, CODE *z, int type, int dim); /* generate pseudo-code for ternary operation */ #define numeric_literal _glp_mpl_numeric_literal CODE *numeric_literal(MPL *mpl); /* parse reference to numeric literal */ #define string_literal _glp_mpl_string_literal CODE *string_literal(MPL *mpl); /* parse reference to string literal */ #define create_arg_list _glp_mpl_create_arg_list ARG_LIST *create_arg_list(MPL *mpl); /* create empty operands list */ #define expand_arg_list _glp_mpl_expand_arg_list ARG_LIST *expand_arg_list(MPL *mpl, ARG_LIST *list, CODE *x); /* append operand to operands list */ #define arg_list_len _glp_mpl_arg_list_len int arg_list_len(MPL *mpl, ARG_LIST *list); /* determine length of operands list */ #define subscript_list _glp_mpl_subscript_list ARG_LIST *subscript_list(MPL *mpl); /* parse subscript list */ #define object_reference _glp_mpl_object_reference CODE *object_reference(MPL *mpl); /* parse reference to named object */ #define numeric_argument _glp_mpl_numeric_argument CODE *numeric_argument(MPL *mpl, char *func); /* parse argument passed to built-in function */ #define symbolic_argument _glp_mpl_symbolic_argument CODE *symbolic_argument(MPL *mpl, char *func); #define elemset_argument _glp_mpl_elemset_argument CODE *elemset_argument(MPL *mpl, char *func); #define function_reference _glp_mpl_function_reference CODE *function_reference(MPL *mpl); /* parse reference to built-in function */ #define create_domain _glp_mpl_create_domain DOMAIN *create_domain(MPL *mpl); /* create empty domain */ #define create_block _glp_mpl_create_block DOMAIN_BLOCK *create_block(MPL *mpl); /* create empty domain block */ #define append_block _glp_mpl_append_block void append_block(MPL *mpl, DOMAIN *domain, DOMAIN_BLOCK *block); /* append domain block to specified domain */ #define append_slot _glp_mpl_append_slot DOMAIN_SLOT *append_slot(MPL *mpl, DOMAIN_BLOCK *block, char *name, CODE *code); /* create and append new slot to domain block */ #define expression_list _glp_mpl_expression_list CODE *expression_list(MPL *mpl); /* parse expression list */ #define literal_set _glp_mpl_literal_set CODE *literal_set(MPL *mpl, CODE *code); /* parse literal set */ #define indexing_expression _glp_mpl_indexing_expression DOMAIN *indexing_expression(MPL *mpl); /* parse indexing expression */ #define close_scope _glp_mpl_close_scope void close_scope(MPL *mpl, DOMAIN *domain); /* close scope of indexing expression */ #define iterated_expression _glp_mpl_iterated_expression CODE *iterated_expression(MPL *mpl); /* parse iterated expression */ #define domain_arity _glp_mpl_domain_arity int domain_arity(MPL *mpl, DOMAIN *domain); /* determine arity of domain */ #define set_expression _glp_mpl_set_expression CODE *set_expression(MPL *mpl); /* parse set expression */ #define branched_expression _glp_mpl_branched_expression CODE *branched_expression(MPL *mpl); /* parse conditional expression */ #define primary_expression _glp_mpl_primary_expression CODE *primary_expression(MPL *mpl); /* parse primary expression */ #define error_preceding _glp_mpl_error_preceding void error_preceding(MPL *mpl, char *opstr); /* raise error if preceding operand has wrong type */ #define error_following _glp_mpl_error_following void error_following(MPL *mpl, char *opstr); /* raise error if following operand has wrong type */ #define error_dimension _glp_mpl_error_dimension void error_dimension(MPL *mpl, char *opstr, int dim1, int dim2); /* raise error if operands have different dimension */ #define expression_0 _glp_mpl_expression_0 CODE *expression_0(MPL *mpl); /* parse expression of level 0 */ #define expression_1 _glp_mpl_expression_1 CODE *expression_1(MPL *mpl); /* parse expression of level 1 */ #define expression_2 _glp_mpl_expression_2 CODE *expression_2(MPL *mpl); /* parse expression of level 2 */ #define expression_3 _glp_mpl_expression_3 CODE *expression_3(MPL *mpl); /* parse expression of level 3 */ #define expression_4 _glp_mpl_expression_4 CODE *expression_4(MPL *mpl); /* parse expression of level 4 */ #define expression_5 _glp_mpl_expression_5 CODE *expression_5(MPL *mpl); /* parse expression of level 5 */ #define expression_6 _glp_mpl_expression_6 CODE *expression_6(MPL *mpl); /* parse expression of level 6 */ #define expression_7 _glp_mpl_expression_7 CODE *expression_7(MPL *mpl); /* parse expression of level 7 */ #define expression_8 _glp_mpl_expression_8 CODE *expression_8(MPL *mpl); /* parse expression of level 8 */ #define expression_9 _glp_mpl_expression_9 CODE *expression_9(MPL *mpl); /* parse expression of level 9 */ #define expression_10 _glp_mpl_expression_10 CODE *expression_10(MPL *mpl); /* parse expression of level 10 */ #define expression_11 _glp_mpl_expression_11 CODE *expression_11(MPL *mpl); /* parse expression of level 11 */ #define expression_12 _glp_mpl_expression_12 CODE *expression_12(MPL *mpl); /* parse expression of level 12 */ #define expression_13 _glp_mpl_expression_13 CODE *expression_13(MPL *mpl); /* parse expression of level 13 */ #define set_statement _glp_mpl_set_statement SET *set_statement(MPL *mpl); /* parse set statement */ #define parameter_statement _glp_mpl_parameter_statement PARAMETER *parameter_statement(MPL *mpl); /* parse parameter statement */ #define variable_statement _glp_mpl_variable_statement VARIABLE *variable_statement(MPL *mpl); /* parse variable statement */ #define constraint_statement _glp_mpl_constraint_statement CONSTRAINT *constraint_statement(MPL *mpl); /* parse constraint statement */ #define objective_statement _glp_mpl_objective_statement CONSTRAINT *objective_statement(MPL *mpl); /* parse objective statement */ #define table_statement _glp_mpl_table_statement TABLE *table_statement(MPL *mpl); /* parse table statement */ #define solve_statement _glp_mpl_solve_statement void *solve_statement(MPL *mpl); /* parse solve statement */ #define check_statement _glp_mpl_check_statement CHECK *check_statement(MPL *mpl); /* parse check statement */ #define display_statement _glp_mpl_display_statement DISPLAY *display_statement(MPL *mpl); /* parse display statement */ #define printf_statement _glp_mpl_printf_statement PRINTF *printf_statement(MPL *mpl); /* parse printf statement */ #define for_statement _glp_mpl_for_statement FOR *for_statement(MPL *mpl); /* parse for statement */ #define end_statement _glp_mpl_end_statement void end_statement(MPL *mpl); /* parse end statement */ #define simple_statement _glp_mpl_simple_statement STATEMENT *simple_statement(MPL *mpl, int spec); /* parse simple statement */ #define model_section _glp_mpl_model_section void model_section(MPL *mpl); /* parse model section */ /**********************************************************************/ /* * * PROCESSING DATA SECTION * * */ /**********************************************************************/ #if 2 + 2 == 5 struct SLICE /* see TUPLE */ { /* component of slice; the slice itself is associated with its first component; slices are similar to n-tuples with exception that some slice components (which are indicated by asterisks) don't refer to any symbols */ SYMBOL *sym; /* symbol, which this component refers to; can be NULL */ SLICE *next; /* the next component of slice */ }; #endif #define create_slice _glp_mpl_create_slice SLICE *create_slice(MPL *mpl); /* create slice */ #define expand_slice _glp_mpl_expand_slice SLICE *expand_slice ( MPL *mpl, SLICE *slice, /* destroyed */ SYMBOL *sym /* destroyed */ ); /* append new component to slice */ #define slice_dimen _glp_mpl_slice_dimen int slice_dimen ( MPL *mpl, SLICE *slice /* not changed */ ); /* determine dimension of slice */ #define slice_arity _glp_mpl_slice_arity int slice_arity ( MPL *mpl, SLICE *slice /* not changed */ ); /* determine arity of slice */ #define fake_slice _glp_mpl_fake_slice SLICE *fake_slice(MPL *mpl, int dim); /* create fake slice of all asterisks */ #define delete_slice _glp_mpl_delete_slice void delete_slice ( MPL *mpl, SLICE *slice /* destroyed */ ); /* delete slice */ #define is_number _glp_mpl_is_number int is_number(MPL *mpl); /* check if current token is number */ #define is_symbol _glp_mpl_is_symbol int is_symbol(MPL *mpl); /* check if current token is symbol */ #define is_literal _glp_mpl_is_literal int is_literal(MPL *mpl, char *literal); /* check if current token is given symbolic literal */ #define read_number _glp_mpl_read_number double read_number(MPL *mpl); /* read number */ #define read_symbol _glp_mpl_read_symbol SYMBOL *read_symbol(MPL *mpl); /* read symbol */ #define read_slice _glp_mpl_read_slice SLICE *read_slice ( MPL *mpl, char *name, /* not changed */ int dim ); /* read slice */ #define select_set _glp_mpl_select_set SET *select_set ( MPL *mpl, char *name /* not changed */ ); /* select set to saturate it with elemental sets */ #define simple_format _glp_mpl_simple_format void simple_format ( MPL *mpl, SET *set, /* not changed */ MEMBER *memb, /* modified */ SLICE *slice /* not changed */ ); /* read set data block in simple format */ #define matrix_format _glp_mpl_matrix_format void matrix_format ( MPL *mpl, SET *set, /* not changed */ MEMBER *memb, /* modified */ SLICE *slice, /* not changed */ int tr ); /* read set data block in matrix format */ #define set_data _glp_mpl_set_data void set_data(MPL *mpl); /* read set data */ #define select_parameter _glp_mpl_select_parameter PARAMETER *select_parameter ( MPL *mpl, char *name /* not changed */ ); /* select parameter to saturate it with data */ #define set_default _glp_mpl_set_default void set_default ( MPL *mpl, PARAMETER *par, /* not changed */ SYMBOL *altval /* destroyed */ ); /* set default parameter value */ #define read_value _glp_mpl_read_value MEMBER *read_value ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* destroyed */ ); /* read value and assign it to parameter member */ #define plain_format _glp_mpl_plain_format void plain_format ( MPL *mpl, PARAMETER *par, /* not changed */ SLICE *slice /* not changed */ ); /* read parameter data block in plain format */ #define tabular_format _glp_mpl_tabular_format void tabular_format ( MPL *mpl, PARAMETER *par, /* not changed */ SLICE *slice, /* not changed */ int tr ); /* read parameter data block in tabular format */ #define tabbing_format _glp_mpl_tabbing_format void tabbing_format ( MPL *mpl, SYMBOL *altval /* not changed */ ); /* read parameter data block in tabbing format */ #define parameter_data _glp_mpl_parameter_data void parameter_data(MPL *mpl); /* read parameter data */ #define data_section _glp_mpl_data_section void data_section(MPL *mpl); /* read data section */ /**********************************************************************/ /* * * FLOATING-POINT NUMBERS * * */ /**********************************************************************/ #define fp_add _glp_mpl_fp_add double fp_add(MPL *mpl, double x, double y); /* floating-point addition */ #define fp_sub _glp_mpl_fp_sub double fp_sub(MPL *mpl, double x, double y); /* floating-point subtraction */ #define fp_less _glp_mpl_fp_less double fp_less(MPL *mpl, double x, double y); /* floating-point non-negative subtraction */ #define fp_mul _glp_mpl_fp_mul double fp_mul(MPL *mpl, double x, double y); /* floating-point multiplication */ #define fp_div _glp_mpl_fp_div double fp_div(MPL *mpl, double x, double y); /* floating-point division */ #define fp_idiv _glp_mpl_fp_idiv double fp_idiv(MPL *mpl, double x, double y); /* floating-point quotient of exact division */ #define fp_mod _glp_mpl_fp_mod double fp_mod(MPL *mpl, double x, double y); /* floating-point remainder of exact division */ #define fp_power _glp_mpl_fp_power double fp_power(MPL *mpl, double x, double y); /* floating-point exponentiation (raise to power) */ #define fp_exp _glp_mpl_fp_exp double fp_exp(MPL *mpl, double x); /* floating-point base-e exponential */ #define fp_log _glp_mpl_fp_log double fp_log(MPL *mpl, double x); /* floating-point natural logarithm */ #define fp_log10 _glp_mpl_fp_log10 double fp_log10(MPL *mpl, double x); /* floating-point common (decimal) logarithm */ #define fp_sqrt _glp_mpl_fp_sqrt double fp_sqrt(MPL *mpl, double x); /* floating-point square root */ #define fp_sin _glp_mpl_fp_sin double fp_sin(MPL *mpl, double x); /* floating-point trigonometric sine */ #define fp_cos _glp_mpl_fp_cos double fp_cos(MPL *mpl, double x); /* floating-point trigonometric cosine */ #define fp_atan _glp_mpl_fp_atan double fp_atan(MPL *mpl, double x); /* floating-point trigonometric arctangent */ #define fp_atan2 _glp_mpl_fp_atan2 double fp_atan2(MPL *mpl, double y, double x); /* floating-point trigonometric arctangent */ #define fp_round _glp_mpl_fp_round double fp_round(MPL *mpl, double x, double n); /* round floating-point value to n fractional digits */ #define fp_trunc _glp_mpl_fp_trunc double fp_trunc(MPL *mpl, double x, double n); /* truncate floating-point value to n fractional digits */ /**********************************************************************/ /* * * PSEUDO-RANDOM NUMBER GENERATORS * * */ /**********************************************************************/ #define fp_irand224 _glp_mpl_fp_irand224 double fp_irand224(MPL *mpl); /* pseudo-random integer in the range [0, 2^24) */ #define fp_uniform01 _glp_mpl_fp_uniform01 double fp_uniform01(MPL *mpl); /* pseudo-random number in the range [0, 1) */ #define fp_uniform _glp_mpl_uniform double fp_uniform(MPL *mpl, double a, double b); /* pseudo-random number in the range [a, b) */ #define fp_normal01 _glp_mpl_fp_normal01 double fp_normal01(MPL *mpl); /* Gaussian random variate with mu = 0 and sigma = 1 */ #define fp_normal _glp_mpl_fp_normal double fp_normal(MPL *mpl, double mu, double sigma); /* Gaussian random variate with specified mu and sigma */ /**********************************************************************/ /* * * DATE/TIME * * */ /**********************************************************************/ #define fn_gmtime _glp_mpl_fn_gmtime double fn_gmtime(MPL *mpl); /* obtain the current calendar time (UTC) */ #define fn_str2time _glp_mpl_fn_str2time double fn_str2time(MPL *mpl, const char *str, const char *fmt); /* convert character string to the calendar time */ #define fn_time2str _glp_mpl_fn_time2str void fn_time2str(MPL *mpl, char *str, double t, const char *fmt); /* convert the calendar time to character string */ /**********************************************************************/ /* * * CHARACTER STRINGS * * */ /**********************************************************************/ #define create_string _glp_mpl_create_string STRING *create_string ( MPL *mpl, char buf[MAX_LENGTH+1] /* not changed */ ); /* create character string */ #define copy_string _glp_mpl_copy_string STRING *copy_string ( MPL *mpl, STRING *str /* not changed */ ); /* make copy of character string */ #define compare_strings _glp_mpl_compare_strings int compare_strings ( MPL *mpl, STRING *str1, /* not changed */ STRING *str2 /* not changed */ ); /* compare one character string with another */ #define fetch_string _glp_mpl_fetch_string char *fetch_string ( MPL *mpl, STRING *str, /* not changed */ char buf[MAX_LENGTH+1] /* modified */ ); /* extract content of character string */ #define delete_string _glp_mpl_delete_string void delete_string ( MPL *mpl, STRING *str /* destroyed */ ); /* delete character string */ /**********************************************************************/ /* * * SYMBOLS * * */ /**********************************************************************/ struct SYMBOL { /* symbol (numeric or abstract quantity) */ double num; /* numeric value of symbol (used only if str == NULL) */ STRING *str; /* abstract value of symbol (used only if str != NULL) */ }; #define create_symbol_num _glp_mpl_create_symbol_num SYMBOL *create_symbol_num(MPL *mpl, double num); /* create symbol of numeric type */ #define create_symbol_str _glp_mpl_create_symbol_str SYMBOL *create_symbol_str ( MPL *mpl, STRING *str /* destroyed */ ); /* create symbol of abstract type */ #define copy_symbol _glp_mpl_copy_symbol SYMBOL *copy_symbol ( MPL *mpl, SYMBOL *sym /* not changed */ ); /* make copy of symbol */ #define compare_symbols _glp_mpl_compare_symbols int compare_symbols ( MPL *mpl, SYMBOL *sym1, /* not changed */ SYMBOL *sym2 /* not changed */ ); /* compare one symbol with another */ #define delete_symbol _glp_mpl_delete_symbol void delete_symbol ( MPL *mpl, SYMBOL *sym /* destroyed */ ); /* delete symbol */ #define format_symbol _glp_mpl_format_symbol char *format_symbol ( MPL *mpl, SYMBOL *sym /* not changed */ ); /* format symbol for displaying or printing */ #define concat_symbols _glp_mpl_concat_symbols SYMBOL *concat_symbols ( MPL *mpl, SYMBOL *sym1, /* destroyed */ SYMBOL *sym2 /* destroyed */ ); /* concatenate one symbol with another */ /**********************************************************************/ /* * * N-TUPLES * * */ /**********************************************************************/ struct TUPLE { /* component of n-tuple; the n-tuple itself is associated with its first component; (note that 0-tuple has no components) */ SYMBOL *sym; /* symbol, which the component refers to; cannot be NULL */ TUPLE *next; /* the next component of n-tuple */ }; #define create_tuple _glp_mpl_create_tuple TUPLE *create_tuple(MPL *mpl); /* create n-tuple */ #define expand_tuple _glp_mpl_expand_tuple TUPLE *expand_tuple ( MPL *mpl, TUPLE *tuple, /* destroyed */ SYMBOL *sym /* destroyed */ ); /* append symbol to n-tuple */ #define tuple_dimen _glp_mpl_tuple_dimen int tuple_dimen ( MPL *mpl, TUPLE *tuple /* not changed */ ); /* determine dimension of n-tuple */ #define copy_tuple _glp_mpl_copy_tuple TUPLE *copy_tuple ( MPL *mpl, TUPLE *tuple /* not changed */ ); /* make copy of n-tuple */ #define compare_tuples _glp_mpl_compare_tuples int compare_tuples ( MPL *mpl, TUPLE *tuple1, /* not changed */ TUPLE *tuple2 /* not changed */ ); /* compare one n-tuple with another */ #define build_subtuple _glp_mpl_build_subtuple TUPLE *build_subtuple ( MPL *mpl, TUPLE *tuple, /* not changed */ int dim ); /* build subtuple of given n-tuple */ #define delete_tuple _glp_mpl_delete_tuple void delete_tuple ( MPL *mpl, TUPLE *tuple /* destroyed */ ); /* delete n-tuple */ #define format_tuple _glp_mpl_format_tuple char *format_tuple ( MPL *mpl, int c, TUPLE *tuple /* not changed */ ); /* format n-tuple for displaying or printing */ /**********************************************************************/ /* * * ELEMENTAL SETS * * */ /**********************************************************************/ #if 2 + 2 == 5 struct ELEMSET /* see ARRAY */ { /* elemental set of n-tuples; formally it is a "value" assigned to members of model sets (like numbers and symbols, which are values assigned to members of model parameters); note that a simple model set is not an elemental set, it is 0-dimensional array, the only member of which (if it exists) is assigned an elemental set */ #endif #define create_elemset _glp_mpl_create_elemset ELEMSET *create_elemset(MPL *mpl, int dim); /* create elemental set */ #define find_tuple _glp_mpl_find_tuple MEMBER *find_tuple ( MPL *mpl, ELEMSET *set, /* not changed */ TUPLE *tuple /* not changed */ ); /* check if elemental set contains given n-tuple */ #define add_tuple _glp_mpl_add_tuple MEMBER *add_tuple ( MPL *mpl, ELEMSET *set, /* modified */ TUPLE *tuple /* destroyed */ ); /* add new n-tuple to elemental set */ #define check_then_add _glp_mpl_check_then_add MEMBER *check_then_add ( MPL *mpl, ELEMSET *set, /* modified */ TUPLE *tuple /* destroyed */ ); /* check and add new n-tuple to elemental set */ #define copy_elemset _glp_mpl_copy_elemset ELEMSET *copy_elemset ( MPL *mpl, ELEMSET *set /* not changed */ ); /* make copy of elemental set */ #define delete_elemset _glp_mpl_delete_elemset void delete_elemset ( MPL *mpl, ELEMSET *set /* destroyed */ ); /* delete elemental set */ #define arelset_size _glp_mpl_arelset_size int arelset_size(MPL *mpl, double t0, double tf, double dt); /* compute size of "arithmetic" elemental set */ #define arelset_member _glp_mpl_arelset_member double arelset_member(MPL *mpl, double t0, double tf, double dt, int j); /* compute member of "arithmetic" elemental set */ #define create_arelset _glp_mpl_create_arelset ELEMSET *create_arelset(MPL *mpl, double t0, double tf, double dt); /* create "arithmetic" elemental set */ #define set_union _glp_mpl_set_union ELEMSET *set_union ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ); /* union of two elemental sets */ #define set_diff _glp_mpl_set_diff ELEMSET *set_diff ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ); /* difference between two elemental sets */ #define set_symdiff _glp_mpl_set_symdiff ELEMSET *set_symdiff ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ); /* symmetric difference between two elemental sets */ #define set_inter _glp_mpl_set_inter ELEMSET *set_inter ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ); /* intersection of two elemental sets */ #define set_cross _glp_mpl_set_cross ELEMSET *set_cross ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ); /* cross (Cartesian) product of two elemental sets */ /**********************************************************************/ /* * * ELEMENTAL VARIABLES * * */ /**********************************************************************/ struct ELEMVAR { /* elemental variable; formally it is a "value" assigned to members of model variables (like numbers and symbols, which are values assigned to members of model parameters) */ int j; /* LP column number assigned to this elemental variable */ VARIABLE *var; /* model variable, which contains this elemental variable */ MEMBER *memb; /* array member, which is assigned this elemental variable */ double lbnd; /* lower bound */ double ubnd; /* upper bound */ double temp; /* working quantity used in operations on linear forms; normally it contains floating-point zero */ #if 1 /* 15/V-2010 */ int stat; double prim, dual; /* solution components provided by the solver */ #endif }; /**********************************************************************/ /* * * LINEAR FORMS * * */ /**********************************************************************/ struct FORMULA { /* term of linear form c * x, where c is a coefficient, x is an elemental variable; the linear form itself is the sum of terms and is associated with its first term; (note that the linear form may be empty that means the sum is equal to zero) */ double coef; /* coefficient at elemental variable or constant term */ ELEMVAR *var; /* reference to elemental variable; NULL means constant term */ FORMULA *next; /* the next term of linear form */ }; #define constant_term _glp_mpl_constant_term FORMULA *constant_term(MPL *mpl, double coef); /* create constant term */ #define single_variable _glp_mpl_single_variable FORMULA *single_variable ( MPL *mpl, ELEMVAR *var /* referenced */ ); /* create single variable */ #define copy_formula _glp_mpl_copy_formula FORMULA *copy_formula ( MPL *mpl, FORMULA *form /* not changed */ ); /* make copy of linear form */ #define delete_formula _glp_mpl_delete_formula void delete_formula ( MPL *mpl, FORMULA *form /* destroyed */ ); /* delete linear form */ #define linear_comb _glp_mpl_linear_comb FORMULA *linear_comb ( MPL *mpl, double a, FORMULA *fx, /* destroyed */ double b, FORMULA *fy /* destroyed */ ); /* linear combination of two linear forms */ #define remove_constant _glp_mpl_remove_constant FORMULA *remove_constant ( MPL *mpl, FORMULA *form, /* destroyed */ double *coef /* modified */ ); /* remove constant term from linear form */ #define reduce_terms _glp_mpl_reduce_terms FORMULA *reduce_terms ( MPL *mpl, FORMULA *form /* destroyed */ ); /* reduce identical terms in linear form */ /**********************************************************************/ /* * * ELEMENTAL CONSTRAINTS * * */ /**********************************************************************/ struct ELEMCON { /* elemental constraint; formally it is a "value" assigned to members of model constraints (like numbers or symbols, which are values assigned to members of model parameters) */ int i; /* LP row number assigned to this elemental constraint */ CONSTRAINT *con; /* model constraint, which contains this elemental constraint */ MEMBER *memb; /* array member, which is assigned this elemental constraint */ FORMULA *form; /* linear form */ double lbnd; /* lower bound */ double ubnd; /* upper bound */ #if 1 /* 15/V-2010 */ int stat; double prim, dual; /* solution components provided by the solver */ #endif }; /**********************************************************************/ /* * * GENERIC VALUES * * */ /**********************************************************************/ union VALUE { /* generic value, which can be assigned to object member or be a result of evaluation of expression */ /* indicator that specifies the particular type of generic value is stored in the corresponding array or pseudo-code descriptor and can be one of the following: A_NONE - no value A_NUMERIC - floating-point number A_SYMBOLIC - symbol A_LOGICAL - logical value A_TUPLE - n-tuple A_ELEMSET - elemental set A_ELEMVAR - elemental variable A_FORMULA - linear form A_ELEMCON - elemental constraint */ void *none; /* null */ double num; /* value */ SYMBOL *sym; /* value */ int bit; /* value */ TUPLE *tuple; /* value */ ELEMSET *set; /* value */ ELEMVAR *var; /* reference */ FORMULA *form; /* value */ ELEMCON *con; /* reference */ }; #define delete_value _glp_mpl_delete_value void delete_value ( MPL *mpl, int type, VALUE *value /* content destroyed */ ); /* delete generic value */ /**********************************************************************/ /* * * SYMBOLICALLY INDEXED ARRAYS * * */ /**********************************************************************/ struct ARRAY { /* multi-dimensional array, a set of members indexed over simple or compound sets of symbols; arrays are used to represent the contents of model objects (i.e. sets, parameters, variables, constraints, and objectives); arrays also are used as "values" that are assigned to members of set objects, in which case the array itself represents an elemental set */ int type; /* type of generic values assigned to the array members: A_NONE - none (members have no assigned values) A_NUMERIC - floating-point numbers A_SYMBOLIC - symbols A_ELEMSET - elemental sets A_ELEMVAR - elemental variables A_ELEMCON - elemental constraints */ int dim; /* dimension of the array that determines number of components in n-tuples for all members of the array, dim >= 0; dim = 0 means the array is 0-dimensional */ int size; /* size of the array, i.e. number of its members */ MEMBER *head; /* the first array member; NULL means the array is empty */ MEMBER *tail; /* the last array member; NULL means the array is empty */ AVL *tree; /* the search tree intended to find array members for logarithmic time; NULL means the search tree doesn't exist */ ARRAY *prev; /* the previous array in the translator database */ ARRAY *next; /* the next array in the translator database */ }; struct MEMBER { /* array member */ TUPLE *tuple; /* n-tuple, which identifies the member; number of its components is the same for all members within the array and determined by the array dimension; duplicate members are not allowed */ MEMBER *next; /* the next array member */ VALUE value; /* generic value assigned to the member */ }; #define create_array _glp_mpl_create_array ARRAY *create_array(MPL *mpl, int type, int dim); /* create array */ #define find_member _glp_mpl_find_member MEMBER *find_member ( MPL *mpl, ARRAY *array, /* not changed */ TUPLE *tuple /* not changed */ ); /* find array member with given n-tuple */ #define add_member _glp_mpl_add_member MEMBER *add_member ( MPL *mpl, ARRAY *array, /* modified */ TUPLE *tuple /* destroyed */ ); /* add new member to array */ #define delete_array _glp_mpl_delete_array void delete_array ( MPL *mpl, ARRAY *array /* destroyed */ ); /* delete array */ /**********************************************************************/ /* * * DOMAINS AND DUMMY INDICES * * */ /**********************************************************************/ struct DOMAIN { /* domain (a simple or compound set); syntactically domain looks like '{ i in I, (j,k) in S, t in T : }'; domains are used to define sets, over which model objects are indexed, and also as constituents of iterated operators */ DOMAIN_BLOCK *list; /* linked list of domain blocks (in the example above such blocks are 'i in I', '(j,k) in S', and 't in T'); this list cannot be empty */ CODE *code; /* pseudo-code for computing the logical predicate, which follows the colon; NULL means no predicate is specified */ }; struct DOMAIN_BLOCK { /* domain block; syntactically domain blocks look like 'i in I', '(j,k) in S', and 't in T' in the example above (in the sequel sets like I, S, and T are called basic sets) */ DOMAIN_SLOT *list; /* linked list of domain slots (i.e. indexing positions); number of slots in this list is the same as dimension of n-tuples in the basic set; this list cannot be empty */ CODE *code; /* pseudo-code for computing basic set; cannot be NULL */ TUPLE *backup; /* if this n-tuple is not empty, current values of dummy indices in the domain block are the same as components of this n-tuple (note that this n-tuple may have larger dimension than number of dummy indices in this block, in which case extra components are ignored); this n-tuple is used to restore former values of dummy indices, if they were changed due to recursive calls to the domain block */ DOMAIN_BLOCK *next; /* the next block in the same domain */ }; struct DOMAIN_SLOT { /* domain slot; it specifies an individual indexing position and defines the corresponding dummy index */ char *name; /* symbolic name of the dummy index; null pointer means the dummy index is not explicitly specified */ CODE *code; /* pseudo-code for computing symbolic value, at which the dummy index is bound; NULL means the dummy index is free within the domain scope */ SYMBOL *value; /* current value assigned to the dummy index; NULL means no value is assigned at the moment */ CODE *list; /* linked list of pseudo-codes with operation O_INDEX referring to this slot; this linked list is used to invalidate resultant values of the operation, which depend on this dummy index */ DOMAIN_SLOT *next; /* the next slot in the same domain block */ }; #define assign_dummy_index _glp_mpl_assign_dummy_index void assign_dummy_index ( MPL *mpl, DOMAIN_SLOT *slot, /* modified */ SYMBOL *value /* not changed */ ); /* assign new value to dummy index */ #define update_dummy_indices _glp_mpl_update_dummy_indices void update_dummy_indices ( MPL *mpl, DOMAIN_BLOCK *block /* not changed */ ); /* update current values of dummy indices */ #define enter_domain_block _glp_mpl_enter_domain_block int enter_domain_block ( MPL *mpl, DOMAIN_BLOCK *block, /* not changed */ TUPLE *tuple, /* not changed */ void *info, void (*func)(MPL *mpl, void *info) ); /* enter domain block */ #define eval_within_domain _glp_mpl_eval_within_domain int eval_within_domain ( MPL *mpl, DOMAIN *domain, /* not changed */ TUPLE *tuple, /* not changed */ void *info, void (*func)(MPL *mpl, void *info) ); /* perform evaluation within domain scope */ #define loop_within_domain _glp_mpl_loop_within_domain void loop_within_domain ( MPL *mpl, DOMAIN *domain, /* not changed */ void *info, int (*func)(MPL *mpl, void *info) ); /* perform iterations within domain scope */ #define out_of_domain _glp_mpl_out_of_domain void out_of_domain ( MPL *mpl, char *name, /* not changed */ TUPLE *tuple /* not changed */ ); /* raise domain exception */ #define get_domain_tuple _glp_mpl_get_domain_tuple TUPLE *get_domain_tuple ( MPL *mpl, DOMAIN *domain /* not changed */ ); /* obtain current n-tuple from domain */ #define clean_domain _glp_mpl_clean_domain void clean_domain(MPL *mpl, DOMAIN *domain); /* clean domain */ /**********************************************************************/ /* * * MODEL SETS * * */ /**********************************************************************/ struct SET { /* model set */ char *name; /* symbolic name; cannot be NULL */ char *alias; /* alias; NULL means alias is not specified */ int dim; /* aka arity */ /* dimension (number of subscripts); dim = 0 means 0-dimensional (unsubscripted) set, dim > 0 means set of sets */ DOMAIN *domain; /* subscript domain; NULL for 0-dimensional set */ int dimen; /* dimension of n-tuples, which members of this set consist of (note that the model set itself is an array of elemental sets, which are its members; so, don't confuse this dimension with dimension of the model set); always non-zero */ WITHIN *within; /* list of supersets, which restrict each member of the set to be in every superset from this list; this list can be empty */ CODE *assign; /* pseudo-code for computing assigned value; can be NULL */ CODE *option; /* pseudo-code for computing default value; can be NULL */ GADGET *gadget; /* plain set used to initialize the array of sets; can be NULL */ int data; /* data status flag: 0 - no data are provided in the data section 1 - data are provided, but not checked yet 2 - data are provided and have been checked */ ARRAY *array; /* array of members, which are assigned elemental sets */ }; struct WITHIN { /* restricting superset list entry */ CODE *code; /* pseudo-code for computing the superset; cannot be NULL */ WITHIN *next; /* the next entry for the same set or parameter */ }; struct GADGET { /* plain set used to initialize the array of sets with data */ SET *set; /* pointer to plain set; cannot be NULL */ int ind[20]; /* ind[dim+dimen]; */ /* permutation of integers 1, 2, ..., dim+dimen */ }; #define check_elem_set _glp_mpl_check_elem_set void check_elem_set ( MPL *mpl, SET *set, /* not changed */ TUPLE *tuple, /* not changed */ ELEMSET *refer /* not changed */ ); /* check elemental set assigned to set member */ #define take_member_set _glp_mpl_take_member_set ELEMSET *take_member_set /* returns reference, not value */ ( MPL *mpl, SET *set, /* not changed */ TUPLE *tuple /* not changed */ ); /* obtain elemental set assigned to set member */ #define eval_member_set _glp_mpl_eval_member_set ELEMSET *eval_member_set /* returns reference, not value */ ( MPL *mpl, SET *set, /* not changed */ TUPLE *tuple /* not changed */ ); /* evaluate elemental set assigned to set member */ #define eval_whole_set _glp_mpl_eval_whole_set void eval_whole_set(MPL *mpl, SET *set); /* evaluate model set over entire domain */ #define clean_set _glp_mpl_clean_set void clean_set(MPL *mpl, SET *set); /* clean model set */ /**********************************************************************/ /* * * MODEL PARAMETERS * * */ /**********************************************************************/ struct PARAMETER { /* model parameter */ char *name; /* symbolic name; cannot be NULL */ char *alias; /* alias; NULL means alias is not specified */ int dim; /* aka arity */ /* dimension (number of subscripts); dim = 0 means 0-dimensional (unsubscripted) parameter */ DOMAIN *domain; /* subscript domain; NULL for 0-dimensional parameter */ int type; /* parameter type: A_NUMERIC - numeric A_INTEGER - integer A_BINARY - binary A_SYMBOLIC - symbolic */ CONDITION *cond; /* list of conditions, which restrict each parameter member to satisfy to every condition from this list; this list is used only for numeric parameters and can be empty */ WITHIN *in; /* list of supersets, which restrict each parameter member to be in every superset from this list; this list is used only for symbolic parameters and can be empty */ CODE *assign; /* pseudo-code for computing assigned value; can be NULL */ CODE *option; /* pseudo-code for computing default value; can be NULL */ int data; /* data status flag: 0 - no data are provided in the data section 1 - data are provided, but not checked yet 2 - data are provided and have been checked */ SYMBOL *defval; /* default value provided in the data section; can be NULL */ ARRAY *array; /* array of members, which are assigned numbers or symbols */ }; struct CONDITION { /* restricting condition list entry */ int rho; /* flag that specifies the form of the condition: O_LT - less than O_LE - less than or equal to O_EQ - equal to O_GE - greater than or equal to O_GT - greater than O_NE - not equal to */ CODE *code; /* pseudo-code for computing the reference value */ CONDITION *next; /* the next entry for the same parameter */ }; #define check_value_num _glp_mpl_check_value_num void check_value_num ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple, /* not changed */ double value ); /* check numeric value assigned to parameter member */ #define take_member_num _glp_mpl_take_member_num double take_member_num ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ); /* obtain numeric value assigned to parameter member */ #define eval_member_num _glp_mpl_eval_member_num double eval_member_num ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ); /* evaluate numeric value assigned to parameter member */ #define check_value_sym _glp_mpl_check_value_sym void check_value_sym ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple, /* not changed */ SYMBOL *value /* not changed */ ); /* check symbolic value assigned to parameter member */ #define take_member_sym _glp_mpl_take_member_sym SYMBOL *take_member_sym /* returns value, not reference */ ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ); /* obtain symbolic value assigned to parameter member */ #define eval_member_sym _glp_mpl_eval_member_sym SYMBOL *eval_member_sym /* returns value, not reference */ ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ); /* evaluate symbolic value assigned to parameter member */ #define eval_whole_par _glp_mpl_eval_whole_par void eval_whole_par(MPL *mpl, PARAMETER *par); /* evaluate model parameter over entire domain */ #define clean_parameter _glp_mpl_clean_parameter void clean_parameter(MPL *mpl, PARAMETER *par); /* clean model parameter */ /**********************************************************************/ /* * * MODEL VARIABLES * * */ /**********************************************************************/ struct VARIABLE { /* model variable */ char *name; /* symbolic name; cannot be NULL */ char *alias; /* alias; NULL means alias is not specified */ int dim; /* aka arity */ /* dimension (number of subscripts); dim = 0 means 0-dimensional (unsubscripted) variable */ DOMAIN *domain; /* subscript domain; NULL for 0-dimensional variable */ int type; /* variable type: A_NUMERIC - continuous A_INTEGER - integer A_BINARY - binary */ CODE *lbnd; /* pseudo-code for computing lower bound; NULL means lower bound is not specified */ CODE *ubnd; /* pseudo-code for computing upper bound; NULL means upper bound is not specified */ /* if both the pointers lbnd and ubnd refer to the same code, the variable is fixed at the corresponding value */ ARRAY *array; /* array of members, which are assigned elemental variables */ }; #define take_member_var _glp_mpl_take_member_var ELEMVAR *take_member_var /* returns reference */ ( MPL *mpl, VARIABLE *var, /* not changed */ TUPLE *tuple /* not changed */ ); /* obtain reference to elemental variable */ #define eval_member_var _glp_mpl_eval_member_var ELEMVAR *eval_member_var /* returns reference */ ( MPL *mpl, VARIABLE *var, /* not changed */ TUPLE *tuple /* not changed */ ); /* evaluate reference to elemental variable */ #define eval_whole_var _glp_mpl_eval_whole_var void eval_whole_var(MPL *mpl, VARIABLE *var); /* evaluate model variable over entire domain */ #define clean_variable _glp_mpl_clean_variable void clean_variable(MPL *mpl, VARIABLE *var); /* clean model variable */ /**********************************************************************/ /* * * MODEL CONSTRAINTS AND OBJECTIVES * * */ /**********************************************************************/ struct CONSTRAINT { /* model constraint or objective */ char *name; /* symbolic name; cannot be NULL */ char *alias; /* alias; NULL means alias is not specified */ int dim; /* aka arity */ /* dimension (number of subscripts); dim = 0 means 0-dimensional (unsubscripted) constraint */ DOMAIN *domain; /* subscript domain; NULL for 0-dimensional constraint */ int type; /* constraint type: A_CONSTRAINT - constraint A_MINIMIZE - objective (minimization) A_MAXIMIZE - objective (maximization) */ CODE *code; /* pseudo-code for computing main linear form; cannot be NULL */ CODE *lbnd; /* pseudo-code for computing lower bound; NULL means lower bound is not specified */ CODE *ubnd; /* pseudo-code for computing upper bound; NULL means upper bound is not specified */ /* if both the pointers lbnd and ubnd refer to the same code, the constraint has the form of equation */ ARRAY *array; /* array of members, which are assigned elemental constraints */ }; #define take_member_con _glp_mpl_take_member_con ELEMCON *take_member_con /* returns reference */ ( MPL *mpl, CONSTRAINT *con, /* not changed */ TUPLE *tuple /* not changed */ ); /* obtain reference to elemental constraint */ #define eval_member_con _glp_mpl_eval_member_con ELEMCON *eval_member_con /* returns reference */ ( MPL *mpl, CONSTRAINT *con, /* not changed */ TUPLE *tuple /* not changed */ ); /* evaluate reference to elemental constraint */ #define eval_whole_con _glp_mpl_eval_whole_con void eval_whole_con(MPL *mpl, CONSTRAINT *con); /* evaluate model constraint over entire domain */ #define clean_constraint _glp_mpl_clean_constraint void clean_constraint(MPL *mpl, CONSTRAINT *con); /* clean model constraint */ /**********************************************************************/ /* * * DATA TABLES * * */ /**********************************************************************/ struct TABLE { /* data table */ char *name; /* symbolic name; cannot be NULL */ char *alias; /* alias; NULL means alias is not specified */ int type; /* table type: A_INPUT - input table A_OUTPUT - output table */ TABARG *arg; /* argument list; cannot be empty */ union { struct { SET *set; /* input set; NULL means the set is not specified */ TABFLD *fld; /* field list; cannot be empty */ TABIN *list; /* input list; can be empty */ } in; struct { DOMAIN *domain; /* subscript domain; cannot be NULL */ TABOUT *list; /* output list; cannot be empty */ } out; } u; }; struct TABARG { /* table argument list entry */ CODE *code; /* pseudo-code for computing the argument */ TABARG *next; /* next entry for the same table */ }; struct TABFLD { /* table field list entry */ char *name; /* field name; cannot be NULL */ TABFLD *next; /* next entry for the same table */ }; struct TABIN { /* table input list entry */ PARAMETER *par; /* parameter to be read; cannot be NULL */ char *name; /* column name; cannot be NULL */ TABIN *next; /* next entry for the same table */ }; struct TABOUT { /* table output list entry */ CODE *code; /* pseudo-code for computing the value to be written */ char *name; /* column name; cannot be NULL */ TABOUT *next; /* next entry for the same table */ }; struct TABDCA { /* table driver communication area */ int id; /* driver identifier (set by mpl_tab_drv_open) */ void *link; /* driver link pointer (set by mpl_tab_drv_open) */ int na; /* number of arguments */ char **arg; /* char *arg[1+ns]; */ /* arg[k], 1 <= k <= ns, is pointer to k-th argument */ int nf; /* number of fields */ char **name; /* char *name[1+nc]; */ /* name[k], 1 <= k <= nc, is name of k-th field */ int *type; /* int type[1+nc]; */ /* type[k], 1 <= k <= nc, is type of k-th field: '?' - value not assigned 'N' - number 'S' - character string */ double *num; /* double num[1+nc]; */ /* num[k], 1 <= k <= nc, is numeric value of k-th field */ char **str; /* str[k], 1 <= k <= nc, is string value of k-th field */ }; #define mpl_tab_num_args _glp_mpl_tab_num_args int mpl_tab_num_args(TABDCA *dca); #define mpl_tab_get_arg _glp_mpl_tab_get_arg const char *mpl_tab_get_arg(TABDCA *dca, int k); #define mpl_tab_num_flds _glp_mpl_tab_num_flds int mpl_tab_num_flds(TABDCA *dca); #define mpl_tab_get_name _glp_mpl_tab_get_name const char *mpl_tab_get_name(TABDCA *dca, int k); #define mpl_tab_get_type _glp_mpl_tab_get_type int mpl_tab_get_type(TABDCA *dca, int k); #define mpl_tab_get_num _glp_mpl_tab_get_num double mpl_tab_get_num(TABDCA *dca, int k); #define mpl_tab_get_str _glp_mpl_tab_get_str const char *mpl_tab_get_str(TABDCA *dca, int k); #define mpl_tab_set_num _glp_mpl_tab_set_num void mpl_tab_set_num(TABDCA *dca, int k, double num); #define mpl_tab_set_str _glp_mpl_tab_set_str void mpl_tab_set_str(TABDCA *dca, int k, const char *str); #define mpl_tab_drv_open _glp_mpl_tab_drv_open void mpl_tab_drv_open(MPL *mpl, int mode); #define mpl_tab_drv_read _glp_mpl_tab_drv_read int mpl_tab_drv_read(MPL *mpl); #define mpl_tab_drv_write _glp_mpl_tab_drv_write void mpl_tab_drv_write(MPL *mpl); #define mpl_tab_drv_close _glp_mpl_tab_drv_close void mpl_tab_drv_close(MPL *mpl); /**********************************************************************/ /* * * PSEUDO-CODE * * */ /**********************************************************************/ union OPERANDS { /* operands that participate in pseudo-code operation (choice of particular operands depends on the operation code) */ /*--------------------------------------------------------------*/ double num; /* O_NUMBER */ /* floaing-point number to be taken */ /*--------------------------------------------------------------*/ char *str; /* O_STRING */ /* character string to be taken */ /*--------------------------------------------------------------*/ struct /* O_INDEX */ { DOMAIN_SLOT *slot; /* domain slot, which contains dummy index to be taken */ CODE *next; /* the next pseudo-code with op = O_INDEX, which refers to the same slot as this one; pointer to the beginning of this list is stored in the corresponding domain slot */ } index; /*--------------------------------------------------------------*/ struct /* O_MEMNUM, O_MEMSYM */ { PARAMETER *par; /* model parameter, which contains member to be taken */ ARG_LIST *list; /* list of subscripts; NULL for 0-dimensional parameter */ } par; /*--------------------------------------------------------------*/ struct /* O_MEMSET */ { SET *set; /* model set, which contains member to be taken */ ARG_LIST *list; /* list of subscripts; NULL for 0-dimensional set */ } set; /*--------------------------------------------------------------*/ struct /* O_MEMVAR */ { VARIABLE *var; /* model variable, which contains member to be taken */ ARG_LIST *list; /* list of subscripts; NULL for 0-dimensional variable */ #if 1 /* 15/V-2010 */ int suff; /* suffix specified: */ #define DOT_NONE 0x00 /* none (means variable itself) */ #define DOT_LB 0x01 /* .lb (lower bound) */ #define DOT_UB 0x02 /* .ub (upper bound) */ #define DOT_STATUS 0x03 /* .status (status) */ #define DOT_VAL 0x04 /* .val (primal value) */ #define DOT_DUAL 0x05 /* .dual (dual value) */ #endif } var; #if 1 /* 15/V-2010 */ /*--------------------------------------------------------------*/ struct /* O_MEMCON */ { CONSTRAINT *con; /* model constraint, which contains member to be taken */ ARG_LIST *list; /* list of subscripys; NULL for 0-dimensional constraint */ int suff; /* suffix specified (see O_MEMVAR above) */ } con; #endif /*--------------------------------------------------------------*/ ARG_LIST *list; /* O_TUPLE, O_MAKE, n-ary operations */ /* list of operands */ /*--------------------------------------------------------------*/ DOMAIN_BLOCK *slice; /* O_SLICE */ /* domain block, which specifies slice (i.e. n-tuple that contains free dummy indices); this operation is never evaluated */ /*--------------------------------------------------------------*/ struct /* unary, binary, ternary operations */ { CODE *x; /* pseudo-code for computing first operand */ CODE *y; /* pseudo-code for computing second operand */ CODE *z; /* pseudo-code for computing third operand */ } arg; /*--------------------------------------------------------------*/ struct /* iterated operations */ { DOMAIN *domain; /* domain, over which the operation is performed */ CODE *x; /* pseudo-code for computing "integrand" */ } loop; /*--------------------------------------------------------------*/ }; struct ARG_LIST { /* operands list entry */ CODE *x; /* pseudo-code for computing operand */ ARG_LIST *next; /* the next operand of the same operation */ }; struct CODE { /* pseudo-code (internal form of expressions) */ int op; /* operation code: */ #define O_NUMBER 301 /* take floating-point number */ #define O_STRING 302 /* take character string */ #define O_INDEX 303 /* take dummy index */ #define O_MEMNUM 304 /* take member of numeric parameter */ #define O_MEMSYM 305 /* take member of symbolic parameter */ #define O_MEMSET 306 /* take member of set */ #define O_MEMVAR 307 /* take member of variable */ #define O_MEMCON 308 /* take member of constraint */ #define O_TUPLE 309 /* make n-tuple */ #define O_MAKE 310 /* make elemental set of n-tuples */ #define O_SLICE 311 /* define domain block (dummy op) */ /* 0-ary operations --------------------*/ #define O_IRAND224 312 /* pseudo-random in [0, 2^24-1] */ #define O_UNIFORM01 313 /* pseudo-random in [0, 1) */ #define O_NORMAL01 314 /* gaussian random, mu = 0, sigma = 1 */ #define O_GMTIME 315 /* current calendar time (UTC) */ /* unary operations --------------------*/ #define O_CVTNUM 316 /* conversion to numeric */ #define O_CVTSYM 317 /* conversion to symbolic */ #define O_CVTLOG 318 /* conversion to logical */ #define O_CVTTUP 319 /* conversion to 1-tuple */ #define O_CVTLFM 320 /* conversion to linear form */ #define O_PLUS 321 /* unary plus */ #define O_MINUS 322 /* unary minus */ #define O_NOT 323 /* negation (logical "not") */ #define O_ABS 324 /* absolute value */ #define O_CEIL 325 /* round upward ("ceiling of x") */ #define O_FLOOR 326 /* round downward ("floor of x") */ #define O_EXP 327 /* base-e exponential */ #define O_LOG 328 /* natural logarithm */ #define O_LOG10 329 /* common (decimal) logarithm */ #define O_SQRT 330 /* square root */ #define O_SIN 331 /* trigonometric sine */ #define O_COS 332 /* trigonometric cosine */ #define O_ATAN 333 /* trigonometric arctangent */ #define O_ROUND 334 /* round to nearest integer */ #define O_TRUNC 335 /* truncate to nearest integer */ #define O_CARD 336 /* cardinality of set */ #define O_LENGTH 337 /* length of symbolic value */ /* binary operations -------------------*/ #define O_ADD 338 /* addition */ #define O_SUB 339 /* subtraction */ #define O_LESS 340 /* non-negative subtraction */ #define O_MUL 341 /* multiplication */ #define O_DIV 342 /* division */ #define O_IDIV 343 /* quotient of exact division */ #define O_MOD 344 /* remainder of exact division */ #define O_POWER 345 /* exponentiation (raise to power) */ #define O_ATAN2 346 /* trigonometric arctangent */ #define O_ROUND2 347 /* round to n fractional digits */ #define O_TRUNC2 348 /* truncate to n fractional digits */ #define O_UNIFORM 349 /* pseudo-random in [a, b) */ #define O_NORMAL 350 /* gaussian random, given mu and sigma */ #define O_CONCAT 351 /* concatenation */ #define O_LT 352 /* comparison on 'less than' */ #define O_LE 353 /* comparison on 'not greater than' */ #define O_EQ 354 /* comparison on 'equal to' */ #define O_GE 355 /* comparison on 'not less than' */ #define O_GT 356 /* comparison on 'greater than' */ #define O_NE 357 /* comparison on 'not equal to' */ #define O_AND 358 /* conjunction (logical "and") */ #define O_OR 359 /* disjunction (logical "or") */ #define O_UNION 360 /* union */ #define O_DIFF 361 /* difference */ #define O_SYMDIFF 362 /* symmetric difference */ #define O_INTER 363 /* intersection */ #define O_CROSS 364 /* cross (Cartesian) product */ #define O_IN 365 /* test on 'x in Y' */ #define O_NOTIN 366 /* test on 'x not in Y' */ #define O_WITHIN 367 /* test on 'X within Y' */ #define O_NOTWITHIN 368 /* test on 'X not within Y' */ #define O_SUBSTR 369 /* substring */ #define O_STR2TIME 370 /* convert string to time */ #define O_TIME2STR 371 /* convert time to string */ /* ternary operations ------------------*/ #define O_DOTS 372 /* build "arithmetic" set */ #define O_FORK 373 /* if-then-else */ #define O_SUBSTR3 374 /* substring */ /* n-ary operations --------------------*/ #define O_MIN 375 /* minimal value (n-ary) */ #define O_MAX 376 /* maximal value (n-ary) */ /* iterated operations -----------------*/ #define O_SUM 377 /* summation */ #define O_PROD 378 /* multiplication */ #define O_MINIMUM 379 /* minimum */ #define O_MAXIMUM 380 /* maximum */ #define O_FORALL 381 /* conjunction (A-quantification) */ #define O_EXISTS 382 /* disjunction (E-quantification) */ #define O_SETOF 383 /* compute elemental set */ #define O_BUILD 384 /* build elemental set */ OPERANDS arg; /* operands that participate in the operation */ int type; /* type of the resultant value: A_NUMERIC - numeric A_SYMBOLIC - symbolic A_LOGICAL - logical A_TUPLE - n-tuple A_ELEMSET - elemental set A_FORMULA - linear form */ int dim; /* dimension of the resultant value; for A_TUPLE and A_ELEMSET it is the dimension of the corresponding n-tuple(s) and cannot be zero; for other resultant types it is always zero */ CODE *up; /* parent pseudo-code, which refers to this pseudo-code as to its operand; NULL means this pseudo-code has no parent and defines an expression, which is not contained in another expression */ int vflag; /* volatile flag; being set this flag means that this operation has a side effect; for primary expressions this flag is set directly by corresponding parsing routines (for example, if primary expression is a reference to a function that generates pseudo-random numbers); in other cases this flag is inherited from operands */ int valid; /* if this flag is set, the resultant value, which is a temporary result of evaluating this operation on particular values of operands, is valid; if this flag is clear, the resultant value doesn't exist and therefore not valid; having been evaluated the resultant value is stored here and not destroyed until the dummy indices, which this value depends on, have been changed (and if it doesn't depend on dummy indices at all, it is never destroyed); thus, if the resultant value is valid, evaluating routine can immediately take its copy not computing the result from scratch; this mechanism is similar to moving invariants out of loops and allows improving efficiency at the expense of some extra memory needed to keep temporary results */ /* however, if the volatile flag (see above) is set, even if the resultant value is valid, evaluating routine computes it as if it were not valid, i.e. caching is not used in this case */ VALUE value; /* resultant value in generic format */ }; #define eval_numeric _glp_mpl_eval_numeric double eval_numeric(MPL *mpl, CODE *code); /* evaluate pseudo-code to determine numeric value */ #define eval_symbolic _glp_mpl_eval_symbolic SYMBOL *eval_symbolic(MPL *mpl, CODE *code); /* evaluate pseudo-code to determine symbolic value */ #define eval_logical _glp_mpl_eval_logical int eval_logical(MPL *mpl, CODE *code); /* evaluate pseudo-code to determine logical value */ #define eval_tuple _glp_mpl_eval_tuple TUPLE *eval_tuple(MPL *mpl, CODE *code); /* evaluate pseudo-code to construct n-tuple */ #define eval_elemset _glp_mpl_eval_elemset ELEMSET *eval_elemset(MPL *mpl, CODE *code); /* evaluate pseudo-code to construct elemental set */ #define is_member _glp_mpl_is_member int is_member(MPL *mpl, CODE *code, TUPLE *tuple); /* check if n-tuple is in set specified by pseudo-code */ #define eval_formula _glp_mpl_eval_formula FORMULA *eval_formula(MPL *mpl, CODE *code); /* evaluate pseudo-code to construct linear form */ #define clean_code _glp_mpl_clean_code void clean_code(MPL *mpl, CODE *code); /* clean pseudo-code */ /**********************************************************************/ /* * * MODEL STATEMENTS * * */ /**********************************************************************/ struct CHECK { /* check statement */ DOMAIN *domain; /* subscript domain; NULL means domain is not used */ CODE *code; /* code for computing the predicate to be checked */ }; struct DISPLAY { /* display statement */ DOMAIN *domain; /* subscript domain; NULL means domain is not used */ DISPLAY1 *list; /* display list; cannot be empty */ }; struct DISPLAY1 { /* display list entry */ int type; /* item type: A_INDEX - dummy index A_SET - model set A_PARAMETER - model parameter A_VARIABLE - model variable A_CONSTRAINT - model constraint/objective A_EXPRESSION - expression */ union { DOMAIN_SLOT *slot; SET *set; PARAMETER *par; VARIABLE *var; CONSTRAINT *con; CODE *code; } u; /* item to be displayed */ #if 0 /* 15/V-2010 */ ARG_LIST *list; /* optional subscript list (for constraint/objective only) */ #endif DISPLAY1 *next; /* the next entry for the same statement */ }; struct PRINTF { /* printf statement */ DOMAIN *domain; /* subscript domain; NULL means domain is not used */ CODE *fmt; /* pseudo-code for computing format string */ PRINTF1 *list; /* printf list; can be empty */ CODE *fname; /* pseudo-code for computing filename to redirect the output; NULL means the output goes to stdout */ int app; /* if this flag is set, the output is appended */ }; struct PRINTF1 { /* printf list entry */ CODE *code; /* pseudo-code for computing value to be printed */ PRINTF1 *next; /* the next entry for the same statement */ }; struct FOR { /* for statement */ DOMAIN *domain; /* subscript domain; cannot be NULL */ STATEMENT *list; /* linked list of model statements within this for statement in the original order */ }; struct STATEMENT { /* model statement */ int line; /* number of source text line, where statement begins */ int type; /* statement type: A_SET - set statement A_PARAMETER - parameter statement A_VARIABLE - variable statement A_CONSTRAINT - constraint/objective statement A_TABLE - table statement A_SOLVE - solve statement A_CHECK - check statement A_DISPLAY - display statement A_PRINTF - printf statement A_FOR - for statement */ union { SET *set; PARAMETER *par; VARIABLE *var; CONSTRAINT *con; TABLE *tab; void *slv; /* currently not used (set to NULL) */ CHECK *chk; DISPLAY *dpy; PRINTF *prt; FOR *fur; } u; /* specific part of statement */ STATEMENT *next; /* the next statement; in this list statements follow in the same order as they appear in the model section */ }; #define execute_table _glp_mpl_execute_table void execute_table(MPL *mpl, TABLE *tab); /* execute table statement */ #define free_dca _glp_mpl_free_dca void free_dca(MPL *mpl); /* free table driver communucation area */ #define clean_table _glp_mpl_clean_table void clean_table(MPL *mpl, TABLE *tab); /* clean table statement */ #define execute_check _glp_mpl_execute_check void execute_check(MPL *mpl, CHECK *chk); /* execute check statement */ #define clean_check _glp_mpl_clean_check void clean_check(MPL *mpl, CHECK *chk); /* clean check statement */ #define execute_display _glp_mpl_execute_display void execute_display(MPL *mpl, DISPLAY *dpy); /* execute display statement */ #define clean_display _glp_mpl_clean_display void clean_display(MPL *mpl, DISPLAY *dpy); /* clean display statement */ #define execute_printf _glp_mpl_execute_printf void execute_printf(MPL *mpl, PRINTF *prt); /* execute printf statement */ #define clean_printf _glp_mpl_clean_printf void clean_printf(MPL *mpl, PRINTF *prt); /* clean printf statement */ #define execute_for _glp_mpl_execute_for void execute_for(MPL *mpl, FOR *fur); /* execute for statement */ #define clean_for _glp_mpl_clean_for void clean_for(MPL *mpl, FOR *fur); /* clean for statement */ #define execute_statement _glp_mpl_execute_statement void execute_statement(MPL *mpl, STATEMENT *stmt); /* execute specified model statement */ #define clean_statement _glp_mpl_clean_statement void clean_statement(MPL *mpl, STATEMENT *stmt); /* clean specified model statement */ /**********************************************************************/ /* * * GENERATING AND POSTSOLVING MODEL * * */ /**********************************************************************/ #define alloc_content _glp_mpl_alloc_content void alloc_content(MPL *mpl); /* allocate content arrays for all model objects */ #define generate_model _glp_mpl_generate_model void generate_model(MPL *mpl); /* generate model */ #define build_problem _glp_mpl_build_problem void build_problem(MPL *mpl); /* build problem instance */ #define postsolve_model _glp_mpl_postsolve_model void postsolve_model(MPL *mpl); /* postsolve model */ #define clean_model _glp_mpl_clean_model void clean_model(MPL *mpl); /* clean model content */ /**********************************************************************/ /* * * INPUT/OUTPUT * * */ /**********************************************************************/ #define open_input _glp_mpl_open_input void open_input(MPL *mpl, char *file); /* open input text file */ #define read_char _glp_mpl_read_char int read_char(MPL *mpl); /* read next character from input text file */ #define close_input _glp_mpl_close_input void close_input(MPL *mpl); /* close input text file */ #define open_output _glp_mpl_open_output void open_output(MPL *mpl, char *file); /* open output text file */ #define write_char _glp_mpl_write_char void write_char(MPL *mpl, int c); /* write next character to output text file */ #define write_text _glp_mpl_write_text void write_text(MPL *mpl, char *fmt, ...); /* format and write text to output text file */ #define flush_output _glp_mpl_flush_output void flush_output(MPL *mpl); /* finalize writing data to output text file */ /**********************************************************************/ /* * * SOLVER INTERFACE * * */ /**********************************************************************/ #define MPL_FR 401 /* free (unbounded) */ #define MPL_LO 402 /* lower bound */ #define MPL_UP 403 /* upper bound */ #define MPL_DB 404 /* both lower and upper bounds */ #define MPL_FX 405 /* fixed */ #define MPL_ST 411 /* constraint */ #define MPL_MIN 412 /* objective (minimization) */ #define MPL_MAX 413 /* objective (maximization) */ #define MPL_NUM 421 /* continuous */ #define MPL_INT 422 /* integer */ #define MPL_BIN 423 /* binary */ #define error _glp_mpl_error void error(MPL *mpl, char *fmt, ...); /* print error message and terminate model processing */ #define warning _glp_mpl_warning void warning(MPL *mpl, char *fmt, ...); /* print warning message and continue model processing */ #define mpl_initialize _glp_mpl_initialize MPL *mpl_initialize(void); /* create and initialize translator database */ #define mpl_read_model _glp_mpl_read_model int mpl_read_model(MPL *mpl, char *file, int skip_data); /* read model section and optional data section */ #define mpl_read_data _glp_mpl_read_data int mpl_read_data(MPL *mpl, char *file); /* read data section */ #define mpl_generate _glp_mpl_generate int mpl_generate(MPL *mpl, char *file); /* generate model */ #define mpl_get_prob_name _glp_mpl_get_prob_name char *mpl_get_prob_name(MPL *mpl); /* obtain problem (model) name */ #define mpl_get_num_rows _glp_mpl_get_num_rows int mpl_get_num_rows(MPL *mpl); /* determine number of rows */ #define mpl_get_num_cols _glp_mpl_get_num_cols int mpl_get_num_cols(MPL *mpl); /* determine number of columns */ #define mpl_get_row_name _glp_mpl_get_row_name char *mpl_get_row_name(MPL *mpl, int i); /* obtain row name */ #define mpl_get_row_kind _glp_mpl_get_row_kind int mpl_get_row_kind(MPL *mpl, int i); /* determine row kind */ #define mpl_get_row_bnds _glp_mpl_get_row_bnds int mpl_get_row_bnds(MPL *mpl, int i, double *lb, double *ub); /* obtain row bounds */ #define mpl_get_mat_row _glp_mpl_get_mat_row int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]); /* obtain row of the constraint matrix */ #define mpl_get_row_c0 _glp_mpl_get_row_c0 double mpl_get_row_c0(MPL *mpl, int i); /* obtain constant term of free row */ #define mpl_get_col_name _glp_mpl_get_col_name char *mpl_get_col_name(MPL *mpl, int j); /* obtain column name */ #define mpl_get_col_kind _glp_mpl_get_col_kind int mpl_get_col_kind(MPL *mpl, int j); /* determine column kind */ #define mpl_get_col_bnds _glp_mpl_get_col_bnds int mpl_get_col_bnds(MPL *mpl, int j, double *lb, double *ub); /* obtain column bounds */ #define mpl_has_solve_stmt _glp_mpl_has_solve_stmt int mpl_has_solve_stmt(MPL *mpl); /* check if model has solve statement */ #if 1 /* 15/V-2010 */ #define mpl_put_row_soln _glp_mpl_put_row_soln void mpl_put_row_soln(MPL *mpl, int i, int stat, double prim, double dual); /* store row (constraint/objective) solution components */ #endif #if 1 /* 15/V-2010 */ #define mpl_put_col_soln _glp_mpl_put_col_soln void mpl_put_col_soln(MPL *mpl, int j, int stat, double prim, double dual); /* store column (variable) solution components */ #endif #if 0 /* 15/V-2010 */ #define mpl_put_col_value _glp_mpl_put_col_value void mpl_put_col_value(MPL *mpl, int j, double val); /* store column value */ #endif #define mpl_postsolve _glp_mpl_postsolve int mpl_postsolve(MPL *mpl); /* postsolve model */ #define mpl_terminate _glp_mpl_terminate void mpl_terminate(MPL *mpl); /* free all resources used by translator */ #endif /* eof */ glpk-4.52.1/src/glpmpl01.c0000644000062000006210000052704612175147600014326 0ustar maomkpasswd/* glpmpl01.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_STDIO #include "glpmpl.h" #define dmp_get_atomv dmp_get_atom /**********************************************************************/ /* * * PROCESSING MODEL SECTION * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- enter_context - enter current token into context queue. -- -- This routine enters the current token into the context queue. */ void enter_context(MPL *mpl) { char *image, *s; if (mpl->token == T_EOF) image = "_|_"; else if (mpl->token == T_STRING) image = "'...'"; else image = mpl->image; xassert(0 <= mpl->c_ptr && mpl->c_ptr < CONTEXT_SIZE); mpl->context[mpl->c_ptr++] = ' '; if (mpl->c_ptr == CONTEXT_SIZE) mpl->c_ptr = 0; for (s = image; *s != '\0'; s++) { mpl->context[mpl->c_ptr++] = *s; if (mpl->c_ptr == CONTEXT_SIZE) mpl->c_ptr = 0; } return; } /*---------------------------------------------------------------------- -- print_context - print current content of context queue. -- -- This routine prints current content of the context queue. */ void print_context(MPL *mpl) { int c; while (mpl->c_ptr > 0) { mpl->c_ptr--; c = mpl->context[0]; memmove(mpl->context, mpl->context+1, CONTEXT_SIZE-1); mpl->context[CONTEXT_SIZE-1] = (char)c; } xprintf("Context: %s%.*s\n", mpl->context[0] == ' ' ? "" : "...", CONTEXT_SIZE, mpl->context); return; } /*---------------------------------------------------------------------- -- get_char - scan next character from input text file. -- -- This routine scans a next ASCII character from the input text file. -- In case of end-of-file, the character is assigned EOF. */ void get_char(MPL *mpl) { int c; if (mpl->c == EOF) goto done; if (mpl->c == '\n') mpl->line++; c = read_char(mpl); if (c == EOF) { if (mpl->c == '\n') mpl->line--; else warning(mpl, "final NL missing before end of file"); } else if (c == '\n') ; else if (isspace(c)) c = ' '; else if (iscntrl(c)) { enter_context(mpl); error(mpl, "control character 0x%02X not allowed", c); } mpl->c = c; done: return; } /*---------------------------------------------------------------------- -- append_char - append character to current token. -- -- This routine appends the current character to the current token and -- then scans a next character. */ void append_char(MPL *mpl) { xassert(0 <= mpl->imlen && mpl->imlen <= MAX_LENGTH); if (mpl->imlen == MAX_LENGTH) { switch (mpl->token) { case T_NAME: enter_context(mpl); error(mpl, "symbolic name %s... too long", mpl->image); case T_SYMBOL: enter_context(mpl); error(mpl, "symbol %s... too long", mpl->image); case T_NUMBER: enter_context(mpl); error(mpl, "numeric literal %s... too long", mpl->image); case T_STRING: enter_context(mpl); error(mpl, "string literal too long"); default: xassert(mpl != mpl); } } mpl->image[mpl->imlen++] = (char)mpl->c; mpl->image[mpl->imlen] = '\0'; get_char(mpl); return; } /*---------------------------------------------------------------------- -- get_token - scan next token from input text file. -- -- This routine scans a next token from the input text file using the -- standard finite automation technique. */ void get_token(MPL *mpl) { /* save the current token */ mpl->b_token = mpl->token; mpl->b_imlen = mpl->imlen; strcpy(mpl->b_image, mpl->image); mpl->b_value = mpl->value; /* if the next token is already scanned, make it current */ if (mpl->f_scan) { mpl->f_scan = 0; mpl->token = mpl->f_token; mpl->imlen = mpl->f_imlen; strcpy(mpl->image, mpl->f_image); mpl->value = mpl->f_value; goto done; } loop: /* nothing has been scanned so far */ mpl->token = 0; mpl->imlen = 0; mpl->image[0] = '\0'; mpl->value = 0.0; /* skip any uninteresting characters */ while (mpl->c == ' ' || mpl->c == '\n') get_char(mpl); /* recognize and construct the token */ if (mpl->c == EOF) { /* end-of-file reached */ mpl->token = T_EOF; } else if (mpl->c == '#') { /* comment; skip anything until end-of-line */ while (mpl->c != '\n' && mpl->c != EOF) get_char(mpl); goto loop; } else if (!mpl->flag_d && (isalpha(mpl->c) || mpl->c == '_')) { /* symbolic name or reserved keyword */ mpl->token = T_NAME; while (isalnum(mpl->c) || mpl->c == '_') append_char(mpl); if (strcmp(mpl->image, "and") == 0) mpl->token = T_AND; else if (strcmp(mpl->image, "by") == 0) mpl->token = T_BY; else if (strcmp(mpl->image, "cross") == 0) mpl->token = T_CROSS; else if (strcmp(mpl->image, "diff") == 0) mpl->token = T_DIFF; else if (strcmp(mpl->image, "div") == 0) mpl->token = T_DIV; else if (strcmp(mpl->image, "else") == 0) mpl->token = T_ELSE; else if (strcmp(mpl->image, "if") == 0) mpl->token = T_IF; else if (strcmp(mpl->image, "in") == 0) mpl->token = T_IN; #if 1 /* 21/VII-2006 */ else if (strcmp(mpl->image, "Infinity") == 0) mpl->token = T_INFINITY; #endif else if (strcmp(mpl->image, "inter") == 0) mpl->token = T_INTER; else if (strcmp(mpl->image, "less") == 0) mpl->token = T_LESS; else if (strcmp(mpl->image, "mod") == 0) mpl->token = T_MOD; else if (strcmp(mpl->image, "not") == 0) mpl->token = T_NOT; else if (strcmp(mpl->image, "or") == 0) mpl->token = T_OR; else if (strcmp(mpl->image, "s") == 0 && mpl->c == '.') { mpl->token = T_SPTP; append_char(mpl); if (mpl->c != 't') sptp: { enter_context(mpl); error(mpl, "keyword s.t. incomplete"); } append_char(mpl); if (mpl->c != '.') goto sptp; append_char(mpl); } else if (strcmp(mpl->image, "symdiff") == 0) mpl->token = T_SYMDIFF; else if (strcmp(mpl->image, "then") == 0) mpl->token = T_THEN; else if (strcmp(mpl->image, "union") == 0) mpl->token = T_UNION; else if (strcmp(mpl->image, "within") == 0) mpl->token = T_WITHIN; } else if (!mpl->flag_d && isdigit(mpl->c)) { /* numeric literal */ mpl->token = T_NUMBER; /* scan integer part */ while (isdigit(mpl->c)) append_char(mpl); /* scan optional fractional part */ if (mpl->c == '.') { append_char(mpl); if (mpl->c == '.') { /* hmm, it is not the fractional part, it is dots that follow the integer part */ mpl->imlen--; mpl->image[mpl->imlen] = '\0'; mpl->f_dots = 1; goto conv; } frac: while (isdigit(mpl->c)) append_char(mpl); } /* scan optional decimal exponent */ if (mpl->c == 'e' || mpl->c == 'E') { append_char(mpl); if (mpl->c == '+' || mpl->c == '-') append_char(mpl); if (!isdigit(mpl->c)) { enter_context(mpl); error(mpl, "numeric literal %s incomplete", mpl->image); } while (isdigit(mpl->c)) append_char(mpl); } /* there must be no letter following the numeric literal */ if (isalpha(mpl->c) || mpl->c == '_') { enter_context(mpl); error(mpl, "symbol %s%c... should be enclosed in quotes", mpl->image, mpl->c); } conv: /* convert numeric literal to floating-point */ if (str2num(mpl->image, &mpl->value)) err: { enter_context(mpl); error(mpl, "cannot convert numeric literal %s to floating-p" "oint number", mpl->image); } } else if (mpl->c == '\'' || mpl->c == '"') { /* character string */ int quote = mpl->c; mpl->token = T_STRING; get_char(mpl); for (;;) { if (mpl->c == '\n' || mpl->c == EOF) { enter_context(mpl); error(mpl, "unexpected end of line; string literal incom" "plete"); } if (mpl->c == quote) { get_char(mpl); if (mpl->c != quote) break; } append_char(mpl); } } else if (!mpl->flag_d && mpl->c == '+') mpl->token = T_PLUS, append_char(mpl); else if (!mpl->flag_d && mpl->c == '-') mpl->token = T_MINUS, append_char(mpl); else if (mpl->c == '*') { mpl->token = T_ASTERISK, append_char(mpl); if (mpl->c == '*') mpl->token = T_POWER, append_char(mpl); } else if (mpl->c == '/') { mpl->token = T_SLASH, append_char(mpl); if (mpl->c == '*') { /* comment sequence */ get_char(mpl); for (;;) { if (mpl->c == EOF) { /* do not call enter_context at this point */ error(mpl, "unexpected end of file; comment sequence " "incomplete"); } else if (mpl->c == '*') { get_char(mpl); if (mpl->c == '/') break; } else get_char(mpl); } get_char(mpl); goto loop; } } else if (mpl->c == '^') mpl->token = T_POWER, append_char(mpl); else if (mpl->c == '<') { mpl->token = T_LT, append_char(mpl); if (mpl->c == '=') mpl->token = T_LE, append_char(mpl); else if (mpl->c == '>') mpl->token = T_NE, append_char(mpl); #if 1 /* 11/II-2008 */ else if (mpl->c == '-') mpl->token = T_INPUT, append_char(mpl); #endif } else if (mpl->c == '=') { mpl->token = T_EQ, append_char(mpl); if (mpl->c == '=') append_char(mpl); } else if (mpl->c == '>') { mpl->token = T_GT, append_char(mpl); if (mpl->c == '=') mpl->token = T_GE, append_char(mpl); #if 1 /* 14/VII-2006 */ else if (mpl->c == '>') mpl->token = T_APPEND, append_char(mpl); #endif } else if (mpl->c == '!') { mpl->token = T_NOT, append_char(mpl); if (mpl->c == '=') mpl->token = T_NE, append_char(mpl); } else if (mpl->c == '&') { mpl->token = T_CONCAT, append_char(mpl); if (mpl->c == '&') mpl->token = T_AND, append_char(mpl); } else if (mpl->c == '|') { mpl->token = T_BAR, append_char(mpl); if (mpl->c == '|') mpl->token = T_OR, append_char(mpl); } else if (!mpl->flag_d && mpl->c == '.') { mpl->token = T_POINT, append_char(mpl); if (mpl->f_dots) { /* dots; the first dot was read on the previous call to the scanner, so the current character is the second dot */ mpl->token = T_DOTS; mpl->imlen = 2; strcpy(mpl->image, ".."); mpl->f_dots = 0; } else if (mpl->c == '.') mpl->token = T_DOTS, append_char(mpl); else if (isdigit(mpl->c)) { /* numeric literal that begins with the decimal point */ mpl->token = T_NUMBER, append_char(mpl); goto frac; } } else if (mpl->c == ',') mpl->token = T_COMMA, append_char(mpl); else if (mpl->c == ':') { mpl->token = T_COLON, append_char(mpl); if (mpl->c == '=') mpl->token = T_ASSIGN, append_char(mpl); } else if (mpl->c == ';') mpl->token = T_SEMICOLON, append_char(mpl); else if (mpl->c == '(') mpl->token = T_LEFT, append_char(mpl); else if (mpl->c == ')') mpl->token = T_RIGHT, append_char(mpl); else if (mpl->c == '[') mpl->token = T_LBRACKET, append_char(mpl); else if (mpl->c == ']') mpl->token = T_RBRACKET, append_char(mpl); else if (mpl->c == '{') mpl->token = T_LBRACE, append_char(mpl); else if (mpl->c == '}') mpl->token = T_RBRACE, append_char(mpl); #if 1 /* 11/II-2008 */ else if (mpl->c == '~') mpl->token = T_TILDE, append_char(mpl); #endif else if (isalnum(mpl->c) || strchr("+-._", mpl->c) != NULL) { /* symbol */ xassert(mpl->flag_d); mpl->token = T_SYMBOL; while (isalnum(mpl->c) || strchr("+-._", mpl->c) != NULL) append_char(mpl); switch (str2num(mpl->image, &mpl->value)) { case 0: mpl->token = T_NUMBER; break; case 1: goto err; case 2: break; default: xassert(mpl != mpl); } } else { enter_context(mpl); error(mpl, "character %c not allowed", mpl->c); } /* enter the current token into the context queue */ enter_context(mpl); /* reset the flag, which may be set by indexing_expression() and is used by expression_list() */ mpl->flag_x = 0; done: return; } /*---------------------------------------------------------------------- -- unget_token - return current token back to input stream. -- -- This routine returns the current token back to the input stream, so -- the previously scanned token becomes the current one. */ void unget_token(MPL *mpl) { /* save the current token, which becomes the next one */ xassert(!mpl->f_scan); mpl->f_scan = 1; mpl->f_token = mpl->token; mpl->f_imlen = mpl->imlen; strcpy(mpl->f_image, mpl->image); mpl->f_value = mpl->value; /* restore the previous token, which becomes the current one */ mpl->token = mpl->b_token; mpl->imlen = mpl->b_imlen; strcpy(mpl->image, mpl->b_image); mpl->value = mpl->b_value; return; } /*---------------------------------------------------------------------- -- is_keyword - check if current token is given non-reserved keyword. -- -- If the current token is given (non-reserved) keyword, this routine -- returns non-zero. Otherwise zero is returned. */ int is_keyword(MPL *mpl, char *keyword) { return mpl->token == T_NAME && strcmp(mpl->image, keyword) == 0; } /*---------------------------------------------------------------------- -- is_reserved - check if current token is reserved keyword. -- -- If the current token is a reserved keyword, this routine returns -- non-zero. Otherwise zero is returned. */ int is_reserved(MPL *mpl) { return mpl->token == T_AND && mpl->image[0] == 'a' || mpl->token == T_BY || mpl->token == T_CROSS || mpl->token == T_DIFF || mpl->token == T_DIV || mpl->token == T_ELSE || mpl->token == T_IF || mpl->token == T_IN || mpl->token == T_INTER || mpl->token == T_LESS || mpl->token == T_MOD || mpl->token == T_NOT && mpl->image[0] == 'n' || mpl->token == T_OR && mpl->image[0] == 'o' || mpl->token == T_SYMDIFF || mpl->token == T_THEN || mpl->token == T_UNION || mpl->token == T_WITHIN; } /*---------------------------------------------------------------------- -- make_code - generate pseudo-code (basic routine). -- -- This routine generates specified pseudo-code. It is assumed that all -- other translator routines use this basic routine. */ CODE *make_code(MPL *mpl, int op, OPERANDS *arg, int type, int dim) { CODE *code; DOMAIN *domain; DOMAIN_BLOCK *block; ARG_LIST *e; /* generate pseudo-code */ code = alloc(CODE); code->op = op; code->vflag = 0; /* is inherited from operand(s) */ /* copy operands and also make them referring to the pseudo-code being generated, because the latter becomes the parent for all its operands */ memset(&code->arg, '?', sizeof(OPERANDS)); switch (op) { case O_NUMBER: code->arg.num = arg->num; break; case O_STRING: code->arg.str = arg->str; break; case O_INDEX: code->arg.index.slot = arg->index.slot; code->arg.index.next = arg->index.next; break; case O_MEMNUM: case O_MEMSYM: for (e = arg->par.list; e != NULL; e = e->next) { xassert(e->x != NULL); xassert(e->x->up == NULL); e->x->up = code; code->vflag |= e->x->vflag; } code->arg.par.par = arg->par.par; code->arg.par.list = arg->par.list; break; case O_MEMSET: for (e = arg->set.list; e != NULL; e = e->next) { xassert(e->x != NULL); xassert(e->x->up == NULL); e->x->up = code; code->vflag |= e->x->vflag; } code->arg.set.set = arg->set.set; code->arg.set.list = arg->set.list; break; case O_MEMVAR: for (e = arg->var.list; e != NULL; e = e->next) { xassert(e->x != NULL); xassert(e->x->up == NULL); e->x->up = code; code->vflag |= e->x->vflag; } code->arg.var.var = arg->var.var; code->arg.var.list = arg->var.list; #if 1 /* 15/V-2010 */ code->arg.var.suff = arg->var.suff; #endif break; #if 1 /* 15/V-2010 */ case O_MEMCON: for (e = arg->con.list; e != NULL; e = e->next) { xassert(e->x != NULL); xassert(e->x->up == NULL); e->x->up = code; code->vflag |= e->x->vflag; } code->arg.con.con = arg->con.con; code->arg.con.list = arg->con.list; code->arg.con.suff = arg->con.suff; break; #endif case O_TUPLE: case O_MAKE: for (e = arg->list; e != NULL; e = e->next) { xassert(e->x != NULL); xassert(e->x->up == NULL); e->x->up = code; code->vflag |= e->x->vflag; } code->arg.list = arg->list; break; case O_SLICE: xassert(arg->slice != NULL); code->arg.slice = arg->slice; break; case O_IRAND224: case O_UNIFORM01: case O_NORMAL01: case O_GMTIME: code->vflag = 1; break; case O_CVTNUM: case O_CVTSYM: case O_CVTLOG: case O_CVTTUP: case O_CVTLFM: case O_PLUS: case O_MINUS: case O_NOT: case O_ABS: case O_CEIL: case O_FLOOR: case O_EXP: case O_LOG: case O_LOG10: case O_SQRT: case O_SIN: case O_COS: case O_ATAN: case O_ROUND: case O_TRUNC: case O_CARD: case O_LENGTH: /* unary operation */ xassert(arg->arg.x != NULL); xassert(arg->arg.x->up == NULL); arg->arg.x->up = code; code->vflag |= arg->arg.x->vflag; code->arg.arg.x = arg->arg.x; break; case O_ADD: case O_SUB: case O_LESS: case O_MUL: case O_DIV: case O_IDIV: case O_MOD: case O_POWER: case O_ATAN2: case O_ROUND2: case O_TRUNC2: case O_UNIFORM: if (op == O_UNIFORM) code->vflag = 1; case O_NORMAL: if (op == O_NORMAL) code->vflag = 1; case O_CONCAT: case O_LT: case O_LE: case O_EQ: case O_GE: case O_GT: case O_NE: case O_AND: case O_OR: case O_UNION: case O_DIFF: case O_SYMDIFF: case O_INTER: case O_CROSS: case O_IN: case O_NOTIN: case O_WITHIN: case O_NOTWITHIN: case O_SUBSTR: case O_STR2TIME: case O_TIME2STR: /* binary operation */ xassert(arg->arg.x != NULL); xassert(arg->arg.x->up == NULL); arg->arg.x->up = code; code->vflag |= arg->arg.x->vflag; xassert(arg->arg.y != NULL); xassert(arg->arg.y->up == NULL); arg->arg.y->up = code; code->vflag |= arg->arg.y->vflag; code->arg.arg.x = arg->arg.x; code->arg.arg.y = arg->arg.y; break; case O_DOTS: case O_FORK: case O_SUBSTR3: /* ternary operation */ xassert(arg->arg.x != NULL); xassert(arg->arg.x->up == NULL); arg->arg.x->up = code; code->vflag |= arg->arg.x->vflag; xassert(arg->arg.y != NULL); xassert(arg->arg.y->up == NULL); arg->arg.y->up = code; code->vflag |= arg->arg.y->vflag; if (arg->arg.z != NULL) { xassert(arg->arg.z->up == NULL); arg->arg.z->up = code; code->vflag |= arg->arg.z->vflag; } code->arg.arg.x = arg->arg.x; code->arg.arg.y = arg->arg.y; code->arg.arg.z = arg->arg.z; break; case O_MIN: case O_MAX: /* n-ary operation */ for (e = arg->list; e != NULL; e = e->next) { xassert(e->x != NULL); xassert(e->x->up == NULL); e->x->up = code; code->vflag |= e->x->vflag; } code->arg.list = arg->list; break; case O_SUM: case O_PROD: case O_MINIMUM: case O_MAXIMUM: case O_FORALL: case O_EXISTS: case O_SETOF: case O_BUILD: /* iterated operation */ domain = arg->loop.domain; xassert(domain != NULL); if (domain->code != NULL) { xassert(domain->code->up == NULL); domain->code->up = code; code->vflag |= domain->code->vflag; } for (block = domain->list; block != NULL; block = block->next) { xassert(block->code != NULL); xassert(block->code->up == NULL); block->code->up = code; code->vflag |= block->code->vflag; } if (arg->loop.x != NULL) { xassert(arg->loop.x->up == NULL); arg->loop.x->up = code; code->vflag |= arg->loop.x->vflag; } code->arg.loop.domain = arg->loop.domain; code->arg.loop.x = arg->loop.x; break; default: xassert(op != op); } /* set other attributes of the pseudo-code */ code->type = type; code->dim = dim; code->up = NULL; code->valid = 0; memset(&code->value, '?', sizeof(VALUE)); return code; } /*---------------------------------------------------------------------- -- make_unary - generate pseudo-code for unary operation. -- -- This routine generates pseudo-code for unary operation. */ CODE *make_unary(MPL *mpl, int op, CODE *x, int type, int dim) { CODE *code; OPERANDS arg; xassert(x != NULL); arg.arg.x = x; code = make_code(mpl, op, &arg, type, dim); return code; } /*---------------------------------------------------------------------- -- make_binary - generate pseudo-code for binary operation. -- -- This routine generates pseudo-code for binary operation. */ CODE *make_binary(MPL *mpl, int op, CODE *x, CODE *y, int type, int dim) { CODE *code; OPERANDS arg; xassert(x != NULL); xassert(y != NULL); arg.arg.x = x; arg.arg.y = y; code = make_code(mpl, op, &arg, type, dim); return code; } /*---------------------------------------------------------------------- -- make_ternary - generate pseudo-code for ternary operation. -- -- This routine generates pseudo-code for ternary operation. */ CODE *make_ternary(MPL *mpl, int op, CODE *x, CODE *y, CODE *z, int type, int dim) { CODE *code; OPERANDS arg; xassert(x != NULL); xassert(y != NULL); /* third operand can be NULL */ arg.arg.x = x; arg.arg.y = y; arg.arg.z = z; code = make_code(mpl, op, &arg, type, dim); return code; } /*---------------------------------------------------------------------- -- numeric_literal - parse reference to numeric literal. -- -- This routine parses primary expression using the syntax: -- -- ::= */ CODE *numeric_literal(MPL *mpl) { CODE *code; OPERANDS arg; xassert(mpl->token == T_NUMBER); arg.num = mpl->value; code = make_code(mpl, O_NUMBER, &arg, A_NUMERIC, 0); get_token(mpl /* */); return code; } /*---------------------------------------------------------------------- -- string_literal - parse reference to string literal. -- -- This routine parses primary expression using the syntax: -- -- ::= */ CODE *string_literal(MPL *mpl) { CODE *code; OPERANDS arg; xassert(mpl->token == T_STRING); arg.str = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(arg.str, mpl->image); code = make_code(mpl, O_STRING, &arg, A_SYMBOLIC, 0); get_token(mpl /* */); return code; } /*---------------------------------------------------------------------- -- create_arg_list - create empty operands list. -- -- This routine creates operands list, which is initially empty. */ ARG_LIST *create_arg_list(MPL *mpl) { ARG_LIST *list; xassert(mpl == mpl); list = NULL; return list; } /*---------------------------------------------------------------------- -- expand_arg_list - append operand to operands list. -- -- This routine appends new operand to specified operands list. */ ARG_LIST *expand_arg_list(MPL *mpl, ARG_LIST *list, CODE *x) { ARG_LIST *tail, *temp; xassert(x != NULL); /* create new operands list entry */ tail = alloc(ARG_LIST); tail->x = x; tail->next = NULL; /* and append it to the operands list */ if (list == NULL) list = tail; else { for (temp = list; temp->next != NULL; temp = temp->next); temp->next = tail; } return list; } /*---------------------------------------------------------------------- -- arg_list_len - determine length of operands list. -- -- This routine returns the number of operands in operands list. */ int arg_list_len(MPL *mpl, ARG_LIST *list) { ARG_LIST *temp; int len; xassert(mpl == mpl); len = 0; for (temp = list; temp != NULL; temp = temp->next) len++; return len; } /*---------------------------------------------------------------------- -- subscript_list - parse subscript list. -- -- This routine parses subscript list using the syntax: -- -- ::= -- ::= , -- ::= */ ARG_LIST *subscript_list(MPL *mpl) { ARG_LIST *list; CODE *x; list = create_arg_list(mpl); for (;;) { /* parse subscript expression */ x = expression_5(mpl); /* convert it to symbolic type, if necessary */ if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); /* check that now the expression is of symbolic type */ if (x->type != A_SYMBOLIC) error(mpl, "subscript expression has invalid type"); xassert(x->dim == 0); /* and append it to the subscript list */ list = expand_arg_list(mpl, list, x); /* check a token that follows the subscript expression */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_RBRACKET) break; else error(mpl, "syntax error in subscript list"); } return list; } #if 1 /* 15/V-2010 */ /*---------------------------------------------------------------------- -- object_reference - parse reference to named object. -- -- This routine parses primary expression using the syntax: -- -- ::= -- ::= -- ::= [ ] -- ::= -- ::= [ ] -- ::= -- ::= [ ] -- -- ::= -- ::= [ ] -- -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= | .lb | .ub | .status | .val | .dual */ CODE *object_reference(MPL *mpl) { AVLNODE *node; DOMAIN_SLOT *slot; SET *set; PARAMETER *par; VARIABLE *var; CONSTRAINT *con; ARG_LIST *list; OPERANDS arg; CODE *code; char *name; int dim, suff; /* find the object in the symbolic name table */ xassert(mpl->token == T_NAME); node = avl_find_node(mpl->tree, mpl->image); if (node == NULL) error(mpl, "%s not defined", mpl->image); /* check the object type and obtain its dimension */ switch (avl_get_node_type(node)) { case A_INDEX: /* dummy index */ slot = (DOMAIN_SLOT *)avl_get_node_link(node); name = slot->name; dim = 0; break; case A_SET: /* model set */ set = (SET *)avl_get_node_link(node); name = set->name; dim = set->dim; /* if a set object is referenced in its own declaration and the dimen attribute is not specified yet, use dimen 1 by default */ if (set->dimen == 0) set->dimen = 1; break; case A_PARAMETER: /* model parameter */ par = (PARAMETER *)avl_get_node_link(node); name = par->name; dim = par->dim; break; case A_VARIABLE: /* model variable */ var = (VARIABLE *)avl_get_node_link(node); name = var->name; dim = var->dim; break; case A_CONSTRAINT: /* model constraint or objective */ con = (CONSTRAINT *)avl_get_node_link(node); name = con->name; dim = con->dim; break; default: xassert(node != node); } get_token(mpl /* */); /* parse optional subscript list */ if (mpl->token == T_LBRACKET) { /* subscript list is specified */ if (dim == 0) error(mpl, "%s cannot be subscripted", name); get_token(mpl /* [ */); list = subscript_list(mpl); if (dim != arg_list_len(mpl, list)) error(mpl, "%s must have %d subscript%s rather than %d", name, dim, dim == 1 ? "" : "s", arg_list_len(mpl, list)); xassert(mpl->token == T_RBRACKET); get_token(mpl /* ] */); } else { /* subscript list is not specified */ if (dim != 0) error(mpl, "%s must be subscripted", name); list = create_arg_list(mpl); } /* parse optional suffix */ if (!mpl->flag_s && avl_get_node_type(node) == A_VARIABLE) suff = DOT_NONE; else suff = DOT_VAL; if (mpl->token == T_POINT) { get_token(mpl /* . */); if (mpl->token != T_NAME) error(mpl, "invalid use of period"); if (!(avl_get_node_type(node) == A_VARIABLE || avl_get_node_type(node) == A_CONSTRAINT)) error(mpl, "%s cannot have a suffix", name); if (strcmp(mpl->image, "lb") == 0) suff = DOT_LB; else if (strcmp(mpl->image, "ub") == 0) suff = DOT_UB; else if (strcmp(mpl->image, "status") == 0) suff = DOT_STATUS; else if (strcmp(mpl->image, "val") == 0) suff = DOT_VAL; else if (strcmp(mpl->image, "dual") == 0) suff = DOT_DUAL; else error(mpl, "suffix .%s invalid", mpl->image); get_token(mpl /* suffix */); } /* generate pseudo-code to take value of the object */ switch (avl_get_node_type(node)) { case A_INDEX: arg.index.slot = slot; arg.index.next = slot->list; code = make_code(mpl, O_INDEX, &arg, A_SYMBOLIC, 0); slot->list = code; break; case A_SET: arg.set.set = set; arg.set.list = list; code = make_code(mpl, O_MEMSET, &arg, A_ELEMSET, set->dimen); break; case A_PARAMETER: arg.par.par = par; arg.par.list = list; if (par->type == A_SYMBOLIC) code = make_code(mpl, O_MEMSYM, &arg, A_SYMBOLIC, 0); else code = make_code(mpl, O_MEMNUM, &arg, A_NUMERIC, 0); break; case A_VARIABLE: if (!mpl->flag_s && (suff == DOT_STATUS || suff == DOT_VAL || suff == DOT_DUAL)) error(mpl, "invalid reference to status, primal value, o" "r dual value of variable %s above solve statement", var->name); arg.var.var = var; arg.var.list = list; arg.var.suff = suff; code = make_code(mpl, O_MEMVAR, &arg, suff == DOT_NONE ? A_FORMULA : A_NUMERIC, 0); break; case A_CONSTRAINT: if (!mpl->flag_s && (suff == DOT_STATUS || suff == DOT_VAL || suff == DOT_DUAL)) error(mpl, "invalid reference to status, primal value, o" "r dual value of %s %s above solve statement", con->type == A_CONSTRAINT ? "constraint" : "objective" , con->name); arg.con.con = con; arg.con.list = list; arg.con.suff = suff; code = make_code(mpl, O_MEMCON, &arg, A_NUMERIC, 0); break; default: xassert(node != node); } return code; } #endif /*---------------------------------------------------------------------- -- numeric_argument - parse argument passed to built-in function. -- -- This routine parses an argument passed to numeric built-in function -- using the syntax: -- -- ::= */ CODE *numeric_argument(MPL *mpl, char *func) { CODE *x; x = expression_5(mpl); /* convert the argument to numeric type, if necessary */ if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); /* check that now the argument is of numeric type */ if (x->type != A_NUMERIC) error(mpl, "argument for %s has invalid type", func); xassert(x->dim == 0); return x; } #if 1 /* 15/VII-2006 */ CODE *symbolic_argument(MPL *mpl, char *func) { CODE *x; x = expression_5(mpl); /* convert the argument to symbolic type, if necessary */ if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); /* check that now the argument is of symbolic type */ if (x->type != A_SYMBOLIC) error(mpl, "argument for %s has invalid type", func); xassert(x->dim == 0); return x; } #endif #if 1 /* 15/VII-2006 */ CODE *elemset_argument(MPL *mpl, char *func) { CODE *x; x = expression_9(mpl); if (x->type != A_ELEMSET) error(mpl, "argument for %s has invalid type", func); xassert(x->dim > 0); return x; } #endif /*---------------------------------------------------------------------- -- function_reference - parse reference to built-in function. -- -- This routine parses primary expression using the syntax: -- -- ::= abs ( ) -- ::= ceil ( ) -- ::= floor ( ) -- ::= exp ( ) -- ::= log ( ) -- ::= log10 ( ) -- ::= max ( ) -- ::= min ( ) -- ::= sqrt ( ) -- ::= sin ( ) -- ::= cos ( ) -- ::= atan ( ) -- ::= atan2 ( , ) -- ::= round ( ) -- ::= round ( , ) -- ::= trunc ( ) -- ::= trunc ( , ) -- ::= Irand224 ( ) -- ::= Uniform01 ( ) -- ::= Uniform ( , ) -- ::= Normal01 ( ) -- ::= Normal ( , ) -- ::= card ( ) -- ::= length ( ) -- ::= substr ( , ) -- ::= substr ( , , ) -- ::= str2time ( , ) -- ::= time2str ( , ) -- ::= gmtime ( ) -- ::= -- ::= , */ CODE *function_reference(MPL *mpl) { CODE *code; OPERANDS arg; int op; char func[15+1]; /* determine operation code */ xassert(mpl->token == T_NAME); if (strcmp(mpl->image, "abs") == 0) op = O_ABS; else if (strcmp(mpl->image, "ceil") == 0) op = O_CEIL; else if (strcmp(mpl->image, "floor") == 0) op = O_FLOOR; else if (strcmp(mpl->image, "exp") == 0) op = O_EXP; else if (strcmp(mpl->image, "log") == 0) op = O_LOG; else if (strcmp(mpl->image, "log10") == 0) op = O_LOG10; else if (strcmp(mpl->image, "sqrt") == 0) op = O_SQRT; else if (strcmp(mpl->image, "sin") == 0) op = O_SIN; else if (strcmp(mpl->image, "cos") == 0) op = O_COS; else if (strcmp(mpl->image, "atan") == 0) op = O_ATAN; else if (strcmp(mpl->image, "min") == 0) op = O_MIN; else if (strcmp(mpl->image, "max") == 0) op = O_MAX; else if (strcmp(mpl->image, "round") == 0) op = O_ROUND; else if (strcmp(mpl->image, "trunc") == 0) op = O_TRUNC; else if (strcmp(mpl->image, "Irand224") == 0) op = O_IRAND224; else if (strcmp(mpl->image, "Uniform01") == 0) op = O_UNIFORM01; else if (strcmp(mpl->image, "Uniform") == 0) op = O_UNIFORM; else if (strcmp(mpl->image, "Normal01") == 0) op = O_NORMAL01; else if (strcmp(mpl->image, "Normal") == 0) op = O_NORMAL; else if (strcmp(mpl->image, "card") == 0) op = O_CARD; else if (strcmp(mpl->image, "length") == 0) op = O_LENGTH; else if (strcmp(mpl->image, "substr") == 0) op = O_SUBSTR; else if (strcmp(mpl->image, "str2time") == 0) op = O_STR2TIME; else if (strcmp(mpl->image, "time2str") == 0) op = O_TIME2STR; else if (strcmp(mpl->image, "gmtime") == 0) op = O_GMTIME; else error(mpl, "function %s unknown", mpl->image); /* save symbolic name of the function */ strcpy(func, mpl->image); xassert(strlen(func) < sizeof(func)); get_token(mpl /* */); /* check the left parenthesis that follows the function name */ xassert(mpl->token == T_LEFT); get_token(mpl /* ( */); /* parse argument list */ if (op == O_MIN || op == O_MAX) { /* min and max allow arbitrary number of arguments */ arg.list = create_arg_list(mpl); /* parse argument list */ for (;;) { /* parse argument and append it to the operands list */ arg.list = expand_arg_list(mpl, arg.list, numeric_argument(mpl, func)); /* check a token that follows the argument */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_RIGHT) break; else error(mpl, "syntax error in argument list for %s", func); } } else if (op == O_IRAND224 || op == O_UNIFORM01 || op == O_NORMAL01 || op == O_GMTIME) { /* Irand224, Uniform01, Normal01, gmtime need no arguments */ if (mpl->token != T_RIGHT) error(mpl, "%s needs no arguments", func); } else if (op == O_UNIFORM || op == O_NORMAL) { /* Uniform and Normal need two arguments */ /* parse the first argument */ arg.arg.x = numeric_argument(mpl, func); /* check a token that follows the first argument */ if (mpl->token == T_COMMA) ; else if (mpl->token == T_RIGHT) error(mpl, "%s needs two arguments", func); else error(mpl, "syntax error in argument for %s", func); get_token(mpl /* , */); /* parse the second argument */ arg.arg.y = numeric_argument(mpl, func); /* check a token that follows the second argument */ if (mpl->token == T_COMMA) error(mpl, "%s needs two argument", func); else if (mpl->token == T_RIGHT) ; else error(mpl, "syntax error in argument for %s", func); } else if (op == O_ATAN || op == O_ROUND || op == O_TRUNC) { /* atan, round, and trunc need one or two arguments */ /* parse the first argument */ arg.arg.x = numeric_argument(mpl, func); /* parse the second argument, if specified */ if (mpl->token == T_COMMA) { switch (op) { case O_ATAN: op = O_ATAN2; break; case O_ROUND: op = O_ROUND2; break; case O_TRUNC: op = O_TRUNC2; break; default: xassert(op != op); } get_token(mpl /* , */); arg.arg.y = numeric_argument(mpl, func); } /* check a token that follows the last argument */ if (mpl->token == T_COMMA) error(mpl, "%s needs one or two arguments", func); else if (mpl->token == T_RIGHT) ; else error(mpl, "syntax error in argument for %s", func); } else if (op == O_SUBSTR) { /* substr needs two or three arguments */ /* parse the first argument */ arg.arg.x = symbolic_argument(mpl, func); /* check a token that follows the first argument */ if (mpl->token == T_COMMA) ; else if (mpl->token == T_RIGHT) error(mpl, "%s needs two or three arguments", func); else error(mpl, "syntax error in argument for %s", func); get_token(mpl /* , */); /* parse the second argument */ arg.arg.y = numeric_argument(mpl, func); /* parse the third argument, if specified */ if (mpl->token == T_COMMA) { op = O_SUBSTR3; get_token(mpl /* , */); arg.arg.z = numeric_argument(mpl, func); } /* check a token that follows the last argument */ if (mpl->token == T_COMMA) error(mpl, "%s needs two or three arguments", func); else if (mpl->token == T_RIGHT) ; else error(mpl, "syntax error in argument for %s", func); } else if (op == O_STR2TIME) { /* str2time needs two arguments, both symbolic */ /* parse the first argument */ arg.arg.x = symbolic_argument(mpl, func); /* check a token that follows the first argument */ if (mpl->token == T_COMMA) ; else if (mpl->token == T_RIGHT) error(mpl, "%s needs two arguments", func); else error(mpl, "syntax error in argument for %s", func); get_token(mpl /* , */); /* parse the second argument */ arg.arg.y = symbolic_argument(mpl, func); /* check a token that follows the second argument */ if (mpl->token == T_COMMA) error(mpl, "%s needs two argument", func); else if (mpl->token == T_RIGHT) ; else error(mpl, "syntax error in argument for %s", func); } else if (op == O_TIME2STR) { /* time2str needs two arguments, numeric and symbolic */ /* parse the first argument */ arg.arg.x = numeric_argument(mpl, func); /* check a token that follows the first argument */ if (mpl->token == T_COMMA) ; else if (mpl->token == T_RIGHT) error(mpl, "%s needs two arguments", func); else error(mpl, "syntax error in argument for %s", func); get_token(mpl /* , */); /* parse the second argument */ arg.arg.y = symbolic_argument(mpl, func); /* check a token that follows the second argument */ if (mpl->token == T_COMMA) error(mpl, "%s needs two argument", func); else if (mpl->token == T_RIGHT) ; else error(mpl, "syntax error in argument for %s", func); } else { /* other functions need one argument */ if (op == O_CARD) arg.arg.x = elemset_argument(mpl, func); else if (op == O_LENGTH) arg.arg.x = symbolic_argument(mpl, func); else arg.arg.x = numeric_argument(mpl, func); /* check a token that follows the argument */ if (mpl->token == T_COMMA) error(mpl, "%s needs one argument", func); else if (mpl->token == T_RIGHT) ; else error(mpl, "syntax error in argument for %s", func); } /* make pseudo-code to call the built-in function */ if (op == O_SUBSTR || op == O_SUBSTR3 || op == O_TIME2STR) code = make_code(mpl, op, &arg, A_SYMBOLIC, 0); else code = make_code(mpl, op, &arg, A_NUMERIC, 0); /* the reference ends with the right parenthesis */ xassert(mpl->token == T_RIGHT); get_token(mpl /* ) */); return code; } /*---------------------------------------------------------------------- -- create_domain - create empty domain. -- -- This routine creates empty domain, which is initially empty, i.e. -- has no domain blocks. */ DOMAIN *create_domain(MPL *mpl) { DOMAIN *domain; domain = alloc(DOMAIN); domain->list = NULL; domain->code = NULL; return domain; } /*---------------------------------------------------------------------- -- create_block - create empty domain block. -- -- This routine creates empty domain block, which is initially empty, -- i.e. has no domain slots. */ DOMAIN_BLOCK *create_block(MPL *mpl) { DOMAIN_BLOCK *block; block = alloc(DOMAIN_BLOCK); block->list = NULL; block->code = NULL; block->backup = NULL; block->next = NULL; return block; } /*---------------------------------------------------------------------- -- append_block - append domain block to specified domain. -- -- This routine adds given domain block to the end of the block list of -- specified domain. */ void append_block(MPL *mpl, DOMAIN *domain, DOMAIN_BLOCK *block) { DOMAIN_BLOCK *temp; xassert(mpl == mpl); xassert(domain != NULL); xassert(block != NULL); xassert(block->next == NULL); if (domain->list == NULL) domain->list = block; else { for (temp = domain->list; temp->next != NULL; temp = temp->next); temp->next = block; } return; } /*---------------------------------------------------------------------- -- append_slot - create and append new slot to domain block. -- -- This routine creates new domain slot and adds it to the end of slot -- list of specified domain block. -- -- The parameter name is symbolic name of the dummy index associated -- with the slot (the character string must be allocated). NULL means -- the dummy index is not explicitly specified. -- -- The parameter code is pseudo-code for computing symbolic value, at -- which the dummy index is bounded. NULL means the dummy index is free -- in the domain scope. */ DOMAIN_SLOT *append_slot(MPL *mpl, DOMAIN_BLOCK *block, char *name, CODE *code) { DOMAIN_SLOT *slot, *temp; xassert(block != NULL); slot = alloc(DOMAIN_SLOT); slot->name = name; slot->code = code; slot->value = NULL; slot->list = NULL; slot->next = NULL; if (block->list == NULL) block->list = slot; else { for (temp = block->list; temp->next != NULL; temp = temp->next); temp->next = slot; } return slot; } /*---------------------------------------------------------------------- -- expression_list - parse expression list. -- -- This routine parses a list of one or more expressions enclosed into -- the parentheses using the syntax: -- -- ::= ( ) -- ::= -- ::= , -- -- Note that this construction may have three different meanings: -- -- 1. If consists of only one expression, is a parenthesized expression, which may be of any -- valid type (not necessarily 1-tuple). -- -- 2. If consists of several expressions separated by -- commae, where no expression is undeclared symbolic name, is a n-tuple. -- -- 3. If consists of several expressions separated by -- commae, where at least one expression is undeclared symbolic name -- (that denotes a dummy index), is a slice and -- can be only used as constituent of indexing expression. */ #define max_dim 20 /* maximal number of components allowed within parentheses */ CODE *expression_list(MPL *mpl) { CODE *code; OPERANDS arg; struct { char *name; CODE *code; } list[1+max_dim]; int flag_x, next_token, dim, j, slice = 0; xassert(mpl->token == T_LEFT); /* the flag, which allows recognizing undeclared symbolic names as dummy indices, will be automatically reset by get_token(), so save it before scanning the next token */ flag_x = mpl->flag_x; get_token(mpl /* ( */); /* parse */ for (dim = 1; ; dim++) { if (dim > max_dim) error(mpl, "too many components within parentheses"); /* current component of can be either dummy index or expression */ if (mpl->token == T_NAME) { /* symbolic name is recognized as dummy index only if: the flag, which allows that, is set, and the name is followed by comma or right parenthesis, and the name is undeclared */ get_token(mpl /* */); next_token = mpl->token; unget_token(mpl); if (!(flag_x && (next_token == T_COMMA || next_token == T_RIGHT) && avl_find_node(mpl->tree, mpl->image) == NULL)) { /* this is not dummy index */ goto expr; } /* all dummy indices within the same slice must have unique symbolic names */ for (j = 1; j < dim; j++) { if (list[j].name != NULL && strcmp(list[j].name, mpl->image) == 0) error(mpl, "duplicate dummy index %s not allowed", mpl->image); } /* current component of is dummy index */ list[dim].name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(list[dim].name, mpl->image); list[dim].code = NULL; get_token(mpl /* */); /* is a slice, because at least one dummy index has appeared */ slice = 1; /* note that the context ( ) is not allowed, i.e. in this case is considered as a parenthesized expression */ if (dim == 1 && mpl->token == T_RIGHT) error(mpl, "%s not defined", list[dim].name); } else expr: { /* current component of is expression */ code = expression_13(mpl); /* if the current expression is followed by comma or it is not the very first expression, entire is n-tuple or slice, in which case the current expression should be converted to symbolic type, if necessary */ if (mpl->token == T_COMMA || dim > 1) { if (code->type == A_NUMERIC) code = make_unary(mpl, O_CVTSYM, code, A_SYMBOLIC, 0); /* now the expression must be of symbolic type */ if (code->type != A_SYMBOLIC) error(mpl, "component expression has invalid type"); xassert(code->dim == 0); } list[dim].name = NULL; list[dim].code = code; } /* check a token that follows the current component */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_RIGHT) break; else error(mpl, "right parenthesis missing where expected"); } /* generate pseudo-code for */ if (dim == 1 && !slice) { /* is a parenthesized expression */ code = list[1].code; } else if (!slice) { /* is a n-tuple */ arg.list = create_arg_list(mpl); for (j = 1; j <= dim; j++) arg.list = expand_arg_list(mpl, arg.list, list[j].code); code = make_code(mpl, O_TUPLE, &arg, A_TUPLE, dim); } else { /* is a slice */ arg.slice = create_block(mpl); for (j = 1; j <= dim; j++) append_slot(mpl, arg.slice, list[j].name, list[j].code); /* note that actually pseudo-codes with op = O_SLICE are never evaluated */ code = make_code(mpl, O_SLICE, &arg, A_TUPLE, dim); } get_token(mpl /* ) */); /* if is a slice, there must be the keyword 'in', which follows the right parenthesis */ if (slice && mpl->token != T_IN) error(mpl, "keyword in missing where expected"); /* if the slice flag is set and there is the keyword 'in', which follows , the latter must be a slice */ if (flag_x && mpl->token == T_IN && !slice) { if (dim == 1) error(mpl, "syntax error in indexing expression"); else error(mpl, "0-ary slice not allowed"); } return code; } /*---------------------------------------------------------------------- -- literal set - parse literal set. -- -- This routine parses literal set using the syntax: -- -- ::= { } -- ::= -- ::= , -- ::= -- -- It is assumed that the left curly brace and the very first member -- expression that follows it are already parsed. The right curly brace -- remains unscanned on exit. */ CODE *literal_set(MPL *mpl, CODE *code) { OPERANDS arg; int j; xassert(code != NULL); arg.list = create_arg_list(mpl); /* parse */ for (j = 1; ; j++) { /* all member expressions must be n-tuples; so, if the current expression is not n-tuple, convert it to 1-tuple */ if (code->type == A_NUMERIC) code = make_unary(mpl, O_CVTSYM, code, A_SYMBOLIC, 0); if (code->type == A_SYMBOLIC) code = make_unary(mpl, O_CVTTUP, code, A_TUPLE, 1); /* now the expression must be n-tuple */ if (code->type != A_TUPLE) error(mpl, "member expression has invalid type"); /* all member expressions must have identical dimension */ if (arg.list != NULL && arg.list->x->dim != code->dim) error(mpl, "member %d has %d component%s while member %d ha" "s %d component%s", j-1, arg.list->x->dim, arg.list->x->dim == 1 ? "" : "s", j, code->dim, code->dim == 1 ? "" : "s"); /* append the current expression to the member list */ arg.list = expand_arg_list(mpl, arg.list, code); /* check a token that follows the current expression */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_RBRACE) break; else error(mpl, "syntax error in literal set"); /* parse the next expression that follows the comma */ code = expression_5(mpl); } /* generate pseudo-code for */ code = make_code(mpl, O_MAKE, &arg, A_ELEMSET, arg.list->x->dim); return code; } /*---------------------------------------------------------------------- -- indexing_expression - parse indexing expression. -- -- This routine parses indexing expression using the syntax: -- -- ::= -- ::= { } -- ::= { : } -- ::= -- ::= , -- ::= -- ::= in -- ::= in -- ::= -- ::= ( ) -- ::= -- ::= -- -- This routine creates domain for , where each -- domain block corresponds to , and each domain slot -- corresponds to individual indexing position. */ DOMAIN *indexing_expression(MPL *mpl) { DOMAIN *domain; DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; CODE *code; xassert(mpl->token == T_LBRACE); get_token(mpl /* { */); if (mpl->token == T_RBRACE) error(mpl, "empty indexing expression not allowed"); /* create domain to be constructed */ domain = create_domain(mpl); /* parse either or that follows the left brace */ for (;;) { /* domain block for is not created yet */ block = NULL; /* pseudo-code for is not generated yet */ code = NULL; /* check a token, which begins with */ if (mpl->token == T_NAME) { /* it is a symbolic name */ int next_token; char *name; /* symbolic name is recognized as dummy index only if it is followed by the keyword 'in' and not declared */ get_token(mpl /* */); next_token = mpl->token; unget_token(mpl); if (!(next_token == T_IN && avl_find_node(mpl->tree, mpl->image) == NULL)) { /* this is not dummy index; the symbolic name begins an expression, which is either or the very first in */ goto expr; } /* create domain block with one slot, which is assigned the dummy index */ block = create_block(mpl); name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(name, mpl->image); append_slot(mpl, block, name, NULL); get_token(mpl /* */); /* the keyword 'in' is already checked above */ xassert(mpl->token == T_IN); get_token(mpl /* in */); /* that follows the keyword 'in' will be parsed below */ } else if (mpl->token == T_LEFT) { /* it is the left parenthesis; parse expression that begins with this parenthesis (the flag is set in order to allow recognizing slices; see the routine expression_list) */ mpl->flag_x = 1; code = expression_9(mpl); if (code->op != O_SLICE) { /* this is either or the very first in */ goto expr; } /* this is a slice; besides the corresponding domain block is already created by expression_list() */ block = code->arg.slice; code = NULL; /* is not parsed yet */ /* the keyword 'in' following the slice is already checked by expression_list() */ xassert(mpl->token == T_IN); get_token(mpl /* in */); /* that follows the keyword 'in' will be parsed below */ } expr: /* parse expression that follows either the keyword 'in' (in which case it can be as well as the very first in ); note that this expression can be already parsed above */ if (code == NULL) code = expression_9(mpl); /* check the type of the expression just parsed */ if (code->type != A_ELEMSET) { /* it is not and therefore it can only be the very first in ; however, then there must be no dummy index neither slice between the left brace and this expression */ if (block != NULL) error(mpl, "domain expression has invalid type"); /* parse the rest part of and make this set be , i.e. the construction {a, b, c} is parsed as it were written as {A}, where A = {a, b, c} is a temporary elemental set */ code = literal_set(mpl, code); } /* now pseudo-code for has been built */ xassert(code != NULL); xassert(code->type == A_ELEMSET); xassert(code->dim > 0); /* if domain block for the current is still not created, create it for fake slice of the same dimension as */ if (block == NULL) { int j; block = create_block(mpl); for (j = 1; j <= code->dim; j++) append_slot(mpl, block, NULL, NULL); } /* number of indexing positions in must be the same as dimension of n-tuples in basic set */ { int dim = 0; for (slot = block->list; slot != NULL; slot = slot->next) dim++; if (dim != code->dim) error(mpl,"%d %s specified for set of dimension %d", dim, dim == 1 ? "index" : "indices", code->dim); } /* store pseudo-code for in the domain block */ xassert(block->code == NULL); block->code = code; /* and append the domain block to the domain */ append_block(mpl, domain, block); /* the current has been completely parsed; include all its dummy indices into the symbolic name table to make them available for referencing from expressions; implicit declarations of dummy indices remain valid while the corresponding domain scope is valid */ for (slot = block->list; slot != NULL; slot = slot->next) if (slot->name != NULL) { AVLNODE *node; xassert(avl_find_node(mpl->tree, slot->name) == NULL); node = avl_insert_node(mpl->tree, slot->name); avl_set_node_type(node, A_INDEX); avl_set_node_link(node, (void *)slot); } /* check a token that follows */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_COLON || mpl->token == T_RBRACE) break; else error(mpl, "syntax error in indexing expression"); } /* parse that follows the colon */ if (mpl->token == T_COLON) { get_token(mpl /* : */); code = expression_13(mpl); /* convert the expression to logical type, if necessary */ if (code->type == A_SYMBOLIC) code = make_unary(mpl, O_CVTNUM, code, A_NUMERIC, 0); if (code->type == A_NUMERIC) code = make_unary(mpl, O_CVTLOG, code, A_LOGICAL, 0); /* now the expression must be of logical type */ if (code->type != A_LOGICAL) error(mpl, "expression following colon has invalid type"); xassert(code->dim == 0); domain->code = code; /* the right brace must follow the logical expression */ if (mpl->token != T_RBRACE) error(mpl, "syntax error in indexing expression"); } get_token(mpl /* } */); return domain; } /*---------------------------------------------------------------------- -- close_scope - close scope of indexing expression. -- -- The routine closes the scope of indexing expression specified by its -- domain and thereby makes all dummy indices introduced in the indexing -- expression no longer available for referencing. */ void close_scope(MPL *mpl, DOMAIN *domain) { DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; AVLNODE *node; xassert(domain != NULL); /* remove all dummy indices from the symbolic names table */ for (block = domain->list; block != NULL; block = block->next) { for (slot = block->list; slot != NULL; slot = slot->next) { if (slot->name != NULL) { node = avl_find_node(mpl->tree, slot->name); xassert(node != NULL); xassert(avl_get_node_type(node) == A_INDEX); avl_delete_node(mpl->tree, node); } } } return; } /*---------------------------------------------------------------------- -- iterated_expression - parse iterated expression. -- -- This routine parses primary expression using the syntax: -- -- ::= -- ::= sum -- ::= prod -- ::= min -- ::= max -- ::= exists -- -- ::= forall -- -- ::= setof -- -- Note that parsing "integrand" depends on the iterated operator. */ #if 1 /* 07/IX-2008 */ static void link_up(CODE *code) { /* if we have something like sum{(i+1,j,k-1) in E} x[i,j,k], where i and k are dummy indices defined out of the iterated expression, we should link up pseudo-code for computing i+1 and k-1 to pseudo-code for computing the iterated expression; this is needed to invalidate current value of the iterated expression once i or k have been changed */ DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; for (block = code->arg.loop.domain->list; block != NULL; block = block->next) { for (slot = block->list; slot != NULL; slot = slot->next) { if (slot->code != NULL) { xassert(slot->code->up == NULL); slot->code->up = code; } } } return; } #endif CODE *iterated_expression(MPL *mpl) { CODE *code; OPERANDS arg; int op; char opstr[8]; /* determine operation code */ xassert(mpl->token == T_NAME); if (strcmp(mpl->image, "sum") == 0) op = O_SUM; else if (strcmp(mpl->image, "prod") == 0) op = O_PROD; else if (strcmp(mpl->image, "min") == 0) op = O_MINIMUM; else if (strcmp(mpl->image, "max") == 0) op = O_MAXIMUM; else if (strcmp(mpl->image, "forall") == 0) op = O_FORALL; else if (strcmp(mpl->image, "exists") == 0) op = O_EXISTS; else if (strcmp(mpl->image, "setof") == 0) op = O_SETOF; else error(mpl, "operator %s unknown", mpl->image); strcpy(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); get_token(mpl /* */); /* check the left brace that follows the operator name */ xassert(mpl->token == T_LBRACE); /* parse indexing expression that controls iterating */ arg.loop.domain = indexing_expression(mpl); /* parse "integrand" expression and generate pseudo-code */ switch (op) { case O_SUM: case O_PROD: case O_MINIMUM: case O_MAXIMUM: arg.loop.x = expression_3(mpl); /* convert the integrand to numeric type, if necessary */ if (arg.loop.x->type == A_SYMBOLIC) arg.loop.x = make_unary(mpl, O_CVTNUM, arg.loop.x, A_NUMERIC, 0); /* now the integrand must be of numeric type or linear form (the latter is only allowed for the sum operator) */ if (!(arg.loop.x->type == A_NUMERIC || op == O_SUM && arg.loop.x->type == A_FORMULA)) err: error(mpl, "integrand following %s{...} has invalid type" , opstr); xassert(arg.loop.x->dim == 0); /* generate pseudo-code */ code = make_code(mpl, op, &arg, arg.loop.x->type, 0); break; case O_FORALL: case O_EXISTS: arg.loop.x = expression_12(mpl); /* convert the integrand to logical type, if necessary */ if (arg.loop.x->type == A_SYMBOLIC) arg.loop.x = make_unary(mpl, O_CVTNUM, arg.loop.x, A_NUMERIC, 0); if (arg.loop.x->type == A_NUMERIC) arg.loop.x = make_unary(mpl, O_CVTLOG, arg.loop.x, A_LOGICAL, 0); /* now the integrand must be of logical type */ if (arg.loop.x->type != A_LOGICAL) goto err; xassert(arg.loop.x->dim == 0); /* generate pseudo-code */ code = make_code(mpl, op, &arg, A_LOGICAL, 0); break; case O_SETOF: arg.loop.x = expression_5(mpl); /* convert the integrand to 1-tuple, if necessary */ if (arg.loop.x->type == A_NUMERIC) arg.loop.x = make_unary(mpl, O_CVTSYM, arg.loop.x, A_SYMBOLIC, 0); if (arg.loop.x->type == A_SYMBOLIC) arg.loop.x = make_unary(mpl, O_CVTTUP, arg.loop.x, A_TUPLE, 1); /* now the integrand must be n-tuple */ if (arg.loop.x->type != A_TUPLE) goto err; xassert(arg.loop.x->dim > 0); /* generate pseudo-code */ code = make_code(mpl, op, &arg, A_ELEMSET, arg.loop.x->dim); break; default: xassert(op != op); } /* close the scope of the indexing expression */ close_scope(mpl, arg.loop.domain); #if 1 /* 07/IX-2008 */ link_up(code); #endif return code; } /*---------------------------------------------------------------------- -- domain_arity - determine arity of domain. -- -- This routine returns arity of specified domain, which is number of -- its free dummy indices. */ int domain_arity(MPL *mpl, DOMAIN *domain) { DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; int arity; xassert(mpl == mpl); arity = 0; for (block = domain->list; block != NULL; block = block->next) for (slot = block->list; slot != NULL; slot = slot->next) if (slot->code == NULL) arity++; return arity; } /*---------------------------------------------------------------------- -- set_expression - parse set expression. -- -- This routine parses primary expression using the syntax: -- -- ::= { } -- ::= */ CODE *set_expression(MPL *mpl) { CODE *code; OPERANDS arg; xassert(mpl->token == T_LBRACE); get_token(mpl /* { */); /* check a token that follows the left brace */ if (mpl->token == T_RBRACE) { /* it is the right brace, so the resultant is an empty set of dimension 1 */ arg.list = NULL; /* generate pseudo-code to build the resultant set */ code = make_code(mpl, O_MAKE, &arg, A_ELEMSET, 1); get_token(mpl /* } */); } else { /* the next token begins an indexing expression */ unget_token(mpl); arg.loop.domain = indexing_expression(mpl); arg.loop.x = NULL; /* integrand is not used */ /* close the scope of the indexing expression */ close_scope(mpl, arg.loop.domain); /* generate pseudo-code to build the resultant set */ code = make_code(mpl, O_BUILD, &arg, A_ELEMSET, domain_arity(mpl, arg.loop.domain)); #if 1 /* 07/IX-2008 */ link_up(code); #endif } return code; } /*---------------------------------------------------------------------- -- branched_expression - parse conditional expression. -- -- This routine parses primary expression using the syntax: -- -- ::= -- ::= if then -- ::= if then -- else -- ::= */ CODE *branched_expression(MPL *mpl) { CODE *code, *x, *y, *z; xassert(mpl->token == T_IF); get_token(mpl /* if */); /* parse that follows 'if' */ x = expression_13(mpl); /* convert the expression to logical type, if necessary */ if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); /* now the expression must be of logical type */ if (x->type != A_LOGICAL) error(mpl, "expression following if has invalid type"); xassert(x->dim == 0); /* the keyword 'then' must follow the logical expression */ if (mpl->token != T_THEN) error(mpl, "keyword then missing where expected"); get_token(mpl /* then */); /* parse that follows 'then' and check its type */ y = expression_9(mpl); if (!(y->type == A_NUMERIC || y->type == A_SYMBOLIC || y->type == A_ELEMSET || y->type == A_FORMULA)) error(mpl, "expression following then has invalid type"); /* if the expression that follows the keyword 'then' is elemental set, the keyword 'else' cannot be omitted; otherwise else-part is optional */ if (mpl->token != T_ELSE) { if (y->type == A_ELEMSET) error(mpl, "keyword else missing where expected"); z = NULL; goto skip; } get_token(mpl /* else */); /* parse that follow 'else' and check its type */ z = expression_9(mpl); if (!(z->type == A_NUMERIC || z->type == A_SYMBOLIC || z->type == A_ELEMSET || z->type == A_FORMULA)) error(mpl, "expression following else has invalid type"); /* convert to identical types, if necessary */ if (y->type == A_FORMULA || z->type == A_FORMULA) { if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type == A_NUMERIC) y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); if (z->type == A_SYMBOLIC) z = make_unary(mpl, O_CVTNUM, z, A_NUMERIC, 0); if (z->type == A_NUMERIC) z = make_unary(mpl, O_CVTLFM, z, A_FORMULA, 0); } if (y->type == A_SYMBOLIC || z->type == A_SYMBOLIC) { if (y->type == A_NUMERIC) y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); if (z->type == A_NUMERIC) z = make_unary(mpl, O_CVTSYM, z, A_SYMBOLIC, 0); } /* now both expressions must have identical types */ if (y->type != z->type) error(mpl, "expressions following then and else have incompati" "ble types"); /* and identical dimensions */ if (y->dim != z->dim) error(mpl, "expressions following then and else have different" " dimensions %d and %d, respectively", y->dim, z->dim); skip: /* generate pseudo-code to perform branching */ code = make_ternary(mpl, O_FORK, x, y, z, y->type, y->dim); return code; } /*---------------------------------------------------------------------- -- primary_expression - parse primary expression. -- -- This routine parses primary expression using the syntax: -- -- ::= -- ::= Infinity -- ::= -- ::= -- ::= -- ::= [ ] -- ::= -- ::= [ ] -- ::= -- ::= [ ] -- ::= ( ) -- ::= ( ) -- ::= -- ::= { } -- ::= -- ::= -- -- For complete list of syntactic rules for see -- comments to the corresponding parsing routines. */ CODE *primary_expression(MPL *mpl) { CODE *code; if (mpl->token == T_NUMBER) { /* parse numeric literal */ code = numeric_literal(mpl); } #if 1 /* 21/VII-2006 */ else if (mpl->token == T_INFINITY) { /* parse "infinity" */ OPERANDS arg; arg.num = DBL_MAX; code = make_code(mpl, O_NUMBER, &arg, A_NUMERIC, 0); get_token(mpl /* Infinity */); } #endif else if (mpl->token == T_STRING) { /* parse string literal */ code = string_literal(mpl); } else if (mpl->token == T_NAME) { int next_token; get_token(mpl /* */); next_token = mpl->token; unget_token(mpl); /* check a token that follows */ switch (next_token) { case T_LBRACKET: /* parse reference to subscripted object */ code = object_reference(mpl); break; case T_LEFT: /* parse reference to built-in function */ code = function_reference(mpl); break; case T_LBRACE: /* parse iterated expression */ code = iterated_expression(mpl); break; default: /* parse reference to unsubscripted object */ code = object_reference(mpl); break; } } else if (mpl->token == T_LEFT) { /* parse parenthesized expression */ code = expression_list(mpl); } else if (mpl->token == T_LBRACE) { /* parse set expression */ code = set_expression(mpl); } else if (mpl->token == T_IF) { /* parse conditional expression */ code = branched_expression(mpl); } else if (is_reserved(mpl)) { /* other reserved keywords cannot be used here */ error(mpl, "invalid use of reserved keyword %s", mpl->image); } else error(mpl, "syntax error in expression"); return code; } /*---------------------------------------------------------------------- -- error_preceding - raise error if preceding operand has wrong type. -- -- This routine is called to raise error if operand that precedes some -- infix operator has invalid type. */ void error_preceding(MPL *mpl, char *opstr) { error(mpl, "operand preceding %s has invalid type", opstr); /* no return */ } /*---------------------------------------------------------------------- -- error_following - raise error if following operand has wrong type. -- -- This routine is called to raise error if operand that follows some -- infix operator has invalid type. */ void error_following(MPL *mpl, char *opstr) { error(mpl, "operand following %s has invalid type", opstr); /* no return */ } /*---------------------------------------------------------------------- -- error_dimension - raise error if operands have different dimension. -- -- This routine is called to raise error if two operands of some infix -- operator have different dimension. */ void error_dimension(MPL *mpl, char *opstr, int dim1, int dim2) { error(mpl, "operands preceding and following %s have different di" "mensions %d and %d, respectively", opstr, dim1, dim2); /* no return */ } /*---------------------------------------------------------------------- -- expression_0 - parse expression of level 0. -- -- This routine parses expression of level 0 using the syntax: -- -- ::= */ CODE *expression_0(MPL *mpl) { CODE *code; code = primary_expression(mpl); return code; } /*---------------------------------------------------------------------- -- expression_1 - parse expression of level 1. -- -- This routine parses expression of level 1 using the syntax: -- -- ::= -- ::= -- ::= -- ::= ^ | ** */ CODE *expression_1(MPL *mpl) { CODE *x, *y; char opstr[8]; x = expression_0(mpl); if (mpl->token == T_POWER) { strcpy(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type != A_NUMERIC) error_preceding(mpl, opstr); get_token(mpl /* ^ | ** */); if (mpl->token == T_PLUS || mpl->token == T_MINUS) y = expression_2(mpl); else y = expression_1(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type != A_NUMERIC) error_following(mpl, opstr); x = make_binary(mpl, O_POWER, x, y, A_NUMERIC, 0); } return x; } /*---------------------------------------------------------------------- -- expression_2 - parse expression of level 2. -- -- This routine parses expression of level 2 using the syntax: -- -- ::= -- ::= + -- ::= - */ CODE *expression_2(MPL *mpl) { CODE *x; if (mpl->token == T_PLUS) { get_token(mpl /* + */); x = expression_1(mpl); if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) error_following(mpl, "+"); x = make_unary(mpl, O_PLUS, x, x->type, 0); } else if (mpl->token == T_MINUS) { get_token(mpl /* - */); x = expression_1(mpl); if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) error_following(mpl, "-"); x = make_unary(mpl, O_MINUS, x, x->type, 0); } else x = expression_1(mpl); return x; } /*---------------------------------------------------------------------- -- expression_3 - parse expression of level 3. -- -- This routine parses expression of level 3 using the syntax: -- -- ::= -- ::= * -- ::= / -- ::= div -- ::= mod */ CODE *expression_3(MPL *mpl) { CODE *x, *y; x = expression_2(mpl); for (;;) { if (mpl->token == T_ASTERISK) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) error_preceding(mpl, "*"); get_token(mpl /* * */); y = expression_2(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) error_following(mpl, "*"); if (x->type == A_FORMULA && y->type == A_FORMULA) error(mpl, "multiplication of linear forms not allowed"); if (x->type == A_NUMERIC && y->type == A_NUMERIC) x = make_binary(mpl, O_MUL, x, y, A_NUMERIC, 0); else x = make_binary(mpl, O_MUL, x, y, A_FORMULA, 0); } else if (mpl->token == T_SLASH) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) error_preceding(mpl, "/"); get_token(mpl /* / */); y = expression_2(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type != A_NUMERIC) error_following(mpl, "/"); if (x->type == A_NUMERIC) x = make_binary(mpl, O_DIV, x, y, A_NUMERIC, 0); else x = make_binary(mpl, O_DIV, x, y, A_FORMULA, 0); } else if (mpl->token == T_DIV) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type != A_NUMERIC) error_preceding(mpl, "div"); get_token(mpl /* div */); y = expression_2(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type != A_NUMERIC) error_following(mpl, "div"); x = make_binary(mpl, O_IDIV, x, y, A_NUMERIC, 0); } else if (mpl->token == T_MOD) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type != A_NUMERIC) error_preceding(mpl, "mod"); get_token(mpl /* mod */); y = expression_2(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type != A_NUMERIC) error_following(mpl, "mod"); x = make_binary(mpl, O_MOD, x, y, A_NUMERIC, 0); } else break; } return x; } /*---------------------------------------------------------------------- -- expression_4 - parse expression of level 4. -- -- This routine parses expression of level 4 using the syntax: -- -- ::= -- ::= + -- ::= - -- ::= less */ CODE *expression_4(MPL *mpl) { CODE *x, *y; x = expression_3(mpl); for (;;) { if (mpl->token == T_PLUS) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) error_preceding(mpl, "+"); get_token(mpl /* + */); y = expression_3(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) error_following(mpl, "+"); if (x->type == A_NUMERIC && y->type == A_FORMULA) x = make_unary(mpl, O_CVTLFM, x, A_FORMULA, 0); if (x->type == A_FORMULA && y->type == A_NUMERIC) y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); x = make_binary(mpl, O_ADD, x, y, x->type, 0); } else if (mpl->token == T_MINUS) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (!(x->type == A_NUMERIC || x->type == A_FORMULA)) error_preceding(mpl, "-"); get_token(mpl /* - */); y = expression_3(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (!(y->type == A_NUMERIC || y->type == A_FORMULA)) error_following(mpl, "-"); if (x->type == A_NUMERIC && y->type == A_FORMULA) x = make_unary(mpl, O_CVTLFM, x, A_FORMULA, 0); if (x->type == A_FORMULA && y->type == A_NUMERIC) y = make_unary(mpl, O_CVTLFM, y, A_FORMULA, 0); x = make_binary(mpl, O_SUB, x, y, x->type, 0); } else if (mpl->token == T_LESS) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type != A_NUMERIC) error_preceding(mpl, "less"); get_token(mpl /* less */); y = expression_3(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type != A_NUMERIC) error_following(mpl, "less"); x = make_binary(mpl, O_LESS, x, y, A_NUMERIC, 0); } else break; } return x; } /*---------------------------------------------------------------------- -- expression_5 - parse expression of level 5. -- -- This routine parses expression of level 5 using the syntax: -- -- ::= -- ::= & */ CODE *expression_5(MPL *mpl) { CODE *x, *y; x = expression_4(mpl); for (;;) { if (mpl->token == T_CONCAT) { if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); if (x->type != A_SYMBOLIC) error_preceding(mpl, "&"); get_token(mpl /* & */); y = expression_4(mpl); if (y->type == A_NUMERIC) y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); if (y->type != A_SYMBOLIC) error_following(mpl, "&"); x = make_binary(mpl, O_CONCAT, x, y, A_SYMBOLIC, 0); } else break; } return x; } /*---------------------------------------------------------------------- -- expression_6 - parse expression of level 6. -- -- This routine parses expression of level 6 using the syntax: -- -- ::= -- ::= .. -- ::= .. by -- */ CODE *expression_6(MPL *mpl) { CODE *x, *y, *z; x = expression_5(mpl); if (mpl->token == T_DOTS) { if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type != A_NUMERIC) error_preceding(mpl, ".."); get_token(mpl /* .. */); y = expression_5(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type != A_NUMERIC) error_following(mpl, ".."); if (mpl->token == T_BY) { get_token(mpl /* by */); z = expression_5(mpl); if (z->type == A_SYMBOLIC) z = make_unary(mpl, O_CVTNUM, z, A_NUMERIC, 0); if (z->type != A_NUMERIC) error_following(mpl, "by"); } else z = NULL; x = make_ternary(mpl, O_DOTS, x, y, z, A_ELEMSET, 1); } return x; } /*---------------------------------------------------------------------- -- expression_7 - parse expression of level 7. -- -- This routine parses expression of level 7 using the syntax: -- -- ::= -- ::= cross */ CODE *expression_7(MPL *mpl) { CODE *x, *y; x = expression_6(mpl); for (;;) { if (mpl->token == T_CROSS) { if (x->type != A_ELEMSET) error_preceding(mpl, "cross"); get_token(mpl /* cross */); y = expression_6(mpl); if (y->type != A_ELEMSET) error_following(mpl, "cross"); x = make_binary(mpl, O_CROSS, x, y, A_ELEMSET, x->dim + y->dim); } else break; } return x; } /*---------------------------------------------------------------------- -- expression_8 - parse expression of level 8. -- -- This routine parses expression of level 8 using the syntax: -- -- ::= -- ::= inter */ CODE *expression_8(MPL *mpl) { CODE *x, *y; x = expression_7(mpl); for (;;) { if (mpl->token == T_INTER) { if (x->type != A_ELEMSET) error_preceding(mpl, "inter"); get_token(mpl /* inter */); y = expression_7(mpl); if (y->type != A_ELEMSET) error_following(mpl, "inter"); if (x->dim != y->dim) error_dimension(mpl, "inter", x->dim, y->dim); x = make_binary(mpl, O_INTER, x, y, A_ELEMSET, x->dim); } else break; } return x; } /*---------------------------------------------------------------------- -- expression_9 - parse expression of level 9. -- -- This routine parses expression of level 9 using the syntax: -- -- ::= -- ::= union -- ::= diff -- ::= symdiff */ CODE *expression_9(MPL *mpl) { CODE *x, *y; x = expression_8(mpl); for (;;) { if (mpl->token == T_UNION) { if (x->type != A_ELEMSET) error_preceding(mpl, "union"); get_token(mpl /* union */); y = expression_8(mpl); if (y->type != A_ELEMSET) error_following(mpl, "union"); if (x->dim != y->dim) error_dimension(mpl, "union", x->dim, y->dim); x = make_binary(mpl, O_UNION, x, y, A_ELEMSET, x->dim); } else if (mpl->token == T_DIFF) { if (x->type != A_ELEMSET) error_preceding(mpl, "diff"); get_token(mpl /* diff */); y = expression_8(mpl); if (y->type != A_ELEMSET) error_following(mpl, "diff"); if (x->dim != y->dim) error_dimension(mpl, "diff", x->dim, y->dim); x = make_binary(mpl, O_DIFF, x, y, A_ELEMSET, x->dim); } else if (mpl->token == T_SYMDIFF) { if (x->type != A_ELEMSET) error_preceding(mpl, "symdiff"); get_token(mpl /* symdiff */); y = expression_8(mpl); if (y->type != A_ELEMSET) error_following(mpl, "symdiff"); if (x->dim != y->dim) error_dimension(mpl, "symdiff", x->dim, y->dim); x = make_binary(mpl, O_SYMDIFF, x, y, A_ELEMSET, x->dim); } else break; } return x; } /*---------------------------------------------------------------------- -- expression_10 - parse expression of level 10. -- -- This routine parses expression of level 10 using the syntax: -- -- ::= -- ::= -- ::= < | <= | = | == | >= | > | <> | != | in | not in | ! in | -- within | not within | ! within */ CODE *expression_10(MPL *mpl) { CODE *x, *y; int op = -1; char opstr[16]; x = expression_9(mpl); strcpy(opstr, ""); switch (mpl->token) { case T_LT: op = O_LT; break; case T_LE: op = O_LE; break; case T_EQ: op = O_EQ; break; case T_GE: op = O_GE; break; case T_GT: op = O_GT; break; case T_NE: op = O_NE; break; case T_IN: op = O_IN; break; case T_WITHIN: op = O_WITHIN; break; case T_NOT: strcpy(opstr, mpl->image); get_token(mpl /* not | ! */); if (mpl->token == T_IN) op = O_NOTIN; else if (mpl->token == T_WITHIN) op = O_NOTWITHIN; else error(mpl, "invalid use of %s", opstr); strcat(opstr, " "); break; default: goto done; } strcat(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); switch (op) { case O_EQ: case O_NE: #if 1 /* 02/VIII-2008 */ case O_LT: case O_LE: case O_GT: case O_GE: #endif if (!(x->type == A_NUMERIC || x->type == A_SYMBOLIC)) error_preceding(mpl, opstr); get_token(mpl /* */); y = expression_9(mpl); if (!(y->type == A_NUMERIC || y->type == A_SYMBOLIC)) error_following(mpl, opstr); if (x->type == A_NUMERIC && y->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); if (x->type == A_SYMBOLIC && y->type == A_NUMERIC) y = make_unary(mpl, O_CVTSYM, y, A_SYMBOLIC, 0); x = make_binary(mpl, op, x, y, A_LOGICAL, 0); break; #if 0 /* 02/VIII-2008 */ case O_LT: case O_LE: case O_GT: case O_GE: if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type != A_NUMERIC) error_preceding(mpl, opstr); get_token(mpl /* */); y = expression_9(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type != A_NUMERIC) error_following(mpl, opstr); x = make_binary(mpl, op, x, y, A_LOGICAL, 0); break; #endif case O_IN: case O_NOTIN: if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTSYM, x, A_SYMBOLIC, 0); if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTTUP, x, A_TUPLE, 1); if (x->type != A_TUPLE) error_preceding(mpl, opstr); get_token(mpl /* */); y = expression_9(mpl); if (y->type != A_ELEMSET) error_following(mpl, opstr); if (x->dim != y->dim) error_dimension(mpl, opstr, x->dim, y->dim); x = make_binary(mpl, op, x, y, A_LOGICAL, 0); break; case O_WITHIN: case O_NOTWITHIN: if (x->type != A_ELEMSET) error_preceding(mpl, opstr); get_token(mpl /* */); y = expression_9(mpl); if (y->type != A_ELEMSET) error_following(mpl, opstr); if (x->dim != y->dim) error_dimension(mpl, opstr, x->dim, y->dim); x = make_binary(mpl, op, x, y, A_LOGICAL, 0); break; default: xassert(op != op); } done: return x; } /*---------------------------------------------------------------------- -- expression_11 - parse expression of level 11. -- -- This routine parses expression of level 11 using the syntax: -- -- ::= -- ::= not -- ::= ! */ CODE *expression_11(MPL *mpl) { CODE *x; char opstr[8]; if (mpl->token == T_NOT) { strcpy(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); get_token(mpl /* not | ! */); x = expression_10(mpl); if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); if (x->type != A_LOGICAL) error_following(mpl, opstr); x = make_unary(mpl, O_NOT, x, A_LOGICAL, 0); } else x = expression_10(mpl); return x; } /*---------------------------------------------------------------------- -- expression_12 - parse expression of level 12. -- -- This routine parses expression of level 12 using the syntax: -- -- ::= -- ::= and -- ::= && */ CODE *expression_12(MPL *mpl) { CODE *x, *y; char opstr[8]; x = expression_11(mpl); for (;;) { if (mpl->token == T_AND) { strcpy(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); if (x->type != A_LOGICAL) error_preceding(mpl, opstr); get_token(mpl /* and | && */); y = expression_11(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type == A_NUMERIC) y = make_unary(mpl, O_CVTLOG, y, A_LOGICAL, 0); if (y->type != A_LOGICAL) error_following(mpl, opstr); x = make_binary(mpl, O_AND, x, y, A_LOGICAL, 0); } else break; } return x; } /*---------------------------------------------------------------------- -- expression_13 - parse expression of level 13. -- -- This routine parses expression of level 13 using the syntax: -- -- ::= -- ::= or -- ::= || */ CODE *expression_13(MPL *mpl) { CODE *x, *y; char opstr[8]; x = expression_12(mpl); for (;;) { if (mpl->token == T_OR) { strcpy(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); if (x->type == A_SYMBOLIC) x = make_unary(mpl, O_CVTNUM, x, A_NUMERIC, 0); if (x->type == A_NUMERIC) x = make_unary(mpl, O_CVTLOG, x, A_LOGICAL, 0); if (x->type != A_LOGICAL) error_preceding(mpl, opstr); get_token(mpl /* or | || */); y = expression_12(mpl); if (y->type == A_SYMBOLIC) y = make_unary(mpl, O_CVTNUM, y, A_NUMERIC, 0); if (y->type == A_NUMERIC) y = make_unary(mpl, O_CVTLOG, y, A_LOGICAL, 0); if (y->type != A_LOGICAL) error_following(mpl, opstr); x = make_binary(mpl, O_OR, x, y, A_LOGICAL, 0); } else break; } return x; } /*---------------------------------------------------------------------- -- set_statement - parse set statement. -- -- This routine parses set statement using the syntax: -- -- ::= set -- ; -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= , dimen -- ::= , within -- ::= , := -- ::= , default -- -- Commae in are optional and may be omitted anywhere. */ SET *set_statement(MPL *mpl) { SET *set; int dimen_used = 0; xassert(is_keyword(mpl, "set")); get_token(mpl /* set */); /* symbolic name must follow the keyword 'set' */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "symbolic name missing where expected"); /* there must be no other object with the same name */ if (avl_find_node(mpl->tree, mpl->image) != NULL) error(mpl, "%s multiply declared", mpl->image); /* create model set */ set = alloc(SET); set->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(set->name, mpl->image); set->alias = NULL; set->dim = 0; set->domain = NULL; set->dimen = 0; set->within = NULL; set->assign = NULL; set->option = NULL; set->gadget = NULL; set->data = 0; set->array = NULL; get_token(mpl /* */); /* parse optional alias */ if (mpl->token == T_STRING) { set->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(set->alias, mpl->image); get_token(mpl /* */); } /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { set->domain = indexing_expression(mpl); set->dim = domain_arity(mpl, set->domain); } /* include the set name in the symbolic names table */ { AVLNODE *node; node = avl_insert_node(mpl->tree, set->name); avl_set_node_type(node, A_SET); avl_set_node_link(node, (void *)set); } /* parse the list of optional attributes */ for (;;) { if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_SEMICOLON) break; if (is_keyword(mpl, "dimen")) { /* dimension of set members */ int dimen; get_token(mpl /* dimen */); if (!(mpl->token == T_NUMBER && 1.0 <= mpl->value && mpl->value <= 20.0 && floor(mpl->value) == mpl->value)) error(mpl, "dimension must be integer between 1 and 20"); dimen = (int)(mpl->value + 0.5); if (dimen_used) error(mpl, "at most one dimension attribute allowed"); if (set->dimen > 0) error(mpl, "dimension %d conflicts with dimension %d alr" "eady determined", dimen, set->dimen); set->dimen = dimen; dimen_used = 1; get_token(mpl /* */); } else if (mpl->token == T_WITHIN || mpl->token == T_IN) { /* restricting superset */ WITHIN *within, *temp; if (mpl->token == T_IN && !mpl->as_within) { warning(mpl, "keyword in understood as within"); mpl->as_within = 1; } get_token(mpl /* within */); /* create new restricting superset list entry and append it to the within-list */ within = alloc(WITHIN); within->code = NULL; within->next = NULL; if (set->within == NULL) set->within = within; else { for (temp = set->within; temp->next != NULL; temp = temp->next); temp->next = within; } /* parse an expression that follows 'within' */ within->code = expression_9(mpl); if (within->code->type != A_ELEMSET) error(mpl, "expression following within has invalid type" ); xassert(within->code->dim > 0); /* check/set dimension of set members */ if (set->dimen == 0) set->dimen = within->code->dim; if (set->dimen != within->code->dim) error(mpl, "set expression following within must have di" "mension %d rather than %d", set->dimen, within->code->dim); } else if (mpl->token == T_ASSIGN) { /* assignment expression */ if (!(set->assign == NULL && set->option == NULL && set->gadget == NULL)) err: error(mpl, "at most one := or default/data allowed"); get_token(mpl /* := */); /* parse an expression that follows ':=' */ set->assign = expression_9(mpl); if (set->assign->type != A_ELEMSET) error(mpl, "expression following := has invalid type"); xassert(set->assign->dim > 0); /* check/set dimension of set members */ if (set->dimen == 0) set->dimen = set->assign->dim; if (set->dimen != set->assign->dim) error(mpl, "set expression following := must have dimens" "ion %d rather than %d", set->dimen, set->assign->dim); } else if (is_keyword(mpl, "default")) { /* expression for default value */ if (!(set->assign == NULL && set->option == NULL)) goto err; get_token(mpl /* := */); /* parse an expression that follows 'default' */ set->option = expression_9(mpl); if (set->option->type != A_ELEMSET) error(mpl, "expression following default has invalid typ" "e"); xassert(set->option->dim > 0); /* check/set dimension of set members */ if (set->dimen == 0) set->dimen = set->option->dim; if (set->dimen != set->option->dim) error(mpl, "set expression following default must have d" "imension %d rather than %d", set->dimen, set->option->dim); } #if 1 /* 12/XII-2008 */ else if (is_keyword(mpl, "data")) { /* gadget to initialize the set by data from plain set */ GADGET *gadget; AVLNODE *node; int i, k, fff[20]; if (!(set->assign == NULL && set->gadget == NULL)) goto err; get_token(mpl /* data */); set->gadget = gadget = alloc(GADGET); /* set name must follow the keyword 'data' */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "set name missing where expected"); /* find the set in the symbolic name table */ node = avl_find_node(mpl->tree, mpl->image); if (node == NULL) error(mpl, "%s not defined", mpl->image); if (avl_get_node_type(node) != A_SET) err1: error(mpl, "%s not a plain set", mpl->image); gadget->set = avl_get_node_link(node); if (gadget->set->dim != 0) goto err1; if (gadget->set == set) error(mpl, "set cannot be initialized by itself"); /* check and set dimensions */ if (set->dim >= gadget->set->dimen) err2: error(mpl, "dimension of %s too small", mpl->image); if (set->dimen == 0) set->dimen = gadget->set->dimen - set->dim; if (set->dim + set->dimen > gadget->set->dimen) goto err2; else if (set->dim + set->dimen < gadget->set->dimen) error(mpl, "dimension of %s too big", mpl->image); get_token(mpl /* set name */); /* left parenthesis must follow the set name */ if (mpl->token == T_LEFT) get_token(mpl /* ( */); else error(mpl, "left parenthesis missing where expected"); /* parse permutation of component numbers */ for (k = 0; k < gadget->set->dimen; k++) fff[k] = 0; k = 0; for (;;) { if (mpl->token != T_NUMBER) error(mpl, "component number missing where expected"); if (str2int(mpl->image, &i) != 0) err3: error(mpl, "component number must be integer between " "1 and %d", gadget->set->dimen); if (!(1 <= i && i <= gadget->set->dimen)) goto err3; if (fff[i-1] != 0) error(mpl, "component %d multiply specified", i); gadget->ind[k++] = i, fff[i-1] = 1; xassert(k <= gadget->set->dimen); get_token(mpl /* number */); if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_RIGHT) break; else error(mpl, "syntax error in data attribute"); } if (k < gadget->set->dimen) error(mpl, "there are must be %d components rather than " "%d", gadget->set->dimen, k); get_token(mpl /* ) */); } #endif else error(mpl, "syntax error in set statement"); } /* close the domain scope */ if (set->domain != NULL) close_scope(mpl, set->domain); /* if dimension of set members is still unknown, set it to 1 */ if (set->dimen == 0) set->dimen = 1; /* the set statement has been completely parsed */ xassert(mpl->token == T_SEMICOLON); get_token(mpl /* ; */); return set; } /*---------------------------------------------------------------------- -- parameter_statement - parse parameter statement. -- -- This routine parses parameter statement using the syntax: -- -- ::= param -- ; -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= , integer -- ::= , binary -- ::= , symbolic -- ::= , -- ::= , in -- ::= , := -- ::= , default -- ::= < | <= | = | == | >= | > | <> | != -- -- Commae in are optional and may be omitted anywhere. */ PARAMETER *parameter_statement(MPL *mpl) { PARAMETER *par; int integer_used = 0, binary_used = 0, symbolic_used = 0; xassert(is_keyword(mpl, "param")); get_token(mpl /* param */); /* symbolic name must follow the keyword 'param' */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "symbolic name missing where expected"); /* there must be no other object with the same name */ if (avl_find_node(mpl->tree, mpl->image) != NULL) error(mpl, "%s multiply declared", mpl->image); /* create model parameter */ par = alloc(PARAMETER); par->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(par->name, mpl->image); par->alias = NULL; par->dim = 0; par->domain = NULL; par->type = A_NUMERIC; par->cond = NULL; par->in = NULL; par->assign = NULL; par->option = NULL; par->data = 0; par->defval = NULL; par->array = NULL; get_token(mpl /* */); /* parse optional alias */ if (mpl->token == T_STRING) { par->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(par->alias, mpl->image); get_token(mpl /* */); } /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { par->domain = indexing_expression(mpl); par->dim = domain_arity(mpl, par->domain); } /* include the parameter name in the symbolic names table */ { AVLNODE *node; node = avl_insert_node(mpl->tree, par->name); avl_set_node_type(node, A_PARAMETER); avl_set_node_link(node, (void *)par); } /* parse the list of optional attributes */ for (;;) { if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_SEMICOLON) break; if (is_keyword(mpl, "integer")) { if (integer_used) error(mpl, "at most one integer allowed"); if (par->type == A_SYMBOLIC) error(mpl, "symbolic parameter cannot be integer"); if (par->type != A_BINARY) par->type = A_INTEGER; integer_used = 1; get_token(mpl /* integer */); } else if (is_keyword(mpl, "binary")) bin: { if (binary_used) error(mpl, "at most one binary allowed"); if (par->type == A_SYMBOLIC) error(mpl, "symbolic parameter cannot be binary"); par->type = A_BINARY; binary_used = 1; get_token(mpl /* binary */); } else if (is_keyword(mpl, "logical")) { if (!mpl->as_binary) { warning(mpl, "keyword logical understood as binary"); mpl->as_binary = 1; } goto bin; } else if (is_keyword(mpl, "symbolic")) { if (symbolic_used) error(mpl, "at most one symbolic allowed"); if (par->type != A_NUMERIC) error(mpl, "integer or binary parameter cannot be symbol" "ic"); /* the parameter may be referenced from expressions given in the same parameter declaration, so its type must be completed before parsing that expressions */ if (!(par->cond == NULL && par->in == NULL && par->assign == NULL && par->option == NULL)) error(mpl, "keyword symbolic must precede any other para" "meter attributes"); par->type = A_SYMBOLIC; symbolic_used = 1; get_token(mpl /* symbolic */); } else if (mpl->token == T_LT || mpl->token == T_LE || mpl->token == T_EQ || mpl->token == T_GE || mpl->token == T_GT || mpl->token == T_NE) { /* restricting condition */ CONDITION *cond, *temp; char opstr[8]; /* create new restricting condition list entry and append it to the conditions list */ cond = alloc(CONDITION); switch (mpl->token) { case T_LT: cond->rho = O_LT, strcpy(opstr, mpl->image); break; case T_LE: cond->rho = O_LE, strcpy(opstr, mpl->image); break; case T_EQ: cond->rho = O_EQ, strcpy(opstr, mpl->image); break; case T_GE: cond->rho = O_GE, strcpy(opstr, mpl->image); break; case T_GT: cond->rho = O_GT, strcpy(opstr, mpl->image); break; case T_NE: cond->rho = O_NE, strcpy(opstr, mpl->image); break; default: xassert(mpl->token != mpl->token); } xassert(strlen(opstr) < sizeof(opstr)); cond->code = NULL; cond->next = NULL; if (par->cond == NULL) par->cond = cond; else { for (temp = par->cond; temp->next != NULL; temp = temp->next); temp->next = cond; } #if 0 /* 13/VIII-2008 */ if (par->type == A_SYMBOLIC && !(cond->rho == O_EQ || cond->rho == O_NE)) error(mpl, "inequality restriction not allowed"); #endif get_token(mpl /* rho */); /* parse an expression that follows relational operator */ cond->code = expression_5(mpl); if (!(cond->code->type == A_NUMERIC || cond->code->type == A_SYMBOLIC)) error(mpl, "expression following %s has invalid type", opstr); xassert(cond->code->dim == 0); /* convert to the parameter type, if necessary */ if (par->type != A_SYMBOLIC && cond->code->type == A_SYMBOLIC) cond->code = make_unary(mpl, O_CVTNUM, cond->code, A_NUMERIC, 0); if (par->type == A_SYMBOLIC && cond->code->type != A_SYMBOLIC) cond->code = make_unary(mpl, O_CVTSYM, cond->code, A_SYMBOLIC, 0); } else if (mpl->token == T_IN || mpl->token == T_WITHIN) { /* restricting superset */ WITHIN *in, *temp; if (mpl->token == T_WITHIN && !mpl->as_in) { warning(mpl, "keyword within understood as in"); mpl->as_in = 1; } get_token(mpl /* in */); /* create new restricting superset list entry and append it to the in-list */ in = alloc(WITHIN); in->code = NULL; in->next = NULL; if (par->in == NULL) par->in = in; else { for (temp = par->in; temp->next != NULL; temp = temp->next); temp->next = in; } /* parse an expression that follows 'in' */ in->code = expression_9(mpl); if (in->code->type != A_ELEMSET) error(mpl, "expression following in has invalid type"); xassert(in->code->dim > 0); if (in->code->dim != 1) error(mpl, "set expression following in must have dimens" "ion 1 rather than %d", in->code->dim); } else if (mpl->token == T_ASSIGN) { /* assignment expression */ if (!(par->assign == NULL && par->option == NULL)) err: error(mpl, "at most one := or default allowed"); get_token(mpl /* := */); /* parse an expression that follows ':=' */ par->assign = expression_5(mpl); /* the expression must be of numeric/symbolic type */ if (!(par->assign->type == A_NUMERIC || par->assign->type == A_SYMBOLIC)) error(mpl, "expression following := has invalid type"); xassert(par->assign->dim == 0); /* convert to the parameter type, if necessary */ if (par->type != A_SYMBOLIC && par->assign->type == A_SYMBOLIC) par->assign = make_unary(mpl, O_CVTNUM, par->assign, A_NUMERIC, 0); if (par->type == A_SYMBOLIC && par->assign->type != A_SYMBOLIC) par->assign = make_unary(mpl, O_CVTSYM, par->assign, A_SYMBOLIC, 0); } else if (is_keyword(mpl, "default")) { /* expression for default value */ if (!(par->assign == NULL && par->option == NULL)) goto err; get_token(mpl /* default */); /* parse an expression that follows 'default' */ par->option = expression_5(mpl); if (!(par->option->type == A_NUMERIC || par->option->type == A_SYMBOLIC)) error(mpl, "expression following default has invalid typ" "e"); xassert(par->option->dim == 0); /* convert to the parameter type, if necessary */ if (par->type != A_SYMBOLIC && par->option->type == A_SYMBOLIC) par->option = make_unary(mpl, O_CVTNUM, par->option, A_NUMERIC, 0); if (par->type == A_SYMBOLIC && par->option->type != A_SYMBOLIC) par->option = make_unary(mpl, O_CVTSYM, par->option, A_SYMBOLIC, 0); } else error(mpl, "syntax error in parameter statement"); } /* close the domain scope */ if (par->domain != NULL) close_scope(mpl, par->domain); /* the parameter statement has been completely parsed */ xassert(mpl->token == T_SEMICOLON); get_token(mpl /* ; */); return par; } /*---------------------------------------------------------------------- -- variable_statement - parse variable statement. -- -- This routine parses variable statement using the syntax: -- -- ::= var -- ; -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= , integer -- ::= , binary -- ::= , -- ::= >= | <= | = | == -- -- Commae in are optional and may be omitted anywhere. */ VARIABLE *variable_statement(MPL *mpl) { VARIABLE *var; int integer_used = 0, binary_used = 0; xassert(is_keyword(mpl, "var")); if (mpl->flag_s) error(mpl, "variable statement must precede solve statement"); get_token(mpl /* var */); /* symbolic name must follow the keyword 'var' */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "symbolic name missing where expected"); /* there must be no other object with the same name */ if (avl_find_node(mpl->tree, mpl->image) != NULL) error(mpl, "%s multiply declared", mpl->image); /* create model variable */ var = alloc(VARIABLE); var->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(var->name, mpl->image); var->alias = NULL; var->dim = 0; var->domain = NULL; var->type = A_NUMERIC; var->lbnd = NULL; var->ubnd = NULL; var->array = NULL; get_token(mpl /* */); /* parse optional alias */ if (mpl->token == T_STRING) { var->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(var->alias, mpl->image); get_token(mpl /* */); } /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { var->domain = indexing_expression(mpl); var->dim = domain_arity(mpl, var->domain); } /* include the variable name in the symbolic names table */ { AVLNODE *node; node = avl_insert_node(mpl->tree, var->name); avl_set_node_type(node, A_VARIABLE); avl_set_node_link(node, (void *)var); } /* parse the list of optional attributes */ for (;;) { if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_SEMICOLON) break; if (is_keyword(mpl, "integer")) { if (integer_used) error(mpl, "at most one integer allowed"); if (var->type != A_BINARY) var->type = A_INTEGER; integer_used = 1; get_token(mpl /* integer */); } else if (is_keyword(mpl, "binary")) bin: { if (binary_used) error(mpl, "at most one binary allowed"); var->type = A_BINARY; binary_used = 1; get_token(mpl /* binary */); } else if (is_keyword(mpl, "logical")) { if (!mpl->as_binary) { warning(mpl, "keyword logical understood as binary"); mpl->as_binary = 1; } goto bin; } else if (is_keyword(mpl, "symbolic")) error(mpl, "variable cannot be symbolic"); else if (mpl->token == T_GE) { /* lower bound */ if (var->lbnd != NULL) { if (var->lbnd == var->ubnd) error(mpl, "both fixed value and lower bound not allo" "wed"); else error(mpl, "at most one lower bound allowed"); } get_token(mpl /* >= */); /* parse an expression that specifies the lower bound */ var->lbnd = expression_5(mpl); if (var->lbnd->type == A_SYMBOLIC) var->lbnd = make_unary(mpl, O_CVTNUM, var->lbnd, A_NUMERIC, 0); if (var->lbnd->type != A_NUMERIC) error(mpl, "expression following >= has invalid type"); xassert(var->lbnd->dim == 0); } else if (mpl->token == T_LE) { /* upper bound */ if (var->ubnd != NULL) { if (var->ubnd == var->lbnd) error(mpl, "both fixed value and upper bound not allo" "wed"); else error(mpl, "at most one upper bound allowed"); } get_token(mpl /* <= */); /* parse an expression that specifies the upper bound */ var->ubnd = expression_5(mpl); if (var->ubnd->type == A_SYMBOLIC) var->ubnd = make_unary(mpl, O_CVTNUM, var->ubnd, A_NUMERIC, 0); if (var->ubnd->type != A_NUMERIC) error(mpl, "expression following <= has invalid type"); xassert(var->ubnd->dim == 0); } else if (mpl->token == T_EQ) { /* fixed value */ char opstr[8]; if (!(var->lbnd == NULL && var->ubnd == NULL)) { if (var->lbnd == var->ubnd) error(mpl, "at most one fixed value allowed"); else if (var->lbnd != NULL) error(mpl, "both lower bound and fixed value not allo" "wed"); else error(mpl, "both upper bound and fixed value not allo" "wed"); } strcpy(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); get_token(mpl /* = | == */); /* parse an expression that specifies the fixed value */ var->lbnd = expression_5(mpl); if (var->lbnd->type == A_SYMBOLIC) var->lbnd = make_unary(mpl, O_CVTNUM, var->lbnd, A_NUMERIC, 0); if (var->lbnd->type != A_NUMERIC) error(mpl, "expression following %s has invalid type", opstr); xassert(var->lbnd->dim == 0); /* indicate that the variable is fixed, not bounded */ var->ubnd = var->lbnd; } else if (mpl->token == T_LT || mpl->token == T_GT || mpl->token == T_NE) error(mpl, "strict bound not allowed"); else error(mpl, "syntax error in variable statement"); } /* close the domain scope */ if (var->domain != NULL) close_scope(mpl, var->domain); /* the variable statement has been completely parsed */ xassert(mpl->token == T_SEMICOLON); get_token(mpl /* ; */); return var; } /*---------------------------------------------------------------------- -- constraint_statement - parse constraint statement. -- -- This routine parses constraint statement using the syntax: -- -- ::= -- : ; -- ::= -- ::= subject to -- ::= subj to -- ::= s.t. -- ::= -- ::= -- ::= -- ::= -- ::= , >= -- ::= , <= -- ::= , = -- ::= , <= , <= -- ::= , >= , >= -- ::= -- -- Commae in are optional and may be omitted anywhere. */ CONSTRAINT *constraint_statement(MPL *mpl) { CONSTRAINT *con; CODE *first, *second, *third; int rho; char opstr[8]; if (mpl->flag_s) error(mpl, "constraint statement must precede solve statement") ; if (is_keyword(mpl, "subject")) { get_token(mpl /* subject */); if (!is_keyword(mpl, "to")) error(mpl, "keyword subject to incomplete"); get_token(mpl /* to */); } else if (is_keyword(mpl, "subj")) { get_token(mpl /* subj */); if (!is_keyword(mpl, "to")) error(mpl, "keyword subj to incomplete"); get_token(mpl /* to */); } else if (mpl->token == T_SPTP) get_token(mpl /* s.t. */); /* the current token must be symbolic name of constraint */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "symbolic name missing where expected"); /* there must be no other object with the same name */ if (avl_find_node(mpl->tree, mpl->image) != NULL) error(mpl, "%s multiply declared", mpl->image); /* create model constraint */ con = alloc(CONSTRAINT); con->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(con->name, mpl->image); con->alias = NULL; con->dim = 0; con->domain = NULL; con->type = A_CONSTRAINT; con->code = NULL; con->lbnd = NULL; con->ubnd = NULL; con->array = NULL; get_token(mpl /* */); /* parse optional alias */ if (mpl->token == T_STRING) { con->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(con->alias, mpl->image); get_token(mpl /* */); } /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { con->domain = indexing_expression(mpl); con->dim = domain_arity(mpl, con->domain); } /* include the constraint name in the symbolic names table */ { AVLNODE *node; node = avl_insert_node(mpl->tree, con->name); avl_set_node_type(node, A_CONSTRAINT); avl_set_node_link(node, (void *)con); } /* the colon must precede the first expression */ if (mpl->token != T_COLON) error(mpl, "colon missing where expected"); get_token(mpl /* : */); /* parse the first expression */ first = expression_5(mpl); if (first->type == A_SYMBOLIC) first = make_unary(mpl, O_CVTNUM, first, A_NUMERIC, 0); if (!(first->type == A_NUMERIC || first->type == A_FORMULA)) error(mpl, "expression following colon has invalid type"); xassert(first->dim == 0); /* relational operator must follow the first expression */ if (mpl->token == T_COMMA) get_token(mpl /* , */); switch (mpl->token) { case T_LE: case T_GE: case T_EQ: break; case T_LT: case T_GT: case T_NE: error(mpl, "strict inequality not allowed"); case T_SEMICOLON: error(mpl, "constraint must be equality or inequality"); default: goto err; } rho = mpl->token; strcpy(opstr, mpl->image); xassert(strlen(opstr) < sizeof(opstr)); get_token(mpl /* rho */); /* parse the second expression */ second = expression_5(mpl); if (second->type == A_SYMBOLIC) second = make_unary(mpl, O_CVTNUM, second, A_NUMERIC, 0); if (!(second->type == A_NUMERIC || second->type == A_FORMULA)) error(mpl, "expression following %s has invalid type", opstr); xassert(second->dim == 0); /* check a token that follow the second expression */ if (mpl->token == T_COMMA) { get_token(mpl /* , */); if (mpl->token == T_SEMICOLON) goto err; } if (mpl->token == T_LT || mpl->token == T_LE || mpl->token == T_EQ || mpl->token == T_GE || mpl->token == T_GT || mpl->token == T_NE) { /* it is another relational operator, therefore the constraint is double inequality */ if (rho == T_EQ || mpl->token != rho) error(mpl, "double inequality must be ... <= ... <= ... or " "... >= ... >= ..."); /* the first expression cannot be linear form */ if (first->type == A_FORMULA) error(mpl, "leftmost expression in double inequality cannot" " be linear form"); get_token(mpl /* rho */); /* parse the third expression */ third = expression_5(mpl); if (third->type == A_SYMBOLIC) third = make_unary(mpl, O_CVTNUM, second, A_NUMERIC, 0); if (!(third->type == A_NUMERIC || third->type == A_FORMULA)) error(mpl, "rightmost expression in double inequality const" "raint has invalid type"); xassert(third->dim == 0); /* the third expression also cannot be linear form */ if (third->type == A_FORMULA) error(mpl, "rightmost expression in double inequality canno" "t be linear form"); } else { /* the constraint is equality or single inequality */ third = NULL; } /* close the domain scope */ if (con->domain != NULL) close_scope(mpl, con->domain); /* convert all expressions to linear form, if necessary */ if (first->type != A_FORMULA) first = make_unary(mpl, O_CVTLFM, first, A_FORMULA, 0); if (second->type != A_FORMULA) second = make_unary(mpl, O_CVTLFM, second, A_FORMULA, 0); if (third != NULL) third = make_unary(mpl, O_CVTLFM, third, A_FORMULA, 0); /* arrange expressions in the constraint */ if (third == NULL) { /* the constraint is equality or single inequality */ switch (rho) { case T_LE: /* first <= second */ con->code = first; con->lbnd = NULL; con->ubnd = second; break; case T_GE: /* first >= second */ con->code = first; con->lbnd = second; con->ubnd = NULL; break; case T_EQ: /* first = second */ con->code = first; con->lbnd = second; con->ubnd = second; break; default: xassert(rho != rho); } } else { /* the constraint is double inequality */ switch (rho) { case T_LE: /* first <= second <= third */ con->code = second; con->lbnd = first; con->ubnd = third; break; case T_GE: /* first >= second >= third */ con->code = second; con->lbnd = third; con->ubnd = first; break; default: xassert(rho != rho); } } /* the constraint statement has been completely parsed */ if (mpl->token != T_SEMICOLON) err: error(mpl, "syntax error in constraint statement"); get_token(mpl /* ; */); return con; } /*---------------------------------------------------------------------- -- objective_statement - parse objective statement. -- -- This routine parses objective statement using the syntax: -- -- ::= : -- ; -- ::= minimize -- ::= maximize -- ::= -- ::= -- ::= -- ::= -- ::= */ CONSTRAINT *objective_statement(MPL *mpl) { CONSTRAINT *obj; int type; if (is_keyword(mpl, "minimize")) type = A_MINIMIZE; else if (is_keyword(mpl, "maximize")) type = A_MAXIMIZE; else xassert(mpl != mpl); if (mpl->flag_s) error(mpl, "objective statement must precede solve statement"); get_token(mpl /* minimize | maximize */); /* symbolic name must follow the verb 'minimize' or 'maximize' */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "symbolic name missing where expected"); /* there must be no other object with the same name */ if (avl_find_node(mpl->tree, mpl->image) != NULL) error(mpl, "%s multiply declared", mpl->image); /* create model objective */ obj = alloc(CONSTRAINT); obj->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(obj->name, mpl->image); obj->alias = NULL; obj->dim = 0; obj->domain = NULL; obj->type = type; obj->code = NULL; obj->lbnd = NULL; obj->ubnd = NULL; obj->array = NULL; get_token(mpl /* */); /* parse optional alias */ if (mpl->token == T_STRING) { obj->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(obj->alias, mpl->image); get_token(mpl /* */); } /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { obj->domain = indexing_expression(mpl); obj->dim = domain_arity(mpl, obj->domain); } /* include the constraint name in the symbolic names table */ { AVLNODE *node; node = avl_insert_node(mpl->tree, obj->name); avl_set_node_type(node, A_CONSTRAINT); avl_set_node_link(node, (void *)obj); } /* the colon must precede the objective expression */ if (mpl->token != T_COLON) error(mpl, "colon missing where expected"); get_token(mpl /* : */); /* parse the objective expression */ obj->code = expression_5(mpl); if (obj->code->type == A_SYMBOLIC) obj->code = make_unary(mpl, O_CVTNUM, obj->code, A_NUMERIC, 0); if (obj->code->type == A_NUMERIC) obj->code = make_unary(mpl, O_CVTLFM, obj->code, A_FORMULA, 0); if (obj->code->type != A_FORMULA) error(mpl, "expression following colon has invalid type"); xassert(obj->code->dim == 0); /* close the domain scope */ if (obj->domain != NULL) close_scope(mpl, obj->domain); /* the objective statement has been completely parsed */ if (mpl->token != T_SEMICOLON) error(mpl, "syntax error in objective statement"); get_token(mpl /* ; */); return obj; } #if 1 /* 11/II-2008 */ /*********************************************************************** * table_statement - parse table statement * * This routine parses table statement using the syntax: * * ::= *
::= * * ::= * table
IN : * [ ] , ; * ::= * ::= * ::= * ::= * ::= , * ::= * ::= <- * ::= * ::= , * ::= * ::= , * ::= * ::= ~ * * ::= * table
OUT : * ; * ::= * ::= * ::= , * ::= * ::= ~ */ TABLE *table_statement(MPL *mpl) { TABLE *tab; TABARG *last_arg, *arg; TABFLD *last_fld, *fld; TABIN *last_in, *in; TABOUT *last_out, *out; AVLNODE *node; int nflds; char name[MAX_LENGTH+1]; xassert(is_keyword(mpl, "table")); get_token(mpl /* solve */); /* symbolic name must follow the keyword table */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "symbolic name missing where expected"); /* there must be no other object with the same name */ if (avl_find_node(mpl->tree, mpl->image) != NULL) error(mpl, "%s multiply declared", mpl->image); /* create data table */ tab = alloc(TABLE); tab->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(tab->name, mpl->image); get_token(mpl /* */); /* parse optional alias */ if (mpl->token == T_STRING) { tab->alias = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(tab->alias, mpl->image); get_token(mpl /* */); } else tab->alias = NULL; /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { /* this is output table */ tab->type = A_OUTPUT; tab->u.out.domain = indexing_expression(mpl); if (!is_keyword(mpl, "OUT")) error(mpl, "keyword OUT missing where expected"); get_token(mpl /* OUT */); } else { /* this is input table */ tab->type = A_INPUT; if (!is_keyword(mpl, "IN")) error(mpl, "keyword IN missing where expected"); get_token(mpl /* IN */); } /* parse argument list */ tab->arg = last_arg = NULL; for (;;) { /* create argument list entry */ arg = alloc(TABARG); /* parse argument expression */ if (mpl->token == T_COMMA || mpl->token == T_COLON || mpl->token == T_SEMICOLON) error(mpl, "argument expression missing where expected"); arg->code = expression_5(mpl); /* convert the result to symbolic type, if necessary */ if (arg->code->type == A_NUMERIC) arg->code = make_unary(mpl, O_CVTSYM, arg->code, A_SYMBOLIC, 0); /* check that now the result is of symbolic type */ if (arg->code->type != A_SYMBOLIC) error(mpl, "argument expression has invalid type"); /* add the entry to the end of the list */ arg->next = NULL; if (last_arg == NULL) tab->arg = arg; else last_arg->next = arg; last_arg = arg; /* argument expression has been parsed */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_COLON || mpl->token == T_SEMICOLON) break; } xassert(tab->arg != NULL); /* argument list must end with colon */ if (mpl->token == T_COLON) get_token(mpl /* : */); else error(mpl, "colon missing where expected"); /* parse specific part of the table statement */ switch (tab->type) { case A_INPUT: goto input_table; case A_OUTPUT: goto output_table; default: xassert(tab != tab); } input_table: /* parse optional set name */ if (mpl->token == T_NAME) { node = avl_find_node(mpl->tree, mpl->image); if (node == NULL) error(mpl, "%s not defined", mpl->image); if (avl_get_node_type(node) != A_SET) error(mpl, "%s not a set", mpl->image); tab->u.in.set = (SET *)avl_get_node_link(node); if (tab->u.in.set->assign != NULL) error(mpl, "%s needs no data", mpl->image); if (tab->u.in.set->dim != 0) error(mpl, "%s must be a simple set", mpl->image); get_token(mpl /* */); if (mpl->token == T_INPUT) get_token(mpl /* <- */); else error(mpl, "delimiter <- missing where expected"); } else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else tab->u.in.set = NULL; /* parse field list */ tab->u.in.fld = last_fld = NULL; nflds = 0; if (mpl->token == T_LBRACKET) get_token(mpl /* [ */); else error(mpl, "field list missing where expected"); for (;;) { /* create field list entry */ fld = alloc(TABFLD); /* parse field name */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "field name missing where expected"); fld->name = dmp_get_atomv(mpl->pool, strlen(mpl->image)+1); strcpy(fld->name, mpl->image); get_token(mpl /* */); /* add the entry to the end of the list */ fld->next = NULL; if (last_fld == NULL) tab->u.in.fld = fld; else last_fld->next = fld; last_fld = fld; nflds++; /* field name has been parsed */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_RBRACKET) break; else error(mpl, "syntax error in field list"); } /* check that the set dimen is equal to the number of fields */ if (tab->u.in.set != NULL && tab->u.in.set->dimen != nflds) error(mpl, "there must be %d field%s rather than %d", tab->u.in.set->dimen, tab->u.in.set->dimen == 1 ? "" : "s", nflds); get_token(mpl /* ] */); /* parse optional input list */ tab->u.in.list = last_in = NULL; while (mpl->token == T_COMMA) { get_token(mpl /* , */); /* create input list entry */ in = alloc(TABIN); /* parse parameter name */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "parameter name missing where expected"); node = avl_find_node(mpl->tree, mpl->image); if (node == NULL) error(mpl, "%s not defined", mpl->image); if (avl_get_node_type(node) != A_PARAMETER) error(mpl, "%s not a parameter", mpl->image); in->par = (PARAMETER *)avl_get_node_link(node); if (in->par->dim != nflds) error(mpl, "%s must have %d subscript%s rather than %d", mpl->image, nflds, nflds == 1 ? "" : "s", in->par->dim); if (in->par->assign != NULL) error(mpl, "%s needs no data", mpl->image); get_token(mpl /* */); /* parse optional field name */ if (mpl->token == T_TILDE) { get_token(mpl /* ~ */); /* parse field name */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "field name missing where expected"); xassert(strlen(mpl->image) < sizeof(name)); strcpy(name, mpl->image); get_token(mpl /* */); } else { /* field name is the same as the parameter name */ xassert(strlen(in->par->name) < sizeof(name)); strcpy(name, in->par->name); } /* assign field name */ in->name = dmp_get_atomv(mpl->pool, strlen(name)+1); strcpy(in->name, name); /* add the entry to the end of the list */ in->next = NULL; if (last_in == NULL) tab->u.in.list = in; else last_in->next = in; last_in = in; } goto end_of_table; output_table: /* parse output list */ tab->u.out.list = last_out = NULL; for (;;) { /* create output list entry */ out = alloc(TABOUT); /* parse expression */ if (mpl->token == T_COMMA || mpl->token == T_SEMICOLON) error(mpl, "expression missing where expected"); if (mpl->token == T_NAME) { xassert(strlen(mpl->image) < sizeof(name)); strcpy(name, mpl->image); } else name[0] = '\0'; out->code = expression_5(mpl); /* parse optional field name */ if (mpl->token == T_TILDE) { get_token(mpl /* ~ */); /* parse field name */ if (mpl->token == T_NAME) ; else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "field name missing where expected"); xassert(strlen(mpl->image) < sizeof(name)); strcpy(name, mpl->image); get_token(mpl /* */); } /* assign field name */ if (name[0] == '\0') error(mpl, "field name required"); out->name = dmp_get_atomv(mpl->pool, strlen(name)+1); strcpy(out->name, name); /* add the entry to the end of the list */ out->next = NULL; if (last_out == NULL) tab->u.out.list = out; else last_out->next = out; last_out = out; /* output item has been parsed */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_SEMICOLON) break; else error(mpl, "syntax error in output list"); } /* close the domain scope */ close_scope(mpl,tab->u.out.domain); end_of_table: /* the table statement must end with semicolon */ if (mpl->token != T_SEMICOLON) error(mpl, "syntax error in table statement"); get_token(mpl /* ; */); return tab; } #endif /*---------------------------------------------------------------------- -- solve_statement - parse solve statement. -- -- This routine parses solve statement using the syntax: -- -- ::= solve ; -- -- The solve statement can be used at most once. */ void *solve_statement(MPL *mpl) { xassert(is_keyword(mpl, "solve")); if (mpl->flag_s) error(mpl, "at most one solve statement allowed"); mpl->flag_s = 1; get_token(mpl /* solve */); /* semicolon must follow solve statement */ if (mpl->token != T_SEMICOLON) error(mpl, "syntax error in solve statement"); get_token(mpl /* ; */); return NULL; } /*---------------------------------------------------------------------- -- check_statement - parse check statement. -- -- This routine parses check statement using the syntax: -- -- ::= check : ; -- ::= -- ::= -- -- If is omitted, colon following it may also be omitted. */ CHECK *check_statement(MPL *mpl) { CHECK *chk; xassert(is_keyword(mpl, "check")); /* create check descriptor */ chk = alloc(CHECK); chk->domain = NULL; chk->code = NULL; get_token(mpl /* check */); /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { chk->domain = indexing_expression(mpl); #if 0 if (mpl->token != T_COLON) error(mpl, "colon missing where expected"); #endif } /* skip optional colon */ if (mpl->token == T_COLON) get_token(mpl /* : */); /* parse logical expression */ chk->code = expression_13(mpl); if (chk->code->type != A_LOGICAL) error(mpl, "expression has invalid type"); xassert(chk->code->dim == 0); /* close the domain scope */ if (chk->domain != NULL) close_scope(mpl, chk->domain); /* the check statement has been completely parsed */ if (mpl->token != T_SEMICOLON) error(mpl, "syntax error in check statement"); get_token(mpl /* ; */); return chk; } #if 1 /* 15/V-2010 */ /*---------------------------------------------------------------------- -- display_statement - parse display statement. -- -- This routine parses display statement using the syntax: -- -- ::= display : ; -- ::= display ; -- ::= -- ::= -- ::= -- ::= , -- ::= -- ::= -- ::= [ ] -- ::= -- ::= [ ] -- ::= -- ::= [ ] -- ::= -- ::= [ ] -- ::= */ DISPLAY *display_statement(MPL *mpl) { DISPLAY *dpy; DISPLAY1 *entry, *last_entry; xassert(is_keyword(mpl, "display")); /* create display descriptor */ dpy = alloc(DISPLAY); dpy->domain = NULL; dpy->list = last_entry = NULL; get_token(mpl /* display */); /* parse optional indexing expression */ if (mpl->token == T_LBRACE) dpy->domain = indexing_expression(mpl); /* skip optional colon */ if (mpl->token == T_COLON) get_token(mpl /* : */); /* parse display list */ for (;;) { /* create new display entry */ entry = alloc(DISPLAY1); entry->type = 0; entry->next = NULL; /* and append it to the display list */ if (dpy->list == NULL) dpy->list = entry; else last_entry->next = entry; last_entry = entry; /* parse display entry */ if (mpl->token == T_NAME) { AVLNODE *node; int next_token; get_token(mpl /* */); next_token = mpl->token; unget_token(mpl); if (!(next_token == T_COMMA || next_token == T_SEMICOLON)) { /* symbolic name begins expression */ goto expr; } /* display entry is dummy index or model object */ node = avl_find_node(mpl->tree, mpl->image); if (node == NULL) error(mpl, "%s not defined", mpl->image); entry->type = avl_get_node_type(node); switch (avl_get_node_type(node)) { case A_INDEX: entry->u.slot = (DOMAIN_SLOT *)avl_get_node_link(node); break; case A_SET: entry->u.set = (SET *)avl_get_node_link(node); break; case A_PARAMETER: entry->u.par = (PARAMETER *)avl_get_node_link(node); break; case A_VARIABLE: entry->u.var = (VARIABLE *)avl_get_node_link(node); if (!mpl->flag_s) error(mpl, "invalid reference to variable %s above" " solve statement", entry->u.var->name); break; case A_CONSTRAINT: entry->u.con = (CONSTRAINT *)avl_get_node_link(node); if (!mpl->flag_s) error(mpl, "invalid reference to %s %s above solve" " statement", entry->u.con->type == A_CONSTRAINT ? "constraint" : "objective", entry->u.con->name); break; default: xassert(node != node); } get_token(mpl /* */); } else expr: { /* display entry is expression */ entry->type = A_EXPRESSION; entry->u.code = expression_13(mpl); } /* check a token that follows the entry parsed */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else break; } /* close the domain scope */ if (dpy->domain != NULL) close_scope(mpl, dpy->domain); /* the display statement has been completely parsed */ if (mpl->token != T_SEMICOLON) error(mpl, "syntax error in display statement"); get_token(mpl /* ; */); return dpy; } #endif /*---------------------------------------------------------------------- -- printf_statement - parse printf statement. -- -- This routine parses print statement using the syntax: -- -- ::= ; -- ::= > ; -- ::= >> ; -- ::= printf : -- ::= printf -- ::= -- ::= -- ::= -- ::= -- ::= , -- ::= -- ::= */ PRINTF *printf_statement(MPL *mpl) { PRINTF *prt; PRINTF1 *entry, *last_entry; xassert(is_keyword(mpl, "printf")); /* create printf descriptor */ prt = alloc(PRINTF); prt->domain = NULL; prt->fmt = NULL; prt->list = last_entry = NULL; get_token(mpl /* printf */); /* parse optional indexing expression */ if (mpl->token == T_LBRACE) { prt->domain = indexing_expression(mpl); #if 0 if (mpl->token != T_COLON) error(mpl, "colon missing where expected"); #endif } /* skip optional colon */ if (mpl->token == T_COLON) get_token(mpl /* : */); /* parse expression for format string */ prt->fmt = expression_5(mpl); /* convert it to symbolic type, if necessary */ if (prt->fmt->type == A_NUMERIC) prt->fmt = make_unary(mpl, O_CVTSYM, prt->fmt, A_SYMBOLIC, 0); /* check that now the expression is of symbolic type */ if (prt->fmt->type != A_SYMBOLIC) error(mpl, "format expression has invalid type"); /* parse printf list */ while (mpl->token == T_COMMA) { get_token(mpl /* , */); /* create new printf entry */ entry = alloc(PRINTF1); entry->code = NULL; entry->next = NULL; /* and append it to the printf list */ if (prt->list == NULL) prt->list = entry; else last_entry->next = entry; last_entry = entry; /* parse printf entry */ entry->code = expression_9(mpl); if (!(entry->code->type == A_NUMERIC || entry->code->type == A_SYMBOLIC || entry->code->type == A_LOGICAL)) error(mpl, "only numeric, symbolic, or logical expression a" "llowed"); } /* close the domain scope */ if (prt->domain != NULL) close_scope(mpl, prt->domain); #if 1 /* 14/VII-2006 */ /* parse optional redirection */ prt->fname = NULL, prt->app = 0; if (mpl->token == T_GT || mpl->token == T_APPEND) { prt->app = (mpl->token == T_APPEND); get_token(mpl /* > or >> */); /* parse expression for file name string */ prt->fname = expression_5(mpl); /* convert it to symbolic type, if necessary */ if (prt->fname->type == A_NUMERIC) prt->fname = make_unary(mpl, O_CVTSYM, prt->fname, A_SYMBOLIC, 0); /* check that now the expression is of symbolic type */ if (prt->fname->type != A_SYMBOLIC) error(mpl, "file name expression has invalid type"); } #endif /* the printf statement has been completely parsed */ if (mpl->token != T_SEMICOLON) error(mpl, "syntax error in printf statement"); get_token(mpl /* ; */); return prt; } /*---------------------------------------------------------------------- -- for_statement - parse for statement. -- -- This routine parses for statement using the syntax: -- -- ::= for -- ::= for { } -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= */ FOR *for_statement(MPL *mpl) { FOR *fur; STATEMENT *stmt, *last_stmt; xassert(is_keyword(mpl, "for")); /* create for descriptor */ fur = alloc(FOR); fur->domain = NULL; fur->list = last_stmt = NULL; get_token(mpl /* for */); /* parse indexing expression */ if (mpl->token != T_LBRACE) error(mpl, "indexing expression missing where expected"); fur->domain = indexing_expression(mpl); /* skip optional colon */ if (mpl->token == T_COLON) get_token(mpl /* : */); /* parse for statement body */ if (mpl->token != T_LBRACE) { /* parse simple statement */ fur->list = simple_statement(mpl, 1); } else { /* parse compound statement */ get_token(mpl /* { */); while (mpl->token != T_RBRACE) { /* parse statement */ stmt = simple_statement(mpl, 1); /* and append it to the end of the statement list */ if (last_stmt == NULL) fur->list = stmt; else last_stmt->next = stmt; last_stmt = stmt; } get_token(mpl /* } */); } /* close the domain scope */ xassert(fur->domain != NULL); close_scope(mpl, fur->domain); /* the for statement has been completely parsed */ return fur; } /*---------------------------------------------------------------------- -- end_statement - parse end statement. -- -- This routine parses end statement using the syntax: -- -- ::= end ; */ void end_statement(MPL *mpl) { if (!mpl->flag_d && is_keyword(mpl, "end") || mpl->flag_d && is_literal(mpl, "end")) { get_token(mpl /* end */); if (mpl->token == T_SEMICOLON) get_token(mpl /* ; */); else warning(mpl, "no semicolon following end statement; missing" " semicolon inserted"); } else warning(mpl, "unexpected end of file; missing end statement in" "serted"); if (mpl->token != T_EOF) warning(mpl, "some text detected beyond end statement; text ig" "nored"); return; } /*---------------------------------------------------------------------- -- simple_statement - parse simple statement. -- -- This routine parses simple statement using the syntax: -- -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= -- ::= -- -- If the flag spec is set, some statements cannot be used. */ STATEMENT *simple_statement(MPL *mpl, int spec) { STATEMENT *stmt; stmt = alloc(STATEMENT); stmt->line = mpl->line; stmt->next = NULL; if (is_keyword(mpl, "set")) { if (spec) error(mpl, "set statement not allowed here"); stmt->type = A_SET; stmt->u.set = set_statement(mpl); } else if (is_keyword(mpl, "param")) { if (spec) error(mpl, "parameter statement not allowed here"); stmt->type = A_PARAMETER; stmt->u.par = parameter_statement(mpl); } else if (is_keyword(mpl, "var")) { if (spec) error(mpl, "variable statement not allowed here"); stmt->type = A_VARIABLE; stmt->u.var = variable_statement(mpl); } else if (is_keyword(mpl, "subject") || is_keyword(mpl, "subj") || mpl->token == T_SPTP) { if (spec) error(mpl, "constraint statement not allowed here"); stmt->type = A_CONSTRAINT; stmt->u.con = constraint_statement(mpl); } else if (is_keyword(mpl, "minimize") || is_keyword(mpl, "maximize")) { if (spec) error(mpl, "objective statement not allowed here"); stmt->type = A_CONSTRAINT; stmt->u.con = objective_statement(mpl); } #if 1 /* 11/II-2008 */ else if (is_keyword(mpl, "table")) { if (spec) error(mpl, "table statement not allowed here"); stmt->type = A_TABLE; stmt->u.tab = table_statement(mpl); } #endif else if (is_keyword(mpl, "solve")) { if (spec) error(mpl, "solve statement not allowed here"); stmt->type = A_SOLVE; stmt->u.slv = solve_statement(mpl); } else if (is_keyword(mpl, "check")) { stmt->type = A_CHECK; stmt->u.chk = check_statement(mpl); } else if (is_keyword(mpl, "display")) { stmt->type = A_DISPLAY; stmt->u.dpy = display_statement(mpl); } else if (is_keyword(mpl, "printf")) { stmt->type = A_PRINTF; stmt->u.prt = printf_statement(mpl); } else if (is_keyword(mpl, "for")) { stmt->type = A_FOR; stmt->u.fur = for_statement(mpl); } else if (mpl->token == T_NAME) { if (spec) error(mpl, "constraint statement not allowed here"); stmt->type = A_CONSTRAINT; stmt->u.con = constraint_statement(mpl); } else if (is_reserved(mpl)) error(mpl, "invalid use of reserved keyword %s", mpl->image); else error(mpl, "syntax error in model section"); return stmt; } /*---------------------------------------------------------------------- -- model_section - parse model section. -- -- This routine parses model section using the syntax: -- -- ::= -- ::= -- -- Parsing model section is terminated by either the keyword 'data', or -- the keyword 'end', or the end of file. */ void model_section(MPL *mpl) { STATEMENT *stmt, *last_stmt; xassert(mpl->model == NULL); last_stmt = NULL; while (!(mpl->token == T_EOF || is_keyword(mpl, "data") || is_keyword(mpl, "end"))) { /* parse statement */ stmt = simple_statement(mpl, 0); /* and append it to the end of the statement list */ if (last_stmt == NULL) mpl->model = stmt; else last_stmt->next = stmt; last_stmt = stmt; } return; } /* eof */ glpk-4.52.1/src/glpmpl02.c0000644000062000006210000013073312175147600014320 0ustar maomkpasswd/* glpmpl02.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_STDIO #include "env.h" #include "glpmpl.h" /**********************************************************************/ /* * * PROCESSING DATA SECTION * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- create_slice - create slice. -- -- This routine creates a slice, which initially has no components. */ SLICE *create_slice(MPL *mpl) { SLICE *slice; xassert(mpl == mpl); slice = NULL; return slice; } /*---------------------------------------------------------------------- -- expand_slice - append new component to slice. -- -- This routine expands slice appending to it either a given symbol or -- null component, which becomes the last component of the slice. */ SLICE *expand_slice ( MPL *mpl, SLICE *slice, /* destroyed */ SYMBOL *sym /* destroyed */ ) { SLICE *tail, *temp; /* create a new component */ tail = dmp_get_atom(mpl->tuples, sizeof(SLICE)); tail->sym = sym; tail->next = NULL; /* and append it to the component list */ if (slice == NULL) slice = tail; else { for (temp = slice; temp->next != NULL; temp = temp->next); temp->next = tail; } return slice; } /*---------------------------------------------------------------------- -- slice_dimen - determine dimension of slice. -- -- This routine returns dimension of slice, which is number of all its -- components including null ones. */ int slice_dimen ( MPL *mpl, SLICE *slice /* not changed */ ) { SLICE *temp; int dim; xassert(mpl == mpl); dim = 0; for (temp = slice; temp != NULL; temp = temp->next) dim++; return dim; } /*---------------------------------------------------------------------- -- slice_arity - determine arity of slice. -- -- This routine returns arity of slice, i.e. number of null components -- (indicated by asterisks) in the slice. */ int slice_arity ( MPL *mpl, SLICE *slice /* not changed */ ) { SLICE *temp; int arity; xassert(mpl == mpl); arity = 0; for (temp = slice; temp != NULL; temp = temp->next) if (temp->sym == NULL) arity++; return arity; } /*---------------------------------------------------------------------- -- fake_slice - create fake slice of all asterisks. -- -- This routine creates a fake slice of given dimension, which contains -- asterisks in all components. Zero dimension is allowed. */ SLICE *fake_slice(MPL *mpl, int dim) { SLICE *slice; slice = create_slice(mpl); while (dim-- > 0) slice = expand_slice(mpl, slice, NULL); return slice; } /*---------------------------------------------------------------------- -- delete_slice - delete slice. -- -- This routine deletes specified slice. */ void delete_slice ( MPL *mpl, SLICE *slice /* destroyed */ ) { SLICE *temp; while (slice != NULL) { temp = slice; slice = temp->next; if (temp->sym != NULL) delete_symbol(mpl, temp->sym); xassert(sizeof(SLICE) == sizeof(TUPLE)); dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); } return; } /*---------------------------------------------------------------------- -- is_number - check if current token is number. -- -- If the current token is a number, this routine returns non-zero. -- Otherwise zero is returned. */ int is_number(MPL *mpl) { return mpl->token == T_NUMBER; } /*---------------------------------------------------------------------- -- is_symbol - check if current token is symbol. -- -- If the current token is suitable to be a symbol, the routine returns -- non-zero. Otherwise zero is returned. */ int is_symbol(MPL *mpl) { return mpl->token == T_NUMBER || mpl->token == T_SYMBOL || mpl->token == T_STRING; } /*---------------------------------------------------------------------- -- is_literal - check if current token is given symbolic literal. -- -- If the current token is given symbolic literal, this routine returns -- non-zero. Otherwise zero is returned. -- -- This routine is used on processing the data section in the same way -- as the routine is_keyword on processing the model section. */ int is_literal(MPL *mpl, char *literal) { return is_symbol(mpl) && strcmp(mpl->image, literal) == 0; } /*---------------------------------------------------------------------- -- read_number - read number. -- -- This routine reads the current token, which must be a number, and -- returns its numeric value. */ double read_number(MPL *mpl) { double num; xassert(is_number(mpl)); num = mpl->value; get_token(mpl /* */); return num; } /*---------------------------------------------------------------------- -- read_symbol - read symbol. -- -- This routine reads the current token, which must be a symbol, and -- returns its symbolic value. */ SYMBOL *read_symbol(MPL *mpl) { SYMBOL *sym; xassert(is_symbol(mpl)); if (is_number(mpl)) sym = create_symbol_num(mpl, mpl->value); else sym = create_symbol_str(mpl, create_string(mpl, mpl->image)); get_token(mpl /* */); return sym; } /*---------------------------------------------------------------------- -- read_slice - read slice. -- -- This routine reads slice using the syntax: -- -- ::= [ ] -- ::= ( ) -- ::= -- ::= , -- ::= -- ::= * -- -- The bracketed form of slice is used for members of multi-dimensional -- objects while the parenthesized form is used for elemental sets. */ SLICE *read_slice ( MPL *mpl, char *name, /* not changed */ int dim ) { SLICE *slice; int close; xassert(name != NULL); switch (mpl->token) { case T_LBRACKET: close = T_RBRACKET; break; case T_LEFT: xassert(dim > 0); close = T_RIGHT; break; default: xassert(mpl != mpl); } if (dim == 0) error(mpl, "%s cannot be subscripted", name); get_token(mpl /* ( | [ */); /* read slice components */ slice = create_slice(mpl); for (;;) { /* the current token must be a symbol or asterisk */ if (is_symbol(mpl)) slice = expand_slice(mpl, slice, read_symbol(mpl)); else if (mpl->token == T_ASTERISK) { slice = expand_slice(mpl, slice, NULL); get_token(mpl /* * */); } else error(mpl, "number, symbol, or asterisk missing where expec" "ted"); /* check a token that follows the symbol */ if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == close) break; else error(mpl, "syntax error in slice"); } /* number of slice components must be the same as the appropriate dimension */ if (slice_dimen(mpl, slice) != dim) { switch (close) { case T_RBRACKET: error(mpl, "%s must have %d subscript%s, not %d", name, dim, dim == 1 ? "" : "s", slice_dimen(mpl, slice)); break; case T_RIGHT: error(mpl, "%s has dimension %d, not %d", name, dim, slice_dimen(mpl, slice)); break; default: xassert(close != close); } } get_token(mpl /* ) | ] */); return slice; } /*---------------------------------------------------------------------- -- select_set - select set to saturate it with elemental sets. -- -- This routine selects set to saturate it with elemental sets provided -- in the data section. */ SET *select_set ( MPL *mpl, char *name /* not changed */ ) { SET *set; AVLNODE *node; xassert(name != NULL); node = avl_find_node(mpl->tree, name); if (node == NULL || avl_get_node_type(node) != A_SET) error(mpl, "%s not a set", name); set = (SET *)avl_get_node_link(node); if (set->assign != NULL || set->gadget != NULL) error(mpl, "%s needs no data", name); set->data = 1; return set; } /*---------------------------------------------------------------------- -- simple_format - read set data block in simple format. -- -- This routine reads set data block using the syntax: -- -- ::= , , ... , -- -- where are used to construct a complete n-tuple, which is -- included in elemental set assigned to the set member. Commae between -- symbols are optional and may be omitted anywhere. -- -- Number of components in the slice must be the same as dimension of -- n-tuples in elemental sets assigned to the set members. To construct -- complete n-tuple the routine replaces null positions in the slice by -- corresponding . -- -- If the slice contains at least one null position, the current token -- must be symbol. Otherwise, the routine reads no symbols to construct -- the n-tuple, so the current token is not checked. */ void simple_format ( MPL *mpl, SET *set, /* not changed */ MEMBER *memb, /* modified */ SLICE *slice /* not changed */ ) { TUPLE *tuple; SLICE *temp; SYMBOL *sym, *with = NULL; xassert(set != NULL); xassert(memb != NULL); xassert(slice != NULL); xassert(set->dimen == slice_dimen(mpl, slice)); xassert(memb->value.set->dim == set->dimen); if (slice_arity(mpl, slice) > 0) xassert(is_symbol(mpl)); /* read symbols and construct complete n-tuple */ tuple = create_tuple(mpl); for (temp = slice; temp != NULL; temp = temp->next) { if (temp->sym == NULL) { /* substitution is needed; read symbol */ if (!is_symbol(mpl)) { int lack = slice_arity(mpl, temp); /* with cannot be null due to assertion above */ xassert(with != NULL); if (lack == 1) error(mpl, "one item missing in data group beginning " "with %s", format_symbol(mpl, with)); else error(mpl, "%d items missing in data group beginning " "with %s", lack, format_symbol(mpl, with)); } sym = read_symbol(mpl); if (with == NULL) with = sym; } else { /* copy symbol from the slice */ sym = copy_symbol(mpl, temp->sym); } /* append the symbol to the n-tuple */ tuple = expand_tuple(mpl, tuple, sym); /* skip optional comma *between* */ if (temp->next != NULL && mpl->token == T_COMMA) get_token(mpl /* , */); } /* add constructed n-tuple to elemental set */ check_then_add(mpl, memb->value.set, tuple); return; } /*---------------------------------------------------------------------- -- matrix_format - read set data block in matrix format. -- -- This routine reads set data block using the syntax: -- -- ::= ... := -- +/- +/- ... +/- -- +/- +/- ... +/- -- . . . . . . . . . . . -- +/- +/- ... +/- -- -- where are symbols that denote rows of the matrix, -- are symbols that denote columns of the matrix, "+" and "-" indicate -- whether corresponding n-tuple needs to be included in the elemental -- set or not, respectively. -- -- Number of the slice components must be the same as dimension of the -- elemental set. The slice must have two null positions. To construct -- complete n-tuple for particular element of the matrix the routine -- replaces first null position of the slice by the corresponding -- (or , if the flag tr is on) and second null position by the -- corresponding (or by , if the flag tr is on). */ void matrix_format ( MPL *mpl, SET *set, /* not changed */ MEMBER *memb, /* modified */ SLICE *slice, /* not changed */ int tr ) { SLICE *list, *col, *temp; TUPLE *tuple; SYMBOL *row; xassert(set != NULL); xassert(memb != NULL); xassert(slice != NULL); xassert(set->dimen == slice_dimen(mpl, slice)); xassert(memb->value.set->dim == set->dimen); xassert(slice_arity(mpl, slice) == 2); /* read the matrix heading that contains column symbols (there may be no columns at all) */ list = create_slice(mpl); while (mpl->token != T_ASSIGN) { /* read column symbol and append it to the column list */ if (!is_symbol(mpl)) error(mpl, "number, symbol, or := missing where expected"); list = expand_slice(mpl, list, read_symbol(mpl)); } get_token(mpl /* := */); /* read zero or more rows that contain matrix data */ while (is_symbol(mpl)) { /* read row symbol (if the matrix has no columns, row symbols are just ignored) */ row = read_symbol(mpl); /* read the matrix row accordingly to the column list */ for (col = list; col != NULL; col = col->next) { int which = 0; /* check indicator */ if (is_literal(mpl, "+")) ; else if (is_literal(mpl, "-")) { get_token(mpl /* - */); continue; } else { int lack = slice_dimen(mpl, col); if (lack == 1) error(mpl, "one item missing in data group beginning " "with %s", format_symbol(mpl, row)); else error(mpl, "%d items missing in data group beginning " "with %s", lack, format_symbol(mpl, row)); } /* construct complete n-tuple */ tuple = create_tuple(mpl); for (temp = slice; temp != NULL; temp = temp->next) { if (temp->sym == NULL) { /* substitution is needed */ switch (++which) { case 1: /* substitute in the first null position */ tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, tr ? col->sym : row)); break; case 2: /* substitute in the second null position */ tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, tr ? row : col->sym)); break; default: xassert(which != which); } } else { /* copy symbol from the slice */ tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, temp->sym)); } } xassert(which == 2); /* add constructed n-tuple to elemental set */ check_then_add(mpl, memb->value.set, tuple); get_token(mpl /* + */); } /* delete the row symbol */ delete_symbol(mpl, row); } /* delete the column list */ delete_slice(mpl, list); return; } /*---------------------------------------------------------------------- -- set_data - read set data. -- -- This routine reads set data using the syntax: -- -- ::= set ; -- ::= set [ ] ; -- ::= -- ::= -- ::= , := -- ::= , ( ) -- ::= , -- ::= , : -- ::= , (tr) -- ::= , (tr) : -- -- Commae in are optional and may be omitted anywhere. */ void set_data(MPL *mpl) { SET *set; TUPLE *tuple; MEMBER *memb; SLICE *slice; int tr = 0; xassert(is_literal(mpl, "set")); get_token(mpl /* set */); /* symbolic name of set must follows the keyword 'set' */ if (!is_symbol(mpl)) error(mpl, "set name missing where expected"); /* select the set to saturate it with data */ set = select_set(mpl, mpl->image); get_token(mpl /* */); /* read optional subscript list, which identifies member of the set to be read */ tuple = create_tuple(mpl); if (mpl->token == T_LBRACKET) { /* subscript list is specified */ if (set->dim == 0) error(mpl, "%s cannot be subscripted", set->name); get_token(mpl /* [ */); /* read symbols and construct subscript list */ for (;;) { if (!is_symbol(mpl)) error(mpl, "number or symbol missing where expected"); tuple = expand_tuple(mpl, tuple, read_symbol(mpl)); if (mpl->token == T_COMMA) get_token(mpl /* , */); else if (mpl->token == T_RBRACKET) break; else error(mpl, "syntax error in subscript list"); } if (set->dim != tuple_dimen(mpl, tuple)) error(mpl, "%s must have %d subscript%s rather than %d", set->name, set->dim, set->dim == 1 ? "" : "s", tuple_dimen(mpl, tuple)); get_token(mpl /* ] */); } else { /* subscript list is not specified */ if (set->dim != 0) error(mpl, "%s must be subscripted", set->name); } /* there must be no member with the same subscript list */ if (find_member(mpl, set->array, tuple) != NULL) error(mpl, "%s%s already defined", set->name, format_tuple(mpl, '[', tuple)); /* add new member to the set and assign it empty elemental set */ memb = add_member(mpl, set->array, tuple); memb->value.set = create_elemset(mpl, set->dimen); /* create an initial fake slice of all asterisks */ slice = fake_slice(mpl, set->dimen); /* read zero or more data assignments */ for (;;) { /* skip optional comma */ if (mpl->token == T_COMMA) get_token(mpl /* , */); /* process assignment element */ if (mpl->token == T_ASSIGN) { /* assignment ligature is non-significant element */ get_token(mpl /* := */); } else if (mpl->token == T_LEFT) { /* left parenthesis begins either new slice or "transpose" indicator */ int is_tr; get_token(mpl /* ( */); is_tr = is_literal(mpl, "tr"); unget_token(mpl /* ( */); if (is_tr) goto left; /* delete the current slice and read new one */ delete_slice(mpl, slice); slice = read_slice(mpl, set->name, set->dimen); /* each new slice resets the "transpose" indicator */ tr = 0; /* if the new slice is 0-ary, formally there is one 0-tuple (in the simple format) that follows it */ if (slice_arity(mpl, slice) == 0) simple_format(mpl, set, memb, slice); } else if (is_symbol(mpl)) { /* number or symbol begins data in the simple format */ simple_format(mpl, set, memb, slice); } else if (mpl->token == T_COLON) { /* colon begins data in the matrix format */ if (slice_arity(mpl, slice) != 2) err1: error(mpl, "slice currently used must specify 2 asterisk" "s, not %d", slice_arity(mpl, slice)); get_token(mpl /* : */); /* read elemental set data in the matrix format */ matrix_format(mpl, set, memb, slice, tr); } else if (mpl->token == T_LEFT) left: { /* left parenthesis begins the "transpose" indicator, which is followed by data in the matrix format */ get_token(mpl /* ( */); if (!is_literal(mpl, "tr")) err2: error(mpl, "transpose indicator (tr) incomplete"); if (slice_arity(mpl, slice) != 2) goto err1; get_token(mpl /* tr */); if (mpl->token != T_RIGHT) goto err2; get_token(mpl /* ) */); /* in this case the colon is optional */ if (mpl->token == T_COLON) get_token(mpl /* : */); /* set the "transpose" indicator */ tr = 1; /* read elemental set data in the matrix format */ matrix_format(mpl, set, memb, slice, tr); } else if (mpl->token == T_SEMICOLON) { /* semicolon terminates the data block */ get_token(mpl /* ; */); break; } else error(mpl, "syntax error in set data block"); } /* delete the current slice */ delete_slice(mpl, slice); return; } /*---------------------------------------------------------------------- -- select_parameter - select parameter to saturate it with data. -- -- This routine selects parameter to saturate it with data provided in -- the data section. */ PARAMETER *select_parameter ( MPL *mpl, char *name /* not changed */ ) { PARAMETER *par; AVLNODE *node; xassert(name != NULL); node = avl_find_node(mpl->tree, name); if (node == NULL || avl_get_node_type(node) != A_PARAMETER) error(mpl, "%s not a parameter", name); par = (PARAMETER *)avl_get_node_link(node); if (par->assign != NULL) error(mpl, "%s needs no data", name); if (par->data) error(mpl, "%s already provided with data", name); par->data = 1; return par; } /*---------------------------------------------------------------------- -- set_default - set default parameter value. -- -- This routine sets default value for specified parameter. */ void set_default ( MPL *mpl, PARAMETER *par, /* not changed */ SYMBOL *altval /* destroyed */ ) { xassert(par != NULL); xassert(altval != NULL); if (par->option != NULL) error(mpl, "default value for %s already specified in model se" "ction", par->name); xassert(par->defval == NULL); par->defval = altval; return; } /*---------------------------------------------------------------------- -- read_value - read value and assign it to parameter member. -- -- This routine reads numeric or symbolic value from the input stream -- and assigns to new parameter member specified by its n-tuple, which -- (the member) is created and added to the parameter array. */ MEMBER *read_value ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* destroyed */ ) { MEMBER *memb; xassert(par != NULL); xassert(is_symbol(mpl)); /* there must be no member with the same n-tuple */ if (find_member(mpl, par->array, tuple) != NULL) error(mpl, "%s%s already defined", par->name, format_tuple(mpl, '[', tuple)); /* create new parameter member with given n-tuple */ memb = add_member(mpl, par->array, tuple); /* read value and assigns it to the new parameter member */ switch (par->type) { case A_NUMERIC: case A_INTEGER: case A_BINARY: if (!is_number(mpl)) error(mpl, "%s requires numeric data", par->name); memb->value.num = read_number(mpl); break; case A_SYMBOLIC: memb->value.sym = read_symbol(mpl); break; default: xassert(par != par); } return memb; } /*---------------------------------------------------------------------- -- plain_format - read parameter data block in plain format. -- -- This routine reads parameter data block using the syntax: -- -- ::= , , ... , , -- -- where are used to determine a complete subscript list for -- parameter member, is a numeric or symbolic value assigned to -- the parameter member. Commae between data items are optional and may -- be omitted anywhere. -- -- Number of components in the slice must be the same as dimension of -- the parameter. To construct the complete subscript list the routine -- replaces null positions in the slice by corresponding . */ void plain_format ( MPL *mpl, PARAMETER *par, /* not changed */ SLICE *slice /* not changed */ ) { TUPLE *tuple; SLICE *temp; SYMBOL *sym, *with = NULL; xassert(par != NULL); xassert(par->dim == slice_dimen(mpl, slice)); xassert(is_symbol(mpl)); /* read symbols and construct complete subscript list */ tuple = create_tuple(mpl); for (temp = slice; temp != NULL; temp = temp->next) { if (temp->sym == NULL) { /* substitution is needed; read symbol */ if (!is_symbol(mpl)) { int lack = slice_arity(mpl, temp) + 1; xassert(with != NULL); xassert(lack > 1); error(mpl, "%d items missing in data group beginning wit" "h %s", lack, format_symbol(mpl, with)); } sym = read_symbol(mpl); if (with == NULL) with = sym; } else { /* copy symbol from the slice */ sym = copy_symbol(mpl, temp->sym); } /* append the symbol to the subscript list */ tuple = expand_tuple(mpl, tuple, sym); /* skip optional comma */ if (mpl->token == T_COMMA) get_token(mpl /* , */); } /* read value and assign it to new parameter member */ if (!is_symbol(mpl)) { xassert(with != NULL); error(mpl, "one item missing in data group beginning with %s", format_symbol(mpl, with)); } read_value(mpl, par, tuple); return; } /*---------------------------------------------------------------------- -- tabular_format - read parameter data block in tabular format. -- -- This routine reads parameter data block using the syntax: -- -- ::= ... := -- ... -- ... -- . . . . . . . . . . . -- ... -- -- where are symbols that denote rows of the table, -- are symbols that denote columns of the table, are numeric -- or symbolic values assigned to the corresponding parameter members. -- If is specified as single point, no value is provided. -- -- Number of components in the slice must be the same as dimension of -- the parameter. The slice must have two null positions. To construct -- complete subscript list for particular the routine replaces -- the first null position of the slice by the corresponding (or -- , if the flag tr is on) and the second null position by the -- corresponding (or by , if the flag tr is on). */ void tabular_format ( MPL *mpl, PARAMETER *par, /* not changed */ SLICE *slice, /* not changed */ int tr ) { SLICE *list, *col, *temp; TUPLE *tuple; SYMBOL *row; xassert(par != NULL); xassert(par->dim == slice_dimen(mpl, slice)); xassert(slice_arity(mpl, slice) == 2); /* read the table heading that contains column symbols (the table may have no columns) */ list = create_slice(mpl); while (mpl->token != T_ASSIGN) { /* read column symbol and append it to the column list */ if (!is_symbol(mpl)) error(mpl, "number, symbol, or := missing where expected"); list = expand_slice(mpl, list, read_symbol(mpl)); } get_token(mpl /* := */); /* read zero or more rows that contain tabular data */ while (is_symbol(mpl)) { /* read row symbol (if the table has no columns, these symbols are just ignored) */ row = read_symbol(mpl); /* read values accordingly to the column list */ for (col = list; col != NULL; col = col->next) { int which = 0; /* if the token is single point, no value is provided */ if (is_literal(mpl, ".")) { get_token(mpl /* . */); continue; } /* construct complete subscript list */ tuple = create_tuple(mpl); for (temp = slice; temp != NULL; temp = temp->next) { if (temp->sym == NULL) { /* substitution is needed */ switch (++which) { case 1: /* substitute in the first null position */ tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, tr ? col->sym : row)); break; case 2: /* substitute in the second null position */ tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, tr ? row : col->sym)); break; default: xassert(which != which); } } else { /* copy symbol from the slice */ tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, temp->sym)); } } xassert(which == 2); /* read value and assign it to new parameter member */ if (!is_symbol(mpl)) { int lack = slice_dimen(mpl, col); if (lack == 1) error(mpl, "one item missing in data group beginning " "with %s", format_symbol(mpl, row)); else error(mpl, "%d items missing in data group beginning " "with %s", lack, format_symbol(mpl, row)); } read_value(mpl, par, tuple); } /* delete the row symbol */ delete_symbol(mpl, row); } /* delete the column list */ delete_slice(mpl, list); return; } /*---------------------------------------------------------------------- -- tabbing_format - read parameter data block in tabbing format. -- -- This routine reads parameter data block using the syntax: -- -- ::= , ... , , := , -- , ... , , , ... , , -- , ... , , , ... , , -- . . . . . . . . . . . . . . . . . -- , ... , , , ... , -- ::= -- ::= : -- -- where are names of parameters (all the parameters must be -- subscripted and have identical dimensions), are symbols -- used to define subscripts of parameter members, are numeric -- or symbolic values assigned to the corresponding parameter members. -- Optional may specify a simple set, in which case n-tuples -- built of for each row of the data table (i.e. subscripts -- of parameter members) are added to the specified set. Commae between -- data items are optional and may be omitted anywhere. -- -- If the parameter altval is not NULL, it specifies a default value -- provided for all the parameters specified in the data block. */ void tabbing_format ( MPL *mpl, SYMBOL *altval /* not changed */ ) { SET *set = NULL; PARAMETER *par; SLICE *list, *col; TUPLE *tuple; int next_token, j, dim = 0; char *last_name = NULL; /* read the optional */ if (is_symbol(mpl)) { get_token(mpl /* */); next_token = mpl->token; unget_token(mpl /* */); if (next_token == T_COLON) { /* select the set to saturate it with data */ set = select_set(mpl, mpl->image); /* the set must be simple (i.e. not set of sets) */ if (set->dim != 0) error(mpl, "%s must be a simple set", set->name); /* and must not be defined yet */ if (set->array->head != NULL) error(mpl, "%s already defined", set->name); /* add new (the only) member to the set and assign it empty elemental set */ add_member(mpl, set->array, NULL)->value.set = create_elemset(mpl, set->dimen); last_name = set->name, dim = set->dimen; get_token(mpl /* */); xassert(mpl->token == T_COLON); get_token(mpl /* : */); } } /* read the table heading that contains parameter names */ list = create_slice(mpl); while (mpl->token != T_ASSIGN) { /* there must be symbolic name of parameter */ if (!is_symbol(mpl)) error(mpl, "parameter name or := missing where expected"); /* select the parameter to saturate it with data */ par = select_parameter(mpl, mpl->image); /* the parameter must be subscripted */ if (par->dim == 0) error(mpl, "%s not a subscripted parameter", mpl->image); /* the set (if specified) and all the parameters in the data block must have identical dimension */ if (dim != 0 && par->dim != dim) { xassert(last_name != NULL); error(mpl, "%s has dimension %d while %s has dimension %d", last_name, dim, par->name, par->dim); } /* set default value for the parameter (if specified) */ if (altval != NULL) set_default(mpl, par, copy_symbol(mpl, altval)); /* append the parameter to the column list */ list = expand_slice(mpl, list, (SYMBOL *)par); last_name = par->name, dim = par->dim; get_token(mpl /* */); /* skip optional comma */ if (mpl->token == T_COMMA) get_token(mpl /* , */); } if (slice_dimen(mpl, list) == 0) error(mpl, "at least one parameter name required"); get_token(mpl /* := */); /* skip optional comma */ if (mpl->token == T_COMMA) get_token(mpl /* , */); /* read rows that contain tabbing data */ while (is_symbol(mpl)) { /* read subscript list */ tuple = create_tuple(mpl); for (j = 1; j <= dim; j++) { /* read j-th subscript */ if (!is_symbol(mpl)) { int lack = slice_dimen(mpl, list) + dim - j + 1; xassert(tuple != NULL); xassert(lack > 1); error(mpl, "%d items missing in data group beginning wit" "h %s", lack, format_symbol(mpl, tuple->sym)); } /* read and append j-th subscript to the n-tuple */ tuple = expand_tuple(mpl, tuple, read_symbol(mpl)); /* skip optional comma *between* */ if (j < dim && mpl->token == T_COMMA) get_token(mpl /* , */); } /* if the set is specified, add to it new n-tuple, which is a copy of the subscript list just read */ if (set != NULL) check_then_add(mpl, set->array->head->value.set, copy_tuple(mpl, tuple)); /* skip optional comma between and */ if (mpl->token == T_COMMA) get_token(mpl /* , */); /* read values accordingly to the column list */ for (col = list; col != NULL; col = col->next) { /* if the token is single point, no value is provided */ if (is_literal(mpl, ".")) { get_token(mpl /* . */); continue; } /* read value and assign it to new parameter member */ if (!is_symbol(mpl)) { int lack = slice_dimen(mpl, col); xassert(tuple != NULL); if (lack == 1) error(mpl, "one item missing in data group beginning " "with %s", format_symbol(mpl, tuple->sym)); else error(mpl, "%d items missing in data group beginning " "with %s", lack, format_symbol(mpl, tuple->sym)); } read_value(mpl, (PARAMETER *)col->sym, copy_tuple(mpl, tuple)); /* skip optional comma preceding the next value */ if (col->next != NULL && mpl->token == T_COMMA) get_token(mpl /* , */); } /* delete the original subscript list */ delete_tuple(mpl, tuple); /* skip optional comma (only if there is next data group) */ if (mpl->token == T_COMMA) { get_token(mpl /* , */); if (!is_symbol(mpl)) unget_token(mpl /* , */); } } /* delete the column list (it contains parameters, not symbols, so nullify it before) */ for (col = list; col != NULL; col = col->next) col->sym = NULL; delete_slice(mpl, list); return; } /*---------------------------------------------------------------------- -- parameter_data - read parameter data. -- -- This routine reads parameter data using the syntax: -- -- ::= param : ; -- ::= param -- ; -- ::= -- ::= -- ::= default -- ::= -- ::= , := -- ::= , [ ] -- ::= , -- ::= , : -- ::= , (tr) -- ::= , (tr) : -- -- Commae in are optional and may be omitted anywhere. */ void parameter_data(MPL *mpl) { PARAMETER *par; SYMBOL *altval = NULL; SLICE *slice; int tr = 0; xassert(is_literal(mpl, "param")); get_token(mpl /* param */); /* read optional default value */ if (is_literal(mpl, "default")) { get_token(mpl /* default */); if (!is_symbol(mpl)) error(mpl, "default value missing where expected"); altval = read_symbol(mpl); /* if the default value follows the keyword 'param', the next token must be only the colon */ if (mpl->token != T_COLON) error(mpl, "colon missing where expected"); } /* being used after the keyword 'param' or the optional default value the colon begins data in the tabbing format */ if (mpl->token == T_COLON) { get_token(mpl /* : */); /* skip optional comma */ if (mpl->token == T_COMMA) get_token(mpl /* , */); /* read parameter data in the tabbing format */ tabbing_format(mpl, altval); /* on reading data in the tabbing format the default value is always copied, so delete the original symbol */ if (altval != NULL) delete_symbol(mpl, altval); /* the next token must be only semicolon */ if (mpl->token != T_SEMICOLON) error(mpl, "symbol, number, or semicolon missing where expe" "cted"); get_token(mpl /* ; */); goto done; } /* in other cases there must be symbolic name of parameter, which follows the keyword 'param' */ if (!is_symbol(mpl)) error(mpl, "parameter name missing where expected"); /* select the parameter to saturate it with data */ par = select_parameter(mpl, mpl->image); get_token(mpl /* */); /* read optional default value */ if (is_literal(mpl, "default")) { get_token(mpl /* default */); if (!is_symbol(mpl)) error(mpl, "default value missing where expected"); altval = read_symbol(mpl); /* set default value for the parameter */ set_default(mpl, par, altval); } /* create initial fake slice of all asterisks */ slice = fake_slice(mpl, par->dim); /* read zero or more data assignments */ for (;;) { /* skip optional comma */ if (mpl->token == T_COMMA) get_token(mpl /* , */); /* process current assignment */ if (mpl->token == T_ASSIGN) { /* assignment ligature is non-significant element */ get_token(mpl /* := */); } else if (mpl->token == T_LBRACKET) { /* left bracket begins new slice; delete the current slice and read new one */ delete_slice(mpl, slice); slice = read_slice(mpl, par->name, par->dim); /* each new slice resets the "transpose" indicator */ tr = 0; } else if (is_symbol(mpl)) { /* number or symbol begins data in the plain format */ plain_format(mpl, par, slice); } else if (mpl->token == T_COLON) { /* colon begins data in the tabular format */ if (par->dim == 0) err1: error(mpl, "%s not a subscripted parameter", par->name); if (slice_arity(mpl, slice) != 2) err2: error(mpl, "slice currently used must specify 2 asterisk" "s, not %d", slice_arity(mpl, slice)); get_token(mpl /* : */); /* read parameter data in the tabular format */ tabular_format(mpl, par, slice, tr); } else if (mpl->token == T_LEFT) { /* left parenthesis begins the "transpose" indicator, which is followed by data in the tabular format */ get_token(mpl /* ( */); if (!is_literal(mpl, "tr")) err3: error(mpl, "transpose indicator (tr) incomplete"); if (par->dim == 0) goto err1; if (slice_arity(mpl, slice) != 2) goto err2; get_token(mpl /* tr */); if (mpl->token != T_RIGHT) goto err3; get_token(mpl /* ) */); /* in this case the colon is optional */ if (mpl->token == T_COLON) get_token(mpl /* : */); /* set the "transpose" indicator */ tr = 1; /* read parameter data in the tabular format */ tabular_format(mpl, par, slice, tr); } else if (mpl->token == T_SEMICOLON) { /* semicolon terminates the data block */ get_token(mpl /* ; */); break; } else error(mpl, "syntax error in parameter data block"); } /* delete the current slice */ delete_slice(mpl, slice); done: return; } /*---------------------------------------------------------------------- -- data_section - read data section. -- -- This routine reads data section using the syntax: -- -- ::= -- ::= ; -- ::= -- ::= -- -- Reading data section is terminated by either the keyword 'end' or -- the end of file. */ void data_section(MPL *mpl) { while (!(mpl->token == T_EOF || is_literal(mpl, "end"))) { if (is_literal(mpl, "set")) set_data(mpl); else if (is_literal(mpl, "param")) parameter_data(mpl); else error(mpl, "syntax error in data section"); } return; } /* eof */ glpk-4.52.1/src/glpmpl03.c0000644000062000006210000064542312175147600014330 0ustar maomkpasswd/* glpmpl03.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_ERRNO #define _GLPSTD_STDIO #include "env.h" #include "glpmpl.h" /**********************************************************************/ /* * * FLOATING-POINT NUMBERS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- fp_add - floating-point addition. -- -- This routine computes the sum x + y. */ double fp_add(MPL *mpl, double x, double y) { if (x > 0.0 && y > 0.0 && x > + 0.999 * DBL_MAX - y || x < 0.0 && y < 0.0 && x < - 0.999 * DBL_MAX - y) error(mpl, "%.*g + %.*g; floating-point overflow", DBL_DIG, x, DBL_DIG, y); return x + y; } /*---------------------------------------------------------------------- -- fp_sub - floating-point subtraction. -- -- This routine computes the difference x - y. */ double fp_sub(MPL *mpl, double x, double y) { if (x > 0.0 && y < 0.0 && x > + 0.999 * DBL_MAX + y || x < 0.0 && y > 0.0 && x < - 0.999 * DBL_MAX + y) error(mpl, "%.*g - %.*g; floating-point overflow", DBL_DIG, x, DBL_DIG, y); return x - y; } /*---------------------------------------------------------------------- -- fp_less - floating-point non-negative subtraction. -- -- This routine computes the non-negative difference max(0, x - y). */ double fp_less(MPL *mpl, double x, double y) { if (x < y) return 0.0; if (x > 0.0 && y < 0.0 && x > + 0.999 * DBL_MAX + y) error(mpl, "%.*g less %.*g; floating-point overflow", DBL_DIG, x, DBL_DIG, y); return x - y; } /*---------------------------------------------------------------------- -- fp_mul - floating-point multiplication. -- -- This routine computes the product x * y. */ double fp_mul(MPL *mpl, double x, double y) { if (fabs(y) > 1.0 && fabs(x) > (0.999 * DBL_MAX) / fabs(y)) error(mpl, "%.*g * %.*g; floating-point overflow", DBL_DIG, x, DBL_DIG, y); return x * y; } /*---------------------------------------------------------------------- -- fp_div - floating-point division. -- -- This routine computes the quotient x / y. */ double fp_div(MPL *mpl, double x, double y) { if (fabs(y) < DBL_MIN) error(mpl, "%.*g / %.*g; floating-point zero divide", DBL_DIG, x, DBL_DIG, y); if (fabs(y) < 1.0 && fabs(x) > (0.999 * DBL_MAX) * fabs(y)) error(mpl, "%.*g / %.*g; floating-point overflow", DBL_DIG, x, DBL_DIG, y); return x / y; } /*---------------------------------------------------------------------- -- fp_idiv - floating-point quotient of exact division. -- -- This routine computes the quotient of exact division x div y. */ double fp_idiv(MPL *mpl, double x, double y) { if (fabs(y) < DBL_MIN) error(mpl, "%.*g div %.*g; floating-point zero divide", DBL_DIG, x, DBL_DIG, y); if (fabs(y) < 1.0 && fabs(x) > (0.999 * DBL_MAX) * fabs(y)) error(mpl, "%.*g div %.*g; floating-point overflow", DBL_DIG, x, DBL_DIG, y); x /= y; return x > 0.0 ? floor(x) : x < 0.0 ? ceil(x) : 0.0; } /*---------------------------------------------------------------------- -- fp_mod - floating-point remainder of exact division. -- -- This routine computes the remainder of exact division x mod y. -- -- NOTE: By definition x mod y = x - y * floor(x / y). */ double fp_mod(MPL *mpl, double x, double y) { double r; xassert(mpl == mpl); if (x == 0.0) r = 0.0; else if (y == 0.0) r = x; else { r = fmod(fabs(x), fabs(y)); if (r != 0.0) { if (x < 0.0) r = - r; if (x > 0.0 && y < 0.0 || x < 0.0 && y > 0.0) r += y; } } return r; } /*---------------------------------------------------------------------- -- fp_power - floating-point exponentiation (raise to power). -- -- This routine computes the exponentiation x ** y. */ double fp_power(MPL *mpl, double x, double y) { double r; if (x == 0.0 && y <= 0.0 || x < 0.0 && y != floor(y)) error(mpl, "%.*g ** %.*g; result undefined", DBL_DIG, x, DBL_DIG, y); if (x == 0.0) goto eval; if (fabs(x) > 1.0 && y > +1.0 && +log(fabs(x)) > (0.999 * log(DBL_MAX)) / y || fabs(x) < 1.0 && y < -1.0 && +log(fabs(x)) < (0.999 * log(DBL_MAX)) / y) error(mpl, "%.*g ** %.*g; floating-point overflow", DBL_DIG, x, DBL_DIG, y); if (fabs(x) > 1.0 && y < -1.0 && -log(fabs(x)) < (0.999 * log(DBL_MAX)) / y || fabs(x) < 1.0 && y > +1.0 && -log(fabs(x)) > (0.999 * log(DBL_MAX)) / y) r = 0.0; else eval: r = pow(x, y); return r; } /*---------------------------------------------------------------------- -- fp_exp - floating-point base-e exponential. -- -- This routine computes the base-e exponential e ** x. */ double fp_exp(MPL *mpl, double x) { if (x > 0.999 * log(DBL_MAX)) error(mpl, "exp(%.*g); floating-point overflow", DBL_DIG, x); return exp(x); } /*---------------------------------------------------------------------- -- fp_log - floating-point natural logarithm. -- -- This routine computes the natural logarithm log x. */ double fp_log(MPL *mpl, double x) { if (x <= 0.0) error(mpl, "log(%.*g); non-positive argument", DBL_DIG, x); return log(x); } /*---------------------------------------------------------------------- -- fp_log10 - floating-point common (decimal) logarithm. -- -- This routine computes the common (decimal) logarithm lg x. */ double fp_log10(MPL *mpl, double x) { if (x <= 0.0) error(mpl, "log10(%.*g); non-positive argument", DBL_DIG, x); return log10(x); } /*---------------------------------------------------------------------- -- fp_sqrt - floating-point square root. -- -- This routine computes the square root x ** 0.5. */ double fp_sqrt(MPL *mpl, double x) { if (x < 0.0) error(mpl, "sqrt(%.*g); negative argument", DBL_DIG, x); return sqrt(x); } /*---------------------------------------------------------------------- -- fp_sin - floating-point trigonometric sine. -- -- This routine computes the trigonometric sine sin(x). */ double fp_sin(MPL *mpl, double x) { if (!(-1e6 <= x && x <= +1e6)) error(mpl, "sin(%.*g); argument too large", DBL_DIG, x); return sin(x); } /*---------------------------------------------------------------------- -- fp_cos - floating-point trigonometric cosine. -- -- This routine computes the trigonometric cosine cos(x). */ double fp_cos(MPL *mpl, double x) { if (!(-1e6 <= x && x <= +1e6)) error(mpl, "cos(%.*g); argument too large", DBL_DIG, x); return cos(x); } /*---------------------------------------------------------------------- -- fp_atan - floating-point trigonometric arctangent. -- -- This routine computes the trigonometric arctangent atan(x). */ double fp_atan(MPL *mpl, double x) { xassert(mpl == mpl); return atan(x); } /*---------------------------------------------------------------------- -- fp_atan2 - floating-point trigonometric arctangent. -- -- This routine computes the trigonometric arctangent atan(y / x). */ double fp_atan2(MPL *mpl, double y, double x) { xassert(mpl == mpl); return atan2(y, x); } /*---------------------------------------------------------------------- -- fp_round - round floating-point value to n fractional digits. -- -- This routine rounds given floating-point value x to n fractional -- digits with the formula: -- -- round(x, n) = floor(x * 10^n + 0.5) / 10^n. -- -- The parameter n is assumed to be integer. */ double fp_round(MPL *mpl, double x, double n) { double ten_to_n; if (n != floor(n)) error(mpl, "round(%.*g, %.*g); non-integer second argument", DBL_DIG, x, DBL_DIG, n); if (n <= DBL_DIG + 2) { ten_to_n = pow(10.0, n); if (fabs(x) < (0.999 * DBL_MAX) / ten_to_n) { x = floor(x * ten_to_n + 0.5); if (x != 0.0) x /= ten_to_n; } } return x; } /*---------------------------------------------------------------------- -- fp_trunc - truncate floating-point value to n fractional digits. -- -- This routine truncates given floating-point value x to n fractional -- digits with the formula: -- -- ( floor(x * 10^n) / 10^n, if x >= 0 -- trunc(x, n) = < -- ( ceil(x * 10^n) / 10^n, if x < 0 -- -- The parameter n is assumed to be integer. */ double fp_trunc(MPL *mpl, double x, double n) { double ten_to_n; if (n != floor(n)) error(mpl, "trunc(%.*g, %.*g); non-integer second argument", DBL_DIG, x, DBL_DIG, n); if (n <= DBL_DIG + 2) { ten_to_n = pow(10.0, n); if (fabs(x) < (0.999 * DBL_MAX) / ten_to_n) { x = (x >= 0.0 ? floor(x * ten_to_n) : ceil(x * ten_to_n)); if (x != 0.0) x /= ten_to_n; } } return x; } /**********************************************************************/ /* * * PSEUDO-RANDOM NUMBER GENERATORS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- fp_irand224 - pseudo-random integer in the range [0, 2^24). -- -- This routine returns a next pseudo-random integer (converted to -- floating-point) which is uniformly distributed between 0 and 2^24-1, -- inclusive. */ #define two_to_the_24 0x1000000 double fp_irand224(MPL *mpl) { return (double)rng_unif_rand(mpl->rand, two_to_the_24); } /*---------------------------------------------------------------------- -- fp_uniform01 - pseudo-random number in the range [0, 1). -- -- This routine returns a next pseudo-random number which is uniformly -- distributed in the range [0, 1). */ #define two_to_the_31 ((unsigned int)0x80000000) double fp_uniform01(MPL *mpl) { return (double)rng_next_rand(mpl->rand) / (double)two_to_the_31; } /*---------------------------------------------------------------------- -- fp_uniform - pseudo-random number in the range [a, b). -- -- This routine returns a next pseudo-random number which is uniformly -- distributed in the range [a, b). */ double fp_uniform(MPL *mpl, double a, double b) { double x; if (a >= b) error(mpl, "Uniform(%.*g, %.*g); invalid range", DBL_DIG, a, DBL_DIG, b); x = fp_uniform01(mpl); #if 0 x = a * (1.0 - x) + b * x; #else x = fp_add(mpl, a * (1.0 - x), b * x); #endif return x; } /*---------------------------------------------------------------------- -- fp_normal01 - Gaussian random variate with mu = 0 and sigma = 1. -- -- This routine returns a Gaussian random variate with zero mean and -- unit standard deviation. The polar (Box-Mueller) method is used. -- -- This code is a modified version of the routine gsl_ran_gaussian from -- the GNU Scientific Library Version 1.0. */ double fp_normal01(MPL *mpl) { double x, y, r2; do { /* choose x, y in uniform square (-1,-1) to (+1,+1) */ x = -1.0 + 2.0 * fp_uniform01(mpl); y = -1.0 + 2.0 * fp_uniform01(mpl); /* see if it is in the unit circle */ r2 = x * x + y * y; } while (r2 > 1.0 || r2 == 0.0); /* Box-Muller transform */ return y * sqrt(-2.0 * log (r2) / r2); } /*---------------------------------------------------------------------- -- fp_normal - Gaussian random variate with specified mu and sigma. -- -- This routine returns a Gaussian random variate with mean mu and -- standard deviation sigma. */ double fp_normal(MPL *mpl, double mu, double sigma) { double x; #if 0 x = mu + sigma * fp_normal01(mpl); #else x = fp_add(mpl, mu, fp_mul(mpl, sigma, fp_normal01(mpl))); #endif return x; } /**********************************************************************/ /* * * SEGMENTED CHARACTER STRINGS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- create_string - create character string. -- -- This routine creates a segmented character string, which is exactly -- equivalent to specified character string. */ STRING *create_string ( MPL *mpl, char buf[MAX_LENGTH+1] /* not changed */ ) #if 0 { STRING *head, *tail; int i, j; xassert(buf != NULL); xassert(strlen(buf) <= MAX_LENGTH); head = tail = dmp_get_atom(mpl->strings, sizeof(STRING)); for (i = j = 0; ; i++) { if ((tail->seg[j++] = buf[i]) == '\0') break; if (j == STRSEG_SIZE) tail = (tail->next = dmp_get_atom(mpl->strings, sizeof(STRING))), j = 0; } tail->next = NULL; return head; } #else { STRING *str; xassert(strlen(buf) <= MAX_LENGTH); str = dmp_get_atom(mpl->strings, strlen(buf)+1); strcpy(str, buf); return str; } #endif /*---------------------------------------------------------------------- -- copy_string - make copy of character string. -- -- This routine returns an exact copy of segmented character string. */ STRING *copy_string ( MPL *mpl, STRING *str /* not changed */ ) #if 0 { STRING *head, *tail; xassert(str != NULL); head = tail = dmp_get_atom(mpl->strings, sizeof(STRING)); for (; str != NULL; str = str->next) { memcpy(tail->seg, str->seg, STRSEG_SIZE); if (str->next != NULL) tail = (tail->next = dmp_get_atom(mpl->strings, sizeof(STRING))); } tail->next = NULL; return head; } #else { xassert(mpl == mpl); return create_string(mpl, str); } #endif /*---------------------------------------------------------------------- -- compare_strings - compare one character string with another. -- -- This routine compares one segmented character strings with another -- and returns the result of comparison as follows: -- -- = 0 - both strings are identical; -- < 0 - the first string precedes the second one; -- > 0 - the first string follows the second one. */ int compare_strings ( MPL *mpl, STRING *str1, /* not changed */ STRING *str2 /* not changed */ ) #if 0 { int j, c1, c2; xassert(mpl == mpl); for (;; str1 = str1->next, str2 = str2->next) { xassert(str1 != NULL); xassert(str2 != NULL); for (j = 0; j < STRSEG_SIZE; j++) { c1 = (unsigned char)str1->seg[j]; c2 = (unsigned char)str2->seg[j]; if (c1 < c2) return -1; if (c1 > c2) return +1; if (c1 == '\0') goto done; } } done: return 0; } #else { xassert(mpl == mpl); return strcmp(str1, str2); } #endif /*---------------------------------------------------------------------- -- fetch_string - extract content of character string. -- -- This routine returns a character string, which is exactly equivalent -- to specified segmented character string. */ char *fetch_string ( MPL *mpl, STRING *str, /* not changed */ char buf[MAX_LENGTH+1] /* modified */ ) #if 0 { int i, j; xassert(mpl == mpl); xassert(buf != NULL); for (i = 0; ; str = str->next) { xassert(str != NULL); for (j = 0; j < STRSEG_SIZE; j++) if ((buf[i++] = str->seg[j]) == '\0') goto done; } done: xassert(strlen(buf) <= MAX_LENGTH); return buf; } #else { xassert(mpl == mpl); return strcpy(buf, str); } #endif /*---------------------------------------------------------------------- -- delete_string - delete character string. -- -- This routine deletes specified segmented character string. */ void delete_string ( MPL *mpl, STRING *str /* destroyed */ ) #if 0 { STRING *temp; xassert(str != NULL); while (str != NULL) { temp = str; str = str->next; dmp_free_atom(mpl->strings, temp, sizeof(STRING)); } return; } #else { dmp_free_atom(mpl->strings, str, strlen(str)+1); return; } #endif /**********************************************************************/ /* * * SYMBOLS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- create_symbol_num - create symbol of numeric type. -- -- This routine creates a symbol, which has a numeric value specified -- as floating-point number. */ SYMBOL *create_symbol_num(MPL *mpl, double num) { SYMBOL *sym; sym = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); sym->num = num; sym->str = NULL; return sym; } /*---------------------------------------------------------------------- -- create_symbol_str - create symbol of abstract type. -- -- This routine creates a symbol, which has an abstract value specified -- as segmented character string. */ SYMBOL *create_symbol_str ( MPL *mpl, STRING *str /* destroyed */ ) { SYMBOL *sym; xassert(str != NULL); sym = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); sym->num = 0.0; sym->str = str; return sym; } /*---------------------------------------------------------------------- -- copy_symbol - make copy of symbol. -- -- This routine returns an exact copy of symbol. */ SYMBOL *copy_symbol ( MPL *mpl, SYMBOL *sym /* not changed */ ) { SYMBOL *copy; xassert(sym != NULL); copy = dmp_get_atom(mpl->symbols, sizeof(SYMBOL)); if (sym->str == NULL) { copy->num = sym->num; copy->str = NULL; } else { copy->num = 0.0; copy->str = copy_string(mpl, sym->str); } return copy; } /*---------------------------------------------------------------------- -- compare_symbols - compare one symbol with another. -- -- This routine compares one symbol with another and returns the result -- of comparison as follows: -- -- = 0 - both symbols are identical; -- < 0 - the first symbol precedes the second one; -- > 0 - the first symbol follows the second one. -- -- Note that the linear order, in which symbols follow each other, is -- implementation-dependent. It may be not an alphabetical order. */ int compare_symbols ( MPL *mpl, SYMBOL *sym1, /* not changed */ SYMBOL *sym2 /* not changed */ ) { xassert(sym1 != NULL); xassert(sym2 != NULL); /* let all numeric quantities precede all symbolic quantities */ if (sym1->str == NULL && sym2->str == NULL) { if (sym1->num < sym2->num) return -1; if (sym1->num > sym2->num) return +1; return 0; } if (sym1->str == NULL) return -1; if (sym2->str == NULL) return +1; return compare_strings(mpl, sym1->str, sym2->str); } /*---------------------------------------------------------------------- -- delete_symbol - delete symbol. -- -- This routine deletes specified symbol. */ void delete_symbol ( MPL *mpl, SYMBOL *sym /* destroyed */ ) { xassert(sym != NULL); if (sym->str != NULL) delete_string(mpl, sym->str); dmp_free_atom(mpl->symbols, sym, sizeof(SYMBOL)); return; } /*---------------------------------------------------------------------- -- format_symbol - format symbol for displaying or printing. -- -- This routine converts specified symbol to a charater string, which -- is suitable for displaying or printing. -- -- The resultant string is never longer than 255 characters. If it gets -- longer, it is truncated from the right and appended by dots. */ char *format_symbol ( MPL *mpl, SYMBOL *sym /* not changed */ ) { char *buf = mpl->sym_buf; xassert(sym != NULL); if (sym->str == NULL) sprintf(buf, "%.*g", DBL_DIG, sym->num); else { char str[MAX_LENGTH+1]; int quoted, j, len; fetch_string(mpl, sym->str, str); if (!(isalpha((unsigned char)str[0]) || str[0] == '_')) quoted = 1; else { quoted = 0; for (j = 1; str[j] != '\0'; j++) { if (!(isalnum((unsigned char)str[j]) || strchr("+-._", (unsigned char)str[j]) != NULL)) { quoted = 1; break; } } } # define safe_append(c) \ (void)(len < 255 ? (buf[len++] = (char)(c)) : 0) buf[0] = '\0', len = 0; if (quoted) safe_append('\''); for (j = 0; str[j] != '\0'; j++) { if (quoted && str[j] == '\'') safe_append('\''); safe_append(str[j]); } if (quoted) safe_append('\''); # undef safe_append buf[len] = '\0'; if (len == 255) strcpy(buf+252, "..."); } xassert(strlen(buf) <= 255); return buf; } /*---------------------------------------------------------------------- -- concat_symbols - concatenate one symbol with another. -- -- This routine concatenates values of two given symbols and assigns -- the resultant character string to a new symbol, which is returned on -- exit. Both original symbols are destroyed. */ SYMBOL *concat_symbols ( MPL *mpl, SYMBOL *sym1, /* destroyed */ SYMBOL *sym2 /* destroyed */ ) { char str1[MAX_LENGTH+1], str2[MAX_LENGTH+1]; xassert(MAX_LENGTH >= DBL_DIG + DBL_DIG); if (sym1->str == NULL) sprintf(str1, "%.*g", DBL_DIG, sym1->num); else fetch_string(mpl, sym1->str, str1); if (sym2->str == NULL) sprintf(str2, "%.*g", DBL_DIG, sym2->num); else fetch_string(mpl, sym2->str, str2); if (strlen(str1) + strlen(str2) > MAX_LENGTH) { char buf[255+1]; strcpy(buf, format_symbol(mpl, sym1)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s & %s; resultant symbol exceeds %d characters", buf, format_symbol(mpl, sym2), MAX_LENGTH); } delete_symbol(mpl, sym1); delete_symbol(mpl, sym2); return create_symbol_str(mpl, create_string(mpl, strcat(str1, str2))); } /**********************************************************************/ /* * * N-TUPLES * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- create_tuple - create n-tuple. -- -- This routine creates a n-tuple, which initially has no components, -- i.e. which is 0-tuple. */ TUPLE *create_tuple(MPL *mpl) { TUPLE *tuple; xassert(mpl == mpl); tuple = NULL; return tuple; } /*---------------------------------------------------------------------- -- expand_tuple - append symbol to n-tuple. -- -- This routine expands n-tuple appending to it a given symbol, which -- becomes its new last component. */ TUPLE *expand_tuple ( MPL *mpl, TUPLE *tuple, /* destroyed */ SYMBOL *sym /* destroyed */ ) { TUPLE *tail, *temp; xassert(sym != NULL); /* create a new component */ tail = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); tail->sym = sym; tail->next = NULL; /* and append it to the component list */ if (tuple == NULL) tuple = tail; else { for (temp = tuple; temp->next != NULL; temp = temp->next); temp->next = tail; } return tuple; } /*---------------------------------------------------------------------- -- tuple_dimen - determine dimension of n-tuple. -- -- This routine returns dimension of n-tuple, i.e. number of components -- in the n-tuple. */ int tuple_dimen ( MPL *mpl, TUPLE *tuple /* not changed */ ) { TUPLE *temp; int dim = 0; xassert(mpl == mpl); for (temp = tuple; temp != NULL; temp = temp->next) dim++; return dim; } /*---------------------------------------------------------------------- -- copy_tuple - make copy of n-tuple. -- -- This routine returns an exact copy of n-tuple. */ TUPLE *copy_tuple ( MPL *mpl, TUPLE *tuple /* not changed */ ) { TUPLE *head, *tail; if (tuple == NULL) head = NULL; else { head = tail = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); for (; tuple != NULL; tuple = tuple->next) { xassert(tuple->sym != NULL); tail->sym = copy_symbol(mpl, tuple->sym); if (tuple->next != NULL) tail = (tail->next = dmp_get_atom(mpl->tuples, sizeof(TUPLE))); } tail->next = NULL; } return head; } /*---------------------------------------------------------------------- -- compare_tuples - compare one n-tuple with another. -- -- This routine compares two given n-tuples, which must have the same -- dimension (not checked for the sake of efficiency), and returns one -- of the following codes: -- -- = 0 - both n-tuples are identical; -- < 0 - the first n-tuple precedes the second one; -- > 0 - the first n-tuple follows the second one. -- -- Note that the linear order, in which n-tuples follow each other, is -- implementation-dependent. It may be not an alphabetical order. */ int compare_tuples ( MPL *mpl, TUPLE *tuple1, /* not changed */ TUPLE *tuple2 /* not changed */ ) { TUPLE *item1, *item2; int ret; xassert(mpl == mpl); for (item1 = tuple1, item2 = tuple2; item1 != NULL; item1 = item1->next, item2 = item2->next) { xassert(item2 != NULL); xassert(item1->sym != NULL); xassert(item2->sym != NULL); ret = compare_symbols(mpl, item1->sym, item2->sym); if (ret != 0) return ret; } xassert(item2 == NULL); return 0; } /*---------------------------------------------------------------------- -- build_subtuple - build subtuple of given n-tuple. -- -- This routine builds subtuple, which consists of first dim components -- of given n-tuple. */ TUPLE *build_subtuple ( MPL *mpl, TUPLE *tuple, /* not changed */ int dim ) { TUPLE *head, *temp; int j; head = create_tuple(mpl); for (j = 1, temp = tuple; j <= dim; j++, temp = temp->next) { xassert(temp != NULL); head = expand_tuple(mpl, head, copy_symbol(mpl, temp->sym)); } return head; } /*---------------------------------------------------------------------- -- delete_tuple - delete n-tuple. -- -- This routine deletes specified n-tuple. */ void delete_tuple ( MPL *mpl, TUPLE *tuple /* destroyed */ ) { TUPLE *temp; while (tuple != NULL) { temp = tuple; tuple = temp->next; xassert(temp->sym != NULL); delete_symbol(mpl, temp->sym); dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); } return; } /*---------------------------------------------------------------------- -- format_tuple - format n-tuple for displaying or printing. -- -- This routine converts specified n-tuple to a character string, which -- is suitable for displaying or printing. -- -- The resultant string is never longer than 255 characters. If it gets -- longer, it is truncated from the right and appended by dots. */ char *format_tuple ( MPL *mpl, int c, TUPLE *tuple /* not changed */ ) { TUPLE *temp; int dim, j, len; char *buf = mpl->tup_buf, str[255+1], *save; # define safe_append(c) \ (void)(len < 255 ? (buf[len++] = (char)(c)) : 0) buf[0] = '\0', len = 0; dim = tuple_dimen(mpl, tuple); if (c == '[' && dim > 0) safe_append('['); if (c == '(' && dim > 1) safe_append('('); for (temp = tuple; temp != NULL; temp = temp->next) { if (temp != tuple) safe_append(','); xassert(temp->sym != NULL); save = mpl->sym_buf; mpl->sym_buf = str; format_symbol(mpl, temp->sym); mpl->sym_buf = save; xassert(strlen(str) < sizeof(str)); for (j = 0; str[j] != '\0'; j++) safe_append(str[j]); } if (c == '[' && dim > 0) safe_append(']'); if (c == '(' && dim > 1) safe_append(')'); # undef safe_append buf[len] = '\0'; if (len == 255) strcpy(buf+252, "..."); xassert(strlen(buf) <= 255); return buf; } /**********************************************************************/ /* * * ELEMENTAL SETS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- create_elemset - create elemental set. -- -- This routine creates an elemental set, whose members are n-tuples of -- specified dimension. Being created the set is initially empty. */ ELEMSET *create_elemset(MPL *mpl, int dim) { ELEMSET *set; xassert(dim > 0); set = create_array(mpl, A_NONE, dim); return set; } /*---------------------------------------------------------------------- -- find_tuple - check if elemental set contains given n-tuple. -- -- This routine finds given n-tuple in specified elemental set in order -- to check if the set contains that n-tuple. If the n-tuple is found, -- the routine returns pointer to corresponding array member. Otherwise -- null pointer is returned. */ MEMBER *find_tuple ( MPL *mpl, ELEMSET *set, /* not changed */ TUPLE *tuple /* not changed */ ) { xassert(set != NULL); xassert(set->type == A_NONE); xassert(set->dim == tuple_dimen(mpl, tuple)); return find_member(mpl, set, tuple); } /*---------------------------------------------------------------------- -- add_tuple - add new n-tuple to elemental set. -- -- This routine adds given n-tuple to specified elemental set. -- -- For the sake of efficiency this routine doesn't check whether the -- set already contains the same n-tuple or not. Therefore the calling -- program should use the routine find_tuple (if necessary) in order to -- make sure that the given n-tuple is not contained in the set, since -- duplicate n-tuples within the same set are not allowed. */ MEMBER *add_tuple ( MPL *mpl, ELEMSET *set, /* modified */ TUPLE *tuple /* destroyed */ ) { MEMBER *memb; xassert(set != NULL); xassert(set->type == A_NONE); xassert(set->dim == tuple_dimen(mpl, tuple)); memb = add_member(mpl, set, tuple); memb->value.none = NULL; return memb; } /*---------------------------------------------------------------------- -- check_then_add - check and add new n-tuple to elemental set. -- -- This routine is equivalent to the routine add_tuple except that it -- does check for duplicate n-tuples. */ MEMBER *check_then_add ( MPL *mpl, ELEMSET *set, /* modified */ TUPLE *tuple /* destroyed */ ) { if (find_tuple(mpl, set, tuple) != NULL) error(mpl, "duplicate tuple %s detected", format_tuple(mpl, '(', tuple)); return add_tuple(mpl, set, tuple); } /*---------------------------------------------------------------------- -- copy_elemset - make copy of elemental set. -- -- This routine makes an exact copy of elemental set. */ ELEMSET *copy_elemset ( MPL *mpl, ELEMSET *set /* not changed */ ) { ELEMSET *copy; MEMBER *memb; xassert(set != NULL); xassert(set->type == A_NONE); xassert(set->dim > 0); copy = create_elemset(mpl, set->dim); for (memb = set->head; memb != NULL; memb = memb->next) add_tuple(mpl, copy, copy_tuple(mpl, memb->tuple)); return copy; } /*---------------------------------------------------------------------- -- delete_elemset - delete elemental set. -- -- This routine deletes specified elemental set. */ void delete_elemset ( MPL *mpl, ELEMSET *set /* destroyed */ ) { xassert(set != NULL); xassert(set->type == A_NONE); delete_array(mpl, set); return; } /*---------------------------------------------------------------------- -- arelset_size - compute size of "arithmetic" elemental set. -- -- This routine computes the size of "arithmetic" elemental set, which -- is specified in the form of arithmetic progression: -- -- { t0 .. tf by dt }. -- -- The size is computed using the formula: -- -- n = max(0, floor((tf - t0) / dt) + 1). */ int arelset_size(MPL *mpl, double t0, double tf, double dt) { double temp; if (dt == 0.0) error(mpl, "%.*g .. %.*g by %.*g; zero stride not allowed", DBL_DIG, t0, DBL_DIG, tf, DBL_DIG, dt); if (tf > 0.0 && t0 < 0.0 && tf > + 0.999 * DBL_MAX + t0) temp = +DBL_MAX; else if (tf < 0.0 && t0 > 0.0 && tf < - 0.999 * DBL_MAX + t0) temp = -DBL_MAX; else temp = tf - t0; if (fabs(dt) < 1.0 && fabs(temp) > (0.999 * DBL_MAX) * fabs(dt)) { if (temp > 0.0 && dt > 0.0 || temp < 0.0 && dt < 0.0) temp = +DBL_MAX; else temp = 0.0; } else { temp = floor(temp / dt) + 1.0; if (temp < 0.0) temp = 0.0; } xassert(temp >= 0.0); if (temp > (double)(INT_MAX - 1)) error(mpl, "%.*g .. %.*g by %.*g; set too large", DBL_DIG, t0, DBL_DIG, tf, DBL_DIG, dt); return (int)(temp + 0.5); } /*---------------------------------------------------------------------- -- arelset_member - compute member of "arithmetic" elemental set. -- -- This routine returns a numeric value of symbol, which is equivalent -- to j-th member of given "arithmetic" elemental set specified in the -- form of arithmetic progression: -- -- { t0 .. tf by dt }. -- -- The symbol value is computed with the formula: -- -- j-th member = t0 + (j - 1) * dt, -- -- The number j must satisfy to the restriction 1 <= j <= n, where n is -- the set size computed by the routine arelset_size. */ double arelset_member(MPL *mpl, double t0, double tf, double dt, int j) { xassert(1 <= j && j <= arelset_size(mpl, t0, tf, dt)); return t0 + (double)(j - 1) * dt; } /*---------------------------------------------------------------------- -- create_arelset - create "arithmetic" elemental set. -- -- This routine creates "arithmetic" elemental set, which is specified -- in the form of arithmetic progression: -- -- { t0 .. tf by dt }. -- -- Components of this set are 1-tuples. */ ELEMSET *create_arelset(MPL *mpl, double t0, double tf, double dt) { ELEMSET *set; int j, n; set = create_elemset(mpl, 1); n = arelset_size(mpl, t0, tf, dt); for (j = 1; j <= n; j++) { add_tuple ( mpl, set, expand_tuple ( mpl, create_tuple(mpl), create_symbol_num ( mpl, arelset_member(mpl, t0, tf, dt, j) ) ) ); } return set; } /*---------------------------------------------------------------------- -- set_union - union of two elemental sets. -- -- This routine computes the union: -- -- X U Y = { j | (j in X) or (j in Y) }, -- -- where X and Y are given elemental sets (destroyed on exit). */ ELEMSET *set_union ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ) { MEMBER *memb; xassert(X != NULL); xassert(X->type == A_NONE); xassert(X->dim > 0); xassert(Y != NULL); xassert(Y->type == A_NONE); xassert(Y->dim > 0); xassert(X->dim == Y->dim); for (memb = Y->head; memb != NULL; memb = memb->next) { if (find_tuple(mpl, X, memb->tuple) == NULL) add_tuple(mpl, X, copy_tuple(mpl, memb->tuple)); } delete_elemset(mpl, Y); return X; } /*---------------------------------------------------------------------- -- set_diff - difference between two elemental sets. -- -- This routine computes the difference: -- -- X \ Y = { j | (j in X) and (j not in Y) }, -- -- where X and Y are given elemental sets (destroyed on exit). */ ELEMSET *set_diff ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ) { ELEMSET *Z; MEMBER *memb; xassert(X != NULL); xassert(X->type == A_NONE); xassert(X->dim > 0); xassert(Y != NULL); xassert(Y->type == A_NONE); xassert(Y->dim > 0); xassert(X->dim == Y->dim); Z = create_elemset(mpl, X->dim); for (memb = X->head; memb != NULL; memb = memb->next) { if (find_tuple(mpl, Y, memb->tuple) == NULL) add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); } delete_elemset(mpl, X); delete_elemset(mpl, Y); return Z; } /*---------------------------------------------------------------------- -- set_symdiff - symmetric difference between two elemental sets. -- -- This routine computes the symmetric difference: -- -- X (+) Y = (X \ Y) U (Y \ X), -- -- where X and Y are given elemental sets (destroyed on exit). */ ELEMSET *set_symdiff ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ) { ELEMSET *Z; MEMBER *memb; xassert(X != NULL); xassert(X->type == A_NONE); xassert(X->dim > 0); xassert(Y != NULL); xassert(Y->type == A_NONE); xassert(Y->dim > 0); xassert(X->dim == Y->dim); /* Z := X \ Y */ Z = create_elemset(mpl, X->dim); for (memb = X->head; memb != NULL; memb = memb->next) { if (find_tuple(mpl, Y, memb->tuple) == NULL) add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); } /* Z := Z U (Y \ X) */ for (memb = Y->head; memb != NULL; memb = memb->next) { if (find_tuple(mpl, X, memb->tuple) == NULL) add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); } delete_elemset(mpl, X); delete_elemset(mpl, Y); return Z; } /*---------------------------------------------------------------------- -- set_inter - intersection of two elemental sets. -- -- This routine computes the intersection: -- -- X ^ Y = { j | (j in X) and (j in Y) }, -- -- where X and Y are given elemental sets (destroyed on exit). */ ELEMSET *set_inter ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ) { ELEMSET *Z; MEMBER *memb; xassert(X != NULL); xassert(X->type == A_NONE); xassert(X->dim > 0); xassert(Y != NULL); xassert(Y->type == A_NONE); xassert(Y->dim > 0); xassert(X->dim == Y->dim); Z = create_elemset(mpl, X->dim); for (memb = X->head; memb != NULL; memb = memb->next) { if (find_tuple(mpl, Y, memb->tuple) != NULL) add_tuple(mpl, Z, copy_tuple(mpl, memb->tuple)); } delete_elemset(mpl, X); delete_elemset(mpl, Y); return Z; } /*---------------------------------------------------------------------- -- set_cross - cross (Cartesian) product of two elemental sets. -- -- This routine computes the cross (Cartesian) product: -- -- X x Y = { (i,j) | (i in X) and (j in Y) }, -- -- where X and Y are given elemental sets (destroyed on exit). */ ELEMSET *set_cross ( MPL *mpl, ELEMSET *X, /* destroyed */ ELEMSET *Y /* destroyed */ ) { ELEMSET *Z; MEMBER *memx, *memy; TUPLE *tuple, *temp; xassert(X != NULL); xassert(X->type == A_NONE); xassert(X->dim > 0); xassert(Y != NULL); xassert(Y->type == A_NONE); xassert(Y->dim > 0); Z = create_elemset(mpl, X->dim + Y->dim); for (memx = X->head; memx != NULL; memx = memx->next) { for (memy = Y->head; memy != NULL; memy = memy->next) { tuple = copy_tuple(mpl, memx->tuple); for (temp = memy->tuple; temp != NULL; temp = temp->next) tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, temp->sym)); add_tuple(mpl, Z, tuple); } } delete_elemset(mpl, X); delete_elemset(mpl, Y); return Z; } /**********************************************************************/ /* * * ELEMENTAL VARIABLES * * */ /**********************************************************************/ /* (there are no specific routines for elemental variables) */ /**********************************************************************/ /* * * LINEAR FORMS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- constant_term - create constant term. -- -- This routine creates the linear form, which is a constant term. */ FORMULA *constant_term(MPL *mpl, double coef) { FORMULA *form; if (coef == 0.0) form = NULL; else { form = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); form->coef = coef; form->var = NULL; form->next = NULL; } return form; } /*---------------------------------------------------------------------- -- single_variable - create single variable. -- -- This routine creates the linear form, which is a single elemental -- variable. */ FORMULA *single_variable ( MPL *mpl, ELEMVAR *var /* referenced */ ) { FORMULA *form; xassert(var != NULL); form = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); form->coef = 1.0; form->var = var; form->next = NULL; return form; } /*---------------------------------------------------------------------- -- copy_formula - make copy of linear form. -- -- This routine returns an exact copy of linear form. */ FORMULA *copy_formula ( MPL *mpl, FORMULA *form /* not changed */ ) { FORMULA *head, *tail; if (form == NULL) head = NULL; else { head = tail = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); for (; form != NULL; form = form->next) { tail->coef = form->coef; tail->var = form->var; if (form->next != NULL) tail = (tail->next = dmp_get_atom(mpl->formulae, sizeof(FORMULA))); } tail->next = NULL; } return head; } /*---------------------------------------------------------------------- -- delete_formula - delete linear form. -- -- This routine deletes specified linear form. */ void delete_formula ( MPL *mpl, FORMULA *form /* destroyed */ ) { FORMULA *temp; while (form != NULL) { temp = form; form = form->next; dmp_free_atom(mpl->formulae, temp, sizeof(FORMULA)); } return; } /*---------------------------------------------------------------------- -- linear_comb - linear combination of two linear forms. -- -- This routine computes the linear combination: -- -- a * fx + b * fy, -- -- where a and b are numeric coefficients, fx and fy are linear forms -- (destroyed on exit). */ FORMULA *linear_comb ( MPL *mpl, double a, FORMULA *fx, /* destroyed */ double b, FORMULA *fy /* destroyed */ ) { FORMULA *form = NULL, *term, *temp; double c0 = 0.0; for (term = fx; term != NULL; term = term->next) { if (term->var == NULL) c0 = fp_add(mpl, c0, fp_mul(mpl, a, term->coef)); else term->var->temp = fp_add(mpl, term->var->temp, fp_mul(mpl, a, term->coef)); } for (term = fy; term != NULL; term = term->next) { if (term->var == NULL) c0 = fp_add(mpl, c0, fp_mul(mpl, b, term->coef)); else term->var->temp = fp_add(mpl, term->var->temp, fp_mul(mpl, b, term->coef)); } for (term = fx; term != NULL; term = term->next) { if (term->var != NULL && term->var->temp != 0.0) { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); temp->coef = term->var->temp, temp->var = term->var; temp->next = form, form = temp; term->var->temp = 0.0; } } for (term = fy; term != NULL; term = term->next) { if (term->var != NULL && term->var->temp != 0.0) { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); temp->coef = term->var->temp, temp->var = term->var; temp->next = form, form = temp; term->var->temp = 0.0; } } if (c0 != 0.0) { temp = dmp_get_atom(mpl->formulae, sizeof(FORMULA)); temp->coef = c0, temp->var = NULL; temp->next = form, form = temp; } delete_formula(mpl, fx); delete_formula(mpl, fy); return form; } /*---------------------------------------------------------------------- -- remove_constant - remove constant term from linear form. -- -- This routine removes constant term from linear form and stores its -- value to given location. */ FORMULA *remove_constant ( MPL *mpl, FORMULA *form, /* destroyed */ double *coef /* modified */ ) { FORMULA *head = NULL, *temp; *coef = 0.0; while (form != NULL) { temp = form; form = form->next; if (temp->var == NULL) { /* constant term */ *coef = fp_add(mpl, *coef, temp->coef); dmp_free_atom(mpl->formulae, temp, sizeof(FORMULA)); } else { /* linear term */ temp->next = head; head = temp; } } return head; } /*---------------------------------------------------------------------- -- reduce_terms - reduce identical terms in linear form. -- -- This routine reduces identical terms in specified linear form. */ FORMULA *reduce_terms ( MPL *mpl, FORMULA *form /* destroyed */ ) { FORMULA *term, *next_term; double c0 = 0.0; for (term = form; term != NULL; term = term->next) { if (term->var == NULL) c0 = fp_add(mpl, c0, term->coef); else term->var->temp = fp_add(mpl, term->var->temp, term->coef); } next_term = form, form = NULL; for (term = next_term; term != NULL; term = next_term) { next_term = term->next; if (term->var == NULL && c0 != 0.0) { term->coef = c0, c0 = 0.0; term->next = form, form = term; } else if (term->var != NULL && term->var->temp != 0.0) { term->coef = term->var->temp, term->var->temp = 0.0; term->next = form, form = term; } else dmp_free_atom(mpl->formulae, term, sizeof(FORMULA)); } return form; } /**********************************************************************/ /* * * ELEMENTAL CONSTRAINTS * * */ /**********************************************************************/ /* (there are no specific routines for elemental constraints) */ /**********************************************************************/ /* * * GENERIC VALUES * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- delete_value - delete generic value. -- -- This routine deletes specified generic value. -- -- NOTE: The generic value to be deleted must be valid. */ void delete_value ( MPL *mpl, int type, VALUE *value /* content destroyed */ ) { xassert(value != NULL); switch (type) { case A_NONE: value->none = NULL; break; case A_NUMERIC: value->num = 0.0; break; case A_SYMBOLIC: delete_symbol(mpl, value->sym), value->sym = NULL; break; case A_LOGICAL: value->bit = 0; break; case A_TUPLE: delete_tuple(mpl, value->tuple), value->tuple = NULL; break; case A_ELEMSET: delete_elemset(mpl, value->set), value->set = NULL; break; case A_ELEMVAR: value->var = NULL; break; case A_FORMULA: delete_formula(mpl, value->form), value->form = NULL; break; case A_ELEMCON: value->con = NULL; break; default: xassert(type != type); } return; } /**********************************************************************/ /* * * SYMBOLICALLY INDEXED ARRAYS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- create_array - create array. -- -- This routine creates an array of specified type and dimension. Being -- created the array is initially empty. -- -- The type indicator determines generic values, which can be assigned -- to the array members: -- -- A_NONE - none (members have no assigned values) -- A_NUMERIC - floating-point numbers -- A_SYMBOLIC - symbols -- A_ELEMSET - elemental sets -- A_ELEMVAR - elemental variables -- A_ELEMCON - elemental constraints -- -- The dimension may be 0, in which case the array consists of the only -- member (such arrays represent 0-dimensional objects). */ ARRAY *create_array(MPL *mpl, int type, int dim) { ARRAY *array; xassert(type == A_NONE || type == A_NUMERIC || type == A_SYMBOLIC || type == A_ELEMSET || type == A_ELEMVAR || type == A_ELEMCON); xassert(dim >= 0); array = dmp_get_atom(mpl->arrays, sizeof(ARRAY)); array->type = type; array->dim = dim; array->size = 0; array->head = NULL; array->tail = NULL; array->tree = NULL; array->prev = NULL; array->next = mpl->a_list; /* include the array in the global array list */ if (array->next != NULL) array->next->prev = array; mpl->a_list = array; return array; } /*---------------------------------------------------------------------- -- find_member - find array member with given n-tuple. -- -- This routine finds an array member, which has given n-tuple. If the -- array is short, the linear search is used. Otherwise the routine -- autimatically creates the search tree (i.e. the array index) to find -- members for logarithmic time. */ static int compare_member_tuples(void *info, const void *key1, const void *key2) { /* this is an auxiliary routine used to compare keys, which are n-tuples assigned to array members */ return compare_tuples((MPL *)info, (TUPLE *)key1, (TUPLE *)key2); } MEMBER *find_member ( MPL *mpl, ARRAY *array, /* not changed */ TUPLE *tuple /* not changed */ ) { MEMBER *memb; xassert(array != NULL); /* the n-tuple must have the same dimension as the array */ xassert(tuple_dimen(mpl, tuple) == array->dim); /* if the array is large enough, create the search tree and index all existing members of the array */ if (array->size > 30 && array->tree == NULL) { array->tree = avl_create_tree(compare_member_tuples, mpl); for (memb = array->head; memb != NULL; memb = memb->next) avl_set_node_link(avl_insert_node(array->tree, memb->tuple), (void *)memb); } /* find a member, which has the given tuple */ if (array->tree == NULL) { /* the search tree doesn't exist; use the linear search */ for (memb = array->head; memb != NULL; memb = memb->next) if (compare_tuples(mpl, memb->tuple, tuple) == 0) break; } else { /* the search tree exists; use the binary search */ AVLNODE *node; node = avl_find_node(array->tree, tuple); memb = (MEMBER *)(node == NULL ? NULL : avl_get_node_link(node)); } return memb; } /*---------------------------------------------------------------------- -- add_member - add new member to array. -- -- This routine creates a new member with given n-tuple and adds it to -- specified array. -- -- For the sake of efficiency this routine doesn't check whether the -- array already contains a member with the given n-tuple or not. Thus, -- if necessary, the calling program should use the routine find_member -- in order to be sure that the array contains no member with the same -- n-tuple, because members with duplicate n-tuples are not allowed. -- -- This routine assigns no generic value to the new member, because the -- calling program must do that. */ MEMBER *add_member ( MPL *mpl, ARRAY *array, /* modified */ TUPLE *tuple /* destroyed */ ) { MEMBER *memb; xassert(array != NULL); /* the n-tuple must have the same dimension as the array */ xassert(tuple_dimen(mpl, tuple) == array->dim); /* create new member */ memb = dmp_get_atom(mpl->members, sizeof(MEMBER)); memb->tuple = tuple; memb->next = NULL; memset(&memb->value, '?', sizeof(VALUE)); /* and append it to the member list */ array->size++; if (array->head == NULL) array->head = memb; else array->tail->next = memb; array->tail = memb; /* if the search tree exists, index the new member */ if (array->tree != NULL) avl_set_node_link(avl_insert_node(array->tree, memb->tuple), (void *)memb); return memb; } /*---------------------------------------------------------------------- -- delete_array - delete array. -- -- This routine deletes specified array. -- -- Generic values assigned to the array members are not deleted by this -- routine. The calling program itself must delete all assigned generic -- values before deleting the array. */ void delete_array ( MPL *mpl, ARRAY *array /* destroyed */ ) { MEMBER *memb; xassert(array != NULL); /* delete all existing array members */ while (array->head != NULL) { memb = array->head; array->head = memb->next; delete_tuple(mpl, memb->tuple); dmp_free_atom(mpl->members, memb, sizeof(MEMBER)); } /* if the search tree exists, also delete it */ if (array->tree != NULL) avl_delete_tree(array->tree); /* remove the array from the global array list */ if (array->prev == NULL) mpl->a_list = array->next; else array->prev->next = array->next; if (array->next == NULL) ; else array->next->prev = array->prev; /* delete the array descriptor */ dmp_free_atom(mpl->arrays, array, sizeof(ARRAY)); return; } /**********************************************************************/ /* * * DOMAINS AND DUMMY INDICES * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- assign_dummy_index - assign new value to dummy index. -- -- This routine assigns new value to specified dummy index and, that is -- important, invalidates all temporary resultant values, which depends -- on that dummy index. */ void assign_dummy_index ( MPL *mpl, DOMAIN_SLOT *slot, /* modified */ SYMBOL *value /* not changed */ ) { CODE *leaf, *code; xassert(slot != NULL); xassert(value != NULL); /* delete the current value assigned to the dummy index */ if (slot->value != NULL) { /* if the current value and the new one are identical, actual assignment is not needed */ if (compare_symbols(mpl, slot->value, value) == 0) goto done; /* delete a symbol, which is the current value */ delete_symbol(mpl, slot->value), slot->value = NULL; } /* now walk through all the pseudo-codes with op = O_INDEX, which refer to the dummy index to be changed (these pseudo-codes are leaves in the forest of *all* expressions in the database) */ for (leaf = slot->list; leaf != NULL; leaf = leaf->arg.index. next) { xassert(leaf->op == O_INDEX); /* invalidate all resultant values, which depend on the dummy index, walking from the current leaf toward the root of the corresponding expression tree */ for (code = leaf; code != NULL; code = code->up) { if (code->valid) { /* invalidate and delete resultant value */ code->valid = 0; delete_value(mpl, code->type, &code->value); } } } /* assign new value to the dummy index */ slot->value = copy_symbol(mpl, value); done: return; } /*---------------------------------------------------------------------- -- update_dummy_indices - update current values of dummy indices. -- -- This routine assigns components of "backup" n-tuple to dummy indices -- of specified domain block. If no "backup" n-tuple is defined for the -- domain block, values of the dummy indices remain untouched. */ void update_dummy_indices ( MPL *mpl, DOMAIN_BLOCK *block /* not changed */ ) { DOMAIN_SLOT *slot; TUPLE *temp; if (block->backup != NULL) { for (slot = block->list, temp = block->backup; slot != NULL; slot = slot->next, temp = temp->next) { xassert(temp != NULL); xassert(temp->sym != NULL); assign_dummy_index(mpl, slot, temp->sym); } } return; } /*---------------------------------------------------------------------- -- enter_domain_block - enter domain block. -- -- Let specified domain block have the form: -- -- { ..., (j1, j2, ..., jn) in J, ... } -- -- where j1, j2, ..., jn are dummy indices, J is a basic set. -- -- This routine does the following: -- -- 1. Checks if the given n-tuple is a member of the basic set J. Note -- that J being *out of the scope* of the domain block cannot depend -- on the dummy indices in the same and inner domain blocks, so it -- can be computed before the dummy indices are assigned new values. -- If this check fails, the routine returns with non-zero code. -- -- 2. Saves current values of the dummy indices j1, j2, ..., jn. -- -- 3. Assigns new values, which are components of the given n-tuple, to -- the dummy indices j1, j2, ..., jn. If dimension of the n-tuple is -- larger than n, its extra components n+1, n+2, ... are not used. -- -- 4. Calls the formal routine func which either enters the next domain -- block or evaluates some code within the domain scope. -- -- 5. Restores former values of the dummy indices j1, j2, ..., jn. -- -- Since current values assigned to the dummy indices on entry to this -- routine are restored on exit, the formal routine func is allowed to -- call this routine recursively. */ int enter_domain_block ( MPL *mpl, DOMAIN_BLOCK *block, /* not changed */ TUPLE *tuple, /* not changed */ void *info, void (*func)(MPL *mpl, void *info) ) { TUPLE *backup; int ret = 0; /* check if the given n-tuple is a member of the basic set */ xassert(block->code != NULL); if (!is_member(mpl, block->code, tuple)) { ret = 1; goto done; } /* save reference to "backup" n-tuple, which was used to assign current values of the dummy indices (it is sufficient to save reference, not value, because that n-tuple is defined in some outer level of recursion and therefore cannot be changed on this and deeper recursive calls) */ backup = block->backup; /* set up new "backup" n-tuple, which defines new values of the dummy indices */ block->backup = tuple; /* assign new values to the dummy indices */ update_dummy_indices(mpl, block); /* call the formal routine that does the rest part of the job */ func(mpl, info); /* restore reference to the former "backup" n-tuple */ block->backup = backup; /* restore former values of the dummy indices; note that if the domain block just escaped has no other active instances which may exist due to recursion (it is indicated by a null pointer to the former n-tuple), former values of the dummy indices are undefined; therefore in this case the routine keeps currently assigned values of the dummy indices that involves keeping all dependent temporary results and thereby, if this domain block is not used recursively, allows improving efficiency */ update_dummy_indices(mpl, block); done: return ret; } /*---------------------------------------------------------------------- -- eval_within_domain - perform evaluation within domain scope. -- -- This routine assigns new values (symbols) to all dummy indices of -- specified domain and calls the formal routine func, which is used to -- evaluate some code in the domain scope. Each free dummy index in the -- domain is assigned a value specified in the corresponding component -- of given n-tuple. Non-free dummy indices are assigned values, which -- are computed by this routine. -- -- Number of components in the given n-tuple must be the same as number -- of free indices in the domain. -- -- If the given n-tuple is not a member of the domain set, the routine -- func is not called, and non-zero code is returned. -- -- For the sake of convenience it is allowed to specify domain as NULL -- (then n-tuple also must be 0-tuple, i.e. empty), in which case this -- routine just calls the routine func and returns zero. -- -- This routine allows recursive calls from the routine func providing -- correct values of dummy indices for each instance. -- -- NOTE: The n-tuple passed to this routine must not be changed by any -- other routines called from the formal routine func until this -- routine has returned. */ struct eval_domain_info { /* working info used by the routine eval_within_domain */ DOMAIN *domain; /* domain, which has to be entered */ DOMAIN_BLOCK *block; /* domain block, which is currently processed */ TUPLE *tuple; /* tail of original n-tuple, whose components have to be assigned to free dummy indices in the current domain block */ void *info; /* transit pointer passed to the formal routine func */ void (*func)(MPL *mpl, void *info); /* routine, which has to be executed in the domain scope */ int failure; /* this flag indicates that given n-tuple is not a member of the domain set */ }; static void eval_domain_func(MPL *mpl, void *_my_info) { /* this routine recursively enters into the domain scope and then calls the routine func */ struct eval_domain_info *my_info = _my_info; if (my_info->block != NULL) { /* the current domain block to be entered exists */ DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; TUPLE *tuple = NULL, *temp = NULL; /* save pointer to the current domain block */ block = my_info->block; /* and get ready to enter the next block (if it exists) */ my_info->block = block->next; /* construct temporary n-tuple, whose components correspond to dummy indices (slots) of the current domain; components of the temporary n-tuple that correspond to free dummy indices are assigned references (not values!) to symbols specified in the corresponding components of the given n-tuple, while other components that correspond to non-free dummy indices are assigned symbolic values computed here */ for (slot = block->list; slot != NULL; slot = slot->next) { /* create component that corresponds to the current slot */ if (tuple == NULL) tuple = temp = dmp_get_atom(mpl->tuples, sizeof(TUPLE)); else temp = (temp->next = dmp_get_atom(mpl->tuples, sizeof(TUPLE))); if (slot->code == NULL) { /* dummy index is free; take reference to symbol, which is specified in the corresponding component of given n-tuple */ xassert(my_info->tuple != NULL); temp->sym = my_info->tuple->sym; xassert(temp->sym != NULL); my_info->tuple = my_info->tuple->next; } else { /* dummy index is non-free; compute symbolic value to be temporarily assigned to the dummy index */ temp->sym = eval_symbolic(mpl, slot->code); } } temp->next = NULL; /* enter the current domain block */ if (enter_domain_block(mpl, block, tuple, my_info, eval_domain_func)) my_info->failure = 1; /* delete temporary n-tuple as well as symbols that correspond to non-free dummy indices (they were computed here) */ for (slot = block->list; slot != NULL; slot = slot->next) { xassert(tuple != NULL); temp = tuple; tuple = tuple->next; if (slot->code != NULL) { /* dummy index is non-free; delete symbolic value */ delete_symbol(mpl, temp->sym); } /* delete component that corresponds to the current slot */ dmp_free_atom(mpl->tuples, temp, sizeof(TUPLE)); } } else { /* there are no more domain blocks, i.e. we have reached the domain scope */ xassert(my_info->tuple == NULL); /* check optional predicate specified for the domain */ if (my_info->domain->code != NULL && !eval_logical(mpl, my_info->domain->code)) { /* the predicate is false */ my_info->failure = 2; } else { /* the predicate is true; do the job */ my_info->func(mpl, my_info->info); } } return; } int eval_within_domain ( MPL *mpl, DOMAIN *domain, /* not changed */ TUPLE *tuple, /* not changed */ void *info, void (*func)(MPL *mpl, void *info) ) { /* this routine performs evaluation within domain scope */ struct eval_domain_info _my_info, *my_info = &_my_info; if (domain == NULL) { xassert(tuple == NULL); func(mpl, info); my_info->failure = 0; } else { xassert(tuple != NULL); my_info->domain = domain; my_info->block = domain->list; my_info->tuple = tuple; my_info->info = info; my_info->func = func; my_info->failure = 0; /* enter the very first domain block */ eval_domain_func(mpl, my_info); } return my_info->failure; } /*---------------------------------------------------------------------- -- loop_within_domain - perform iterations within domain scope. -- -- This routine iteratively assigns new values (symbols) to the dummy -- indices of specified domain by enumerating all n-tuples, which are -- members of the domain set, and for every n-tuple it calls the formal -- routine func to evaluate some code within the domain scope. -- -- If the routine func returns non-zero, enumeration within the domain -- is prematurely terminated. -- -- For the sake of convenience it is allowed to specify domain as NULL, -- in which case this routine just calls the routine func only once and -- returns zero. -- -- This routine allows recursive calls from the routine func providing -- correct values of dummy indices for each instance. */ struct loop_domain_info { /* working info used by the routine loop_within_domain */ DOMAIN *domain; /* domain, which has to be entered */ DOMAIN_BLOCK *block; /* domain block, which is currently processed */ int looping; /* clearing this flag leads to terminating enumeration */ void *info; /* transit pointer passed to the formal routine func */ int (*func)(MPL *mpl, void *info); /* routine, which needs to be executed in the domain scope */ }; static void loop_domain_func(MPL *mpl, void *_my_info) { /* this routine enumerates all n-tuples in the basic set of the current domain block, enters recursively into the domain scope for every n-tuple, and then calls the routine func */ struct loop_domain_info *my_info = _my_info; if (my_info->block != NULL) { /* the current domain block to be entered exists */ DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; TUPLE *bound; /* save pointer to the current domain block */ block = my_info->block; /* and get ready to enter the next block (if it exists) */ my_info->block = block->next; /* compute symbolic values, at which non-free dummy indices of the current domain block are bound; since that values don't depend on free dummy indices of the current block, they can be computed once out of the enumeration loop */ bound = create_tuple(mpl); for (slot = block->list; slot != NULL; slot = slot->next) { if (slot->code != NULL) bound = expand_tuple(mpl, bound, eval_symbolic(mpl, slot->code)); } /* start enumeration */ xassert(block->code != NULL); if (block->code->op == O_DOTS) { /* the basic set is "arithmetic", in which case it doesn't need to be computed explicitly */ TUPLE *tuple; int n, j; double t0, tf, dt; /* compute "parameters" of the basic set */ t0 = eval_numeric(mpl, block->code->arg.arg.x); tf = eval_numeric(mpl, block->code->arg.arg.y); if (block->code->arg.arg.z == NULL) dt = 1.0; else dt = eval_numeric(mpl, block->code->arg.arg.z); /* determine cardinality of the basic set */ n = arelset_size(mpl, t0, tf, dt); /* create dummy 1-tuple for members of the basic set */ tuple = expand_tuple(mpl, create_tuple(mpl), create_symbol_num(mpl, 0.0)); /* in case of "arithmetic" set there is exactly one dummy index, which cannot be non-free */ xassert(bound == NULL); /* walk through 1-tuples of the basic set */ for (j = 1; j <= n && my_info->looping; j++) { /* construct dummy 1-tuple for the current member */ tuple->sym->num = arelset_member(mpl, t0, tf, dt, j); /* enter the current domain block */ enter_domain_block(mpl, block, tuple, my_info, loop_domain_func); } /* delete dummy 1-tuple */ delete_tuple(mpl, tuple); } else { /* the basic set is of general kind, in which case it needs to be explicitly computed */ ELEMSET *set; MEMBER *memb; TUPLE *temp1, *temp2; /* compute the basic set */ set = eval_elemset(mpl, block->code); /* walk through all n-tuples of the basic set */ for (memb = set->head; memb != NULL && my_info->looping; memb = memb->next) { /* all components of the current n-tuple that correspond to non-free dummy indices must be feasible; otherwise the n-tuple is not in the basic set */ temp1 = memb->tuple; temp2 = bound; for (slot = block->list; slot != NULL; slot = slot->next) { xassert(temp1 != NULL); if (slot->code != NULL) { /* non-free dummy index */ xassert(temp2 != NULL); if (compare_symbols(mpl, temp1->sym, temp2->sym) != 0) { /* the n-tuple is not in the basic set */ goto skip; } temp2 = temp2->next; } temp1 = temp1->next; } xassert(temp1 == NULL); xassert(temp2 == NULL); /* enter the current domain block */ enter_domain_block(mpl, block, memb->tuple, my_info, loop_domain_func); skip: ; } /* delete the basic set */ delete_elemset(mpl, set); } /* delete symbolic values binding non-free dummy indices */ delete_tuple(mpl, bound); /* restore pointer to the current domain block */ my_info->block = block; } else { /* there are no more domain blocks, i.e. we have reached the domain scope */ /* check optional predicate specified for the domain */ if (my_info->domain->code != NULL && !eval_logical(mpl, my_info->domain->code)) { /* the predicate is false */ /* nop */; } else { /* the predicate is true; do the job */ my_info->looping = !my_info->func(mpl, my_info->info); } } return; } void loop_within_domain ( MPL *mpl, DOMAIN *domain, /* not changed */ void *info, int (*func)(MPL *mpl, void *info) ) { /* this routine performs iterations within domain scope */ struct loop_domain_info _my_info, *my_info = &_my_info; if (domain == NULL) func(mpl, info); else { my_info->domain = domain; my_info->block = domain->list; my_info->looping = 1; my_info->info = info; my_info->func = func; /* enter the very first domain block */ loop_domain_func(mpl, my_info); } return; } /*---------------------------------------------------------------------- -- out_of_domain - raise domain exception. -- -- This routine is called when a reference is made to a member of some -- model object, but its n-tuple is out of the object domain. */ void out_of_domain ( MPL *mpl, char *name, /* not changed */ TUPLE *tuple /* not changed */ ) { xassert(name != NULL); xassert(tuple != NULL); error(mpl, "%s%s out of domain", name, format_tuple(mpl, '[', tuple)); /* no return */ } /*---------------------------------------------------------------------- -- get_domain_tuple - obtain current n-tuple from domain. -- -- This routine constructs n-tuple, whose components are current values -- assigned to *free* dummy indices of specified domain. -- -- For the sake of convenience it is allowed to specify domain as NULL, -- in which case this routine returns 0-tuple. -- -- NOTE: This routine must not be called out of domain scope. */ TUPLE *get_domain_tuple ( MPL *mpl, DOMAIN *domain /* not changed */ ) { DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; TUPLE *tuple; tuple = create_tuple(mpl); if (domain != NULL) { for (block = domain->list; block != NULL; block = block->next) { for (slot = block->list; slot != NULL; slot = slot->next) { if (slot->code == NULL) { xassert(slot->value != NULL); tuple = expand_tuple(mpl, tuple, copy_symbol(mpl, slot->value)); } } } } return tuple; } /*---------------------------------------------------------------------- -- clean_domain - clean domain. -- -- This routine cleans specified domain that assumes deleting all stuff -- dynamically allocated during the generation phase. */ void clean_domain(MPL *mpl, DOMAIN *domain) { DOMAIN_BLOCK *block; DOMAIN_SLOT *slot; /* if no domain is specified, do nothing */ if (domain == NULL) goto done; /* clean all domain blocks */ for (block = domain->list; block != NULL; block = block->next) { /* clean all domain slots */ for (slot = block->list; slot != NULL; slot = slot->next) { /* clean pseudo-code for computing bound value */ clean_code(mpl, slot->code); /* delete symbolic value assigned to dummy index */ if (slot->value != NULL) delete_symbol(mpl, slot->value), slot->value = NULL; } /* clean pseudo-code for computing basic set */ clean_code(mpl, block->code); } /* clean pseudo-code for computing domain predicate */ clean_code(mpl, domain->code); done: return; } /**********************************************************************/ /* * * MODEL SETS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- check_elem_set - check elemental set assigned to set member. -- -- This routine checks if given elemental set being assigned to member -- of specified model set satisfies to all restrictions. -- -- NOTE: This routine must not be called out of domain scope. */ void check_elem_set ( MPL *mpl, SET *set, /* not changed */ TUPLE *tuple, /* not changed */ ELEMSET *refer /* not changed */ ) { WITHIN *within; MEMBER *memb; int eqno; /* elemental set must be within all specified supersets */ for (within = set->within, eqno = 1; within != NULL; within = within->next, eqno++) { xassert(within->code != NULL); for (memb = refer->head; memb != NULL; memb = memb->next) { if (!is_member(mpl, within->code, memb->tuple)) { char buf[255+1]; strcpy(buf, format_tuple(mpl, '(', memb->tuple)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s%s contains %s which not within specified " "set; see (%d)", set->name, format_tuple(mpl, '[', tuple), buf, eqno); } } } return; } /*---------------------------------------------------------------------- -- take_member_set - obtain elemental set assigned to set member. -- -- This routine obtains a reference to elemental set assigned to given -- member of specified model set and returns it on exit. -- -- NOTE: This routine must not be called out of domain scope. */ ELEMSET *take_member_set /* returns reference, not value */ ( MPL *mpl, SET *set, /* not changed */ TUPLE *tuple /* not changed */ ) { MEMBER *memb; ELEMSET *refer; /* find member in the set array */ memb = find_member(mpl, set->array, tuple); if (memb != NULL) { /* member exists, so just take the reference */ refer = memb->value.set; } else if (set->assign != NULL) { /* compute value using assignment expression */ refer = eval_elemset(mpl, set->assign); add: /* check that the elemental set satisfies to all restrictions, assign it to new member, and add the member to the array */ check_elem_set(mpl, set, tuple, refer); memb = add_member(mpl, set->array, copy_tuple(mpl, tuple)); memb->value.set = refer; } else if (set->option != NULL) { /* compute default elemental set */ refer = eval_elemset(mpl, set->option); goto add; } else { /* no value (elemental set) is provided */ error(mpl, "no value for %s%s", set->name, format_tuple(mpl, '[', tuple)); } return refer; } /*---------------------------------------------------------------------- -- eval_member_set - evaluate elemental set assigned to set member. -- -- This routine evaluates a reference to elemental set assigned to given -- member of specified model set and returns it on exit. */ struct eval_set_info { /* working info used by the routine eval_member_set */ SET *set; /* model set */ TUPLE *tuple; /* n-tuple, which defines set member */ MEMBER *memb; /* normally this pointer is NULL; the routine uses this pointer to check data provided in the data section, in which case it points to a member currently checked; this check is performed automatically only once when a reference to any member occurs for the first time */ ELEMSET *refer; /* evaluated reference to elemental set */ }; static void eval_set_func(MPL *mpl, void *_info) { /* this is auxiliary routine to work within domain scope */ struct eval_set_info *info = _info; if (info->memb != NULL) { /* checking call; check elemental set being assigned */ check_elem_set(mpl, info->set, info->memb->tuple, info->memb->value.set); } else { /* normal call; evaluate member, which has given n-tuple */ info->refer = take_member_set(mpl, info->set, info->tuple); } return; } #if 1 /* 12/XII-2008 */ static void saturate_set(MPL *mpl, SET *set) { GADGET *gadget = set->gadget; ELEMSET *data; MEMBER *elem, *memb; TUPLE *tuple, *work[20]; int i; xprintf("Generating %s...\n", set->name); eval_whole_set(mpl, gadget->set); /* gadget set must have exactly one member */ xassert(gadget->set->array != NULL); xassert(gadget->set->array->head != NULL); xassert(gadget->set->array->head == gadget->set->array->tail); data = gadget->set->array->head->value.set; xassert(data->type == A_NONE); xassert(data->dim == gadget->set->dimen); /* walk thru all elements of the plain set */ for (elem = data->head; elem != NULL; elem = elem->next) { /* create a copy of n-tuple */ tuple = copy_tuple(mpl, elem->tuple); /* rearrange component of the n-tuple */ for (i = 0; i < gadget->set->dimen; i++) work[i] = NULL; for (i = 0; tuple != NULL; tuple = tuple->next) work[gadget->ind[i++]-1] = tuple; xassert(i == gadget->set->dimen); for (i = 0; i < gadget->set->dimen; i++) { xassert(work[i] != NULL); work[i]->next = work[i+1]; } /* construct subscript list from first set->dim components */ if (set->dim == 0) tuple = NULL; else tuple = work[0], work[set->dim-1]->next = NULL; /* find corresponding member of the set to be initialized */ memb = find_member(mpl, set->array, tuple); if (memb == NULL) { /* not found; add new member to the set and assign it empty elemental set */ memb = add_member(mpl, set->array, tuple); memb->value.set = create_elemset(mpl, set->dimen); } else { /* found; free subscript list */ delete_tuple(mpl, tuple); } /* construct new n-tuple from rest set->dimen components */ tuple = work[set->dim]; xassert(set->dim + set->dimen == gadget->set->dimen); work[gadget->set->dimen-1]->next = NULL; /* and add it to the elemental set assigned to the member (no check for duplicates is needed) */ add_tuple(mpl, memb->value.set, tuple); } /* the set has been saturated with data */ set->data = 1; return; } #endif ELEMSET *eval_member_set /* returns reference, not value */ ( MPL *mpl, SET *set, /* not changed */ TUPLE *tuple /* not changed */ ) { /* this routine evaluates set member */ struct eval_set_info _info, *info = &_info; xassert(set->dim == tuple_dimen(mpl, tuple)); info->set = set; info->tuple = tuple; #if 1 /* 12/XII-2008 */ if (set->gadget != NULL && set->data == 0) { /* initialize the set with data from a plain set */ saturate_set(mpl, set); } #endif if (set->data == 1) { /* check data, which are provided in the data section, but not checked yet */ /* save pointer to the last array member; note that during the check new members may be added beyond the last member due to references to the same parameter from default expression as well as from expressions that define restricting supersets; however, values assigned to the new members will be checked by other routine, so we don't need to check them here */ MEMBER *tail = set->array->tail; /* change the data status to prevent infinite recursive loop due to references to the same set during the check */ set->data = 2; /* check elemental sets assigned to array members in the data section until the marked member has been reached */ for (info->memb = set->array->head; info->memb != NULL; info->memb = info->memb->next) { if (eval_within_domain(mpl, set->domain, info->memb->tuple, info, eval_set_func)) out_of_domain(mpl, set->name, info->memb->tuple); if (info->memb == tail) break; } /* the check has been finished */ } /* evaluate member, which has given n-tuple */ info->memb = NULL; if (eval_within_domain(mpl, info->set->domain, info->tuple, info, eval_set_func)) out_of_domain(mpl, set->name, info->tuple); /* bring evaluated reference to the calling program */ return info->refer; } /*---------------------------------------------------------------------- -- eval_whole_set - evaluate model set over entire domain. -- -- This routine evaluates all members of specified model set over entire -- domain. */ static int whole_set_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ SET *set = (SET *)info; TUPLE *tuple = get_domain_tuple(mpl, set->domain); eval_member_set(mpl, set, tuple); delete_tuple(mpl, tuple); return 0; } void eval_whole_set(MPL *mpl, SET *set) { loop_within_domain(mpl, set->domain, set, whole_set_func); return; } /*---------------------------------------------------------------------- -- clean set - clean model set. -- -- This routine cleans specified model set that assumes deleting all -- stuff dynamically allocated during the generation phase. */ void clean_set(MPL *mpl, SET *set) { WITHIN *within; MEMBER *memb; /* clean subscript domain */ clean_domain(mpl, set->domain); /* clean pseudo-code for computing supersets */ for (within = set->within; within != NULL; within = within->next) clean_code(mpl, within->code); /* clean pseudo-code for computing assigned value */ clean_code(mpl, set->assign); /* clean pseudo-code for computing default value */ clean_code(mpl, set->option); /* reset data status flag */ set->data = 0; /* delete content array */ for (memb = set->array->head; memb != NULL; memb = memb->next) delete_value(mpl, set->array->type, &memb->value); delete_array(mpl, set->array), set->array = NULL; return; } /**********************************************************************/ /* * * MODEL PARAMETERS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- check_value_num - check numeric value assigned to parameter member. -- -- This routine checks if numeric value being assigned to some member -- of specified numeric model parameter satisfies to all restrictions. -- -- NOTE: This routine must not be called out of domain scope. */ void check_value_num ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple, /* not changed */ double value ) { CONDITION *cond; WITHIN *in; int eqno; /* the value must satisfy to the parameter type */ switch (par->type) { case A_NUMERIC: break; case A_INTEGER: if (value != floor(value)) error(mpl, "%s%s = %.*g not integer", par->name, format_tuple(mpl, '[', tuple), DBL_DIG, value); break; case A_BINARY: if (!(value == 0.0 || value == 1.0)) error(mpl, "%s%s = %.*g not binary", par->name, format_tuple(mpl, '[', tuple), DBL_DIG, value); break; default: xassert(par != par); } /* the value must satisfy to all specified conditions */ for (cond = par->cond, eqno = 1; cond != NULL; cond = cond->next, eqno++) { double bound; char *rho; xassert(cond->code != NULL); bound = eval_numeric(mpl, cond->code); switch (cond->rho) { case O_LT: if (!(value < bound)) { rho = "<"; err: error(mpl, "%s%s = %.*g not %s %.*g; see (%d)", par->name, format_tuple(mpl, '[', tuple), DBL_DIG, value, rho, DBL_DIG, bound, eqno); } break; case O_LE: if (!(value <= bound)) { rho = "<="; goto err; } break; case O_EQ: if (!(value == bound)) { rho = "="; goto err; } break; case O_GE: if (!(value >= bound)) { rho = ">="; goto err; } break; case O_GT: if (!(value > bound)) { rho = ">"; goto err; } break; case O_NE: if (!(value != bound)) { rho = "<>"; goto err; } break; default: xassert(cond != cond); } } /* the value must be in all specified supersets */ for (in = par->in, eqno = 1; in != NULL; in = in->next, eqno++) { TUPLE *dummy; xassert(in->code != NULL); xassert(in->code->dim == 1); dummy = expand_tuple(mpl, create_tuple(mpl), create_symbol_num(mpl, value)); if (!is_member(mpl, in->code, dummy)) error(mpl, "%s%s = %.*g not in specified set; see (%d)", par->name, format_tuple(mpl, '[', tuple), DBL_DIG, value, eqno); delete_tuple(mpl, dummy); } return; } /*---------------------------------------------------------------------- -- take_member_num - obtain num. value assigned to parameter member. -- -- This routine obtains a numeric value assigned to member of specified -- numeric model parameter and returns it on exit. -- -- NOTE: This routine must not be called out of domain scope. */ double take_member_num ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ) { MEMBER *memb; double value; /* find member in the parameter array */ memb = find_member(mpl, par->array, tuple); if (memb != NULL) { /* member exists, so just take its value */ value = memb->value.num; } else if (par->assign != NULL) { /* compute value using assignment expression */ value = eval_numeric(mpl, par->assign); add: /* check that the value satisfies to all restrictions, assign it to new member, and add the member to the array */ check_value_num(mpl, par, tuple, value); memb = add_member(mpl, par->array, copy_tuple(mpl, tuple)); memb->value.num = value; } else if (par->option != NULL) { /* compute default value */ value = eval_numeric(mpl, par->option); goto add; } else if (par->defval != NULL) { /* take default value provided in the data section */ if (par->defval->str != NULL) error(mpl, "cannot convert %s to floating-point number", format_symbol(mpl, par->defval)); value = par->defval->num; goto add; } else { /* no value is provided */ error(mpl, "no value for %s%s", par->name, format_tuple(mpl, '[', tuple)); } return value; } /*---------------------------------------------------------------------- -- eval_member_num - evaluate num. value assigned to parameter member. -- -- This routine evaluates a numeric value assigned to given member of -- specified numeric model parameter and returns it on exit. */ struct eval_num_info { /* working info used by the routine eval_member_num */ PARAMETER *par; /* model parameter */ TUPLE *tuple; /* n-tuple, which defines parameter member */ MEMBER *memb; /* normally this pointer is NULL; the routine uses this pointer to check data provided in the data section, in which case it points to a member currently checked; this check is performed automatically only once when a reference to any member occurs for the first time */ double value; /* evaluated numeric value */ }; static void eval_num_func(MPL *mpl, void *_info) { /* this is auxiliary routine to work within domain scope */ struct eval_num_info *info = _info; if (info->memb != NULL) { /* checking call; check numeric value being assigned */ check_value_num(mpl, info->par, info->memb->tuple, info->memb->value.num); } else { /* normal call; evaluate member, which has given n-tuple */ info->value = take_member_num(mpl, info->par, info->tuple); } return; } double eval_member_num ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ) { /* this routine evaluates numeric parameter member */ struct eval_num_info _info, *info = &_info; xassert(par->type == A_NUMERIC || par->type == A_INTEGER || par->type == A_BINARY); xassert(par->dim == tuple_dimen(mpl, tuple)); info->par = par; info->tuple = tuple; if (par->data == 1) { /* check data, which are provided in the data section, but not checked yet */ /* save pointer to the last array member; note that during the check new members may be added beyond the last member due to references to the same parameter from default expression as well as from expressions that define restricting conditions; however, values assigned to the new members will be checked by other routine, so we don't need to check them here */ MEMBER *tail = par->array->tail; /* change the data status to prevent infinite recursive loop due to references to the same parameter during the check */ par->data = 2; /* check values assigned to array members in the data section until the marked member has been reached */ for (info->memb = par->array->head; info->memb != NULL; info->memb = info->memb->next) { if (eval_within_domain(mpl, par->domain, info->memb->tuple, info, eval_num_func)) out_of_domain(mpl, par->name, info->memb->tuple); if (info->memb == tail) break; } /* the check has been finished */ } /* evaluate member, which has given n-tuple */ info->memb = NULL; if (eval_within_domain(mpl, info->par->domain, info->tuple, info, eval_num_func)) out_of_domain(mpl, par->name, info->tuple); /* bring evaluated value to the calling program */ return info->value; } /*---------------------------------------------------------------------- -- check_value_sym - check symbolic value assigned to parameter member. -- -- This routine checks if symbolic value being assigned to some member -- of specified symbolic model parameter satisfies to all restrictions. -- -- NOTE: This routine must not be called out of domain scope. */ void check_value_sym ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple, /* not changed */ SYMBOL *value /* not changed */ ) { CONDITION *cond; WITHIN *in; int eqno; /* the value must satisfy to all specified conditions */ for (cond = par->cond, eqno = 1; cond != NULL; cond = cond->next, eqno++) { SYMBOL *bound; char buf[255+1]; xassert(cond->code != NULL); bound = eval_symbolic(mpl, cond->code); switch (cond->rho) { #if 1 /* 13/VIII-2008 */ case O_LT: if (!(compare_symbols(mpl, value, bound) < 0)) { strcpy(buf, format_symbol(mpl, bound)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s%s = %s not < %s", par->name, format_tuple(mpl, '[', tuple), format_symbol(mpl, value), buf, eqno); } break; case O_LE: if (!(compare_symbols(mpl, value, bound) <= 0)) { strcpy(buf, format_symbol(mpl, bound)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s%s = %s not <= %s", par->name, format_tuple(mpl, '[', tuple), format_symbol(mpl, value), buf, eqno); } break; #endif case O_EQ: if (!(compare_symbols(mpl, value, bound) == 0)) { strcpy(buf, format_symbol(mpl, bound)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s%s = %s not = %s", par->name, format_tuple(mpl, '[', tuple), format_symbol(mpl, value), buf, eqno); } break; #if 1 /* 13/VIII-2008 */ case O_GE: if (!(compare_symbols(mpl, value, bound) >= 0)) { strcpy(buf, format_symbol(mpl, bound)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s%s = %s not >= %s", par->name, format_tuple(mpl, '[', tuple), format_symbol(mpl, value), buf, eqno); } break; case O_GT: if (!(compare_symbols(mpl, value, bound) > 0)) { strcpy(buf, format_symbol(mpl, bound)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s%s = %s not > %s", par->name, format_tuple(mpl, '[', tuple), format_symbol(mpl, value), buf, eqno); } break; #endif case O_NE: if (!(compare_symbols(mpl, value, bound) != 0)) { strcpy(buf, format_symbol(mpl, bound)); xassert(strlen(buf) < sizeof(buf)); error(mpl, "%s%s = %s not <> %s", par->name, format_tuple(mpl, '[', tuple), format_symbol(mpl, value), buf, eqno); } break; default: xassert(cond != cond); } delete_symbol(mpl, bound); } /* the value must be in all specified supersets */ for (in = par->in, eqno = 1; in != NULL; in = in->next, eqno++) { TUPLE *dummy; xassert(in->code != NULL); xassert(in->code->dim == 1); dummy = expand_tuple(mpl, create_tuple(mpl), copy_symbol(mpl, value)); if (!is_member(mpl, in->code, dummy)) error(mpl, "%s%s = %s not in specified set; see (%d)", par->name, format_tuple(mpl, '[', tuple), format_symbol(mpl, value), eqno); delete_tuple(mpl, dummy); } return; } /*---------------------------------------------------------------------- -- take_member_sym - obtain symb. value assigned to parameter member. -- -- This routine obtains a symbolic value assigned to member of specified -- symbolic model parameter and returns it on exit. -- -- NOTE: This routine must not be called out of domain scope. */ SYMBOL *take_member_sym /* returns value, not reference */ ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ) { MEMBER *memb; SYMBOL *value; /* find member in the parameter array */ memb = find_member(mpl, par->array, tuple); if (memb != NULL) { /* member exists, so just take its value */ value = copy_symbol(mpl, memb->value.sym); } else if (par->assign != NULL) { /* compute value using assignment expression */ value = eval_symbolic(mpl, par->assign); add: /* check that the value satisfies to all restrictions, assign it to new member, and add the member to the array */ check_value_sym(mpl, par, tuple, value); memb = add_member(mpl, par->array, copy_tuple(mpl, tuple)); memb->value.sym = copy_symbol(mpl, value); } else if (par->option != NULL) { /* compute default value */ value = eval_symbolic(mpl, par->option); goto add; } else if (par->defval != NULL) { /* take default value provided in the data section */ value = copy_symbol(mpl, par->defval); goto add; } else { /* no value is provided */ error(mpl, "no value for %s%s", par->name, format_tuple(mpl, '[', tuple)); } return value; } /*---------------------------------------------------------------------- -- eval_member_sym - evaluate symb. value assigned to parameter member. -- -- This routine evaluates a symbolic value assigned to given member of -- specified symbolic model parameter and returns it on exit. */ struct eval_sym_info { /* working info used by the routine eval_member_sym */ PARAMETER *par; /* model parameter */ TUPLE *tuple; /* n-tuple, which defines parameter member */ MEMBER *memb; /* normally this pointer is NULL; the routine uses this pointer to check data provided in the data section, in which case it points to a member currently checked; this check is performed automatically only once when a reference to any member occurs for the first time */ SYMBOL *value; /* evaluated symbolic value */ }; static void eval_sym_func(MPL *mpl, void *_info) { /* this is auxiliary routine to work within domain scope */ struct eval_sym_info *info = _info; if (info->memb != NULL) { /* checking call; check symbolic value being assigned */ check_value_sym(mpl, info->par, info->memb->tuple, info->memb->value.sym); } else { /* normal call; evaluate member, which has given n-tuple */ info->value = take_member_sym(mpl, info->par, info->tuple); } return; } SYMBOL *eval_member_sym /* returns value, not reference */ ( MPL *mpl, PARAMETER *par, /* not changed */ TUPLE *tuple /* not changed */ ) { /* this routine evaluates symbolic parameter member */ struct eval_sym_info _info, *info = &_info; xassert(par->type == A_SYMBOLIC); xassert(par->dim == tuple_dimen(mpl, tuple)); info->par = par; info->tuple = tuple; if (par->data == 1) { /* check data, which are provided in the data section, but not checked yet */ /* save pointer to the last array member; note that during the check new members may be added beyond the last member due to references to the same parameter from default expression as well as from expressions that define restricting conditions; however, values assigned to the new members will be checked by other routine, so we don't need to check them here */ MEMBER *tail = par->array->tail; /* change the data status to prevent infinite recursive loop due to references to the same parameter during the check */ par->data = 2; /* check values assigned to array members in the data section until the marked member has been reached */ for (info->memb = par->array->head; info->memb != NULL; info->memb = info->memb->next) { if (eval_within_domain(mpl, par->domain, info->memb->tuple, info, eval_sym_func)) out_of_domain(mpl, par->name, info->memb->tuple); if (info->memb == tail) break; } /* the check has been finished */ } /* evaluate member, which has given n-tuple */ info->memb = NULL; if (eval_within_domain(mpl, info->par->domain, info->tuple, info, eval_sym_func)) out_of_domain(mpl, par->name, info->tuple); /* bring evaluated value to the calling program */ return info->value; } /*---------------------------------------------------------------------- -- eval_whole_par - evaluate model parameter over entire domain. -- -- This routine evaluates all members of specified model parameter over -- entire domain. */ static int whole_par_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ PARAMETER *par = (PARAMETER *)info; TUPLE *tuple = get_domain_tuple(mpl, par->domain); switch (par->type) { case A_NUMERIC: case A_INTEGER: case A_BINARY: eval_member_num(mpl, par, tuple); break; case A_SYMBOLIC: delete_symbol(mpl, eval_member_sym(mpl, par, tuple)); break; default: xassert(par != par); } delete_tuple(mpl, tuple); return 0; } void eval_whole_par(MPL *mpl, PARAMETER *par) { loop_within_domain(mpl, par->domain, par, whole_par_func); return; } /*---------------------------------------------------------------------- -- clean_parameter - clean model parameter. -- -- This routine cleans specified model parameter that assumes deleting -- all stuff dynamically allocated during the generation phase. */ void clean_parameter(MPL *mpl, PARAMETER *par) { CONDITION *cond; WITHIN *in; MEMBER *memb; /* clean subscript domain */ clean_domain(mpl, par->domain); /* clean pseudo-code for computing restricting conditions */ for (cond = par->cond; cond != NULL; cond = cond->next) clean_code(mpl, cond->code); /* clean pseudo-code for computing restricting supersets */ for (in = par->in; in != NULL; in = in->next) clean_code(mpl, in->code); /* clean pseudo-code for computing assigned value */ clean_code(mpl, par->assign); /* clean pseudo-code for computing default value */ clean_code(mpl, par->option); /* reset data status flag */ par->data = 0; /* delete default symbolic value */ if (par->defval != NULL) delete_symbol(mpl, par->defval), par->defval = NULL; /* delete content array */ for (memb = par->array->head; memb != NULL; memb = memb->next) delete_value(mpl, par->array->type, &memb->value); delete_array(mpl, par->array), par->array = NULL; return; } /**********************************************************************/ /* * * MODEL VARIABLES * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- take_member_var - obtain reference to elemental variable. -- -- This routine obtains a reference to elemental variable assigned to -- given member of specified model variable and returns it on exit. If -- necessary, new elemental variable is created. -- -- NOTE: This routine must not be called out of domain scope. */ ELEMVAR *take_member_var /* returns reference */ ( MPL *mpl, VARIABLE *var, /* not changed */ TUPLE *tuple /* not changed */ ) { MEMBER *memb; ELEMVAR *refer; /* find member in the variable array */ memb = find_member(mpl, var->array, tuple); if (memb != NULL) { /* member exists, so just take the reference */ refer = memb->value.var; } else { /* member is referenced for the first time and therefore does not exist; create new elemental variable, assign it to new member, and add the member to the variable array */ memb = add_member(mpl, var->array, copy_tuple(mpl, tuple)); refer = (memb->value.var = dmp_get_atom(mpl->elemvars, sizeof(ELEMVAR))); refer->j = 0; refer->var = var; refer->memb = memb; /* compute lower bound */ if (var->lbnd == NULL) refer->lbnd = 0.0; else refer->lbnd = eval_numeric(mpl, var->lbnd); /* compute upper bound */ if (var->ubnd == NULL) refer->ubnd = 0.0; else if (var->ubnd == var->lbnd) refer->ubnd = refer->lbnd; else refer->ubnd = eval_numeric(mpl, var->ubnd); /* nullify working quantity */ refer->temp = 0.0; #if 1 /* 15/V-2010 */ /* solution has not been obtained by the solver yet */ refer->stat = 0; refer->prim = refer->dual = 0.0; #endif } return refer; } /*---------------------------------------------------------------------- -- eval_member_var - evaluate reference to elemental variable. -- -- This routine evaluates a reference to elemental variable assigned to -- member of specified model variable and returns it on exit. */ struct eval_var_info { /* working info used by the routine eval_member_var */ VARIABLE *var; /* model variable */ TUPLE *tuple; /* n-tuple, which defines variable member */ ELEMVAR *refer; /* evaluated reference to elemental variable */ }; static void eval_var_func(MPL *mpl, void *_info) { /* this is auxiliary routine to work within domain scope */ struct eval_var_info *info = _info; info->refer = take_member_var(mpl, info->var, info->tuple); return; } ELEMVAR *eval_member_var /* returns reference */ ( MPL *mpl, VARIABLE *var, /* not changed */ TUPLE *tuple /* not changed */ ) { /* this routine evaluates variable member */ struct eval_var_info _info, *info = &_info; xassert(var->dim == tuple_dimen(mpl, tuple)); info->var = var; info->tuple = tuple; /* evaluate member, which has given n-tuple */ if (eval_within_domain(mpl, info->var->domain, info->tuple, info, eval_var_func)) out_of_domain(mpl, var->name, info->tuple); /* bring evaluated reference to the calling program */ return info->refer; } /*---------------------------------------------------------------------- -- eval_whole_var - evaluate model variable over entire domain. -- -- This routine evaluates all members of specified model variable over -- entire domain. */ static int whole_var_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ VARIABLE *var = (VARIABLE *)info; TUPLE *tuple = get_domain_tuple(mpl, var->domain); eval_member_var(mpl, var, tuple); delete_tuple(mpl, tuple); return 0; } void eval_whole_var(MPL *mpl, VARIABLE *var) { loop_within_domain(mpl, var->domain, var, whole_var_func); return; } /*---------------------------------------------------------------------- -- clean_variable - clean model variable. -- -- This routine cleans specified model variable that assumes deleting -- all stuff dynamically allocated during the generation phase. */ void clean_variable(MPL *mpl, VARIABLE *var) { MEMBER *memb; /* clean subscript domain */ clean_domain(mpl, var->domain); /* clean code for computing lower bound */ clean_code(mpl, var->lbnd); /* clean code for computing upper bound */ if (var->ubnd != var->lbnd) clean_code(mpl, var->ubnd); /* delete content array */ for (memb = var->array->head; memb != NULL; memb = memb->next) dmp_free_atom(mpl->elemvars, memb->value.var, sizeof(ELEMVAR)); delete_array(mpl, var->array), var->array = NULL; return; } /**********************************************************************/ /* * * MODEL CONSTRAINTS AND OBJECTIVES * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- take_member_con - obtain reference to elemental constraint. -- -- This routine obtains a reference to elemental constraint assigned -- to given member of specified model constraint and returns it on exit. -- If necessary, new elemental constraint is created. -- -- NOTE: This routine must not be called out of domain scope. */ ELEMCON *take_member_con /* returns reference */ ( MPL *mpl, CONSTRAINT *con, /* not changed */ TUPLE *tuple /* not changed */ ) { MEMBER *memb; ELEMCON *refer; /* find member in the constraint array */ memb = find_member(mpl, con->array, tuple); if (memb != NULL) { /* member exists, so just take the reference */ refer = memb->value.con; } else { /* member is referenced for the first time and therefore does not exist; create new elemental constraint, assign it to new member, and add the member to the constraint array */ memb = add_member(mpl, con->array, copy_tuple(mpl, tuple)); refer = (memb->value.con = dmp_get_atom(mpl->elemcons, sizeof(ELEMCON))); refer->i = 0; refer->con = con; refer->memb = memb; /* compute linear form */ xassert(con->code != NULL); refer->form = eval_formula(mpl, con->code); /* compute lower and upper bounds */ if (con->lbnd == NULL && con->ubnd == NULL) { /* objective has no bounds */ double temp; xassert(con->type == A_MINIMIZE || con->type == A_MAXIMIZE); /* carry the constant term to the right-hand side */ refer->form = remove_constant(mpl, refer->form, &temp); refer->lbnd = refer->ubnd = - temp; } else if (con->lbnd != NULL && con->ubnd == NULL) { /* constraint a * x + b >= c * y + d is transformed to the standard form a * x - c * y >= d - b */ double temp; xassert(con->type == A_CONSTRAINT); refer->form = linear_comb(mpl, +1.0, refer->form, -1.0, eval_formula(mpl, con->lbnd)); refer->form = remove_constant(mpl, refer->form, &temp); refer->lbnd = - temp; refer->ubnd = 0.0; } else if (con->lbnd == NULL && con->ubnd != NULL) { /* constraint a * x + b <= c * y + d is transformed to the standard form a * x - c * y <= d - b */ double temp; xassert(con->type == A_CONSTRAINT); refer->form = linear_comb(mpl, +1.0, refer->form, -1.0, eval_formula(mpl, con->ubnd)); refer->form = remove_constant(mpl, refer->form, &temp); refer->lbnd = 0.0; refer->ubnd = - temp; } else if (con->lbnd == con->ubnd) { /* constraint a * x + b = c * y + d is transformed to the standard form a * x - c * y = d - b */ double temp; xassert(con->type == A_CONSTRAINT); refer->form = linear_comb(mpl, +1.0, refer->form, -1.0, eval_formula(mpl, con->lbnd)); refer->form = remove_constant(mpl, refer->form, &temp); refer->lbnd = refer->ubnd = - temp; } else { /* ranged constraint c <= a * x + b <= d is transformed to the standard form c - b <= a * x <= d - b */ double temp, temp1, temp2; xassert(con->type == A_CONSTRAINT); refer->form = remove_constant(mpl, refer->form, &temp); xassert(remove_constant(mpl, eval_formula(mpl, con->lbnd), &temp1) == NULL); xassert(remove_constant(mpl, eval_formula(mpl, con->ubnd), &temp2) == NULL); refer->lbnd = fp_sub(mpl, temp1, temp); refer->ubnd = fp_sub(mpl, temp2, temp); } #if 1 /* 15/V-2010 */ /* solution has not been obtained by the solver yet */ refer->stat = 0; refer->prim = refer->dual = 0.0; #endif } return refer; } /*---------------------------------------------------------------------- -- eval_member_con - evaluate reference to elemental constraint. -- -- This routine evaluates a reference to elemental constraint assigned -- to member of specified model constraint and returns it on exit. */ struct eval_con_info { /* working info used by the routine eval_member_con */ CONSTRAINT *con; /* model constraint */ TUPLE *tuple; /* n-tuple, which defines constraint member */ ELEMCON *refer; /* evaluated reference to elemental constraint */ }; static void eval_con_func(MPL *mpl, void *_info) { /* this is auxiliary routine to work within domain scope */ struct eval_con_info *info = _info; info->refer = take_member_con(mpl, info->con, info->tuple); return; } ELEMCON *eval_member_con /* returns reference */ ( MPL *mpl, CONSTRAINT *con, /* not changed */ TUPLE *tuple /* not changed */ ) { /* this routine evaluates constraint member */ struct eval_con_info _info, *info = &_info; xassert(con->dim == tuple_dimen(mpl, tuple)); info->con = con; info->tuple = tuple; /* evaluate member, which has given n-tuple */ if (eval_within_domain(mpl, info->con->domain, info->tuple, info, eval_con_func)) out_of_domain(mpl, con->name, info->tuple); /* bring evaluated reference to the calling program */ return info->refer; } /*---------------------------------------------------------------------- -- eval_whole_con - evaluate model constraint over entire domain. -- -- This routine evaluates all members of specified model constraint over -- entire domain. */ static int whole_con_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ CONSTRAINT *con = (CONSTRAINT *)info; TUPLE *tuple = get_domain_tuple(mpl, con->domain); eval_member_con(mpl, con, tuple); delete_tuple(mpl, tuple); return 0; } void eval_whole_con(MPL *mpl, CONSTRAINT *con) { loop_within_domain(mpl, con->domain, con, whole_con_func); return; } /*---------------------------------------------------------------------- -- clean_constraint - clean model constraint. -- -- This routine cleans specified model constraint that assumes deleting -- all stuff dynamically allocated during the generation phase. */ void clean_constraint(MPL *mpl, CONSTRAINT *con) { MEMBER *memb; /* clean subscript domain */ clean_domain(mpl, con->domain); /* clean code for computing main linear form */ clean_code(mpl, con->code); /* clean code for computing lower bound */ clean_code(mpl, con->lbnd); /* clean code for computing upper bound */ if (con->ubnd != con->lbnd) clean_code(mpl, con->ubnd); /* delete content array */ for (memb = con->array->head; memb != NULL; memb = memb->next) { delete_formula(mpl, memb->value.con->form); dmp_free_atom(mpl->elemcons, memb->value.con, sizeof(ELEMCON)); } delete_array(mpl, con->array), con->array = NULL; return; } /**********************************************************************/ /* * * PSEUDO-CODE * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- eval_numeric - evaluate pseudo-code to determine numeric value. -- -- This routine evaluates specified pseudo-code to determine resultant -- numeric value, which is returned on exit. */ struct iter_num_info { /* working info used by the routine iter_num_func */ CODE *code; /* pseudo-code for iterated operation to be performed */ double value; /* resultant value */ }; static int iter_num_func(MPL *mpl, void *_info) { /* this is auxiliary routine used to perform iterated operation on numeric "integrand" within domain scope */ struct iter_num_info *info = _info; double temp; temp = eval_numeric(mpl, info->code->arg.loop.x); switch (info->code->op) { case O_SUM: /* summation over domain */ info->value = fp_add(mpl, info->value, temp); break; case O_PROD: /* multiplication over domain */ info->value = fp_mul(mpl, info->value, temp); break; case O_MINIMUM: /* minimum over domain */ if (info->value > temp) info->value = temp; break; case O_MAXIMUM: /* maximum over domain */ if (info->value < temp) info->value = temp; break; default: xassert(info != info); } return 0; } double eval_numeric(MPL *mpl, CODE *code) { double value; xassert(code != NULL); xassert(code->type == A_NUMERIC); xassert(code->dim == 0); /* if the operation has a side effect, invalidate and delete the resultant value */ if (code->vflag && code->valid) { code->valid = 0; delete_value(mpl, code->type, &code->value); } /* if resultant value is valid, no evaluation is needed */ if (code->valid) { value = code->value.num; goto done; } /* evaluate pseudo-code recursively */ switch (code->op) { case O_NUMBER: /* take floating-point number */ value = code->arg.num; break; case O_MEMNUM: /* take member of numeric parameter */ { TUPLE *tuple; ARG_LIST *e; tuple = create_tuple(mpl); for (e = code->arg.par.list; e != NULL; e = e->next) tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, e->x)); value = eval_member_num(mpl, code->arg.par.par, tuple); delete_tuple(mpl, tuple); } break; case O_MEMVAR: /* take computed value of elemental variable */ { TUPLE *tuple; ARG_LIST *e; #if 1 /* 15/V-2010 */ ELEMVAR *var; #endif tuple = create_tuple(mpl); for (e = code->arg.var.list; e != NULL; e = e->next) tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, e->x)); #if 0 /* 15/V-2010 */ value = eval_member_var(mpl, code->arg.var.var, tuple) ->value; #else var = eval_member_var(mpl, code->arg.var.var, tuple); switch (code->arg.var.suff) { case DOT_LB: if (var->var->lbnd == NULL) value = -DBL_MAX; else value = var->lbnd; break; case DOT_UB: if (var->var->ubnd == NULL) value = +DBL_MAX; else value = var->ubnd; break; case DOT_STATUS: value = var->stat; break; case DOT_VAL: value = var->prim; break; case DOT_DUAL: value = var->dual; break; default: xassert(code != code); } #endif delete_tuple(mpl, tuple); } break; #if 1 /* 15/V-2010 */ case O_MEMCON: /* take computed value of elemental constraint */ { TUPLE *tuple; ARG_LIST *e; ELEMCON *con; tuple = create_tuple(mpl); for (e = code->arg.con.list; e != NULL; e = e->next) tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, e->x)); con = eval_member_con(mpl, code->arg.con.con, tuple); switch (code->arg.con.suff) { case DOT_LB: if (con->con->lbnd == NULL) value = -DBL_MAX; else value = con->lbnd; break; case DOT_UB: if (con->con->ubnd == NULL) value = +DBL_MAX; else value = con->ubnd; break; case DOT_STATUS: value = con->stat; break; case DOT_VAL: value = con->prim; break; case DOT_DUAL: value = con->dual; break; default: xassert(code != code); } delete_tuple(mpl, tuple); } break; #endif case O_IRAND224: /* pseudo-random in [0, 2^24-1] */ value = fp_irand224(mpl); break; case O_UNIFORM01: /* pseudo-random in [0, 1) */ value = fp_uniform01(mpl); break; case O_NORMAL01: /* gaussian random, mu = 0, sigma = 1 */ value = fp_normal01(mpl); break; case O_GMTIME: /* current calendar time */ value = fn_gmtime(mpl); break; case O_CVTNUM: /* conversion to numeric */ { SYMBOL *sym; sym = eval_symbolic(mpl, code->arg.arg.x); #if 0 /* 23/XI-2008 */ if (sym->str != NULL) error(mpl, "cannot convert %s to floating-point numbe" "r", format_symbol(mpl, sym)); value = sym->num; #else if (sym->str == NULL) value = sym->num; else { if (str2num(sym->str, &value)) error(mpl, "cannot convert %s to floating-point nu" "mber", format_symbol(mpl, sym)); } #endif delete_symbol(mpl, sym); } break; case O_PLUS: /* unary plus */ value = + eval_numeric(mpl, code->arg.arg.x); break; case O_MINUS: /* unary minus */ value = - eval_numeric(mpl, code->arg.arg.x); break; case O_ABS: /* absolute value */ value = fabs(eval_numeric(mpl, code->arg.arg.x)); break; case O_CEIL: /* round upward ("ceiling of x") */ value = ceil(eval_numeric(mpl, code->arg.arg.x)); break; case O_FLOOR: /* round downward ("floor of x") */ value = floor(eval_numeric(mpl, code->arg.arg.x)); break; case O_EXP: /* base-e exponential */ value = fp_exp(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_LOG: /* natural logarithm */ value = fp_log(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_LOG10: /* common (decimal) logarithm */ value = fp_log10(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_SQRT: /* square root */ value = fp_sqrt(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_SIN: /* trigonometric sine */ value = fp_sin(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_COS: /* trigonometric cosine */ value = fp_cos(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_ATAN: /* trigonometric arctangent (one argument) */ value = fp_atan(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_ATAN2: /* trigonometric arctangent (two arguments) */ value = fp_atan2(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_ROUND: /* round to nearest integer */ value = fp_round(mpl, eval_numeric(mpl, code->arg.arg.x), 0.0); break; case O_ROUND2: /* round to n fractional digits */ value = fp_round(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_TRUNC: /* truncate to nearest integer */ value = fp_trunc(mpl, eval_numeric(mpl, code->arg.arg.x), 0.0); break; case O_TRUNC2: /* truncate to n fractional digits */ value = fp_trunc(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_ADD: /* addition */ value = fp_add(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_SUB: /* subtraction */ value = fp_sub(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_LESS: /* non-negative subtraction */ value = fp_less(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_MUL: /* multiplication */ value = fp_mul(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_DIV: /* division */ value = fp_div(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_IDIV: /* quotient of exact division */ value = fp_idiv(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_MOD: /* remainder of exact division */ value = fp_mod(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_POWER: /* exponentiation (raise to power) */ value = fp_power(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_UNIFORM: /* pseudo-random in [a, b) */ value = fp_uniform(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_NORMAL: /* gaussian random, given mu and sigma */ value = fp_normal(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y)); break; case O_CARD: { ELEMSET *set; set = eval_elemset(mpl, code->arg.arg.x); value = set->size; delete_array(mpl, set); } break; case O_LENGTH: { SYMBOL *sym; char str[MAX_LENGTH+1]; sym = eval_symbolic(mpl, code->arg.arg.x); if (sym->str == NULL) sprintf(str, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, str); delete_symbol(mpl, sym); value = strlen(str); } break; case O_STR2TIME: { SYMBOL *sym; char str[MAX_LENGTH+1], fmt[MAX_LENGTH+1]; sym = eval_symbolic(mpl, code->arg.arg.x); if (sym->str == NULL) sprintf(str, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, str); delete_symbol(mpl, sym); sym = eval_symbolic(mpl, code->arg.arg.y); if (sym->str == NULL) sprintf(fmt, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, fmt); delete_symbol(mpl, sym); value = fn_str2time(mpl, str, fmt); } break; case O_FORK: /* if-then-else */ if (eval_logical(mpl, code->arg.arg.x)) value = eval_numeric(mpl, code->arg.arg.y); else if (code->arg.arg.z == NULL) value = 0.0; else value = eval_numeric(mpl, code->arg.arg.z); break; case O_MIN: /* minimal value (n-ary) */ { ARG_LIST *e; double temp; value = +DBL_MAX; for (e = code->arg.list; e != NULL; e = e->next) { temp = eval_numeric(mpl, e->x); if (value > temp) value = temp; } } break; case O_MAX: /* maximal value (n-ary) */ { ARG_LIST *e; double temp; value = -DBL_MAX; for (e = code->arg.list; e != NULL; e = e->next) { temp = eval_numeric(mpl, e->x); if (value < temp) value = temp; } } break; case O_SUM: /* summation over domain */ { struct iter_num_info _info, *info = &_info; info->code = code; info->value = 0.0; loop_within_domain(mpl, code->arg.loop.domain, info, iter_num_func); value = info->value; } break; case O_PROD: /* multiplication over domain */ { struct iter_num_info _info, *info = &_info; info->code = code; info->value = 1.0; loop_within_domain(mpl, code->arg.loop.domain, info, iter_num_func); value = info->value; } break; case O_MINIMUM: /* minimum over domain */ { struct iter_num_info _info, *info = &_info; info->code = code; info->value = +DBL_MAX; loop_within_domain(mpl, code->arg.loop.domain, info, iter_num_func); if (info->value == +DBL_MAX) error(mpl, "min{} over empty set; result undefined"); value = info->value; } break; case O_MAXIMUM: /* maximum over domain */ { struct iter_num_info _info, *info = &_info; info->code = code; info->value = -DBL_MAX; loop_within_domain(mpl, code->arg.loop.domain, info, iter_num_func); if (info->value == -DBL_MAX) error(mpl, "max{} over empty set; result undefined"); value = info->value; } break; default: xassert(code != code); } /* save resultant value */ xassert(!code->valid); code->valid = 1; code->value.num = value; done: return value; } /*---------------------------------------------------------------------- -- eval_symbolic - evaluate pseudo-code to determine symbolic value. -- -- This routine evaluates specified pseudo-code to determine resultant -- symbolic value, which is returned on exit. */ SYMBOL *eval_symbolic(MPL *mpl, CODE *code) { SYMBOL *value; xassert(code != NULL); xassert(code->type == A_SYMBOLIC); xassert(code->dim == 0); /* if the operation has a side effect, invalidate and delete the resultant value */ if (code->vflag && code->valid) { code->valid = 0; delete_value(mpl, code->type, &code->value); } /* if resultant value is valid, no evaluation is needed */ if (code->valid) { value = copy_symbol(mpl, code->value.sym); goto done; } /* evaluate pseudo-code recursively */ switch (code->op) { case O_STRING: /* take character string */ value = create_symbol_str(mpl, create_string(mpl, code->arg.str)); break; case O_INDEX: /* take dummy index */ xassert(code->arg.index.slot->value != NULL); value = copy_symbol(mpl, code->arg.index.slot->value); break; case O_MEMSYM: /* take member of symbolic parameter */ { TUPLE *tuple; ARG_LIST *e; tuple = create_tuple(mpl); for (e = code->arg.par.list; e != NULL; e = e->next) tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, e->x)); value = eval_member_sym(mpl, code->arg.par.par, tuple); delete_tuple(mpl, tuple); } break; case O_CVTSYM: /* conversion to symbolic */ value = create_symbol_num(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_CONCAT: /* concatenation */ value = concat_symbols(mpl, eval_symbolic(mpl, code->arg.arg.x), eval_symbolic(mpl, code->arg.arg.y)); break; case O_FORK: /* if-then-else */ if (eval_logical(mpl, code->arg.arg.x)) value = eval_symbolic(mpl, code->arg.arg.y); else if (code->arg.arg.z == NULL) value = create_symbol_num(mpl, 0.0); else value = eval_symbolic(mpl, code->arg.arg.z); break; case O_SUBSTR: case O_SUBSTR3: { double pos, len; char str[MAX_LENGTH+1]; value = eval_symbolic(mpl, code->arg.arg.x); if (value->str == NULL) sprintf(str, "%.*g", DBL_DIG, value->num); else fetch_string(mpl, value->str, str); delete_symbol(mpl, value); if (code->op == O_SUBSTR) { pos = eval_numeric(mpl, code->arg.arg.y); if (pos != floor(pos)) error(mpl, "substr('...', %.*g); non-integer secon" "d argument", DBL_DIG, pos); if (pos < 1 || pos > strlen(str) + 1) error(mpl, "substr('...', %.*g); substring out of " "range", DBL_DIG, pos); } else { pos = eval_numeric(mpl, code->arg.arg.y); len = eval_numeric(mpl, code->arg.arg.z); if (pos != floor(pos) || len != floor(len)) error(mpl, "substr('...', %.*g, %.*g); non-integer" " second and/or third argument", DBL_DIG, pos, DBL_DIG, len); if (pos < 1 || len < 0 || pos + len > strlen(str) + 1) error(mpl, "substr('...', %.*g, %.*g); substring o" "ut of range", DBL_DIG, pos, DBL_DIG, len); str[(int)pos + (int)len - 1] = '\0'; } value = create_symbol_str(mpl, create_string(mpl, str + (int)pos - 1)); } break; case O_TIME2STR: { double num; SYMBOL *sym; char str[MAX_LENGTH+1], fmt[MAX_LENGTH+1]; num = eval_numeric(mpl, code->arg.arg.x); sym = eval_symbolic(mpl, code->arg.arg.y); if (sym->str == NULL) sprintf(fmt, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, fmt); delete_symbol(mpl, sym); fn_time2str(mpl, str, num, fmt); value = create_symbol_str(mpl, create_string(mpl, str)); } break; default: xassert(code != code); } /* save resultant value */ xassert(!code->valid); code->valid = 1; code->value.sym = copy_symbol(mpl, value); done: return value; } /*---------------------------------------------------------------------- -- eval_logical - evaluate pseudo-code to determine logical value. -- -- This routine evaluates specified pseudo-code to determine resultant -- logical value, which is returned on exit. */ struct iter_log_info { /* working info used by the routine iter_log_func */ CODE *code; /* pseudo-code for iterated operation to be performed */ int value; /* resultant value */ }; static int iter_log_func(MPL *mpl, void *_info) { /* this is auxiliary routine used to perform iterated operation on logical "integrand" within domain scope */ struct iter_log_info *info = _info; int ret = 0; switch (info->code->op) { case O_FORALL: /* conjunction over domain */ info->value &= eval_logical(mpl, info->code->arg.loop.x); if (!info->value) ret = 1; break; case O_EXISTS: /* disjunction over domain */ info->value |= eval_logical(mpl, info->code->arg.loop.x); if (info->value) ret = 1; break; default: xassert(info != info); } return ret; } int eval_logical(MPL *mpl, CODE *code) { int value; xassert(code->type == A_LOGICAL); xassert(code->dim == 0); /* if the operation has a side effect, invalidate and delete the resultant value */ if (code->vflag && code->valid) { code->valid = 0; delete_value(mpl, code->type, &code->value); } /* if resultant value is valid, no evaluation is needed */ if (code->valid) { value = code->value.bit; goto done; } /* evaluate pseudo-code recursively */ switch (code->op) { case O_CVTLOG: /* conversion to logical */ value = (eval_numeric(mpl, code->arg.arg.x) != 0.0); break; case O_NOT: /* negation (logical "not") */ value = !eval_logical(mpl, code->arg.arg.x); break; case O_LT: /* comparison on 'less than' */ #if 0 /* 02/VIII-2008 */ value = (eval_numeric(mpl, code->arg.arg.x) < eval_numeric(mpl, code->arg.arg.y)); #else xassert(code->arg.arg.x != NULL); if (code->arg.arg.x->type == A_NUMERIC) value = (eval_numeric(mpl, code->arg.arg.x) < eval_numeric(mpl, code->arg.arg.y)); else { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); value = (compare_symbols(mpl, sym1, sym2) < 0); delete_symbol(mpl, sym1); delete_symbol(mpl, sym2); } #endif break; case O_LE: /* comparison on 'not greater than' */ #if 0 /* 02/VIII-2008 */ value = (eval_numeric(mpl, code->arg.arg.x) <= eval_numeric(mpl, code->arg.arg.y)); #else xassert(code->arg.arg.x != NULL); if (code->arg.arg.x->type == A_NUMERIC) value = (eval_numeric(mpl, code->arg.arg.x) <= eval_numeric(mpl, code->arg.arg.y)); else { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); value = (compare_symbols(mpl, sym1, sym2) <= 0); delete_symbol(mpl, sym1); delete_symbol(mpl, sym2); } #endif break; case O_EQ: /* comparison on 'equal to' */ xassert(code->arg.arg.x != NULL); if (code->arg.arg.x->type == A_NUMERIC) value = (eval_numeric(mpl, code->arg.arg.x) == eval_numeric(mpl, code->arg.arg.y)); else { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); value = (compare_symbols(mpl, sym1, sym2) == 0); delete_symbol(mpl, sym1); delete_symbol(mpl, sym2); } break; case O_GE: /* comparison on 'not less than' */ #if 0 /* 02/VIII-2008 */ value = (eval_numeric(mpl, code->arg.arg.x) >= eval_numeric(mpl, code->arg.arg.y)); #else xassert(code->arg.arg.x != NULL); if (code->arg.arg.x->type == A_NUMERIC) value = (eval_numeric(mpl, code->arg.arg.x) >= eval_numeric(mpl, code->arg.arg.y)); else { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); value = (compare_symbols(mpl, sym1, sym2) >= 0); delete_symbol(mpl, sym1); delete_symbol(mpl, sym2); } #endif break; case O_GT: /* comparison on 'greater than' */ #if 0 /* 02/VIII-2008 */ value = (eval_numeric(mpl, code->arg.arg.x) > eval_numeric(mpl, code->arg.arg.y)); #else xassert(code->arg.arg.x != NULL); if (code->arg.arg.x->type == A_NUMERIC) value = (eval_numeric(mpl, code->arg.arg.x) > eval_numeric(mpl, code->arg.arg.y)); else { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); value = (compare_symbols(mpl, sym1, sym2) > 0); delete_symbol(mpl, sym1); delete_symbol(mpl, sym2); } #endif break; case O_NE: /* comparison on 'not equal to' */ xassert(code->arg.arg.x != NULL); if (code->arg.arg.x->type == A_NUMERIC) value = (eval_numeric(mpl, code->arg.arg.x) != eval_numeric(mpl, code->arg.arg.y)); else { SYMBOL *sym1 = eval_symbolic(mpl, code->arg.arg.x); SYMBOL *sym2 = eval_symbolic(mpl, code->arg.arg.y); value = (compare_symbols(mpl, sym1, sym2) != 0); delete_symbol(mpl, sym1); delete_symbol(mpl, sym2); } break; case O_AND: /* conjunction (logical "and") */ value = eval_logical(mpl, code->arg.arg.x) && eval_logical(mpl, code->arg.arg.y); break; case O_OR: /* disjunction (logical "or") */ value = eval_logical(mpl, code->arg.arg.x) || eval_logical(mpl, code->arg.arg.y); break; case O_IN: /* test on 'x in Y' */ { TUPLE *tuple; tuple = eval_tuple(mpl, code->arg.arg.x); value = is_member(mpl, code->arg.arg.y, tuple); delete_tuple(mpl, tuple); } break; case O_NOTIN: /* test on 'x not in Y' */ { TUPLE *tuple; tuple = eval_tuple(mpl, code->arg.arg.x); value = !is_member(mpl, code->arg.arg.y, tuple); delete_tuple(mpl, tuple); } break; case O_WITHIN: /* test on 'X within Y' */ { ELEMSET *set; MEMBER *memb; set = eval_elemset(mpl, code->arg.arg.x); value = 1; for (memb = set->head; memb != NULL; memb = memb->next) { if (!is_member(mpl, code->arg.arg.y, memb->tuple)) { value = 0; break; } } delete_elemset(mpl, set); } break; case O_NOTWITHIN: /* test on 'X not within Y' */ { ELEMSET *set; MEMBER *memb; set = eval_elemset(mpl, code->arg.arg.x); value = 1; for (memb = set->head; memb != NULL; memb = memb->next) { if (is_member(mpl, code->arg.arg.y, memb->tuple)) { value = 0; break; } } delete_elemset(mpl, set); } break; case O_FORALL: /* conjunction (A-quantification) */ { struct iter_log_info _info, *info = &_info; info->code = code; info->value = 1; loop_within_domain(mpl, code->arg.loop.domain, info, iter_log_func); value = info->value; } break; case O_EXISTS: /* disjunction (E-quantification) */ { struct iter_log_info _info, *info = &_info; info->code = code; info->value = 0; loop_within_domain(mpl, code->arg.loop.domain, info, iter_log_func); value = info->value; } break; default: xassert(code != code); } /* save resultant value */ xassert(!code->valid); code->valid = 1; code->value.bit = value; done: return value; } /*---------------------------------------------------------------------- -- eval_tuple - evaluate pseudo-code to construct n-tuple. -- -- This routine evaluates specified pseudo-code to construct resultant -- n-tuple, which is returned on exit. */ TUPLE *eval_tuple(MPL *mpl, CODE *code) { TUPLE *value; xassert(code != NULL); xassert(code->type == A_TUPLE); xassert(code->dim > 0); /* if the operation has a side effect, invalidate and delete the resultant value */ if (code->vflag && code->valid) { code->valid = 0; delete_value(mpl, code->type, &code->value); } /* if resultant value is valid, no evaluation is needed */ if (code->valid) { value = copy_tuple(mpl, code->value.tuple); goto done; } /* evaluate pseudo-code recursively */ switch (code->op) { case O_TUPLE: /* make n-tuple */ { ARG_LIST *e; value = create_tuple(mpl); for (e = code->arg.list; e != NULL; e = e->next) value = expand_tuple(mpl, value, eval_symbolic(mpl, e->x)); } break; case O_CVTTUP: /* convert to 1-tuple */ value = expand_tuple(mpl, create_tuple(mpl), eval_symbolic(mpl, code->arg.arg.x)); break; default: xassert(code != code); } /* save resultant value */ xassert(!code->valid); code->valid = 1; code->value.tuple = copy_tuple(mpl, value); done: return value; } /*---------------------------------------------------------------------- -- eval_elemset - evaluate pseudo-code to construct elemental set. -- -- This routine evaluates specified pseudo-code to construct resultant -- elemental set, which is returned on exit. */ struct iter_set_info { /* working info used by the routine iter_set_func */ CODE *code; /* pseudo-code for iterated operation to be performed */ ELEMSET *value; /* resultant value */ }; static int iter_set_func(MPL *mpl, void *_info) { /* this is auxiliary routine used to perform iterated operation on n-tuple "integrand" within domain scope */ struct iter_set_info *info = _info; TUPLE *tuple; switch (info->code->op) { case O_SETOF: /* compute next n-tuple and add it to the set; in this case duplicate n-tuples are silently ignored */ tuple = eval_tuple(mpl, info->code->arg.loop.x); if (find_tuple(mpl, info->value, tuple) == NULL) add_tuple(mpl, info->value, tuple); else delete_tuple(mpl, tuple); break; case O_BUILD: /* construct next n-tuple using current values assigned to *free* dummy indices as its components and add it to the set; in this case duplicate n-tuples cannot appear */ add_tuple(mpl, info->value, get_domain_tuple(mpl, info->code->arg.loop.domain)); break; default: xassert(info != info); } return 0; } ELEMSET *eval_elemset(MPL *mpl, CODE *code) { ELEMSET *value; xassert(code != NULL); xassert(code->type == A_ELEMSET); xassert(code->dim > 0); /* if the operation has a side effect, invalidate and delete the resultant value */ if (code->vflag && code->valid) { code->valid = 0; delete_value(mpl, code->type, &code->value); } /* if resultant value is valid, no evaluation is needed */ if (code->valid) { value = copy_elemset(mpl, code->value.set); goto done; } /* evaluate pseudo-code recursively */ switch (code->op) { case O_MEMSET: /* take member of set */ { TUPLE *tuple; ARG_LIST *e; tuple = create_tuple(mpl); for (e = code->arg.set.list; e != NULL; e = e->next) tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, e->x)); value = copy_elemset(mpl, eval_member_set(mpl, code->arg.set.set, tuple)); delete_tuple(mpl, tuple); } break; case O_MAKE: /* make elemental set of n-tuples */ { ARG_LIST *e; value = create_elemset(mpl, code->dim); for (e = code->arg.list; e != NULL; e = e->next) check_then_add(mpl, value, eval_tuple(mpl, e->x)); } break; case O_UNION: /* union of two elemental sets */ value = set_union(mpl, eval_elemset(mpl, code->arg.arg.x), eval_elemset(mpl, code->arg.arg.y)); break; case O_DIFF: /* difference between two elemental sets */ value = set_diff(mpl, eval_elemset(mpl, code->arg.arg.x), eval_elemset(mpl, code->arg.arg.y)); break; case O_SYMDIFF: /* symmetric difference between two elemental sets */ value = set_symdiff(mpl, eval_elemset(mpl, code->arg.arg.x), eval_elemset(mpl, code->arg.arg.y)); break; case O_INTER: /* intersection of two elemental sets */ value = set_inter(mpl, eval_elemset(mpl, code->arg.arg.x), eval_elemset(mpl, code->arg.arg.y)); break; case O_CROSS: /* cross (Cartesian) product of two elemental sets */ value = set_cross(mpl, eval_elemset(mpl, code->arg.arg.x), eval_elemset(mpl, code->arg.arg.y)); break; case O_DOTS: /* build "arithmetic" elemental set */ value = create_arelset(mpl, eval_numeric(mpl, code->arg.arg.x), eval_numeric(mpl, code->arg.arg.y), code->arg.arg.z == NULL ? 1.0 : eval_numeric(mpl, code->arg.arg.z)); break; case O_FORK: /* if-then-else */ if (eval_logical(mpl, code->arg.arg.x)) value = eval_elemset(mpl, code->arg.arg.y); else value = eval_elemset(mpl, code->arg.arg.z); break; case O_SETOF: /* compute elemental set */ { struct iter_set_info _info, *info = &_info; info->code = code; info->value = create_elemset(mpl, code->dim); loop_within_domain(mpl, code->arg.loop.domain, info, iter_set_func); value = info->value; } break; case O_BUILD: /* build elemental set identical to domain set */ { struct iter_set_info _info, *info = &_info; info->code = code; info->value = create_elemset(mpl, code->dim); loop_within_domain(mpl, code->arg.loop.domain, info, iter_set_func); value = info->value; } break; default: xassert(code != code); } /* save resultant value */ xassert(!code->valid); code->valid = 1; code->value.set = copy_elemset(mpl, value); done: return value; } /*---------------------------------------------------------------------- -- is_member - check if n-tuple is in set specified by pseudo-code. -- -- This routine checks if given n-tuple is a member of elemental set -- specified in the form of pseudo-code (i.e. by expression). -- -- The n-tuple may have more components that dimension of the elemental -- set, in which case the extra components are ignored. */ static void null_func(MPL *mpl, void *info) { /* this is dummy routine used to enter the domain scope */ xassert(mpl == mpl); xassert(info == NULL); return; } int is_member(MPL *mpl, CODE *code, TUPLE *tuple) { int value; xassert(code != NULL); xassert(code->type == A_ELEMSET); xassert(code->dim > 0); xassert(tuple != NULL); switch (code->op) { case O_MEMSET: /* check if given n-tuple is member of elemental set, which is assigned to member of model set */ { ARG_LIST *e; TUPLE *temp; ELEMSET *set; /* evaluate reference to elemental set */ temp = create_tuple(mpl); for (e = code->arg.set.list; e != NULL; e = e->next) temp = expand_tuple(mpl, temp, eval_symbolic(mpl, e->x)); set = eval_member_set(mpl, code->arg.set.set, temp); delete_tuple(mpl, temp); /* check if the n-tuple is contained in the set array */ temp = build_subtuple(mpl, tuple, set->dim); value = (find_tuple(mpl, set, temp) != NULL); delete_tuple(mpl, temp); } break; case O_MAKE: /* check if given n-tuple is member of literal set */ { ARG_LIST *e; TUPLE *temp, *that; value = 0; temp = build_subtuple(mpl, tuple, code->dim); for (e = code->arg.list; e != NULL; e = e->next) { that = eval_tuple(mpl, e->x); value = (compare_tuples(mpl, temp, that) == 0); delete_tuple(mpl, that); if (value) break; } delete_tuple(mpl, temp); } break; case O_UNION: value = is_member(mpl, code->arg.arg.x, tuple) || is_member(mpl, code->arg.arg.y, tuple); break; case O_DIFF: value = is_member(mpl, code->arg.arg.x, tuple) && !is_member(mpl, code->arg.arg.y, tuple); break; case O_SYMDIFF: { int in1 = is_member(mpl, code->arg.arg.x, tuple); int in2 = is_member(mpl, code->arg.arg.y, tuple); value = (in1 && !in2) || (!in1 && in2); } break; case O_INTER: value = is_member(mpl, code->arg.arg.x, tuple) && is_member(mpl, code->arg.arg.y, tuple); break; case O_CROSS: { int j; value = is_member(mpl, code->arg.arg.x, tuple); if (value) { for (j = 1; j <= code->arg.arg.x->dim; j++) { xassert(tuple != NULL); tuple = tuple->next; } value = is_member(mpl, code->arg.arg.y, tuple); } } break; case O_DOTS: /* check if given 1-tuple is member of "arithmetic" set */ { int j; double x, t0, tf, dt; xassert(code->dim == 1); /* compute "parameters" of the "arithmetic" set */ t0 = eval_numeric(mpl, code->arg.arg.x); tf = eval_numeric(mpl, code->arg.arg.y); if (code->arg.arg.z == NULL) dt = 1.0; else dt = eval_numeric(mpl, code->arg.arg.z); /* make sure the parameters are correct */ arelset_size(mpl, t0, tf, dt); /* if component of 1-tuple is symbolic, not numeric, the 1-tuple cannot be member of "arithmetic" set */ xassert(tuple->sym != NULL); if (tuple->sym->str != NULL) { value = 0; break; } /* determine numeric value of the component */ x = tuple->sym->num; /* if the component value is out of the set range, the 1-tuple is not in the set */ if (dt > 0.0 && !(t0 <= x && x <= tf) || dt < 0.0 && !(tf <= x && x <= t0)) { value = 0; break; } /* estimate ordinal number of the 1-tuple in the set */ j = (int)(((x - t0) / dt) + 0.5) + 1; /* perform the main check */ value = (arelset_member(mpl, t0, tf, dt, j) == x); } break; case O_FORK: /* check if given n-tuple is member of conditional set */ if (eval_logical(mpl, code->arg.arg.x)) value = is_member(mpl, code->arg.arg.y, tuple); else value = is_member(mpl, code->arg.arg.z, tuple); break; case O_SETOF: /* check if given n-tuple is member of computed set */ /* it is not clear how to efficiently perform the check not computing the entire elemental set :+( */ error(mpl, "implementation restriction; in/within setof{} n" "ot allowed"); break; case O_BUILD: /* check if given n-tuple is member of domain set */ { TUPLE *temp; temp = build_subtuple(mpl, tuple, code->dim); /* try to enter the domain scope; if it is successful, the n-tuple is in the domain set */ value = (eval_within_domain(mpl, code->arg.loop.domain, temp, NULL, null_func) == 0); delete_tuple(mpl, temp); } break; default: xassert(code != code); } return value; } /*---------------------------------------------------------------------- -- eval_formula - evaluate pseudo-code to construct linear form. -- -- This routine evaluates specified pseudo-code to construct resultant -- linear form, which is returned on exit. */ struct iter_form_info { /* working info used by the routine iter_form_func */ CODE *code; /* pseudo-code for iterated operation to be performed */ FORMULA *value; /* resultant value */ FORMULA *tail; /* pointer to the last term */ }; static int iter_form_func(MPL *mpl, void *_info) { /* this is auxiliary routine used to perform iterated operation on linear form "integrand" within domain scope */ struct iter_form_info *info = _info; switch (info->code->op) { case O_SUM: /* summation over domain */ #if 0 info->value = linear_comb(mpl, +1.0, info->value, +1.0, eval_formula(mpl, info->code->arg.loop.x)); #else /* the routine linear_comb needs to look through all terms of both linear forms to reduce identical terms, so using it here is not a good idea (for example, evaluation of sum{i in 1..n} x[i] required quadratic time); the better idea is to gather all terms of the integrand in one list and reduce identical terms only once after all terms of the resultant linear form have been evaluated */ { FORMULA *form, *term; form = eval_formula(mpl, info->code->arg.loop.x); if (info->value == NULL) { xassert(info->tail == NULL); info->value = form; } else { xassert(info->tail != NULL); info->tail->next = form; } for (term = form; term != NULL; term = term->next) info->tail = term; } #endif break; default: xassert(info != info); } return 0; } FORMULA *eval_formula(MPL *mpl, CODE *code) { FORMULA *value; xassert(code != NULL); xassert(code->type == A_FORMULA); xassert(code->dim == 0); /* if the operation has a side effect, invalidate and delete the resultant value */ if (code->vflag && code->valid) { code->valid = 0; delete_value(mpl, code->type, &code->value); } /* if resultant value is valid, no evaluation is needed */ if (code->valid) { value = copy_formula(mpl, code->value.form); goto done; } /* evaluate pseudo-code recursively */ switch (code->op) { case O_MEMVAR: /* take member of variable */ { TUPLE *tuple; ARG_LIST *e; tuple = create_tuple(mpl); for (e = code->arg.var.list; e != NULL; e = e->next) tuple = expand_tuple(mpl, tuple, eval_symbolic(mpl, e->x)); #if 1 /* 15/V-2010 */ xassert(code->arg.var.suff == DOT_NONE); #endif value = single_variable(mpl, eval_member_var(mpl, code->arg.var.var, tuple)); delete_tuple(mpl, tuple); } break; case O_CVTLFM: /* convert to linear form */ value = constant_term(mpl, eval_numeric(mpl, code->arg.arg.x)); break; case O_PLUS: /* unary plus */ value = linear_comb(mpl, 0.0, constant_term(mpl, 0.0), +1.0, eval_formula(mpl, code->arg.arg.x)); break; case O_MINUS: /* unary minus */ value = linear_comb(mpl, 0.0, constant_term(mpl, 0.0), -1.0, eval_formula(mpl, code->arg.arg.x)); break; case O_ADD: /* addition */ value = linear_comb(mpl, +1.0, eval_formula(mpl, code->arg.arg.x), +1.0, eval_formula(mpl, code->arg.arg.y)); break; case O_SUB: /* subtraction */ value = linear_comb(mpl, +1.0, eval_formula(mpl, code->arg.arg.x), -1.0, eval_formula(mpl, code->arg.arg.y)); break; case O_MUL: /* multiplication */ xassert(code->arg.arg.x != NULL); xassert(code->arg.arg.y != NULL); if (code->arg.arg.x->type == A_NUMERIC) { xassert(code->arg.arg.y->type == A_FORMULA); value = linear_comb(mpl, eval_numeric(mpl, code->arg.arg.x), eval_formula(mpl, code->arg.arg.y), 0.0, constant_term(mpl, 0.0)); } else { xassert(code->arg.arg.x->type == A_FORMULA); xassert(code->arg.arg.y->type == A_NUMERIC); value = linear_comb(mpl, eval_numeric(mpl, code->arg.arg.y), eval_formula(mpl, code->arg.arg.x), 0.0, constant_term(mpl, 0.0)); } break; case O_DIV: /* division */ value = linear_comb(mpl, fp_div(mpl, 1.0, eval_numeric(mpl, code->arg.arg.y)), eval_formula(mpl, code->arg.arg.x), 0.0, constant_term(mpl, 0.0)); break; case O_FORK: /* if-then-else */ if (eval_logical(mpl, code->arg.arg.x)) value = eval_formula(mpl, code->arg.arg.y); else if (code->arg.arg.z == NULL) value = constant_term(mpl, 0.0); else value = eval_formula(mpl, code->arg.arg.z); break; case O_SUM: /* summation over domain */ { struct iter_form_info _info, *info = &_info; info->code = code; info->value = constant_term(mpl, 0.0); info->tail = NULL; loop_within_domain(mpl, code->arg.loop.domain, info, iter_form_func); value = reduce_terms(mpl, info->value); } break; default: xassert(code != code); } /* save resultant value */ xassert(!code->valid); code->valid = 1; code->value.form = copy_formula(mpl, value); done: return value; } /*---------------------------------------------------------------------- -- clean_code - clean pseudo-code. -- -- This routine recursively cleans specified pseudo-code that assumes -- deleting all temporary resultant values. */ void clean_code(MPL *mpl, CODE *code) { ARG_LIST *e; /* if no pseudo-code is specified, do nothing */ if (code == NULL) goto done; /* if resultant value is valid (exists), delete it */ if (code->valid) { code->valid = 0; delete_value(mpl, code->type, &code->value); } /* recursively clean pseudo-code for operands */ switch (code->op) { case O_NUMBER: case O_STRING: case O_INDEX: break; case O_MEMNUM: case O_MEMSYM: for (e = code->arg.par.list; e != NULL; e = e->next) clean_code(mpl, e->x); break; case O_MEMSET: for (e = code->arg.set.list; e != NULL; e = e->next) clean_code(mpl, e->x); break; case O_MEMVAR: for (e = code->arg.var.list; e != NULL; e = e->next) clean_code(mpl, e->x); break; #if 1 /* 15/V-2010 */ case O_MEMCON: for (e = code->arg.con.list; e != NULL; e = e->next) clean_code(mpl, e->x); break; #endif case O_TUPLE: case O_MAKE: for (e = code->arg.list; e != NULL; e = e->next) clean_code(mpl, e->x); break; case O_SLICE: xassert(code != code); case O_IRAND224: case O_UNIFORM01: case O_NORMAL01: case O_GMTIME: break; case O_CVTNUM: case O_CVTSYM: case O_CVTLOG: case O_CVTTUP: case O_CVTLFM: case O_PLUS: case O_MINUS: case O_NOT: case O_ABS: case O_CEIL: case O_FLOOR: case O_EXP: case O_LOG: case O_LOG10: case O_SQRT: case O_SIN: case O_COS: case O_ATAN: case O_ROUND: case O_TRUNC: case O_CARD: case O_LENGTH: /* unary operation */ clean_code(mpl, code->arg.arg.x); break; case O_ADD: case O_SUB: case O_LESS: case O_MUL: case O_DIV: case O_IDIV: case O_MOD: case O_POWER: case O_ATAN2: case O_ROUND2: case O_TRUNC2: case O_UNIFORM: case O_NORMAL: case O_CONCAT: case O_LT: case O_LE: case O_EQ: case O_GE: case O_GT: case O_NE: case O_AND: case O_OR: case O_UNION: case O_DIFF: case O_SYMDIFF: case O_INTER: case O_CROSS: case O_IN: case O_NOTIN: case O_WITHIN: case O_NOTWITHIN: case O_SUBSTR: case O_STR2TIME: case O_TIME2STR: /* binary operation */ clean_code(mpl, code->arg.arg.x); clean_code(mpl, code->arg.arg.y); break; case O_DOTS: case O_FORK: case O_SUBSTR3: /* ternary operation */ clean_code(mpl, code->arg.arg.x); clean_code(mpl, code->arg.arg.y); clean_code(mpl, code->arg.arg.z); break; case O_MIN: case O_MAX: /* n-ary operation */ for (e = code->arg.list; e != NULL; e = e->next) clean_code(mpl, e->x); break; case O_SUM: case O_PROD: case O_MINIMUM: case O_MAXIMUM: case O_FORALL: case O_EXISTS: case O_SETOF: case O_BUILD: /* iterated operation */ clean_domain(mpl, code->arg.loop.domain); clean_code(mpl, code->arg.loop.x); break; default: xassert(code->op != code->op); } done: return; } #if 1 /* 11/II-2008 */ /**********************************************************************/ /* * * DATA TABLES * * */ /**********************************************************************/ int mpl_tab_num_args(TABDCA *dca) { /* returns the number of arguments */ return dca->na; } const char *mpl_tab_get_arg(TABDCA *dca, int k) { /* returns pointer to k-th argument */ xassert(1 <= k && k <= dca->na); return dca->arg[k]; } int mpl_tab_num_flds(TABDCA *dca) { /* returns the number of fields */ return dca->nf; } const char *mpl_tab_get_name(TABDCA *dca, int k) { /* returns pointer to name of k-th field */ xassert(1 <= k && k <= dca->nf); return dca->name[k]; } int mpl_tab_get_type(TABDCA *dca, int k) { /* returns type of k-th field */ xassert(1 <= k && k <= dca->nf); return dca->type[k]; } double mpl_tab_get_num(TABDCA *dca, int k) { /* returns numeric value of k-th field */ xassert(1 <= k && k <= dca->nf); xassert(dca->type[k] == 'N'); return dca->num[k]; } const char *mpl_tab_get_str(TABDCA *dca, int k) { /* returns pointer to string value of k-th field */ xassert(1 <= k && k <= dca->nf); xassert(dca->type[k] == 'S'); xassert(dca->str[k] != NULL); return dca->str[k]; } void mpl_tab_set_num(TABDCA *dca, int k, double num) { /* assign numeric value to k-th field */ xassert(1 <= k && k <= dca->nf); xassert(dca->type[k] == '?'); dca->type[k] = 'N'; dca->num[k] = num; return; } void mpl_tab_set_str(TABDCA *dca, int k, const char *str) { /* assign string value to k-th field */ xassert(1 <= k && k <= dca->nf); xassert(dca->type[k] == '?'); xassert(strlen(str) <= MAX_LENGTH); xassert(dca->str[k] != NULL); dca->type[k] = 'S'; strcpy(dca->str[k], str); return; } static int write_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ TABLE *tab = info; TABDCA *dca = mpl->dca; TABOUT *out; SYMBOL *sym; int k; char buf[MAX_LENGTH+1]; /* evaluate field values */ k = 0; for (out = tab->u.out.list; out != NULL; out = out->next) { k++; switch (out->code->type) { case A_NUMERIC: dca->type[k] = 'N'; dca->num[k] = eval_numeric(mpl, out->code); dca->str[k][0] = '\0'; break; case A_SYMBOLIC: sym = eval_symbolic(mpl, out->code); if (sym->str == NULL) { dca->type[k] = 'N'; dca->num[k] = sym->num; dca->str[k][0] = '\0'; } else { dca->type[k] = 'S'; dca->num[k] = 0.0; fetch_string(mpl, sym->str, buf); strcpy(dca->str[k], buf); } delete_symbol(mpl, sym); break; default: xassert(out != out); } } /* write record to output table */ mpl_tab_drv_write(mpl); return 0; } void execute_table(MPL *mpl, TABLE *tab) { /* execute table statement */ TABARG *arg; TABFLD *fld; TABIN *in; TABOUT *out; TABDCA *dca; SET *set; int k; char buf[MAX_LENGTH+1]; /* allocate table driver communication area */ xassert(mpl->dca == NULL); mpl->dca = dca = xmalloc(sizeof(TABDCA)); dca->id = 0; dca->link = NULL; dca->na = 0; dca->arg = NULL; dca->nf = 0; dca->name = NULL; dca->type = NULL; dca->num = NULL; dca->str = NULL; /* allocate arguments */ xassert(dca->na == 0); for (arg = tab->arg; arg != NULL; arg = arg->next) dca->na++; dca->arg = xcalloc(1+dca->na, sizeof(char *)); #if 1 /* 28/IX-2008 */ for (k = 1; k <= dca->na; k++) dca->arg[k] = NULL; #endif /* evaluate argument values */ k = 0; for (arg = tab->arg; arg != NULL; arg = arg->next) { SYMBOL *sym; k++; xassert(arg->code->type == A_SYMBOLIC); sym = eval_symbolic(mpl, arg->code); if (sym->str == NULL) sprintf(buf, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, buf); delete_symbol(mpl, sym); dca->arg[k] = xmalloc(strlen(buf)+1); strcpy(dca->arg[k], buf); } /* perform table input/output */ switch (tab->type) { case A_INPUT: goto read_table; case A_OUTPUT: goto write_table; default: xassert(tab != tab); } read_table: /* read data from input table */ /* add the only member to the control set and assign it empty elemental set */ set = tab->u.in.set; if (set != NULL) { if (set->data) error(mpl, "%s already provided with data", set->name); xassert(set->array->head == NULL); add_member(mpl, set->array, NULL)->value.set = create_elemset(mpl, set->dimen); set->data = 1; } /* check parameters specified in the input list */ for (in = tab->u.in.list; in != NULL; in = in->next) { if (in->par->data) error(mpl, "%s already provided with data", in->par->name); in->par->data = 1; } /* allocate and initialize fields */ xassert(dca->nf == 0); for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) dca->nf++; for (in = tab->u.in.list; in != NULL; in = in->next) dca->nf++; dca->name = xcalloc(1+dca->nf, sizeof(char *)); dca->type = xcalloc(1+dca->nf, sizeof(int)); dca->num = xcalloc(1+dca->nf, sizeof(double)); dca->str = xcalloc(1+dca->nf, sizeof(char *)); k = 0; for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) { k++; dca->name[k] = fld->name; dca->type[k] = '?'; dca->num[k] = 0.0; dca->str[k] = xmalloc(MAX_LENGTH+1); dca->str[k][0] = '\0'; } for (in = tab->u.in.list; in != NULL; in = in->next) { k++; dca->name[k] = in->name; dca->type[k] = '?'; dca->num[k] = 0.0; dca->str[k] = xmalloc(MAX_LENGTH+1); dca->str[k][0] = '\0'; } /* open input table */ mpl_tab_drv_open(mpl, 'R'); /* read and process records */ for (;;) { TUPLE *tup; /* reset field types */ for (k = 1; k <= dca->nf; k++) dca->type[k] = '?'; /* read next record */ if (mpl_tab_drv_read(mpl)) break; /* all fields must be set by the driver */ for (k = 1; k <= dca->nf; k++) { if (dca->type[k] == '?') error(mpl, "field %s missing in input table", dca->name[k]); } /* construct n-tuple */ tup = create_tuple(mpl); k = 0; for (fld = tab->u.in.fld; fld != NULL; fld = fld->next) { k++; xassert(k <= dca->nf); switch (dca->type[k]) { case 'N': tup = expand_tuple(mpl, tup, create_symbol_num(mpl, dca->num[k])); break; case 'S': xassert(strlen(dca->str[k]) <= MAX_LENGTH); tup = expand_tuple(mpl, tup, create_symbol_str(mpl, create_string(mpl, dca->str[k]))); break; default: xassert(dca != dca); } } /* add n-tuple just read to the control set */ if (tab->u.in.set != NULL) check_then_add(mpl, tab->u.in.set->array->head->value.set, copy_tuple(mpl, tup)); /* assign values to the parameters in the input list */ for (in = tab->u.in.list; in != NULL; in = in->next) { MEMBER *memb; k++; xassert(k <= dca->nf); /* there must be no member with the same n-tuple */ if (find_member(mpl, in->par->array, tup) != NULL) error(mpl, "%s%s already defined", in->par->name, format_tuple(mpl, '[', tup)); /* create new parameter member with given n-tuple */ memb = add_member(mpl, in->par->array, copy_tuple(mpl, tup)) ; /* assign value to the parameter member */ switch (in->par->type) { case A_NUMERIC: case A_INTEGER: case A_BINARY: if (dca->type[k] != 'N') error(mpl, "%s requires numeric data", in->par->name); memb->value.num = dca->num[k]; break; case A_SYMBOLIC: switch (dca->type[k]) { case 'N': memb->value.sym = create_symbol_num(mpl, dca->num[k]); break; case 'S': xassert(strlen(dca->str[k]) <= MAX_LENGTH); memb->value.sym = create_symbol_str(mpl, create_string(mpl,dca->str[k])); break; default: xassert(dca != dca); } break; default: xassert(in != in); } } /* n-tuple is no more needed */ delete_tuple(mpl, tup); } /* close input table */ mpl_tab_drv_close(mpl); goto done; write_table: /* write data to output table */ /* allocate and initialize fields */ xassert(dca->nf == 0); for (out = tab->u.out.list; out != NULL; out = out->next) dca->nf++; dca->name = xcalloc(1+dca->nf, sizeof(char *)); dca->type = xcalloc(1+dca->nf, sizeof(int)); dca->num = xcalloc(1+dca->nf, sizeof(double)); dca->str = xcalloc(1+dca->nf, sizeof(char *)); k = 0; for (out = tab->u.out.list; out != NULL; out = out->next) { k++; dca->name[k] = out->name; dca->type[k] = '?'; dca->num[k] = 0.0; dca->str[k] = xmalloc(MAX_LENGTH+1); dca->str[k][0] = '\0'; } /* open output table */ mpl_tab_drv_open(mpl, 'W'); /* evaluate fields and write records */ loop_within_domain(mpl, tab->u.out.domain, tab, write_func); /* close output table */ mpl_tab_drv_close(mpl); done: /* free table driver communication area */ free_dca(mpl); return; } void free_dca(MPL *mpl) { /* free table driver communucation area */ TABDCA *dca = mpl->dca; int k; if (dca != NULL) { if (dca->link != NULL) mpl_tab_drv_close(mpl); if (dca->arg != NULL) { for (k = 1; k <= dca->na; k++) #if 1 /* 28/IX-2008 */ if (dca->arg[k] != NULL) #endif xfree(dca->arg[k]); xfree(dca->arg); } if (dca->name != NULL) xfree(dca->name); if (dca->type != NULL) xfree(dca->type); if (dca->num != NULL) xfree(dca->num); if (dca->str != NULL) { for (k = 1; k <= dca->nf; k++) xfree(dca->str[k]); xfree(dca->str); } xfree(dca), mpl->dca = NULL; } return; } void clean_table(MPL *mpl, TABLE *tab) { /* clean table statement */ TABARG *arg; TABOUT *out; /* clean string list */ for (arg = tab->arg; arg != NULL; arg = arg->next) clean_code(mpl, arg->code); switch (tab->type) { case A_INPUT: break; case A_OUTPUT: /* clean subscript domain */ clean_domain(mpl, tab->u.out.domain); /* clean output list */ for (out = tab->u.out.list; out != NULL; out = out->next) clean_code(mpl, out->code); break; default: xassert(tab != tab); } return; } #endif /**********************************************************************/ /* * * MODEL STATEMENTS * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- execute_check - execute check statement. -- -- This routine executes specified check statement. */ static int check_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ CHECK *chk = (CHECK *)info; if (!eval_logical(mpl, chk->code)) error(mpl, "check%s failed", format_tuple(mpl, '[', get_domain_tuple(mpl, chk->domain))); return 0; } void execute_check(MPL *mpl, CHECK *chk) { loop_within_domain(mpl, chk->domain, chk, check_func); return; } /*---------------------------------------------------------------------- -- clean_check - clean check statement. -- -- This routine cleans specified check statement that assumes deleting -- all stuff dynamically allocated on generating/postsolving phase. */ void clean_check(MPL *mpl, CHECK *chk) { /* clean subscript domain */ clean_domain(mpl, chk->domain); /* clean pseudo-code for computing predicate */ clean_code(mpl, chk->code); return; } /*---------------------------------------------------------------------- -- execute_display - execute display statement. -- -- This routine executes specified display statement. */ static void display_set(MPL *mpl, SET *set, MEMBER *memb) { /* display member of model set */ ELEMSET *s = memb->value.set; MEMBER *m; write_text(mpl, "%s%s%s\n", set->name, format_tuple(mpl, '[', memb->tuple), s->head == NULL ? " is empty" : ":"); for (m = s->head; m != NULL; m = m->next) write_text(mpl, " %s\n", format_tuple(mpl, '(', m->tuple)); return; } static void display_par(MPL *mpl, PARAMETER *par, MEMBER *memb) { /* display member of model parameter */ switch (par->type) { case A_NUMERIC: case A_INTEGER: case A_BINARY: write_text(mpl, "%s%s = %.*g\n", par->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.num); break; case A_SYMBOLIC: write_text(mpl, "%s%s = %s\n", par->name, format_tuple(mpl, '[', memb->tuple), format_symbol(mpl, memb->value.sym)); break; default: xassert(par != par); } return; } #if 1 /* 15/V-2010 */ static void display_var(MPL *mpl, VARIABLE *var, MEMBER *memb, int suff) { /* display member of model variable */ if (suff == DOT_NONE || suff == DOT_VAL) write_text(mpl, "%s%s.val = %.*g\n", var->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.var->prim); else if (suff == DOT_LB) write_text(mpl, "%s%s.lb = %.*g\n", var->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.var->var->lbnd == NULL ? -DBL_MAX : memb->value.var->lbnd); else if (suff == DOT_UB) write_text(mpl, "%s%s.ub = %.*g\n", var->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.var->var->ubnd == NULL ? +DBL_MAX : memb->value.var->ubnd); else if (suff == DOT_STATUS) write_text(mpl, "%s%s.status = %d\n", var->name, format_tuple (mpl, '[', memb->tuple), memb->value.var->stat); else if (suff == DOT_DUAL) write_text(mpl, "%s%s.dual = %.*g\n", var->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.var->dual); else xassert(suff != suff); return; } #endif #if 1 /* 15/V-2010 */ static void display_con(MPL *mpl, CONSTRAINT *con, MEMBER *memb, int suff) { /* display member of model constraint */ if (suff == DOT_NONE || suff == DOT_VAL) write_text(mpl, "%s%s.val = %.*g\n", con->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.con->prim); else if (suff == DOT_LB) write_text(mpl, "%s%s.lb = %.*g\n", con->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.con->con->lbnd == NULL ? -DBL_MAX : memb->value.con->lbnd); else if (suff == DOT_UB) write_text(mpl, "%s%s.ub = %.*g\n", con->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.con->con->ubnd == NULL ? +DBL_MAX : memb->value.con->ubnd); else if (suff == DOT_STATUS) write_text(mpl, "%s%s.status = %d\n", con->name, format_tuple (mpl, '[', memb->tuple), memb->value.con->stat); else if (suff == DOT_DUAL) write_text(mpl, "%s%s.dual = %.*g\n", con->name, format_tuple(mpl, '[', memb->tuple), DBL_DIG, memb->value.con->dual); else xassert(suff != suff); return; } #endif static void display_memb(MPL *mpl, CODE *code) { /* display member specified by pseudo-code */ MEMBER memb; ARG_LIST *e; xassert(code->op == O_MEMNUM || code->op == O_MEMSYM || code->op == O_MEMSET || code->op == O_MEMVAR || code->op == O_MEMCON); memb.tuple = create_tuple(mpl); for (e = code->arg.par.list; e != NULL; e = e->next) memb.tuple = expand_tuple(mpl, memb.tuple, eval_symbolic(mpl, e->x)); switch (code->op) { case O_MEMNUM: memb.value.num = eval_member_num(mpl, code->arg.par.par, memb.tuple); display_par(mpl, code->arg.par.par, &memb); break; case O_MEMSYM: memb.value.sym = eval_member_sym(mpl, code->arg.par.par, memb.tuple); display_par(mpl, code->arg.par.par, &memb); delete_symbol(mpl, memb.value.sym); break; case O_MEMSET: memb.value.set = eval_member_set(mpl, code->arg.set.set, memb.tuple); display_set(mpl, code->arg.set.set, &memb); break; case O_MEMVAR: memb.value.var = eval_member_var(mpl, code->arg.var.var, memb.tuple); display_var (mpl, code->arg.var.var, &memb, code->arg.var.suff); break; case O_MEMCON: memb.value.con = eval_member_con(mpl, code->arg.con.con, memb.tuple); display_con (mpl, code->arg.con.con, &memb, code->arg.con.suff); break; default: xassert(code != code); } delete_tuple(mpl, memb.tuple); return; } static void display_code(MPL *mpl, CODE *code) { /* display value of expression */ switch (code->type) { case A_NUMERIC: /* numeric value */ { double num; num = eval_numeric(mpl, code); write_text(mpl, "%.*g\n", DBL_DIG, num); } break; case A_SYMBOLIC: /* symbolic value */ { SYMBOL *sym; sym = eval_symbolic(mpl, code); write_text(mpl, "%s\n", format_symbol(mpl, sym)); delete_symbol(mpl, sym); } break; case A_LOGICAL: /* logical value */ { int bit; bit = eval_logical(mpl, code); write_text(mpl, "%s\n", bit ? "true" : "false"); } break; case A_TUPLE: /* n-tuple */ { TUPLE *tuple; tuple = eval_tuple(mpl, code); write_text(mpl, "%s\n", format_tuple(mpl, '(', tuple)); delete_tuple(mpl, tuple); } break; case A_ELEMSET: /* elemental set */ { ELEMSET *set; MEMBER *memb; set = eval_elemset(mpl, code); if (set->head == 0) write_text(mpl, "set is empty\n"); for (memb = set->head; memb != NULL; memb = memb->next) write_text(mpl, " %s\n", format_tuple(mpl, '(', memb->tuple)); delete_elemset(mpl, set); } break; case A_FORMULA: /* linear form */ { FORMULA *form, *term; form = eval_formula(mpl, code); if (form == NULL) write_text(mpl, "linear form is empty\n"); for (term = form; term != NULL; term = term->next) { if (term->var == NULL) write_text(mpl, " %.*g\n", term->coef); else write_text(mpl, " %.*g %s%s\n", DBL_DIG, term->coef, term->var->var->name, format_tuple(mpl, '[', term->var->memb->tuple)); } delete_formula(mpl, form); } break; default: xassert(code != code); } return; } static int display_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ DISPLAY *dpy = (DISPLAY *)info; DISPLAY1 *entry; for (entry = dpy->list; entry != NULL; entry = entry->next) { if (entry->type == A_INDEX) { /* dummy index */ DOMAIN_SLOT *slot = entry->u.slot; write_text(mpl, "%s = %s\n", slot->name, format_symbol(mpl, slot->value)); } else if (entry->type == A_SET) { /* model set */ SET *set = entry->u.set; MEMBER *memb; if (set->assign != NULL) { /* the set has assignment expression; evaluate all its members over entire domain */ eval_whole_set(mpl, set); } else { /* the set has no assignment expression; refer to its any existing member ignoring resultant value to check the data provided the data section */ #if 1 /* 12/XII-2008 */ if (set->gadget != NULL && set->data == 0) { /* initialize the set with data from a plain set */ saturate_set(mpl, set); } #endif if (set->array->head != NULL) eval_member_set(mpl, set, set->array->head->tuple); } /* display all members of the set array */ if (set->array->head == NULL) write_text(mpl, "%s has empty content\n", set->name); for (memb = set->array->head; memb != NULL; memb = memb->next) display_set(mpl, set, memb); } else if (entry->type == A_PARAMETER) { /* model parameter */ PARAMETER *par = entry->u.par; MEMBER *memb; if (par->assign != NULL) { /* the parameter has an assignment expression; evaluate all its member over entire domain */ eval_whole_par(mpl, par); } else { /* the parameter has no assignment expression; refer to its any existing member ignoring resultant value to check the data provided in the data section */ if (par->array->head != NULL) { if (par->type != A_SYMBOLIC) eval_member_num(mpl, par, par->array->head->tuple); else delete_symbol(mpl, eval_member_sym(mpl, par, par->array->head->tuple)); } } /* display all members of the parameter array */ if (par->array->head == NULL) write_text(mpl, "%s has empty content\n", par->name); for (memb = par->array->head; memb != NULL; memb = memb->next) display_par(mpl, par, memb); } else if (entry->type == A_VARIABLE) { /* model variable */ VARIABLE *var = entry->u.var; MEMBER *memb; xassert(mpl->flag_p); /* display all members of the variable array */ if (var->array->head == NULL) write_text(mpl, "%s has empty content\n", var->name); for (memb = var->array->head; memb != NULL; memb = memb->next) display_var(mpl, var, memb, DOT_NONE); } else if (entry->type == A_CONSTRAINT) { /* model constraint */ CONSTRAINT *con = entry->u.con; MEMBER *memb; xassert(mpl->flag_p); /* display all members of the constraint array */ if (con->array->head == NULL) write_text(mpl, "%s has empty content\n", con->name); for (memb = con->array->head; memb != NULL; memb = memb->next) display_con(mpl, con, memb, DOT_NONE); } else if (entry->type == A_EXPRESSION) { /* expression */ CODE *code = entry->u.code; if (code->op == O_MEMNUM || code->op == O_MEMSYM || code->op == O_MEMSET || code->op == O_MEMVAR || code->op == O_MEMCON) display_memb(mpl, code); else display_code(mpl, code); } else xassert(entry != entry); } return 0; } void execute_display(MPL *mpl, DISPLAY *dpy) { loop_within_domain(mpl, dpy->domain, dpy, display_func); return; } /*---------------------------------------------------------------------- -- clean_display - clean display statement. -- -- This routine cleans specified display statement that assumes deleting -- all stuff dynamically allocated on generating/postsolving phase. */ void clean_display(MPL *mpl, DISPLAY *dpy) { DISPLAY1 *d; #if 0 /* 15/V-2010 */ ARG_LIST *e; #endif /* clean subscript domain */ clean_domain(mpl, dpy->domain); /* clean display list */ for (d = dpy->list; d != NULL; d = d->next) { /* clean pseudo-code for computing expression */ if (d->type == A_EXPRESSION) clean_code(mpl, d->u.code); #if 0 /* 15/V-2010 */ /* clean pseudo-code for computing subscripts */ for (e = d->list; e != NULL; e = e->next) clean_code(mpl, e->x); #endif } return; } /*---------------------------------------------------------------------- -- execute_printf - execute printf statement. -- -- This routine executes specified printf statement. */ #if 1 /* 14/VII-2006 */ static void print_char(MPL *mpl, int c) { if (mpl->prt_fp == NULL) write_char(mpl, c); else xfputc(c, mpl->prt_fp); return; } static void print_text(MPL *mpl, char *fmt, ...) { va_list arg; char buf[OUTBUF_SIZE], *c; va_start(arg, fmt); vsprintf(buf, fmt, arg); xassert(strlen(buf) < sizeof(buf)); va_end(arg); for (c = buf; *c != '\0'; c++) print_char(mpl, *c); return; } #endif static int printf_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ PRINTF *prt = (PRINTF *)info; PRINTF1 *entry; SYMBOL *sym; char fmt[MAX_LENGTH+1], *c, *from, save; /* evaluate format control string */ sym = eval_symbolic(mpl, prt->fmt); if (sym->str == NULL) sprintf(fmt, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, fmt); delete_symbol(mpl, sym); /* scan format control string and perform formatting output */ entry = prt->list; for (c = fmt; *c != '\0'; c++) { if (*c == '%') { /* scan format specifier */ from = c++; if (*c == '%') { print_char(mpl, '%'); continue; } if (entry == NULL) break; /* scan optional flags */ while (*c == '-' || *c == '+' || *c == ' ' || *c == '#' || *c == '0') c++; /* scan optional minimum field width */ while (isdigit((unsigned char)*c)) c++; /* scan optional precision */ if (*c == '.') { c++; while (isdigit((unsigned char)*c)) c++; } /* scan conversion specifier and perform formatting */ save = *(c+1), *(c+1) = '\0'; if (*c == 'd' || *c == 'i' || *c == 'e' || *c == 'E' || *c == 'f' || *c == 'F' || *c == 'g' || *c == 'G') { /* the specifier requires numeric value */ double value; xassert(entry != NULL); switch (entry->code->type) { case A_NUMERIC: value = eval_numeric(mpl, entry->code); break; case A_SYMBOLIC: sym = eval_symbolic(mpl, entry->code); if (sym->str != NULL) error(mpl, "cannot convert %s to floating-point" " number", format_symbol(mpl, sym)); value = sym->num; delete_symbol(mpl, sym); break; case A_LOGICAL: if (eval_logical(mpl, entry->code)) value = 1.0; else value = 0.0; break; default: xassert(entry != entry); } if (*c == 'd' || *c == 'i') { double int_max = (double)INT_MAX; if (!(-int_max <= value && value <= +int_max)) error(mpl, "cannot convert %.*g to integer", DBL_DIG, value); print_text(mpl, from, (int)floor(value + 0.5)); } else print_text(mpl, from, value); } else if (*c == 's') { /* the specifier requires symbolic value */ char value[MAX_LENGTH+1]; switch (entry->code->type) { case A_NUMERIC: sprintf(value, "%.*g", DBL_DIG, eval_numeric(mpl, entry->code)); break; case A_LOGICAL: if (eval_logical(mpl, entry->code)) strcpy(value, "T"); else strcpy(value, "F"); break; case A_SYMBOLIC: sym = eval_symbolic(mpl, entry->code); if (sym->str == NULL) sprintf(value, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, value); delete_symbol(mpl, sym); break; default: xassert(entry != entry); } print_text(mpl, from, value); } else error(mpl, "format specifier missing or invalid"); *(c+1) = save; entry = entry->next; } else if (*c == '\\') { /* write some control character */ c++; if (*c == 't') print_char(mpl, '\t'); else if (*c == 'n') print_char(mpl, '\n'); #if 1 /* 28/X-2010 */ else if (*c == '\0') { /* format string ends with backslash */ error(mpl, "invalid use of escape character \\ in format" " control string"); } #endif else print_char(mpl, *c); } else { /* write character without formatting */ print_char(mpl, *c); } } return 0; } #if 0 /* 14/VII-2006 */ void execute_printf(MPL *mpl, PRINTF *prt) { loop_within_domain(mpl, prt->domain, prt, printf_func); return; } #else void execute_printf(MPL *mpl, PRINTF *prt) { if (prt->fname == NULL) { /* switch to the standard output */ if (mpl->prt_fp != NULL) { xfclose(mpl->prt_fp), mpl->prt_fp = NULL; xfree(mpl->prt_file), mpl->prt_file = NULL; } } else { /* evaluate file name string */ SYMBOL *sym; char fname[MAX_LENGTH+1]; sym = eval_symbolic(mpl, prt->fname); if (sym->str == NULL) sprintf(fname, "%.*g", DBL_DIG, sym->num); else fetch_string(mpl, sym->str, fname); delete_symbol(mpl, sym); /* close the current print file, if necessary */ if (mpl->prt_fp != NULL && (!prt->app || strcmp(mpl->prt_file, fname) != 0)) { xfclose(mpl->prt_fp), mpl->prt_fp = NULL; xfree(mpl->prt_file), mpl->prt_file = NULL; } /* open the specified print file, if necessary */ if (mpl->prt_fp == NULL) { mpl->prt_fp = xfopen(fname, prt->app ? "a" : "w"); if (mpl->prt_fp == NULL) error(mpl, "unable to open `%s' for writing - %s", fname, xerrmsg()); mpl->prt_file = xmalloc(strlen(fname)+1); strcpy(mpl->prt_file, fname); } } loop_within_domain(mpl, prt->domain, prt, printf_func); if (mpl->prt_fp != NULL) { xfflush(mpl->prt_fp); if (xferror(mpl->prt_fp)) error(mpl, "writing error to `%s' - %s", mpl->prt_file, xerrmsg()); } return; } #endif /*---------------------------------------------------------------------- -- clean_printf - clean printf statement. -- -- This routine cleans specified printf statement that assumes deleting -- all stuff dynamically allocated on generating/postsolving phase. */ void clean_printf(MPL *mpl, PRINTF *prt) { PRINTF1 *p; /* clean subscript domain */ clean_domain(mpl, prt->domain); /* clean pseudo-code for computing format string */ clean_code(mpl, prt->fmt); /* clean printf list */ for (p = prt->list; p != NULL; p = p->next) { /* clean pseudo-code for computing value to be printed */ clean_code(mpl, p->code); } #if 1 /* 14/VII-2006 */ /* clean pseudo-code for computing file name string */ clean_code(mpl, prt->fname); #endif return; } /*---------------------------------------------------------------------- -- execute_for - execute for statement. -- -- This routine executes specified for statement. */ static int for_func(MPL *mpl, void *info) { /* this is auxiliary routine to work within domain scope */ FOR *fur = (FOR *)info; STATEMENT *stmt, *save; save = mpl->stmt; for (stmt = fur->list; stmt != NULL; stmt = stmt->next) execute_statement(mpl, stmt); mpl->stmt = save; return 0; } void execute_for(MPL *mpl, FOR *fur) { loop_within_domain(mpl, fur->domain, fur, for_func); return; } /*---------------------------------------------------------------------- -- clean_for - clean for statement. -- -- This routine cleans specified for statement that assumes deleting all -- stuff dynamically allocated on generating/postsolving phase. */ void clean_for(MPL *mpl, FOR *fur) { STATEMENT *stmt; /* clean subscript domain */ clean_domain(mpl, fur->domain); /* clean all sub-statements */ for (stmt = fur->list; stmt != NULL; stmt = stmt->next) clean_statement(mpl, stmt); return; } /*---------------------------------------------------------------------- -- execute_statement - execute specified model statement. -- -- This routine executes specified model statement. */ void execute_statement(MPL *mpl, STATEMENT *stmt) { mpl->stmt = stmt; switch (stmt->type) { case A_SET: case A_PARAMETER: case A_VARIABLE: break; case A_CONSTRAINT: xprintf("Generating %s...\n", stmt->u.con->name); eval_whole_con(mpl, stmt->u.con); break; case A_TABLE: switch (stmt->u.tab->type) { case A_INPUT: xprintf("Reading %s...\n", stmt->u.tab->name); break; case A_OUTPUT: xprintf("Writing %s...\n", stmt->u.tab->name); break; default: xassert(stmt != stmt); } execute_table(mpl, stmt->u.tab); break; case A_SOLVE: break; case A_CHECK: xprintf("Checking (line %d)...\n", stmt->line); execute_check(mpl, stmt->u.chk); break; case A_DISPLAY: write_text(mpl, "Display statement at line %d\n", stmt->line); execute_display(mpl, stmt->u.dpy); break; case A_PRINTF: execute_printf(mpl, stmt->u.prt); break; case A_FOR: execute_for(mpl, stmt->u.fur); break; default: xassert(stmt != stmt); } return; } /*---------------------------------------------------------------------- -- clean_statement - clean specified model statement. -- -- This routine cleans specified model statement that assumes deleting -- all stuff dynamically allocated on generating/postsolving phase. */ void clean_statement(MPL *mpl, STATEMENT *stmt) { switch(stmt->type) { case A_SET: clean_set(mpl, stmt->u.set); break; case A_PARAMETER: clean_parameter(mpl, stmt->u.par); break; case A_VARIABLE: clean_variable(mpl, stmt->u.var); break; case A_CONSTRAINT: clean_constraint(mpl, stmt->u.con); break; #if 1 /* 11/II-2008 */ case A_TABLE: clean_table(mpl, stmt->u.tab); break; #endif case A_SOLVE: break; case A_CHECK: clean_check(mpl, stmt->u.chk); break; case A_DISPLAY: clean_display(mpl, stmt->u.dpy); break; case A_PRINTF: clean_printf(mpl, stmt->u.prt); break; case A_FOR: clean_for(mpl, stmt->u.fur); break; default: xassert(stmt != stmt); } return; } /* eof */ glpk-4.52.1/src/glpmpl04.c0000644000062000006210000013407512175147600014325 0ustar maomkpasswd/* glpmpl04.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_ERRNO #define _GLPSTD_STDIO #include "glpmpl.h" #define xfault xerror #define dmp_create_poolx(size) dmp_create_pool() /**********************************************************************/ /* * * GENERATING AND POSTSOLVING MODEL * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- alloc_content - allocate content arrays for all model objects. -- -- This routine allocates content arrays for all existing model objects -- and thereby finalizes creating model. -- -- This routine must be called immediately after reading model section, -- i.e. before reading data section or generating model. */ void alloc_content(MPL *mpl) { STATEMENT *stmt; /* walk through all model statements */ for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) { switch (stmt->type) { case A_SET: /* model set */ xassert(stmt->u.set->array == NULL); stmt->u.set->array = create_array(mpl, A_ELEMSET, stmt->u.set->dim); break; case A_PARAMETER: /* model parameter */ xassert(stmt->u.par->array == NULL); switch (stmt->u.par->type) { case A_NUMERIC: case A_INTEGER: case A_BINARY: stmt->u.par->array = create_array(mpl, A_NUMERIC, stmt->u.par->dim); break; case A_SYMBOLIC: stmt->u.par->array = create_array(mpl, A_SYMBOLIC, stmt->u.par->dim); break; default: xassert(stmt != stmt); } break; case A_VARIABLE: /* model variable */ xassert(stmt->u.var->array == NULL); stmt->u.var->array = create_array(mpl, A_ELEMVAR, stmt->u.var->dim); break; case A_CONSTRAINT: /* model constraint/objective */ xassert(stmt->u.con->array == NULL); stmt->u.con->array = create_array(mpl, A_ELEMCON, stmt->u.con->dim); break; #if 1 /* 11/II-2008 */ case A_TABLE: #endif case A_SOLVE: case A_CHECK: case A_DISPLAY: case A_PRINTF: case A_FOR: /* functional statements have no content array */ break; default: xassert(stmt != stmt); } } return; } /*---------------------------------------------------------------------- -- generate_model - generate model. -- -- This routine executes the model statements which precede the solve -- statement. */ void generate_model(MPL *mpl) { STATEMENT *stmt; xassert(!mpl->flag_p); for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) { execute_statement(mpl, stmt); if (mpl->stmt->type == A_SOLVE) break; } mpl->stmt = stmt; return; } /*---------------------------------------------------------------------- -- build_problem - build problem instance. -- -- This routine builds lists of rows and columns for problem instance, -- which corresponds to the generated model. */ void build_problem(MPL *mpl) { STATEMENT *stmt; MEMBER *memb; VARIABLE *v; CONSTRAINT *c; FORMULA *t; int i, j; xassert(mpl->m == 0); xassert(mpl->n == 0); xassert(mpl->row == NULL); xassert(mpl->col == NULL); /* check that all elemental variables has zero column numbers */ for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) { if (stmt->type == A_VARIABLE) { v = stmt->u.var; for (memb = v->array->head; memb != NULL; memb = memb->next) xassert(memb->value.var->j == 0); } } /* assign row numbers to elemental constraints and objectives */ for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) { if (stmt->type == A_CONSTRAINT) { c = stmt->u.con; for (memb = c->array->head; memb != NULL; memb = memb->next) { xassert(memb->value.con->i == 0); memb->value.con->i = ++mpl->m; /* walk through linear form and mark elemental variables, which are referenced at least once */ for (t = memb->value.con->form; t != NULL; t = t->next) { xassert(t->var != NULL); t->var->memb->value.var->j = -1; } } } } /* assign column numbers to marked elemental variables */ for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) { if (stmt->type == A_VARIABLE) { v = stmt->u.var; for (memb = v->array->head; memb != NULL; memb = memb->next) if (memb->value.var->j != 0) memb->value.var->j = ++mpl->n; } } /* build list of rows */ mpl->row = xcalloc(1+mpl->m, sizeof(ELEMCON *)); for (i = 1; i <= mpl->m; i++) mpl->row[i] = NULL; for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) { if (stmt->type == A_CONSTRAINT) { c = stmt->u.con; for (memb = c->array->head; memb != NULL; memb = memb->next) { i = memb->value.con->i; xassert(1 <= i && i <= mpl->m); xassert(mpl->row[i] == NULL); mpl->row[i] = memb->value.con; } } } for (i = 1; i <= mpl->m; i++) xassert(mpl->row[i] != NULL); /* build list of columns */ mpl->col = xcalloc(1+mpl->n, sizeof(ELEMVAR *)); for (j = 1; j <= mpl->n; j++) mpl->col[j] = NULL; for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) { if (stmt->type == A_VARIABLE) { v = stmt->u.var; for (memb = v->array->head; memb != NULL; memb = memb->next) { j = memb->value.var->j; if (j == 0) continue; xassert(1 <= j && j <= mpl->n); xassert(mpl->col[j] == NULL); mpl->col[j] = memb->value.var; } } } for (j = 1; j <= mpl->n; j++) xassert(mpl->col[j] != NULL); return; } /*---------------------------------------------------------------------- -- postsolve_model - postsolve model. -- -- This routine executes the model statements which follow the solve -- statement. */ void postsolve_model(MPL *mpl) { STATEMENT *stmt; xassert(!mpl->flag_p); mpl->flag_p = 1; for (stmt = mpl->stmt; stmt != NULL; stmt = stmt->next) execute_statement(mpl, stmt); mpl->stmt = NULL; return; } /*---------------------------------------------------------------------- -- clean_model - clean model content. -- -- This routine cleans the model content that assumes deleting all stuff -- dynamically allocated on generating/postsolving phase. -- -- Actually cleaning model content is not needed. This function is used -- mainly to be sure that there were no logical errors on using dynamic -- memory pools during the generation phase. -- -- NOTE: This routine must not be called if any errors were detected on -- the generation phase. */ void clean_model(MPL *mpl) { STATEMENT *stmt; for (stmt = mpl->model; stmt != NULL; stmt = stmt->next) clean_statement(mpl, stmt); /* check that all atoms have been returned to their pools */ if (dmp_in_use(mpl->strings) != 0) error(mpl, "internal logic error: %d string segment(s) were lo" "st", dmp_in_use(mpl->strings)); if (dmp_in_use(mpl->symbols) != 0) error(mpl, "internal logic error: %d symbol(s) were lost", dmp_in_use(mpl->symbols)); if (dmp_in_use(mpl->tuples) != 0) error(mpl, "internal logic error: %d n-tuple component(s) were" " lost", dmp_in_use(mpl->tuples)); if (dmp_in_use(mpl->arrays) != 0) error(mpl, "internal logic error: %d array(s) were lost", dmp_in_use(mpl->arrays)); if (dmp_in_use(mpl->members) != 0) error(mpl, "internal logic error: %d array member(s) were lost" , dmp_in_use(mpl->members)); if (dmp_in_use(mpl->elemvars) != 0) error(mpl, "internal logic error: %d elemental variable(s) wer" "e lost", dmp_in_use(mpl->elemvars)); if (dmp_in_use(mpl->formulae) != 0) error(mpl, "internal logic error: %d linear term(s) were lost", dmp_in_use(mpl->formulae)); if (dmp_in_use(mpl->elemcons) != 0) error(mpl, "internal logic error: %d elemental constraint(s) w" "ere lost", dmp_in_use(mpl->elemcons)); return; } /**********************************************************************/ /* * * INPUT/OUTPUT * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- open_input - open input text file. -- -- This routine opens the input text file for scanning. */ void open_input(MPL *mpl, char *file) { mpl->line = 0; mpl->c = '\n'; mpl->token = 0; mpl->imlen = 0; mpl->image[0] = '\0'; mpl->value = 0.0; mpl->b_token = T_EOF; mpl->b_imlen = 0; mpl->b_image[0] = '\0'; mpl->b_value = 0.0; mpl->f_dots = 0; mpl->f_scan = 0; mpl->f_token = 0; mpl->f_imlen = 0; mpl->f_image[0] = '\0'; mpl->f_value = 0.0; memset(mpl->context, ' ', CONTEXT_SIZE); mpl->c_ptr = 0; xassert(mpl->in_fp == NULL); mpl->in_fp = xfopen(file, "r"); if (mpl->in_fp == NULL) error(mpl, "unable to open %s - %s", file, xerrmsg()); mpl->in_file = file; /* scan the very first character */ get_char(mpl); /* scan the very first token */ get_token(mpl); return; } /*---------------------------------------------------------------------- -- read_char - read next character from input text file. -- -- This routine returns a next ASCII character read from the input text -- file. If the end of file has been reached, EOF is returned. */ int read_char(MPL *mpl) { int c; xassert(mpl->in_fp != NULL); c = xfgetc(mpl->in_fp); if (c < 0) { if (xferror(mpl->in_fp)) error(mpl, "read error on %s - %s", mpl->in_file, xerrmsg()); c = EOF; } return c; } /*---------------------------------------------------------------------- -- close_input - close input text file. -- -- This routine closes the input text file. */ void close_input(MPL *mpl) { xassert(mpl->in_fp != NULL); xfclose(mpl->in_fp); mpl->in_fp = NULL; mpl->in_file = NULL; return; } /*---------------------------------------------------------------------- -- open_output - open output text file. -- -- This routine opens the output text file for writing data produced by -- display and printf statements. */ void open_output(MPL *mpl, char *file) { xassert(mpl->out_fp == NULL); if (file == NULL) { file = ""; mpl->out_fp = (void *)stdout; } else { mpl->out_fp = xfopen(file, "w"); if (mpl->out_fp == NULL) error(mpl, "unable to create %s - %s", file, xerrmsg()); } mpl->out_file = xmalloc(strlen(file)+1); strcpy(mpl->out_file, file); return; } /*---------------------------------------------------------------------- -- write_char - write next character to output text file. -- -- This routine writes an ASCII character to the output text file. */ void write_char(MPL *mpl, int c) { xassert(mpl->out_fp != NULL); if (mpl->out_fp == (void *)stdout) xprintf("%c", c); else xfprintf(mpl->out_fp, "%c", c); return; } /*---------------------------------------------------------------------- -- write_text - format and write text to output text file. -- -- This routine formats a text using the format control string and then -- writes this text to the output text file. */ void write_text(MPL *mpl, char *fmt, ...) { va_list arg; char buf[OUTBUF_SIZE], *c; va_start(arg, fmt); vsprintf(buf, fmt, arg); xassert(strlen(buf) < sizeof(buf)); va_end(arg); for (c = buf; *c != '\0'; c++) write_char(mpl, *c); return; } /*---------------------------------------------------------------------- -- flush_output - finalize writing data to output text file. -- -- This routine finalizes writing data to the output text file. */ void flush_output(MPL *mpl) { xassert(mpl->out_fp != NULL); if (mpl->out_fp != (void *)stdout) { xfflush(mpl->out_fp); if (xferror(mpl->out_fp)) error(mpl, "write error on %s - %s", mpl->out_file, xerrmsg()); } return; } /**********************************************************************/ /* * * SOLVER INTERFACE * * */ /**********************************************************************/ /*---------------------------------------------------------------------- -- error - print error message and terminate model processing. -- -- This routine formats and prints an error message and then terminates -- model processing. */ void error(MPL *mpl, char *fmt, ...) { va_list arg; char msg[4095+1]; va_start(arg, fmt); vsprintf(msg, fmt, arg); xassert(strlen(msg) < sizeof(msg)); va_end(arg); switch (mpl->phase) { case 1: case 2: /* translation phase */ xprintf("%s:%d: %s\n", mpl->in_file == NULL ? "(unknown)" : mpl->in_file, mpl->line, msg); print_context(mpl); break; case 3: /* generation/postsolve phase */ xprintf("%s:%d: %s\n", mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file, mpl->stmt == NULL ? 0 : mpl->stmt->line, msg); break; default: xassert(mpl != mpl); } mpl->phase = 4; longjmp(mpl->jump, 1); /* no return */ } /*---------------------------------------------------------------------- -- warning - print warning message and continue model processing. -- -- This routine formats and prints a warning message and returns to the -- calling program. */ void warning(MPL *mpl, char *fmt, ...) { va_list arg; char msg[4095+1]; va_start(arg, fmt); vsprintf(msg, fmt, arg); xassert(strlen(msg) < sizeof(msg)); va_end(arg); switch (mpl->phase) { case 1: case 2: /* translation phase */ xprintf("%s:%d: warning: %s\n", mpl->in_file == NULL ? "(unknown)" : mpl->in_file, mpl->line, msg); break; case 3: /* generation/postsolve phase */ xprintf("%s:%d: warning: %s\n", mpl->mod_file == NULL ? "(unknown)" : mpl->mod_file, mpl->stmt == NULL ? 0 : mpl->stmt->line, msg); break; default: xassert(mpl != mpl); } return; } /*---------------------------------------------------------------------- -- mpl_initialize - create and initialize translator database. -- -- *Synopsis* -- -- #include "glpmpl.h" -- MPL *mpl_initialize(void); -- -- *Description* -- -- The routine mpl_initialize creates and initializes the database used -- by the GNU MathProg translator. -- -- *Returns* -- -- The routine returns a pointer to the database created. */ MPL *mpl_initialize(void) { MPL *mpl; mpl = xmalloc(sizeof(MPL)); /* scanning segment */ mpl->line = 0; mpl->c = 0; mpl->token = 0; mpl->imlen = 0; mpl->image = xcalloc(MAX_LENGTH+1, sizeof(char)); mpl->image[0] = '\0'; mpl->value = 0.0; mpl->b_token = 0; mpl->b_imlen = 0; mpl->b_image = xcalloc(MAX_LENGTH+1, sizeof(char)); mpl->b_image[0] = '\0'; mpl->b_value = 0.0; mpl->f_dots = 0; mpl->f_scan = 0; mpl->f_token = 0; mpl->f_imlen = 0; mpl->f_image = xcalloc(MAX_LENGTH+1, sizeof(char)); mpl->f_image[0] = '\0'; mpl->f_value = 0.0; mpl->context = xcalloc(CONTEXT_SIZE, sizeof(char)); memset(mpl->context, ' ', CONTEXT_SIZE); mpl->c_ptr = 0; mpl->flag_d = 0; /* translating segment */ mpl->pool = dmp_create_poolx(0); mpl->tree = avl_create_tree(avl_strcmp, NULL); mpl->model = NULL; mpl->flag_x = 0; mpl->as_within = 0; mpl->as_in = 0; mpl->as_binary = 0; mpl->flag_s = 0; /* common segment */ mpl->strings = dmp_create_poolx(sizeof(STRING)); mpl->symbols = dmp_create_poolx(sizeof(SYMBOL)); mpl->tuples = dmp_create_poolx(sizeof(TUPLE)); mpl->arrays = dmp_create_poolx(sizeof(ARRAY)); mpl->members = dmp_create_poolx(sizeof(MEMBER)); mpl->elemvars = dmp_create_poolx(sizeof(ELEMVAR)); mpl->formulae = dmp_create_poolx(sizeof(FORMULA)); mpl->elemcons = dmp_create_poolx(sizeof(ELEMCON)); mpl->a_list = NULL; mpl->sym_buf = xcalloc(255+1, sizeof(char)); mpl->sym_buf[0] = '\0'; mpl->tup_buf = xcalloc(255+1, sizeof(char)); mpl->tup_buf[0] = '\0'; /* generating/postsolving segment */ mpl->rand = rng_create_rand(); mpl->flag_p = 0; mpl->stmt = NULL; #if 1 /* 11/II-2008 */ mpl->dca = NULL; #endif mpl->m = 0; mpl->n = 0; mpl->row = NULL; mpl->col = NULL; /* input/output segment */ mpl->in_fp = NULL; mpl->in_file = NULL; mpl->out_fp = NULL; mpl->out_file = NULL; mpl->prt_fp = NULL; mpl->prt_file = NULL; /* solver interface segment */ if (setjmp(mpl->jump)) xassert(mpl != mpl); mpl->phase = 0; mpl->mod_file = NULL; mpl->mpl_buf = xcalloc(255+1, sizeof(char)); mpl->mpl_buf[0] = '\0'; return mpl; } /*---------------------------------------------------------------------- -- mpl_read_model - read model section and optional data section. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_read_model(MPL *mpl, char *file, int skip_data); -- -- *Description* -- -- The routine mpl_read_model reads model section and optionally data -- section, which may follow the model section, from the text file, -- whose name is the character string file, performs translating model -- statements and data blocks, and stores all the information in the -- translator database. -- -- The parameter skip_data is a flag. If the input file contains the -- data section and this flag is set, the data section is not read as -- if there were no data section and a warning message is issued. This -- allows reading the data section from another input file. -- -- This routine should be called once after the routine mpl_initialize -- and before other API routines. -- -- *Returns* -- -- The routine mpl_read_model returns one the following codes: -- -- 1 - translation successful. The input text file contains only model -- section. In this case the calling program may call the routine -- mpl_read_data to read data section from another file. -- 2 - translation successful. The input text file contains both model -- and data section. -- 4 - processing failed due to some errors. In this case the calling -- program should call the routine mpl_terminate to terminate model -- processing. */ int mpl_read_model(MPL *mpl, char *file, int skip_data) { if (mpl->phase != 0) xfault("mpl_read_model: invalid call sequence\n"); if (file == NULL) xfault("mpl_read_model: no input filename specified\n"); /* set up error handler */ if (setjmp(mpl->jump)) goto done; /* translate model section */ mpl->phase = 1; xprintf("Reading model section from %s...\n", file); open_input(mpl, file); model_section(mpl); if (mpl->model == NULL) error(mpl, "empty model section not allowed"); /* save name of the input text file containing model section for error diagnostics during the generation phase */ mpl->mod_file = xcalloc(strlen(file)+1, sizeof(char)); strcpy(mpl->mod_file, mpl->in_file); /* allocate content arrays for all model objects */ alloc_content(mpl); /* optional data section may begin with the keyword 'data' */ if (is_keyword(mpl, "data")) { if (skip_data) { warning(mpl, "data section ignored"); goto skip; } mpl->flag_d = 1; get_token(mpl /* data */); if (mpl->token != T_SEMICOLON) error(mpl, "semicolon missing where expected"); get_token(mpl /* ; */); /* translate data section */ mpl->phase = 2; xprintf("Reading data section from %s...\n", file); data_section(mpl); } /* process end statement */ end_statement(mpl); skip: xprintf("%d line%s were read\n", mpl->line, mpl->line == 1 ? "" : "s"); close_input(mpl); done: /* return to the calling program */ return mpl->phase; } /*---------------------------------------------------------------------- -- mpl_read_data - read data section. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_read_data(MPL *mpl, char *file); -- -- *Description* -- -- The routine mpl_read_data reads data section from the text file, -- whose name is the character string file, performs translating data -- blocks, and stores the data read in the translator database. -- -- If this routine is used, it should be called once after the routine -- mpl_read_model and if the latter returned the code 1. -- -- *Returns* -- -- The routine mpl_read_data returns one of the following codes: -- -- 2 - data section has been successfully processed. -- 4 - processing failed due to some errors. In this case the calling -- program should call the routine mpl_terminate to terminate model -- processing. */ int mpl_read_data(MPL *mpl, char *file) #if 0 /* 02/X-2008 */ { if (mpl->phase != 1) #else { if (!(mpl->phase == 1 || mpl->phase == 2)) #endif xfault("mpl_read_data: invalid call sequence\n"); if (file == NULL) xfault("mpl_read_data: no input filename specified\n"); /* set up error handler */ if (setjmp(mpl->jump)) goto done; /* process data section */ mpl->phase = 2; xprintf("Reading data section from %s...\n", file); mpl->flag_d = 1; open_input(mpl, file); /* in this case the keyword 'data' is optional */ if (is_literal(mpl, "data")) { get_token(mpl /* data */); if (mpl->token != T_SEMICOLON) error(mpl, "semicolon missing where expected"); get_token(mpl /* ; */); } data_section(mpl); /* process end statement */ end_statement(mpl); xprintf("%d line%s were read\n", mpl->line, mpl->line == 1 ? "" : "s"); close_input(mpl); done: /* return to the calling program */ return mpl->phase; } /*---------------------------------------------------------------------- -- mpl_generate - generate model. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_generate(MPL *mpl, char *file); -- -- *Description* -- -- The routine mpl_generate generates the model using its description -- stored in the translator database. This phase means generating all -- variables, constraints, and objectives, executing check and display -- statements, which precede the solve statement (if it is presented), -- and building the problem instance. -- -- The character string file specifies the name of output text file, to -- which output produced by display statements should be written. It is -- allowed to specify NULL, in which case the output goes to stdout via -- the routine print. -- -- This routine should be called once after the routine mpl_read_model -- or mpl_read_data and if one of the latters returned the code 2. -- -- *Returns* -- -- The routine mpl_generate returns one of the following codes: -- -- 3 - model has been successfully generated. In this case the calling -- program may call other api routines to obtain components of the -- problem instance from the translator database. -- 4 - processing failed due to some errors. In this case the calling -- program should call the routine mpl_terminate to terminate model -- processing. */ int mpl_generate(MPL *mpl, char *file) { if (!(mpl->phase == 1 || mpl->phase == 2)) xfault("mpl_generate: invalid call sequence\n"); /* set up error handler */ if (setjmp(mpl->jump)) goto done; /* generate model */ mpl->phase = 3; open_output(mpl, file); generate_model(mpl); flush_output(mpl); /* build problem instance */ build_problem(mpl); /* generation phase has been finished */ xprintf("Model has been successfully generated\n"); done: /* return to the calling program */ return mpl->phase; } /*---------------------------------------------------------------------- -- mpl_get_prob_name - obtain problem (model) name. -- -- *Synopsis* -- -- #include "glpmpl.h" -- char *mpl_get_prob_name(MPL *mpl); -- -- *Returns* -- -- The routine mpl_get_prob_name returns a pointer to internal buffer, -- which contains symbolic name of the problem (model). -- -- *Note* -- -- Currently MathProg has no feature to assign a symbolic name to the -- model. Therefore the routine mpl_get_prob_name tries to construct -- such name using the name of input text file containing model section, -- although this is not a good idea (due to portability problems). */ char *mpl_get_prob_name(MPL *mpl) { char *name = mpl->mpl_buf; char *file = mpl->mod_file; int k; if (mpl->phase != 3) xfault("mpl_get_prob_name: invalid call sequence\n"); for (;;) { if (strchr(file, '/') != NULL) file = strchr(file, '/') + 1; else if (strchr(file, '\\') != NULL) file = strchr(file, '\\') + 1; else if (strchr(file, ':') != NULL) file = strchr(file, ':') + 1; else break; } for (k = 0; ; k++) { if (k == 255) break; if (!(isalnum((unsigned char)*file) || *file == '_')) break; name[k] = *file++; } if (k == 0) strcpy(name, "Unknown"); else name[k] = '\0'; xassert(strlen(name) <= 255); return name; } /*---------------------------------------------------------------------- -- mpl_get_num_rows - determine number of rows. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_get_num_rows(MPL *mpl); -- -- *Returns* -- -- The routine mpl_get_num_rows returns total number of rows in the -- problem, where each row is an individual constraint or objective. */ int mpl_get_num_rows(MPL *mpl) { if (mpl->phase != 3) xfault("mpl_get_num_rows: invalid call sequence\n"); return mpl->m; } /*---------------------------------------------------------------------- -- mpl_get_num_cols - determine number of columns. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_get_num_cols(MPL *mpl); -- -- *Returns* -- -- The routine mpl_get_num_cols returns total number of columns in the -- problem, where each column is an individual variable. */ int mpl_get_num_cols(MPL *mpl) { if (mpl->phase != 3) xfault("mpl_get_num_cols: invalid call sequence\n"); return mpl->n; } /*---------------------------------------------------------------------- -- mpl_get_row_name - obtain row name. -- -- *Synopsis* -- -- #include "glpmpl.h" -- char *mpl_get_row_name(MPL *mpl, int i); -- -- *Returns* -- -- The routine mpl_get_row_name returns a pointer to internal buffer, -- which contains symbolic name of i-th row of the problem. */ char *mpl_get_row_name(MPL *mpl, int i) { char *name = mpl->mpl_buf, *t; int len; if (mpl->phase != 3) xfault("mpl_get_row_name: invalid call sequence\n"); if (!(1 <= i && i <= mpl->m)) xfault("mpl_get_row_name: i = %d; row number out of range\n", i); strcpy(name, mpl->row[i]->con->name); len = strlen(name); xassert(len <= 255); t = format_tuple(mpl, '[', mpl->row[i]->memb->tuple); while (*t) { if (len == 255) break; name[len++] = *t++; } name[len] = '\0'; if (len == 255) strcpy(name+252, "..."); xassert(strlen(name) <= 255); return name; } /*---------------------------------------------------------------------- -- mpl_get_row_kind - determine row kind. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_get_row_kind(MPL *mpl, int i); -- -- *Returns* -- -- The routine mpl_get_row_kind returns the kind of i-th row, which can -- be one of the following: -- -- MPL_ST - non-free (constraint) row; -- MPL_MIN - free (objective) row to be minimized; -- MPL_MAX - free (objective) row to be maximized. */ int mpl_get_row_kind(MPL *mpl, int i) { int kind; if (mpl->phase != 3) xfault("mpl_get_row_kind: invalid call sequence\n"); if (!(1 <= i && i <= mpl->m)) xfault("mpl_get_row_kind: i = %d; row number out of range\n", i); switch (mpl->row[i]->con->type) { case A_CONSTRAINT: kind = MPL_ST; break; case A_MINIMIZE: kind = MPL_MIN; break; case A_MAXIMIZE: kind = MPL_MAX; break; default: xassert(mpl != mpl); } return kind; } /*---------------------------------------------------------------------- -- mpl_get_row_bnds - obtain row bounds. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_get_row_bnds(MPL *mpl, int i, double *lb, double *ub); -- -- *Description* -- -- The routine mpl_get_row_bnds stores lower and upper bounds of i-th -- row of the problem to the locations, which the parameters lb and ub -- point to, respectively. Besides the routine returns the type of the -- i-th row. -- -- If some of the parameters lb and ub is NULL, the corresponding bound -- value is not stored. -- -- Types and bounds have the following meaning: -- -- Type Bounds Note -- ----------------------------------------------------------- -- MPL_FR -inf < f(x) < +inf Free linear form -- MPL_LO lb <= f(x) < +inf Inequality f(x) >= lb -- MPL_UP -inf < f(x) <= ub Inequality f(x) <= ub -- MPL_DB lb <= f(x) <= ub Inequality lb <= f(x) <= ub -- MPL_FX f(x) = lb Equality f(x) = lb -- -- where f(x) is the corresponding linear form of the i-th row. -- -- If the row has no lower bound, *lb is set to zero; if the row has -- no upper bound, *ub is set to zero; and if the row is of fixed type, -- both *lb and *ub are set to the same value. -- -- *Returns* -- -- The routine returns the type of the i-th row as it is stated in the -- table above. */ int mpl_get_row_bnds(MPL *mpl, int i, double *_lb, double *_ub) { ELEMCON *con; int type; double lb, ub; if (mpl->phase != 3) xfault("mpl_get_row_bnds: invalid call sequence\n"); if (!(1 <= i && i <= mpl->m)) xfault("mpl_get_row_bnds: i = %d; row number out of range\n", i); con = mpl->row[i]; #if 0 /* 21/VII-2006 */ if (con->con->lbnd == NULL && con->con->ubnd == NULL) type = MPL_FR, lb = ub = 0.0; else if (con->con->ubnd == NULL) type = MPL_LO, lb = con->lbnd, ub = 0.0; else if (con->con->lbnd == NULL) type = MPL_UP, lb = 0.0, ub = con->ubnd; else if (con->con->lbnd != con->con->ubnd) type = MPL_DB, lb = con->lbnd, ub = con->ubnd; else type = MPL_FX, lb = ub = con->lbnd; #else lb = (con->con->lbnd == NULL ? -DBL_MAX : con->lbnd); ub = (con->con->ubnd == NULL ? +DBL_MAX : con->ubnd); if (lb == -DBL_MAX && ub == +DBL_MAX) type = MPL_FR, lb = ub = 0.0; else if (ub == +DBL_MAX) type = MPL_LO, ub = 0.0; else if (lb == -DBL_MAX) type = MPL_UP, lb = 0.0; else if (con->con->lbnd != con->con->ubnd) type = MPL_DB; else type = MPL_FX; #endif if (_lb != NULL) *_lb = lb; if (_ub != NULL) *_ub = ub; return type; } /*---------------------------------------------------------------------- -- mpl_get_mat_row - obtain row of the constraint matrix. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]); -- -- *Description* -- -- The routine mpl_get_mat_row stores column indices and numeric values -- of constraint coefficients for the i-th row to locations ndx[1], ..., -- ndx[len] and val[1], ..., val[len], respectively, where 0 <= len <= n -- is number of (structural) non-zero constraint coefficients, and n is -- number of columns in the problem. -- -- If the parameter ndx is NULL, column indices are not stored. If the -- parameter val is NULL, numeric values are not stored. -- -- Note that free rows may have constant terms, which are not part of -- the constraint matrix and therefore not reported by this routine. The -- constant term of a particular row can be obtained, if necessary, via -- the routine mpl_get_row_c0. -- -- *Returns* -- -- The routine mpl_get_mat_row returns len, which is length of i-th row -- of the constraint matrix (i.e. number of non-zero coefficients). */ int mpl_get_mat_row(MPL *mpl, int i, int ndx[], double val[]) { FORMULA *term; int len = 0; if (mpl->phase != 3) xfault("mpl_get_mat_row: invalid call sequence\n"); if (!(1 <= i && i <= mpl->m)) xfault("mpl_get_mat_row: i = %d; row number out of range\n", i); for (term = mpl->row[i]->form; term != NULL; term = term->next) { xassert(term->var != NULL); len++; xassert(len <= mpl->n); if (ndx != NULL) ndx[len] = term->var->j; if (val != NULL) val[len] = term->coef; } return len; } /*---------------------------------------------------------------------- -- mpl_get_row_c0 - obtain constant term of free row. -- -- *Synopsis* -- -- #include "glpmpl.h" -- double mpl_get_row_c0(MPL *mpl, int i); -- -- *Returns* -- -- The routine mpl_get_row_c0 returns numeric value of constant term of -- i-th row. -- -- Note that only free rows may have non-zero constant terms. Therefore -- if i-th row is not free, the routine returns zero. */ double mpl_get_row_c0(MPL *mpl, int i) { ELEMCON *con; double c0; if (mpl->phase != 3) xfault("mpl_get_row_c0: invalid call sequence\n"); if (!(1 <= i && i <= mpl->m)) xfault("mpl_get_row_c0: i = %d; row number out of range\n", i); con = mpl->row[i]; if (con->con->lbnd == NULL && con->con->ubnd == NULL) c0 = - con->lbnd; else c0 = 0.0; return c0; } /*---------------------------------------------------------------------- -- mpl_get_col_name - obtain column name. -- -- *Synopsis* -- -- #include "glpmpl.h" -- char *mpl_get_col_name(MPL *mpl, int j); -- -- *Returns* -- -- The routine mpl_get_col_name returns a pointer to internal buffer, -- which contains symbolic name of j-th column of the problem. */ char *mpl_get_col_name(MPL *mpl, int j) { char *name = mpl->mpl_buf, *t; int len; if (mpl->phase != 3) xfault("mpl_get_col_name: invalid call sequence\n"); if (!(1 <= j && j <= mpl->n)) xfault("mpl_get_col_name: j = %d; column number out of range\n" , j); strcpy(name, mpl->col[j]->var->name); len = strlen(name); xassert(len <= 255); t = format_tuple(mpl, '[', mpl->col[j]->memb->tuple); while (*t) { if (len == 255) break; name[len++] = *t++; } name[len] = '\0'; if (len == 255) strcpy(name+252, "..."); xassert(strlen(name) <= 255); return name; } /*---------------------------------------------------------------------- -- mpl_get_col_kind - determine column kind. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_get_col_kind(MPL *mpl, int j); -- -- *Returns* -- -- The routine mpl_get_col_kind returns the kind of j-th column, which -- can be one of the following: -- -- MPL_NUM - continuous variable; -- MPL_INT - integer variable; -- MPL_BIN - binary variable. -- -- Note that column kinds are defined independently on type and bounds -- (reported by the routine mpl_get_col_bnds) of corresponding columns. -- This means, in particular, that bounds of an integer column may be -- fractional, or a binary column may have lower and upper bounds that -- are not 0 and 1 (or it may have no lower/upper bound at all). */ int mpl_get_col_kind(MPL *mpl, int j) { int kind; if (mpl->phase != 3) xfault("mpl_get_col_kind: invalid call sequence\n"); if (!(1 <= j && j <= mpl->n)) xfault("mpl_get_col_kind: j = %d; column number out of range\n" , j); switch (mpl->col[j]->var->type) { case A_NUMERIC: kind = MPL_NUM; break; case A_INTEGER: kind = MPL_INT; break; case A_BINARY: kind = MPL_BIN; break; default: xassert(mpl != mpl); } return kind; } /*---------------------------------------------------------------------- -- mpl_get_col_bnds - obtain column bounds. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_get_col_bnds(MPL *mpl, int j, double *lb, double *ub); -- -- *Description* -- -- The routine mpl_get_col_bnds stores lower and upper bound of j-th -- column of the problem to the locations, which the parameters lb and -- ub point to, respectively. Besides the routine returns the type of -- the j-th column. -- -- If some of the parameters lb and ub is NULL, the corresponding bound -- value is not stored. -- -- Types and bounds have the following meaning: -- -- Type Bounds Note -- ------------------------------------------------------ -- MPL_FR -inf < x < +inf Free (unbounded) variable -- MPL_LO lb <= x < +inf Variable with lower bound -- MPL_UP -inf < x <= ub Variable with upper bound -- MPL_DB lb <= x <= ub Double-bounded variable -- MPL_FX x = lb Fixed variable -- -- where x is individual variable corresponding to the j-th column. -- -- If the column has no lower bound, *lb is set to zero; if the column -- has no upper bound, *ub is set to zero; and if the column is of fixed -- type, both *lb and *ub are set to the same value. -- -- *Returns* -- -- The routine returns the type of the j-th column as it is stated in -- the table above. */ int mpl_get_col_bnds(MPL *mpl, int j, double *_lb, double *_ub) { ELEMVAR *var; int type; double lb, ub; if (mpl->phase != 3) xfault("mpl_get_col_bnds: invalid call sequence\n"); if (!(1 <= j && j <= mpl->n)) xfault("mpl_get_col_bnds: j = %d; column number out of range\n" , j); var = mpl->col[j]; #if 0 /* 21/VII-2006 */ if (var->var->lbnd == NULL && var->var->ubnd == NULL) type = MPL_FR, lb = ub = 0.0; else if (var->var->ubnd == NULL) type = MPL_LO, lb = var->lbnd, ub = 0.0; else if (var->var->lbnd == NULL) type = MPL_UP, lb = 0.0, ub = var->ubnd; else if (var->var->lbnd != var->var->ubnd) type = MPL_DB, lb = var->lbnd, ub = var->ubnd; else type = MPL_FX, lb = ub = var->lbnd; #else lb = (var->var->lbnd == NULL ? -DBL_MAX : var->lbnd); ub = (var->var->ubnd == NULL ? +DBL_MAX : var->ubnd); if (lb == -DBL_MAX && ub == +DBL_MAX) type = MPL_FR, lb = ub = 0.0; else if (ub == +DBL_MAX) type = MPL_LO, ub = 0.0; else if (lb == -DBL_MAX) type = MPL_UP, lb = 0.0; else if (var->var->lbnd != var->var->ubnd) type = MPL_DB; else type = MPL_FX; #endif if (_lb != NULL) *_lb = lb; if (_ub != NULL) *_ub = ub; return type; } /*---------------------------------------------------------------------- -- mpl_has_solve_stmt - check if model has solve statement. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_has_solve_stmt(MPL *mpl); -- -- *Returns* -- -- If the model has the solve statement, the routine returns non-zero, -- otherwise zero is returned. */ int mpl_has_solve_stmt(MPL *mpl) { if (mpl->phase != 3) xfault("mpl_has_solve_stmt: invalid call sequence\n"); return mpl->flag_s; } #if 1 /* 15/V-2010 */ void mpl_put_row_soln(MPL *mpl, int i, int stat, double prim, double dual) { /* store row (constraint/objective) solution components */ xassert(mpl->phase == 3); xassert(1 <= i && i <= mpl->m); mpl->row[i]->stat = stat; mpl->row[i]->prim = prim; mpl->row[i]->dual = dual; return; } #endif #if 1 /* 15/V-2010 */ void mpl_put_col_soln(MPL *mpl, int j, int stat, double prim, double dual) { /* store column (variable) solution components */ xassert(mpl->phase == 3); xassert(1 <= j && j <= mpl->n); mpl->col[j]->stat = stat; mpl->col[j]->prim = prim; mpl->col[j]->dual = dual; return; } #endif #if 0 /* 15/V-2010 */ /*---------------------------------------------------------------------- -- mpl_put_col_value - store column value. -- -- *Synopsis* -- -- #include "glpmpl.h" -- void mpl_put_col_value(MPL *mpl, int j, double val); -- -- *Description* -- -- The routine mpl_put_col_value stores numeric value of j-th column -- into the translator database. It is assumed that the column value is -- provided by the solver. */ void mpl_put_col_value(MPL *mpl, int j, double val) { if (mpl->phase != 3) xfault("mpl_put_col_value: invalid call sequence\n"); if (!(1 <= j && j <= mpl->n)) xfault( "mpl_put_col_value: j = %d; column number out of range\n", j); mpl->col[j]->prim = val; return; } #endif /*---------------------------------------------------------------------- -- mpl_postsolve - postsolve model. -- -- *Synopsis* -- -- #include "glpmpl.h" -- int mpl_postsolve(MPL *mpl); -- -- *Description* -- -- The routine mpl_postsolve performs postsolving of the model using -- its description stored in the translator database. This phase means -- executing statements, which follow the solve statement. -- -- If this routine is used, it should be called once after the routine -- mpl_generate and if the latter returned the code 3. -- -- *Returns* -- -- The routine mpl_postsolve returns one of the following codes: -- -- 3 - model has been successfully postsolved. -- 4 - processing failed due to some errors. In this case the calling -- program should call the routine mpl_terminate to terminate model -- processing. */ int mpl_postsolve(MPL *mpl) { if (!(mpl->phase == 3 && !mpl->flag_p)) xfault("mpl_postsolve: invalid call sequence\n"); /* set up error handler */ if (setjmp(mpl->jump)) goto done; /* perform postsolving */ postsolve_model(mpl); flush_output(mpl); /* postsolving phase has been finished */ xprintf("Model has been successfully processed\n"); done: /* return to the calling program */ return mpl->phase; } /*---------------------------------------------------------------------- -- mpl_terminate - free all resources used by translator. -- -- *Synopsis* -- -- #include "glpmpl.h" -- void mpl_terminate(MPL *mpl); -- -- *Description* -- -- The routine mpl_terminate frees all the resources used by the GNU -- MathProg translator. */ void mpl_terminate(MPL *mpl) { if (setjmp(mpl->jump)) xassert(mpl != mpl); switch (mpl->phase) { case 0: case 1: case 2: case 3: /* there were no errors; clean the model content */ clean_model(mpl); xassert(mpl->a_list == NULL); #if 1 /* 11/II-2008 */ xassert(mpl->dca == NULL); #endif break; case 4: /* model processing has been finished due to error; delete search trees, which may be created for some arrays */ { ARRAY *a; for (a = mpl->a_list; a != NULL; a = a->next) if (a->tree != NULL) avl_delete_tree(a->tree); } #if 1 /* 11/II-2008 */ free_dca(mpl); #endif break; default: xassert(mpl != mpl); } /* delete the translator database */ xfree(mpl->image); xfree(mpl->b_image); xfree(mpl->f_image); xfree(mpl->context); dmp_delete_pool(mpl->pool); avl_delete_tree(mpl->tree); dmp_delete_pool(mpl->strings); dmp_delete_pool(mpl->symbols); dmp_delete_pool(mpl->tuples); dmp_delete_pool(mpl->arrays); dmp_delete_pool(mpl->members); dmp_delete_pool(mpl->elemvars); dmp_delete_pool(mpl->formulae); dmp_delete_pool(mpl->elemcons); xfree(mpl->sym_buf); xfree(mpl->tup_buf); rng_delete_rand(mpl->rand); if (mpl->row != NULL) xfree(mpl->row); if (mpl->col != NULL) xfree(mpl->col); if (mpl->in_fp != NULL) xfclose(mpl->in_fp); if (mpl->out_fp != NULL && mpl->out_fp != (void *)stdout) xfclose(mpl->out_fp); if (mpl->out_file != NULL) xfree(mpl->out_file); if (mpl->prt_fp != NULL) xfclose(mpl->prt_fp); if (mpl->prt_file != NULL) xfree(mpl->prt_file); if (mpl->mod_file != NULL) xfree(mpl->mod_file); xfree(mpl->mpl_buf); xfree(mpl); return; } /* eof */ glpk-4.52.1/src/glpmpl05.c0000644000062000006210000005342212175147600014322 0ustar maomkpasswd/* glpmpl05.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Authors: Andrew Makhorin * Heinrich Schuchardt * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_STDIO #define _GLPSTD_TIME #include "glpmpl.h" #if 1 /* 11/VI-2013 */ #include "jd.h" #endif double fn_gmtime(MPL *mpl) { /* obtain the current calendar time (UTC) */ time_t timer; struct tm *tm; int j; time(&timer); if (timer == (time_t)(-1)) err: error(mpl, "gmtime(); unable to obtain current calendar time"); tm = gmtime(&timer); if (tm == NULL) goto err; j = jday(tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year); if (j < 0) goto err; return (((double)(j - jday(1, 1, 1970)) * 24.0 + (double)tm->tm_hour) * 60.0 + (double)tm->tm_min) * 60.0 + (double)tm->tm_sec; } static char *week[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; static char *moon[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; static void error1(MPL *mpl, const char *str, const char *s, const char *fmt, const char *f, const char *msg) { xprintf("Input string passed to str2time:\n"); xprintf("%s\n", str); xprintf("%*s\n", (s - str) + 1, "^"); xprintf("Format string passed to str2time:\n"); xprintf("%s\n", fmt); xprintf("%*s\n", (f - fmt) + 1, "^"); error(mpl, "%s", msg); /* no return */ } double fn_str2time(MPL *mpl, const char *str, const char *fmt) { /* convert character string to the calendar time */ int j, year, month, day, hh, mm, ss, zone; const char *s, *f; year = month = day = hh = mm = ss = -1, zone = INT_MAX; s = str; for (f = fmt; *f != '\0'; f++) { if (*f == '%') { f++; if (*f == 'b' || *f == 'h') { /* the abbreviated month name */ int k; char *name; if (month >= 0) error1(mpl, str, s, fmt, f, "month multiply specified" ); while (*s == ' ') s++; for (month = 1; month <= 12; month++) { name = moon[month-1]; for (k = 0; k <= 2; k++) { if (toupper((unsigned char)s[k]) != toupper((unsigned char)name[k])) goto next; } s += 3; for (k = 3; name[k] != '\0'; k++) { if (toupper((unsigned char)*s) != toupper((unsigned char)name[k])) break; s++; } break; next: ; } if (month > 12) error1(mpl, str, s, fmt, f, "abbreviated month name m" "issing or invalid"); } else if (*f == 'd') { /* the day of the month as a decimal number (01..31) */ if (day >= 0) error1(mpl, str, s, fmt, f, "day multiply specified"); while (*s == ' ') s++; if (!('0' <= *s && *s <= '9')) error1(mpl, str, s, fmt, f, "day missing or invalid"); day = (*s++) - '0'; if ('0' <= *s && *s <= '9') day = 10 * day + ((*s++) - '0'); if (!(1 <= day && day <= 31)) error1(mpl, str, s, fmt, f, "day out of range"); } else if (*f == 'H') { /* the hour as a decimal number, using a 24-hour clock (00..23) */ if (hh >= 0) error1(mpl, str, s, fmt, f, "hour multiply specified") ; while (*s == ' ') s++; if (!('0' <= *s && *s <= '9')) error1(mpl, str, s, fmt, f, "hour missing or invalid") ; hh = (*s++) - '0'; if ('0' <= *s && *s <= '9') hh = 10 * hh + ((*s++) - '0'); if (!(0 <= hh && hh <= 23)) error1(mpl, str, s, fmt, f, "hour out of range"); } else if (*f == 'm') { /* the month as a decimal number (01..12) */ if (month >= 0) error1(mpl, str, s, fmt, f, "month multiply specified" ); while (*s == ' ') s++; if (!('0' <= *s && *s <= '9')) error1(mpl, str, s, fmt, f, "month missing or invalid" ); month = (*s++) - '0'; if ('0' <= *s && *s <= '9') month = 10 * month + ((*s++) - '0'); if (!(1 <= month && month <= 12)) error1(mpl, str, s, fmt, f, "month out of range"); } else if (*f == 'M') { /* the minute as a decimal number (00..59) */ if (mm >= 0) error1(mpl, str, s, fmt, f, "minute multiply specifie" "d"); while (*s == ' ') s++; if (!('0' <= *s && *s <= '9')) error1(mpl, str, s, fmt, f, "minute missing or invali" "d"); mm = (*s++) - '0'; if ('0' <= *s && *s <= '9') mm = 10 * mm + ((*s++) - '0'); if (!(0 <= mm && mm <= 59)) error1(mpl, str, s, fmt, f, "minute out of range"); } else if (*f == 'S') { /* the second as a decimal number (00..60) */ if (ss >= 0) error1(mpl, str, s, fmt, f, "second multiply specifie" "d"); while (*s == ' ') s++; if (!('0' <= *s && *s <= '9')) error1(mpl, str, s, fmt, f, "second missing or invali" "d"); ss = (*s++) - '0'; if ('0' <= *s && *s <= '9') ss = 10 * ss + ((*s++) - '0'); if (!(0 <= ss && ss <= 60)) error1(mpl, str, s, fmt, f, "second out of range"); } else if (*f == 'y') { /* the year without a century as a decimal number (00..99); the values 00 to 68 mean the years 2000 to 2068 while the values 69 to 99 mean the years 1969 to 1999 */ if (year >= 0) error1(mpl, str, s, fmt, f, "year multiply specified") ; while (*s == ' ') s++; if (!('0' <= *s && *s <= '9')) error1(mpl, str, s, fmt, f, "year missing or invalid") ; year = (*s++) - '0'; if ('0' <= *s && *s <= '9') year = 10 * year + ((*s++) - '0'); year += (year >= 69 ? 1900 : 2000); } else if (*f == 'Y') { /* the year as a decimal number, using the Gregorian calendar */ if (year >= 0) error1(mpl, str, s, fmt, f, "year multiply specified") ; while (*s == ' ') s++; if (!('0' <= *s && *s <= '9')) error1(mpl, str, s, fmt, f, "year missing or invalid") ; year = 0; for (j = 1; j <= 4; j++) { if (!('0' <= *s && *s <= '9')) break; year = 10 * year + ((*s++) - '0'); } if (!(1 <= year && year <= 4000)) error1(mpl, str, s, fmt, f, "year out of range"); } else if (*f == 'z') { /* time zone offset in the form zhhmm */ int z, hh, mm; if (zone != INT_MAX) error1(mpl, str, s, fmt, f, "time zone offset multipl" "y specified"); while (*s == ' ') s++; if (*s == 'Z') { z = hh = mm = 0, s++; goto skip; } if (*s == '+') z = +1, s++; else if (*s == '-') z = -1, s++; else error1(mpl, str, s, fmt, f, "time zone offset sign mi" "ssing"); hh = 0; for (j = 1; j <= 2; j++) { if (!('0' <= *s && *s <= '9')) err1: error1(mpl, str, s, fmt, f, "time zone offset valu" "e incomplete or invalid"); hh = 10 * hh + ((*s++) - '0'); } if (hh > 23) err2: error1(mpl, str, s, fmt, f, "time zone offset value o" "ut of range"); if (*s == ':') { s++; if (!('0' <= *s && *s <= '9')) goto err1; } mm = 0; if (!('0' <= *s && *s <= '9')) goto skip; for (j = 1; j <= 2; j++) { if (!('0' <= *s && *s <= '9')) goto err1; mm = 10 * mm + ((*s++) - '0'); } if (mm > 59) goto err2; skip: zone = z * (60 * hh + mm); } else if (*f == '%') { /* literal % character */ goto test; } else error1(mpl, str, s, fmt, f, "invalid conversion specifie" "r"); } else if (*f == ' ') ; else test: { /* check a matching character in the input string */ if (*s != *f) error1(mpl, str, s, fmt, f, "character mismatch"); s++; } } if (year < 0) year = 1970; if (month < 0) month = 1; if (day < 0) day = 1; if (hh < 0) hh = 0; if (mm < 0) mm = 0; if (ss < 0) ss = 0; if (zone == INT_MAX) zone = 0; j = jday(day, month, year); xassert(j >= 0); return (((double)(j - jday(1, 1, 1970)) * 24.0 + (double)hh) * 60.0 + (double)mm) * 60.0 + (double)ss - 60.0 * (double)zone; } static void error2(MPL *mpl, const char *fmt, const char *f, const char *msg) { xprintf("Format string passed to time2str:\n"); xprintf("%s\n", fmt); xprintf("%*s\n", (f - fmt) + 1, "^"); error(mpl, "%s", msg); /* no return */ } static int weekday(int j) { /* determine weekday number (1 = Mon, ..., 7 = Sun) */ return (j + jday(1, 1, 1970)) % 7 + 1; } static int firstday(int year) { /* determine the first day of the first week for a specified year according to ISO 8601 */ int j; /* if 1 January is Monday, Tuesday, Wednesday or Thursday, it is in week 01; if 1 January is Friday, Saturday or Sunday, it is in week 52 or 53 of the previous year */ j = jday(1, 1, year) - jday(1, 1, 1970); switch (weekday(j)) { case 1: /* 1 Jan is Mon */ j += 0; break; case 2: /* 1 Jan is Tue */ j -= 1; break; case 3: /* 1 Jan is Wed */ j -= 2; break; case 4: /* 1 Jan is Thu */ j -= 3; break; case 5: /* 1 Jan is Fri */ j += 3; break; case 6: /* 1 Jan is Sat */ j += 2; break; case 7: /* 1 Jan is Sun */ j += 1; break; default: xassert(j != j); } /* the first day of the week must be Monday */ xassert(weekday(j) == 1); return j; } void fn_time2str(MPL *mpl, char *str, double t, const char *fmt) { /* convert the calendar time to character string */ int j, year, month, day, hh, mm, ss, len; double temp; const char *f; char buf[MAX_LENGTH+1]; if (!(-62135596800.0 <= t && t <= 64092211199.0)) error(mpl, "time2str(%.*g,...); argument out of range", DBL_DIG, t); t = floor(t + 0.5); temp = fabs(t) / 86400.0; j = (int)floor(temp); if (t < 0.0) { if (temp == floor(temp)) j = - j; else j = - (j + 1); } xassert(jdate(j + jday(1, 1, 1970), &day, &month, &year) == 0); ss = (int)(t - 86400.0 * (double)j); xassert(0 <= ss && ss < 86400); mm = ss / 60, ss %= 60; hh = mm / 60, mm %= 60; len = 0; for (f = fmt; *f != '\0'; f++) { if (*f == '%') { f++; if (*f == 'a') { /* the abbreviated weekday name */ memcpy(buf, week[weekday(j)-1], 3), buf[3] = '\0'; } else if (*f == 'A') { /* the full weekday name */ strcpy(buf, week[weekday(j)-1]); } else if (*f == 'b' || *f == 'h') { /* the abbreviated month name */ memcpy(buf, moon[month-1], 3), buf[3] = '\0'; } else if (*f == 'B') { /* the full month name */ strcpy(buf, moon[month-1]); } else if (*f == 'C') { /* the century of the year */ sprintf(buf, "%02d", year / 100); } else if (*f == 'd') { /* the day of the month as a decimal number (01..31) */ sprintf(buf, "%02d", day); } else if (*f == 'D') { /* the date using the format %m/%d/%y */ sprintf(buf, "%02d/%02d/%02d", month, day, year % 100); } else if (*f == 'e') { /* the day of the month like with %d, but padded with blank (1..31) */ sprintf(buf, "%2d", day); } else if (*f == 'F') { /* the date using the format %Y-%m-%d */ sprintf(buf, "%04d-%02d-%02d", year, month, day); } else if (*f == 'g') { /* the year corresponding to the ISO week number, but without the century (range 00 through 99); this has the same format and value as %y, except that if the ISO week number (see %V) belongs to the previous or next year, that year is used instead */ int iso; if (j < firstday(year)) iso = year - 1; else if (j < firstday(year + 1)) iso = year; else iso = year + 1; sprintf(buf, "%02d", iso % 100); } else if (*f == 'G') { /* the year corresponding to the ISO week number; this has the same format and value as %Y, excepth that if the ISO week number (see %V) belongs to the previous or next year, that year is used instead */ int iso; if (j < firstday(year)) iso = year - 1; else if (j < firstday(year + 1)) iso = year; else iso = year + 1; sprintf(buf, "%04d", iso); } else if (*f == 'H') { /* the hour as a decimal number, using a 24-hour clock (00..23) */ sprintf(buf, "%02d", hh); } else if (*f == 'I') { /* the hour as a decimal number, using a 12-hour clock (01..12) */ sprintf(buf, "%02d", hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); } else if (*f == 'j') { /* the day of the year as a decimal number (001..366) */ sprintf(buf, "%03d", jday(day, month, year) - jday(1, 1, year) + 1); } else if (*f == 'k') { /* the hour as a decimal number, using a 24-hour clock like %H, but padded with blank (0..23) */ sprintf(buf, "%2d", hh); } else if (*f == 'l') { /* the hour as a decimal number, using a 12-hour clock like %I, but padded with blank (1..12) */ sprintf(buf, "%2d", hh == 0 ? 12 : hh <= 12 ? hh : hh - 12); } else if (*f == 'm') { /* the month as a decimal number (01..12) */ sprintf(buf, "%02d", month); } else if (*f == 'M') { /* the minute as a decimal number (00..59) */ sprintf(buf, "%02d", mm); } else if (*f == 'p') { /* either AM or PM, according to the given time value; noon is treated as PM and midnight as AM */ strcpy(buf, hh <= 11 ? "AM" : "PM"); } else if (*f == 'P') { /* either am or pm, according to the given time value; noon is treated as pm and midnight as am */ strcpy(buf, hh <= 11 ? "am" : "pm"); } else if (*f == 'r') { /* the calendar time using the format %I:%M:%S %p */ sprintf(buf, "%02d:%02d:%02d %s", hh == 0 ? 12 : hh <= 12 ? hh : hh - 12, mm, ss, hh <= 11 ? "AM" : "PM"); } else if (*f == 'R') { /* the hour and minute using the format %H:%M */ sprintf(buf, "%02d:%02d", hh, mm); } else if (*f == 'S') { /* the second as a decimal number (00..59) */ sprintf(buf, "%02d", ss); } else if (*f == 'T') { /* the time of day using the format %H:%M:%S */ sprintf(buf, "%02d:%02d:%02d", hh, mm, ss); } else if (*f == 'u') { /* the day of the week as a decimal number (1..7), Monday being 1 */ sprintf(buf, "%d", weekday(j)); } else if (*f == 'U') { /* the week number of the current year as a decimal number (range 00 through 53), starting with the first Sunday as the first day of the first week; days preceding the first Sunday in the year are considered to be in week 00 */ #if 1 /* 09/I-2009 */ #undef sun /* causes compilation error in SunOS */ #endif int sun; /* sun = the first Sunday of the year */ sun = jday(1, 1, year) - jday(1, 1, 1970); sun += (7 - weekday(sun)); sprintf(buf, "%02d", (j + 7 - sun) / 7); } else if (*f == 'V') { /* the ISO week number as a decimal number (range 01 through 53); ISO weeks start with Monday and end with Sunday; week 01 of a year is the first week which has the majority of its days in that year; week 01 of a year can contain days from the previous year; the week before week 01 of a year is the last week (52 or 53) of the previous year even if it contains days from the new year */ int iso; if (j < firstday(year)) iso = j - firstday(year - 1); else if (j < firstday(year + 1)) iso = j - firstday(year); else iso = j - firstday(year + 1); sprintf(buf, "%02d", iso / 7 + 1); } else if (*f == 'w') { /* the day of the week as a decimal number (0..6), Sunday being 0 */ sprintf(buf, "%d", weekday(j) % 7); } else if (*f == 'W') { /* the week number of the current year as a decimal number (range 00 through 53), starting with the first Monday as the first day of the first week; days preceding the first Monday in the year are considered to be in week 00 */ int mon; /* mon = the first Monday of the year */ mon = jday(1, 1, year) - jday(1, 1, 1970); mon += (8 - weekday(mon)) % 7; sprintf(buf, "%02d", (j + 7 - mon) / 7); } else if (*f == 'y') { /* the year without a century as a decimal number (00..99) */ sprintf(buf, "%02d", year % 100); } else if (*f == 'Y') { /* the year as a decimal number, using the Gregorian calendar */ sprintf(buf, "%04d", year); } else if (*f == '%') { /* a literal % character */ buf[0] = '%', buf[1] = '\0'; } else error2(mpl, fmt, f, "invalid conversion specifier"); } else buf[0] = *f, buf[1] = '\0'; if (len + strlen(buf) > MAX_LENGTH) error(mpl, "time2str; output string length exceeds %d chara" "cters", MAX_LENGTH); memcpy(str+len, buf, strlen(buf)); len += strlen(buf); } str[len] = '\0'; return; } /* eof */ glpk-4.52.1/src/glpmpl06.c0000644000062000006210000007515612175147600014333 0ustar maomkpasswd/* glpmpl06.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_ERRNO #define _GLPSTD_STDIO #include "glpmpl.h" #include "glpsql.h" /**********************************************************************/ #define CSV_FIELD_MAX 50 /* maximal number of fields in record */ #define CSV_FDLEN_MAX 100 /* maximal field length */ struct csv { /* comma-separated values file */ int mode; /* 'R' = reading; 'W' = writing */ char *fname; /* name of csv file */ FILE *fp; /* stream assigned to csv file */ jmp_buf jump; /* address for non-local go to in case of error */ int count; /* record count */ /*--------------------------------------------------------------*/ /* used only for input csv file */ int c; /* current character or EOF */ int what; /* current marker: */ #define CSV_EOF 0 /* end-of-file */ #define CSV_EOR 1 /* end-of-record */ #define CSV_NUM 2 /* floating-point number */ #define CSV_STR 3 /* character string */ char field[CSV_FDLEN_MAX+1]; /* current field just read */ int nf; /* number of fields in the csv file */ int ref[1+CSV_FIELD_MAX]; /* ref[k] = k', if k-th field of the csv file corresponds to k'-th field in the table statement; if ref[k] = 0, k-th field of the csv file is ignored */ #if 1 /* 01/VI-2010 */ int nskip; /* number of comment records preceding the header record */ #endif }; #undef read_char static void read_char(struct csv *csv) { /* read character from csv data file */ int c; xassert(csv->c != EOF); if (csv->c == '\n') csv->count++; loop: c = fgetc(csv->fp); if (ferror(csv->fp)) { xprintf("%s:%d: read error - %s\n", csv->fname, csv->count, strerror(errno)); longjmp(csv->jump, 0); } if (feof(csv->fp)) { if (csv->c == '\n') { csv->count--; c = EOF; } else { xprintf("%s:%d: warning: missing final end-of-line\n", csv->fname, csv->count); c = '\n'; } } else if (c == '\r') goto loop; else if (c == '\n') ; else if (iscntrl(c)) { xprintf("%s:%d: invalid control character 0x%02X\n", csv->fname, csv->count, c); longjmp(csv->jump, 0); } csv->c = c; return; } static void read_field(struct csv *csv) { /* read field from csv data file */ /* check for end of file */ if (csv->c == EOF) { csv->what = CSV_EOF; strcpy(csv->field, "EOF"); goto done; } /* check for end of record */ if (csv->c == '\n') { csv->what = CSV_EOR; strcpy(csv->field, "EOR"); read_char(csv); if (csv->c == ',') err1: { xprintf("%s:%d: empty field not allowed\n", csv->fname, csv->count); longjmp(csv->jump, 0); } if (csv->c == '\n') { xprintf("%s:%d: empty record not allowed\n", csv->fname, csv->count); longjmp(csv->jump, 0); } #if 1 /* 01/VI-2010 */ /* skip comment records; may appear only before the very first record containing field names */ if (csv->c == '#' && csv->count == 1) { while (csv->c == '#') { while (csv->c != '\n') read_char(csv); read_char(csv); csv->nskip++; } } #endif goto done; } /* skip comma before next field */ if (csv->c == ',') read_char(csv); /* read field */ if (csv->c == '\'' || csv->c == '"') { /* read a field enclosed in quotes */ int quote = csv->c, len = 0; csv->what = CSV_STR; /* skip opening quote */ read_char(csv); /* read field characters within quotes */ for (;;) { /* check for closing quote and read it */ if (csv->c == quote) { read_char(csv); if (csv->c == quote) ; else if (csv->c == ',' || csv->c == '\n') break; else { xprintf("%s:%d: invalid field\n", csv->fname, csv->count); longjmp(csv->jump, 0); } } /* check the current field length */ if (len == CSV_FDLEN_MAX) err2: { xprintf("%s:%d: field too long\n", csv->fname, csv->count); longjmp(csv->jump, 0); } /* add the current character to the field */ csv->field[len++] = (char)csv->c; /* read the next character */ read_char(csv); } /* the field has been read */ if (len == 0) goto err1; csv->field[len] = '\0'; } else { /* read a field not enclosed in quotes */ int len = 0; double temp; csv->what = CSV_NUM; while (!(csv->c == ',' || csv->c == '\n')) { /* quotes within the field are not allowed */ if (csv->c == '\'' || csv->c == '"') { xprintf("%s:%d: invalid use of single or double quote wi" "thin field\n", csv->fname, csv->count); longjmp(csv->jump, 0); } /* check the current field length */ if (len == CSV_FDLEN_MAX) goto err2; /* add the current character to the field */ csv->field[len++] = (char)csv->c; /* read the next character */ read_char(csv); } /* the field has been read */ if (len == 0) goto err1; csv->field[len] = '\0'; /* check the field type */ if (str2num(csv->field, &temp)) csv->what = CSV_STR; } done: return; } static struct csv *csv_open_file(TABDCA *dca, int mode) { /* open csv data file */ struct csv *csv; /* create control structure */ csv = xmalloc(sizeof(struct csv)); csv->mode = mode; csv->fname = NULL; csv->fp = NULL; if (setjmp(csv->jump)) goto fail; csv->count = 0; csv->c = '\n'; csv->what = 0; csv->field[0] = '\0'; csv->nf = 0; /* try to open the csv data file */ if (mpl_tab_num_args(dca) < 2) { xprintf("csv_driver: file name not specified\n"); longjmp(csv->jump, 0); } csv->fname = xmalloc(strlen(mpl_tab_get_arg(dca, 2))+1); strcpy(csv->fname, mpl_tab_get_arg(dca, 2)); if (mode == 'R') { /* open the file for reading */ int k; csv->fp = fopen(csv->fname, "r"); if (csv->fp == NULL) { xprintf("csv_driver: unable to open %s - %s\n", csv->fname, strerror(errno)); longjmp(csv->jump, 0); } #if 1 /* 01/VI-2010 */ csv->nskip = 0; #endif /* skip fake new-line */ read_field(csv); xassert(csv->what == CSV_EOR); /* read field names */ xassert(csv->nf == 0); for (;;) { read_field(csv); if (csv->what == CSV_EOR) break; if (csv->what != CSV_STR) { xprintf("%s:%d: invalid field name\n", csv->fname, csv->count); longjmp(csv->jump, 0); } if (csv->nf == CSV_FIELD_MAX) { xprintf("%s:%d: too many fields\n", csv->fname, csv->count); longjmp(csv->jump, 0); } csv->nf++; /* find corresponding field in the table statement */ for (k = mpl_tab_num_flds(dca); k >= 1; k--) { if (strcmp(mpl_tab_get_name(dca, k), csv->field) == 0) break; } csv->ref[csv->nf] = k; } /* find dummy RECNO field in the table statement */ for (k = mpl_tab_num_flds(dca); k >= 1; k--) if (strcmp(mpl_tab_get_name(dca, k), "RECNO") == 0) break; csv->ref[0] = k; } else if (mode == 'W') { /* open the file for writing */ int k, nf; csv->fp = fopen(csv->fname, "w"); if (csv->fp == NULL) { xprintf("csv_driver: unable to create %s - %s\n", csv->fname, strerror(errno)); longjmp(csv->jump, 0); } /* write field names */ nf = mpl_tab_num_flds(dca); for (k = 1; k <= nf; k++) fprintf(csv->fp, "%s%c", mpl_tab_get_name(dca, k), k < nf ? ',' : '\n'); csv->count++; } else xassert(mode != mode); /* the file has been open */ return csv; fail: /* the file cannot be open */ if (csv->fname != NULL) xfree(csv->fname); if (csv->fp != NULL) fclose(csv->fp); xfree(csv); return NULL; } static int csv_read_record(TABDCA *dca, struct csv *csv) { /* read next record from csv data file */ int k, ret = 0; xassert(csv->mode == 'R'); if (setjmp(csv->jump)) { ret = 1; goto done; } /* read dummy RECNO field */ if (csv->ref[0] > 0) #if 0 /* 01/VI-2010 */ mpl_tab_set_num(dca, csv->ref[0], csv->count-1); #else mpl_tab_set_num(dca, csv->ref[0], csv->count-csv->nskip-1); #endif /* read fields */ for (k = 1; k <= csv->nf; k++) { read_field(csv); if (csv->what == CSV_EOF) { /* end-of-file reached */ xassert(k == 1); ret = -1; goto done; } else if (csv->what == CSV_EOR) { /* end-of-record reached */ int lack = csv->nf - k + 1; if (lack == 1) xprintf("%s:%d: one field missing\n", csv->fname, csv->count); else xprintf("%s:%d: %d fields missing\n", csv->fname, csv->count, lack); longjmp(csv->jump, 0); } else if (csv->what == CSV_NUM) { /* floating-point number */ if (csv->ref[k] > 0) { double num; xassert(str2num(csv->field, &num) == 0); mpl_tab_set_num(dca, csv->ref[k], num); } } else if (csv->what == CSV_STR) { /* character string */ if (csv->ref[k] > 0) mpl_tab_set_str(dca, csv->ref[k], csv->field); } else xassert(csv != csv); } /* now there must be NL */ read_field(csv); xassert(csv->what != CSV_EOF); if (csv->what != CSV_EOR) { xprintf("%s:%d: too many fields\n", csv->fname, csv->count); longjmp(csv->jump, 0); } done: return ret; } static int csv_write_record(TABDCA *dca, struct csv *csv) { /* write next record to csv data file */ int k, nf, ret = 0; const char *c; xassert(csv->mode == 'W'); nf = mpl_tab_num_flds(dca); for (k = 1; k <= nf; k++) { switch (mpl_tab_get_type(dca, k)) { case 'N': fprintf(csv->fp, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); break; case 'S': fputc('"', csv->fp); for (c = mpl_tab_get_str(dca, k); *c != '\0'; c++) { if (*c == '"') fputc('"', csv->fp), fputc('"', csv->fp); else fputc(*c, csv->fp); } fputc('"', csv->fp); break; default: xassert(dca != dca); } fputc(k < nf ? ',' : '\n', csv->fp); } csv->count++; if (ferror(csv->fp)) { xprintf("%s:%d: write error - %s\n", csv->fname, csv->count, strerror(errno)); ret = 1; } return ret; } static int csv_close_file(TABDCA *dca, struct csv *csv) { /* close csv data file */ int ret = 0; xassert(dca == dca); if (csv->mode == 'W') { fflush(csv->fp); if (ferror(csv->fp)) { xprintf("%s:%d: write error - %s\n", csv->fname, csv->count, strerror(errno)); ret = 1; } } xfree(csv->fname); fclose(csv->fp); xfree(csv); return ret; } /**********************************************************************/ #define DBF_FIELD_MAX 50 /* maximal number of fields in record */ #define DBF_FDLEN_MAX 100 /* maximal field length */ struct dbf { /* xBASE data file */ int mode; /* 'R' = reading; 'W' = writing */ char *fname; /* name of xBASE file */ FILE *fp; /* stream assigned to xBASE file */ jmp_buf jump; /* address for non-local go to in case of error */ int offset; /* offset of a byte to be read next */ int count; /* record count */ int nf; /* number of fields */ int ref[1+DBF_FIELD_MAX]; /* ref[k] = k', if k-th field of the csv file corresponds to k'-th field in the table statement; if ref[k] = 0, k-th field of the csv file is ignored */ int type[1+DBF_FIELD_MAX]; /* type[k] is type of k-th field */ int len[1+DBF_FIELD_MAX]; /* len[k] is length of k-th field */ int prec[1+DBF_FIELD_MAX]; /* prec[k] is precision of k-th field */ }; static int read_byte(struct dbf *dbf) { /* read byte from xBASE data file */ int b; b = fgetc(dbf->fp); if (ferror(dbf->fp)) { xprintf("%s:0x%X: read error - %s\n", dbf->fname, dbf->offset, strerror(errno)); longjmp(dbf->jump, 0); } if (feof(dbf->fp)) { xprintf("%s:0x%X: unexpected end of file\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } xassert(0x00 <= b && b <= 0xFF); dbf->offset++; return b; } static void read_header(TABDCA *dca, struct dbf *dbf) { /* read xBASE data file header */ int b, j, k, recl; char name[10+1]; /* (ignored) */ for (j = 1; j <= 10; j++) read_byte(dbf); /* length of each record, in bytes */ recl = read_byte(dbf); recl += read_byte(dbf) << 8; /* (ignored) */ for (j = 1; j <= 20; j++) read_byte(dbf); /* field descriptor array */ xassert(dbf->nf == 0); for (;;) { /* check for end of array */ b = read_byte(dbf); if (b == 0x0D) break; if (dbf->nf == DBF_FIELD_MAX) { xprintf("%s:0x%X: too many fields\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } dbf->nf++; /* field name */ name[0] = (char)b; for (j = 1; j < 10; j++) { b = read_byte(dbf); name[j] = (char)b; } name[10] = '\0'; b = read_byte(dbf); if (b != 0x00) { xprintf("%s:0x%X: invalid field name\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } /* find corresponding field in the table statement */ for (k = mpl_tab_num_flds(dca); k >= 1; k--) if (strcmp(mpl_tab_get_name(dca, k), name) == 0) break; dbf->ref[dbf->nf] = k; /* field type */ b = read_byte(dbf); if (!(b == 'C' || b == 'N')) { xprintf("%s:0x%X: invalid field type\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } dbf->type[dbf->nf] = b; /* (ignored) */ for (j = 1; j <= 4; j++) read_byte(dbf); /* field length */ b = read_byte(dbf); if (b == 0) { xprintf("%s:0x%X: invalid field length\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } if (b > DBF_FDLEN_MAX) { xprintf("%s:0x%X: field too long\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } dbf->len[dbf->nf] = b; recl -= b; /* (ignored) */ for (j = 1; j <= 15; j++) read_byte(dbf); } if (recl != 1) { xprintf("%s:0x%X: invalid file header\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } /* find dummy RECNO field in the table statement */ for (k = mpl_tab_num_flds(dca); k >= 1; k--) if (strcmp(mpl_tab_get_name(dca, k), "RECNO") == 0) break; dbf->ref[0] = k; return; } static void parse_third_arg(TABDCA *dca, struct dbf *dbf) { /* parse xBASE file format (third argument) */ int j, k, temp; const char *arg; dbf->nf = mpl_tab_num_flds(dca); arg = mpl_tab_get_arg(dca, 3), j = 0; for (k = 1; k <= dbf->nf; k++) { /* parse specification of k-th field */ if (arg[j] == '\0') { xprintf("xBASE driver: field %s: specification missing\n", mpl_tab_get_name(dca, k)); longjmp(dbf->jump, 0); } /* parse field type */ if (arg[j] == 'C' || arg[j] == 'N') dbf->type[k] = arg[j], j++; else { xprintf("xBASE driver: field %s: invalid field type\n", mpl_tab_get_name(dca, k)); longjmp(dbf->jump, 0); } /* check for left parenthesis */ if (arg[j] == '(') j++; else err: { xprintf("xBASE driver: field %s: invalid field format\n", mpl_tab_get_name(dca, k)); longjmp(dbf->jump, 0); } /* parse field length */ temp = 0; while (isdigit(arg[j])) { if (temp > DBF_FDLEN_MAX) break; temp = 10 * temp + (arg[j] - '0'), j++; } if (!(1 <= temp && temp <= DBF_FDLEN_MAX)) { xprintf("xBASE driver: field %s: invalid field length\n", mpl_tab_get_name(dca, k)); longjmp(dbf->jump, 0); } dbf->len[k] = temp; /* parse optional field precision */ if (dbf->type[k] == 'N' && arg[j] == ',') { j++; temp = 0; while (isdigit(arg[j])) { if (temp > dbf->len[k]) break; temp = 10 * temp + (arg[j] - '0'), j++; } if (temp > dbf->len[k]) { xprintf("xBASE driver: field %s: invalid field precision" "\n", mpl_tab_get_name(dca, k)); longjmp(dbf->jump, 0); } dbf->prec[k] = temp; } else dbf->prec[k] = 0; /* check for right parenthesis */ if (arg[j] == ')') j++; else goto err; } /* ignore other specifications */ return; } static void write_byte(struct dbf *dbf, int b) { /* write byte to xBASE data file */ fputc(b, dbf->fp); dbf->offset++; return; } static void write_header(TABDCA *dca, struct dbf *dbf) { /* write xBASE data file header */ int j, k, temp; const char *name; /* version number */ write_byte(dbf, 0x03 /* file without DBT */); /* date of last update (YYMMDD) */ write_byte(dbf, 70 /* 1970 */); write_byte(dbf, 1 /* January */); write_byte(dbf, 1 /* 1st */); /* number of records (unknown so far) */ for (j = 1; j <= 4; j++) write_byte(dbf, 0xFF); /* length of the header, in bytes */ temp = 32 + dbf->nf * 32 + 1; write_byte(dbf, temp); write_byte(dbf, temp >> 8); /* length of each record, in bytes */ temp = 1; for (k = 1; k <= dbf->nf; k++) temp += dbf->len[k]; write_byte(dbf, temp); write_byte(dbf, temp >> 8); /* (reserved) */ for (j = 1; j <= 20; j++) write_byte(dbf, 0x00); /* field descriptor array */ for (k = 1; k <= dbf->nf; k++) { /* field name (terminated by 0x00) */ name = mpl_tab_get_name(dca, k); for (j = 0; j < 10 && name[j] != '\0'; j++) write_byte(dbf, name[j]); for (j = j; j < 11; j++) write_byte(dbf, 0x00); /* field type */ write_byte(dbf, dbf->type[k]); /* (reserved) */ for (j = 1; j <= 4; j++) write_byte(dbf, 0x00); /* field length */ write_byte(dbf, dbf->len[k]); /* field precision */ write_byte(dbf, dbf->prec[k]); /* (reserved) */ for (j = 1; j <= 14; j++) write_byte(dbf, 0x00); } /* end of header */ write_byte(dbf, 0x0D); return; } static struct dbf *dbf_open_file(TABDCA *dca, int mode) { /* open xBASE data file */ struct dbf *dbf; /* create control structure */ dbf = xmalloc(sizeof(struct dbf)); dbf->mode = mode; dbf->fname = NULL; dbf->fp = NULL; if (setjmp(dbf->jump)) goto fail; dbf->offset = 0; dbf->count = 0; dbf->nf = 0; /* try to open the xBASE data file */ if (mpl_tab_num_args(dca) < 2) { xprintf("xBASE driver: file name not specified\n"); longjmp(dbf->jump, 0); } dbf->fname = xmalloc(strlen(mpl_tab_get_arg(dca, 2))+1); strcpy(dbf->fname, mpl_tab_get_arg(dca, 2)); if (mode == 'R') { /* open the file for reading */ dbf->fp = fopen(dbf->fname, "rb"); if (dbf->fp == NULL) { xprintf("xBASE driver: unable to open %s - %s\n", dbf->fname, strerror(errno)); longjmp(dbf->jump, 0); } read_header(dca, dbf); } else if (mode == 'W') { /* open the file for writing */ if (mpl_tab_num_args(dca) < 3) { xprintf("xBASE driver: file format not specified\n"); longjmp(dbf->jump, 0); } parse_third_arg(dca, dbf); dbf->fp = fopen(dbf->fname, "wb"); if (dbf->fp == NULL) { xprintf("xBASE driver: unable to create %s - %s\n", dbf->fname, strerror(errno)); longjmp(dbf->jump, 0); } write_header(dca, dbf); } else xassert(mode != mode); /* the file has been open */ return dbf; fail: /* the file cannot be open */ if (dbf->fname != NULL) xfree(dbf->fname); if (dbf->fp != NULL) fclose(dbf->fp); xfree(dbf); return NULL; } static int dbf_read_record(TABDCA *dca, struct dbf *dbf) { /* read next record from xBASE data file */ int b, j, k, ret = 0; char buf[DBF_FDLEN_MAX+1]; xassert(dbf->mode == 'R'); if (setjmp(dbf->jump)) { ret = 1; goto done; } /* check record flag */ b = read_byte(dbf); if (b == 0x1A) { /* end of data */ ret = -1; goto done; } if (b != 0x20) { xprintf("%s:0x%X: invalid record flag\n", dbf->fname, dbf->offset); longjmp(dbf->jump, 0); } /* read dummy RECNO field */ if (dbf->ref[0] > 0) mpl_tab_set_num(dca, dbf->ref[0], dbf->count+1); /* read fields */ for (k = 1; k <= dbf->nf; k++) { /* read k-th field */ for (j = 0; j < dbf->len[k]; j++) buf[j] = (char)read_byte(dbf); buf[dbf->len[k]] = '\0'; /* set field value */ if (dbf->type[k] == 'C') { /* character field */ if (dbf->ref[k] > 0) mpl_tab_set_str(dca, dbf->ref[k], strtrim(buf)); } else if (dbf->type[k] == 'N') { /* numeric field */ if (dbf->ref[k] > 0) { double num; strspx(buf); xassert(str2num(buf, &num) == 0); mpl_tab_set_num(dca, dbf->ref[k], num); } } else xassert(dbf != dbf); } /* increase record count */ dbf->count++; done: return ret; } static int dbf_write_record(TABDCA *dca, struct dbf *dbf) { /* write next record to xBASE data file */ int j, k, ret = 0; char buf[255+1]; xassert(dbf->mode == 'W'); if (setjmp(dbf->jump)) { ret = 1; goto done; } /* record flag */ write_byte(dbf, 0x20); xassert(dbf->nf == mpl_tab_num_flds(dca)); for (k = 1; k <= dbf->nf; k++) { if (dbf->type[k] == 'C') { /* character field */ const char *str; if (mpl_tab_get_type(dca, k) == 'N') { sprintf(buf, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); str = buf; } else if (mpl_tab_get_type(dca, k) == 'S') str = mpl_tab_get_str(dca, k); else xassert(dca != dca); if ((int)strlen(str) > dbf->len[k]) { xprintf("xBASE driver: field %s: cannot convert %.15s..." " to field format\n", mpl_tab_get_name(dca, k), str); longjmp(dbf->jump, 0); } for (j = 0; j < dbf->len[k] && str[j] != '\0'; j++) write_byte(dbf, str[j]); for (j = j; j < dbf->len[k]; j++) write_byte(dbf, ' '); } else if (dbf->type[k] == 'N') { /* numeric field */ double num = mpl_tab_get_num(dca, k); if (fabs(num) > 1e20) err: { xprintf("xBASE driver: field %s: cannot convert %g to fi" "eld format\n", mpl_tab_get_name(dca, k), num); longjmp(dbf->jump, 0); } sprintf(buf, "%*.*f", dbf->len[k], dbf->prec[k], num); xassert(strlen(buf) < sizeof(buf)); if ((int)strlen(buf) != dbf->len[k]) goto err; for (j = 0; j < dbf->len[k]; j++) write_byte(dbf, buf[j]); } else xassert(dbf != dbf); } /* increase record count */ dbf->count++; done: return ret; } static int dbf_close_file(TABDCA *dca, struct dbf *dbf) { /* close xBASE data file */ int ret = 0; xassert(dca == dca); if (dbf->mode == 'W') { if (setjmp(dbf->jump)) { ret = 1; goto skip; } /* end-of-file flag */ write_byte(dbf, 0x1A); /* number of records */ dbf->offset = 4; if (fseek(dbf->fp, dbf->offset, SEEK_SET)) { xprintf("%s:0x%X: seek error - %s\n", dbf->fname, dbf->offset, strerror(errno)); longjmp(dbf->jump, 0); } write_byte(dbf, dbf->count); write_byte(dbf, dbf->count >> 8); write_byte(dbf, dbf->count >> 16); write_byte(dbf, dbf->count >> 24); fflush(dbf->fp); if (ferror(dbf->fp)) { xprintf("%s:0x%X: write error - %s\n", dbf->fname, dbf->offset, strerror(errno)); longjmp(dbf->jump, 0); } skip: ; } xfree(dbf->fname); fclose(dbf->fp); xfree(dbf); return ret; } /**********************************************************************/ #define TAB_CSV 1 #define TAB_XBASE 2 #define TAB_ODBC 3 #define TAB_MYSQL 4 void mpl_tab_drv_open(MPL *mpl, int mode) { TABDCA *dca = mpl->dca; xassert(dca->id == 0); xassert(dca->link == NULL); xassert(dca->na >= 1); if (strcmp(dca->arg[1], "CSV") == 0) { dca->id = TAB_CSV; dca->link = csv_open_file(dca, mode); } else if (strcmp(dca->arg[1], "xBASE") == 0) { dca->id = TAB_XBASE; dca->link = dbf_open_file(dca, mode); } else if (strcmp(dca->arg[1], "ODBC") == 0 || strcmp(dca->arg[1], "iODBC") == 0) { dca->id = TAB_ODBC; dca->link = db_iodbc_open(dca, mode); } else if (strcmp(dca->arg[1], "MySQL") == 0) { dca->id = TAB_MYSQL; dca->link = db_mysql_open(dca, mode); } else xprintf("Invalid table driver `%s'\n", dca->arg[1]); if (dca->link == NULL) error(mpl, "error on opening table %s", mpl->stmt->u.tab->name); return; } int mpl_tab_drv_read(MPL *mpl) { TABDCA *dca = mpl->dca; int ret; switch (dca->id) { case TAB_CSV: ret = csv_read_record(dca, dca->link); break; case TAB_XBASE: ret = dbf_read_record(dca, dca->link); break; case TAB_ODBC: ret = db_iodbc_read(dca, dca->link); break; case TAB_MYSQL: ret = db_mysql_read(dca, dca->link); break; default: xassert(dca != dca); } if (ret > 0) error(mpl, "error on reading data from table %s", mpl->stmt->u.tab->name); return ret; } void mpl_tab_drv_write(MPL *mpl) { TABDCA *dca = mpl->dca; int ret; switch (dca->id) { case TAB_CSV: ret = csv_write_record(dca, dca->link); break; case TAB_XBASE: ret = dbf_write_record(dca, dca->link); break; case TAB_ODBC: ret = db_iodbc_write(dca, dca->link); break; case TAB_MYSQL: ret = db_mysql_write(dca, dca->link); break; default: xassert(dca != dca); } if (ret) error(mpl, "error on writing data to table %s", mpl->stmt->u.tab->name); return; } void mpl_tab_drv_close(MPL *mpl) { TABDCA *dca = mpl->dca; int ret; switch (dca->id) { case TAB_CSV: ret = csv_close_file(dca, dca->link); break; case TAB_XBASE: ret = dbf_close_file(dca, dca->link); break; case TAB_ODBC: ret = db_iodbc_close(dca, dca->link); break; case TAB_MYSQL: ret = db_mysql_close(dca, dca->link); break; default: xassert(dca != dca); } dca->id = 0; dca->link = NULL; if (ret) error(mpl, "error on closing table %s", mpl->stmt->u.tab->name); return; } /* eof */ glpk-4.52.1/src/glpmps.c0000644000062000006210000013374112175147600014167 0ustar maomkpasswd/* glpmps.c (MPS format routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #if 1 /* 11/VI-2013 */ #include "env2.h" #endif #include "glpapi.h" #include "glplib.h" /*********************************************************************** * NAME * * glp_init_mpscp - initialize MPS format control parameters * * SYNOPSIS * * void glp_init_mpscp(glp_mpscp *parm); * * DESCRIPTION * * The routine glp_init_mpscp initializes control parameters, which are * used by the MPS input/output routines glp_read_mps and glp_write_mps, * with default values. * * Default values of the control parameters are stored in the glp_mpscp * structure, which the parameter parm points to. */ void glp_init_mpscp(glp_mpscp *parm) { parm->blank = '\0'; parm->obj_name = NULL; parm->tol_mps = 1e-12; return; } static void check_parm(const char *func, const glp_mpscp *parm) { /* check control parameters */ if (!(0x00 <= parm->blank && parm->blank <= 0xFF) || !(parm->blank == '\0' || isprint(parm->blank))) xerror("%s: blank = 0x%02X; invalid parameter\n", func, parm->blank); if (!(parm->obj_name == NULL || strlen(parm->obj_name) <= 255)) xerror("%s: obj_name = \"%.12s...\"; parameter too long\n", func, parm->obj_name); if (!(0.0 <= parm->tol_mps && parm->tol_mps < 1.0)) xerror("%s: tol_mps = %g; invalid parameter\n", func, parm->tol_mps); return; } /*********************************************************************** * NAME * * glp_read_mps - read problem data in MPS format * * SYNOPSIS * * int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, * const char *fname); * * DESCRIPTION * * The routine glp_read_mps reads problem data in MPS format from a * text file. * * The parameter fmt specifies the version of MPS format: * * GLP_MPS_DECK - fixed (ancient) MPS format; * GLP_MPS_FILE - free (modern) MPS format. * * The parameter parm is a pointer to the structure glp_mpscp, which * specifies control parameters used by the routine. If parm is NULL, * the routine uses default settings. * * The character string fname specifies a name of the text file to be * read. * * Note that before reading data the current content of the problem * object is completely erased with the routine glp_erase_prob. * * RETURNS * * If the operation was successful, the routine glp_read_mps returns * zero. Otherwise, it prints an error message and returns non-zero. */ struct csa { /* common storage area */ glp_prob *P; /* pointer to problem object */ int deck; /* MPS format (0 - free, 1 - fixed) */ const glp_mpscp *parm; /* pointer to control parameters */ const char *fname; /* name of input MPS file */ XFILE *fp; /* stream assigned to input MPS file */ jmp_buf jump; /* label for go to in case of error */ int recno; /* current record (card) number */ int recpos; /* current record (card) position */ int c; /* current character */ int fldno; /* current field number */ char field[255+1]; /* current field content */ int w80; /* warning 'record must not be longer than 80 chars' issued */ int wef; /* warning 'extra fields detected beyond field 6' issued */ int obj_row; /* objective row number */ void *work1, *work2, *work3; /* working arrays */ }; static void error(struct csa *csa, const char *fmt, ...) { /* print error message and terminate processing */ va_list arg; xprintf("%s:%d: ", csa->fname, csa->recno); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); longjmp(csa->jump, 1); /* no return */ } static void warning(struct csa *csa, const char *fmt, ...) { /* print warning message and continue processing */ va_list arg; xprintf("%s:%d: warning: ", csa->fname, csa->recno); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); return; } static void read_char(struct csa *csa) { /* read next character */ int c; if (csa->c == '\n') csa->recno++, csa->recpos = 0; csa->recpos++; read: c = xfgetc(csa->fp); if (c < 0) { if (xferror(csa->fp)) error(csa, "read error - %s\n", xerrmsg()); else if (csa->c == '\n') error(csa, "unexpected end of file\n"); else { warning(csa, "missing final end of line\n"); c = '\n'; } } else if (c == '\n') ; else if (csa->c == '\r') { c = '\r'; goto badc; } else if (csa->deck && c == '\r') { csa->c = '\r'; goto read; } else if (c == ' ') ; else if (isspace(c)) { if (csa->deck) badc: error(csa, "in fixed MPS format white-space character 0x%02" "X is not allowed\n", c); c = ' '; } else if (iscntrl(c)) error(csa, "invalid control character 0x%02X\n", c); if (csa->deck && csa->recpos == 81 && c != '\n' && csa->w80 < 1) { warning(csa, "in fixed MPS format record must not be longer th" "an 80 characters\n"); csa->w80++; } csa->c = c; return; } static int indicator(struct csa *csa, int name) { /* skip comment records and read possible indicator record */ int ret; /* reset current field number */ csa->fldno = 0; loop: /* read the very first character of the next record */ xassert(csa->c == '\n'); read_char(csa); if (csa->c == ' ' || csa->c == '\n') { /* data record */ ret = 0; } else if (csa->c == '*') { /* comment record */ while (csa->c != '\n') read_char(csa); goto loop; } else { /* indicator record */ int len = 0; while (csa->c != ' ' && csa->c != '\n' && len < 12) { csa->field[len++] = (char)csa->c; read_char(csa); } csa->field[len] = '\0'; if (!(strcmp(csa->field, "NAME") == 0 || strcmp(csa->field, "ROWS") == 0 || strcmp(csa->field, "COLUMNS") == 0 || strcmp(csa->field, "RHS") == 0 || strcmp(csa->field, "RANGES") == 0 || strcmp(csa->field, "BOUNDS") == 0 || strcmp(csa->field, "ENDATA") == 0)) error(csa, "invalid indicator record\n"); if (!name) { while (csa->c != '\n') read_char(csa); } ret = 1; } return ret; } static void read_field(struct csa *csa) { /* read next field of the current data record */ csa->fldno++; if (csa->deck) { /* fixed MPS format */ int beg, end, pos; /* determine predefined field positions */ if (csa->fldno == 1) beg = 2, end = 3; else if (csa->fldno == 2) beg = 5, end = 12; else if (csa->fldno == 3) beg = 15, end = 22; else if (csa->fldno == 4) beg = 25, end = 36; else if (csa->fldno == 5) beg = 40, end = 47; else if (csa->fldno == 6) beg = 50, end = 61; else xassert(csa != csa); /* skip blanks preceding the current field */ if (csa->c != '\n') { pos = csa->recpos; while (csa->recpos < beg) { if (csa->c == ' ') ; else if (csa->c == '\n') break; else error(csa, "in fixed MPS format positions %d-%d must " "be blank\n", pos, beg-1); read_char(csa); } } /* skip possible comment beginning in the field 3 or 5 */ if ((csa->fldno == 3 || csa->fldno == 5) && csa->c == '$') { while (csa->c != '\n') read_char(csa); } /* read the current field */ for (pos = beg; pos <= end; pos++) { if (csa->c == '\n') break; csa->field[pos-beg] = (char)csa->c; read_char(csa); } csa->field[pos-beg] = '\0'; strtrim(csa->field); /* skip blanks following the last field */ if (csa->fldno == 6 && csa->c != '\n') { while (csa->recpos <= 72) { if (csa->c == ' ') ; else if (csa->c == '\n') break; else error(csa, "in fixed MPS format positions 62-72 must " "be blank\n"); read_char(csa); } while (csa->c != '\n') read_char(csa); } } else { /* free MPS format */ int len; /* skip blanks preceding the current field */ while (csa->c == ' ') read_char(csa); /* skip possible comment */ if (csa->c == '$') { while (csa->c != '\n') read_char(csa); } /* read the current field */ len = 0; while (!(csa->c == ' ' || csa->c == '\n')) { if (len == 255) error(csa, "length of field %d exceeds 255 characters\n", csa->fldno++); csa->field[len++] = (char)csa->c; read_char(csa); } csa->field[len] = '\0'; /* skip anything following the last field (any extra fields are considered to be comments) */ if (csa->fldno == 6) { while (csa->c == ' ') read_char(csa); if (csa->c != '$' && csa->c != '\n' && csa->wef < 1) { warning(csa, "some extra field(s) detected beyond field " "6; field(s) ignored\n"); csa->wef++; } while (csa->c != '\n') read_char(csa); } } return; } static void patch_name(struct csa *csa, char *name) { /* process embedded blanks in symbolic name */ int blank = csa->parm->blank; if (blank == '\0') { /* remove emedded blanks */ strspx(name); } else { /* replace embedded blanks by specified character */ for (; *name != '\0'; name++) if (*name == ' ') *name = (char)blank; } return; } static double read_number(struct csa *csa) { /* read next field and convert it to floating-point number */ double x; char *s; /* read next field */ read_field(csa); xassert(csa->fldno == 4 || csa->fldno == 6); if (csa->field[0] == '\0') error(csa, "missing numeric value in field %d\n", csa->fldno); /* skip initial spaces of the field */ for (s = csa->field; *s == ' '; s++); /* perform conversion */ if (str2num(s, &x) != 0) error(csa, "cannot convert `%s' to floating-point number\n", s); return x; } static void skip_field(struct csa *csa) { /* read and skip next field (assumed to be blank) */ read_field(csa); if (csa->field[0] != '\0') error(csa, "field %d must be blank\n", csa->fldno); return; } static void read_name(struct csa *csa) { /* read NAME indicator record */ if (!(indicator(csa, 1) && strcmp(csa->field, "NAME") == 0)) error(csa, "missing NAME indicator record\n"); /* this indicator record looks like a data record; simulate that fields 1 and 2 were read */ csa->fldno = 2; /* field 3: model name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') warning(csa, "missing model name in field 3\n"); else glp_set_prob_name(csa->P, csa->field); /* skip anything following field 3 */ while (csa->c != '\n') read_char(csa); return; } static void read_rows(struct csa *csa) { /* read ROWS section */ int i, type; loop: if (indicator(csa, 0)) goto done; /* field 1: row type */ read_field(csa), strspx(csa->field); if (strcmp(csa->field, "N") == 0) type = GLP_FR; else if (strcmp(csa->field, "G") == 0) type = GLP_LO; else if (strcmp(csa->field, "L") == 0) type = GLP_UP; else if (strcmp(csa->field, "E") == 0) type = GLP_FX; else if (csa->field[0] == '\0') error(csa, "missing row type in field 1\n"); else error(csa, "invalid row type in field 1\n"); /* field 2: row name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') error(csa, "missing row name in field 2\n"); if (glp_find_row(csa->P, csa->field) != 0) error(csa, "row `%s' multiply specified\n", csa->field); i = glp_add_rows(csa->P, 1); glp_set_row_name(csa->P, i, csa->field); glp_set_row_bnds(csa->P, i, type, 0.0, 0.0); /* fields 3, 4, 5, and 6 must be blank */ skip_field(csa); skip_field(csa); skip_field(csa); skip_field(csa); goto loop; done: return; } static void read_columns(struct csa *csa) { /* read COLUMNS section */ int i, j, f, len, kind = GLP_CV, *ind; double aij, *val; char name[255+1], *flag; /* allocate working arrays */ csa->work1 = ind = xcalloc(1+csa->P->m, sizeof(int)); csa->work2 = val = xcalloc(1+csa->P->m, sizeof(double)); csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); memset(&flag[1], 0, csa->P->m); /* no current column exists */ j = 0, len = 0; loop: if (indicator(csa, 0)) goto done; /* field 1 must be blank */ if (csa->deck) { read_field(csa); if (csa->field[0] != '\0') error(csa, "field 1 must be blank\n"); } else csa->fldno++; /* field 2: column or kind name */ read_field(csa), patch_name(csa, csa->field); strcpy(name, csa->field); /* field 3: row name or keyword 'MARKER' */ read_field(csa), patch_name(csa, csa->field); if (strcmp(csa->field, "'MARKER'") == 0) { /* process kind data record */ /* field 4 must be blank */ if (csa->deck) { read_field(csa); if (csa->field[0] != '\0') error(csa, "field 4 must be blank\n"); } else csa->fldno++; /* field 5: keyword 'INTORG' or 'INTEND' */ read_field(csa), patch_name(csa, csa->field); if (strcmp(csa->field, "'INTORG'") == 0) kind = GLP_IV; else if (strcmp(csa->field, "'INTEND'") == 0) kind = GLP_CV; else if (csa->field[0] == '\0') error(csa, "missing keyword in field 5\n"); else error(csa, "invalid keyword in field 5\n"); /* field 6 must be blank */ skip_field(csa); goto loop; } /* process column name specified in field 2 */ if (name[0] == '\0') { /* the same column as in previous data record */ if (j == 0) error(csa, "missing column name in field 2\n"); } else if (j != 0 && strcmp(name, csa->P->col[j]->name) == 0) { /* the same column as in previous data record */ xassert(j != 0); } else { /* store the current column */ if (j != 0) { glp_set_mat_col(csa->P, j, len, ind, val); while (len > 0) flag[ind[len--]] = 0; } /* create new column */ if (glp_find_col(csa->P, name) != 0) error(csa, "column `%s' multiply specified\n", name); j = glp_add_cols(csa->P, 1); glp_set_col_name(csa->P, j, name); glp_set_col_kind(csa->P, j, kind); if (kind == GLP_CV) glp_set_col_bnds(csa->P, j, GLP_LO, 0.0, 0.0); else if (kind == GLP_IV) glp_set_col_bnds(csa->P, j, GLP_DB, 0.0, 1.0); else xassert(kind != kind); } /* process fields 3-4 and 5-6 */ for (f = 3; f <= 5; f += 2) { /* field 3 or 5: row name */ if (f == 3) { if (csa->field[0] == '\0') error(csa, "missing row name in field 3\n"); } else { read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') { /* if field 5 is blank, field 6 also must be blank */ skip_field(csa); continue; } } i = glp_find_row(csa->P, csa->field); if (i == 0) error(csa, "row `%s' not found\n", csa->field); if (flag[i]) error(csa, "duplicate coefficient in row `%s'\n", csa->field); /* field 4 or 6: coefficient value */ aij = read_number(csa); if (fabs(aij) < csa->parm->tol_mps) aij = 0.0; len++, ind[len] = i, val[len] = aij, flag[i] = 1; } goto loop; done: /* store the last column */ if (j != 0) glp_set_mat_col(csa->P, j, len, ind, val); /* free working arrays */ xfree(ind); xfree(val); xfree(flag); csa->work1 = csa->work2 = csa->work3 = NULL; return; } static void read_rhs(struct csa *csa) { /* read RHS section */ int i, f, v, type; double rhs; char name[255+1], *flag; /* allocate working array */ csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); memset(&flag[1], 0, csa->P->m); /* no current RHS vector exists */ v = 0; loop: if (indicator(csa, 0)) goto done; /* field 1 must be blank */ if (csa->deck) { read_field(csa); if (csa->field[0] != '\0') error(csa, "field 1 must be blank\n"); } else csa->fldno++; /* field 2: RHS vector name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') { /* the same RHS vector as in previous data record */ if (v == 0) { warning(csa, "missing RHS vector name in field 2\n"); goto blnk; } } else if (v != 0 && strcmp(csa->field, name) == 0) { /* the same RHS vector as in previous data record */ xassert(v != 0); } else blnk: { /* new RHS vector */ if (v != 0) error(csa, "multiple RHS vectors not supported\n"); v++; strcpy(name, csa->field); } /* process fields 3-4 and 5-6 */ for (f = 3; f <= 5; f += 2) { /* field 3 or 5: row name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') { if (f == 3) error(csa, "missing row name in field 3\n"); else { /* if field 5 is blank, field 6 also must be blank */ skip_field(csa); continue; } } i = glp_find_row(csa->P, csa->field); if (i == 0) error(csa, "row `%s' not found\n", csa->field); if (flag[i]) error(csa, "duplicate right-hand side for row `%s'\n", csa->field); /* field 4 or 6: right-hand side value */ rhs = read_number(csa); if (fabs(rhs) < csa->parm->tol_mps) rhs = 0.0; type = csa->P->row[i]->type; if (type == GLP_FR) { if (i == csa->obj_row) glp_set_obj_coef(csa->P, 0, rhs); else if (rhs != 0.0) warning(csa, "non-zero right-hand side for free row `%s'" " ignored\n", csa->P->row[i]->name); } else glp_set_row_bnds(csa->P, i, type, rhs, rhs); flag[i] = 1; } goto loop; done: /* free working array */ xfree(flag); csa->work3 = NULL; return; } static void read_ranges(struct csa *csa) { /* read RANGES section */ int i, f, v, type; double rhs, rng; char name[255+1], *flag; /* allocate working array */ csa->work3 = flag = xcalloc(1+csa->P->m, sizeof(char)); memset(&flag[1], 0, csa->P->m); /* no current RANGES vector exists */ v = 0; loop: if (indicator(csa, 0)) goto done; /* field 1 must be blank */ if (csa->deck) { read_field(csa); if (csa->field[0] != '\0') error(csa, "field 1 must be blank\n"); } else csa->fldno++; /* field 2: RANGES vector name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') { /* the same RANGES vector as in previous data record */ if (v == 0) { warning(csa, "missing RANGES vector name in field 2\n"); goto blnk; } } else if (v != 0 && strcmp(csa->field, name) == 0) { /* the same RANGES vector as in previous data record */ xassert(v != 0); } else blnk: { /* new RANGES vector */ if (v != 0) error(csa, "multiple RANGES vectors not supported\n"); v++; strcpy(name, csa->field); } /* process fields 3-4 and 5-6 */ for (f = 3; f <= 5; f += 2) { /* field 3 or 5: row name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') { if (f == 3) error(csa, "missing row name in field 3\n"); else { /* if field 5 is blank, field 6 also must be blank */ skip_field(csa); continue; } } i = glp_find_row(csa->P, csa->field); if (i == 0) error(csa, "row `%s' not found\n", csa->field); if (flag[i]) error(csa, "duplicate range for row `%s'\n", csa->field); /* field 4 or 6: range value */ rng = read_number(csa); if (fabs(rng) < csa->parm->tol_mps) rng = 0.0; type = csa->P->row[i]->type; if (type == GLP_FR) warning(csa, "range for free row `%s' ignored\n", csa->P->row[i]->name); else if (type == GLP_LO) { rhs = csa->P->row[i]->lb; glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB, rhs, rhs + fabs(rng)); } else if (type == GLP_UP) { rhs = csa->P->row[i]->ub; glp_set_row_bnds(csa->P, i, rhs == 0.0 ? GLP_FX : GLP_DB, rhs - fabs(rng), rhs); } else if (type == GLP_FX) { rhs = csa->P->row[i]->lb; if (rng > 0.0) glp_set_row_bnds(csa->P, i, GLP_DB, rhs, rhs + rng); else if (rng < 0.0) glp_set_row_bnds(csa->P, i, GLP_DB, rhs + rng, rhs); } else xassert(type != type); flag[i] = 1; } goto loop; done: /* free working array */ xfree(flag); csa->work3 = NULL; return; } static void read_bounds(struct csa *csa) { /* read BOUNDS section */ GLPCOL *col; int j, v, mask, data; double bnd, lb, ub; char type[2+1], name[255+1], *flag; /* allocate working array */ csa->work3 = flag = xcalloc(1+csa->P->n, sizeof(char)); memset(&flag[1], 0, csa->P->n); /* no current BOUNDS vector exists */ v = 0; loop: if (indicator(csa, 0)) goto done; /* field 1: bound type */ read_field(csa); if (strcmp(csa->field, "LO") == 0) mask = 0x01, data = 1; else if (strcmp(csa->field, "UP") == 0) mask = 0x10, data = 1; else if (strcmp(csa->field, "FX") == 0) mask = 0x11, data = 1; else if (strcmp(csa->field, "FR") == 0) mask = 0x11, data = 0; else if (strcmp(csa->field, "MI") == 0) mask = 0x01, data = 0; else if (strcmp(csa->field, "PL") == 0) mask = 0x10, data = 0; else if (strcmp(csa->field, "LI") == 0) mask = 0x01, data = 1; else if (strcmp(csa->field, "UI") == 0) mask = 0x10, data = 1; else if (strcmp(csa->field, "BV") == 0) mask = 0x11, data = 0; else if (csa->field[0] == '\0') error(csa, "missing bound type in field 1\n"); else error(csa, "invalid bound type in field 1\n"); strcpy(type, csa->field); /* field 2: BOUNDS vector name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') { /* the same BOUNDS vector as in previous data record */ if (v == 0) { warning(csa, "missing BOUNDS vector name in field 2\n"); goto blnk; } } else if (v != 0 && strcmp(csa->field, name) == 0) { /* the same BOUNDS vector as in previous data record */ xassert(v != 0); } else blnk: { /* new BOUNDS vector */ if (v != 0) error(csa, "multiple BOUNDS vectors not supported\n"); v++; strcpy(name, csa->field); } /* field 3: column name */ read_field(csa), patch_name(csa, csa->field); if (csa->field[0] == '\0') error(csa, "missing column name in field 3\n"); j = glp_find_col(csa->P, csa->field); if (j == 0) error(csa, "column `%s' not found\n", csa->field); if ((flag[j] & mask) == 0x01) error(csa, "duplicate lower bound for column `%s'\n", csa->field); if ((flag[j] & mask) == 0x10) error(csa, "duplicate upper bound for column `%s'\n", csa->field); xassert((flag[j] & mask) == 0x00); /* field 4: bound value */ if (data) { bnd = read_number(csa); if (fabs(bnd) < csa->parm->tol_mps) bnd = 0.0; } else read_field(csa), bnd = 0.0; /* get current column bounds */ col = csa->P->col[j]; if (col->type == GLP_FR) lb = -DBL_MAX, ub = +DBL_MAX; else if (col->type == GLP_LO) lb = col->lb, ub = +DBL_MAX; else if (col->type == GLP_UP) lb = -DBL_MAX, ub = col->ub; else if (col->type == GLP_DB) lb = col->lb, ub = col->ub; else if (col->type == GLP_FX) lb = ub = col->lb; else xassert(col != col); /* change column bounds */ if (strcmp(type, "LO") == 0) lb = bnd; else if (strcmp(type, "UP") == 0) ub = bnd; else if (strcmp(type, "FX") == 0) lb = ub = bnd; else if (strcmp(type, "FR") == 0) lb = -DBL_MAX, ub = +DBL_MAX; else if (strcmp(type, "MI") == 0) lb = -DBL_MAX; else if (strcmp(type, "PL") == 0) ub = +DBL_MAX; else if (strcmp(type, "LI") == 0) { glp_set_col_kind(csa->P, j, GLP_IV); lb = ceil(bnd); #if 1 /* 16/VII-2013 */ /* if column upper bound has not been explicitly specified, take it as +inf */ if (!(flag[j] & 0x10)) ub = +DBL_MAX; #endif } else if (strcmp(type, "UI") == 0) { glp_set_col_kind(csa->P, j, GLP_IV); ub = floor(bnd); } else if (strcmp(type, "BV") == 0) { glp_set_col_kind(csa->P, j, GLP_IV); lb = 0.0, ub = 1.0; } else xassert(type != type); /* set new column bounds */ if (lb == -DBL_MAX && ub == +DBL_MAX) glp_set_col_bnds(csa->P, j, GLP_FR, lb, ub); else if (ub == +DBL_MAX) glp_set_col_bnds(csa->P, j, GLP_LO, lb, ub); else if (lb == -DBL_MAX) glp_set_col_bnds(csa->P, j, GLP_UP, lb, ub); else if (lb != ub) glp_set_col_bnds(csa->P, j, GLP_DB, lb, ub); else glp_set_col_bnds(csa->P, j, GLP_FX, lb, ub); flag[j] |= (char)mask; /* fields 5 and 6 must be blank */ skip_field(csa); skip_field(csa); goto loop; done: /* free working array */ xfree(flag); csa->work3 = NULL; return; } int glp_read_mps(glp_prob *P, int fmt, const glp_mpscp *parm, const char *fname) { /* read problem data in MPS format */ glp_mpscp _parm; struct csa _csa, *csa = &_csa; int ret; xprintf("Reading problem data from `%s'...\n", fname); if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) xerror("glp_read_mps: fmt = %d; invalid parameter\n", fmt); if (parm == NULL) glp_init_mpscp(&_parm), parm = &_parm; /* check control parameters */ check_parm("glp_read_mps", parm); /* initialize common storage area */ csa->P = P; csa->deck = (fmt == GLP_MPS_DECK); csa->parm = parm; csa->fname = fname; csa->fp = NULL; if (setjmp(csa->jump)) { ret = 1; goto done; } csa->recno = csa->recpos = 0; csa->c = '\n'; csa->fldno = 0; csa->field[0] = '\0'; csa->w80 = csa->wef = 0; csa->obj_row = 0; csa->work1 = csa->work2 = csa->work3 = NULL; /* erase problem object */ glp_erase_prob(P); glp_create_index(P); /* open input MPS file */ csa->fp = xfopen(fname, "r"); if (csa->fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* read NAME indicator record */ read_name(csa); if (P->name != NULL) xprintf("Problem: %s\n", P->name); /* read ROWS section */ if (!(indicator(csa, 0) && strcmp(csa->field, "ROWS") == 0)) error(csa, "missing ROWS indicator record\n"); read_rows(csa); /* determine objective row */ if (parm->obj_name == NULL || parm->obj_name[0] == '\0') { /* use the first row of N type */ int i; for (i = 1; i <= P->m; i++) { if (P->row[i]->type == GLP_FR) { csa->obj_row = i; break; } } if (csa->obj_row == 0) warning(csa, "unable to determine objective row\n"); } else { /* use a row with specified name */ int i; for (i = 1; i <= P->m; i++) { xassert(P->row[i]->name != NULL); if (strcmp(parm->obj_name, P->row[i]->name) == 0) { csa->obj_row = i; break; } } if (csa->obj_row == 0) error(csa, "objective row `%s' not found\n", parm->obj_name); } if (csa->obj_row != 0) { glp_set_obj_name(P, P->row[csa->obj_row]->name); xprintf("Objective: %s\n", P->obj); } /* read COLUMNS section */ if (strcmp(csa->field, "COLUMNS") != 0) error(csa, "missing COLUMNS indicator record\n"); read_columns(csa); /* set objective coefficients */ if (csa->obj_row != 0) { GLPAIJ *aij; for (aij = P->row[csa->obj_row]->ptr; aij != NULL; aij = aij->r_next) glp_set_obj_coef(P, aij->col->j, aij->val); } /* read optional RHS section */ if (strcmp(csa->field, "RHS") == 0) read_rhs(csa); /* read optional RANGES section */ if (strcmp(csa->field, "RANGES") == 0) read_ranges(csa); /* read optional BOUNDS section */ if (strcmp(csa->field, "BOUNDS") == 0) read_bounds(csa); /* read ENDATA indicator record */ if (strcmp(csa->field, "ENDATA") != 0) error(csa, "invalid use of %s indicator record\n", csa->field); /* print some statistics */ xprintf("%d row%s, %d column%s, %d non-zero%s\n", P->m, P->m == 1 ? "" : "s", P->n, P->n == 1 ? "" : "s", P->nnz, P->nnz == 1 ? "" : "s"); if (glp_get_num_int(P) > 0) { int ni = glp_get_num_int(P); int nb = glp_get_num_bin(P); if (ni == 1) { if (nb == 0) xprintf("One variable is integer\n"); else xprintf("One variable is binary\n"); } else { xprintf("%d integer variables, ", ni); if (nb == 0) xprintf("none"); else if (nb == 1) xprintf("one"); else if (nb == ni) xprintf("all"); else xprintf("%d", nb); xprintf(" of which %s binary\n", nb == 1 ? "is" : "are"); } } xprintf("%d records were read\n", csa->recno); /* problem data has been successfully read */ glp_delete_index(P); glp_sort_matrix(P); ret = 0; done: if (csa->fp != NULL) xfclose(csa->fp); if (csa->work1 != NULL) xfree(csa->work1); if (csa->work2 != NULL) xfree(csa->work2); if (csa->work3 != NULL) xfree(csa->work3); if (ret != 0) glp_erase_prob(P); return ret; } /*********************************************************************** * NAME * * glp_write_mps - write problem data in MPS format * * SYNOPSIS * * int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, * const char *fname); * * DESCRIPTION * * The routine glp_write_mps writes problem data in MPS format to a * text file. * * The parameter fmt specifies the version of MPS format: * * GLP_MPS_DECK - fixed (ancient) MPS format; * GLP_MPS_FILE - free (modern) MPS format. * * The parameter parm is a pointer to the structure glp_mpscp, which * specifies control parameters used by the routine. If parm is NULL, * the routine uses default settings. * * The character string fname specifies a name of the text file to be * written. * * RETURNS * * If the operation was successful, the routine glp_read_mps returns * zero. Otherwise, it prints an error message and returns non-zero. */ #define csa csa1 struct csa { /* common storage area */ glp_prob *P; /* pointer to problem object */ int deck; /* MPS format (0 - free, 1 - fixed) */ const glp_mpscp *parm; /* pointer to control parameters */ char field[255+1]; /* field buffer */ }; static char *mps_name(struct csa *csa) { /* make problem name */ char *f; if (csa->P->name == NULL) csa->field[0] = '\0'; else if (csa->deck) { strncpy(csa->field, csa->P->name, 8); csa->field[8] = '\0'; } else strcpy(csa->field, csa->P->name); for (f = csa->field; *f != '\0'; f++) if (*f == ' ') *f = '_'; return csa->field; } static char *row_name(struct csa *csa, int i) { /* make i-th row name */ char *f; xassert(0 <= i && i <= csa->P->m); if (i == 0 || csa->P->row[i]->name == NULL || csa->deck && strlen(csa->P->row[i]->name) > 8) sprintf(csa->field, "R%07d", i); else { strcpy(csa->field, csa->P->row[i]->name); for (f = csa->field; *f != '\0'; f++) if (*f == ' ') *f = '_'; } return csa->field; } static char *col_name(struct csa *csa, int j) { /* make j-th column name */ char *f; xassert(1 <= j && j <= csa->P->n); if (csa->P->col[j]->name == NULL || csa->deck && strlen(csa->P->col[j]->name) > 8) sprintf(csa->field, "C%07d", j); else { strcpy(csa->field, csa->P->col[j]->name); for (f = csa->field; *f != '\0'; f++) if (*f == ' ') *f = '_'; } return csa->field; } static char *mps_numb(struct csa *csa, double val) { /* format floating-point number */ int dig; char *exp; for (dig = 12; dig >= 6; dig--) { if (val != 0.0 && fabs(val) < 0.002) sprintf(csa->field, "%.*E", dig-1, val); else sprintf(csa->field, "%.*G", dig, val); exp = strchr(csa->field, 'E'); if (exp != NULL) sprintf(exp+1, "%d", atoi(exp+1)); if (strlen(csa->field) <= 12) break; } xassert(strlen(csa->field) <= 12); return csa->field; } int glp_write_mps(glp_prob *P, int fmt, const glp_mpscp *parm, const char *fname) { /* write problem data in MPS format */ glp_mpscp _parm; struct csa _csa, *csa = &_csa; XFILE *fp; int out_obj, one_col = 0, empty = 0; int i, j, recno, marker, count, gap, ret; xprintf("Writing problem data to `%s'...\n", fname); if (!(fmt == GLP_MPS_DECK || fmt == GLP_MPS_FILE)) xerror("glp_write_mps: fmt = %d; invalid parameter\n", fmt); if (parm == NULL) glp_init_mpscp(&_parm), parm = &_parm; /* check control parameters */ check_parm("glp_write_mps", parm); /* initialize common storage area */ csa->P = P; csa->deck = (fmt == GLP_MPS_DECK); csa->parm = parm; /* create output MPS file */ fp = xfopen(fname, "w"), recno = 0; if (fp == NULL) { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* write comment records */ xfprintf(fp, "* %-*s%s\n", P->name == NULL ? 1 : 12, "Problem:", P->name == NULL ? "" : P->name), recno++; xfprintf(fp, "* %-12s%s\n", "Class:", glp_get_num_int(P) == 0 ? "LP" : "MIP"), recno++; xfprintf(fp, "* %-12s%d\n", "Rows:", P->m), recno++; if (glp_get_num_int(P) == 0) xfprintf(fp, "* %-12s%d\n", "Columns:", P->n), recno++; else xfprintf(fp, "* %-12s%d (%d integer, %d binary)\n", "Columns:", P->n, glp_get_num_int(P), glp_get_num_bin(P)), recno++; xfprintf(fp, "* %-12s%d\n", "Non-zeros:", P->nnz), recno++; xfprintf(fp, "* %-12s%s\n", "Format:", csa->deck ? "Fixed MPS" : "Free MPS"), recno++; xfprintf(fp, "*\n", recno++); /* write NAME indicator record */ xfprintf(fp, "NAME%*s%s\n", P->name == NULL ? 0 : csa->deck ? 10 : 1, "", mps_name(csa)), recno++; #if 1 /* determine whether to write the objective row */ out_obj = 1; for (i = 1; i <= P->m; i++) { if (P->row[i]->type == GLP_FR) { out_obj = 0; break; } } #endif /* write ROWS section */ xfprintf(fp, "ROWS\n"), recno++; for (i = (out_obj ? 0 : 1); i <= P->m; i++) { int type; type = (i == 0 ? GLP_FR : P->row[i]->type); if (type == GLP_FR) type = 'N'; else if (type == GLP_LO) type = 'G'; else if (type == GLP_UP) type = 'L'; else if (type == GLP_DB || type == GLP_FX) type = 'E'; else xassert(type != type); xfprintf(fp, " %c%*s%s\n", type, csa->deck ? 2 : 1, "", row_name(csa, i)), recno++; } /* write COLUMNS section */ xfprintf(fp, "COLUMNS\n"), recno++; marker = 0; for (j = 1; j <= P->n; j++) { GLPAIJ cj, *aij; int kind; kind = P->col[j]->kind; if (kind == GLP_CV) { if (marker % 2 == 1) { /* close current integer block */ marker++; xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n", csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", csa->deck ? 17 : 1, ""), recno++; } } else if (kind == GLP_IV) { if (marker % 2 == 0) { /* open new integer block */ marker++; xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTORG'\n", csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", csa->deck ? 17 : 1, ""), recno++; } } else xassert(kind != kind); if (out_obj && P->col[j]->coef != 0.0) { /* make fake objective coefficient */ aij = &cj; aij->row = NULL; aij->val = P->col[j]->coef; aij->c_next = P->col[j]->ptr; } else aij = P->col[j]->ptr; #if 1 /* FIXME */ if (aij == NULL) { /* empty column */ empty++; xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", csa->deck ? 8 : 1, col_name(csa, j)); /* we need a row */ xassert(P->m > 0); xfprintf(fp, "%*s%-*s", csa->deck ? 2 : 1, "", csa->deck ? 8 : 1, row_name(csa, 1)); xfprintf(fp, "%*s0%*s$ empty column\n", csa->deck ? 13 : 1, "", csa->deck ? 3 : 1, ""), recno++; } #endif count = 0; for (aij = aij; aij != NULL; aij = aij->c_next) { if (one_col || count % 2 == 0) xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", csa->deck ? 8 : 1, col_name(csa, j)); gap = (one_col || count % 2 == 0 ? 2 : 3); xfprintf(fp, "%*s%-*s", csa->deck ? gap : 1, "", csa->deck ? 8 : 1, row_name(csa, aij->row == NULL ? 0 : aij->row->i)); xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, mps_numb(csa, aij->val)), count++; if (one_col || count % 2 == 0) xfprintf(fp, "\n"), recno++; } if (!(one_col || count % 2 == 0)) xfprintf(fp, "\n"), recno++; } if (marker % 2 == 1) { /* close last integer block */ marker++; xfprintf(fp, "%*sM%07d%*s'MARKER'%*s'INTEND'\n", csa->deck ? 4 : 1, "", marker, csa->deck ? 2 : 1, "", csa->deck ? 17 : 1, ""), recno++; } #if 1 if (empty > 0) xprintf("Warning: problem has %d empty column(s)\n", empty); #endif /* write RHS section */ xfprintf(fp, "RHS\n"), recno++; count = 0; for (i = (out_obj ? 0 : 1); i <= P->m; i++) { int type; double rhs; if (i == 0) rhs = P->c0; else { type = P->row[i]->type; if (type == GLP_FR) rhs = 0.0; else if (type == GLP_LO) rhs = P->row[i]->lb; else if (type == GLP_UP) rhs = P->row[i]->ub; else if (type == GLP_DB || type == GLP_FX) rhs = P->row[i]->lb; else xassert(type != type); } if (rhs != 0.0) { if (one_col || count % 2 == 0) xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", csa->deck ? 8 : 1, "RHS1"); gap = (one_col || count % 2 == 0 ? 2 : 3); xfprintf(fp, "%*s%-*s", csa->deck ? gap : 1, "", csa->deck ? 8 : 1, row_name(csa, i)); xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, mps_numb(csa, rhs)), count++; if (one_col || count % 2 == 0) xfprintf(fp, "\n"), recno++; } } if (!(one_col || count % 2 == 0)) xfprintf(fp, "\n"), recno++; /* write RANGES section */ for (i = P->m; i >= 1; i--) if (P->row[i]->type == GLP_DB) break; if (i == 0) goto bnds; xfprintf(fp, "RANGES\n"), recno++; count = 0; for (i = 1; i <= P->m; i++) { if (P->row[i]->type == GLP_DB) { if (one_col || count % 2 == 0) xfprintf(fp, "%*s%-*s", csa->deck ? 4 : 1, "", csa->deck ? 8 : 1, "RNG1"); gap = (one_col || count % 2 == 0 ? 2 : 3); xfprintf(fp, "%*s%-*s", csa->deck ? gap : 1, "", csa->deck ? 8 : 1, row_name(csa, i)); xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, mps_numb(csa, P->row[i]->ub - P->row[i]->lb)), count++; if (one_col || count % 2 == 0) xfprintf(fp, "\n"), recno++; } } if (!(one_col || count % 2 == 0)) xfprintf(fp, "\n"), recno++; bnds: /* write BOUNDS section */ for (j = P->n; j >= 1; j--) if (!(P->col[j]->kind == GLP_CV && P->col[j]->type == GLP_LO && P->col[j]->lb == 0.0)) break; if (j == 0) goto endt; xfprintf(fp, "BOUNDS\n"), recno++; for (j = 1; j <= P->n; j++) { int type, data[2]; double bnd[2]; char *spec[2]; spec[0] = spec[1] = NULL; type = P->col[j]->type; if (type == GLP_FR) spec[0] = "FR", data[0] = 0; else if (type == GLP_LO) { if (P->col[j]->lb != 0.0) spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb; if (P->col[j]->kind == GLP_IV) spec[1] = "PL", data[1] = 0; } else if (type == GLP_UP) { spec[0] = "MI", data[0] = 0; spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub; } else if (type == GLP_DB) { if (P->col[j]->lb != 0.0) spec[0] = "LO", data[0] = 1, bnd[0] = P->col[j]->lb; spec[1] = "UP", data[1] = 1, bnd[1] = P->col[j]->ub; } else if (type == GLP_FX) spec[0] = "FX", data[0] = 1, bnd[0] = P->col[j]->lb; else xassert(type != type); for (i = 0; i <= 1; i++) { if (spec[i] != NULL) { xfprintf(fp, " %s %-*s%*s%-*s", spec[i], csa->deck ? 8 : 1, "BND1", csa->deck ? 2 : 1, "", csa->deck ? 8 : 1, col_name(csa, j)); if (data[i]) xfprintf(fp, "%*s%*s", csa->deck ? 2 : 1, "", csa->deck ? 12 : 1, mps_numb(csa, bnd[i])); xfprintf(fp, "\n"), recno++; } } } endt: /* write ENDATA indicator record */ xfprintf(fp, "ENDATA\n"), recno++; xfflush(fp); if (xferror(fp)) { xprintf("Write error on `%s' - %s\n", fname, xerrmsg()); ret = 1; goto done; } /* problem data has been successfully written */ xprintf("%d records were written\n", recno); ret = 0; done: if (fp != NULL) xfclose(fp); return ret; } /* eof */ glpk-4.52.1/src/glpnet03.c0000644000062000006210000010047012175147600014312 0ustar maomkpasswd/* glpnet03.c (Klingman's network problem generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * This code is the result of translation of the Fortran program NETGEN * developed by Dr. Darwin Klingman, which is publically available from * NETLIB at . * * The translation was made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * glp_netgen - Klingman's network problem generator * * SYNOPSIS * * int glp_netgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, * const int parm[1+15]); * * DESCRIPTION * * The routine glp_netgen is a network problem generator developed by * Dr. Darwin Klingman. It can create capacitated and uncapacitated * minimum cost flow (or transshipment), transportation, and assignment * problems. * * The parameter G specifies the graph object, to which the generated * problem data have to be stored. Note that on entry the graph object * is erased with the routine glp_erase_graph. * * The parameter v_rhs specifies an offset of the field of type double * in the vertex data block, to which the routine stores the supply or * demand value. If v_rhs < 0, the value is not stored. * * The parameter a_cap specifies an offset of the field of type double * in the arc data block, to which the routine stores the arc capacity. * If a_cap < 0, the capacity is not stored. * * The parameter a_cost specifies an offset of the field of type double * in the arc data block, to which the routine stores the per-unit cost * if the arc flow. If a_cost < 0, the cost is not stored. * * The array parm contains description of the network to be generated: * * parm[0] not used * parm[1] (iseed) 8-digit positive random number seed * parm[2] (nprob) 8-digit problem id number * parm[3] (nodes) total number of nodes * parm[4] (nsorc) total number of source nodes (including * transshipment nodes) * parm[5] (nsink) total number of sink nodes (including * transshipment nodes) * parm[6] (iarcs) number of arcs * parm[7] (mincst) minimum cost for arcs * parm[8] (maxcst) maximum cost for arcs * parm[9] (itsup) total supply * parm[10] (ntsorc) number of transshipment source nodes * parm[11] (ntsink) number of transshipment sink nodes * parm[12] (iphic) percentage of skeleton arcs to be given * the maximum cost * parm[13] (ipcap) percentage of arcs to be capacitated * parm[14] (mincap) minimum upper bound for capacitated arcs * parm[15] (maxcap) maximum upper bound for capacitated arcs * * The routine generates a transportation problem if: * * nsorc + nsink = nodes, ntsorc = 0, and ntsink = 0. * * The routine generates an assignment problem if the requirements for * a transportation problem are met and: * * nsorc = nsink and itsup = nsorc. * * RETURNS * * If the instance was successfully generated, the routine glp_netgen * returns zero; otherwise, if specified parameters are inconsistent, * the routine returns a non-zero error code. * * REFERENCES * * D.Klingman, A.Napier, and J.Stutz. NETGEN: A program for generating * large scale capacitated assignment, transportation, and minimum cost * flow networks. Management Science 20 (1974), 814-20. */ struct csa { /* common storage area */ glp_graph *G; int v_rhs, a_cap, a_cost; int nodes, iarcs, mincst, maxcst, itsup, nsorc, nsink, nonsor, nfsink, narcs, nsort, nftsor, ipcap, mincap, maxcap, ktl, nodlft, *ipred, *ihead, *itail, *iflag, *isup, *lsinks, mult, modul, i15, i16, jran; }; #define G (csa->G) #define v_rhs (csa->v_rhs) #define a_cap (csa->a_cap) #define a_cost (csa->a_cost) #define nodes (csa->nodes) #define iarcs (csa->iarcs) #define mincst (csa->mincst) #define maxcst (csa->maxcst) #define itsup (csa->itsup) #define nsorc (csa->nsorc) #define nsink (csa->nsink) #define nonsor (csa->nonsor) #define nfsink (csa->nfsink) #define narcs (csa->narcs) #define nsort (csa->nsort) #define nftsor (csa->nftsor) #define ipcap (csa->ipcap) #define mincap (csa->mincap) #define maxcap (csa->maxcap) #define ktl (csa->ktl) #define nodlft (csa->nodlft) #if 0 /* spent a day to find out this bug */ #define ist (csa->ist) #else #define ist (ipred[0]) #endif #define ipred (csa->ipred) #define ihead (csa->ihead) #define itail (csa->itail) #define iflag (csa->iflag) #define isup (csa->isup) #define lsinks (csa->lsinks) #define mult (csa->mult) #define modul (csa->modul) #define i15 (csa->i15) #define i16 (csa->i16) #define jran (csa->jran) static void cresup(struct csa *csa); static void chain(struct csa *csa, int lpick, int lsorc); static void chnarc(struct csa *csa, int lsorc); static void sort(struct csa *csa); static void pickj(struct csa *csa, int it); static void assign(struct csa *csa); static void setran(struct csa *csa, int iseed); static int iran(struct csa *csa, int ilow, int ihigh); int glp_netgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost, const int parm[1+15]) { struct csa _csa, *csa = &_csa; int iseed, nprob, ntsorc, ntsink, iphic, i, nskel, nltr, ltsink, ntrans, npsink, nftr, npsorc, ntravl, ntrrem, lsorc, lpick, nsksr, nsrchn, j, item, l, ks, k, ksp, li, n, ii, it, ih, icap, jcap, icost, jcost, ret; G = G_; v_rhs = _v_rhs; a_cap = _a_cap; a_cost = _a_cost; if (G != NULL) { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_netgen: v_rhs = %d; invalid offset\n", v_rhs); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_netgen: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_netgen: a_cost = %d; invalid offset\n", a_cost); } /* Input the user's random number seed and fix it if non-positive. */ iseed = parm[1]; nprob = parm[2]; if (iseed <= 0) iseed = 13502460; setran(csa, iseed); /* Input the user's problem characteristics. */ nodes = parm[3]; nsorc = parm[4]; nsink = parm[5]; iarcs = parm[6]; mincst = parm[7]; maxcst = parm[8]; itsup = parm[9]; ntsorc = parm[10]; ntsink = parm[11]; iphic = parm[12]; ipcap = parm[13]; mincap = parm[14]; maxcap = parm[15]; /* Check the size of the problem. */ if (!(10 <= nodes && nodes <= 100000)) { ret = 1; goto done; } /* Check user supplied parameters for consistency. */ if (!(nsorc >= 0 && nsink >= 0 && nsorc + nsink <= nodes)) { ret = 2; goto done; } if (iarcs < 0) { ret = 3; goto done; } if (mincst > maxcst) { ret = 4; goto done; } if (itsup < 0) { ret = 5; goto done; } if (!(0 <= ntsorc && ntsorc <= nsorc)) { ret = 6; goto done; } if (!(0 <= ntsink && ntsink <= nsink)) { ret = 7; goto done; } if (!(0 <= iphic && iphic <= 100)) { ret = 8; goto done; } if (!(0 <= ipcap && ipcap <= 100)) { ret = 9; goto done; } if (mincap > maxcap) { ret = 10; goto done; } /* Initailize the graph object. */ if (G != NULL) { glp_erase_graph(G, G->v_size, G->a_size); glp_add_vertices(G, nodes); if (v_rhs >= 0) { double zero = 0.0; for (i = 1; i <= nodes; i++) { glp_vertex *v = G->v[i]; memcpy((char *)v->data + v_rhs, &zero, sizeof(double)); } } } /* Allocate working arrays. */ ipred = xcalloc(1+nodes, sizeof(int)); ihead = xcalloc(1+nodes, sizeof(int)); itail = xcalloc(1+nodes, sizeof(int)); iflag = xcalloc(1+nodes, sizeof(int)); isup = xcalloc(1+nodes, sizeof(int)); lsinks = xcalloc(1+nodes, sizeof(int)); /* Print the problem documentation records. */ if (G == NULL) { xprintf("BEGIN\n"); xprintf("NETGEN PROBLEM%8d%10s%10d NODES AND%10d ARCS\n", nprob, "", nodes, iarcs); xprintf("USER:%11d%11d%11d%11d%11d%11d\nDATA:%11d%11d%11d%11d%" "11d%11d\n", iseed, nsorc, nsink, mincst, maxcst, itsup, ntsorc, ntsink, iphic, ipcap, mincap, maxcap); } else glp_set_graph_name(G, "NETGEN"); /* Set various constants used in the program. */ narcs = 0; nskel = 0; nltr = nodes - nsink; ltsink = nltr + ntsink; ntrans = nltr - nsorc; nfsink = nltr + 1; nonsor = nodes - nsorc + ntsorc; npsink = nsink - ntsink; nodlft = nodes - nsink + ntsink; nftr = nsorc + 1; nftsor = nsorc - ntsorc + 1; npsorc = nsorc - ntsorc; /* Randomly distribute the supply among the source nodes. */ if (npsorc + npsink == nodes && npsorc == npsink && itsup == nsorc) { assign(csa); nskel = nsorc; goto L390; } cresup(csa); /* Print the supply records. */ if (G == NULL) { xprintf("SUPPLY\n"); for (i = 1; i <= nsorc; i++) xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]); xprintf("ARCS\n"); } else { if (v_rhs >= 0) { for (i = 1; i <= nsorc; i++) { double temp = (double)isup[i]; glp_vertex *v = G->v[i]; memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); } } } /* Make the sources point to themselves in ipred array. */ for (i = 1; i <= nsorc; i++) ipred[i] = i; if (ntrans == 0) goto L170; /* Chain the transshipment nodes together in the ipred array. */ ist = nftr; ipred[nltr] = 0; for (i = nftr; i < nltr; i++) ipred[i] = i+1; /* Form even length chains for 60 percent of the transshipments.*/ ntravl = 6 * ntrans / 10; ntrrem = ntrans - ntravl; L140: lsorc = 1; while (ntravl != 0) { lpick = iran(csa, 1, ntravl + ntrrem); ntravl--; chain(csa, lpick, lsorc); if (lsorc == nsorc) goto L140; lsorc++; } /* Add the remaining transshipments to the chains. */ while (ntrrem != 0) { lpick = iran(csa, 1, ntrrem); ntrrem--; lsorc = iran(csa, 1, nsorc); chain(csa, lpick, lsorc); } L170: /* Set all demands equal to zero. */ for (i = nfsink; i <= nodes; i++) ipred[i] = 0; /* The following loop takes one chain at a time (through the use of logic contained in the loop and calls to other routines) and creates the remaining network arcs. */ for (lsorc = 1; lsorc <= nsorc; lsorc++) { chnarc(csa, lsorc); for (i = nfsink; i <= nodes; i++) iflag[i] = 0; /* Choose the number of sinks to be hooked up to the current chain. */ if (ntrans != 0) nsksr = (nsort * 2 * nsink) / ntrans; else nsksr = nsink / nsorc + 1; if (nsksr < 2) nsksr = 2; if (nsksr > nsink) nsksr = nsink; nsrchn = nsort; /* Randomly pick nsksr sinks and put their names in lsinks. */ ktl = nsink; for (j = 1; j <= nsksr; j++) { item = iran(csa, 1, ktl); ktl--; for (l = nfsink; l <= nodes; l++) { if (iflag[l] != 1) { item--; if (item == 0) goto L230; } } break; L230: lsinks[j] = l; iflag[l] = 1; } /* If last source chain, add all sinks with zero demand to lsinks list. */ if (lsorc == nsorc) { for (j = nfsink; j <= nodes; j++) { if (ipred[j] == 0 && iflag[j] != 1) { nsksr++; lsinks[nsksr] = j; iflag[j] = 1; } } } /* Create demands for group of sinks in lsinks. */ ks = isup[lsorc] / nsksr; k = ipred[lsorc]; for (i = 1; i <= nsksr; i++) { nsort++; ksp = iran(csa, 1, ks); j = iran(csa, 1, nsksr); itail[nsort] = k; li = lsinks[i]; ihead[nsort] = li; ipred[li] += ksp; li = lsinks[j]; ipred[li] += ks - ksp; n = iran(csa, 1, nsrchn); k = lsorc; for (ii = 1; ii <= n; ii++) k = ipred[k]; } li = lsinks[1]; ipred[li] += isup[lsorc] - ks * nsksr; nskel += nsort; /* Sort the arcs in the chain from source lsorc using itail as sort key. */ sort(csa); /* Print this part of skeleton and create the arcs for these nodes. */ i = 1; itail[nsort+1] = 0; L300: for (j = nftsor; j <= nodes; j++) iflag[j] = 0; ktl = nonsor - 1; it = itail[i]; iflag[it] = 1; L320: ih = ihead[i]; iflag[ih] = 1; narcs++; ktl--; /* Determine if this skeleton arc should be capacitated. */ icap = itsup; jcap = iran(csa, 1, 100); if (jcap <= ipcap) { icap = isup[lsorc]; if (mincap > icap) icap = mincap; } /* Determine if this skeleton arc should have the maximum cost. */ icost = maxcst; jcost = iran(csa, 1, 100); if (jcost > iphic) icost = iran(csa, mincst, maxcst); if (G == NULL) xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ih, "", icost, icap); else { glp_arc *a = glp_add_arc(G, it, ih); if (a_cap >= 0) { double temp = (double)icap; memcpy((char *)a->data + a_cap, &temp, sizeof(double)); } if (a_cost >= 0) { double temp = (double)icost; memcpy((char *)a->data + a_cost, &temp, sizeof(double)); } } i++; if (itail[i] == it) goto L320; pickj(csa, it); if (i <= nsort) goto L300; } /* Create arcs from the transshipment sinks. */ if (ntsink != 0) { for (i = nfsink; i <= ltsink; i++) { for (j = nftsor; j <= nodes; j++) iflag[j] = 0; ktl = nonsor - 1; iflag[i] = 1; pickj(csa, i); } } L390: /* Print the demand records and end record. */ if (G == NULL) { xprintf("DEMAND\n"); for (i = nfsink; i <= nodes; i++) xprintf("%6s%6d%18s%10d\n", "", i, "", ipred[i]); xprintf("END\n"); } else { if (v_rhs >= 0) { for (i = nfsink; i <= nodes; i++) { double temp = - (double)ipred[i]; glp_vertex *v = G->v[i]; memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); } } } /* Free working arrays. */ xfree(ipred); xfree(ihead); xfree(itail); xfree(iflag); xfree(isup); xfree(lsinks); /* The instance has been successfully generated. */ ret = 0; done: return ret; } /*********************************************************************** * The routine cresup randomly distributes the total supply among the * source nodes. */ static void cresup(struct csa *csa) { int i, j, ks, ksp; xassert(itsup > nsorc); ks = itsup / nsorc; for (i = 1; i <= nsorc; i++) isup[i] = 0; for (i = 1; i <= nsorc; i++) { ksp = iran(csa, 1, ks); j = iran(csa, 1, nsorc); isup[i] += ksp; isup[j] += ks - ksp; } j = iran(csa, 1, nsorc); isup[j] += itsup - ks * nsorc; return; } /*********************************************************************** * The routine chain adds node lpick to the end of the chain with source * node lsorc. */ static void chain(struct csa *csa, int lpick, int lsorc) { int i, j, k, l, m; k = 0; m = ist; for (i = 1; i <= lpick; i++) { l = k; k = m; m = ipred[k]; } ipred[l] = m; j = ipred[lsorc]; ipred[k] = j; ipred[lsorc] = k; return; } /*********************************************************************** * The routine chnarc puts the arcs in the chain from source lsorc into * the ihead and itail arrays for sorting. */ static void chnarc(struct csa *csa, int lsorc) { int ito, ifrom; nsort = 0; ito = ipred[lsorc]; L10: if (ito == lsorc) return; nsort++; ifrom = ipred[ito]; ihead[nsort] = ito; itail[nsort] = ifrom; ito = ifrom; goto L10; } /*********************************************************************** * The routine sort sorts the nsort arcs in the ihead and itail arrays. * ihead is used as the sort key (i.e. forward star sort order). */ static void sort(struct csa *csa) { int i, j, k, l, m, n, it; n = nsort; m = n; L10: m /= 2; if (m == 0) return; k = n - m; j = 1; L20: i = j; L30: l = i + m; if (itail[i] <= itail[l]) goto L40; it = itail[i]; itail[i] = itail[l]; itail[l] = it; it = ihead[i]; ihead[i] = ihead[l]; ihead[l] = it; i -= m; if (i >= 1) goto L30; L40: j++; if (j <= k) goto L20; goto L10; } /*********************************************************************** * The routine pickj creates a random number of arcs out of node 'it'. * Various parameters are dynamically adjusted in an attempt to ensure * that the generated network has the correct number of arcs. */ static void pickj(struct csa *csa, int it) { int j, k, l, nn, nupbnd, icap, jcap, icost; if ((nodlft - 1) * 2 > iarcs - narcs - 1) { nodlft--; return; } if ((iarcs - narcs + nonsor - ktl - 1) / nodlft - nonsor + 1 >= 0) k = nonsor; else { nupbnd = (iarcs - narcs - nodlft) / nodlft * 2; L40: k = iran(csa, 1, nupbnd); if (nodlft == 1) k = iarcs - narcs; if ((nodlft - 1) * (nonsor - 1) < iarcs - narcs - k) goto L40; } nodlft--; for (j = 1; j <= k; j++) { nn = iran(csa, 1, ktl); ktl--; for (l = nftsor; l <= nodes; l++) { if (iflag[l] != 1) { nn--; if (nn == 0) goto L70; } } return; L70: iflag[l] = 1; icap = itsup; jcap = iran(csa, 1, 100); if (jcap <= ipcap) icap = iran(csa, mincap, maxcap); icost = iran(csa, mincst, maxcst); if (G == NULL) xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, l, "", icost, icap); else { glp_arc *a = glp_add_arc(G, it, l); if (a_cap >= 0) { double temp = (double)icap; memcpy((char *)a->data + a_cap, &temp, sizeof(double)); } if (a_cost >= 0) { double temp = (double)icost; memcpy((char *)a->data + a_cost, &temp, sizeof(double)); } } narcs++; } return; } /*********************************************************************** * The routine assign generate assignment problems. It defines the unit * supplies, builds a skeleton, then calls pickj to create the arcs. */ static void assign(struct csa *csa) { int i, it, nn, l, ll, icost; if (G == NULL) xprintf("SUPPLY\n"); for (i = 1; i <= nsorc; i++) { isup[i] = 1; iflag[i] = 0; if (G == NULL) xprintf("%6s%6d%18s%10d\n", "", i, "", isup[i]); else { if (v_rhs >= 0) { double temp = (double)isup[i]; glp_vertex *v = G->v[i]; memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); } } } if (G == NULL) xprintf("ARCS\n"); for (i = nfsink; i <= nodes; i++) ipred[i] = 1; for (it = 1; it <= nsorc; it++) { for (i = nfsink; i <= nodes; i++) iflag[i] = 0; ktl = nsink - 1; nn = iran(csa, 1, nsink - it + 1); for (l = 1; l <= nsorc; l++) { if (iflag[l] != 1) { nn--; if (nn == 0) break; } } narcs++; ll = nsorc + l; icost = iran(csa, mincst, maxcst); if (G == NULL) xprintf("%6s%6d%6d%2s%10d%10d\n", "", it, ll, "", icost, isup[1]); else { glp_arc *a = glp_add_arc(G, it, ll); if (a_cap >= 0) { double temp = (double)isup[1]; memcpy((char *)a->data + a_cap, &temp, sizeof(double)); } if (a_cost >= 0) { double temp = (double)icost; memcpy((char *)a->data + a_cost, &temp, sizeof(double)); } } iflag[l] = 1; iflag[ll] = 1; pickj(csa, it); } return; } /*********************************************************************** * Portable congruential (uniform) random number generator: * * next_value = ((7**5) * previous_value) modulo ((2**31)-1) * * This generator consists of three routines: * * (1) setran - initializes constants and seed * (2) iran - generates an integer random number * (3) rran - generates a real random number * * The generator requires a machine with at least 32 bits of precision. * The seed (iseed) must be in the range [1,(2**31)-1]. */ static void setran(struct csa *csa, int iseed) { xassert(iseed >= 1); mult = 16807; modul = 2147483647; i15 = 1 << 15; i16 = 1 << 16; jran = iseed; return; } /*********************************************************************** * The routine iran generates an integer random number between ilow and * ihigh. If ilow > ihigh then iran returns ihigh. */ static int iran(struct csa *csa, int ilow, int ihigh) { int ixhi, ixlo, ixalo, leftlo, ixahi, ifulhi, irtlo, iover, irthi, j; ixhi = jran / i16; ixlo = jran - ixhi * i16; ixalo = ixlo * mult; leftlo = ixalo / i16; ixahi = ixhi * mult; ifulhi = ixahi + leftlo; irtlo = ixalo - leftlo * i16; iover = ifulhi / i15; irthi = ifulhi - iover * i15; jran = ((irtlo - modul) + irthi * i16) + iover; if (jran < 0) jran += modul; j = ihigh - ilow + 1; if (j > 0) return jran % j + ilow; else return ihigh; } /*********************************************************************** * NAME * * glp_netgen_prob - Klingman's standard network problem instance * * SYNOPSIS * * void glp_netgen_prob(int nprob, int parm[1+15]); * * DESCRIPTION * * The routine glp_netgen_prob provides the set of parameters for * Klingman's network problem generator (see the routine glp_netgen), * which describe a standard network problem instance. * * The parameter nprob (101 <= nprob <= 150) specifies the problem * instance number. * * The array parm contains description of the network, provided by the * routine. (For detailed description of these parameters see comments * to the routine glp_netgen.) * * PROBLEM CHARACTERISTICS * * The table below shows characteristics of Klingman's standard network * problem instances. * * Problem Nodes Arcs Optimum * ------- ----- ----- ---------- * 101 5000 25336 6191726 * 102 5000 25387 72337144 * 103 5000 25355 218947553 * 104 5000 25344 -19100371 * 105 5000 25332 31192578 * 106 5000 12870 4314276 * 107 5000 37832 7393769 * 108 5000 50309 8405738 * 109 5000 75299 9190300 * 110 5000 12825 8975048 * 111 5000 37828 4747532 * 112 5000 50325 4012671 * 113 5000 75318 2979725 * 114 5000 26514 5821181 * 115 5000 25962 6353310 * 116 5000 25304 5915426 * 117 5000 12816 4420560 * 118 5000 37797 7045842 * 119 5000 50301 7724179 * 120 5000 75330 8455200 * 121 5000 25000 66366360 * 122 5000 25000 30997529 * 123 5000 25000 23388777 * 124 5000 25000 17803443 * 125 5000 25000 14119622 * 126 5000 12500 18802218 * 127 5000 37500 27674647 * 128 5000 50000 30906194 * 129 5000 75000 40905209 * 130 5000 12500 38939608 * 131 5000 37500 16752978 * 132 5000 50000 13302951 * 133 5000 75000 9830268 * 134 1000 25000 3804874 * 135 2500 25000 11729616 * 136 7500 25000 33318101 * 137 10000 25000 46426030 * 138 5000 25000 60710879 * 139 5000 25000 32729682 * 140 5000 25000 27183831 * 141 5000 25000 19963286 * 142 5000 25000 20243457 * 143 5000 25000 18586777 * 144 5000 25000 2504591 * 145 5000 25000 215956138 * 146 5000 25000 2253113811 * 147 5000 25000 -427908373 * 148 5000 25000 -92965318 * 149 5000 25000 86051224 * 150 5000 25000 619314919 */ static const int data[50][1+15] = { { 0, 13502460, 101, 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 4281922, 102, 5000, 2500, 2500, 25000, 1, 100, 2500000, 0, 0, 0, 100, 1, 1000 }, { 0, 44820113, 103, 5000, 2500, 2500, 25000, 1, 100, 6250000, 0, 0, 0, 100, 1, 1000 }, { 0, 13450451, 104, 5000, 2500, 2500, 25000, -100, -1, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 14719436, 105, 5000, 2500, 2500, 25000, 101, 200, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 17365786, 106, 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 100, 1, 1000 }, { 0, 19540113, 107, 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 100, 1, 1000 }, { 0, 19560313, 108, 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 100, 1, 1000 }, { 0, 2403509, 109, 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 100, 1, 1000 }, { 0, 92480414, 110, 5000, 2500, 2500, 12500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 4230140, 111, 5000, 2500, 2500, 37500, 1, 100, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 10032490, 112, 5000, 2500, 2500, 50000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 17307474, 113, 5000, 2500, 2500, 75000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 4925114, 114, 5000, 500, 4500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 19842704, 115, 5000, 1500, 3500, 25000, 1, 100, 250000, 0, 0, 0, 100, 1, 1000 }, { 0, 88392060, 116, 5000, 2500, 2500, 25000, 1, 100, 250000, 0, 0, 0, 0, 1, 1000 }, { 0, 12904407, 117, 5000, 2500, 2500, 12500, 1, 100, 125000, 0, 0, 0, 0, 1, 1000 }, { 0, 11811811, 118, 5000, 2500, 2500, 37500, 1, 100, 375000, 0, 0, 0, 0, 1, 1000 }, { 0, 90023593, 119, 5000, 2500, 2500, 50000, 1, 100, 500000, 0, 0, 0, 0, 1, 1000 }, { 0, 93028922, 120, 5000, 2500, 2500, 75000, 1, 100, 750000, 0, 0, 0, 0, 1, 1000 }, { 0, 72707401, 121, 5000, 50, 50, 25000, 1, 100, 250000, 50, 50, 0, 100, 1, 1000 }, { 0, 93040771, 122, 5000, 250, 250, 25000, 1, 100, 250000, 250, 250, 0, 100, 1, 1000 }, { 0, 70220611, 123, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 52774811, 124, 5000, 1000, 1000, 25000, 1, 100, 250000, 1000, 1000, 0, 100, 1, 1000 }, { 0, 22492311, 125, 5000, 1500, 1500, 25000, 1, 100, 250000, 1500, 1500, 0, 100, 1, 1000 }, { 0, 35269337, 126, 5000, 500, 500, 12500, 1, 100, 125000, 500, 500, 0, 100, 1, 1000 }, { 0, 30140502, 127, 5000, 500, 500, 37500, 1, 100, 375000, 500, 500, 0, 100, 1, 1000 }, { 0, 49205455, 128, 5000, 500, 500, 50000, 1, 100, 500000, 500, 500, 0, 100, 1, 1000 }, { 0, 42958341, 129, 5000, 500, 500, 75000, 1, 100, 750000, 500, 500, 0, 100, 1, 1000 }, { 0, 25440925, 130, 5000, 500, 500, 12500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 75294924, 131, 5000, 500, 500, 37500, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 4463965, 132, 5000, 500, 500, 50000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 13390427, 133, 5000, 500, 500, 75000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 95250971, 134, 1000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 54830522, 135, 2500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 520593, 136, 7500, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 52900925, 137, 10000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 22603395, 138, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 50 }, { 0, 55253099, 139, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 250 }, { 0, 75357001, 140, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 500 }, { 0, 10072459, 141, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 2500 }, { 0, 55728492, 142, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 100, 1, 5000 }, { 0, 593043, 143, 5000, 500, 500, 25000, 1, 100, 250000, 500, 500, 0, 0, 1, 1000 }, { 0, 94236572, 144, 5000, 500, 500, 25000, 1, 10, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 94882955, 145, 5000, 500, 500, 25000, 1, 1000, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 48489922, 146, 5000, 500, 500, 25000, 1, 10000, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 75578374, 147, 5000, 500, 500, 25000, -100, -1, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 44821152, 148, 5000, 500, 500, 25000, -50, 49, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 45224103, 149, 5000, 500, 500, 25000, 101, 200, 250000, 500, 500, 0, 100, 1, 1000 }, { 0, 63491741, 150, 5000, 500, 500, 25000, 1001, 1100, 250000, 500, 500, 0, 100, 1, 1000 }, }; void glp_netgen_prob(int nprob, int parm[1+15]) { int k; if (!(101 <= nprob && nprob <= 150)) xerror("glp_netgen_prob: nprob = %d; invalid problem instance " "number\n", nprob); for (k = 1; k <= 15; k++) parm[k] = data[nprob-101][k]; return; } /**********************************************************************/ #if 0 static int scan(char card[80+1], int pos, int len) { char buf[10+1]; memcpy(buf, &card[pos-1], len); buf[len] = '\0'; return atoi(buf); } int main(void) { int parm[1+15]; char card[80+1]; xassert(fgets(card, sizeof(card), stdin) == card); parm[1] = scan(card, 1, 8); parm[2] = scan(card, 9, 8); xassert(fgets(card, sizeof(card), stdin) == card); parm[3] = scan(card, 1, 5); parm[4] = scan(card, 6, 5); parm[5] = scan(card, 11, 5); parm[6] = scan(card, 16, 5); parm[7] = scan(card, 21, 5); parm[8] = scan(card, 26, 5); parm[9] = scan(card, 31, 10); parm[10] = scan(card, 41, 5); parm[11] = scan(card, 46, 5); parm[12] = scan(card, 51, 5); parm[13] = scan(card, 56, 5); parm[14] = scan(card, 61, 10); parm[15] = scan(card, 71, 10); glp_netgen(NULL, 0, 0, 0, parm); return 0; } #endif /* eof */ glpk-4.52.1/src/glpnet04.c0000644000062000006210000006213712175147600014322 0ustar maomkpasswd/* glpnet04.c (grid-like network problem generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * This code is a modified version of the program GRIDGEN, a grid-like * network problem generator developed by Yusin Lee and Jim Orlin. * The original code is publically available on the DIMACS ftp site at: * . * * All changes concern only the program interface, so this modified * version produces exactly the same instances as the original version. * * Changes were made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" /*********************************************************************** * NAME * * glp_gridgen - grid-like network problem generator * * SYNOPSIS * * int glp_gridgen(glp_graph *G, int v_rhs, int a_cap, int a_cost, * const int parm[1+14]); * * DESCRIPTION * * The routine glp_gridgen is a grid-like network problem generator * developed by Yusin Lee and Jim Orlin. * * The parameter G specifies the graph object, to which the generated * problem data have to be stored. Note that on entry the graph object * is erased with the routine glp_erase_graph. * * The parameter v_rhs specifies an offset of the field of type double * in the vertex data block, to which the routine stores the supply or * demand value. If v_rhs < 0, the value is not stored. * * The parameter a_cap specifies an offset of the field of type double * in the arc data block, to which the routine stores the arc capacity. * If a_cap < 0, the capacity is not stored. * * The parameter a_cost specifies an offset of the field of type double * in the arc data block, to which the routine stores the per-unit cost * if the arc flow. If a_cost < 0, the cost is not stored. * * The array parm contains description of the network to be generated: * * parm[0] not used * parm[1] two-ways arcs indicator: * 1 - if links in both direction should be generated * 0 - otherwise * parm[2] random number seed (a positive integer) * parm[3] number of nodes (the number of nodes generated might be * slightly different to make the network a grid) * parm[4] grid width * parm[5] number of sources * parm[6] number of sinks * parm[7] average degree * parm[8] total flow * parm[9] distribution of arc costs: * 1 - uniform * 2 - exponential * parm[10] lower bound for arc cost (uniform) * 100 * lambda (exponential) * parm[11] upper bound for arc cost (uniform) * not used (exponential) * parm[12] distribution of arc capacities: * 1 - uniform * 2 - exponential * parm[13] lower bound for arc capacity (uniform) * 100 * lambda (exponential) * parm[14] upper bound for arc capacity (uniform) * not used (exponential) * * RETURNS * * If the instance was successfully generated, the routine glp_gridgen * returns zero; otherwise, if specified parameters are inconsistent, * the routine returns a non-zero error code. * * COMMENTS * * This network generator generates a grid-like network plus a super * node. In additional to the arcs connecting the nodes in the grid, * there is an arc from each supply node to the super node and from the * super node to each demand node to guarantee feasiblity. These arcs * have very high costs and very big capacities. * * The idea of this network generator is as follows: First, a grid of * n1 * n2 is generated. For example, 5 * 3. The nodes are numbered as * 1 to 15, and the supernode is numbered as n1*n2+1. Then arcs between * adjacent nodes are generated. For these arcs, the user is allowed to * specify either to generate two-way arcs or one-way arcs. If two-way * arcs are to be generated, two arcs, one in each direction, will be * generated between each adjacent node pairs. Otherwise, only one arc * will be generated. If this is the case, the arcs will be generated * in alterntive directions as shown below. * * 1 ---> 2 ---> 3 ---> 4 ---> 5 * | ^ | ^ | * | | | | | * V | V | V * 6 <--- 7 <--- 8 <--- 9 <--- 10 * | ^ | ^ | * | | | | | * V | V | V * 11 --->12 --->13 --->14 ---> 15 * * Then the arcs between the super node and the source/sink nodes are * added as mentioned before. If the number of arcs still doesn't reach * the requirement, additional arcs will be added by uniformly picking * random node pairs. There is no checking to prevent multiple arcs * between any pair of nodes. However, there will be no self-arcs (arcs * that poins back to its tail node) in the network. * * The source and sink nodes are selected uniformly in the network, and * the imbalances of each source/sink node are also assigned by uniform * distribution. */ struct stat_para { /* structure for statistical distributions */ int distribution; /* the distribution: */ #define UNIFORM 1 /* uniform distribution */ #define EXPONENTIAL 2 /* exponential distribution */ double parameter[5]; /* the parameters of the distribution */ }; struct arcs { int from; /* the FROM node of that arc */ int to; /* the TO node of that arc */ int cost; /* original cost of that arc */ int u; /* capacity of the arc */ }; struct imbalance { int node; /* Node ID */ int supply; /* Supply of that node */ }; struct csa { /* common storage area */ glp_graph *G; int v_rhs, a_cap, a_cost; int seed; /* random number seed */ int seed_original; /* the original seed from input */ int two_way; /* 0: generate arcs in both direction for the basic grid, except for the arcs to/from the super node. 1: o/w */ int n_node; /* total number of nodes in the network, numbered 1 to n_node, including the super node, which is the last one */ int n_arc; /* total number of arcs in the network, counting EVERY arc. */ int n_grid_arc; /* number of arcs in the basic grid, including the arcs to/from the super node */ int n_source, n_sink; /* number of source and sink nodes */ int avg_degree; /* average degree, arcs to and from the super node are counted */ int t_supply; /* total supply in the network */ int n1, n2; /* the two edges of the network grid. n1 >= n2 */ struct imbalance *source_list, *sink_list; /* head of the array of source/sink nodes */ struct stat_para arc_costs; /* the distribution of arc costs */ struct stat_para capacities; /* distribution of the capacities of the arcs */ struct arcs *arc_list; /* head of the arc list array. Arcs in this array are in the order of grid_arcs, arcs to/from super node, and other arcs */ }; #define G (csa->G) #define v_rhs (csa->v_rhs) #define a_cap (csa->a_cap) #define a_cost (csa->a_cost) #define seed (csa->seed) #define seed_original (csa->seed_original) #define two_way (csa->two_way) #define n_node (csa->n_node) #define n_arc (csa->n_arc) #define n_grid_arc (csa->n_grid_arc) #define n_source (csa->n_source) #define n_sink (csa->n_sink) #define avg_degree (csa->avg_degree) #define t_supply (csa->t_supply) #define n1 (csa->n1) #define n2 (csa->n2) #define source_list (csa->source_list) #define sink_list (csa->sink_list) #define arc_costs (csa->arc_costs) #define capacities (csa->capacities) #define arc_list (csa->arc_list) static void assign_capacities(struct csa *csa); static void assign_costs(struct csa *csa); static void assign_imbalance(struct csa *csa); static int exponential(struct csa *csa, double lambda[1]); static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs *arc_ptr); static struct arcs *gen_basic_grid(struct csa *csa, struct arcs *arc_ptr); static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr); static void generate(struct csa *csa); static void output(struct csa *csa); static double randy(struct csa *csa); static void select_source_sinks(struct csa *csa); static int uniform(struct csa *csa, double a[2]); int glp_gridgen(glp_graph *G_, int _v_rhs, int _a_cap, int _a_cost, const int parm[1+14]) { struct csa _csa, *csa = &_csa; int n, ret; G = G_; v_rhs = _v_rhs; a_cap = _a_cap; a_cost = _a_cost; if (G != NULL) { if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double)) xerror("glp_gridgen: v_rhs = %d; invalid offset\n", v_rhs); if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_gridgen: a_cap = %d; invalid offset\n", a_cap); if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double)) xerror("glp_gridgen: a_cost = %d; invalid offset\n", a_cost) ; } /* Check the parameters for consistency. */ if (!(parm[1] == 0 || parm[1] == 1)) { ret = 1; goto done; } if (parm[2] < 1) { ret = 2; goto done; } if (!(10 <= parm[3] && parm[3] <= 40000)) { ret = 3; goto done; } if (!(1 <= parm[4] && parm[4] <= 40000)) { ret = 4; goto done; } if (!(parm[5] >= 0 && parm[6] >= 0 && parm[5] + parm[6] <= parm[3])) { ret = 5; goto done; } if (!(1 <= parm[7] && parm[7] <= parm[3])) { ret = 6; goto done; } if (parm[8] < 0) { ret = 7; goto done; } if (!(parm[9] == 1 || parm[9] == 2)) { ret = 8; goto done; } if (parm[9] == 1 && parm[10] > parm[11] || parm[9] == 2 && parm[10] < 1) { ret = 9; goto done; } if (!(parm[12] == 1 || parm[12] == 2)) { ret = 10; goto done; } if (parm[12] == 1 && !(0 <= parm[13] && parm[13] <= parm[14]) || parm[12] == 2 && parm[13] < 1) { ret = 11; goto done; } /* Initialize the graph object. */ if (G != NULL) { glp_erase_graph(G, G->v_size, G->a_size); glp_set_graph_name(G, "GRIDGEN"); } /* Copy the generator parameters. */ two_way = parm[1]; seed_original = seed = parm[2]; n_node = parm[3]; n = parm[4]; n_source = parm[5]; n_sink = parm[6]; avg_degree = parm[7]; t_supply = parm[8]; arc_costs.distribution = parm[9]; if (parm[9] == 1) { arc_costs.parameter[0] = parm[10]; arc_costs.parameter[1] = parm[11]; } else { arc_costs.parameter[0] = (double)parm[10] / 100.0; arc_costs.parameter[1] = 0.0; } capacities.distribution = parm[12]; if (parm[12] == 1) { capacities.parameter[0] = parm[13]; capacities.parameter[1] = parm[14]; } else { capacities.parameter[0] = (double)parm[13] / 100.0; capacities.parameter[1] = 0.0; } /* Calculate the edge lengths of the grid according to the input. */ if (n * n >= n_node) { n1 = n; n2 = (int)((double)n_node / (double)n + 0.5); } else { n2 = n; n1 = (int)((double)n_node / (double)n + 0.5); } /* Recalculate the total number of nodes and plus 1 for the super node. */ n_node = n1 * n2 + 1; n_arc = n_node * avg_degree; n_grid_arc = (two_way + 1) * ((n1 - 1) * n2 + (n2 - 1) * n1) + n_source + n_sink; if (n_grid_arc > n_arc) n_arc = n_grid_arc; arc_list = xcalloc(n_arc, sizeof(struct arcs)); source_list = xcalloc(n_source, sizeof(struct imbalance)); sink_list = xcalloc(n_sink, sizeof(struct imbalance)); /* Generate a random network. */ generate(csa); /* Output the network. */ output(csa); /* Free all allocated memory. */ xfree(arc_list); xfree(source_list); xfree(sink_list); /* The instance has been successfully generated. */ ret = 0; done: return ret; } #undef random static void assign_capacities(struct csa *csa) { /* Assign a capacity to each arc. */ struct arcs *arc_ptr = arc_list; int (*random)(struct csa *csa, double *); int i; /* Determine the random number generator to use. */ switch (arc_costs.distribution) { case UNIFORM: random = uniform; break; case EXPONENTIAL: random = exponential; break; default: xassert(csa != csa); } /* Assign capacities to grid arcs. */ for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) arc_ptr->u = random(csa, capacities.parameter); i = i - n_source - n_sink; /* Assign capacities to arcs to/from supernode. */ for (; i < n_grid_arc; i++, arc_ptr++) arc_ptr->u = t_supply; /* Assign capacities to all other arcs. */ for (; i < n_arc; i++, arc_ptr++) arc_ptr->u = random(csa, capacities.parameter); return; } static void assign_costs(struct csa *csa) { /* Assign a cost to each arc. */ struct arcs *arc_ptr = arc_list; int (*random)(struct csa *csa, double *); int i; /* A high cost assigned to arcs to/from the supernode. */ int high_cost; /* The maximum cost assigned to arcs in the base grid. */ int max_cost = 0; /* Determine the random number generator to use. */ switch (arc_costs.distribution) { case UNIFORM: random = uniform; break; case EXPONENTIAL: random = exponential; break; default: xassert(csa != csa); } /* Assign costs to arcs in the base grid. */ for (i = n_source + n_sink; i < n_grid_arc; i++, arc_ptr++) { arc_ptr->cost = random(csa, arc_costs.parameter); if (max_cost < arc_ptr->cost) max_cost = arc_ptr->cost; } i = i - n_source - n_sink; /* Assign costs to arcs to/from the super node. */ high_cost = max_cost * 2; for (; i < n_grid_arc; i++, arc_ptr++) arc_ptr->cost = high_cost; /* Assign costs to all other arcs. */ for (; i < n_arc; i++, arc_ptr++) arc_ptr->cost = random(csa, arc_costs.parameter); return; } static void assign_imbalance(struct csa *csa) { /* Assign an imbalance to each node. */ int total, i; double avg; struct imbalance *ptr; /* assign the supply nodes */ avg = 2.0 * t_supply / n_source; do { for (i = 1, total = t_supply, ptr = source_list + 1; i < n_source; i++, ptr++) { ptr->supply = (int)(randy(csa) * avg + 0.5); total -= ptr->supply; } source_list->supply = total; } /* redo all if the assignment "overshooted" */ while (total <= 0); /* assign the demand nodes */ avg = -2.0 * t_supply / n_sink; do { for (i = 1, total = t_supply, ptr = sink_list + 1; i < n_sink; i++, ptr++) { ptr->supply = (int)(randy(csa) * avg - 0.5); total += ptr->supply; } sink_list->supply = - total; } while (total <= 0); return; } static int exponential(struct csa *csa, double lambda[1]) { /* Returns an "exponentially distributed" integer with parameter lambda. */ return ((int)(- lambda[0] * log((double)randy(csa)) + 0.5)); } static struct arcs *gen_additional_arcs(struct csa *csa, struct arcs *arc_ptr) { /* Generate an arc from each source to the supernode and from supernode to each sink. */ int i; for (i = 0; i < n_source; i++, arc_ptr++) { arc_ptr->from = source_list[i].node; arc_ptr->to = n_node; } for (i = 0; i < n_sink; i++, arc_ptr++) { arc_ptr->to = sink_list[i].node; arc_ptr->from = n_node; } return arc_ptr; } static struct arcs *gen_basic_grid(struct csa *csa, struct arcs *arc_ptr) { /* Generate the basic grid. */ int direction = 1, i, j, k; if (two_way) { /* Generate an arc in each direction. */ for (i = 1; i < n_node; i += n1) { for (j = i, k = j + n1 - 1; j < k; j++) { arc_ptr->from = j; arc_ptr->to = j + 1; arc_ptr++; arc_ptr->from = j + 1; arc_ptr->to = j; arc_ptr++; } } for (i = 1; i <= n1; i++) { for (j = i + n1; j < n_node; j += n1) { arc_ptr->from = j; arc_ptr->to = j - n1; arc_ptr++; arc_ptr->from = j - n1; arc_ptr->to = j; arc_ptr++; } } } else { /* Generate one arc in each direction. */ for (i = 1; i < n_node; i += n1) { if (direction == 1) j = i; else j = i + 1; for (k = j + n1 - 1; j < k; j++) { arc_ptr->from = j; arc_ptr->to = j + direction; arc_ptr++; } direction = - direction; } for (i = 1; i <= n1; i++) { j = i + n1; if (direction == 1) { for (; j < n_node; j += n1) { arc_ptr->from = j - n1; arc_ptr->to = j; arc_ptr++; } } else { for (; j < n_node; j += n1) { arc_ptr->from = j - n1; arc_ptr->to = j; arc_ptr++; } } direction = - direction; } } return arc_ptr; } static void gen_more_arcs(struct csa *csa, struct arcs *arc_ptr) { /* Generate random arcs to meet the specified density. */ int i; double ab[2]; ab[0] = 0.9; ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the supernode cannot be selected */ for (i = n_grid_arc; i < n_arc; i++, arc_ptr++) { arc_ptr->from = uniform(csa, ab); arc_ptr->to = uniform(csa, ab); if (arc_ptr->from == arc_ptr->to) { arc_ptr--; i--; } } return; } static void generate(struct csa *csa) { /* Generate a random network. */ struct arcs *arc_ptr = arc_list; arc_ptr = gen_basic_grid(csa, arc_ptr); select_source_sinks(csa); arc_ptr = gen_additional_arcs(csa, arc_ptr); gen_more_arcs(csa, arc_ptr); assign_costs(csa); assign_capacities(csa); assign_imbalance(csa); return; } static void output(struct csa *csa) { /* Output the network in DIMACS format. */ struct arcs *arc_ptr; struct imbalance *imb_ptr; int i; if (G != NULL) goto skip; /* Output "c", "p" records. */ xprintf("c generated by GRIDGEN\n"); xprintf("c seed %d\n", seed_original); xprintf("c nodes %d\n", n_node); xprintf("c grid size %d X %d\n", n1, n2); xprintf("c sources %d sinks %d\n", n_source, n_sink); xprintf("c avg. degree %d\n", avg_degree); xprintf("c supply %d\n", t_supply); switch (arc_costs.distribution) { case UNIFORM: xprintf("c arc costs: UNIFORM distr. min %d max %d\n", (int)arc_costs.parameter[0], (int)arc_costs.parameter[1]); break; case EXPONENTIAL: xprintf("c arc costs: EXPONENTIAL distr. lambda %d\n", (int)arc_costs.parameter[0]); break; default: xassert(csa != csa); } switch (capacities.distribution) { case UNIFORM: xprintf("c arc caps : UNIFORM distr. min %d max %d\n", (int)capacities.parameter[0], (int)capacities.parameter[1]); break; case EXPONENTIAL: xprintf("c arc caps : EXPONENTIAL distr. %d lambda %d\n", (int)capacities.parameter[0]); break; default: xassert(csa != csa); } skip: if (G == NULL) xprintf("p min %d %d\n", n_node, n_arc); else { glp_add_vertices(G, n_node); if (v_rhs >= 0) { double zero = 0.0; for (i = 1; i <= n_node; i++) { glp_vertex *v = G->v[i]; memcpy((char *)v->data + v_rhs, &zero, sizeof(double)); } } } /* Output "n node supply". */ for (i = 0, imb_ptr = source_list; i < n_source; i++, imb_ptr++) { if (G == NULL) xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); else { if (v_rhs >= 0) { double temp = (double)imb_ptr->supply; glp_vertex *v = G->v[imb_ptr->node]; memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); } } } for (i = 0, imb_ptr = sink_list; i < n_sink; i++, imb_ptr++) { if (G == NULL) xprintf("n %d %d\n", imb_ptr->node, imb_ptr->supply); else { if (v_rhs >= 0) { double temp = (double)imb_ptr->supply; glp_vertex *v = G->v[imb_ptr->node]; memcpy((char *)v->data + v_rhs, &temp, sizeof(double)); } } } /* Output "a from to lowcap=0 hicap cost". */ for (i = 0, arc_ptr = arc_list; i < n_arc; i++, arc_ptr++) { if (G == NULL) xprintf("a %d %d 0 %d %d\n", arc_ptr->from, arc_ptr->to, arc_ptr->u, arc_ptr->cost); else { glp_arc *a = glp_add_arc(G, arc_ptr->from, arc_ptr->to); if (a_cap >= 0) { double temp = (double)arc_ptr->u; memcpy((char *)a->data + a_cap, &temp, sizeof(double)); } if (a_cost >= 0) { double temp = (double)arc_ptr->cost; memcpy((char *)a->data + a_cost, &temp, sizeof(double)); } } } return; } static double randy(struct csa *csa) { /* Returns a random number between 0.0 and 1.0. See Ward Cheney & David Kincaid, "Numerical Mathematics and Computing," 2Ed, pp. 335. */ seed = 16807 * seed % 2147483647; if (seed < 0) seed = - seed; return seed * 4.6566128752459e-10; } static void select_source_sinks(struct csa *csa) { /* Randomly select the source nodes and sink nodes. */ int i, *int_ptr; int *temp_list; /* a temporary list of nodes */ struct imbalance *ptr; double ab[2]; /* parameter for random number generator */ ab[0] = 0.9; ab[1] = n_node - 0.99; /* upper limit is n_node-1 because the supernode cannot be selected */ temp_list = xcalloc(n_node, sizeof(int)); for (i = 0, int_ptr = temp_list; i < n_node; i++, int_ptr++) *int_ptr = 0; /* Select the source nodes. */ for (i = 0, ptr = source_list; i < n_source; i++, ptr++) { ptr->node = uniform(csa, ab); if (temp_list[ptr->node] == 1) /* check for duplicates */ { ptr--; i--; } else temp_list[ptr->node] = 1; } /* Select the sink nodes. */ for (i = 0, ptr = sink_list; i < n_sink; i++, ptr++) { ptr->node = uniform(csa, ab); if (temp_list[ptr->node] == 1) { ptr--; i--; } else temp_list[ptr->node] = 1; } xfree(temp_list); return; } int uniform(struct csa *csa, double a[2]) { /* Generates an integer uniformly selected from [a[0],a[1]]. */ return (int)((a[1] - a[0]) * randy(csa) + a[0] + 0.5); } /**********************************************************************/ #if 0 int main(void) { int parm[1+14]; double temp; scanf("%d", &parm[1]); scanf("%d", &parm[2]); scanf("%d", &parm[3]); scanf("%d", &parm[4]); scanf("%d", &parm[5]); scanf("%d", &parm[6]); scanf("%d", &parm[7]); scanf("%d", &parm[8]); scanf("%d", &parm[9]); if (parm[9] == 1) { scanf("%d", &parm[10]); scanf("%d", &parm[11]); } else { scanf("%le", &temp); parm[10] = (int)(100.0 * temp + .5); parm[11] = 0; } scanf("%d", &parm[12]); if (parm[12] == 1) { scanf("%d", &parm[13]); scanf("%d", &parm[14]); } else { scanf("%le", &temp); parm[13] = (int)(100.0 * temp + .5); parm[14] = 0; } glp_gridgen(NULL, 0, 0, 0, parm); return 0; } #endif /* eof */ glpk-4.52.1/src/glpnet05.c0000644000062000006210000002600212175147600014312 0ustar maomkpasswd/* glpnet05.c (Goldfarb's maximum flow problem generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * This code is a modified version of the program RMFGEN, a maxflow * problem generator developed by D.Goldfarb and M.Grigoriadis, and * originally implemented by Tamas Badics . * The original code is publically available on the DIMACS ftp site at: * . * * All changes concern only the program interface, so this modified * version produces exactly the same instances as the original version. * * Changes were made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "rng.h" /*********************************************************************** * NAME * * glp_rmfgen - Goldfarb's maximum flow problem generator * * SYNOPSIS * * int glp_rmfgen(glp_graph *G, int *s, int *t, int a_cap, * const int parm[1+5]); * * DESCRIPTION * * The routine glp_rmfgen is a maximum flow problem generator developed * by D.Goldfarb and M.Grigoriadis. * * The parameter G specifies the graph object, to which the generated * problem data have to be stored. Note that on entry the graph object * is erased with the routine glp_erase_graph. * * The pointer s specifies a location, to which the routine stores the * source node number. If s is NULL, the node number is not stored. * * The pointer t specifies a location, to which the routine stores the * sink node number. If t is NULL, the node number is not stored. * * The parameter a_cap specifies an offset of the field of type double * in the arc data block, to which the routine stores the arc capacity. * If a_cap < 0, the capacity is not stored. * * The array parm contains description of the network to be generated: * * parm[0] not used * parm[1] (seed) random number seed (a positive integer) * parm[2] (a) frame size * parm[3] (b) depth * parm[4] (c1) minimal arc capacity * parm[5] (c2) maximal arc capacity * * RETURNS * * If the instance was successfully generated, the routine glp_netgen * returns zero; otherwise, if specified parameters are inconsistent, * the routine returns a non-zero error code. * * COMMENTS * * The generated network is as follows. It has b pieces of frames of * size a * a. (So alltogether the number of vertices is a * a * b) * * In each frame all the vertices are connected with their neighbours * (forth and back). In addition the vertices of a frame are connected * one to one with the vertices of next frame using a random permutation * of those vertices. * * The source is the lower left vertex of the first frame, the sink is * the upper right vertex of the b'th frame. * * t * +-------+ * | .| * | . | * / | / | * +-------+/ -+ b * | | |/. * a | -v- |/ * | | |/ * +-------+ 1 * s a * * The capacities are randomly chosen integers from the range of [c1,c2] * in the case of interconnecting edges, and c2 * a * a for the in-frame * edges. * * REFERENCES * * D.Goldfarb and M.D.Grigoriadis, "A computational comparison of the * Dinic and network simplex methods for maximum flow." Annals of Op. * Res. 13 (1988), pp. 83-123. * * U.Derigs and W.Meier, "Implementing Goldberg's max-flow algorithm: * A computational investigation." Zeitschrift fuer Operations Research * 33 (1989), pp. 383-403. */ typedef struct VERTEX { struct EDGE **edgelist; /* Pointer to the list of pointers to the adjacent edges. (No matter that to or from edges) */ struct EDGE **current; /* Pointer to the current edge */ int degree; /* Number of adjacent edges (both direction) */ int index; } vertex; typedef struct EDGE { int from; int to; int cap; /* Capacity */ } edge; typedef struct NETWORK { struct NETWORK *next, *prev; int vertnum; int edgenum; vertex *verts; /* Vertex array[1..vertnum] */ edge *edges; /* Edge array[1..edgenum] */ int source; /* Pointer to the source */ int sink; /* Pointer to the sink */ } network; struct csa { /* common storage area */ glp_graph *G; int *s, *t, a_cap; RNG *rand; network *N; int *Parr; int A, AA, C2AA, Ec; }; #define G (csa->G) #define s (csa->s) #define t (csa->t) #define a_cap (csa->a_cap) #define N (csa->N) #define Parr (csa->Parr) #define A (csa->A) #define AA (csa->AA) #define C2AA (csa->C2AA) #define Ec (csa->Ec) #undef random #define random(A) (int)(rng_unif_01(csa->rand) * (double)(A)) #define RANDOM(A, B) (int)(random((B) - (A) + 1) + (A)) #define sgn(A) (((A) > 0) ? 1 : ((A) == 0) ? 0 : -1) static void make_edge(struct csa *csa, int from, int to, int c1, int c2) { Ec++; N->edges[Ec].from = from; N->edges[Ec].to = to; N->edges[Ec].cap = RANDOM(c1, c2); return; } static void permute(struct csa *csa) { int i, j, tmp; for (i = 1; i < AA; i++) { j = RANDOM(i, AA); tmp = Parr[i]; Parr[i] = Parr[j]; Parr[j] = tmp; } return; } static void connect(struct csa *csa, int offset, int cv, int x1, int y1) { int cv1; cv1 = offset + (x1 - 1) * A + y1; Ec++; N->edges[Ec].from = cv; N->edges[Ec].to = cv1; N->edges[Ec].cap = C2AA; return; } static network *gen_rmf(struct csa *csa, int a, int b, int c1, int c2) { /* generates a network with a*a*b nodes and 6a*a*b-4ab-2a*a edges random_frame network: Derigs & Meier, Methods & Models of OR (1989), 33:383-403 */ int x, y, z, offset, cv; A = a; AA = a * a; C2AA = c2 * AA; Ec = 0; N = (network *)xmalloc(sizeof(network)); N->vertnum = AA * b; N->edgenum = 5 * AA * b - 4 * A * b - AA; N->edges = (edge *)xcalloc(N->edgenum + 1, sizeof(edge)); N->source = 1; N->sink = N->vertnum; Parr = (int *)xcalloc(AA + 1, sizeof(int)); for (x = 1; x <= AA; x++) Parr[x] = x; for (z = 1; z <= b; z++) { offset = AA * (z - 1); if (z != b) permute(csa); for (x = 1; x <= A; x++) { for (y = 1; y <= A; y++) { cv = offset + (x - 1) * A + y; if (z != b) make_edge(csa, cv, offset + AA + Parr[cv - offset], c1, c2); /* the intermediate edges */ if (y < A) connect(csa, offset, cv, x, y + 1); if (y > 1) connect(csa, offset, cv, x, y - 1); if (x < A) connect(csa, offset, cv, x + 1, y); if (x > 1) connect(csa, offset, cv, x - 1, y); } } } xfree(Parr); return N; } static void print_max_format(struct csa *csa, network *n, char *comm[], int dim) { /* prints a network heading with dim lines of comments (no \n needs at the ends) */ int i, vnum, e_num; edge *e; vnum = n->vertnum; e_num = n->edgenum; if (G == NULL) { for (i = 0; i < dim; i++) xprintf("c %s\n", comm[i]); xprintf("p max %7d %10d\n", vnum, e_num); xprintf("n %7d s\n", n->source); xprintf("n %7d t\n", n->sink); } else { glp_add_vertices(G, vnum); if (s != NULL) *s = n->source; if (t != NULL) *t = n->sink; } for (i = 1; i <= e_num; i++) { e = &n->edges[i]; if (G == NULL) xprintf("a %7d %7d %10d\n", e->from, e->to, (int)e->cap); else { glp_arc *a = glp_add_arc(G, e->from, e->to); if (a_cap >= 0) { double temp = (double)e->cap; memcpy((char *)a->data + a_cap, &temp, sizeof(double)); } } } return; } static void gen_free_net(network *n) { xfree(n->edges); xfree(n); return; } int glp_rmfgen(glp_graph *G_, int *_s, int *_t, int _a_cap, const int parm[1+5]) { struct csa _csa, *csa = &_csa; network *n; char comm[10][80], *com1[10]; int seed, a, b, c1, c2, ret; G = G_; s = _s; t = _t; a_cap = _a_cap; if (G != NULL) { if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double)) xerror("glp_rmfgen: a_cap = %d; invalid offset\n", a_cap); } seed = parm[1]; a = parm[2]; b = parm[3]; c1 = parm[4]; c2 = parm[5]; if (!(seed > 0 && 1 <= a && a <= 1000 && 1 <= b && b <= 1000 && 0 <= c1 && c1 <= c2 && c2 <= 1000)) { ret = 1; goto done; } if (G != NULL) { glp_erase_graph(G, G->v_size, G->a_size); glp_set_graph_name(G, "RMFGEN"); } csa->rand = rng_create_rand(); rng_init_rand(csa->rand, seed); n = gen_rmf(csa, a, b, c1, c2); sprintf(comm[0], "This file was generated by genrmf."); sprintf(comm[1], "The parameters are: a: %d b: %d c1: %d c2: %d", a, b, c1, c2); com1[0] = comm[0]; com1[1] = comm[1]; print_max_format(csa, n, com1, 2); gen_free_net(n); rng_delete_rand(csa->rand); ret = 0; done: return ret; } /**********************************************************************/ #if 0 int main(int argc, char *argv[]) { int seed, a, b, c1, c2, i, parm[1+5]; seed = 123; a = b = c1 = c2 = -1; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-seed") == 0) seed = atoi(argv[++i]); else if (strcmp(argv[i], "-a") == 0) a = atoi(argv[++i]); else if (strcmp(argv[i], "-b") == 0) b = atoi(argv[++i]); else if (strcmp(argv[i], "-c1") == 0) c1 = atoi(argv[++i]); else if (strcmp(argv[i], "-c2") == 0) c2 = atoi(argv[++i]); } if (a < 0 || b < 0 || c1 < 0 || c2 < 0) { xprintf("Usage:\n"); xprintf("genrmf [-seed seed] -a frame_size -b depth\n"); xprintf(" -c1 cap_range1 -c2 cap_range2\n"); } else { parm[1] = seed; parm[2] = a; parm[3] = b; parm[4] = c1; parm[5] = c2; glp_rmfgen(NULL, NULL, NULL, 0, parm); } return 0; } #endif /* eof */ glpk-4.52.1/src/glpnpp.h0000644000062000006210000005331712175147600014172 0ustar maomkpasswd/* glpnpp.h (LP/MIP preprocessor) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPNPP_H #define GLPNPP_H #include "glpapi.h" typedef struct NPP NPP; typedef struct NPPROW NPPROW; typedef struct NPPCOL NPPCOL; typedef struct NPPAIJ NPPAIJ; typedef struct NPPTSE NPPTSE; typedef struct NPPLFE NPPLFE; struct NPP { /* LP/MIP preprocessor workspace */ /*--------------------------------------------------------------*/ /* original problem segment */ int orig_dir; /* optimization direction flag: GLP_MIN - minimization GLP_MAX - maximization */ int orig_m; /* number of rows */ int orig_n; /* number of columns */ int orig_nnz; /* number of non-zero constraint coefficients */ /*--------------------------------------------------------------*/ /* transformed problem segment (always minimization) */ DMP *pool; /* memory pool to store problem components */ char *name; /* problem name (1 to 255 chars); NULL means no name is assigned to the problem */ char *obj; /* objective function name (1 to 255 chars); NULL means no name is assigned to the objective function */ double c0; /* constant term of the objective function */ int nrows; /* number of rows introduced into the problem; this count increases by one every time a new row is added and never decreases; thus, actual number of rows may be less than nrows due to row deletions */ int ncols; /* number of columns introduced into the problem; this count increases by one every time a new column is added and never decreases; thus, actual number of column may be less than ncols due to column deletions */ NPPROW *r_head; /* pointer to the beginning of the row list */ NPPROW *r_tail; /* pointer to the end of the row list */ NPPCOL *c_head; /* pointer to the beginning of the column list */ NPPCOL *c_tail; /* pointer to the end of the column list */ /*--------------------------------------------------------------*/ /* transformation history */ DMP *stack; /* memory pool to store transformation entries */ NPPTSE *top; /* pointer to most recent transformation entry */ #if 0 /* 16/XII-2009 */ int count[1+25]; /* transformation statistics */ #endif /*--------------------------------------------------------------*/ /* resultant (preprocessed) problem segment */ int m; /* number of rows */ int n; /* number of columns */ int nnz; /* number of non-zero constraint coefficients */ int *row_ref; /* int row_ref[1+m]; */ /* row_ref[i], 1 <= i <= m, is the reference number assigned to a row, which is i-th row of the resultant problem */ int *col_ref; /* int col_ref[1+n]; */ /* col_ref[j], 1 <= j <= n, is the reference number assigned to a column, which is j-th column of the resultant problem */ /*--------------------------------------------------------------*/ /* recovered solution segment */ int sol; /* solution indicator: GLP_SOL - basic solution GLP_IPT - interior-point solution GLP_MIP - mixed integer solution */ int scaling; /* scaling option: GLP_OFF - scaling is disabled GLP_ON - scaling is enabled */ int p_stat; /* status of primal basic solution: GLP_UNDEF - primal solution is undefined GLP_FEAS - primal solution is feasible GLP_INFEAS - primal solution is infeasible GLP_NOFEAS - no primal feasible solution exists */ int d_stat; /* status of dual basic solution: GLP_UNDEF - dual solution is undefined GLP_FEAS - dual solution is feasible GLP_INFEAS - dual solution is infeasible GLP_NOFEAS - no dual feasible solution exists */ int t_stat; /* status of interior-point solution: GLP_UNDEF - interior solution is undefined GLP_OPT - interior solution is optimal */ int i_stat; /* status of mixed integer solution: GLP_UNDEF - integer solution is undefined GLP_OPT - integer solution is optimal GLP_FEAS - integer solution is feasible GLP_NOFEAS - no integer solution exists */ char *r_stat; /* char r_stat[1+nrows]; */ /* r_stat[i], 1 <= i <= nrows, is status of i-th row: GLP_BS - inactive constraint GLP_NL - active constraint on lower bound GLP_NU - active constraint on upper bound GLP_NF - active free row GLP_NS - active equality constraint */ char *c_stat; /* char c_stat[1+nrows]; */ /* c_stat[j], 1 <= j <= nrows, is status of j-th column: GLP_BS - basic variable GLP_NL - non-basic variable on lower bound GLP_NU - non-basic variable on upper bound GLP_NF - non-basic free variable GLP_NS - non-basic fixed variable */ double *r_pi; /* double r_pi[1+nrows]; */ /* r_pi[i], 1 <= i <= nrows, is Lagrange multiplier (dual value) for i-th row (constraint) */ double *c_value; /* double c_value[1+ncols]; */ /* c_value[j], 1 <= j <= ncols, is primal value of j-th column (structural variable) */ }; struct NPPROW { /* row (constraint) */ int i; /* reference number assigned to the row, 1 <= i <= nrows */ char *name; /* row name (1 to 255 chars); NULL means no name is assigned to the row */ double lb; /* lower bound; -DBL_MAX means the row has no lower bound */ double ub; /* upper bound; +DBL_MAX means the row has no upper bound */ NPPAIJ *ptr; /* pointer to the linked list of constraint coefficients */ int temp; /* working field used by preprocessor routines */ NPPROW *prev; /* pointer to previous row in the row list */ NPPROW *next; /* pointer to next row in the row list */ }; struct NPPCOL { /* column (variable) */ int j; /* reference number assigned to the column, 1 <= j <= ncols */ char *name; /* column name (1 to 255 chars); NULL means no name is assigned to the column */ char is_int; /* 0 means continuous variable; 1 means integer variable */ double lb; /* lower bound; -DBL_MAX means the column has no lower bound */ double ub; /* upper bound; +DBL_MAX means the column has no upper bound */ double coef; /* objective coefficient */ NPPAIJ *ptr; /* pointer to the linked list of constraint coefficients */ int temp; /* working field used by preprocessor routines */ #if 1 /* 28/XII-2009 */ union { double ll; /* implied column lower bound */ int pos; /* vertex ordinal number corresponding to this binary column in the conflict graph (0, if the vertex does not exist) */ } ll; union { double uu; /* implied column upper bound */ int neg; /* vertex ordinal number corresponding to complement of this binary column in the conflict graph (0, if the vertex does not exist) */ } uu; #endif NPPCOL *prev; /* pointer to previous column in the column list */ NPPCOL *next; /* pointer to next column in the column list */ }; struct NPPAIJ { /* constraint coefficient */ NPPROW *row; /* pointer to corresponding row */ NPPCOL *col; /* pointer to corresponding column */ double val; /* (non-zero) coefficient value */ NPPAIJ *r_prev; /* pointer to previous coefficient in the same row */ NPPAIJ *r_next; /* pointer to next coefficient in the same row */ NPPAIJ *c_prev; /* pointer to previous coefficient in the same column */ NPPAIJ *c_next; /* pointer to next coefficient in the same column */ }; struct NPPTSE { /* transformation stack entry */ int (*func)(NPP *npp, void *info); /* pointer to routine performing back transformation */ void *info; /* pointer to specific info (depends on the transformation) */ NPPTSE *link; /* pointer to another entry created *before* this entry */ }; struct NPPLFE { /* linear form element */ int ref; /* row/column reference number */ double val; /* (non-zero) coefficient value */ NPPLFE *next; /* pointer to another element */ }; #define npp_create_wksp _glp_npp_create_wksp NPP *npp_create_wksp(void); /* create LP/MIP preprocessor workspace */ #define npp_insert_row _glp_npp_insert_row void npp_insert_row(NPP *npp, NPPROW *row, int where); /* insert row to the row list */ #define npp_remove_row _glp_npp_remove_row void npp_remove_row(NPP *npp, NPPROW *row); /* remove row from the row list */ #define npp_activate_row _glp_npp_activate_row void npp_activate_row(NPP *npp, NPPROW *row); /* make row active */ #define npp_deactivate_row _glp_npp_deactivate_row void npp_deactivate_row(NPP *npp, NPPROW *row); /* make row inactive */ #define npp_insert_col _glp_npp_insert_col void npp_insert_col(NPP *npp, NPPCOL *col, int where); /* insert column to the column list */ #define npp_remove_col _glp_npp_remove_col void npp_remove_col(NPP *npp, NPPCOL *col); /* remove column from the column list */ #define npp_activate_col _glp_npp_activate_col void npp_activate_col(NPP *npp, NPPCOL *col); /* make column active */ #define npp_deactivate_col _glp_npp_deactivate_col void npp_deactivate_col(NPP *npp, NPPCOL *col); /* make column inactive */ #define npp_add_row _glp_npp_add_row NPPROW *npp_add_row(NPP *npp); /* add new row to the current problem */ #define npp_add_col _glp_npp_add_col NPPCOL *npp_add_col(NPP *npp); /* add new column to the current problem */ #define npp_add_aij _glp_npp_add_aij NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val); /* add new element to the constraint matrix */ #define npp_row_nnz _glp_npp_row_nnz int npp_row_nnz(NPP *npp, NPPROW *row); /* count number of non-zero coefficients in row */ #define npp_col_nnz _glp_npp_col_nnz int npp_col_nnz(NPP *npp, NPPCOL *col); /* count number of non-zero coefficients in column */ #define npp_push_tse _glp_npp_push_tse void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info), int size); /* push new entry to the transformation stack */ #define npp_erase_row _glp_npp_erase_row void npp_erase_row(NPP *npp, NPPROW *row); /* erase row content to make it empty */ #define npp_del_row _glp_npp_del_row void npp_del_row(NPP *npp, NPPROW *row); /* remove row from the current problem */ #define npp_del_col _glp_npp_del_col void npp_del_col(NPP *npp, NPPCOL *col); /* remove column from the current problem */ #define npp_del_aij _glp_npp_del_aij void npp_del_aij(NPP *npp, NPPAIJ *aij); /* remove element from the constraint matrix */ #define npp_load_prob _glp_npp_load_prob void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol, int scaling); /* load original problem into the preprocessor workspace */ #define npp_build_prob _glp_npp_build_prob void npp_build_prob(NPP *npp, glp_prob *prob); /* build resultant (preprocessed) problem */ #define npp_postprocess _glp_npp_postprocess void npp_postprocess(NPP *npp, glp_prob *prob); /* postprocess solution from the resultant problem */ #define npp_unload_sol _glp_npp_unload_sol void npp_unload_sol(NPP *npp, glp_prob *orig); /* store solution to the original problem */ #define npp_delete_wksp _glp_npp_delete_wksp void npp_delete_wksp(NPP *npp); /* delete LP/MIP preprocessor workspace */ #define npp_error() #define npp_free_row _glp_npp_free_row void npp_free_row(NPP *npp, NPPROW *p); /* process free (unbounded) row */ #define npp_geq_row _glp_npp_geq_row void npp_geq_row(NPP *npp, NPPROW *p); /* process row of 'not less than' type */ #define npp_leq_row _glp_npp_leq_row void npp_leq_row(NPP *npp, NPPROW *p); /* process row of 'not greater than' type */ #define npp_free_col _glp_npp_free_col void npp_free_col(NPP *npp, NPPCOL *q); /* process free (unbounded) column */ #define npp_lbnd_col _glp_npp_lbnd_col void npp_lbnd_col(NPP *npp, NPPCOL *q); /* process column with (non-zero) lower bound */ #define npp_ubnd_col _glp_npp_ubnd_col void npp_ubnd_col(NPP *npp, NPPCOL *q); /* process column with upper bound */ #define npp_dbnd_col _glp_npp_dbnd_col void npp_dbnd_col(NPP *npp, NPPCOL *q); /* process non-negative column with upper bound */ #define npp_fixed_col _glp_npp_fixed_col void npp_fixed_col(NPP *npp, NPPCOL *q); /* process fixed column */ #define npp_make_equality _glp_npp_make_equality int npp_make_equality(NPP *npp, NPPROW *p); /* process row with almost identical bounds */ #define npp_make_fixed _glp_npp_make_fixed int npp_make_fixed(NPP *npp, NPPCOL *q); /* process column with almost identical bounds */ #define npp_empty_row _glp_npp_empty_row int npp_empty_row(NPP *npp, NPPROW *p); /* process empty row */ #define npp_empty_col _glp_npp_empty_col int npp_empty_col(NPP *npp, NPPCOL *q); /* process empty column */ #define npp_implied_value _glp_npp_implied_value int npp_implied_value(NPP *npp, NPPCOL *q, double s); /* process implied column value */ #define npp_eq_singlet _glp_npp_eq_singlet int npp_eq_singlet(NPP *npp, NPPROW *p); /* process row singleton (equality constraint) */ #define npp_implied_lower _glp_npp_implied_lower int npp_implied_lower(NPP *npp, NPPCOL *q, double l); /* process implied column lower bound */ #define npp_implied_upper _glp_npp_implied_upper int npp_implied_upper(NPP *npp, NPPCOL *q, double u); /* process implied upper bound of column */ #define npp_ineq_singlet _glp_npp_ineq_singlet int npp_ineq_singlet(NPP *npp, NPPROW *p); /* process row singleton (inequality constraint) */ #define npp_implied_slack _glp_npp_implied_slack void npp_implied_slack(NPP *npp, NPPCOL *q); /* process column singleton (implied slack variable) */ #define npp_implied_free _glp_npp_implied_free int npp_implied_free(NPP *npp, NPPCOL *q); /* process column singleton (implied free variable) */ #define npp_eq_doublet _glp_npp_eq_doublet NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p); /* process row doubleton (equality constraint) */ #define npp_forcing_row _glp_npp_forcing_row int npp_forcing_row(NPP *npp, NPPROW *p, int at); /* process forcing row */ #define npp_analyze_row _glp_npp_analyze_row int npp_analyze_row(NPP *npp, NPPROW *p); /* perform general row analysis */ #define npp_inactive_bound _glp_npp_inactive_bound void npp_inactive_bound(NPP *npp, NPPROW *p, int which); /* remove row lower/upper inactive bound */ #define npp_implied_bounds _glp_npp_implied_bounds void npp_implied_bounds(NPP *npp, NPPROW *p); /* determine implied column bounds */ #define npp_binarize_prob _glp_npp_binarize_prob int npp_binarize_prob(NPP *npp); /* binarize MIP problem */ #define npp_is_packing _glp_npp_is_packing int npp_is_packing(NPP *npp, NPPROW *row); /* test if constraint is packing inequality */ #define npp_hidden_packing _glp_npp_hidden_packing int npp_hidden_packing(NPP *npp, NPPROW *row); /* identify hidden packing inequality */ #define npp_implied_packing _glp_npp_implied_packing int npp_implied_packing(NPP *npp, NPPROW *row, int which, NPPCOL *var[], char set[]); /* identify implied packing inequality */ #define npp_is_covering _glp_npp_is_covering int npp_is_covering(NPP *npp, NPPROW *row); /* test if constraint is covering inequality */ #define npp_hidden_covering _glp_npp_hidden_covering int npp_hidden_covering(NPP *npp, NPPROW *row); /* identify hidden covering inequality */ #define npp_is_partitioning _glp_npp_is_partitioning int npp_is_partitioning(NPP *npp, NPPROW *row); /* test if constraint is partitioning equality */ #define npp_reduce_ineq_coef _glp_npp_reduce_ineq_coef int npp_reduce_ineq_coef(NPP *npp, NPPROW *row); /* reduce inequality constraint coefficients */ #define npp_clean_prob _glp_npp_clean_prob void npp_clean_prob(NPP *npp); /* perform initial LP/MIP processing */ #define npp_process_row _glp_npp_process_row int npp_process_row(NPP *npp, NPPROW *row, int hard); /* perform basic row processing */ #define npp_improve_bounds _glp_npp_improve_bounds int npp_improve_bounds(NPP *npp, NPPROW *row, int flag); /* improve current column bounds */ #define npp_process_col _glp_npp_process_col int npp_process_col(NPP *npp, NPPCOL *col); /* perform basic column processing */ #define npp_process_prob _glp_npp_process_prob int npp_process_prob(NPP *npp, int hard); /* perform basic LP/MIP processing */ #define npp_simplex _glp_npp_simplex int npp_simplex(NPP *npp, const glp_smcp *parm); /* process LP prior to applying primal/dual simplex method */ #define npp_integer _glp_npp_integer int npp_integer(NPP *npp, const glp_iocp *parm); /* process MIP prior to applying branch-and-bound method */ /**********************************************************************/ #define npp_sat_free_row _glp_npp_sat_free_row void npp_sat_free_row(NPP *npp, NPPROW *p); /* process free (unbounded) row */ #define npp_sat_fixed_col _glp_npp_sat_fixed_col int npp_sat_fixed_col(NPP *npp, NPPCOL *q); /* process fixed column */ #define npp_sat_is_bin_comb _glp_npp_sat_is_bin_comb int npp_sat_is_bin_comb(NPP *npp, NPPROW *row); /* test if row is binary combination */ #define npp_sat_num_pos_coef _glp_npp_sat_num_pos_coef int npp_sat_num_pos_coef(NPP *npp, NPPROW *row); /* determine number of positive coefficients */ #define npp_sat_num_neg_coef _glp_npp_sat_num_neg_coef int npp_sat_num_neg_coef(NPP *npp, NPPROW *row); /* determine number of negative coefficients */ #define npp_sat_is_cover_ineq _glp_npp_sat_is_cover_ineq int npp_sat_is_cover_ineq(NPP *npp, NPPROW *row); /* test if row is covering inequality */ #define npp_sat_is_pack_ineq _glp_npp_sat_is_pack_ineq int npp_sat_is_pack_ineq(NPP *npp, NPPROW *row); /* test if row is packing inequality */ #define npp_sat_is_partn_eq _glp_npp_sat_is_partn_eq int npp_sat_is_partn_eq(NPP *npp, NPPROW *row); /* test if row is partitioning equality */ #define npp_sat_reverse_row _glp_npp_sat_reverse_row int npp_sat_reverse_row(NPP *npp, NPPROW *row); /* multiply both sides of row by -1 */ #define npp_sat_split_pack _glp_npp_sat_split_pack NPPROW *npp_sat_split_pack(NPP *npp, NPPROW *row, int nnn); /* split packing inequality */ #define npp_sat_encode_pack _glp_npp_sat_encode_pack void npp_sat_encode_pack(NPP *npp, NPPROW *row); /* encode packing inequality */ typedef struct NPPLIT NPPLIT; typedef struct NPPLSE NPPLSE; typedef struct NPPSED NPPSED; struct NPPLIT { /* literal (binary variable or its negation) */ NPPCOL *col; /* pointer to binary variable; NULL means constant false */ int neg; /* negation flag: 0 - literal is variable (or constant false) 1 - literal is negation of variable (or constant true) */ }; struct NPPLSE { /* literal set element */ NPPLIT lit; /* literal */ NPPLSE *next; /* pointer to another element */ }; struct NPPSED { /* summation encoding descriptor */ /* this struct describes the equality x + y + z = s + 2 * c, which was encoded as CNF and included into the transformed problem; here x and y are literals, z is either a literal or constant zero, s and c are binary variables modeling, resp., the low and high (carry) sum bits */ NPPLIT x, y, z; /* literals; if z.col = NULL, z is constant zero */ NPPCOL *s, *c; /* binary variables modeling the sum bits */ }; #define npp_sat_encode_sum2 _glp_npp_sat_encode_sum2 void npp_sat_encode_sum2(NPP *npp, NPPLSE *set, NPPSED *sed); /* encode 2-bit summation */ #define npp_sat_encode_sum3 _glp_npp_sat_encode_sum3 void npp_sat_encode_sum3(NPP *npp, NPPLSE *set, NPPSED *sed); /* encode 3-bit summation */ #define npp_sat_encode_sum_ax _glp_npp_sat_encode_sum_ax int npp_sat_encode_sum_ax(NPP *npp, NPPROW *row, NPPLIT y[]); /* encode linear combination of 0-1 variables */ #define npp_sat_normalize_clause _glp_npp_sat_normalize_clause int npp_sat_normalize_clause(NPP *npp, int size, NPPLIT lit[]); /* normalize clause */ #define npp_sat_encode_clause _glp_npp_sat_encode_clause NPPROW *npp_sat_encode_clause(NPP *npp, int size, NPPLIT lit[]); /* translate clause to cover inequality */ #define npp_sat_encode_geq _glp_npp_sat_encode_geq int npp_sat_encode_geq(NPP *npp, int n, NPPLIT y[], int rhs); /* encode "not less than" constraint */ #define npp_sat_encode_leq _glp_npp_sat_encode_leq int npp_sat_encode_leq(NPP *npp, int n, NPPLIT y[], int rhs); /* encode "not greater than" constraint */ #define npp_sat_encode_row _glp_npp_sat_encode_row int npp_sat_encode_row(NPP *npp, NPPROW *row); /* encode constraint (row) of general type */ #define npp_sat_encode_prob _glp_npp_sat_encode_prob int npp_sat_encode_prob(NPP *npp); /* encode 0-1 feasibility problem */ #endif /* eof */ glpk-4.52.1/src/glpnpp01.c0000644000062000006210000007127712175147600014333 0ustar maomkpasswd/* glpnpp01.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpnpp.h" NPP *npp_create_wksp(void) { /* create LP/MIP preprocessor workspace */ NPP *npp; npp = xmalloc(sizeof(NPP)); npp->orig_dir = 0; npp->orig_m = npp->orig_n = npp->orig_nnz = 0; npp->pool = dmp_create_pool(); npp->name = npp->obj = NULL; npp->c0 = 0.0; npp->nrows = npp->ncols = 0; npp->r_head = npp->r_tail = NULL; npp->c_head = npp->c_tail = NULL; npp->stack = dmp_create_pool(); npp->top = NULL; #if 0 /* 16/XII-2009 */ memset(&npp->count, 0, sizeof(npp->count)); #endif npp->m = npp->n = npp->nnz = 0; npp->row_ref = npp->col_ref = NULL; npp->sol = npp->scaling = 0; npp->p_stat = npp->d_stat = npp->t_stat = npp->i_stat = 0; npp->r_stat = NULL; /*npp->r_prim =*/ npp->r_pi = NULL; npp->c_stat = NULL; npp->c_value = /*npp->c_dual =*/ NULL; return npp; } void npp_insert_row(NPP *npp, NPPROW *row, int where) { /* insert row to the row list */ if (where == 0) { /* insert row to the beginning of the row list */ row->prev = NULL; row->next = npp->r_head; if (row->next == NULL) npp->r_tail = row; else row->next->prev = row; npp->r_head = row; } else { /* insert row to the end of the row list */ row->prev = npp->r_tail; row->next = NULL; if (row->prev == NULL) npp->r_head = row; else row->prev->next = row; npp->r_tail = row; } return; } void npp_remove_row(NPP *npp, NPPROW *row) { /* remove row from the row list */ if (row->prev == NULL) npp->r_head = row->next; else row->prev->next = row->next; if (row->next == NULL) npp->r_tail = row->prev; else row->next->prev = row->prev; return; } void npp_activate_row(NPP *npp, NPPROW *row) { /* make row active */ if (!row->temp) { row->temp = 1; /* move the row to the beginning of the row list */ npp_remove_row(npp, row); npp_insert_row(npp, row, 0); } return; } void npp_deactivate_row(NPP *npp, NPPROW *row) { /* make row inactive */ if (row->temp) { row->temp = 0; /* move the row to the end of the row list */ npp_remove_row(npp, row); npp_insert_row(npp, row, 1); } return; } void npp_insert_col(NPP *npp, NPPCOL *col, int where) { /* insert column to the column list */ if (where == 0) { /* insert column to the beginning of the column list */ col->prev = NULL; col->next = npp->c_head; if (col->next == NULL) npp->c_tail = col; else col->next->prev = col; npp->c_head = col; } else { /* insert column to the end of the column list */ col->prev = npp->c_tail; col->next = NULL; if (col->prev == NULL) npp->c_head = col; else col->prev->next = col; npp->c_tail = col; } return; } void npp_remove_col(NPP *npp, NPPCOL *col) { /* remove column from the column list */ if (col->prev == NULL) npp->c_head = col->next; else col->prev->next = col->next; if (col->next == NULL) npp->c_tail = col->prev; else col->next->prev = col->prev; return; } void npp_activate_col(NPP *npp, NPPCOL *col) { /* make column active */ if (!col->temp) { col->temp = 1; /* move the column to the beginning of the column list */ npp_remove_col(npp, col); npp_insert_col(npp, col, 0); } return; } void npp_deactivate_col(NPP *npp, NPPCOL *col) { /* make column inactive */ if (col->temp) { col->temp = 0; /* move the column to the end of the column list */ npp_remove_col(npp, col); npp_insert_col(npp, col, 1); } return; } NPPROW *npp_add_row(NPP *npp) { /* add new row to the current problem */ NPPROW *row; row = dmp_get_atom(npp->pool, sizeof(NPPROW)); row->i = ++(npp->nrows); row->name = NULL; row->lb = -DBL_MAX, row->ub = +DBL_MAX; row->ptr = NULL; row->temp = 0; npp_insert_row(npp, row, 1); return row; } NPPCOL *npp_add_col(NPP *npp) { /* add new column to the current problem */ NPPCOL *col; col = dmp_get_atom(npp->pool, sizeof(NPPCOL)); col->j = ++(npp->ncols); col->name = NULL; #if 0 col->kind = GLP_CV; #else col->is_int = 0; #endif col->lb = col->ub = col->coef = 0.0; col->ptr = NULL; col->temp = 0; npp_insert_col(npp, col, 1); return col; } NPPAIJ *npp_add_aij(NPP *npp, NPPROW *row, NPPCOL *col, double val) { /* add new element to the constraint matrix */ NPPAIJ *aij; aij = dmp_get_atom(npp->pool, sizeof(NPPAIJ)); aij->row = row; aij->col = col; aij->val = val; aij->r_prev = NULL; aij->r_next = row->ptr; aij->c_prev = NULL; aij->c_next = col->ptr; if (aij->r_next != NULL) aij->r_next->r_prev = aij; if (aij->c_next != NULL) aij->c_next->c_prev = aij; row->ptr = col->ptr = aij; return aij; } int npp_row_nnz(NPP *npp, NPPROW *row) { /* count number of non-zero coefficients in row */ NPPAIJ *aij; int nnz; xassert(npp == npp); nnz = 0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) nnz++; return nnz; } int npp_col_nnz(NPP *npp, NPPCOL *col) { /* count number of non-zero coefficients in column */ NPPAIJ *aij; int nnz; xassert(npp == npp); nnz = 0; for (aij = col->ptr; aij != NULL; aij = aij->c_next) nnz++; return nnz; } void *npp_push_tse(NPP *npp, int (*func)(NPP *npp, void *info), int size) { /* push new entry to the transformation stack */ NPPTSE *tse; tse = dmp_get_atom(npp->stack, sizeof(NPPTSE)); tse->func = func; tse->info = dmp_get_atom(npp->stack, size); tse->link = npp->top; npp->top = tse; return tse->info; } #if 1 /* 23/XII-2009 */ void npp_erase_row(NPP *npp, NPPROW *row) { /* erase row content to make it empty */ NPPAIJ *aij; while (row->ptr != NULL) { aij = row->ptr; row->ptr = aij->r_next; if (aij->c_prev == NULL) aij->col->ptr = aij->c_next; else aij->c_prev->c_next = aij->c_next; if (aij->c_next == NULL) ; else aij->c_next->c_prev = aij->c_prev; dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); } return; } #endif void npp_del_row(NPP *npp, NPPROW *row) { /* remove row from the current problem */ #if 0 /* 23/XII-2009 */ NPPAIJ *aij; #endif if (row->name != NULL) dmp_free_atom(npp->pool, row->name, strlen(row->name)+1); #if 0 /* 23/XII-2009 */ while (row->ptr != NULL) { aij = row->ptr; row->ptr = aij->r_next; if (aij->c_prev == NULL) aij->col->ptr = aij->c_next; else aij->c_prev->c_next = aij->c_next; if (aij->c_next == NULL) ; else aij->c_next->c_prev = aij->c_prev; dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); } #else npp_erase_row(npp, row); #endif npp_remove_row(npp, row); dmp_free_atom(npp->pool, row, sizeof(NPPROW)); return; } void npp_del_col(NPP *npp, NPPCOL *col) { /* remove column from the current problem */ NPPAIJ *aij; if (col->name != NULL) dmp_free_atom(npp->pool, col->name, strlen(col->name)+1); while (col->ptr != NULL) { aij = col->ptr; col->ptr = aij->c_next; if (aij->r_prev == NULL) aij->row->ptr = aij->r_next; else aij->r_prev->r_next = aij->r_next; if (aij->r_next == NULL) ; else aij->r_next->r_prev = aij->r_prev; dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); } npp_remove_col(npp, col); dmp_free_atom(npp->pool, col, sizeof(NPPCOL)); return; } void npp_del_aij(NPP *npp, NPPAIJ *aij) { /* remove element from the constraint matrix */ if (aij->r_prev == NULL) aij->row->ptr = aij->r_next; else aij->r_prev->r_next = aij->r_next; if (aij->r_next == NULL) ; else aij->r_next->r_prev = aij->r_prev; if (aij->c_prev == NULL) aij->col->ptr = aij->c_next; else aij->c_prev->c_next = aij->c_next; if (aij->c_next == NULL) ; else aij->c_next->c_prev = aij->c_prev; dmp_free_atom(npp->pool, aij, sizeof(NPPAIJ)); return; } void npp_load_prob(NPP *npp, glp_prob *orig, int names, int sol, int scaling) { /* load original problem into the preprocessor workspace */ int m = orig->m; int n = orig->n; NPPROW **link; int i, j; double dir; xassert(names == GLP_OFF || names == GLP_ON); xassert(sol == GLP_SOL || sol == GLP_IPT || sol == GLP_MIP); xassert(scaling == GLP_OFF || scaling == GLP_ON); if (sol == GLP_MIP) xassert(!scaling); npp->orig_dir = orig->dir; if (npp->orig_dir == GLP_MIN) dir = +1.0; else if (npp->orig_dir == GLP_MAX) dir = -1.0; else xassert(npp != npp); npp->orig_m = m; npp->orig_n = n; npp->orig_nnz = orig->nnz; if (names && orig->name != NULL) { npp->name = dmp_get_atom(npp->pool, strlen(orig->name)+1); strcpy(npp->name, orig->name); } if (names && orig->obj != NULL) { npp->obj = dmp_get_atom(npp->pool, strlen(orig->obj)+1); strcpy(npp->obj, orig->obj); } npp->c0 = dir * orig->c0; /* load rows */ link = xcalloc(1+m, sizeof(NPPROW *)); for (i = 1; i <= m; i++) { GLPROW *rrr = orig->row[i]; NPPROW *row; link[i] = row = npp_add_row(npp); xassert(row->i == i); if (names && rrr->name != NULL) { row->name = dmp_get_atom(npp->pool, strlen(rrr->name)+1); strcpy(row->name, rrr->name); } if (!scaling) { if (rrr->type == GLP_FR) row->lb = -DBL_MAX, row->ub = +DBL_MAX; else if (rrr->type == GLP_LO) row->lb = rrr->lb, row->ub = +DBL_MAX; else if (rrr->type == GLP_UP) row->lb = -DBL_MAX, row->ub = rrr->ub; else if (rrr->type == GLP_DB) row->lb = rrr->lb, row->ub = rrr->ub; else if (rrr->type == GLP_FX) row->lb = row->ub = rrr->lb; else xassert(rrr != rrr); } else { double rii = rrr->rii; if (rrr->type == GLP_FR) row->lb = -DBL_MAX, row->ub = +DBL_MAX; else if (rrr->type == GLP_LO) row->lb = rrr->lb * rii, row->ub = +DBL_MAX; else if (rrr->type == GLP_UP) row->lb = -DBL_MAX, row->ub = rrr->ub * rii; else if (rrr->type == GLP_DB) row->lb = rrr->lb * rii, row->ub = rrr->ub * rii; else if (rrr->type == GLP_FX) row->lb = row->ub = rrr->lb * rii; else xassert(rrr != rrr); } } /* load columns and constraint coefficients */ for (j = 1; j <= n; j++) { GLPCOL *ccc = orig->col[j]; GLPAIJ *aaa; NPPCOL *col; col = npp_add_col(npp); xassert(col->j == j); if (names && ccc->name != NULL) { col->name = dmp_get_atom(npp->pool, strlen(ccc->name)+1); strcpy(col->name, ccc->name); } if (sol == GLP_MIP) #if 0 col->kind = ccc->kind; #else col->is_int = (char)(ccc->kind == GLP_IV); #endif if (!scaling) { if (ccc->type == GLP_FR) col->lb = -DBL_MAX, col->ub = +DBL_MAX; else if (ccc->type == GLP_LO) col->lb = ccc->lb, col->ub = +DBL_MAX; else if (ccc->type == GLP_UP) col->lb = -DBL_MAX, col->ub = ccc->ub; else if (ccc->type == GLP_DB) col->lb = ccc->lb, col->ub = ccc->ub; else if (ccc->type == GLP_FX) col->lb = col->ub = ccc->lb; else xassert(ccc != ccc); col->coef = dir * ccc->coef; for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) npp_add_aij(npp, link[aaa->row->i], col, aaa->val); } else { double sjj = ccc->sjj; if (ccc->type == GLP_FR) col->lb = -DBL_MAX, col->ub = +DBL_MAX; else if (ccc->type == GLP_LO) col->lb = ccc->lb / sjj, col->ub = +DBL_MAX; else if (ccc->type == GLP_UP) col->lb = -DBL_MAX, col->ub = ccc->ub / sjj; else if (ccc->type == GLP_DB) col->lb = ccc->lb / sjj, col->ub = ccc->ub / sjj; else if (ccc->type == GLP_FX) col->lb = col->ub = ccc->lb / sjj; else xassert(ccc != ccc); col->coef = dir * ccc->coef * sjj; for (aaa = ccc->ptr; aaa != NULL; aaa = aaa->c_next) npp_add_aij(npp, link[aaa->row->i], col, aaa->row->rii * aaa->val * sjj); } } xfree(link); /* keep solution indicator and scaling option */ npp->sol = sol; npp->scaling = scaling; return; } void npp_build_prob(NPP *npp, glp_prob *prob) { /* build resultant (preprocessed) problem */ NPPROW *row; NPPCOL *col; NPPAIJ *aij; int i, j, type, len, *ind; double dir, *val; glp_erase_prob(prob); glp_set_prob_name(prob, npp->name); glp_set_obj_name(prob, npp->obj); glp_set_obj_dir(prob, npp->orig_dir); if (npp->orig_dir == GLP_MIN) dir = +1.0; else if (npp->orig_dir == GLP_MAX) dir = -1.0; else xassert(npp != npp); glp_set_obj_coef(prob, 0, dir * npp->c0); /* build rows */ for (row = npp->r_head; row != NULL; row = row->next) { row->temp = i = glp_add_rows(prob, 1); glp_set_row_name(prob, i, row->name); if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) type = GLP_FR; else if (row->ub == +DBL_MAX) type = GLP_LO; else if (row->lb == -DBL_MAX) type = GLP_UP; else if (row->lb != row->ub) type = GLP_DB; else type = GLP_FX; glp_set_row_bnds(prob, i, type, row->lb, row->ub); } /* build columns and the constraint matrix */ ind = xcalloc(1+prob->m, sizeof(int)); val = xcalloc(1+prob->m, sizeof(double)); for (col = npp->c_head; col != NULL; col = col->next) { j = glp_add_cols(prob, 1); glp_set_col_name(prob, j, col->name); #if 0 glp_set_col_kind(prob, j, col->kind); #else glp_set_col_kind(prob, j, col->is_int ? GLP_IV : GLP_CV); #endif if (col->lb == -DBL_MAX && col->ub == +DBL_MAX) type = GLP_FR; else if (col->ub == +DBL_MAX) type = GLP_LO; else if (col->lb == -DBL_MAX) type = GLP_UP; else if (col->lb != col->ub) type = GLP_DB; else type = GLP_FX; glp_set_col_bnds(prob, j, type, col->lb, col->ub); glp_set_obj_coef(prob, j, dir * col->coef); len = 0; for (aij = col->ptr; aij != NULL; aij = aij->c_next) { len++; ind[len] = aij->row->temp; val[len] = aij->val; } glp_set_mat_col(prob, j, len, ind, val); } xfree(ind); xfree(val); /* resultant problem has been built */ npp->m = prob->m; npp->n = prob->n; npp->nnz = prob->nnz; npp->row_ref = xcalloc(1+npp->m, sizeof(int)); npp->col_ref = xcalloc(1+npp->n, sizeof(int)); for (row = npp->r_head, i = 0; row != NULL; row = row->next) npp->row_ref[++i] = row->i; for (col = npp->c_head, j = 0; col != NULL; col = col->next) npp->col_ref[++j] = col->j; /* transformed problem segment is no longer needed */ dmp_delete_pool(npp->pool), npp->pool = NULL; npp->name = npp->obj = NULL; npp->c0 = 0.0; npp->r_head = npp->r_tail = NULL; npp->c_head = npp->c_tail = NULL; return; } void npp_postprocess(NPP *npp, glp_prob *prob) { /* postprocess solution from the resultant problem */ GLPROW *row; GLPCOL *col; NPPTSE *tse; int i, j, k; double dir; xassert(npp->orig_dir == prob->dir); if (npp->orig_dir == GLP_MIN) dir = +1.0; else if (npp->orig_dir == GLP_MAX) dir = -1.0; else xassert(npp != npp); #if 0 /* 11/VII-2013; due to call from ios_main */ xassert(npp->m == prob->m); #else if (npp->sol != GLP_MIP) xassert(npp->m == prob->m); #endif xassert(npp->n == prob->n); #if 0 /* 11/VII-2013; due to call from ios_main */ xassert(npp->nnz == prob->nnz); #else if (npp->sol != GLP_MIP) xassert(npp->nnz == prob->nnz); #endif /* copy solution status */ if (npp->sol == GLP_SOL) { npp->p_stat = prob->pbs_stat; npp->d_stat = prob->dbs_stat; } else if (npp->sol == GLP_IPT) npp->t_stat = prob->ipt_stat; else if (npp->sol == GLP_MIP) npp->i_stat = prob->mip_stat; else xassert(npp != npp); /* allocate solution arrays */ if (npp->sol == GLP_SOL) { if (npp->r_stat == NULL) npp->r_stat = xcalloc(1+npp->nrows, sizeof(char)); for (i = 1; i <= npp->nrows; i++) npp->r_stat[i] = 0; if (npp->c_stat == NULL) npp->c_stat = xcalloc(1+npp->ncols, sizeof(char)); for (j = 1; j <= npp->ncols; j++) npp->c_stat[j] = 0; } #if 0 if (npp->r_prim == NULL) npp->r_prim = xcalloc(1+npp->nrows, sizeof(double)); for (i = 1; i <= npp->nrows; i++) npp->r_prim[i] = DBL_MAX; #endif if (npp->c_value == NULL) npp->c_value = xcalloc(1+npp->ncols, sizeof(double)); for (j = 1; j <= npp->ncols; j++) npp->c_value[j] = DBL_MAX; if (npp->sol != GLP_MIP) { if (npp->r_pi == NULL) npp->r_pi = xcalloc(1+npp->nrows, sizeof(double)); for (i = 1; i <= npp->nrows; i++) npp->r_pi[i] = DBL_MAX; #if 0 if (npp->c_dual == NULL) npp->c_dual = xcalloc(1+npp->ncols, sizeof(double)); for (j = 1; j <= npp->ncols; j++) npp->c_dual[j] = DBL_MAX; #endif } /* copy solution components from the resultant problem */ if (npp->sol == GLP_SOL) { for (i = 1; i <= npp->m; i++) { row = prob->row[i]; k = npp->row_ref[i]; npp->r_stat[k] = (char)row->stat; /*npp->r_prim[k] = row->prim;*/ npp->r_pi[k] = dir * row->dual; } for (j = 1; j <= npp->n; j++) { col = prob->col[j]; k = npp->col_ref[j]; npp->c_stat[k] = (char)col->stat; npp->c_value[k] = col->prim; /*npp->c_dual[k] = dir * col->dual;*/ } } else if (npp->sol == GLP_IPT) { for (i = 1; i <= npp->m; i++) { row = prob->row[i]; k = npp->row_ref[i]; /*npp->r_prim[k] = row->pval;*/ npp->r_pi[k] = dir * row->dval; } for (j = 1; j <= npp->n; j++) { col = prob->col[j]; k = npp->col_ref[j]; npp->c_value[k] = col->pval; /*npp->c_dual[k] = dir * col->dval;*/ } } else if (npp->sol == GLP_MIP) { #if 0 for (i = 1; i <= npp->m; i++) { row = prob->row[i]; k = npp->row_ref[i]; /*npp->r_prim[k] = row->mipx;*/ } #endif for (j = 1; j <= npp->n; j++) { col = prob->col[j]; k = npp->col_ref[j]; npp->c_value[k] = col->mipx; } } else xassert(npp != npp); /* perform postprocessing to construct solution to the original problem */ for (tse = npp->top; tse != NULL; tse = tse->link) { xassert(tse->func != NULL); xassert(tse->func(npp, tse->info) == 0); } return; } void npp_unload_sol(NPP *npp, glp_prob *orig) { /* store solution to the original problem */ GLPROW *row; GLPCOL *col; int i, j; double dir; xassert(npp->orig_dir == orig->dir); if (npp->orig_dir == GLP_MIN) dir = +1.0; else if (npp->orig_dir == GLP_MAX) dir = -1.0; else xassert(npp != npp); xassert(npp->orig_m == orig->m); xassert(npp->orig_n == orig->n); xassert(npp->orig_nnz == orig->nnz); if (npp->sol == GLP_SOL) { /* store basic solution */ orig->valid = 0; orig->pbs_stat = npp->p_stat; orig->dbs_stat = npp->d_stat; orig->obj_val = orig->c0; orig->some = 0; for (i = 1; i <= orig->m; i++) { row = orig->row[i]; row->stat = npp->r_stat[i]; if (!npp->scaling) { /*row->prim = npp->r_prim[i];*/ row->dual = dir * npp->r_pi[i]; } else { /*row->prim = npp->r_prim[i] / row->rii;*/ row->dual = dir * npp->r_pi[i] * row->rii; } if (row->stat == GLP_BS) row->dual = 0.0; else if (row->stat == GLP_NL) { xassert(row->type == GLP_LO || row->type == GLP_DB); row->prim = row->lb; } else if (row->stat == GLP_NU) { xassert(row->type == GLP_UP || row->type == GLP_DB); row->prim = row->ub; } else if (row->stat == GLP_NF) { xassert(row->type == GLP_FR); row->prim = 0.0; } else if (row->stat == GLP_NS) { xassert(row->type == GLP_FX); row->prim = row->lb; } else xassert(row != row); } for (j = 1; j <= orig->n; j++) { col = orig->col[j]; col->stat = npp->c_stat[j]; if (!npp->scaling) { col->prim = npp->c_value[j]; /*col->dual = dir * npp->c_dual[j];*/ } else { col->prim = npp->c_value[j] * col->sjj; /*col->dual = dir * npp->c_dual[j] / col->sjj;*/ } if (col->stat == GLP_BS) col->dual = 0.0; #if 1 else if (col->stat == GLP_NL) { xassert(col->type == GLP_LO || col->type == GLP_DB); col->prim = col->lb; } else if (col->stat == GLP_NU) { xassert(col->type == GLP_UP || col->type == GLP_DB); col->prim = col->ub; } else if (col->stat == GLP_NF) { xassert(col->type == GLP_FR); col->prim = 0.0; } else if (col->stat == GLP_NS) { xassert(col->type == GLP_FX); col->prim = col->lb; } else xassert(col != col); #endif orig->obj_val += col->coef * col->prim; } #if 1 /* compute primal values of inactive rows */ for (i = 1; i <= orig->m; i++) { row = orig->row[i]; if (row->stat == GLP_BS) { GLPAIJ *aij; double temp; temp = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) temp += aij->val * aij->col->prim; row->prim = temp; } } /* compute reduced costs of active columns */ for (j = 1; j <= orig->n; j++) { col = orig->col[j]; if (col->stat != GLP_BS) { GLPAIJ *aij; double temp; temp = col->coef; for (aij = col->ptr; aij != NULL; aij = aij->c_next) temp -= aij->val * aij->row->dual; col->dual = temp; } } #endif } else if (npp->sol == GLP_IPT) { /* store interior-point solution */ orig->ipt_stat = npp->t_stat; orig->ipt_obj = orig->c0; for (i = 1; i <= orig->m; i++) { row = orig->row[i]; if (!npp->scaling) { /*row->pval = npp->r_prim[i];*/ row->dval = dir * npp->r_pi[i]; } else { /*row->pval = npp->r_prim[i] / row->rii;*/ row->dval = dir * npp->r_pi[i] * row->rii; } } for (j = 1; j <= orig->n; j++) { col = orig->col[j]; if (!npp->scaling) { col->pval = npp->c_value[j]; /*col->dval = dir * npp->c_dual[j];*/ } else { col->pval = npp->c_value[j] * col->sjj; /*col->dval = dir * npp->c_dual[j] / col->sjj;*/ } orig->ipt_obj += col->coef * col->pval; } #if 1 /* compute row primal values */ for (i = 1; i <= orig->m; i++) { row = orig->row[i]; { GLPAIJ *aij; double temp; temp = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) temp += aij->val * aij->col->pval; row->pval = temp; } } /* compute column dual values */ for (j = 1; j <= orig->n; j++) { col = orig->col[j]; { GLPAIJ *aij; double temp; temp = col->coef; for (aij = col->ptr; aij != NULL; aij = aij->c_next) temp -= aij->val * aij->row->dval; col->dval = temp; } } #endif } else if (npp->sol == GLP_MIP) { /* store MIP solution */ xassert(!npp->scaling); orig->mip_stat = npp->i_stat; orig->mip_obj = orig->c0; #if 0 for (i = 1; i <= orig->m; i++) { row = orig->row[i]; /*row->mipx = npp->r_prim[i];*/ } #endif for (j = 1; j <= orig->n; j++) { col = orig->col[j]; col->mipx = npp->c_value[j]; if (col->kind == GLP_IV) xassert(col->mipx == floor(col->mipx)); orig->mip_obj += col->coef * col->mipx; } #if 1 /* compute row primal values */ for (i = 1; i <= orig->m; i++) { row = orig->row[i]; { GLPAIJ *aij; double temp; temp = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) temp += aij->val * aij->col->mipx; row->mipx = temp; } } #endif } else xassert(npp != npp); return; } void npp_delete_wksp(NPP *npp) { /* delete LP/MIP preprocessor workspace */ if (npp->pool != NULL) dmp_delete_pool(npp->pool); if (npp->stack != NULL) dmp_delete_pool(npp->stack); if (npp->row_ref != NULL) xfree(npp->row_ref); if (npp->col_ref != NULL) xfree(npp->col_ref); if (npp->r_stat != NULL) xfree(npp->r_stat); #if 0 if (npp->r_prim != NULL) xfree(npp->r_prim); #endif if (npp->r_pi != NULL) xfree(npp->r_pi); if (npp->c_stat != NULL) xfree(npp->c_stat); if (npp->c_value != NULL) xfree(npp->c_value); #if 0 if (npp->c_dual != NULL) xfree(npp->c_dual); #endif xfree(npp); return; } /* eof */ glpk-4.52.1/src/glpnpp02.c0000644000062000006210000012625012175147600014324 0ustar maomkpasswd/* glpnpp02.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpnpp.h" /*********************************************************************** * NAME * * npp_free_row - process free (unbounded) row * * SYNOPSIS * * #include "glpnpp.h" * void npp_free_row(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_free_row processes row p, which is free (i.e. has * no finite bounds): * * -inf < sum a[p,j] x[j] < +inf. (1) * j * * PROBLEM TRANSFORMATION * * Constraint (1) cannot be active, so it is redundant and can be * removed from the original problem. * * Removing row p leads to removing a column of multiplier pi[p] for * this row in the dual system. Since row p has no bounds, pi[p] = 0, * so removing the column does not affect the dual solution. * * RECOVERING BASIC SOLUTION * * In solution to the original problem row p is inactive constraint, * so it is assigned status GLP_BS, and multiplier pi[p] is assigned * zero value. * * RECOVERING INTERIOR-POINT SOLUTION * * In solution to the original problem row p is inactive constraint, * so its multiplier pi[p] is assigned zero value. * * RECOVERING MIP SOLUTION * * None needed. */ struct free_row { /* free (unbounded) row */ int p; /* row reference number */ }; static int rcv_free_row(NPP *npp, void *info); void npp_free_row(NPP *npp, NPPROW *p) { /* process free (unbounded) row */ struct free_row *info; /* the row must be free */ xassert(p->lb == -DBL_MAX && p->ub == +DBL_MAX); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_free_row, sizeof(struct free_row)); info->p = p->i; /* remove the row from the problem */ npp_del_row(npp, p); return; } static int rcv_free_row(NPP *npp, void *_info) { /* recover free (unbounded) row */ struct free_row *info = _info; if (npp->sol == GLP_SOL) npp->r_stat[info->p] = GLP_BS; if (npp->sol != GLP_MIP) npp->r_pi[info->p] = 0.0; return 0; } /*********************************************************************** * NAME * * npp_geq_row - process row of 'not less than' type * * SYNOPSIS * * #include "glpnpp.h" * void npp_geq_row(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_geq_row processes row p, which is 'not less than' * inequality constraint: * * L[p] <= sum a[p,j] x[j] (<= U[p]), (1) * j * * where L[p] < U[p], and upper bound may not exist (U[p] = +oo). * * PROBLEM TRANSFORMATION * * Constraint (1) can be replaced by equality constraint: * * sum a[p,j] x[j] - s = L[p], (2) * j * * where * * 0 <= s (<= U[p] - L[p]) (3) * * is a non-negative surplus variable. * * Since in the primal system there appears column s having the only * non-zero coefficient in row p, in the dual system there appears a * new row: * * (-1) pi[p] + lambda = 0, (4) * * where (-1) is coefficient of column s in row p, pi[p] is multiplier * of row p, lambda is multiplier of column q, 0 is coefficient of * column s in the objective row. * * RECOVERING BASIC SOLUTION * * Status of row p in solution to the original problem is determined * by its status and status of column q in solution to the transformed * problem as follows: * * +--------------------------------------+------------------+ * | Transformed problem | Original problem | * +-----------------+--------------------+------------------+ * | Status of row p | Status of column s | Status of row p | * +-----------------+--------------------+------------------+ * | GLP_BS | GLP_BS | N/A | * | GLP_BS | GLP_NL | GLP_BS | * | GLP_BS | GLP_NU | GLP_BS | * | GLP_NS | GLP_BS | GLP_BS | * | GLP_NS | GLP_NL | GLP_NL | * | GLP_NS | GLP_NU | GLP_NU | * +-----------------+--------------------+------------------+ * * Value of row multiplier pi[p] in solution to the original problem * is the same as in solution to the transformed problem. * * 1. In solution to the transformed problem row p and column q cannot * be basic at the same time; otherwise the basis matrix would have * two linear dependent columns: unity column of auxiliary variable * of row p and unity column of variable s. * * 2. Though in the transformed problem row p is equality constraint, * it may be basic due to primal degenerate solution. * * RECOVERING INTERIOR-POINT SOLUTION * * Value of row multiplier pi[p] in solution to the original problem * is the same as in solution to the transformed problem. * * RECOVERING MIP SOLUTION * * None needed. */ struct ineq_row { /* inequality constraint row */ int p; /* row reference number */ int s; /* column reference number for slack/surplus variable */ }; static int rcv_geq_row(NPP *npp, void *info); void npp_geq_row(NPP *npp, NPPROW *p) { /* process row of 'not less than' type */ struct ineq_row *info; NPPCOL *s; /* the row must have lower bound */ xassert(p->lb != -DBL_MAX); xassert(p->lb < p->ub); /* create column for surplus variable */ s = npp_add_col(npp); s->lb = 0.0; s->ub = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub - p->lb); /* and add it to the transformed problem */ npp_add_aij(npp, p, s, -1.0); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_geq_row, sizeof(struct ineq_row)); info->p = p->i; info->s = s->j; /* replace the row by equality constraint */ p->ub = p->lb; return; } static int rcv_geq_row(NPP *npp, void *_info) { /* recover row of 'not less than' type */ struct ineq_row *info = _info; if (npp->sol == GLP_SOL) { if (npp->r_stat[info->p] == GLP_BS) { if (npp->c_stat[info->s] == GLP_BS) { npp_error(); return 1; } else if (npp->c_stat[info->s] == GLP_NL || npp->c_stat[info->s] == GLP_NU) npp->r_stat[info->p] = GLP_BS; else { npp_error(); return 1; } } else if (npp->r_stat[info->p] == GLP_NS) { if (npp->c_stat[info->s] == GLP_BS) npp->r_stat[info->p] = GLP_BS; else if (npp->c_stat[info->s] == GLP_NL) npp->r_stat[info->p] = GLP_NL; else if (npp->c_stat[info->s] == GLP_NU) npp->r_stat[info->p] = GLP_NU; else { npp_error(); return 1; } } else { npp_error(); return 1; } } return 0; } /*********************************************************************** * NAME * * npp_leq_row - process row of 'not greater than' type * * SYNOPSIS * * #include "glpnpp.h" * void npp_leq_row(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_leq_row processes row p, which is 'not greater than' * inequality constraint: * * (L[p] <=) sum a[p,j] x[j] <= U[p], (1) * j * * where L[p] < U[p], and lower bound may not exist (L[p] = +oo). * * PROBLEM TRANSFORMATION * * Constraint (1) can be replaced by equality constraint: * * sum a[p,j] x[j] + s = L[p], (2) * j * * where * * 0 <= s (<= U[p] - L[p]) (3) * * is a non-negative slack variable. * * Since in the primal system there appears column s having the only * non-zero coefficient in row p, in the dual system there appears a * new row: * * (+1) pi[p] + lambda = 0, (4) * * where (+1) is coefficient of column s in row p, pi[p] is multiplier * of row p, lambda is multiplier of column q, 0 is coefficient of * column s in the objective row. * * RECOVERING BASIC SOLUTION * * Status of row p in solution to the original problem is determined * by its status and status of column q in solution to the transformed * problem as follows: * * +--------------------------------------+------------------+ * | Transformed problem | Original problem | * +-----------------+--------------------+------------------+ * | Status of row p | Status of column s | Status of row p | * +-----------------+--------------------+------------------+ * | GLP_BS | GLP_BS | N/A | * | GLP_BS | GLP_NL | GLP_BS | * | GLP_BS | GLP_NU | GLP_BS | * | GLP_NS | GLP_BS | GLP_BS | * | GLP_NS | GLP_NL | GLP_NU | * | GLP_NS | GLP_NU | GLP_NL | * +-----------------+--------------------+------------------+ * * Value of row multiplier pi[p] in solution to the original problem * is the same as in solution to the transformed problem. * * 1. In solution to the transformed problem row p and column q cannot * be basic at the same time; otherwise the basis matrix would have * two linear dependent columns: unity column of auxiliary variable * of row p and unity column of variable s. * * 2. Though in the transformed problem row p is equality constraint, * it may be basic due to primal degeneracy. * * RECOVERING INTERIOR-POINT SOLUTION * * Value of row multiplier pi[p] in solution to the original problem * is the same as in solution to the transformed problem. * * RECOVERING MIP SOLUTION * * None needed. */ static int rcv_leq_row(NPP *npp, void *info); void npp_leq_row(NPP *npp, NPPROW *p) { /* process row of 'not greater than' type */ struct ineq_row *info; NPPCOL *s; /* the row must have upper bound */ xassert(p->ub != +DBL_MAX); xassert(p->lb < p->ub); /* create column for slack variable */ s = npp_add_col(npp); s->lb = 0.0; s->ub = (p->lb == -DBL_MAX ? +DBL_MAX : p->ub - p->lb); /* and add it to the transformed problem */ npp_add_aij(npp, p, s, +1.0); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_leq_row, sizeof(struct ineq_row)); info->p = p->i; info->s = s->j; /* replace the row by equality constraint */ p->lb = p->ub; return; } static int rcv_leq_row(NPP *npp, void *_info) { /* recover row of 'not greater than' type */ struct ineq_row *info = _info; if (npp->sol == GLP_SOL) { if (npp->r_stat[info->p] == GLP_BS) { if (npp->c_stat[info->s] == GLP_BS) { npp_error(); return 1; } else if (npp->c_stat[info->s] == GLP_NL || npp->c_stat[info->s] == GLP_NU) npp->r_stat[info->p] = GLP_BS; else { npp_error(); return 1; } } else if (npp->r_stat[info->p] == GLP_NS) { if (npp->c_stat[info->s] == GLP_BS) npp->r_stat[info->p] = GLP_BS; else if (npp->c_stat[info->s] == GLP_NL) npp->r_stat[info->p] = GLP_NU; else if (npp->c_stat[info->s] == GLP_NU) npp->r_stat[info->p] = GLP_NL; else { npp_error(); return 1; } } else { npp_error(); return 1; } } return 0; } /*********************************************************************** * NAME * * npp_free_col - process free (unbounded) column * * SYNOPSIS * * #include "glpnpp.h" * void npp_free_col(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_free_col processes column q, which is free (i.e. has * no finite bounds): * * -oo < x[q] < +oo. (1) * * PROBLEM TRANSFORMATION * * Free (unbounded) variable can be replaced by the difference of two * non-negative variables: * * x[q] = s' - s'', s', s'' >= 0. (2) * * Assuming that in the transformed problem x[q] becomes s', * transformation (2) causes new column s'' to appear, which differs * from column s' only in the sign of coefficients in constraint and * objective rows. Thus, if in the dual system the following row * corresponds to column s': * * sum a[i,q] pi[i] + lambda' = c[q], (3) * i * * the row which corresponds to column s'' is the following: * * sum (-a[i,q]) pi[i] + lambda'' = -c[q]. (4) * i * * Then from (3) and (4) it follows that: * * lambda' + lambda'' = 0 => lambda' = lmabda'' = 0, (5) * * where lambda' and lambda'' are multipliers for columns s' and s'', * resp. * * RECOVERING BASIC SOLUTION * * With respect to (5) status of column q in solution to the original * problem is determined by statuses of columns s' and s'' in solution * to the transformed problem as follows: * * +--------------------------------------+------------------+ * | Transformed problem | Original problem | * +------------------+-------------------+------------------+ * | Status of col s' | Status of col s'' | Status of col q | * +------------------+-------------------+------------------+ * | GLP_BS | GLP_BS | N/A | * | GLP_BS | GLP_NL | GLP_BS | * | GLP_NL | GLP_BS | GLP_BS | * | GLP_NL | GLP_NL | GLP_NF | * +------------------+-------------------+------------------+ * * Value of column q is computed with formula (2). * * 1. In solution to the transformed problem columns s' and s'' cannot * be basic at the same time, because they differ only in the sign, * hence, are linear dependent. * * 2. Though column q is free, it can be non-basic due to dual * degeneracy. * * 3. If column q is integral, columns s' and s'' are also integral. * * RECOVERING INTERIOR-POINT SOLUTION * * Value of column q is computed with formula (2). * * RECOVERING MIP SOLUTION * * Value of column q is computed with formula (2). */ struct free_col { /* free (unbounded) column */ int q; /* column reference number for variables x[q] and s' */ int s; /* column reference number for variable s'' */ }; static int rcv_free_col(NPP *npp, void *info); void npp_free_col(NPP *npp, NPPCOL *q) { /* process free (unbounded) column */ struct free_col *info; NPPCOL *s; NPPAIJ *aij; /* the column must be free */ xassert(q->lb == -DBL_MAX && q->ub == +DBL_MAX); /* variable x[q] becomes s' */ q->lb = 0.0, q->ub = +DBL_MAX; /* create variable s'' */ s = npp_add_col(npp); s->is_int = q->is_int; s->lb = 0.0, s->ub = +DBL_MAX; /* duplicate objective coefficient */ s->coef = -q->coef; /* duplicate column of the constraint matrix */ for (aij = q->ptr; aij != NULL; aij = aij->c_next) npp_add_aij(npp, aij->row, s, -aij->val); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_free_col, sizeof(struct free_col)); info->q = q->j; info->s = s->j; return; } static int rcv_free_col(NPP *npp, void *_info) { /* recover free (unbounded) column */ struct free_col *info = _info; if (npp->sol == GLP_SOL) { if (npp->c_stat[info->q] == GLP_BS) { if (npp->c_stat[info->s] == GLP_BS) { npp_error(); return 1; } else if (npp->c_stat[info->s] == GLP_NL) npp->c_stat[info->q] = GLP_BS; else { npp_error(); return -1; } } else if (npp->c_stat[info->q] == GLP_NL) { if (npp->c_stat[info->s] == GLP_BS) npp->c_stat[info->q] = GLP_BS; else if (npp->c_stat[info->s] == GLP_NL) npp->c_stat[info->q] = GLP_NF; else { npp_error(); return -1; } } else { npp_error(); return -1; } } /* compute value of x[q] with formula (2) */ npp->c_value[info->q] -= npp->c_value[info->s]; return 0; } /*********************************************************************** * NAME * * npp_lbnd_col - process column with (non-zero) lower bound * * SYNOPSIS * * #include "glpnpp.h" * void npp_lbnd_col(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_lbnd_col processes column q, which has (non-zero) * lower bound: * * l[q] <= x[q] (<= u[q]), (1) * * where l[q] < u[q], and upper bound may not exist (u[q] = +oo). * * PROBLEM TRANSFORMATION * * Column q can be replaced as follows: * * x[q] = l[q] + s, (2) * * where * * 0 <= s (<= u[q] - l[q]) (3) * * is a non-negative variable. * * Substituting x[q] from (2) into the objective row, we have: * * z = sum c[j] x[j] + c0 = * j * * = sum c[j] x[j] + c[q] x[q] + c0 = * j!=q * * = sum c[j] x[j] + c[q] (l[q] + s) + c0 = * j!=q * * = sum c[j] x[j] + c[q] s + c~0, * * where * * c~0 = c0 + c[q] l[q] (4) * * is the constant term of the objective in the transformed problem. * Similarly, substituting x[q] into constraint row i, we have: * * L[i] <= sum a[i,j] x[j] <= U[i] ==> * j * * L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> * j!=q * * L[i] <= sum a[i,j] x[j] + a[i,q] (l[q] + s) <= U[i] ==> * j!=q * * L~[i] <= sum a[i,j] x[j] + a[i,q] s <= U~[i], * j!=q * * where * * L~[i] = L[i] - a[i,q] l[q], U~[i] = U[i] - a[i,q] l[q] (5) * * are lower and upper bounds of row i in the transformed problem, * resp. * * Transformation (2) does not affect the dual system. * * RECOVERING BASIC SOLUTION * * Status of column q in solution to the original problem is the same * as in solution to the transformed problem (GLP_BS, GLP_NL or GLP_NU). * Value of column q is computed with formula (2). * * RECOVERING INTERIOR-POINT SOLUTION * * Value of column q is computed with formula (2). * * RECOVERING MIP SOLUTION * * Value of column q is computed with formula (2). */ struct bnd_col { /* bounded column */ int q; /* column reference number for variables x[q] and s */ double bnd; /* lower/upper bound l[q] or u[q] */ }; static int rcv_lbnd_col(NPP *npp, void *info); void npp_lbnd_col(NPP *npp, NPPCOL *q) { /* process column with (non-zero) lower bound */ struct bnd_col *info; NPPROW *i; NPPAIJ *aij; /* the column must have non-zero lower bound */ xassert(q->lb != 0.0); xassert(q->lb != -DBL_MAX); xassert(q->lb < q->ub); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_lbnd_col, sizeof(struct bnd_col)); info->q = q->j; info->bnd = q->lb; /* substitute x[q] into objective row */ npp->c0 += q->coef * q->lb; /* substitute x[q] into constraint rows */ for (aij = q->ptr; aij != NULL; aij = aij->c_next) { i = aij->row; if (i->lb == i->ub) i->ub = (i->lb -= aij->val * q->lb); else { if (i->lb != -DBL_MAX) i->lb -= aij->val * q->lb; if (i->ub != +DBL_MAX) i->ub -= aij->val * q->lb; } } /* column x[q] becomes column s */ if (q->ub != +DBL_MAX) q->ub -= q->lb; q->lb = 0.0; return; } static int rcv_lbnd_col(NPP *npp, void *_info) { /* recover column with (non-zero) lower bound */ struct bnd_col *info = _info; if (npp->sol == GLP_SOL) { if (npp->c_stat[info->q] == GLP_BS || npp->c_stat[info->q] == GLP_NL || npp->c_stat[info->q] == GLP_NU) npp->c_stat[info->q] = npp->c_stat[info->q]; else { npp_error(); return 1; } } /* compute value of x[q] with formula (2) */ npp->c_value[info->q] = info->bnd + npp->c_value[info->q]; return 0; } /*********************************************************************** * NAME * * npp_ubnd_col - process column with upper bound * * SYNOPSIS * * #include "glpnpp.h" * void npp_ubnd_col(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_ubnd_col processes column q, which has upper bound: * * (l[q] <=) x[q] <= u[q], (1) * * where l[q] < u[q], and lower bound may not exist (l[q] = -oo). * * PROBLEM TRANSFORMATION * * Column q can be replaced as follows: * * x[q] = u[q] - s, (2) * * where * * 0 <= s (<= u[q] - l[q]) (3) * * is a non-negative variable. * * Substituting x[q] from (2) into the objective row, we have: * * z = sum c[j] x[j] + c0 = * j * * = sum c[j] x[j] + c[q] x[q] + c0 = * j!=q * * = sum c[j] x[j] + c[q] (u[q] - s) + c0 = * j!=q * * = sum c[j] x[j] - c[q] s + c~0, * * where * * c~0 = c0 + c[q] u[q] (4) * * is the constant term of the objective in the transformed problem. * Similarly, substituting x[q] into constraint row i, we have: * * L[i] <= sum a[i,j] x[j] <= U[i] ==> * j * * L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> * j!=q * * L[i] <= sum a[i,j] x[j] + a[i,q] (u[q] - s) <= U[i] ==> * j!=q * * L~[i] <= sum a[i,j] x[j] - a[i,q] s <= U~[i], * j!=q * * where * * L~[i] = L[i] - a[i,q] u[q], U~[i] = U[i] - a[i,q] u[q] (5) * * are lower and upper bounds of row i in the transformed problem, * resp. * * Note that in the transformed problem coefficients c[q] and a[i,q] * change their sign. Thus, the row of the dual system corresponding to * column q: * * sum a[i,q] pi[i] + lambda[q] = c[q] (6) * i * * in the transformed problem becomes the following: * * sum (-a[i,q]) pi[i] + lambda[s] = -c[q]. (7) * i * * Therefore: * * lambda[q] = - lambda[s], (8) * * where lambda[q] is multiplier for column q, lambda[s] is multiplier * for column s. * * RECOVERING BASIC SOLUTION * * With respect to (8) status of column q in solution to the original * problem is determined by status of column s in solution to the * transformed problem as follows: * * +-----------------------+--------------------+ * | Status of column s | Status of column q | * | (transformed problem) | (original problem) | * +-----------------------+--------------------+ * | GLP_BS | GLP_BS | * | GLP_NL | GLP_NU | * | GLP_NU | GLP_NL | * +-----------------------+--------------------+ * * Value of column q is computed with formula (2). * * RECOVERING INTERIOR-POINT SOLUTION * * Value of column q is computed with formula (2). * * RECOVERING MIP SOLUTION * * Value of column q is computed with formula (2). */ static int rcv_ubnd_col(NPP *npp, void *info); void npp_ubnd_col(NPP *npp, NPPCOL *q) { /* process column with upper bound */ struct bnd_col *info; NPPROW *i; NPPAIJ *aij; /* the column must have upper bound */ xassert(q->ub != +DBL_MAX); xassert(q->lb < q->ub); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_ubnd_col, sizeof(struct bnd_col)); info->q = q->j; info->bnd = q->ub; /* substitute x[q] into objective row */ npp->c0 += q->coef * q->ub; q->coef = -q->coef; /* substitute x[q] into constraint rows */ for (aij = q->ptr; aij != NULL; aij = aij->c_next) { i = aij->row; if (i->lb == i->ub) i->ub = (i->lb -= aij->val * q->ub); else { if (i->lb != -DBL_MAX) i->lb -= aij->val * q->ub; if (i->ub != +DBL_MAX) i->ub -= aij->val * q->ub; } aij->val = -aij->val; } /* column x[q] becomes column s */ if (q->lb != -DBL_MAX) q->ub -= q->lb; else q->ub = +DBL_MAX; q->lb = 0.0; return; } static int rcv_ubnd_col(NPP *npp, void *_info) { /* recover column with upper bound */ struct bnd_col *info = _info; if (npp->sol == GLP_BS) { if (npp->c_stat[info->q] == GLP_BS) npp->c_stat[info->q] = GLP_BS; else if (npp->c_stat[info->q] == GLP_NL) npp->c_stat[info->q] = GLP_NU; else if (npp->c_stat[info->q] == GLP_NU) npp->c_stat[info->q] = GLP_NL; else { npp_error(); return 1; } } /* compute value of x[q] with formula (2) */ npp->c_value[info->q] = info->bnd - npp->c_value[info->q]; return 0; } /*********************************************************************** * NAME * * npp_dbnd_col - process non-negative column with upper bound * * SYNOPSIS * * #include "glpnpp.h" * void npp_dbnd_col(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_dbnd_col processes column q, which is non-negative * and has upper bound: * * 0 <= x[q] <= u[q], (1) * * where u[q] > 0. * * PROBLEM TRANSFORMATION * * Upper bound of column q can be replaced by the following equality * constraint: * * x[q] + s = u[q], (2) * * where s >= 0 is a non-negative complement variable. * * Since in the primal system along with new row (2) there appears a * new column s having the only non-zero coefficient in this row, in * the dual system there appears a new row: * * (+1)pi + lambda[s] = 0, (3) * * where (+1) is coefficient at column s in row (2), pi is multiplier * for row (2), lambda[s] is multiplier for column s, 0 is coefficient * at column s in the objective row. * * RECOVERING BASIC SOLUTION * * Status of column q in solution to the original problem is determined * by its status and status of column s in solution to the transformed * problem as follows: * * +-----------------------------------+------------------+ * | Transformed problem | Original problem | * +-----------------+-----------------+------------------+ * | Status of col q | Status of col s | Status of col q | * +-----------------+-----------------+------------------+ * | GLP_BS | GLP_BS | GLP_BS | * | GLP_BS | GLP_NL | GLP_NU | * | GLP_NL | GLP_BS | GLP_NL | * | GLP_NL | GLP_NL | GLP_NL (*) | * +-----------------+-----------------+------------------+ * * Value of column q in solution to the original problem is the same as * in solution to the transformed problem. * * 1. Formally, in solution to the transformed problem columns q and s * cannot be non-basic at the same time, since the constraint (2) * would be violated. However, if u[q] is close to zero, violation * may be less than a working precision even if both columns q and s * are non-basic. In this degenerate case row (2) can be only basic, * i.e. non-active constraint (otherwise corresponding row of the * basis matrix would be zero). This allows to pivot out auxiliary * variable and pivot in column s, in which case the row becomes * active while column s becomes basic. * * 2. If column q is integral, column s is also integral. * * RECOVERING INTERIOR-POINT SOLUTION * * Value of column q in solution to the original problem is the same as * in solution to the transformed problem. * * RECOVERING MIP SOLUTION * * Value of column q in solution to the original problem is the same as * in solution to the transformed problem. */ struct dbnd_col { /* double-bounded column */ int q; /* column reference number for variable x[q] */ int s; /* column reference number for complement variable s */ }; static int rcv_dbnd_col(NPP *npp, void *info); void npp_dbnd_col(NPP *npp, NPPCOL *q) { /* process non-negative column with upper bound */ struct dbnd_col *info; NPPROW *p; NPPCOL *s; /* the column must be non-negative with upper bound */ xassert(q->lb == 0.0); xassert(q->ub > 0.0); xassert(q->ub != +DBL_MAX); /* create variable s */ s = npp_add_col(npp); s->is_int = q->is_int; s->lb = 0.0, s->ub = +DBL_MAX; /* create equality constraint (2) */ p = npp_add_row(npp); p->lb = p->ub = q->ub; npp_add_aij(npp, p, q, +1.0); npp_add_aij(npp, p, s, +1.0); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_dbnd_col, sizeof(struct dbnd_col)); info->q = q->j; info->s = s->j; /* remove upper bound of x[q] */ q->ub = +DBL_MAX; return; } static int rcv_dbnd_col(NPP *npp, void *_info) { /* recover non-negative column with upper bound */ struct dbnd_col *info = _info; if (npp->sol == GLP_BS) { if (npp->c_stat[info->q] == GLP_BS) { if (npp->c_stat[info->s] == GLP_BS) npp->c_stat[info->q] = GLP_BS; else if (npp->c_stat[info->s] == GLP_NL) npp->c_stat[info->q] = GLP_NU; else { npp_error(); return 1; } } else if (npp->c_stat[info->q] == GLP_NL) { if (npp->c_stat[info->s] == GLP_BS || npp->c_stat[info->s] == GLP_NL) npp->c_stat[info->q] = GLP_NL; else { npp_error(); return 1; } } else { npp_error(); return 1; } } return 0; } /*********************************************************************** * NAME * * npp_fixed_col - process fixed column * * SYNOPSIS * * #include "glpnpp.h" * void npp_fixed_col(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_fixed_col processes column q, which is fixed: * * x[q] = s[q], (1) * * where s[q] is a fixed column value. * * PROBLEM TRANSFORMATION * * The value of a fixed column can be substituted into the objective * and constraint rows that allows removing the column from the problem. * * Substituting x[q] = s[q] into the objective row, we have: * * z = sum c[j] x[j] + c0 = * j * * = sum c[j] x[j] + c[q] x[q] + c0 = * j!=q * * = sum c[j] x[j] + c[q] s[q] + c0 = * j!=q * * = sum c[j] x[j] + c~0, * j!=q * * where * * c~0 = c0 + c[q] s[q] (2) * * is the constant term of the objective in the transformed problem. * Similarly, substituting x[q] = s[q] into constraint row i, we have: * * L[i] <= sum a[i,j] x[j] <= U[i] ==> * j * * L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> * j!=q * * L[i] <= sum a[i,j] x[j] + a[i,q] s[q] <= U[i] ==> * j!=q * * L~[i] <= sum a[i,j] x[j] + a[i,q] s <= U~[i], * j!=q * * where * * L~[i] = L[i] - a[i,q] s[q], U~[i] = U[i] - a[i,q] s[q] (3) * * are lower and upper bounds of row i in the transformed problem, * resp. * * RECOVERING BASIC SOLUTION * * Column q is assigned status GLP_NS and its value is assigned s[q]. * * RECOVERING INTERIOR-POINT SOLUTION * * Value of column q is assigned s[q]. * * RECOVERING MIP SOLUTION * * Value of column q is assigned s[q]. */ struct fixed_col { /* fixed column */ int q; /* column reference number for variable x[q] */ double s; /* value, at which x[q] is fixed */ }; static int rcv_fixed_col(NPP *npp, void *info); void npp_fixed_col(NPP *npp, NPPCOL *q) { /* process fixed column */ struct fixed_col *info; NPPROW *i; NPPAIJ *aij; /* the column must be fixed */ xassert(q->lb == q->ub); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_fixed_col, sizeof(struct fixed_col)); info->q = q->j; info->s = q->lb; /* substitute x[q] = s[q] into objective row */ npp->c0 += q->coef * q->lb; /* substitute x[q] = s[q] into constraint rows */ for (aij = q->ptr; aij != NULL; aij = aij->c_next) { i = aij->row; if (i->lb == i->ub) i->ub = (i->lb -= aij->val * q->lb); else { if (i->lb != -DBL_MAX) i->lb -= aij->val * q->lb; if (i->ub != +DBL_MAX) i->ub -= aij->val * q->lb; } } /* remove the column from the problem */ npp_del_col(npp, q); return; } static int rcv_fixed_col(NPP *npp, void *_info) { /* recover fixed column */ struct fixed_col *info = _info; if (npp->sol == GLP_SOL) npp->c_stat[info->q] = GLP_NS; npp->c_value[info->q] = info->s; return 0; } /*********************************************************************** * NAME * * npp_make_equality - process row with almost identical bounds * * SYNOPSIS * * #include "glpnpp.h" * int npp_make_equality(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_make_equality processes row p: * * L[p] <= sum a[p,j] x[j] <= U[p], (1) * j * * where -oo < L[p] < U[p] < +oo, i.e. which is double-sided inequality * constraint. * * RETURNS * * 0 - row bounds have not been changed; * * 1 - row has been replaced by equality constraint. * * PROBLEM TRANSFORMATION * * If bounds of row (1) are very close to each other: * * U[p] - L[p] <= eps, (2) * * where eps is an absolute tolerance for row value, the row can be * replaced by the following almost equivalent equiality constraint: * * sum a[p,j] x[j] = b, (3) * j * * where b = (L[p] + U[p]) / 2. If the right-hand side in (3) happens * to be very close to its nearest integer: * * |b - floor(b + 0.5)| <= eps, (4) * * it is reasonable to use this nearest integer as the right-hand side. * * RECOVERING BASIC SOLUTION * * Status of row p in solution to the original problem is determined * by its status and the sign of its multiplier pi[p] in solution to * the transformed problem as follows: * * +-----------------------+---------+--------------------+ * | Status of row p | Sign of | Status of row p | * | (transformed problem) | pi[p] | (original problem) | * +-----------------------+---------+--------------------+ * | GLP_BS | + / - | GLP_BS | * | GLP_NS | + | GLP_NL | * | GLP_NS | - | GLP_NU | * +-----------------------+---------+--------------------+ * * Value of row multiplier pi[p] in solution to the original problem is * the same as in solution to the transformed problem. * * RECOVERING INTERIOR POINT SOLUTION * * Value of row multiplier pi[p] in solution to the original problem is * the same as in solution to the transformed problem. * * RECOVERING MIP SOLUTION * * None needed. */ struct make_equality { /* row with almost identical bounds */ int p; /* row reference number */ }; static int rcv_make_equality(NPP *npp, void *info); int npp_make_equality(NPP *npp, NPPROW *p) { /* process row with almost identical bounds */ struct make_equality *info; double b, eps, nint; /* the row must be double-sided inequality */ xassert(p->lb != -DBL_MAX); xassert(p->ub != +DBL_MAX); xassert(p->lb < p->ub); /* check row bounds */ eps = 1e-9 + 1e-12 * fabs(p->lb); if (p->ub - p->lb > eps) return 0; /* row bounds are very close to each other */ /* create transformation stack entry */ info = npp_push_tse(npp, rcv_make_equality, sizeof(struct make_equality)); info->p = p->i; /* compute right-hand side */ b = 0.5 * (p->ub + p->lb); nint = floor(b + 0.5); if (fabs(b - nint) <= eps) b = nint; /* replace row p by almost equivalent equality constraint */ p->lb = p->ub = b; return 1; } int rcv_make_equality(NPP *npp, void *_info) { /* recover row with almost identical bounds */ struct make_equality *info = _info; if (npp->sol == GLP_SOL) { if (npp->r_stat[info->p] == GLP_BS) npp->r_stat[info->p] = GLP_BS; else if (npp->r_stat[info->p] == GLP_NS) { if (npp->r_pi[info->p] >= 0.0) npp->r_stat[info->p] = GLP_NL; else npp->r_stat[info->p] = GLP_NU; } else { npp_error(); return 1; } } return 0; } /*********************************************************************** * NAME * * npp_make_fixed - process column with almost identical bounds * * SYNOPSIS * * #include "glpnpp.h" * int npp_make_fixed(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_make_fixed processes column q: * * l[q] <= x[q] <= u[q], (1) * * where -oo < l[q] < u[q] < +oo, i.e. which has both lower and upper * bounds. * * RETURNS * * 0 - column bounds have not been changed; * * 1 - column has been fixed. * * PROBLEM TRANSFORMATION * * If bounds of column (1) are very close to each other: * * u[q] - l[q] <= eps, (2) * * where eps is an absolute tolerance for column value, the column can * be fixed: * * x[q] = s[q], (3) * * where s[q] = (l[q] + u[q]) / 2. And if the fixed column value s[q] * happens to be very close to its nearest integer: * * |s[q] - floor(s[q] + 0.5)| <= eps, (4) * * it is reasonable to use this nearest integer as the fixed value. * * RECOVERING BASIC SOLUTION * * In the dual system of the original (as well as transformed) problem * column q corresponds to the following row: * * sum a[i,q] pi[i] + lambda[q] = c[q]. (5) * i * * Since multipliers pi[i] are known for all rows from solution to the * transformed problem, formula (5) allows computing value of multiplier * (reduced cost) for column q: * * lambda[q] = c[q] - sum a[i,q] pi[i]. (6) * i * * Status of column q in solution to the original problem is determined * by its status and the sign of its multiplier lambda[q] in solution to * the transformed problem as follows: * * +-----------------------+-----------+--------------------+ * | Status of column q | Sign of | Status of column q | * | (transformed problem) | lambda[q] | (original problem) | * +-----------------------+-----------+--------------------+ * | GLP_BS | + / - | GLP_BS | * | GLP_NS | + | GLP_NL | * | GLP_NS | - | GLP_NU | * +-----------------------+-----------+--------------------+ * * Value of column q in solution to the original problem is the same as * in solution to the transformed problem. * * RECOVERING INTERIOR POINT SOLUTION * * Value of column q in solution to the original problem is the same as * in solution to the transformed problem. * * RECOVERING MIP SOLUTION * * None needed. */ struct make_fixed { /* column with almost identical bounds */ int q; /* column reference number */ double c; /* objective coefficient at x[q] */ NPPLFE *ptr; /* list of non-zero coefficients a[i,q] */ }; static int rcv_make_fixed(NPP *npp, void *info); int npp_make_fixed(NPP *npp, NPPCOL *q) { /* process column with almost identical bounds */ struct make_fixed *info; NPPAIJ *aij; NPPLFE *lfe; double s, eps, nint; /* the column must be double-bounded */ xassert(q->lb != -DBL_MAX); xassert(q->ub != +DBL_MAX); xassert(q->lb < q->ub); /* check column bounds */ eps = 1e-9 + 1e-12 * fabs(q->lb); if (q->ub - q->lb > eps) return 0; /* column bounds are very close to each other */ /* create transformation stack entry */ info = npp_push_tse(npp, rcv_make_fixed, sizeof(struct make_fixed)); info->q = q->j; info->c = q->coef; info->ptr = NULL; /* save column coefficients a[i,q] (needed for basic solution only) */ if (npp->sol == GLP_SOL) { for (aij = q->ptr; aij != NULL; aij = aij->c_next) { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); lfe->ref = aij->row->i; lfe->val = aij->val; lfe->next = info->ptr; info->ptr = lfe; } } /* compute column fixed value */ s = 0.5 * (q->ub + q->lb); nint = floor(s + 0.5); if (fabs(s - nint) <= eps) s = nint; /* make column q fixed */ q->lb = q->ub = s; return 1; } static int rcv_make_fixed(NPP *npp, void *_info) { /* recover column with almost identical bounds */ struct make_fixed *info = _info; NPPLFE *lfe; double lambda; if (npp->sol == GLP_SOL) { if (npp->c_stat[info->q] == GLP_BS) npp->c_stat[info->q] = GLP_BS; else if (npp->c_stat[info->q] == GLP_NS) { /* compute multiplier for column q with formula (6) */ lambda = info->c; for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) lambda -= lfe->val * npp->r_pi[lfe->ref]; /* assign status to non-basic column */ if (lambda >= 0.0) npp->c_stat[info->q] = GLP_NL; else npp->c_stat[info->q] = GLP_NU; } else { npp_error(); return 1; } } return 0; } /* eof */ glpk-4.52.1/src/glpnpp03.c0000644000062000006210000030076312175147600014330 0ustar maomkpasswd/* glpnpp03.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpnpp.h" /*********************************************************************** * NAME * * npp_empty_row - process empty row * * SYNOPSIS * * #include "glpnpp.h" * int npp_empty_row(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_empty_row processes row p, which is empty, i.e. * coefficients at all columns in this row are zero: * * L[p] <= sum 0 x[j] <= U[p], (1) * * where L[p] <= U[p]. * * RETURNS * * 0 - success; * * 1 - problem has no primal feasible solution. * * PROBLEM TRANSFORMATION * * If the following conditions hold: * * L[p] <= +eps, U[p] >= -eps, (2) * * where eps is an absolute tolerance for row value, the row p is * redundant. In this case it can be replaced by equivalent redundant * row, which is free (unbounded), and then removed from the problem. * Otherwise, the row p is infeasible and, thus, the problem has no * primal feasible solution. * * RECOVERING BASIC SOLUTION * * See the routine npp_free_row. * * RECOVERING INTERIOR-POINT SOLUTION * * See the routine npp_free_row. * * RECOVERING MIP SOLUTION * * None needed. */ int npp_empty_row(NPP *npp, NPPROW *p) { /* process empty row */ double eps = 1e-3; /* the row must be empty */ xassert(p->ptr == NULL); /* check primal feasibility */ if (p->lb > +eps || p->ub < -eps) return 1; /* replace the row by equivalent free (unbounded) row */ p->lb = -DBL_MAX, p->ub = +DBL_MAX; /* and process it */ npp_free_row(npp, p); return 0; } /*********************************************************************** * NAME * * npp_empty_col - process empty column * * SYNOPSIS * * #include "glpnpp.h" * int npp_empty_col(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_empty_col processes column q: * * l[q] <= x[q] <= u[q], (1) * * where l[q] <= u[q], which is empty, i.e. has zero coefficients in * all constraint rows. * * RETURNS * * 0 - success; * * 1 - problem has no dual feasible solution. * * PROBLEM TRANSFORMATION * * The row of the dual system corresponding to the empty column is the * following: * * sum 0 pi[i] + lambda[q] = c[q], (2) * i * * from which it follows that: * * lambda[q] = c[q]. (3) * * If the following condition holds: * * c[q] < - eps, (4) * * where eps is an absolute tolerance for column multiplier, the lower * column bound l[q] must be active to provide dual feasibility (note * that being preprocessed the problem is always minimization). In this * case the column can be fixed on its lower bound and removed from the * problem (if the column is integral, its bounds are also assumed to * be integral). And if the column has no lower bound (l[q] = -oo), the * problem has no dual feasible solution. * * If the following condition holds: * * c[q] > + eps, (5) * * the upper column bound u[q] must be active to provide dual * feasibility. In this case the column can be fixed on its upper bound * and removed from the problem. And if the column has no upper bound * (u[q] = +oo), the problem has no dual feasible solution. * * Finally, if the following condition holds: * * - eps <= c[q] <= +eps, (6) * * dual feasibility does not depend on a particular value of column q. * In this case the column can be fixed either on its lower bound (if * l[q] > -oo) or on its upper bound (if u[q] < +oo) or at zero (if the * column is unbounded) and then removed from the problem. * * RECOVERING BASIC SOLUTION * * See the routine npp_fixed_col. Having been recovered the column * is assigned status GLP_NS. However, if actually it is not fixed * (l[q] < u[q]), its status should be changed to GLP_NL, GLP_NU, or * GLP_NF depending on which bound it was fixed on transformation stage. * * RECOVERING INTERIOR-POINT SOLUTION * * See the routine npp_fixed_col. * * RECOVERING MIP SOLUTION * * See the routine npp_fixed_col. */ struct empty_col { /* empty column */ int q; /* column reference number */ char stat; /* status in basic solution */ }; static int rcv_empty_col(NPP *npp, void *info); int npp_empty_col(NPP *npp, NPPCOL *q) { /* process empty column */ struct empty_col *info; double eps = 1e-3; /* the column must be empty */ xassert(q->ptr == NULL); /* check dual feasibility */ if (q->coef > +eps && q->lb == -DBL_MAX) return 1; if (q->coef < -eps && q->ub == +DBL_MAX) return 1; /* create transformation stack entry */ info = npp_push_tse(npp, rcv_empty_col, sizeof(struct empty_col)); info->q = q->j; /* fix the column */ if (q->lb == -DBL_MAX && q->ub == +DBL_MAX) { /* free column */ info->stat = GLP_NF; q->lb = q->ub = 0.0; } else if (q->ub == +DBL_MAX) lo: { /* column with lower bound */ info->stat = GLP_NL; q->ub = q->lb; } else if (q->lb == -DBL_MAX) up: { /* column with upper bound */ info->stat = GLP_NU; q->lb = q->ub; } else if (q->lb != q->ub) { /* double-bounded column */ if (q->coef >= +DBL_EPSILON) goto lo; if (q->coef <= -DBL_EPSILON) goto up; if (fabs(q->lb) <= fabs(q->ub)) goto lo; else goto up; } else { /* fixed column */ info->stat = GLP_NS; } /* process fixed column */ npp_fixed_col(npp, q); return 0; } static int rcv_empty_col(NPP *npp, void *_info) { /* recover empty column */ struct empty_col *info = _info; if (npp->sol == GLP_SOL) npp->c_stat[info->q] = info->stat; return 0; } /*********************************************************************** * NAME * * npp_implied_value - process implied column value * * SYNOPSIS * * #include "glpnpp.h" * int npp_implied_value(NPP *npp, NPPCOL *q, double s); * * DESCRIPTION * * For column q: * * l[q] <= x[q] <= u[q], (1) * * where l[q] < u[q], the routine npp_implied_value processes its * implied value s[q]. If this implied value satisfies to the current * column bounds and integrality condition, the routine fixes column q * at the given point. Note that the column is kept in the problem in * any case. * * RETURNS * * 0 - column has been fixed; * * 1 - implied value violates to current column bounds; * * 2 - implied value violates integrality condition. * * ALGORITHM * * Implied column value s[q] satisfies to the current column bounds if * the following condition holds: * * l[q] - eps <= s[q] <= u[q] + eps, (2) * * where eps is an absolute tolerance for column value. If the column * is integral, the following condition also must hold: * * |s[q] - floor(s[q]+0.5)| <= eps, (3) * * where floor(s[q]+0.5) is the nearest integer to s[q]. * * If both condition (2) and (3) are satisfied, the column can be fixed * at the value s[q], or, if it is integral, at floor(s[q]+0.5). * Otherwise, if s[q] violates (2) or (3), the problem has no feasible * solution. * * Note: If s[q] is close to l[q] or u[q], it seems to be reasonable to * fix the column at its lower or upper bound, resp. rather than at the * implied value. */ int npp_implied_value(NPP *npp, NPPCOL *q, double s) { /* process implied column value */ double eps, nint; xassert(npp == npp); /* column must not be fixed */ xassert(q->lb < q->ub); /* check integrality */ if (q->is_int) { nint = floor(s + 0.5); if (fabs(s - nint) <= 1e-5) s = nint; else return 2; } /* check current column lower bound */ if (q->lb != -DBL_MAX) { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); if (s < q->lb - eps) return 1; /* if s[q] is close to l[q], fix column at its lower bound rather than at the implied value */ if (s < q->lb + 1e-3 * eps) { q->ub = q->lb; return 0; } } /* check current column upper bound */ if (q->ub != +DBL_MAX) { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); if (s > q->ub + eps) return 1; /* if s[q] is close to u[q], fix column at its upper bound rather than at the implied value */ if (s > q->ub - 1e-3 * eps) { q->lb = q->ub; return 0; } } /* fix column at the implied value */ q->lb = q->ub = s; return 0; } /*********************************************************************** * NAME * * npp_eq_singlet - process row singleton (equality constraint) * * SYNOPSIS * * #include "glpnpp.h" * int npp_eq_singlet(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_eq_singlet processes row p, which is equiality * constraint having the only non-zero coefficient: * * a[p,q] x[q] = b. (1) * * RETURNS * * 0 - success; * * 1 - problem has no primal feasible solution; * * 2 - problem has no integer feasible solution. * * PROBLEM TRANSFORMATION * * The equality constraint defines implied value of column q: * * x[q] = s[q] = b / a[p,q]. (2) * * If the implied value s[q] satisfies to the column bounds (see the * routine npp_implied_value), the column can be fixed at s[q] and * removed from the problem. In this case row p becomes redundant, so * it can be replaced by equivalent free row and also removed from the * problem. * * Note that the routine removes from the problem only row p. Column q * becomes fixed, however, it is kept in the problem. * * RECOVERING BASIC SOLUTION * * In solution to the original problem row p is assigned status GLP_NS * (active equality constraint), and column q is assigned status GLP_BS * (basic column). * * Multiplier for row p can be computed as follows. In the dual system * of the original problem column q corresponds to the following row: * * sum a[i,q] pi[i] + lambda[q] = c[q] ==> * i * * sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q]. * i!=p * * Therefore: * * 1 * pi[p] = ------ (c[q] - lambda[q] - sum a[i,q] pi[i]), (3) * a[p,q] i!=q * * where lambda[q] = 0 (since column[q] is basic), and pi[i] for all * i != p are known in solution to the transformed problem. * * Value of column q in solution to the original problem is assigned * its implied value s[q]. * * RECOVERING INTERIOR-POINT SOLUTION * * Multiplier for row p is computed with formula (3). Value of column * q is assigned its implied value s[q]. * * RECOVERING MIP SOLUTION * * Value of column q is assigned its implied value s[q]. */ struct eq_singlet { /* row singleton (equality constraint) */ int p; /* row reference number */ int q; /* column reference number */ double apq; /* constraint coefficient a[p,q] */ double c; /* objective coefficient at x[q] */ NPPLFE *ptr; /* list of non-zero coefficients a[i,q], i != p */ }; static int rcv_eq_singlet(NPP *npp, void *info); int npp_eq_singlet(NPP *npp, NPPROW *p) { /* process row singleton (equality constraint) */ struct eq_singlet *info; NPPCOL *q; NPPAIJ *aij; NPPLFE *lfe; int ret; double s; /* the row must be singleton equality constraint */ xassert(p->lb == p->ub); xassert(p->ptr != NULL && p->ptr->r_next == NULL); /* compute and process implied column value */ aij = p->ptr; q = aij->col; s = p->lb / aij->val; ret = npp_implied_value(npp, q, s); xassert(0 <= ret && ret <= 2); if (ret != 0) return ret; /* create transformation stack entry */ info = npp_push_tse(npp, rcv_eq_singlet, sizeof(struct eq_singlet)); info->p = p->i; info->q = q->j; info->apq = aij->val; info->c = q->coef; info->ptr = NULL; /* save column coefficients a[i,q], i != p (not needed for MIP solution) */ if (npp->sol != GLP_MIP) { for (aij = q->ptr; aij != NULL; aij = aij->c_next) { if (aij->row == p) continue; /* skip a[p,q] */ lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); lfe->ref = aij->row->i; lfe->val = aij->val; lfe->next = info->ptr; info->ptr = lfe; } } /* remove the row from the problem */ npp_del_row(npp, p); return 0; } static int rcv_eq_singlet(NPP *npp, void *_info) { /* recover row singleton (equality constraint) */ struct eq_singlet *info = _info; NPPLFE *lfe; double temp; if (npp->sol == GLP_SOL) { /* column q must be already recovered as GLP_NS */ if (npp->c_stat[info->q] != GLP_NS) { npp_error(); return 1; } npp->r_stat[info->p] = GLP_NS; npp->c_stat[info->q] = GLP_BS; } if (npp->sol != GLP_MIP) { /* compute multiplier for row p with formula (3) */ temp = info->c; for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) temp -= lfe->val * npp->r_pi[lfe->ref]; npp->r_pi[info->p] = temp / info->apq; } return 0; } /*********************************************************************** * NAME * * npp_implied_lower - process implied column lower bound * * SYNOPSIS * * #include "glpnpp.h" * int npp_implied_lower(NPP *npp, NPPCOL *q, double l); * * DESCRIPTION * * For column q: * * l[q] <= x[q] <= u[q], (1) * * where l[q] < u[q], the routine npp_implied_lower processes its * implied lower bound l'[q]. As the result the current column lower * bound may increase. Note that the column is kept in the problem in * any case. * * RETURNS * * 0 - current column lower bound has not changed; * * 1 - current column lower bound has changed, but not significantly; * * 2 - current column lower bound has significantly changed; * * 3 - column has been fixed on its upper bound; * * 4 - implied lower bound violates current column upper bound. * * ALGORITHM * * If column q is integral, before processing its implied lower bound * should be rounded up: * * ( floor(l'[q]+0.5), if |l'[q] - floor(l'[q]+0.5)| <= eps * l'[q] := < (2) * ( ceil(l'[q]), otherwise * * where floor(l'[q]+0.5) is the nearest integer to l'[q], ceil(l'[q]) * is smallest integer not less than l'[q], and eps is an absolute * tolerance for column value. * * Processing implied column lower bound l'[q] includes the following * cases: * * 1) if l'[q] < l[q] + eps, implied lower bound is redundant; * * 2) if l[q] + eps <= l[q] <= u[q] + eps, current column lower bound * l[q] can be strengthened by replacing it with l'[q]. If in this * case new column lower bound becomes close to current column upper * bound u[q], the column can be fixed on its upper bound; * * 3) if l'[q] > u[q] + eps, implied lower bound violates current * column upper bound u[q], in which case the problem has no primal * feasible solution. */ int npp_implied_lower(NPP *npp, NPPCOL *q, double l) { /* process implied column lower bound */ int ret; double eps, nint; xassert(npp == npp); /* column must not be fixed */ xassert(q->lb < q->ub); /* implied lower bound must be finite */ xassert(l != -DBL_MAX); /* if column is integral, round up l'[q] */ if (q->is_int) { nint = floor(l + 0.5); if (fabs(l - nint) <= 1e-5) l = nint; else l = ceil(l); } /* check current column lower bound */ if (q->lb != -DBL_MAX) { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->lb)); if (l < q->lb + eps) { ret = 0; /* redundant */ goto done; } } /* check current column upper bound */ if (q->ub != +DBL_MAX) { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub)); if (l > q->ub + eps) { ret = 4; /* infeasible */ goto done; } /* if l'[q] is close to u[q], fix column at its upper bound */ if (l > q->ub - 1e-3 * eps) { q->lb = q->ub; ret = 3; /* fixed */ goto done; } } /* check if column lower bound changes significantly */ if (q->lb == -DBL_MAX) ret = 2; /* significantly */ else if (q->is_int && l > q->lb + 0.5) ret = 2; /* significantly */ else if (l > q->lb + 0.30 * (1.0 + fabs(q->lb))) ret = 2; /* significantly */ else ret = 1; /* not significantly */ /* set new column lower bound */ q->lb = l; done: return ret; } /*********************************************************************** * NAME * * npp_implied_upper - process implied column upper bound * * SYNOPSIS * * #include "glpnpp.h" * int npp_implied_upper(NPP *npp, NPPCOL *q, double u); * * DESCRIPTION * * For column q: * * l[q] <= x[q] <= u[q], (1) * * where l[q] < u[q], the routine npp_implied_upper processes its * implied upper bound u'[q]. As the result the current column upper * bound may decrease. Note that the column is kept in the problem in * any case. * * RETURNS * * 0 - current column upper bound has not changed; * * 1 - current column upper bound has changed, but not significantly; * * 2 - current column upper bound has significantly changed; * * 3 - column has been fixed on its lower bound; * * 4 - implied upper bound violates current column lower bound. * * ALGORITHM * * If column q is integral, before processing its implied upper bound * should be rounded down: * * ( floor(u'[q]+0.5), if |u'[q] - floor(l'[q]+0.5)| <= eps * u'[q] := < (2) * ( floor(l'[q]), otherwise * * where floor(u'[q]+0.5) is the nearest integer to u'[q], * floor(u'[q]) is largest integer not greater than u'[q], and eps is * an absolute tolerance for column value. * * Processing implied column upper bound u'[q] includes the following * cases: * * 1) if u'[q] > u[q] - eps, implied upper bound is redundant; * * 2) if l[q] - eps <= u[q] <= u[q] - eps, current column upper bound * u[q] can be strengthened by replacing it with u'[q]. If in this * case new column upper bound becomes close to current column lower * bound, the column can be fixed on its lower bound; * * 3) if u'[q] < l[q] - eps, implied upper bound violates current * column lower bound l[q], in which case the problem has no primal * feasible solution. */ int npp_implied_upper(NPP *npp, NPPCOL *q, double u) { int ret; double eps, nint; xassert(npp == npp); /* column must not be fixed */ xassert(q->lb < q->ub); /* implied upper bound must be finite */ xassert(u != +DBL_MAX); /* if column is integral, round down u'[q] */ if (q->is_int) { nint = floor(u + 0.5); if (fabs(u - nint) <= 1e-5) u = nint; else u = floor(u); } /* check current column upper bound */ if (q->ub != +DBL_MAX) { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->ub)); if (u > q->ub - eps) { ret = 0; /* redundant */ goto done; } } /* check current column lower bound */ if (q->lb != -DBL_MAX) { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb)); if (u < q->lb - eps) { ret = 4; /* infeasible */ goto done; } /* if u'[q] is close to l[q], fix column at its lower bound */ if (u < q->lb + 1e-3 * eps) { q->ub = q->lb; ret = 3; /* fixed */ goto done; } } /* check if column upper bound changes significantly */ if (q->ub == +DBL_MAX) ret = 2; /* significantly */ else if (q->is_int && u < q->ub - 0.5) ret = 2; /* significantly */ else if (u < q->ub - 0.30 * (1.0 + fabs(q->ub))) ret = 2; /* significantly */ else ret = 1; /* not significantly */ /* set new column upper bound */ q->ub = u; done: return ret; } /*********************************************************************** * NAME * * npp_ineq_singlet - process row singleton (inequality constraint) * * SYNOPSIS * * #include "glpnpp.h" * int npp_ineq_singlet(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_ineq_singlet processes row p, which is inequality * constraint having the only non-zero coefficient: * * L[p] <= a[p,q] * x[q] <= U[p], (1) * * where L[p] < U[p], L[p] > -oo and/or U[p] < +oo. * * RETURNS * * 0 - current column bounds have not changed; * * 1 - current column bounds have changed, but not significantly; * * 2 - current column bounds have significantly changed; * * 3 - column has been fixed on its lower or upper bound; * * 4 - problem has no primal feasible solution. * * PROBLEM TRANSFORMATION * * Inequality constraint (1) defines implied bounds of column q: * * ( L[p] / a[p,q], if a[p,q] > 0 * l'[q] = < (2) * ( U[p] / a[p,q], if a[p,q] < 0 * * ( U[p] / a[p,q], if a[p,q] > 0 * u'[q] = < (3) * ( L[p] / a[p,q], if a[p,q] < 0 * * If these implied bounds do not violate current bounds of column q: * * l[q] <= x[q] <= u[q], (4) * * they can be used to strengthen the current column bounds: * * l[q] := max(l[q], l'[q]), (5) * * u[q] := min(u[q], u'[q]). (6) * * (See the routines npp_implied_lower and npp_implied_upper.) * * Once bounds of row p (1) have been carried over column q, the row * becomes redundant, so it can be replaced by equivalent free row and * removed from the problem. * * Note that the routine removes from the problem only row p. Column q, * even it has been fixed, is kept in the problem. * * RECOVERING BASIC SOLUTION * * Note that the row in the dual system corresponding to column q is * the following: * * sum a[i,q] pi[i] + lambda[q] = c[q] ==> * i * (7) * sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q], * i!=p * * where pi[i] for all i != p are known in solution to the transformed * problem. Row p does not exist in the transformed problem, so it has * zero multiplier there. This allows computing multiplier for column q * in solution to the transformed problem: * * lambda~[q] = c[q] - sum a[i,q] pi[i]. (8) * i!=p * * Let in solution to the transformed problem column q be non-basic * with lower bound active (GLP_NL, lambda~[q] >= 0), and this lower * bound be implied one l'[q]. From the original problem's standpoint * this then means that actually the original column lower bound l[q] * is inactive, and active is that row bound L[p] or U[p] that defines * the implied bound l'[q] (2). In this case in solution to the * original problem column q is assigned status GLP_BS while row p is * assigned status GLP_NL (if a[p,q] > 0) or GLP_NU (if a[p,q] < 0). * Since now column q is basic, its multiplier lambda[q] is zero. This * allows using (7) and (8) to find multiplier for row p in solution to * the original problem: * * 1 * pi[p] = ------ (c[q] - sum a[i,q] pi[i]) = lambda~[q] / a[p,q] (9) * a[p,q] i!=p * * Now let in solution to the transformed problem column q be non-basic * with upper bound active (GLP_NU, lambda~[q] <= 0), and this upper * bound be implied one u'[q]. As in the previous case this then means * that from the original problem's standpoint actually the original * column upper bound u[q] is inactive, and active is that row bound * L[p] or U[p] that defines the implied bound u'[q] (3). In this case * in solution to the original problem column q is assigned status * GLP_BS, row p is assigned status GLP_NU (if a[p,q] > 0) or GLP_NL * (if a[p,q] < 0), and its multiplier is computed with formula (9). * * Strengthening bounds of column q according to (5) and (6) may make * it fixed. Thus, if in solution to the transformed problem column q is * non-basic and fixed (GLP_NS), we can suppose that if lambda~[q] > 0, * column q has active lower bound (GLP_NL), and if lambda~[q] < 0, * column q has active upper bound (GLP_NU), reducing this case to two * previous ones. If, however, lambda~[q] is close to zero or * corresponding bound of row p does not exist (this may happen if * lambda~[q] has wrong sign due to round-off errors, in which case it * is expected to be close to zero, since solution is assumed to be dual * feasible), column q can be assigned status GLP_BS (basic), and row p * can be made active on its existing bound. In the latter case row * multiplier pi[p] computed with formula (9) will be also close to * zero, and dual feasibility will be kept. * * In all other cases, namely, if in solution to the transformed * problem column q is basic (GLP_BS), or non-basic with original lower * bound l[q] active (GLP_NL), or non-basic with original upper bound * u[q] active (GLP_NU), constraint (1) is inactive. So in solution to * the original problem status of column q remains unchanged, row p is * assigned status GLP_BS, and its multiplier pi[p] is assigned zero * value. * * RECOVERING INTERIOR-POINT SOLUTION * * First, value of multiplier for column q in solution to the original * problem is computed with formula (8). If lambda~[q] > 0 and column q * has implied lower bound, or if lambda~[q] < 0 and column q has * implied upper bound, this means that from the original problem's * standpoint actually row p has corresponding active bound, in which * case its multiplier pi[p] is computed with formula (9). In other * cases, when the sign of lambda~[q] corresponds to original bound of * column q, or when lambda~[q] =~ 0, value of row multiplier pi[p] is * assigned zero value. * * RECOVERING MIP SOLUTION * * None needed. */ struct ineq_singlet { /* row singleton (inequality constraint) */ int p; /* row reference number */ int q; /* column reference number */ double apq; /* constraint coefficient a[p,q] */ double c; /* objective coefficient at x[q] */ double lb; /* row lower bound */ double ub; /* row upper bound */ char lb_changed; /* this flag is set if column lower bound was changed */ char ub_changed; /* this flag is set if column upper bound was changed */ NPPLFE *ptr; /* list of non-zero coefficients a[i,q], i != p */ }; static int rcv_ineq_singlet(NPP *npp, void *info); int npp_ineq_singlet(NPP *npp, NPPROW *p) { /* process row singleton (inequality constraint) */ struct ineq_singlet *info; NPPCOL *q; NPPAIJ *apq, *aij; NPPLFE *lfe; int lb_changed, ub_changed; double ll, uu; /* the row must be singleton inequality constraint */ xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); xassert(p->lb < p->ub); xassert(p->ptr != NULL && p->ptr->r_next == NULL); /* compute implied column bounds */ apq = p->ptr; q = apq->col; xassert(q->lb < q->ub); if (apq->val > 0.0) { ll = (p->lb == -DBL_MAX ? -DBL_MAX : p->lb / apq->val); uu = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub / apq->val); } else { ll = (p->ub == +DBL_MAX ? -DBL_MAX : p->ub / apq->val); uu = (p->lb == -DBL_MAX ? +DBL_MAX : p->lb / apq->val); } /* process implied column lower bound */ if (ll == -DBL_MAX) lb_changed = 0; else { lb_changed = npp_implied_lower(npp, q, ll); xassert(0 <= lb_changed && lb_changed <= 4); if (lb_changed == 4) return 4; /* infeasible */ } /* process implied column upper bound */ if (uu == +DBL_MAX) ub_changed = 0; else if (lb_changed == 3) { /* column was fixed on its upper bound due to l'[q] = u[q] */ /* note that L[p] < U[p], so l'[q] = u[q] < u'[q] */ ub_changed = 0; } else { ub_changed = npp_implied_upper(npp, q, uu); xassert(0 <= ub_changed && ub_changed <= 4); if (ub_changed == 4) return 4; /* infeasible */ } /* if neither lower nor upper column bound was changed, the row is originally redundant and can be replaced by free row */ if (!lb_changed && !ub_changed) { p->lb = -DBL_MAX, p->ub = +DBL_MAX; npp_free_row(npp, p); return 0; } /* create transformation stack entry */ info = npp_push_tse(npp, rcv_ineq_singlet, sizeof(struct ineq_singlet)); info->p = p->i; info->q = q->j; info->apq = apq->val; info->c = q->coef; info->lb = p->lb; info->ub = p->ub; info->lb_changed = (char)lb_changed; info->ub_changed = (char)ub_changed; info->ptr = NULL; /* save column coefficients a[i,q], i != p (not needed for MIP solution) */ if (npp->sol != GLP_MIP) { for (aij = q->ptr; aij != NULL; aij = aij->c_next) { if (aij == apq) continue; /* skip a[p,q] */ lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); lfe->ref = aij->row->i; lfe->val = aij->val; lfe->next = info->ptr; info->ptr = lfe; } } /* remove the row from the problem */ npp_del_row(npp, p); return lb_changed >= ub_changed ? lb_changed : ub_changed; } static int rcv_ineq_singlet(NPP *npp, void *_info) { /* recover row singleton (inequality constraint) */ struct ineq_singlet *info = _info; NPPLFE *lfe; double lambda; if (npp->sol == GLP_MIP) goto done; /* compute lambda~[q] in solution to the transformed problem with formula (8) */ lambda = info->c; for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) lambda -= lfe->val * npp->r_pi[lfe->ref]; if (npp->sol == GLP_SOL) { /* recover basic solution */ if (npp->c_stat[info->q] == GLP_BS) { /* column q is basic, so row p is inactive */ npp->r_stat[info->p] = GLP_BS; npp->r_pi[info->p] = 0.0; } else if (npp->c_stat[info->q] == GLP_NL) nl: { /* column q is non-basic with lower bound active */ if (info->lb_changed) { /* it is implied bound, so actually row p is active while column q is basic */ npp->r_stat[info->p] = (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); npp->c_stat[info->q] = GLP_BS; npp->r_pi[info->p] = lambda / info->apq; } else { /* it is original bound, so row p is inactive */ npp->r_stat[info->p] = GLP_BS; npp->r_pi[info->p] = 0.0; } } else if (npp->c_stat[info->q] == GLP_NU) nu: { /* column q is non-basic with upper bound active */ if (info->ub_changed) { /* it is implied bound, so actually row p is active while column q is basic */ npp->r_stat[info->p] = (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); npp->c_stat[info->q] = GLP_BS; npp->r_pi[info->p] = lambda / info->apq; } else { /* it is original bound, so row p is inactive */ npp->r_stat[info->p] = GLP_BS; npp->r_pi[info->p] = 0.0; } } else if (npp->c_stat[info->q] == GLP_NS) { /* column q is non-basic and fixed; note, however, that in in the original problem it is non-fixed */ if (lambda > +1e-7) { if (info->apq > 0.0 && info->lb != -DBL_MAX || info->apq < 0.0 && info->ub != +DBL_MAX || !info->lb_changed) { /* either corresponding bound of row p exists or column q remains non-basic with its original lower bound active */ npp->c_stat[info->q] = GLP_NL; goto nl; } } if (lambda < -1e-7) { if (info->apq > 0.0 && info->ub != +DBL_MAX || info->apq < 0.0 && info->lb != -DBL_MAX || !info->ub_changed) { /* either corresponding bound of row p exists or column q remains non-basic with its original upper bound active */ npp->c_stat[info->q] = GLP_NU; goto nu; } } /* either lambda~[q] is close to zero, or corresponding bound of row p does not exist, because lambda~[q] has wrong sign due to round-off errors; in the latter case lambda~[q] is also assumed to be close to zero; so, we can make row p active on its existing bound and column q basic; pi[p] will have wrong sign, but it also will be close to zero (rarus casus of dual degeneracy) */ if (info->lb != -DBL_MAX && info->ub == +DBL_MAX) { /* row lower bound exists, but upper bound doesn't */ npp->r_stat[info->p] = GLP_NL; } else if (info->lb == -DBL_MAX && info->ub != +DBL_MAX) { /* row upper bound exists, but lower bound doesn't */ npp->r_stat[info->p] = GLP_NU; } else if (info->lb != -DBL_MAX && info->ub != +DBL_MAX) { /* both row lower and upper bounds exist */ /* to choose proper active row bound we should not use lambda~[q], because its value being close to zero is unreliable; so we choose that bound which provides primal feasibility for original constraint (1) */ if (info->apq * npp->c_value[info->q] <= 0.5 * (info->lb + info->ub)) npp->r_stat[info->p] = GLP_NL; else npp->r_stat[info->p] = GLP_NU; } else { npp_error(); return 1; } npp->c_stat[info->q] = GLP_BS; npp->r_pi[info->p] = lambda / info->apq; } else { npp_error(); return 1; } } if (npp->sol == GLP_IPT) { /* recover interior-point solution */ if (lambda > +DBL_EPSILON && info->lb_changed || lambda < -DBL_EPSILON && info->ub_changed) { /* actually row p has corresponding active bound */ npp->r_pi[info->p] = lambda / info->apq; } else { /* either bounds of column q are both inactive or its original bound is active */ npp->r_pi[info->p] = 0.0; } } done: return 0; } /*********************************************************************** * NAME * * npp_implied_slack - process column singleton (implied slack variable) * * SYNOPSIS * * #include "glpnpp.h" * void npp_implied_slack(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_implied_slack processes column q: * * l[q] <= x[q] <= u[q], (1) * * where l[q] < u[q], having the only non-zero coefficient in row p, * which is equality constraint: * * sum a[p,j] x[j] + a[p,q] x[q] = b. (2) * j!=q * * PROBLEM TRANSFORMATION * * (If x[q] is integral, this transformation must not be used.) * * The term a[p,q] x[q] in constraint (2) can be considered as a slack * variable that allows to carry bounds of column q over row p and then * remove column q from the problem. * * Constraint (2) can be written as follows: * * sum a[p,j] x[j] = b - a[p,q] x[q]. (3) * j!=q * * According to (1) constraint (3) is equivalent to the following * inequality constraint: * * L[p] <= sum a[p,j] x[j] <= U[p], (4) * j!=q * * where * * ( b - a[p,q] u[q], if a[p,q] > 0 * L[p] = < (5) * ( b - a[p,q] l[q], if a[p,q] < 0 * * ( b - a[p,q] l[q], if a[p,q] > 0 * U[p] = < (6) * ( b - a[p,q] u[q], if a[p,q] < 0 * * From (2) it follows that: * * 1 * x[q] = ------ (b - sum a[p,j] x[j]). (7) * a[p,q] j!=q * * In order to eliminate x[q] from the objective row we substitute it * from (6) to that row: * * z = sum c[j] x[j] + c[q] x[q] + c[0] = * j!=q * 1 * = sum c[j] x[j] + c[q] [------ (b - sum a[p,j] x[j])] + c0 = * j!=q a[p,q] j!=q * * = sum c~[j] x[j] + c~[0], * j!=q * a[p,j] b * c~[j] = c[j] - c[q] ------, c~0 = c0 - c[q] ------ (8) * a[p,q] a[p,q] * * are values of objective coefficients and constant term, resp., in * the transformed problem. * * Note that column q is column singleton, so in the dual system of the * original problem it corresponds to the following row singleton: * * a[p,q] pi[p] + lambda[q] = c[q]. (9) * * In the transformed problem row (9) would be the following: * * a[p,q] pi~[p] + lambda[q] = c~[q] = 0. (10) * * Subtracting (10) from (9) we have: * * a[p,q] (pi[p] - pi~[p]) = c[q] * * that gives the following formula to compute multiplier for row p in * solution to the original problem using its value in solution to the * transformed problem: * * pi[p] = pi~[p] + c[q] / a[p,q]. (11) * * RECOVERING BASIC SOLUTION * * Status of column q in solution to the original problem is defined * by status of row p in solution to the transformed problem and the * sign of coefficient a[p,q] in the original inequality constraint (2) * as follows: * * +-----------------------+---------+--------------------+ * | Status of row p | Sign of | Status of column q | * | (transformed problem) | a[p,q] | (original problem) | * +-----------------------+---------+--------------------+ * | GLP_BS | + / - | GLP_BS | * | GLP_NL | + | GLP_NU | * | GLP_NL | - | GLP_NL | * | GLP_NU | + | GLP_NL | * | GLP_NU | - | GLP_NU | * | GLP_NF | + / - | GLP_NF | * +-----------------------+---------+--------------------+ * * Value of column q is computed with formula (7). Since originally row * p is equality constraint, its status is assigned GLP_NS, and value of * its multiplier pi[p] is computed with formula (11). * * RECOVERING INTERIOR-POINT SOLUTION * * Value of column q is computed with formula (7). Row multiplier value * pi[p] is computed with formula (11). * * RECOVERING MIP SOLUTION * * Value of column q is computed with formula (7). */ struct implied_slack { /* column singleton (implied slack variable) */ int p; /* row reference number */ int q; /* column reference number */ double apq; /* constraint coefficient a[p,q] */ double b; /* right-hand side of original equality constraint */ double c; /* original objective coefficient at x[q] */ NPPLFE *ptr; /* list of non-zero coefficients a[p,j], j != q */ }; static int rcv_implied_slack(NPP *npp, void *info); void npp_implied_slack(NPP *npp, NPPCOL *q) { /* process column singleton (implied slack variable) */ struct implied_slack *info; NPPROW *p; NPPAIJ *aij; NPPLFE *lfe; /* the column must be non-integral non-fixed singleton */ xassert(!q->is_int); xassert(q->lb < q->ub); xassert(q->ptr != NULL && q->ptr->c_next == NULL); /* corresponding row must be equality constraint */ aij = q->ptr; p = aij->row; xassert(p->lb == p->ub); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_implied_slack, sizeof(struct implied_slack)); info->p = p->i; info->q = q->j; info->apq = aij->val; info->b = p->lb; info->c = q->coef; info->ptr = NULL; /* save row coefficients a[p,j], j != q, and substitute x[q] into the objective row */ for (aij = p->ptr; aij != NULL; aij = aij->r_next) { if (aij->col == q) continue; /* skip a[p,q] */ lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); lfe->ref = aij->col->j; lfe->val = aij->val; lfe->next = info->ptr; info->ptr = lfe; aij->col->coef -= info->c * (aij->val / info->apq); } npp->c0 += info->c * (info->b / info->apq); /* compute new row bounds */ if (info->apq > 0.0) { p->lb = (q->ub == +DBL_MAX ? -DBL_MAX : info->b - info->apq * q->ub); p->ub = (q->lb == -DBL_MAX ? +DBL_MAX : info->b - info->apq * q->lb); } else { p->lb = (q->lb == -DBL_MAX ? -DBL_MAX : info->b - info->apq * q->lb); p->ub = (q->ub == +DBL_MAX ? +DBL_MAX : info->b - info->apq * q->ub); } /* remove the column from the problem */ npp_del_col(npp, q); return; } static int rcv_implied_slack(NPP *npp, void *_info) { /* recover column singleton (implied slack variable) */ struct implied_slack *info = _info; NPPLFE *lfe; double temp; if (npp->sol == GLP_SOL) { /* assign statuses to row p and column q */ if (npp->r_stat[info->p] == GLP_BS || npp->r_stat[info->p] == GLP_NF) npp->c_stat[info->q] = npp->r_stat[info->p]; else if (npp->r_stat[info->p] == GLP_NL) npp->c_stat[info->q] = (char)(info->apq > 0.0 ? GLP_NU : GLP_NL); else if (npp->r_stat[info->p] == GLP_NU) npp->c_stat[info->q] = (char)(info->apq > 0.0 ? GLP_NL : GLP_NU); else { npp_error(); return 1; } npp->r_stat[info->p] = GLP_NS; } if (npp->sol != GLP_MIP) { /* compute multiplier for row p */ npp->r_pi[info->p] += info->c / info->apq; } /* compute value of column q */ temp = info->b; for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) temp -= lfe->val * npp->c_value[lfe->ref]; npp->c_value[info->q] = temp / info->apq; return 0; } /*********************************************************************** * NAME * * npp_implied_free - process column singleton (implied free variable) * * SYNOPSIS * * #include "glpnpp.h" * int npp_implied_free(NPP *npp, NPPCOL *q); * * DESCRIPTION * * The routine npp_implied_free processes column q: * * l[q] <= x[q] <= u[q], (1) * * having non-zero coefficient in the only row p, which is inequality * constraint: * * L[p] <= sum a[p,j] x[j] + a[p,q] x[q] <= U[p], (2) * j!=q * * where l[q] < u[q], L[p] < U[p], L[p] > -oo and/or U[p] < +oo. * * RETURNS * * 0 - success; * * 1 - column lower and/or upper bound(s) can be active; * * 2 - problem has no dual feasible solution. * * PROBLEM TRANSFORMATION * * Constraint (2) can be written as follows: * * L[p] - sum a[p,j] x[j] <= a[p,q] x[q] <= U[p] - sum a[p,j] x[j], * j!=q j!=q * * from which it follows that: * * alfa <= a[p,q] x[q] <= beta, (3) * * where * * alfa = inf(L[p] - sum a[p,j] x[j]) = * j!=q * * = L[p] - sup sum a[p,j] x[j] = (4) * j!=q * * = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j], * j in Jp j in Jn * * beta = sup(L[p] - sum a[p,j] x[j]) = * j!=q * * = L[p] - inf sum a[p,j] x[j] = (5) * j!=q * * = L[p] - sum a[p,j] l[j] - sum a[p,j] u[j], * j in Jp j in Jn * * Jp = {j != q: a[p,j] > 0}, Jn = {j != q: a[p,j] < 0}. (6) * * Inequality (3) defines implied bounds of variable x[q]: * * l'[q] <= x[q] <= u'[q], (7) * * where * * ( alfa / a[p,q], if a[p,q] > 0 * l'[q] = < (8a) * ( beta / a[p,q], if a[p,q] < 0 * * ( beta / a[p,q], if a[p,q] > 0 * u'[q] = < (8b) * ( alfa / a[p,q], if a[p,q] < 0 * * Thus, if l'[q] > l[q] - eps and u'[q] < u[q] + eps, where eps is * an absolute tolerance for column value, column bounds (1) cannot be * active, in which case column q can be replaced by equivalent free * (unbounded) column. * * Note that column q is column singleton, so in the dual system of the * original problem it corresponds to the following row singleton: * * a[p,q] pi[p] + lambda[q] = c[q], (9) * * from which it follows that: * * pi[p] = (c[q] - lambda[q]) / a[p,q]. (10) * * Let x[q] be implied free (unbounded) variable. Then column q can be * only basic, so its multiplier lambda[q] is equal to zero, and from * (10) we have: * * pi[p] = c[q] / a[p,q]. (11) * * There are possible three cases: * * 1) pi[p] < -eps, where eps is an absolute tolerance for row * multiplier. In this case, to provide dual feasibility of the * original problem, row p must be active on its lower bound, and * if its lower bound does not exist (L[p] = -oo), the problem has * no dual feasible solution; * * 2) pi[p] > +eps. In this case row p must be active on its upper * bound, and if its upper bound does not exist (U[p] = +oo), the * problem has no dual feasible solution; * * 3) -eps <= pi[p] <= +eps. In this case any (either lower or upper) * bound of row p can be active, because this does not affect dual * feasibility. * * Thus, in all three cases original inequality constraint (2) can be * replaced by equality constraint, where the right-hand side is either * lower or upper bound of row p, and bounds of column q can be removed * that makes it free (unbounded). (May note that this transformation * can be followed by transformation "Column singleton (implied slack * variable)" performed by the routine npp_implied_slack.) * * RECOVERING BASIC SOLUTION * * Status of row p in solution to the original problem is determined * by its status in solution to the transformed problem and its bound, * which was choosen to be active: * * +-----------------------+--------+--------------------+ * | Status of row p | Active | Status of row p | * | (transformed problem) | bound | (original problem) | * +-----------------------+--------+--------------------+ * | GLP_BS | L[p] | GLP_BS | * | GLP_BS | U[p] | GLP_BS | * | GLP_NS | L[p] | GLP_NL | * | GLP_NS | U[p] | GLP_NU | * +-----------------------+--------+--------------------+ * * Value of row multiplier pi[p] (as well as value of column q) in * solution to the original problem is the same as in solution to the * transformed problem. * * RECOVERING INTERIOR-POINT SOLUTION * * Value of row multiplier pi[p] in solution to the original problem is * the same as in solution to the transformed problem. * * RECOVERING MIP SOLUTION * * None needed. */ struct implied_free { /* column singleton (implied free variable) */ int p; /* row reference number */ char stat; /* row status: GLP_NL - active constraint on lower bound GLP_NU - active constraint on upper bound */ }; static int rcv_implied_free(NPP *npp, void *info); int npp_implied_free(NPP *npp, NPPCOL *q) { /* process column singleton (implied free variable) */ struct implied_free *info; NPPROW *p; NPPAIJ *apq, *aij; double alfa, beta, l, u, pi, eps; /* the column must be non-fixed singleton */ xassert(q->lb < q->ub); xassert(q->ptr != NULL && q->ptr->c_next == NULL); /* corresponding row must be inequality constraint */ apq = q->ptr; p = apq->row; xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX); xassert(p->lb < p->ub); /* compute alfa */ alfa = p->lb; if (alfa != -DBL_MAX) { for (aij = p->ptr; aij != NULL; aij = aij->r_next) { if (aij == apq) continue; /* skip a[p,q] */ if (aij->val > 0.0) { if (aij->col->ub == +DBL_MAX) { alfa = -DBL_MAX; break; } alfa -= aij->val * aij->col->ub; } else /* < 0.0 */ { if (aij->col->lb == -DBL_MAX) { alfa = -DBL_MAX; break; } alfa -= aij->val * aij->col->lb; } } } /* compute beta */ beta = p->ub; if (beta != +DBL_MAX) { for (aij = p->ptr; aij != NULL; aij = aij->r_next) { if (aij == apq) continue; /* skip a[p,q] */ if (aij->val > 0.0) { if (aij->col->lb == -DBL_MAX) { beta = +DBL_MAX; break; } beta -= aij->val * aij->col->lb; } else /* < 0.0 */ { if (aij->col->ub == +DBL_MAX) { beta = +DBL_MAX; break; } beta -= aij->val * aij->col->ub; } } } /* compute implied column lower bound l'[q] */ if (apq->val > 0.0) l = (alfa == -DBL_MAX ? -DBL_MAX : alfa / apq->val); else /* < 0.0 */ l = (beta == +DBL_MAX ? -DBL_MAX : beta / apq->val); /* compute implied column upper bound u'[q] */ if (apq->val > 0.0) u = (beta == +DBL_MAX ? +DBL_MAX : beta / apq->val); else u = (alfa == -DBL_MAX ? +DBL_MAX : alfa / apq->val); /* check if column lower bound l[q] can be active */ if (q->lb != -DBL_MAX) { eps = 1e-9 + 1e-12 * fabs(q->lb); if (l < q->lb - eps) return 1; /* yes, it can */ } /* check if column upper bound u[q] can be active */ if (q->ub != +DBL_MAX) { eps = 1e-9 + 1e-12 * fabs(q->ub); if (u > q->ub + eps) return 1; /* yes, it can */ } /* okay; make column q free (unbounded) */ q->lb = -DBL_MAX, q->ub = +DBL_MAX; /* create transformation stack entry */ info = npp_push_tse(npp, rcv_implied_free, sizeof(struct implied_free)); info->p = p->i; info->stat = -1; /* compute row multiplier pi[p] */ pi = q->coef / apq->val; /* check dual feasibility for row p */ if (pi > +DBL_EPSILON) { /* lower bound L[p] must be active */ if (p->lb != -DBL_MAX) nl: { info->stat = GLP_NL; p->ub = p->lb; } else { if (pi > +1e-5) return 2; /* dual infeasibility */ /* take a chance on U[p] */ xassert(p->ub != +DBL_MAX); goto nu; } } else if (pi < -DBL_EPSILON) { /* upper bound U[p] must be active */ if (p->ub != +DBL_MAX) nu: { info->stat = GLP_NU; p->lb = p->ub; } else { if (pi < -1e-5) return 2; /* dual infeasibility */ /* take a chance on L[p] */ xassert(p->lb != -DBL_MAX); goto nl; } } else { /* any bound (either L[p] or U[p]) can be made active */ if (p->ub == +DBL_MAX) { xassert(p->lb != -DBL_MAX); goto nl; } if (p->lb == -DBL_MAX) { xassert(p->ub != +DBL_MAX); goto nu; } if (fabs(p->lb) <= fabs(p->ub)) goto nl; else goto nu; } return 0; } static int rcv_implied_free(NPP *npp, void *_info) { /* recover column singleton (implied free variable) */ struct implied_free *info = _info; if (npp->sol == GLP_SOL) { if (npp->r_stat[info->p] == GLP_BS) npp->r_stat[info->p] = GLP_BS; else if (npp->r_stat[info->p] == GLP_NS) { xassert(info->stat == GLP_NL || info->stat == GLP_NU); npp->r_stat[info->p] = info->stat; } else { npp_error(); return 1; } } return 0; } /*********************************************************************** * NAME * * npp_eq_doublet - process row doubleton (equality constraint) * * SYNOPSIS * * #include "glpnpp.h" * NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_eq_doublet processes row p, which is equality * constraint having exactly two non-zero coefficients: * * a[p,q] x[q] + a[p,r] x[r] = b. (1) * * As the result of processing one of columns q or r is eliminated from * all other rows and, thus, becomes column singleton of type "implied * slack variable". Row p is not changed and along with column q and r * remains in the problem. * * RETURNS * * The routine npp_eq_doublet returns pointer to the descriptor of that * column q or r which has been eliminated. If, due to some reason, the * elimination was not performed, the routine returns NULL. * * PROBLEM TRANSFORMATION * * First, we decide which column q or r will be eliminated. Let it be * column q. Consider i-th constraint row, where column q has non-zero * coefficient a[i,q] != 0: * * L[i] <= sum a[i,j] x[j] <= U[i]. (2) * j * * In order to eliminate column q from row (2) we subtract from it row * (1) multiplied by gamma[i] = a[i,q] / a[p,q], i.e. we replace in the * transformed problem row (2) by its linear combination with row (1). * This transformation changes only coefficients in columns q and r, * and bounds of row i as follows: * * a~[i,q] = a[i,q] - gamma[i] a[p,q] = 0, (3) * * a~[i,r] = a[i,r] - gamma[i] a[p,r], (4) * * L~[i] = L[i] - gamma[i] b, (5) * * U~[i] = U[i] - gamma[i] b. (6) * * RECOVERING BASIC SOLUTION * * The transformation of the primal system of the original problem: * * L <= A x <= U (7) * * is equivalent to multiplying from the left a transformation matrix F * by components of this primal system, which in the transformed problem * becomes the following: * * F L <= F A x <= F U ==> L~ <= A~x <= U~. (8) * * The matrix F has the following structure: * * ( 1 -gamma[1] ) * ( ) * ( 1 -gamma[2] ) * ( ) * ( ... ... ) * ( ) * F = ( 1 -gamma[p-1] ) (9) * ( ) * ( 1 ) * ( ) * ( -gamma[p+1] 1 ) * ( ) * ( ... ... ) * * where its column containing elements -gamma[i] corresponds to row p * of the primal system. * * From (8) it follows that the dual system of the original problem: * * A'pi + lambda = c, (10) * * in the transformed problem becomes the following: * * A'F'inv(F')pi + lambda = c ==> (A~)'pi~ + lambda = c, (11) * * where: * * pi~ = inv(F')pi (12) * * is the vector of row multipliers in the transformed problem. Thus: * * pi = F'pi~. (13) * * Therefore, as it follows from (13), value of multiplier for row p in * solution to the original problem can be computed as follows: * * pi[p] = pi~[p] - sum gamma[i] pi~[i], (14) * i * * where pi~[i] = pi[i] is multiplier for row i (i != p). * * Note that the statuses of all rows and columns are not changed. * * RECOVERING INTERIOR-POINT SOLUTION * * Multiplier for row p in solution to the original problem is computed * with formula (14). * * RECOVERING MIP SOLUTION * * None needed. */ struct eq_doublet { /* row doubleton (equality constraint) */ int p; /* row reference number */ double apq; /* constraint coefficient a[p,q] */ NPPLFE *ptr; /* list of non-zero coefficients a[i,q], i != p */ }; static int rcv_eq_doublet(NPP *npp, void *info); NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p) { /* process row doubleton (equality constraint) */ struct eq_doublet *info; NPPROW *i; NPPCOL *q, *r; NPPAIJ *apq, *apr, *aiq, *air, *next; NPPLFE *lfe; double gamma; /* the row must be doubleton equality constraint */ xassert(p->lb == p->ub); xassert(p->ptr != NULL && p->ptr->r_next != NULL && p->ptr->r_next->r_next == NULL); /* choose column to be eliminated */ { NPPAIJ *a1, *a2; a1 = p->ptr, a2 = a1->r_next; if (fabs(a2->val) < 0.001 * fabs(a1->val)) { /* only first column can be eliminated, because second one has too small constraint coefficient */ apq = a1, apr = a2; } else if (fabs(a1->val) < 0.001 * fabs(a2->val)) { /* only second column can be eliminated, because first one has too small constraint coefficient */ apq = a2, apr = a1; } else { /* both columns are appropriate; choose that one which is shorter to minimize fill-in */ if (npp_col_nnz(npp, a1->col) <= npp_col_nnz(npp, a2->col)) { /* first column is shorter */ apq = a1, apr = a2; } else { /* second column is shorter */ apq = a2, apr = a1; } } } /* now columns q and r have been chosen */ q = apq->col, r = apr->col; /* create transformation stack entry */ info = npp_push_tse(npp, rcv_eq_doublet, sizeof(struct eq_doublet)); info->p = p->i; info->apq = apq->val; info->ptr = NULL; /* transform each row i (i != p), where a[i,q] != 0, to eliminate column q */ for (aiq = q->ptr; aiq != NULL; aiq = next) { next = aiq->c_next; if (aiq == apq) continue; /* skip row p */ i = aiq->row; /* row i to be transformed */ /* save constraint coefficient a[i,q] */ if (npp->sol != GLP_MIP) { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); lfe->ref = i->i; lfe->val = aiq->val; lfe->next = info->ptr; info->ptr = lfe; } /* find coefficient a[i,r] in row i */ for (air = i->ptr; air != NULL; air = air->r_next) if (air->col == r) break; /* if a[i,r] does not exist, create a[i,r] = 0 */ if (air == NULL) air = npp_add_aij(npp, i, r, 0.0); /* compute gamma[i] = a[i,q] / a[p,q] */ gamma = aiq->val / apq->val; /* (row i) := (row i) - gamma[i] * (row p); see (3)-(6) */ /* new a[i,q] is exact zero due to elimnation; remove it from row i */ npp_del_aij(npp, aiq); /* compute new a[i,r] */ air->val -= gamma * apr->val; /* if new a[i,r] is close to zero due to numeric cancelation, remove it from row i */ if (fabs(air->val) <= 1e-10) npp_del_aij(npp, air); /* compute new lower and upper bounds of row i */ if (i->lb == i->ub) i->lb = i->ub = (i->lb - gamma * p->lb); else { if (i->lb != -DBL_MAX) i->lb -= gamma * p->lb; if (i->ub != +DBL_MAX) i->ub -= gamma * p->lb; } } return q; } static int rcv_eq_doublet(NPP *npp, void *_info) { /* recover row doubleton (equality constraint) */ struct eq_doublet *info = _info; NPPLFE *lfe; double gamma, temp; /* we assume that processing row p is followed by processing column q as singleton of type "implied slack variable", in which case row p must always be active equality constraint */ if (npp->sol == GLP_SOL) { if (npp->r_stat[info->p] != GLP_NS) { npp_error(); return 1; } } if (npp->sol != GLP_MIP) { /* compute value of multiplier for row p; see (14) */ temp = npp->r_pi[info->p]; for (lfe = info->ptr; lfe != NULL; lfe = lfe->next) { gamma = lfe->val / info->apq; /* a[i,q] / a[p,q] */ temp -= gamma * npp->r_pi[lfe->ref]; } npp->r_pi[info->p] = temp; } return 0; } /*********************************************************************** * NAME * * npp_forcing_row - process forcing row * * SYNOPSIS * * #include "glpnpp.h" * int npp_forcing_row(NPP *npp, NPPROW *p, int at); * * DESCRIPTION * * The routine npp_forcing row processes row p of general format: * * L[p] <= sum a[p,j] x[j] <= U[p], (1) * j * * l[j] <= x[j] <= u[j], (2) * * where L[p] <= U[p] and l[j] < u[j] for all a[p,j] != 0. It is also * assumed that: * * 1) if at = 0 then |L[p] - U'[p]| <= eps, where U'[p] is implied * row upper bound (see below), eps is an absolute tolerance for row * value; * * 2) if at = 1 then |U[p] - L'[p]| <= eps, where L'[p] is implied * row lower bound (see below). * * RETURNS * * 0 - success; * * 1 - cannot fix columns due to too small constraint coefficients. * * PROBLEM TRANSFORMATION * * Implied lower and upper bounds of row (1) are determined by bounds * of corresponding columns (variables) as follows: * * L'[p] = inf sum a[p,j] x[j] = * j * (3) * = sum a[p,j] l[j] + sum a[p,j] u[j], * j in Jp j in Jn * * U'[p] = sup sum a[p,j] x[j] = * (4) * = sum a[p,j] u[j] + sum a[p,j] l[j], * j in Jp j in Jn * * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) * * If L[p] =~ U'[p] (at = 0), solution can be primal feasible only when * all variables take their boundary values as defined by (4): * * ( u[j], if j in Jp * x[j] = < (6) * ( l[j], if j in Jn * * Similarly, if U[p] =~ L'[p] (at = 1), solution can be primal feasible * only when all variables take their boundary values as defined by (3): * * ( l[j], if j in Jp * x[j] = < (7) * ( u[j], if j in Jn * * Condition (6) or (7) allows fixing all columns (variables x[j]) * in row (1) on their bounds and then removing them from the problem * (see the routine npp_fixed_col). Due to this row p becomes redundant, * so it can be replaced by equivalent free (unbounded) row and also * removed from the problem (see the routine npp_free_row). * * 1. To apply this transformation row (1) should not have coefficients * whose magnitude is too small, i.e. all a[p,j] should satisfy to * the following condition: * * |a[p,j]| >= eps * max(1, |a[p,k]|), (8) * k * where eps is a relative tolerance for constraint coefficients. * Otherwise, fixing columns may be numerically unreliable and may * lead to wrong solution. * * 2. The routine fixes columns and remove bounds of row p, however, * it does not remove the row and columns from the problem. * * RECOVERING BASIC SOLUTION * * In the transformed problem row p being inactive constraint is * assigned status GLP_BS (as the result of transformation of free * row), and all columns in this row are assigned status GLP_NS (as the * result of transformation of fixed columns). * * Note that in the dual system of the transformed (as well as original) * problem every column j in row p corresponds to the following row: * * sum a[i,j] pi[i] + a[p,j] pi[p] + lambda[j] = c[j], (9) * i!=p * * from which it follows that: * * lambda[j] = c[j] - sum a[i,j] pi[i] - a[p,j] pi[p]. (10) * i!=p * * In the transformed problem values of all multipliers pi[i] are known * (including pi[i], whose value is zero, since row p is inactive). * Thus, using formula (10) it is possible to compute values of * multipliers lambda[j] for all columns in row p. * * Note also that in the original problem all columns in row p are * bounded, not fixed. So status GLP_NS assigned to every such column * must be changed to GLP_NL or GLP_NU depending on which bound the * corresponding column has been fixed. This status change may lead to * dual feasibility violation for solution of the original problem, * because now column multipliers must satisfy to the following * condition: * * ( >= 0, if status of column j is GLP_NL, * lambda[j] < (11) * ( <= 0, if status of column j is GLP_NU. * * If this condition holds, solution to the original problem is the * same as to the transformed problem. Otherwise, we have to perform * one degenerate pivoting step of the primal simplex method to obtain * dual feasible (hence, optimal) solution to the original problem as * follows. If, on problem transformation, row p was made active on its * lower bound (case at = 0), we change its status to GLP_NL (or GLP_NS) * and start increasing its multiplier pi[p]. Otherwise, if row p was * made active on its upper bound (case at = 1), we change its status * to GLP_NU (or GLP_NS) and start decreasing pi[p]. From (10) it * follows that: * * delta lambda[j] = - a[p,j] * delta pi[p] = - a[p,j] pi[p]. (12) * * Simple analysis of formulae (3)-(5) shows that changing pi[p] in the * specified direction causes increasing lambda[j] for every column j * assigned status GLP_NL (delta lambda[j] > 0) and decreasing lambda[j] * for every column j assigned status GLP_NU (delta lambda[j] < 0). It * is understood that once the last lambda[q], which violates condition * (11), has reached zero, multipliers lambda[j] for all columns get * valid signs. Such column q can be determined as follows. Let d[j] be * initial value of lambda[j] (i.e. reduced cost of column j) in the * transformed problem computed with formula (10) when pi[p] = 0. Then * lambda[j] = d[j] + delta lambda[j], and from (12) it follows that * lambda[j] becomes zero if: * * delta lambda[j] = - a[p,j] pi[p] = - d[j] ==> * (13) * pi[p] = d[j] / a[p,j]. * * Therefore, the last column q, for which lambda[q] becomes zero, can * be determined from the following condition: * * |d[q] / a[p,q]| = max |pi[p]| = max |d[j] / a[p,j]|, (14) * j in D j in D * * where D is a set of columns j whose, reduced costs d[j] have invalid * signs, i.e. violate condition (11). (Thus, if D is empty, solution * to the original problem is the same as solution to the transformed * problem, and no correction is needed as was noticed above.) In * solution to the original problem column q is assigned status GLP_BS, * since it replaces column of auxiliary variable of row p (becoming * active) in the basis, and multiplier for row p is assigned its new * value, which is pi[p] = d[q] / a[p,q]. Note that due to primal * degeneracy values of all columns having non-zero coefficients in row * p remain unchanged. * * RECOVERING INTERIOR-POINT SOLUTION * * Value of multiplier pi[p] in solution to the original problem is * corrected in the same way as for basic solution. Values of all * columns having non-zero coefficients in row p remain unchanged. * * RECOVERING MIP SOLUTION * * None needed. */ struct forcing_col { /* column fixed on its bound by forcing row */ int j; /* column reference number */ char stat; /* original column status: GLP_NL - fixed on lower bound GLP_NU - fixed on upper bound */ double a; /* constraint coefficient a[p,j] */ double c; /* objective coefficient c[j] */ NPPLFE *ptr; /* list of non-zero coefficients a[i,j], i != p */ struct forcing_col *next; /* pointer to another column fixed by forcing row */ }; struct forcing_row { /* forcing row */ int p; /* row reference number */ char stat; /* status assigned to the row if it becomes active: GLP_NS - active equality constraint GLP_NL - inequality constraint with lower bound active GLP_NU - inequality constraint with upper bound active */ struct forcing_col *ptr; /* list of all columns having non-zero constraint coefficient a[p,j] in the forcing row */ }; static int rcv_forcing_row(NPP *npp, void *info); int npp_forcing_row(NPP *npp, NPPROW *p, int at) { /* process forcing row */ struct forcing_row *info; struct forcing_col *col = NULL; NPPCOL *j; NPPAIJ *apj, *aij; NPPLFE *lfe; double big; xassert(at == 0 || at == 1); /* determine maximal magnitude of the row coefficients */ big = 1.0; for (apj = p->ptr; apj != NULL; apj = apj->r_next) if (big < fabs(apj->val)) big = fabs(apj->val); /* if there are too small coefficients in the row, transformation should not be applied */ for (apj = p->ptr; apj != NULL; apj = apj->r_next) if (fabs(apj->val) < 1e-7 * big) return 1; /* create transformation stack entry */ info = npp_push_tse(npp, rcv_forcing_row, sizeof(struct forcing_row)); info->p = p->i; if (p->lb == p->ub) { /* equality constraint */ info->stat = GLP_NS; } else if (at == 0) { /* inequality constraint; case L[p] = U'[p] */ info->stat = GLP_NL; xassert(p->lb != -DBL_MAX); } else /* at == 1 */ { /* inequality constraint; case U[p] = L'[p] */ info->stat = GLP_NU; xassert(p->ub != +DBL_MAX); } info->ptr = NULL; /* scan the forcing row, fix columns at corresponding bounds, and save column information (the latter is not needed for MIP) */ for (apj = p->ptr; apj != NULL; apj = apj->r_next) { /* column j has non-zero coefficient in the forcing row */ j = apj->col; /* it must be non-fixed */ xassert(j->lb < j->ub); /* allocate stack entry to save column information */ if (npp->sol != GLP_MIP) { col = dmp_get_atom(npp->stack, sizeof(struct forcing_col)); col->j = j->j; col->stat = -1; /* will be set below */ col->a = apj->val; col->c = j->coef; col->ptr = NULL; col->next = info->ptr; info->ptr = col; } /* fix column j */ if (at == 0 && apj->val < 0.0 || at != 0 && apj->val > 0.0) { /* at its lower bound */ if (npp->sol != GLP_MIP) col->stat = GLP_NL; xassert(j->lb != -DBL_MAX); j->ub = j->lb; } else { /* at its upper bound */ if (npp->sol != GLP_MIP) col->stat = GLP_NU; xassert(j->ub != +DBL_MAX); j->lb = j->ub; } /* save column coefficients a[i,j], i != p */ if (npp->sol != GLP_MIP) { for (aij = j->ptr; aij != NULL; aij = aij->c_next) { if (aij == apj) continue; /* skip a[p,j] */ lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE)); lfe->ref = aij->row->i; lfe->val = aij->val; lfe->next = col->ptr; col->ptr = lfe; } } } /* make the row free (unbounded) */ p->lb = -DBL_MAX, p->ub = +DBL_MAX; return 0; } static int rcv_forcing_row(NPP *npp, void *_info) { /* recover forcing row */ struct forcing_row *info = _info; struct forcing_col *col, *piv; NPPLFE *lfe; double d, big, temp; if (npp->sol == GLP_MIP) goto done; /* initially solution to the original problem is the same as to the transformed problem, where row p is inactive constraint with pi[p] = 0, and all columns are non-basic */ if (npp->sol == GLP_SOL) { if (npp->r_stat[info->p] != GLP_BS) { npp_error(); return 1; } for (col = info->ptr; col != NULL; col = col->next) { if (npp->c_stat[col->j] != GLP_NS) { npp_error(); return 1; } npp->c_stat[col->j] = col->stat; /* original status */ } } /* compute reduced costs d[j] for all columns with formula (10) and store them in col.c instead objective coefficients */ for (col = info->ptr; col != NULL; col = col->next) { d = col->c; for (lfe = col->ptr; lfe != NULL; lfe = lfe->next) d -= lfe->val * npp->r_pi[lfe->ref]; col->c = d; } /* consider columns j, whose multipliers lambda[j] has wrong sign in solution to the transformed problem (where lambda[j] = d[j]), and choose column q, whose multipler lambda[q] reaches zero last on changing row multiplier pi[p]; see (14) */ piv = NULL, big = 0.0; for (col = info->ptr; col != NULL; col = col->next) { d = col->c; /* d[j] */ temp = fabs(d / col->a); if (col->stat == GLP_NL) { /* column j has active lower bound */ if (d < 0.0 && big < temp) piv = col, big = temp; } else if (col->stat == GLP_NU) { /* column j has active upper bound */ if (d > 0.0 && big < temp) piv = col, big = temp; } else { npp_error(); return 1; } } /* if column q does not exist, no correction is needed */ if (piv != NULL) { /* correct solution; row p becomes active constraint while column q becomes basic */ if (npp->sol == GLP_SOL) { npp->r_stat[info->p] = info->stat; npp->c_stat[piv->j] = GLP_BS; } /* assign new value to row multiplier pi[p] = d[p] / a[p,q] */ npp->r_pi[info->p] = piv->c / piv->a; } done: return 0; } /*********************************************************************** * NAME * * npp_analyze_row - perform general row analysis * * SYNOPSIS * * #include "glpnpp.h" * int npp_analyze_row(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_analyze_row performs analysis of row p of general * format: * * L[p] <= sum a[p,j] x[j] <= U[p], (1) * j * * l[j] <= x[j] <= u[j], (2) * * where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0. * * RETURNS * * 0x?0 - row lower bound does not exist or is redundant; * * 0x?1 - row lower bound can be active; * * 0x?2 - row lower bound is a forcing bound; * * 0x0? - row upper bound does not exist or is redundant; * * 0x1? - row upper bound can be active; * * 0x2? - row upper bound is a forcing bound; * * 0x33 - row bounds are inconsistent with column bounds. * * ALGORITHM * * Analysis of row (1) is based on analysis of its implied lower and * upper bounds, which are determined by bounds of corresponding columns * (variables) as follows: * * L'[p] = inf sum a[p,j] x[j] = * j * (3) * = sum a[p,j] l[j] + sum a[p,j] u[j], * j in Jp j in Jn * * U'[p] = sup sum a[p,j] x[j] = * (4) * = sum a[p,j] u[j] + sum a[p,j] l[j], * j in Jp j in Jn * * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) * * (Note that bounds of all columns in row p are assumed to be correct, * so L'[p] <= U'[p].) * * Analysis of row lower bound L[p] includes the following cases: * * 1) if L[p] > U'[p] + eps, where eps is an absolute tolerance for row * value, row lower bound L[p] and implied row upper bound U'[p] are * inconsistent, ergo, the problem has no primal feasible solution; * * 2) if U'[p] - eps <= L[p] <= U'[p] + eps, i.e. if L[p] =~ U'[p], * the row is a forcing row on its lower bound (see description of * the routine npp_forcing_row); * * 3) if L[p] > L'[p] + eps, row lower bound L[p] can be active (this * conclusion does not account other rows in the problem); * * 4) if L[p] <= L'[p] + eps, row lower bound L[p] cannot be active, so * it is redundant and can be removed (replaced by -oo). * * Analysis of row upper bound U[p] is performed in a similar way and * includes the following cases: * * 1) if U[p] < L'[p] - eps, row upper bound U[p] and implied row lower * bound L'[p] are inconsistent, ergo the problem has no primal * feasible solution; * * 2) if L'[p] - eps <= U[p] <= L'[p] + eps, i.e. if U[p] =~ L'[p], * the row is a forcing row on its upper bound (see description of * the routine npp_forcing_row); * * 3) if U[p] < U'[p] - eps, row upper bound U[p] can be active (this * conclusion does not account other rows in the problem); * * 4) if U[p] >= U'[p] - eps, row upper bound U[p] cannot be active, so * it is redundant and can be removed (replaced by +oo). */ int npp_analyze_row(NPP *npp, NPPROW *p) { /* perform general row analysis */ NPPAIJ *aij; int ret = 0x00; double l, u, eps; xassert(npp == npp); /* compute implied lower bound L'[p]; see (3) */ l = 0.0; for (aij = p->ptr; aij != NULL; aij = aij->r_next) { if (aij->val > 0.0) { if (aij->col->lb == -DBL_MAX) { l = -DBL_MAX; break; } l += aij->val * aij->col->lb; } else /* aij->val < 0.0 */ { if (aij->col->ub == +DBL_MAX) { l = -DBL_MAX; break; } l += aij->val * aij->col->ub; } } /* compute implied upper bound U'[p]; see (4) */ u = 0.0; for (aij = p->ptr; aij != NULL; aij = aij->r_next) { if (aij->val > 0.0) { if (aij->col->ub == +DBL_MAX) { u = +DBL_MAX; break; } u += aij->val * aij->col->ub; } else /* aij->val < 0.0 */ { if (aij->col->lb == -DBL_MAX) { u = +DBL_MAX; break; } u += aij->val * aij->col->lb; } } /* column bounds are assumed correct, so L'[p] <= U'[p] */ /* check if row lower bound is consistent */ if (p->lb != -DBL_MAX) { eps = 1e-3 + 1e-6 * fabs(p->lb); if (p->lb - eps > u) { ret = 0x33; goto done; } } /* check if row upper bound is consistent */ if (p->ub != +DBL_MAX) { eps = 1e-3 + 1e-6 * fabs(p->ub); if (p->ub + eps < l) { ret = 0x33; goto done; } } /* check if row lower bound can be active/forcing */ if (p->lb != -DBL_MAX) { eps = 1e-9 + 1e-12 * fabs(p->lb); if (p->lb - eps > l) { if (p->lb + eps <= u) ret |= 0x01; else ret |= 0x02; } } /* check if row upper bound can be active/forcing */ if (p->ub != +DBL_MAX) { eps = 1e-9 + 1e-12 * fabs(p->ub); if (p->ub + eps < u) { /* check if the upper bound is forcing */ if (p->ub - eps >= l) ret |= 0x10; else ret |= 0x20; } } done: return ret; } /*********************************************************************** * NAME * * npp_inactive_bound - remove row lower/upper inactive bound * * SYNOPSIS * * #include "glpnpp.h" * void npp_inactive_bound(NPP *npp, NPPROW *p, int which); * * DESCRIPTION * * The routine npp_inactive_bound removes lower (if which = 0) or upper * (if which = 1) bound of row p: * * L[p] <= sum a[p,j] x[j] <= U[p], * * which (bound) is assumed to be redundant. * * PROBLEM TRANSFORMATION * * If which = 0, current lower bound L[p] of row p is assigned -oo. * If which = 1, current upper bound U[p] of row p is assigned +oo. * * RECOVERING BASIC SOLUTION * * If in solution to the transformed problem row p is inactive * constraint (GLP_BS), its status is not changed in solution to the * original problem. Otherwise, status of row p in solution to the * original problem is defined by its type before transformation and * its status in solution to the transformed problem as follows: * * +---------------------+-------+---------------+---------------+ * | Row | Flag | Row status in | Row status in | * | type | which | transfmd soln | original soln | * +---------------------+-------+---------------+---------------+ * | sum >= L[p] | 0 | GLP_NF | GLP_NL | * | sum <= U[p] | 1 | GLP_NF | GLP_NU | * | L[p] <= sum <= U[p] | 0 | GLP_NU | GLP_NU | * | L[p] <= sum <= U[p] | 1 | GLP_NL | GLP_NL | * | sum = L[p] = U[p] | 0 | GLP_NU | GLP_NS | * | sum = L[p] = U[p] | 1 | GLP_NL | GLP_NS | * +---------------------+-------+---------------+---------------+ * * RECOVERING INTERIOR-POINT SOLUTION * * None needed. * * RECOVERING MIP SOLUTION * * None needed. */ struct inactive_bound { /* row inactive bound */ int p; /* row reference number */ char stat; /* row status (if active constraint) */ }; static int rcv_inactive_bound(NPP *npp, void *info); void npp_inactive_bound(NPP *npp, NPPROW *p, int which) { /* remove row lower/upper inactive bound */ struct inactive_bound *info; if (npp->sol == GLP_SOL) { /* create transformation stack entry */ info = npp_push_tse(npp, rcv_inactive_bound, sizeof(struct inactive_bound)); info->p = p->i; if (p->ub == +DBL_MAX) info->stat = GLP_NL; else if (p->lb == -DBL_MAX) info->stat = GLP_NU; else if (p->lb != p->ub) info->stat = (char)(which == 0 ? GLP_NU : GLP_NL); else info->stat = GLP_NS; } /* remove row inactive bound */ if (which == 0) { xassert(p->lb != -DBL_MAX); p->lb = -DBL_MAX; } else if (which == 1) { xassert(p->ub != +DBL_MAX); p->ub = +DBL_MAX; } else xassert(which != which); return; } static int rcv_inactive_bound(NPP *npp, void *_info) { /* recover row status */ struct inactive_bound *info = _info; if (npp->sol != GLP_SOL) { npp_error(); return 1; } if (npp->r_stat[info->p] == GLP_BS) npp->r_stat[info->p] = GLP_BS; else npp->r_stat[info->p] = info->stat; return 0; } /*********************************************************************** * NAME * * npp_implied_bounds - determine implied column bounds * * SYNOPSIS * * #include "glpnpp.h" * void npp_implied_bounds(NPP *npp, NPPROW *p); * * DESCRIPTION * * The routine npp_implied_bounds inspects general row (constraint) p: * * L[p] <= sum a[p,j] x[j] <= U[p], (1) * * l[j] <= x[j] <= u[j], (2) * * where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0, to compute * implied bounds of columns (variables x[j]) in this row. * * The routine stores implied column bounds l'[j] and u'[j] in column * descriptors (NPPCOL); it does not change current column bounds l[j] * and u[j]. (Implied column bounds can be then used to strengthen the * current column bounds; see the routines npp_implied_lower and * npp_implied_upper). * * ALGORITHM * * Current column bounds (2) define implied lower and upper bounds of * row (1) as follows: * * L'[p] = inf sum a[p,j] x[j] = * j * (3) * = sum a[p,j] l[j] + sum a[p,j] u[j], * j in Jp j in Jn * * U'[p] = sup sum a[p,j] x[j] = * (4) * = sum a[p,j] u[j] + sum a[p,j] l[j], * j in Jp j in Jn * * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5) * * (Note that bounds of all columns in row p are assumed to be correct, * so L'[p] <= U'[p].) * * If L[p] > L'[p] and/or U[p] < U'[p], the lower and/or upper bound of * row (1) can be active, in which case such row defines implied bounds * of its variables. * * Let x[k] be some variable having in row (1) coefficient a[p,k] != 0. * Consider a case when row lower bound can be active (L[p] > L'[p]): * * sum a[p,j] x[j] >= L[p] ==> * j * * sum a[p,j] x[j] + a[p,k] x[k] >= L[p] ==> * j!=k * (6) * a[p,k] x[k] >= L[p] - sum a[p,j] x[j] ==> * j!=k * * a[p,k] x[k] >= L[p,k], * * where * * L[p,k] = inf(L[p] - sum a[p,j] x[j]) = * j!=k * * = L[p] - sup sum a[p,j] x[j] = (7) * j!=k * * = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j]. * j in Jp\{k} j in Jn\{k} * * Thus: * * x[k] >= l'[k] = L[p,k] / a[p,k], if a[p,k] > 0, (8) * * x[k] <= u'[k] = L[p,k] / a[p,k], if a[p,k] < 0. (9) * * where l'[k] and u'[k] are implied lower and upper bounds of variable * x[k], resp. * * Now consider a similar case when row upper bound can be active * (U[p] < U'[p]): * * sum a[p,j] x[j] <= U[p] ==> * j * * sum a[p,j] x[j] + a[p,k] x[k] <= U[p] ==> * j!=k * (10) * a[p,k] x[k] <= U[p] - sum a[p,j] x[j] ==> * j!=k * * a[p,k] x[k] <= U[p,k], * * where: * * U[p,k] = sup(U[p] - sum a[p,j] x[j]) = * j!=k * * = U[p] - inf sum a[p,j] x[j] = (11) * j!=k * * = U[p] - sum a[p,j] l[j] - sum a[p,j] u[j]. * j in Jp\{k} j in Jn\{k} * * Thus: * * x[k] <= u'[k] = U[p,k] / a[p,k], if a[p,k] > 0, (12) * * x[k] >= l'[k] = U[p,k] / a[p,k], if a[p,k] < 0. (13) * * Note that in formulae (8), (9), (12), and (13) coefficient a[p,k] * must not be too small in magnitude relatively to other non-zero * coefficients in row (1), i.e. the following condition must hold: * * |a[p,k]| >= eps * max(1, |a[p,j]|), (14) * j * * where eps is a relative tolerance for constraint coefficients. * Otherwise the implied column bounds can be numerical inreliable. For * example, using formula (8) for the following inequality constraint: * * 1e-12 x1 - x2 - x3 >= 0, * * where x1 >= -1, x2, x3, >= 0, may lead to numerically unreliable * conclusion that x1 >= 0. * * Using formulae (8), (9), (12), and (13) to compute implied bounds * for one variable requires |J| operations, where J = {j: a[p,j] != 0}, * because this needs computing L[p,k] and U[p,k]. Thus, computing * implied bounds for all variables in row (1) would require |J|^2 * operations, that is not a good technique. However, the total number * of operations can be reduced to |J| as follows. * * Let a[p,k] > 0. Then from (7) and (11) we have: * * L[p,k] = L[p] - (U'[p] - a[p,k] u[k]) = * * = L[p] - U'[p] + a[p,k] u[k], * * U[p,k] = U[p] - (L'[p] - a[p,k] l[k]) = * * = U[p] - L'[p] + a[p,k] l[k], * * where L'[p] and U'[p] are implied row lower and upper bounds defined * by formulae (3) and (4). Substituting these expressions into (8) and * (12) gives: * * l'[k] = L[p,k] / a[p,k] = u[k] + (L[p] - U'[p]) / a[p,k], (15) * * u'[k] = U[p,k] / a[p,k] = l[k] + (U[p] - L'[p]) / a[p,k]. (16) * * Similarly, if a[p,k] < 0, according to (7) and (11) we have: * * L[p,k] = L[p] - (U'[p] - a[p,k] l[k]) = * * = L[p] - U'[p] + a[p,k] l[k], * * U[p,k] = U[p] - (L'[p] - a[p,k] u[k]) = * * = U[p] - L'[p] + a[p,k] u[k], * * and substituting these expressions into (8) and (12) gives: * * l'[k] = U[p,k] / a[p,k] = u[k] + (U[p] - L'[p]) / a[p,k], (17) * * u'[k] = L[p,k] / a[p,k] = l[k] + (L[p] - U'[p]) / a[p,k]. (18) * * Note that formulae (15)-(18) can be used only if L'[p] and U'[p] * exist. However, if for some variable x[j] it happens that l[j] = -oo * and/or u[j] = +oo, values of L'[p] (if a[p,j] > 0) and/or U'[p] (if * a[p,j] < 0) are undefined. Consider, therefore, the most general * situation, when some column bounds (2) may not exist. * * Let: * * J' = {j : (a[p,j] > 0 and l[j] = -oo) or * (19) * (a[p,j] < 0 and u[j] = +oo)}. * * Then (assuming that row upper bound U[p] can be active) the following * three cases are possible: * * 1) |J'| = 0. In this case L'[p] exists, thus, for all variables x[j] * in row (1) we can use formulae (16) and (17); * * 2) J' = {k}. In this case L'[p] = -oo, however, U[p,k] (11) exists, * so for variable x[k] we can use formulae (12) and (13). Note that * for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] < 0) * or u'[j] = +oo (if a[p,j] > 0); * * 3) |J'| > 1. In this case for all variables x[j] in row [1] we have * l'[j] = -oo (if a[p,j] < 0) or u'[j] = +oo (if a[p,j] > 0). * * Similarly, let: * * J'' = {j : (a[p,j] > 0 and u[j] = +oo) or * (20) * (a[p,j] < 0 and l[j] = -oo)}. * * Then (assuming that row lower bound L[p] can be active) the following * three cases are possible: * * 1) |J''| = 0. In this case U'[p] exists, thus, for all variables x[j] * in row (1) we can use formulae (15) and (18); * * 2) J'' = {k}. In this case U'[p] = +oo, however, L[p,k] (7) exists, * so for variable x[k] we can use formulae (8) and (9). Note that * for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] > 0) * or u'[j] = +oo (if a[p,j] < 0); * * 3) |J''| > 1. In this case for all variables x[j] in row (1) we have * l'[j] = -oo (if a[p,j] > 0) or u'[j] = +oo (if a[p,j] < 0). */ void npp_implied_bounds(NPP *npp, NPPROW *p) { NPPAIJ *apj, *apk; double big, eps, temp; xassert(npp == npp); /* initialize implied bounds for all variables and determine maximal magnitude of row coefficients a[p,j] */ big = 1.0; for (apj = p->ptr; apj != NULL; apj = apj->r_next) { apj->col->ll.ll = -DBL_MAX, apj->col->uu.uu = +DBL_MAX; if (big < fabs(apj->val)) big = fabs(apj->val); } eps = 1e-6 * big; /* process row lower bound (assuming that it can be active) */ if (p->lb != -DBL_MAX) { apk = NULL; for (apj = p->ptr; apj != NULL; apj = apj->r_next) { if (apj->val > 0.0 && apj->col->ub == +DBL_MAX || apj->val < 0.0 && apj->col->lb == -DBL_MAX) { if (apk == NULL) apk = apj; else goto skip1; } } /* if a[p,k] = NULL then |J'| = 0 else J' = { k } */ temp = p->lb; for (apj = p->ptr; apj != NULL; apj = apj->r_next) { if (apj == apk) /* skip a[p,k] */; else if (apj->val > 0.0) temp -= apj->val * apj->col->ub; else /* apj->val < 0.0 */ temp -= apj->val * apj->col->lb; } /* compute column implied bounds */ if (apk == NULL) { /* temp = L[p] - U'[p] */ for (apj = p->ptr; apj != NULL; apj = apj->r_next) { if (apj->val >= +eps) { /* l'[j] := u[j] + (L[p] - U'[p]) / a[p,j] */ apj->col->ll.ll = apj->col->ub + temp / apj->val; } else if (apj->val <= -eps) { /* u'[j] := l[j] + (L[p] - U'[p]) / a[p,j] */ apj->col->uu.uu = apj->col->lb + temp / apj->val; } } } else { /* temp = L[p,k] */ if (apk->val >= +eps) { /* l'[k] := L[p,k] / a[p,k] */ apk->col->ll.ll = temp / apk->val; } else if (apk->val <= -eps) { /* u'[k] := L[p,k] / a[p,k] */ apk->col->uu.uu = temp / apk->val; } } skip1: ; } /* process row upper bound (assuming that it can be active) */ if (p->ub != +DBL_MAX) { apk = NULL; for (apj = p->ptr; apj != NULL; apj = apj->r_next) { if (apj->val > 0.0 && apj->col->lb == -DBL_MAX || apj->val < 0.0 && apj->col->ub == +DBL_MAX) { if (apk == NULL) apk = apj; else goto skip2; } } /* if a[p,k] = NULL then |J''| = 0 else J'' = { k } */ temp = p->ub; for (apj = p->ptr; apj != NULL; apj = apj->r_next) { if (apj == apk) /* skip a[p,k] */; else if (apj->val > 0.0) temp -= apj->val * apj->col->lb; else /* apj->val < 0.0 */ temp -= apj->val * apj->col->ub; } /* compute column implied bounds */ if (apk == NULL) { /* temp = U[p] - L'[p] */ for (apj = p->ptr; apj != NULL; apj = apj->r_next) { if (apj->val >= +eps) { /* u'[j] := l[j] + (U[p] - L'[p]) / a[p,j] */ apj->col->uu.uu = apj->col->lb + temp / apj->val; } else if (apj->val <= -eps) { /* l'[j] := u[j] + (U[p] - L'[p]) / a[p,j] */ apj->col->ll.ll = apj->col->ub + temp / apj->val; } } } else { /* temp = U[p,k] */ if (apk->val >= +eps) { /* u'[k] := U[p,k] / a[p,k] */ apk->col->uu.uu = temp / apk->val; } else if (apk->val <= -eps) { /* l'[k] := U[p,k] / a[p,k] */ apk->col->ll.ll = temp / apk->val; } } skip2: ; } return; } /* eof */ glpk-4.52.1/src/glpnpp04.c0000644000062000006210000014254512175147600014333 0ustar maomkpasswd/* glpnpp04.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpnpp.h" /*********************************************************************** * NAME * * npp_binarize_prob - binarize MIP problem * * SYNOPSIS * * #include "glpnpp.h" * int npp_binarize_prob(NPP *npp); * * DESCRIPTION * * The routine npp_binarize_prob replaces in the original MIP problem * every integer variable: * * l[q] <= x[q] <= u[q], (1) * * where l[q] < u[q], by an equivalent sum of binary variables. * * RETURNS * * The routine returns the number of integer variables for which the * transformation failed, because u[q] - l[q] > d_max. * * PROBLEM TRANSFORMATION * * If variable x[q] has non-zero lower bound, it is first processed * with the routine npp_lbnd_col. Thus, we can assume that: * * 0 <= x[q] <= u[q]. (2) * * If u[q] = 1, variable x[q] is already binary, so further processing * is not needed. Let, therefore, that 2 <= u[q] <= d_max, and n be a * smallest integer such that u[q] <= 2^n - 1 (n >= 2, since u[q] >= 2). * Then variable x[q] can be replaced by the following sum: * * n-1 * x[q] = sum 2^k x[k], (3) * k=0 * * where x[k] are binary columns (variables). If u[q] < 2^n - 1, the * following additional inequality constraint must be also included in * the transformed problem: * * n-1 * sum 2^k x[k] <= u[q]. (4) * k=0 * * Note: Assuming that in the transformed problem x[q] becomes binary * variable x[0], this transformation causes new n-1 binary variables * to appear. * * Substituting x[q] from (3) to the objective row gives: * * z = sum c[j] x[j] + c[0] = * j * * = sum c[j] x[j] + c[q] x[q] + c[0] = * j!=q * n-1 * = sum c[j] x[j] + c[q] sum 2^k x[k] + c[0] = * j!=q k=0 * n-1 * = sum c[j] x[j] + sum c[k] x[k] + c[0], * j!=q k=0 * * where: * * c[k] = 2^k c[q], k = 0, ..., n-1. (5) * * And substituting x[q] from (3) to i-th constraint row i gives: * * L[i] <= sum a[i,j] x[j] <= U[i] ==> * j * * L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> * j!=q * n-1 * L[i] <= sum a[i,j] x[j] + a[i,q] sum 2^k x[k] <= U[i] ==> * j!=q k=0 * n-1 * L[i] <= sum a[i,j] x[j] + sum a[i,k] x[k] <= U[i], * j!=q k=0 * * where: * * a[i,k] = 2^k a[i,q], k = 0, ..., n-1. (6) * * RECOVERING SOLUTION * * Value of variable x[q] is computed with formula (3). */ struct binarize { int q; /* column reference number for x[q] = x[0] */ int j; /* column reference number for x[1]; x[2] has reference number j+1, x[3] - j+2, etc. */ int n; /* total number of binary variables, n >= 2 */ }; static int rcv_binarize_prob(NPP *npp, void *info); int npp_binarize_prob(NPP *npp) { /* binarize MIP problem */ struct binarize *info; NPPROW *row; NPPCOL *col, *bin; NPPAIJ *aij; int u, n, k, temp, nfails, nvars, nbins, nrows; /* new variables will be added to the end of the column list, so we go from the end to beginning of the column list */ nfails = nvars = nbins = nrows = 0; for (col = npp->c_tail; col != NULL; col = col->prev) { /* skip continuous variable */ if (!col->is_int) continue; /* skip fixed variable */ if (col->lb == col->ub) continue; /* skip binary variable */ if (col->lb == 0.0 && col->ub == 1.0) continue; /* check if the transformation is applicable */ if (col->lb < -1e6 || col->ub > +1e6 || col->ub - col->lb > 4095.0) { /* unfortunately, not */ nfails++; continue; } /* process integer non-binary variable x[q] */ nvars++; /* make x[q] non-negative, if its lower bound is non-zero */ if (col->lb != 0.0) npp_lbnd_col(npp, col); /* now 0 <= x[q] <= u[q] */ xassert(col->lb == 0.0); u = (int)col->ub; xassert(col->ub == (double)u); /* if x[q] is binary, further processing is not needed */ if (u == 1) continue; /* determine smallest n such that u <= 2^n - 1 (thus, n is the number of binary variables needed) */ n = 2, temp = 4; while (u >= temp) n++, temp += temp; nbins += n; /* create transformation stack entry */ info = npp_push_tse(npp, rcv_binarize_prob, sizeof(struct binarize)); info->q = col->j; info->j = 0; /* will be set below */ info->n = n; /* if u < 2^n - 1, we need one additional row for (4) */ if (u < temp - 1) { row = npp_add_row(npp), nrows++; row->lb = -DBL_MAX, row->ub = u; } else row = NULL; /* in the transformed problem variable x[q] becomes binary variable x[0], so its objective and constraint coefficients are not changed */ col->ub = 1.0; /* include x[0] into constraint (4) */ if (row != NULL) npp_add_aij(npp, row, col, 1.0); /* add other binary variables x[1], ..., x[n-1] */ for (k = 1, temp = 2; k < n; k++, temp += temp) { /* add new binary variable x[k] */ bin = npp_add_col(npp); bin->is_int = 1; bin->lb = 0.0, bin->ub = 1.0; bin->coef = (double)temp * col->coef; /* store column reference number for x[1] */ if (info->j == 0) info->j = bin->j; else xassert(info->j + (k-1) == bin->j); /* duplicate constraint coefficients for x[k]; this also automatically includes x[k] into constraint (4) */ for (aij = col->ptr; aij != NULL; aij = aij->c_next) npp_add_aij(npp, aij->row, bin, (double)temp * aij->val); } } if (nvars > 0) xprintf("%d integer variable(s) were replaced by %d binary one" "s\n", nvars, nbins); if (nrows > 0) xprintf("%d row(s) were added due to binarization\n", nrows); if (nfails > 0) xprintf("Binarization failed for %d integer variable(s)\n", nfails); return nfails; } static int rcv_binarize_prob(NPP *npp, void *_info) { /* recovery binarized variable */ struct binarize *info = _info; int k, temp; double sum; /* compute value of x[q]; see formula (3) */ sum = npp->c_value[info->q]; for (k = 1, temp = 2; k < info->n; k++, temp += temp) sum += (double)temp * npp->c_value[info->j + (k-1)]; npp->c_value[info->q] = sum; return 0; } /**********************************************************************/ struct elem { /* linear form element a[j] x[j] */ double aj; /* non-zero coefficient value */ NPPCOL *xj; /* pointer to variable (column) */ struct elem *next; /* pointer to another term */ }; static struct elem *copy_form(NPP *npp, NPPROW *row, double s) { /* copy linear form */ NPPAIJ *aij; struct elem *ptr, *e; ptr = NULL; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { e = dmp_get_atom(npp->pool, sizeof(struct elem)); e->aj = s * aij->val; e->xj = aij->col; e->next = ptr; ptr = e; } return ptr; } static void drop_form(NPP *npp, struct elem *ptr) { /* drop linear form */ struct elem *e; while (ptr != NULL) { e = ptr; ptr = e->next; dmp_free_atom(npp->pool, e, sizeof(struct elem)); } return; } /*********************************************************************** * NAME * * npp_is_packing - test if constraint is packing inequality * * SYNOPSIS * * #include "glpnpp.h" * int npp_is_packing(NPP *npp, NPPROW *row); * * RETURNS * * If the specified row (constraint) is packing inequality (see below), * the routine npp_is_packing returns non-zero. Otherwise, it returns * zero. * * PACKING INEQUALITIES * * In canonical format the packing inequality is the following: * * sum x[j] <= 1, (1) * j in J * * where all variables x[j] are binary. This inequality expresses the * condition that in any integer feasible solution at most one variable * from set J can take non-zero (unity) value while other variables * must be equal to zero. W.l.o.g. it is assumed that |J| >= 2, because * if J is empty or |J| = 1, the inequality (1) is redundant. * * In general case the packing inequality may include original variables * x[j] as well as their complements x~[j]: * * sum x[j] + sum x~[j] <= 1, (2) * j in Jp j in Jn * * where Jp and Jn are not intersected. Therefore, using substitution * x~[j] = 1 - x[j] gives the packing inequality in generalized format: * * sum x[j] - sum x[j] <= 1 - |Jn|. (3) * j in Jp j in Jn */ int npp_is_packing(NPP *npp, NPPROW *row) { /* test if constraint is packing inequality */ NPPCOL *col; NPPAIJ *aij; int b; xassert(npp == npp); if (!(row->lb == -DBL_MAX && row->ub != +DBL_MAX)) return 0; b = 1; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { col = aij->col; if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) return 0; if (aij->val == +1.0) ; else if (aij->val == -1.0) b--; else return 0; } if (row->ub != (double)b) return 0; return 1; } /*********************************************************************** * NAME * * npp_hidden_packing - identify hidden packing inequality * * SYNOPSIS * * #include "glpnpp.h" * int npp_hidden_packing(NPP *npp, NPPROW *row); * * DESCRIPTION * * The routine npp_hidden_packing processes specified inequality * constraint, which includes only binary variables, and the number of * the variables is not less than two. If the original inequality is * equivalent to a packing inequality, the routine replaces it by this * equivalent inequality. If the original constraint is double-sided * inequality, it is replaced by a pair of single-sided inequalities, * if necessary. * * RETURNS * * If the original inequality constraint was replaced by equivalent * packing inequality, the routine npp_hidden_packing returns non-zero. * Otherwise, it returns zero. * * PROBLEM TRANSFORMATION * * Consider an inequality constraint: * * sum a[j] x[j] <= b, (1) * j in J * * where all variables x[j] are binary, and |J| >= 2. (In case of '>=' * inequality it can be transformed to '<=' format by multiplying both * its sides by -1.) * * Let Jp = {j: a[j] > 0}, Jn = {j: a[j] < 0}. Performing substitution * x[j] = 1 - x~[j] for all j in Jn, we have: * * sum a[j] x[j] <= b ==> * j in J * * sum a[j] x[j] + sum a[j] x[j] <= b ==> * j in Jp j in Jn * * sum a[j] x[j] + sum a[j] (1 - x~[j]) <= b ==> * j in Jp j in Jn * * sum a[j] x[j] - sum a[j] x~[j] <= b - sum a[j]. * j in Jp j in Jn j in Jn * * Thus, meaning the transformation above, we can assume that in * inequality (1) all coefficients a[j] are positive. Moreover, we can * assume that a[j] <= b. In fact, let a[j] > b; then the following * three cases are possible: * * 1) b < 0. In this case inequality (1) is infeasible, so the problem * has no feasible solution (see the routine npp_analyze_row); * * 2) b = 0. In this case inequality (1) is a forcing inequality on its * upper bound (see the routine npp_forcing row), from which it * follows that all variables x[j] should be fixed at zero; * * 3) b > 0. In this case inequality (1) defines an implied zero upper * bound for variable x[j] (see the routine npp_implied_bounds), from * which it follows that x[j] should be fixed at zero. * * It is assumed that all three cases listed above have been recognized * by the routine npp_process_prob, which performs basic MIP processing * prior to a call the routine npp_hidden_packing. So, if one of these * cases occurs, we should just skip processing such constraint. * * Thus, let 0 < a[j] <= b. Then it is obvious that constraint (1) is * equivalent to packing inquality only if: * * a[j] + a[k] > b + eps (2) * * for all j, k in J, j != k, where eps is an absolute tolerance for * row (linear form) value. Checking the condition (2) for all j and k, * j != k, requires time O(|J|^2). However, this time can be reduced to * O(|J|), if use minimal a[j] and a[k], in which case it is sufficient * to check the condition (2) only once. * * Once the original inequality (1) is replaced by equivalent packing * inequality, we need to perform back substitution x~[j] = 1 - x[j] for * all j in Jn (see above). * * RECOVERING SOLUTION * * None needed. */ static int hidden_packing(NPP *npp, struct elem *ptr, double *_b) { /* process inequality constraint: sum a[j] x[j] <= b; 0 - specified row is NOT hidden packing inequality; 1 - specified row is packing inequality; 2 - specified row is hidden packing inequality. */ struct elem *e, *ej, *ek; int neg; double b = *_b, eps; xassert(npp == npp); /* a[j] must be non-zero, x[j] must be binary, for all j in J */ for (e = ptr; e != NULL; e = e->next) { xassert(e->aj != 0.0); xassert(e->xj->is_int); xassert(e->xj->lb == 0.0 && e->xj->ub == 1.0); } /* check if the specified inequality constraint already has the form of packing inequality */ neg = 0; /* neg is |Jn| */ for (e = ptr; e != NULL; e = e->next) { if (e->aj == +1.0) ; else if (e->aj == -1.0) neg++; else break; } if (e == NULL) { /* all coefficients a[j] are +1 or -1; check rhs b */ if (b == (double)(1 - neg)) { /* it is packing inequality; no processing is needed */ return 1; } } /* substitute x[j] = 1 - x~[j] for all j in Jn to make all a[j] positive; the result is a~[j] = |a[j]| and new rhs b */ for (e = ptr; e != NULL; e = e->next) if (e->aj < 0) b -= e->aj; /* now a[j] > 0 for all j in J (actually |a[j]| are used) */ /* if a[j] > b, skip processing--this case must not appear */ for (e = ptr; e != NULL; e = e->next) if (fabs(e->aj) > b) return 0; /* now 0 < a[j] <= b for all j in J */ /* find two minimal coefficients a[j] and a[k], j != k */ ej = NULL; for (e = ptr; e != NULL; e = e->next) if (ej == NULL || fabs(ej->aj) > fabs(e->aj)) ej = e; xassert(ej != NULL); ek = NULL; for (e = ptr; e != NULL; e = e->next) if (e != ej) if (ek == NULL || fabs(ek->aj) > fabs(e->aj)) ek = e; xassert(ek != NULL); /* the specified constraint is equivalent to packing inequality iff a[j] + a[k] > b + eps */ eps = 1e-3 + 1e-6 * fabs(b); if (fabs(ej->aj) + fabs(ek->aj) <= b + eps) return 0; /* perform back substitution x~[j] = 1 - x[j] and construct the final equivalent packing inequality in generalized format */ b = 1.0; for (e = ptr; e != NULL; e = e->next) { if (e->aj > 0.0) e->aj = +1.0; else /* e->aj < 0.0 */ e->aj = -1.0, b -= 1.0; } *_b = b; return 2; } int npp_hidden_packing(NPP *npp, NPPROW *row) { /* identify hidden packing inequality */ NPPROW *copy; NPPAIJ *aij; struct elem *ptr, *e; int kase, ret, count = 0; double b; /* the row must be inequality constraint */ xassert(row->lb < row->ub); for (kase = 0; kase <= 1; kase++) { if (kase == 0) { /* process row upper bound */ if (row->ub == +DBL_MAX) continue; ptr = copy_form(npp, row, +1.0); b = + row->ub; } else { /* process row lower bound */ if (row->lb == -DBL_MAX) continue; ptr = copy_form(npp, row, -1.0); b = - row->lb; } /* now the inequality has the form "sum a[j] x[j] <= b" */ ret = hidden_packing(npp, ptr, &b); xassert(0 <= ret && ret <= 2); if (kase == 1 && ret == 1 || ret == 2) { /* the original inequality has been identified as hidden packing inequality */ count++; #ifdef GLP_DEBUG xprintf("Original constraint:\n"); for (aij = row->ptr; aij != NULL; aij = aij->r_next) xprintf(" %+g x%d", aij->val, aij->col->j); if (row->lb != -DBL_MAX) xprintf(", >= %g", row->lb); if (row->ub != +DBL_MAX) xprintf(", <= %g", row->ub); xprintf("\n"); xprintf("Equivalent packing inequality:\n"); for (e = ptr; e != NULL; e = e->next) xprintf(" %sx%d", e->aj > 0.0 ? "+" : "-", e->xj->j); xprintf(", <= %g\n", b); #endif if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) { /* the original row is single-sided inequality; no copy is needed */ copy = NULL; } else { /* the original row is double-sided inequality; we need to create its copy for other bound before replacing it with the equivalent inequality */ copy = npp_add_row(npp); if (kase == 0) { /* the copy is for lower bound */ copy->lb = row->lb, copy->ub = +DBL_MAX; } else { /* the copy is for upper bound */ copy->lb = -DBL_MAX, copy->ub = row->ub; } /* copy original row coefficients */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) npp_add_aij(npp, copy, aij->col, aij->val); } /* replace the original inequality by equivalent one */ npp_erase_row(npp, row); row->lb = -DBL_MAX, row->ub = b; for (e = ptr; e != NULL; e = e->next) npp_add_aij(npp, row, e->xj, e->aj); /* continue processing lower bound for the copy */ if (copy != NULL) row = copy; } drop_form(npp, ptr); } return count; } /*********************************************************************** * NAME * * npp_implied_packing - identify implied packing inequality * * SYNOPSIS * * #include "glpnpp.h" * int npp_implied_packing(NPP *npp, NPPROW *row, int which, * NPPCOL *var[], char set[]); * * DESCRIPTION * * The routine npp_implied_packing processes specified row (constraint) * of general format: * * L <= sum a[j] x[j] <= U. (1) * j * * If which = 0, only lower bound L, which must exist, is considered, * while upper bound U is ignored. Similarly, if which = 1, only upper * bound U, which must exist, is considered, while lower bound L is * ignored. Thus, if the specified row is a double-sided inequality or * equality constraint, this routine should be called twice for both * lower and upper bounds. * * The routine npp_implied_packing attempts to find a non-trivial (i.e. * having not less than two binary variables) packing inequality: * * sum x[j] - sum x[j] <= 1 - |Jn|, (2) * j in Jp j in Jn * * which is relaxation of the constraint (1) in the sense that any * solution satisfying to that constraint also satisfies to the packing * inequality (2). If such relaxation exists, the routine stores * pointers to descriptors of corresponding binary variables and their * flags, resp., to locations var[1], var[2], ..., var[len] and set[1], * set[2], ..., set[len], where set[j] = 0 means that j in Jp and * set[j] = 1 means that j in Jn. * * RETURNS * * The routine npp_implied_packing returns len, which is the total * number of binary variables in the packing inequality found, len >= 2. * However, if the relaxation does not exist, the routine returns zero. * * ALGORITHM * * If which = 0, the constraint coefficients (1) are multiplied by -1 * and b is assigned -L; if which = 1, the constraint coefficients (1) * are not changed and b is assigned +U. In both cases the specified * constraint gets the following format: * * sum a[j] x[j] <= b. (3) * j * * (Note that (3) is a relaxation of (1), because one of bounds L or U * is ignored.) * * Let J be set of binary variables, Kp be set of non-binary (integer * or continuous) variables with a[j] > 0, and Kn be set of non-binary * variables with a[j] < 0. Then the inequality (3) can be written as * follows: * * sum a[j] x[j] <= b - sum a[j] x[j] - sum a[j] x[j]. (4) * j in J j in Kp j in Kn * * To get rid of non-binary variables we can replace the inequality (4) * by the following relaxed inequality: * * sum a[j] x[j] <= b~, (5) * j in J * * where: * * b~ = sup(b - sum a[j] x[j] - sum a[j] x[j]) = * j in Kp j in Kn * * = b - inf sum a[j] x[j] - inf sum a[j] x[j] = (6) * j in Kp j in Kn * * = b - sum a[j] l[j] - sum a[j] u[j]. * j in Kp j in Kn * * Note that if lower bound l[j] (if j in Kp) or upper bound u[j] * (if j in Kn) of some non-binary variable x[j] does not exist, then * formally b = +oo, in which case further analysis is not performed. * * Let Bp = {j in J: a[j] > 0}, Bn = {j in J: a[j] < 0}. To make all * the inequality coefficients in (5) positive, we replace all x[j] in * Bn by their complementaries, substituting x[j] = 1 - x~[j] for all * j in Bn, that gives: * * sum a[j] x[j] - sum a[j] x~[j] <= b~ - sum a[j]. (7) * j in Bp j in Bn j in Bn * * This inequality is a relaxation of the original constraint (1), and * it is a binary knapsack inequality. Writing it in the standard format * we have: * * sum alfa[j] z[j] <= beta, (8) * j in J * * where: * ( + a[j], if j in Bp, * alfa[j] = < (9) * ( - a[j], if j in Bn, * * ( x[j], if j in Bp, * z[j] = < (10) * ( 1 - x[j], if j in Bn, * * beta = b~ - sum a[j]. (11) * j in Bn * * In the inequality (8) all coefficients are positive, therefore, the * packing relaxation to be found for this inequality is the following: * * sum z[j] <= 1. (12) * j in P * * It is obvious that set P within J, which we would like to find, must * satisfy to the following condition: * * alfa[j] + alfa[k] > beta + eps for all j, k in P, j != k, (13) * * where eps is an absolute tolerance for value of the linear form. * Thus, it is natural to take P = {j: alpha[j] > (beta + eps) / 2}. * Moreover, if in the equality (8) there exist coefficients alfa[k], * for which alfa[k] <= (beta + eps) / 2, but which, nevertheless, * satisfies to the condition (13) for all j in P, *one* corresponding * variable z[k] (having, for example, maximal coefficient alfa[k]) can * be included in set P, that allows increasing the number of binary * variables in (12) by one. * * Once the set P has been built, for the inequality (12) we need to * perform back substitution according to (10) in order to express it * through the original binary variables. As the result of such back * substitution the relaxed packing inequality get its final format (2), * where Jp = J intersect Bp, and Jn = J intersect Bn. */ int npp_implied_packing(NPP *npp, NPPROW *row, int which, NPPCOL *var[], char set[]) { struct elem *ptr, *e, *i, *k; int len = 0; double b, eps; /* build inequality (3) */ if (which == 0) { ptr = copy_form(npp, row, -1.0); xassert(row->lb != -DBL_MAX); b = - row->lb; } else if (which == 1) { ptr = copy_form(npp, row, +1.0); xassert(row->ub != +DBL_MAX); b = + row->ub; } /* remove non-binary variables to build relaxed inequality (5); compute its right-hand side b~ with formula (6) */ for (e = ptr; e != NULL; e = e->next) { if (!(e->xj->is_int && e->xj->lb == 0.0 && e->xj->ub == 1.0)) { /* x[j] is non-binary variable */ if (e->aj > 0.0) { if (e->xj->lb == -DBL_MAX) goto done; b -= e->aj * e->xj->lb; } else /* e->aj < 0.0 */ { if (e->xj->ub == +DBL_MAX) goto done; b -= e->aj * e->xj->ub; } /* a[j] = 0 means that variable x[j] is removed */ e->aj = 0.0; } } /* substitute x[j] = 1 - x~[j] to build knapsack inequality (8); compute its right-hand side beta with formula (11) */ for (e = ptr; e != NULL; e = e->next) if (e->aj < 0.0) b -= e->aj; /* if beta is close to zero, the knapsack inequality is either infeasible or forcing inequality; this must never happen, so we skip further analysis */ if (b < 1e-3) goto done; /* build set P as well as sets Jp and Jn, and determine x[k] as explained above in comments to the routine */ eps = 1e-3 + 1e-6 * b; i = k = NULL; for (e = ptr; e != NULL; e = e->next) { /* note that alfa[j] = |a[j]| */ if (fabs(e->aj) > 0.5 * (b + eps)) { /* alfa[j] > (b + eps) / 2; include x[j] in set P, i.e. in set Jp or Jn */ var[++len] = e->xj; set[len] = (char)(e->aj > 0.0 ? 0 : 1); /* alfa[i] = min alfa[j] over all j included in set P */ if (i == NULL || fabs(i->aj) > fabs(e->aj)) i = e; } else if (fabs(e->aj) >= 1e-3) { /* alfa[k] = max alfa[j] over all j not included in set P; we skip coefficient a[j] if it is close to zero to avoid numerically unreliable results */ if (k == NULL || fabs(k->aj) < fabs(e->aj)) k = e; } } /* if alfa[k] satisfies to condition (13) for all j in P, include x[k] in P */ if (i != NULL && k != NULL && fabs(i->aj) + fabs(k->aj) > b + eps) { var[++len] = k->xj; set[len] = (char)(k->aj > 0.0 ? 0 : 1); } /* trivial packing inequality being redundant must never appear, so we just ignore it */ if (len < 2) len = 0; done: drop_form(npp, ptr); return len; } /*********************************************************************** * NAME * * npp_is_covering - test if constraint is covering inequality * * SYNOPSIS * * #include "glpnpp.h" * int npp_is_covering(NPP *npp, NPPROW *row); * * RETURNS * * If the specified row (constraint) is covering inequality (see below), * the routine npp_is_covering returns non-zero. Otherwise, it returns * zero. * * COVERING INEQUALITIES * * In canonical format the covering inequality is the following: * * sum x[j] >= 1, (1) * j in J * * where all variables x[j] are binary. This inequality expresses the * condition that in any integer feasible solution variables in set J * cannot be all equal to zero at the same time, i.e. at least one * variable must take non-zero (unity) value. W.l.o.g. it is assumed * that |J| >= 2, because if J is empty, the inequality (1) is * infeasible, and if |J| = 1, the inequality (1) is a forcing row. * * In general case the covering inequality may include original * variables x[j] as well as their complements x~[j]: * * sum x[j] + sum x~[j] >= 1, (2) * j in Jp j in Jn * * where Jp and Jn are not intersected. Therefore, using substitution * x~[j] = 1 - x[j] gives the packing inequality in generalized format: * * sum x[j] - sum x[j] >= 1 - |Jn|. (3) * j in Jp j in Jn * * (May note that the inequality (3) cuts off infeasible solutions, * where x[j] = 0 for all j in Jp and x[j] = 1 for all j in Jn.) * * NOTE: If |J| = 2, the inequality (3) is equivalent to packing * inequality (see the routine npp_is_packing). */ int npp_is_covering(NPP *npp, NPPROW *row) { /* test if constraint is covering inequality */ NPPCOL *col; NPPAIJ *aij; int b; xassert(npp == npp); if (!(row->lb != -DBL_MAX && row->ub == +DBL_MAX)) return 0; b = 1; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { col = aij->col; if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) return 0; if (aij->val == +1.0) ; else if (aij->val == -1.0) b--; else return 0; } if (row->lb != (double)b) return 0; return 1; } /*********************************************************************** * NAME * * npp_hidden_covering - identify hidden covering inequality * * SYNOPSIS * * #include "glpnpp.h" * int npp_hidden_covering(NPP *npp, NPPROW *row); * * DESCRIPTION * * The routine npp_hidden_covering processes specified inequality * constraint, which includes only binary variables, and the number of * the variables is not less than three. If the original inequality is * equivalent to a covering inequality (see below), the routine * replaces it by the equivalent inequality. If the original constraint * is double-sided inequality, it is replaced by a pair of single-sided * inequalities, if necessary. * * RETURNS * * If the original inequality constraint was replaced by equivalent * covering inequality, the routine npp_hidden_covering returns * non-zero. Otherwise, it returns zero. * * PROBLEM TRANSFORMATION * * Consider an inequality constraint: * * sum a[j] x[j] >= b, (1) * j in J * * where all variables x[j] are binary, and |J| >= 3. (In case of '<=' * inequality it can be transformed to '>=' format by multiplying both * its sides by -1.) * * Let Jp = {j: a[j] > 0}, Jn = {j: a[j] < 0}. Performing substitution * x[j] = 1 - x~[j] for all j in Jn, we have: * * sum a[j] x[j] >= b ==> * j in J * * sum a[j] x[j] + sum a[j] x[j] >= b ==> * j in Jp j in Jn * * sum a[j] x[j] + sum a[j] (1 - x~[j]) >= b ==> * j in Jp j in Jn * * sum m a[j] x[j] - sum a[j] x~[j] >= b - sum a[j]. * j in Jp j in Jn j in Jn * * Thus, meaning the transformation above, we can assume that in * inequality (1) all coefficients a[j] are positive. Moreover, we can * assume that b > 0, because otherwise the inequality (1) would be * redundant (see the routine npp_analyze_row). It is then obvious that * constraint (1) is equivalent to covering inequality only if: * * a[j] >= b, (2) * * for all j in J. * * Once the original inequality (1) is replaced by equivalent covering * inequality, we need to perform back substitution x~[j] = 1 - x[j] for * all j in Jn (see above). * * RECOVERING SOLUTION * * None needed. */ static int hidden_covering(NPP *npp, struct elem *ptr, double *_b) { /* process inequality constraint: sum a[j] x[j] >= b; 0 - specified row is NOT hidden covering inequality; 1 - specified row is covering inequality; 2 - specified row is hidden covering inequality. */ struct elem *e; int neg; double b = *_b, eps; xassert(npp == npp); /* a[j] must be non-zero, x[j] must be binary, for all j in J */ for (e = ptr; e != NULL; e = e->next) { xassert(e->aj != 0.0); xassert(e->xj->is_int); xassert(e->xj->lb == 0.0 && e->xj->ub == 1.0); } /* check if the specified inequality constraint already has the form of covering inequality */ neg = 0; /* neg is |Jn| */ for (e = ptr; e != NULL; e = e->next) { if (e->aj == +1.0) ; else if (e->aj == -1.0) neg++; else break; } if (e == NULL) { /* all coefficients a[j] are +1 or -1; check rhs b */ if (b == (double)(1 - neg)) { /* it is covering inequality; no processing is needed */ return 1; } } /* substitute x[j] = 1 - x~[j] for all j in Jn to make all a[j] positive; the result is a~[j] = |a[j]| and new rhs b */ for (e = ptr; e != NULL; e = e->next) if (e->aj < 0) b -= e->aj; /* now a[j] > 0 for all j in J (actually |a[j]| are used) */ /* if b <= 0, skip processing--this case must not appear */ if (b < 1e-3) return 0; /* now a[j] > 0 for all j in J, and b > 0 */ /* the specified constraint is equivalent to covering inequality iff a[j] >= b for all j in J */ eps = 1e-9 + 1e-12 * fabs(b); for (e = ptr; e != NULL; e = e->next) if (fabs(e->aj) < b - eps) return 0; /* perform back substitution x~[j] = 1 - x[j] and construct the final equivalent covering inequality in generalized format */ b = 1.0; for (e = ptr; e != NULL; e = e->next) { if (e->aj > 0.0) e->aj = +1.0; else /* e->aj < 0.0 */ e->aj = -1.0, b -= 1.0; } *_b = b; return 2; } int npp_hidden_covering(NPP *npp, NPPROW *row) { /* identify hidden covering inequality */ NPPROW *copy; NPPAIJ *aij; struct elem *ptr, *e; int kase, ret, count = 0; double b; /* the row must be inequality constraint */ xassert(row->lb < row->ub); for (kase = 0; kase <= 1; kase++) { if (kase == 0) { /* process row lower bound */ if (row->lb == -DBL_MAX) continue; ptr = copy_form(npp, row, +1.0); b = + row->lb; } else { /* process row upper bound */ if (row->ub == +DBL_MAX) continue; ptr = copy_form(npp, row, -1.0); b = - row->ub; } /* now the inequality has the form "sum a[j] x[j] >= b" */ ret = hidden_covering(npp, ptr, &b); xassert(0 <= ret && ret <= 2); if (kase == 1 && ret == 1 || ret == 2) { /* the original inequality has been identified as hidden covering inequality */ count++; #ifdef GLP_DEBUG xprintf("Original constraint:\n"); for (aij = row->ptr; aij != NULL; aij = aij->r_next) xprintf(" %+g x%d", aij->val, aij->col->j); if (row->lb != -DBL_MAX) xprintf(", >= %g", row->lb); if (row->ub != +DBL_MAX) xprintf(", <= %g", row->ub); xprintf("\n"); xprintf("Equivalent covering inequality:\n"); for (e = ptr; e != NULL; e = e->next) xprintf(" %sx%d", e->aj > 0.0 ? "+" : "-", e->xj->j); xprintf(", >= %g\n", b); #endif if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) { /* the original row is single-sided inequality; no copy is needed */ copy = NULL; } else { /* the original row is double-sided inequality; we need to create its copy for other bound before replacing it with the equivalent inequality */ copy = npp_add_row(npp); if (kase == 0) { /* the copy is for upper bound */ copy->lb = -DBL_MAX, copy->ub = row->ub; } else { /* the copy is for lower bound */ copy->lb = row->lb, copy->ub = +DBL_MAX; } /* copy original row coefficients */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) npp_add_aij(npp, copy, aij->col, aij->val); } /* replace the original inequality by equivalent one */ npp_erase_row(npp, row); row->lb = b, row->ub = +DBL_MAX; for (e = ptr; e != NULL; e = e->next) npp_add_aij(npp, row, e->xj, e->aj); /* continue processing upper bound for the copy */ if (copy != NULL) row = copy; } drop_form(npp, ptr); } return count; } /*********************************************************************** * NAME * * npp_is_partitioning - test if constraint is partitioning equality * * SYNOPSIS * * #include "glpnpp.h" * int npp_is_partitioning(NPP *npp, NPPROW *row); * * RETURNS * * If the specified row (constraint) is partitioning equality (see * below), the routine npp_is_partitioning returns non-zero. Otherwise, * it returns zero. * * PARTITIONING EQUALITIES * * In canonical format the partitioning equality is the following: * * sum x[j] = 1, (1) * j in J * * where all variables x[j] are binary. This equality expresses the * condition that in any integer feasible solution exactly one variable * in set J must take non-zero (unity) value while other variables must * be equal to zero. W.l.o.g. it is assumed that |J| >= 2, because if * J is empty, the inequality (1) is infeasible, and if |J| = 1, the * inequality (1) is a fixing row. * * In general case the partitioning equality may include original * variables x[j] as well as their complements x~[j]: * * sum x[j] + sum x~[j] = 1, (2) * j in Jp j in Jn * * where Jp and Jn are not intersected. Therefore, using substitution * x~[j] = 1 - x[j] leads to the partitioning equality in generalized * format: * * sum x[j] - sum x[j] = 1 - |Jn|. (3) * j in Jp j in Jn */ int npp_is_partitioning(NPP *npp, NPPROW *row) { /* test if constraint is partitioning equality */ NPPCOL *col; NPPAIJ *aij; int b; xassert(npp == npp); if (row->lb != row->ub) return 0; b = 1; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { col = aij->col; if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) return 0; if (aij->val == +1.0) ; else if (aij->val == -1.0) b--; else return 0; } if (row->lb != (double)b) return 0; return 1; } /*********************************************************************** * NAME * * npp_reduce_ineq_coef - reduce inequality constraint coefficients * * SYNOPSIS * * #include "glpnpp.h" * int npp_reduce_ineq_coef(NPP *npp, NPPROW *row); * * DESCRIPTION * * The routine npp_reduce_ineq_coef processes specified inequality * constraint attempting to replace it by an equivalent constraint, * where magnitude of coefficients at binary variables is smaller than * in the original constraint. If the inequality is double-sided, it is * replaced by a pair of single-sided inequalities, if necessary. * * RETURNS * * The routine npp_reduce_ineq_coef returns the number of coefficients * reduced. * * BACKGROUND * * Consider an inequality constraint: * * sum a[j] x[j] >= b. (1) * j in J * * (In case of '<=' inequality it can be transformed to '>=' format by * multiplying both its sides by -1.) Let x[k] be a binary variable; * other variables can be integer as well as continuous. We can write * constraint (1) as follows: * * a[k] x[k] + t[k] >= b, (2) * * where: * * t[k] = sum a[j] x[j]. (3) * j in J\{k} * * Since x[k] is binary, constraint (2) is equivalent to disjunction of * the following two constraints: * * x[k] = 0, t[k] >= b (4) * * OR * * x[k] = 1, t[k] >= b - a[k]. (5) * * Let also that for the partial sum t[k] be known some its implied * lower bound inf t[k]. * * Case a[k] > 0. Let inf t[k] < b, since otherwise both constraints * (4) and (5) and therefore constraint (2) are redundant. * If inf t[k] > b - a[k], only constraint (5) is redundant, in which * case it can be replaced with the following redundant and therefore * equivalent constraint: * * t[k] >= b - a'[k] = inf t[k], (6) * * where: * * a'[k] = b - inf t[k]. (7) * * Thus, the original constraint (2) is equivalent to the following * constraint with coefficient at variable x[k] changed: * * a'[k] x[k] + t[k] >= b. (8) * * From inf t[k] < b it follows that a'[k] > 0, i.e. the coefficient * at x[k] keeps its sign. And from inf t[k] > b - a[k] it follows that * a'[k] < a[k], i.e. the coefficient reduces in magnitude. * * Case a[k] < 0. Let inf t[k] < b - a[k], since otherwise both * constraints (4) and (5) and therefore constraint (2) are redundant. * If inf t[k] > b, only constraint (4) is redundant, in which case it * can be replaced with the following redundant and therefore equivalent * constraint: * * t[k] >= b' = inf t[k]. (9) * * Rewriting constraint (5) as follows: * * t[k] >= b - a[k] = b' - a'[k], (10) * * where: * * a'[k] = a[k] + b' - b = a[k] + inf t[k] - b, (11) * * we can see that disjunction of constraint (9) and (10) is equivalent * to disjunction of constraint (4) and (5), from which it follows that * the original constraint (2) is equivalent to the following constraint * with both coefficient at variable x[k] and right-hand side changed: * * a'[k] x[k] + t[k] >= b'. (12) * * From inf t[k] < b - a[k] it follows that a'[k] < 0, i.e. the * coefficient at x[k] keeps its sign. And from inf t[k] > b it follows * that a'[k] > a[k], i.e. the coefficient reduces in magnitude. * * PROBLEM TRANSFORMATION * * In the routine npp_reduce_ineq_coef the following implied lower * bound of the partial sum (3) is used: * * inf t[k] = sum a[j] l[j] + sum a[j] u[j], (13) * j in Jp\{k} k in Jn\{k} * * where Jp = {j : a[j] > 0}, Jn = {j : a[j] < 0}, l[j] and u[j] are * lower and upper bounds, resp., of variable x[j]. * * In order to compute inf t[k] more efficiently, the following formula, * which is equivalent to (13), is actually used: * * ( h - a[k] l[k] = h, if a[k] > 0, * inf t[k] = < (14) * ( h - a[k] u[k] = h - a[k], if a[k] < 0, * * where: * * h = sum a[j] l[j] + sum a[j] u[j] (15) * j in Jp j in Jn * * is the implied lower bound of row (1). * * Reduction of positive coefficient (a[k] > 0) does not change value * of h, since l[k] = 0. In case of reduction of negative coefficient * (a[k] < 0) from (11) it follows that: * * delta a[k] = a'[k] - a[k] = inf t[k] - b (> 0), (16) * * so new value of h (accounting that u[k] = 1) can be computed as * follows: * * h := h + delta a[k] = h + (inf t[k] - b). (17) * * RECOVERING SOLUTION * * None needed. */ static int reduce_ineq_coef(NPP *npp, struct elem *ptr, double *_b) { /* process inequality constraint: sum a[j] x[j] >= b */ /* returns: the number of coefficients reduced */ struct elem *e; int count = 0; double h, inf_t, new_a, b = *_b; xassert(npp == npp); /* compute h; see (15) */ h = 0.0; for (e = ptr; e != NULL; e = e->next) { if (e->aj > 0.0) { if (e->xj->lb == -DBL_MAX) goto done; h += e->aj * e->xj->lb; } else /* e->aj < 0.0 */ { if (e->xj->ub == +DBL_MAX) goto done; h += e->aj * e->xj->ub; } } /* perform reduction of coefficients at binary variables */ for (e = ptr; e != NULL; e = e->next) { /* skip non-binary variable */ if (!(e->xj->is_int && e->xj->lb == 0.0 && e->xj->ub == 1.0)) continue; if (e->aj > 0.0) { /* compute inf t[k]; see (14) */ inf_t = h; if (b - e->aj < inf_t && inf_t < b) { /* compute reduced coefficient a'[k]; see (7) */ new_a = b - inf_t; if (new_a >= +1e-3 && e->aj - new_a >= 0.01 * (1.0 + e->aj)) { /* accept a'[k] */ #ifdef GLP_DEBUG xprintf("+"); #endif e->aj = new_a; count++; } } } else /* e->aj < 0.0 */ { /* compute inf t[k]; see (14) */ inf_t = h - e->aj; if (b < inf_t && inf_t < b - e->aj) { /* compute reduced coefficient a'[k]; see (11) */ new_a = e->aj + (inf_t - b); if (new_a <= -1e-3 && new_a - e->aj >= 0.01 * (1.0 - e->aj)) { /* accept a'[k] */ #ifdef GLP_DEBUG xprintf("-"); #endif e->aj = new_a; /* update h; see (17) */ h += (inf_t - b); /* compute b'; see (9) */ b = inf_t; count++; } } } } *_b = b; done: return count; } int npp_reduce_ineq_coef(NPP *npp, NPPROW *row) { /* reduce inequality constraint coefficients */ NPPROW *copy; NPPAIJ *aij; struct elem *ptr, *e; int kase, count[2]; double b; /* the row must be inequality constraint */ xassert(row->lb < row->ub); count[0] = count[1] = 0; for (kase = 0; kase <= 1; kase++) { if (kase == 0) { /* process row lower bound */ if (row->lb == -DBL_MAX) continue; #ifdef GLP_DEBUG xprintf("L"); #endif ptr = copy_form(npp, row, +1.0); b = + row->lb; } else { /* process row upper bound */ if (row->ub == +DBL_MAX) continue; #ifdef GLP_DEBUG xprintf("U"); #endif ptr = copy_form(npp, row, -1.0); b = - row->ub; } /* now the inequality has the form "sum a[j] x[j] >= b" */ count[kase] = reduce_ineq_coef(npp, ptr, &b); if (count[kase] > 0) { /* the original inequality has been replaced by equivalent one with coefficients reduced */ if (row->lb == -DBL_MAX || row->ub == +DBL_MAX) { /* the original row is single-sided inequality; no copy is needed */ copy = NULL; } else { /* the original row is double-sided inequality; we need to create its copy for other bound before replacing it with the equivalent inequality */ #ifdef GLP_DEBUG xprintf("*"); #endif copy = npp_add_row(npp); if (kase == 0) { /* the copy is for upper bound */ copy->lb = -DBL_MAX, copy->ub = row->ub; } else { /* the copy is for lower bound */ copy->lb = row->lb, copy->ub = +DBL_MAX; } /* copy original row coefficients */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) npp_add_aij(npp, copy, aij->col, aij->val); } /* replace the original inequality by equivalent one */ npp_erase_row(npp, row); row->lb = b, row->ub = +DBL_MAX; for (e = ptr; e != NULL; e = e->next) npp_add_aij(npp, row, e->xj, e->aj); /* continue processing upper bound for the copy */ if (copy != NULL) row = copy; } drop_form(npp, ptr); } return count[0] + count[1]; } /* eof */ glpk-4.52.1/src/glpnpp05.c0000644000062000006210000006401112175147600014323 0ustar maomkpasswd/* glpnpp05.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpnpp.h" /*********************************************************************** * NAME * * npp_clean_prob - perform initial LP/MIP processing * * SYNOPSIS * * #include "glpnpp.h" * void npp_clean_prob(NPP *npp); * * DESCRIPTION * * The routine npp_clean_prob performs initial LP/MIP processing that * currently includes: * * 1) removing free rows; * * 2) replacing double-sided constraint rows with almost identical * bounds, by equality constraint rows; * * 3) removing fixed columns; * * 4) replacing double-bounded columns with almost identical bounds by * fixed columns and removing those columns; * * 5) initial processing constraint coefficients (not implemented); * * 6) initial processing objective coefficients (not implemented). */ void npp_clean_prob(NPP *npp) { /* perform initial LP/MIP processing */ NPPROW *row, *next_row; NPPCOL *col, *next_col; int ret; xassert(npp == npp); /* process rows which originally are free */ for (row = npp->r_head; row != NULL; row = next_row) { next_row = row->next; if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) { /* process free row */ #ifdef GLP_DEBUG xprintf("1"); #endif npp_free_row(npp, row); /* row was deleted */ } } /* process rows which originally are double-sided inequalities */ for (row = npp->r_head; row != NULL; row = next_row) { next_row = row->next; if (row->lb != -DBL_MAX && row->ub != +DBL_MAX && row->lb < row->ub) { ret = npp_make_equality(npp, row); if (ret == 0) ; else if (ret == 1) { /* row was replaced by equality constraint */ #ifdef GLP_DEBUG xprintf("2"); #endif } else xassert(ret != ret); } } /* process columns which are originally fixed */ for (col = npp->c_head; col != NULL; col = next_col) { next_col = col->next; if (col->lb == col->ub) { /* process fixed column */ #ifdef GLP_DEBUG xprintf("3"); #endif npp_fixed_col(npp, col); /* column was deleted */ } } /* process columns which are originally double-bounded */ for (col = npp->c_head; col != NULL; col = next_col) { next_col = col->next; if (col->lb != -DBL_MAX && col->ub != +DBL_MAX && col->lb < col->ub) { ret = npp_make_fixed(npp, col); if (ret == 0) ; else if (ret == 1) { /* column was replaced by fixed column; process it */ #ifdef GLP_DEBUG xprintf("4"); #endif npp_fixed_col(npp, col); /* column was deleted */ } } } return; } /*********************************************************************** * NAME * * npp_process_row - perform basic row processing * * SYNOPSIS * * #include "glpnpp.h" * int npp_process_row(NPP *npp, NPPROW *row, int hard); * * DESCRIPTION * * The routine npp_process_row performs basic row processing that * currently includes: * * 1) removing empty row; * * 2) removing equality constraint row singleton and corresponding * column; * * 3) removing inequality constraint row singleton and corresponding * column if it was fixed; * * 4) performing general row analysis; * * 5) removing redundant row bounds; * * 6) removing forcing row and corresponding columns; * * 7) removing row which becomes free due to redundant bounds; * * 8) computing implied bounds for all columns in the row and using * them to strengthen current column bounds (MIP only, optional, * performed if the flag hard is on). * * Additionally the routine may activate affected rows and/or columns * for further processing. * * RETURNS * * 0 success; * * GLP_ENOPFS primal/integer infeasibility detected; * * GLP_ENODFS dual infeasibility detected. */ int npp_process_row(NPP *npp, NPPROW *row, int hard) { /* perform basic row processing */ NPPCOL *col; NPPAIJ *aij, *next_aij, *aaa; int ret; /* row must not be free */ xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); /* start processing row */ if (row->ptr == NULL) { /* empty row */ ret = npp_empty_row(npp, row); if (ret == 0) { /* row was deleted */ #ifdef GLP_DEBUG xprintf("A"); #endif return 0; } else if (ret == 1) { /* primal infeasibility */ return GLP_ENOPFS; } else xassert(ret != ret); } if (row->ptr->r_next == NULL) { /* row singleton */ col = row->ptr->col; if (row->lb == row->ub) { /* equality constraint */ ret = npp_eq_singlet(npp, row); if (ret == 0) { /* column was fixed, row was deleted */ #ifdef GLP_DEBUG xprintf("B"); #endif /* activate rows affected by column */ for (aij = col->ptr; aij != NULL; aij = aij->c_next) npp_activate_row(npp, aij->row); /* process fixed column */ npp_fixed_col(npp, col); /* column was deleted */ return 0; } else if (ret == 1 || ret == 2) { /* primal/integer infeasibility */ return GLP_ENOPFS; } else xassert(ret != ret); } else { /* inequality constraint */ ret = npp_ineq_singlet(npp, row); if (0 <= ret && ret <= 3) { /* row was deleted */ #ifdef GLP_DEBUG xprintf("C"); #endif /* activate column, since its length was changed due to row deletion */ npp_activate_col(npp, col); if (ret >= 2) { /* column bounds changed significantly or column was fixed */ /* activate rows affected by column */ for (aij = col->ptr; aij != NULL; aij = aij->c_next) npp_activate_row(npp, aij->row); } if (ret == 3) { /* column was fixed; process it */ #ifdef GLP_DEBUG xprintf("D"); #endif npp_fixed_col(npp, col); /* column was deleted */ } return 0; } else if (ret == 4) { /* primal infeasibility */ return GLP_ENOPFS; } else xassert(ret != ret); } } #if 0 /* sometimes this causes too large round-off errors; probably pivot coefficient should be chosen more carefully */ if (row->ptr->r_next->r_next == NULL) { /* row doubleton */ if (row->lb == row->ub) { /* equality constraint */ if (!(row->ptr->col->is_int || row->ptr->r_next->col->is_int)) { /* both columns are continuous */ NPPCOL *q; q = npp_eq_doublet(npp, row); if (q != NULL) { /* column q was eliminated */ #ifdef GLP_DEBUG xprintf("E"); #endif /* now column q is singleton of type "implied slack variable"; we process it here to make sure that on recovering basic solution the row is always active equality constraint (as required by the routine rcv_eq_doublet) */ xassert(npp_process_col(npp, q) == 0); /* column q was deleted; note that row p also may be deleted */ return 0; } } } } #endif /* general row analysis */ ret = npp_analyze_row(npp, row); xassert(0x00 <= ret && ret <= 0xFF); if (ret == 0x33) { /* row bounds are inconsistent with column bounds */ return GLP_ENOPFS; } if ((ret & 0x0F) == 0x00) { /* row lower bound does not exist or redundant */ if (row->lb != -DBL_MAX) { /* remove redundant row lower bound */ #ifdef GLP_DEBUG xprintf("F"); #endif npp_inactive_bound(npp, row, 0); } } else if ((ret & 0x0F) == 0x01) { /* row lower bound can be active */ /* see below */ } else if ((ret & 0x0F) == 0x02) { /* row lower bound is a forcing bound */ #ifdef GLP_DEBUG xprintf("G"); #endif /* process forcing row */ if (npp_forcing_row(npp, row, 0) == 0) fixup: { /* columns were fixed, row was made free */ for (aij = row->ptr; aij != NULL; aij = next_aij) { /* process column fixed by forcing row */ #ifdef GLP_DEBUG xprintf("H"); #endif col = aij->col; next_aij = aij->r_next; /* activate rows affected by column */ for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next) npp_activate_row(npp, aaa->row); /* process fixed column */ npp_fixed_col(npp, col); /* column was deleted */ } /* process free row (which now is empty due to deletion of all its columns) */ npp_free_row(npp, row); /* row was deleted */ return 0; } } else xassert(ret != ret); if ((ret & 0xF0) == 0x00) { /* row upper bound does not exist or redundant */ if (row->ub != +DBL_MAX) { /* remove redundant row upper bound */ #ifdef GLP_DEBUG xprintf("I"); #endif npp_inactive_bound(npp, row, 1); } } else if ((ret & 0xF0) == 0x10) { /* row upper bound can be active */ /* see below */ } else if ((ret & 0xF0) == 0x20) { /* row upper bound is a forcing bound */ #ifdef GLP_DEBUG xprintf("J"); #endif /* process forcing row */ if (npp_forcing_row(npp, row, 1) == 0) goto fixup; } else xassert(ret != ret); if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) { /* row became free due to redundant bounds removal */ #ifdef GLP_DEBUG xprintf("K"); #endif /* activate its columns, since their length will change due to row deletion */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) npp_activate_col(npp, aij->col); /* process free row */ npp_free_row(npp, row); /* row was deleted */ return 0; } #if 1 /* 23/XII-2009 */ /* row lower and/or upper bounds can be active */ if (npp->sol == GLP_MIP && hard) { /* improve current column bounds (optional) */ if (npp_improve_bounds(npp, row, 1) < 0) return GLP_ENOPFS; } #endif return 0; } /*********************************************************************** * NAME * * npp_improve_bounds - improve current column bounds * * SYNOPSIS * * #include "glpnpp.h" * int npp_improve_bounds(NPP *npp, NPPROW *row, int flag); * * DESCRIPTION * * The routine npp_improve_bounds analyzes specified row (inequality * or equality constraint) to determine implied column bounds and then * uses these bounds to improve (strengthen) current column bounds. * * If the flag is on and current column bounds changed significantly * or the column was fixed, the routine activate rows affected by the * column for further processing. (This feature is intended to be used * in the main loop of the routine npp_process_row.) * * NOTE: This operation can be used for MIP problem only. * * RETURNS * * The routine npp_improve_bounds returns the number of significantly * changed bounds plus the number of column having been fixed due to * bound improvements. However, if the routine detects primal/integer * infeasibility, it returns a negative value. */ int npp_improve_bounds(NPP *npp, NPPROW *row, int flag) { /* improve current column bounds */ NPPCOL *col; NPPAIJ *aij, *next_aij, *aaa; int kase, ret, count = 0; double lb, ub; xassert(npp->sol == GLP_MIP); /* row must not be free */ xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); /* determine implied column bounds */ npp_implied_bounds(npp, row); /* and use these bounds to strengthen current column bounds */ for (aij = row->ptr; aij != NULL; aij = next_aij) { col = aij->col; next_aij = aij->r_next; for (kase = 0; kase <= 1; kase++) { /* save current column bounds */ lb = col->lb, ub = col->ub; if (kase == 0) { /* process implied column lower bound */ if (col->ll.ll == -DBL_MAX) continue; ret = npp_implied_lower(npp, col, col->ll.ll); } else { /* process implied column upper bound */ if (col->uu.uu == +DBL_MAX) continue; ret = npp_implied_upper(npp, col, col->uu.uu); } if (ret == 0 || ret == 1) { /* current column bounds did not change or changed, but not significantly; restore current column bounds */ col->lb = lb, col->ub = ub; } else if (ret == 2 || ret == 3) { /* current column bounds changed significantly or column was fixed */ #ifdef GLP_DEBUG xprintf("L"); #endif count++; /* activate other rows affected by column, if required */ if (flag) { for (aaa = col->ptr; aaa != NULL; aaa = aaa->c_next) { if (aaa->row != row) npp_activate_row(npp, aaa->row); } } if (ret == 3) { /* process fixed column */ #ifdef GLP_DEBUG xprintf("M"); #endif npp_fixed_col(npp, col); /* column was deleted */ break; /* for kase */ } } else if (ret == 4) { /* primal/integer infeasibility */ return -1; } else xassert(ret != ret); } } return count; } /*********************************************************************** * NAME * * npp_process_col - perform basic column processing * * SYNOPSIS * * #include "glpnpp.h" * int npp_process_col(NPP *npp, NPPCOL *col); * * DESCRIPTION * * The routine npp_process_col performs basic column processing that * currently includes: * * 1) fixing and removing empty column; * * 2) removing column singleton, which is implied slack variable, and * corresponding row if it becomes free; * * 3) removing bounds of column, which is implied free variable, and * replacing corresponding row by equality constraint. * * Additionally the routine may activate affected rows and/or columns * for further processing. * * RETURNS * * 0 success; * * GLP_ENOPFS primal/integer infeasibility detected; * * GLP_ENODFS dual infeasibility detected. */ int npp_process_col(NPP *npp, NPPCOL *col) { /* perform basic column processing */ NPPROW *row; NPPAIJ *aij; int ret; /* column must not be fixed */ xassert(col->lb < col->ub); /* start processing column */ if (col->ptr == NULL) { /* empty column */ ret = npp_empty_col(npp, col); if (ret == 0) { /* column was fixed and deleted */ #ifdef GLP_DEBUG xprintf("N"); #endif return 0; } else if (ret == 1) { /* dual infeasibility */ return GLP_ENODFS; } else xassert(ret != ret); } if (col->ptr->c_next == NULL) { /* column singleton */ row = col->ptr->row; if (row->lb == row->ub) { /* equality constraint */ if (!col->is_int) slack: { /* implied slack variable */ #ifdef GLP_DEBUG xprintf("O"); #endif npp_implied_slack(npp, col); /* column was deleted */ if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) { /* row became free due to implied slack variable */ #ifdef GLP_DEBUG xprintf("P"); #endif /* activate columns affected by row */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) npp_activate_col(npp, aij->col); /* process free row */ npp_free_row(npp, row); /* row was deleted */ } else { /* row became inequality constraint; activate it since its length changed due to column deletion */ npp_activate_row(npp, row); } return 0; } } else { /* inequality constraint */ if (!col->is_int) { ret = npp_implied_free(npp, col); if (ret == 0) { /* implied free variable */ #ifdef GLP_DEBUG xprintf("Q"); #endif /* column bounds were removed, row was replaced by equality constraint */ goto slack; } else if (ret == 1) { /* column is not implied free variable, because its lower and/or upper bounds can be active */ } else if (ret == 2) { /* dual infeasibility */ return GLP_ENODFS; } } } } /* column still exists */ return 0; } /*********************************************************************** * NAME * * npp_process_prob - perform basic LP/MIP processing * * SYNOPSIS * * #include "glpnpp.h" * int npp_process_prob(NPP *npp, int hard); * * DESCRIPTION * * The routine npp_process_prob performs basic LP/MIP processing that * currently includes: * * 1) initial LP/MIP processing (see the routine npp_clean_prob), * * 2) basic row processing (see the routine npp_process_row), and * * 3) basic column processing (see the routine npp_process_col). * * If the flag hard is on, the routine attempts to improve current * column bounds multiple times within the main processing loop, in * which case this feature may take a time. Otherwise, if the flag hard * is off, improving column bounds is performed only once at the end of * the main loop. (Note that this feature is used for MIP only.) * * The routine uses two sets: the set of active rows and the set of * active columns. Rows/columns are marked by a flag (the field temp in * NPPROW/NPPCOL). If the flag is non-zero, the row/column is active, * in which case it is placed in the beginning of the row/column list; * otherwise, if the flag is zero, the row/column is inactive, in which * case it is placed in the end of the row/column list. If a row/column * being currently processed may affect other rows/columns, the latters * are activated for further processing. * * RETURNS * * 0 success; * * GLP_ENOPFS primal/integer infeasibility detected; * * GLP_ENODFS dual infeasibility detected. */ int npp_process_prob(NPP *npp, int hard) { /* perform basic LP/MIP processing */ NPPROW *row; NPPCOL *col; int processing, ret; /* perform initial LP/MIP processing */ npp_clean_prob(npp); /* activate all remaining rows and columns */ for (row = npp->r_head; row != NULL; row = row->next) row->temp = 1; for (col = npp->c_head; col != NULL; col = col->next) col->temp = 1; /* main processing loop */ processing = 1; while (processing) { processing = 0; /* process all active rows */ for (;;) { row = npp->r_head; if (row == NULL || !row->temp) break; npp_deactivate_row(npp, row); ret = npp_process_row(npp, row, hard); if (ret != 0) goto done; processing = 1; } /* process all active columns */ for (;;) { col = npp->c_head; if (col == NULL || !col->temp) break; npp_deactivate_col(npp, col); ret = npp_process_col(npp, col); if (ret != 0) goto done; processing = 1; } } #if 1 /* 23/XII-2009 */ if (npp->sol == GLP_MIP && !hard) { /* improve current column bounds (optional) */ for (row = npp->r_head; row != NULL; row = row->next) { if (npp_improve_bounds(npp, row, 0) < 0) { ret = GLP_ENOPFS; goto done; } } } #endif /* all seems ok */ ret = 0; done: xassert(ret == 0 || ret == GLP_ENOPFS || ret == GLP_ENODFS); #ifdef GLP_DEBUG xprintf("\n"); #endif return ret; } /**********************************************************************/ int npp_simplex(NPP *npp, const glp_smcp *parm) { /* process LP prior to applying primal/dual simplex method */ int ret; xassert(npp->sol == GLP_SOL); xassert(parm == parm); ret = npp_process_prob(npp, 0); return ret; } /**********************************************************************/ int npp_integer(NPP *npp, const glp_iocp *parm) { /* process MIP prior to applying branch-and-bound method */ NPPROW *row, *prev_row; NPPCOL *col; NPPAIJ *aij; int count, ret; xassert(npp->sol == GLP_MIP); xassert(parm == parm); /*==============================================================*/ /* perform basic MIP processing */ ret = npp_process_prob(npp, 1); if (ret != 0) goto done; /*==============================================================*/ /* binarize problem, if required */ if (parm->binarize) npp_binarize_prob(npp); /*==============================================================*/ /* identify hidden packing inequalities */ count = 0; /* new rows will be added to the end of the row list, so we go from the end to beginning of the row list */ for (row = npp->r_tail; row != NULL; row = prev_row) { prev_row = row->prev; /* skip free row */ if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue; /* skip equality constraint */ if (row->lb == row->ub) continue; /* skip row having less than two variables */ if (row->ptr == NULL || row->ptr->r_next == NULL) continue; /* skip row having non-binary variables */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) { col = aij->col; if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) break; } if (aij != NULL) continue; count += npp_hidden_packing(npp, row); } if (count > 0) xprintf("%d hidden packing inequaliti(es) were detected\n", count); /*==============================================================*/ /* identify hidden covering inequalities */ count = 0; /* new rows will be added to the end of the row list, so we go from the end to beginning of the row list */ for (row = npp->r_tail; row != NULL; row = prev_row) { prev_row = row->prev; /* skip free row */ if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) continue; /* skip equality constraint */ if (row->lb == row->ub) continue; /* skip row having less than three variables */ if (row->ptr == NULL || row->ptr->r_next == NULL || row->ptr->r_next->r_next == NULL) continue; /* skip row having non-binary variables */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) { col = aij->col; if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) break; } if (aij != NULL) continue; count += npp_hidden_covering(npp, row); } if (count > 0) xprintf("%d hidden covering inequaliti(es) were detected\n", count); /*==============================================================*/ /* reduce inequality constraint coefficients */ count = 0; /* new rows will be added to the end of the row list, so we go from the end to beginning of the row list */ for (row = npp->r_tail; row != NULL; row = prev_row) { prev_row = row->prev; /* skip equality constraint */ if (row->lb == row->ub) continue; count += npp_reduce_ineq_coef(npp, row); } if (count > 0) xprintf("%d constraint coefficient(s) were reduced\n", count); /*==============================================================*/ #ifdef GLP_DEBUG routine(npp); #endif /*==============================================================*/ /* all seems ok */ ret = 0; done: return ret; } /* eof */ glpk-4.52.1/src/glpnpp06.c0000644000062000006210000014441312175147600014331 0ustar maomkpasswd/* glpnpp06.c (translate feasibility problem to CNF-SAT) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpnpp.h" /*********************************************************************** * npp_sat_free_row - process free (unbounded) row * * This routine processes row p, which is free (i.e. has no finite * bounds): * * -inf < sum a[p,j] x[j] < +inf. (1) * * The constraint (1) cannot be active and therefore it is redundant, * so the routine simply removes it from the original problem. */ void npp_sat_free_row(NPP *npp, NPPROW *p) { /* the row should be free */ xassert(p->lb == -DBL_MAX && p->ub == +DBL_MAX); /* remove the row from the problem */ npp_del_row(npp, p); return; } /*********************************************************************** * npp_sat_fixed_col - process fixed column * * This routine processes column q, which is fixed: * * x[q] = s[q], (1) * * where s[q] is a fixed column value. * * The routine substitutes fixed value s[q] into constraint rows and * then removes column x[q] from the original problem. * * Substitution of x[q] = s[q] into row i gives: * * L[i] <= sum a[i,j] x[j] <= U[i] ==> * j * * L[i] <= sum a[i,j] x[j] + a[i,q] x[q] <= U[i] ==> * j!=q * * L[i] <= sum a[i,j] x[j] + a[i,q] s[q] <= U[i] ==> * j!=q * * L~[i] <= sum a[i,j] x[j] <= U~[i], * j!=q * * where * * L~[i] = L[i] - a[i,q] s[q], (2) * * U~[i] = U[i] - a[i,q] s[q] (3) * * are, respectively, lower and upper bound of row i in the transformed * problem. * * On recovering solution x[q] is assigned the value of s[q]. */ struct sat_fixed_col { /* fixed column */ int q; /* column reference number for variable x[q] */ int s; /* value, at which x[q] is fixed */ }; static int rcv_sat_fixed_col(NPP *, void *); int npp_sat_fixed_col(NPP *npp, NPPCOL *q) { struct sat_fixed_col *info; NPPROW *i; NPPAIJ *aij; int temp; /* the column should be fixed */ xassert(q->lb == q->ub); /* create transformation stack entry */ info = npp_push_tse(npp, rcv_sat_fixed_col, sizeof(struct sat_fixed_col)); info->q = q->j; info->s = (int)q->lb; xassert((double)info->s == q->lb); /* substitute x[q] = s[q] into constraint rows */ if (info->s == 0) goto skip; for (aij = q->ptr; aij != NULL; aij = aij->c_next) { i = aij->row; if (i->lb != -DBL_MAX) { i->lb -= aij->val * (double)info->s; temp = (int)i->lb; if ((double)temp != i->lb) return 1; /* integer arithmetic error */ } if (i->ub != +DBL_MAX) { i->ub -= aij->val * (double)info->s; temp = (int)i->ub; if ((double)temp != i->ub) return 2; /* integer arithmetic error */ } } skip: /* remove the column from the problem */ npp_del_col(npp, q); return 0; } static int rcv_sat_fixed_col(NPP *npp, void *info_) { struct sat_fixed_col *info = info_; npp->c_value[info->q] = (double)info->s; return 0; } /*********************************************************************** * npp_sat_is_bin_comb - test if row is binary combination * * This routine tests if the specified row is a binary combination, * i.e. all its constraint coefficients are +1 and -1 and all variables * are binary. If the test was passed, the routine returns non-zero, * otherwise zero. */ int npp_sat_is_bin_comb(NPP *npp, NPPROW *row) { NPPCOL *col; NPPAIJ *aij; xassert(npp == npp); for (aij = row->ptr; aij != NULL; aij = aij->r_next) { if (!(aij->val == +1.0 || aij->val == -1.0)) return 0; /* non-unity coefficient */ col = aij->col; if (!(col->is_int && col->lb == 0.0 && col->ub == 1.0)) return 0; /* non-binary column */ } return 1; /* test was passed */ } /*********************************************************************** * npp_sat_num_pos_coef - determine number of positive coefficients * * This routine returns the number of positive coefficients in the * specified row. */ int npp_sat_num_pos_coef(NPP *npp, NPPROW *row) { NPPAIJ *aij; int num = 0; xassert(npp == npp); for (aij = row->ptr; aij != NULL; aij = aij->r_next) { if (aij->val > 0.0) num++; } return num; } /*********************************************************************** * npp_sat_num_neg_coef - determine number of negative coefficients * * This routine returns the number of negative coefficients in the * specified row. */ int npp_sat_num_neg_coef(NPP *npp, NPPROW *row) { NPPAIJ *aij; int num = 0; xassert(npp == npp); for (aij = row->ptr; aij != NULL; aij = aij->r_next) { if (aij->val < 0.0) num++; } return num; } /*********************************************************************** * npp_sat_is_cover_ineq - test if row is covering inequality * * The canonical form of a covering inequality is the following: * * sum x[j] >= 1, (1) * j in J * * where all x[j] are binary variables. * * In general case a covering inequality may have one of the following * two forms: * * sum x[j] - sum x[j] >= 1 - |J-|, (2) * j in J+ j in J- * * * sum x[j] - sum x[j] <= |J+| - 1. (3) * j in J+ j in J- * * Obviously, the inequality (2) can be transformed to the form (1) by * substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the * negation of variable x[j]. And the inequality (3) can be transformed * to (2) by multiplying both left- and right-hand sides by -1. * * This routine returns one of the following codes: * * 0, if the specified row is not a covering inequality; * * 1, if the specified row has the form (2); * * 2, if the specified row has the form (3). */ int npp_sat_is_cover_ineq(NPP *npp, NPPROW *row) { xassert(npp == npp); if (row->lb != -DBL_MAX && row->ub == +DBL_MAX) { /* row is inequality of '>=' type */ if (npp_sat_is_bin_comb(npp, row)) { /* row is a binary combination */ if (row->lb == 1.0 - npp_sat_num_neg_coef(npp, row)) { /* row has the form (2) */ return 1; } } } else if (row->lb == -DBL_MAX && row->ub != +DBL_MAX) { /* row is inequality of '<=' type */ if (npp_sat_is_bin_comb(npp, row)) { /* row is a binary combination */ if (row->ub == npp_sat_num_pos_coef(npp, row) - 1.0) { /* row has the form (3) */ return 2; } } } /* row is not a covering inequality */ return 0; } /*********************************************************************** * npp_sat_is_pack_ineq - test if row is packing inequality * * The canonical form of a packing inequality is the following: * * sum x[j] <= 1, (1) * j in J * * where all x[j] are binary variables. * * In general case a packing inequality may have one of the following * two forms: * * sum x[j] - sum x[j] <= 1 - |J-|, (2) * j in J+ j in J- * * * sum x[j] - sum x[j] >= |J+| - 1. (3) * j in J+ j in J- * * Obviously, the inequality (2) can be transformed to the form (1) by * substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the * negation of variable x[j]. And the inequality (3) can be transformed * to (2) by multiplying both left- and right-hand sides by -1. * * This routine returns one of the following codes: * * 0, if the specified row is not a packing inequality; * * 1, if the specified row has the form (2); * * 2, if the specified row has the form (3). */ int npp_sat_is_pack_ineq(NPP *npp, NPPROW *row) { xassert(npp == npp); if (row->lb == -DBL_MAX && row->ub != +DBL_MAX) { /* row is inequality of '<=' type */ if (npp_sat_is_bin_comb(npp, row)) { /* row is a binary combination */ if (row->ub == 1.0 - npp_sat_num_neg_coef(npp, row)) { /* row has the form (2) */ return 1; } } } else if (row->lb != -DBL_MAX && row->ub == +DBL_MAX) { /* row is inequality of '>=' type */ if (npp_sat_is_bin_comb(npp, row)) { /* row is a binary combination */ if (row->lb == npp_sat_num_pos_coef(npp, row) - 1.0) { /* row has the form (3) */ return 2; } } } /* row is not a packing inequality */ return 0; } /*********************************************************************** * npp_sat_is_partn_eq - test if row is partitioning equality * * The canonical form of a partitioning equality is the following: * * sum x[j] = 1, (1) * j in J * * where all x[j] are binary variables. * * In general case a partitioning equality may have one of the following * two forms: * * sum x[j] - sum x[j] = 1 - |J-|, (2) * j in J+ j in J- * * * sum x[j] - sum x[j] = |J+| - 1. (3) * j in J+ j in J- * * Obviously, the equality (2) can be transformed to the form (1) by * substitution x[j] = 1 - x'[j] for all j in J-, where x'[j] is the * negation of variable x[j]. And the equality (3) can be transformed * to (2) by multiplying both left- and right-hand sides by -1. * * This routine returns one of the following codes: * * 0, if the specified row is not a partitioning equality; * * 1, if the specified row has the form (2); * * 2, if the specified row has the form (3). */ int npp_sat_is_partn_eq(NPP *npp, NPPROW *row) { xassert(npp == npp); if (row->lb == row->ub) { /* row is equality constraint */ if (npp_sat_is_bin_comb(npp, row)) { /* row is a binary combination */ if (row->lb == 1.0 - npp_sat_num_neg_coef(npp, row)) { /* row has the form (2) */ return 1; } if (row->ub == npp_sat_num_pos_coef(npp, row) - 1.0) { /* row has the form (3) */ return 2; } } } /* row is not a partitioning equality */ return 0; } /*********************************************************************** * npp_sat_reverse_row - multiply both sides of row by -1 * * This routines multiplies by -1 both left- and right-hand sides of * the specified row: * * L <= sum x[j] <= U, * * that results in the following row: * * -U <= sum (-x[j]) <= -L. * * If no integer overflow occured, the routine returns zero, otherwise * non-zero. */ int npp_sat_reverse_row(NPP *npp, NPPROW *row) { NPPAIJ *aij; int temp, ret = 0; double old_lb, old_ub; xassert(npp == npp); for (aij = row->ptr; aij != NULL; aij = aij->r_next) { aij->val = -aij->val; temp = (int)aij->val; if ((double)temp != aij->val) ret = 1; } old_lb = row->lb, old_ub = row->ub; if (old_ub == +DBL_MAX) row->lb = -DBL_MAX; else { row->lb = -old_ub; temp = (int)row->lb; if ((double)temp != row->lb) ret = 2; } if (old_lb == -DBL_MAX) row->ub = +DBL_MAX; else { row->ub = -old_lb; temp = (int)row->ub; if ((double)temp != row->ub) ret = 3; } return ret; } /*********************************************************************** * npp_sat_split_pack - split packing inequality * * Let there be given a packing inequality in canonical form: * * sum t[j] <= 1, (1) * j in J * * where t[j] = x[j] or t[j] = 1 - x[j], x[j] is a binary variable. * And let J = J1 U J2 is a partition of the set of literals. Then the * inequality (1) is obviously equivalent to the following two packing * inequalities: * * sum t[j] <= y <--> sum t[j] + (1 - y) <= 1, (2) * j in J1 j in J1 * * sum t[j] <= 1 - y <--> sum t[j] + y <= 1, (3) * j in J2 j in J2 * * where y is a new binary variable added to the transformed problem. * * Assuming that the specified row is a packing inequality (1), this * routine constructs the set J1 by including there first nlit literals * (terms) from the specified row, and the set J2 = J \ J1. Then the * routine creates a new row, which corresponds to inequality (2), and * replaces the specified row with inequality (3). */ NPPROW *npp_sat_split_pack(NPP *npp, NPPROW *row, int nlit) { NPPROW *rrr; NPPCOL *col; NPPAIJ *aij; int k; /* original row should be packing inequality (1) */ xassert(npp_sat_is_pack_ineq(npp, row) == 1); /* and nlit should be less than the number of literals (terms) in the original row */ xassert(0 < nlit && nlit < npp_row_nnz(npp, row)); /* create new row corresponding to inequality (2) */ rrr = npp_add_row(npp); rrr->lb = -DBL_MAX, rrr->ub = 1.0; /* move first nlit literals (terms) from the original row to the new row; the original row becomes inequality (3) */ for (k = 1; k <= nlit; k++) { aij = row->ptr; xassert(aij != NULL); /* add literal to the new row */ npp_add_aij(npp, rrr, aij->col, aij->val); /* correct rhs */ if (aij->val < 0.0) rrr->ub -= 1.0, row->ub += 1.0; /* remove literal from the original row */ npp_del_aij(npp, aij); } /* create new binary variable y */ col = npp_add_col(npp); col->is_int = 1, col->lb = 0.0, col->ub = 1.0; /* include literal (1 - y) in the new row */ npp_add_aij(npp, rrr, col, -1.0); rrr->ub -= 1.0; /* include literal y in the original row */ npp_add_aij(npp, row, col, +1.0); return rrr; } /*********************************************************************** * npp_sat_encode_pack - encode packing inequality * * Given a packing inequality in canonical form: * * sum t[j] <= 1, (1) * j in J * * where t[j] = x[j] or t[j] = 1 - x[j], x[j] is a binary variable, * this routine translates it to CNF by replacing it with the following * equivalent set of edge packing inequalities: * * t[j] + t[k] <= 1 for all j, k in J, j != k. (2) * * Then the routine transforms each edge packing inequality (2) to * corresponding covering inequality (that encodes two-literal clause) * by multiplying both its part by -1: * * - t[j] - t[k] >= -1 <--> (1 - t[j]) + (1 - t[k]) >= 1. (3) * * On exit the routine removes the original row from the problem. */ void npp_sat_encode_pack(NPP *npp, NPPROW *row) { NPPROW *rrr; NPPAIJ *aij, *aik; /* original row should be packing inequality (1) */ xassert(npp_sat_is_pack_ineq(npp, row) == 1); /* create equivalent system of covering inequalities (3) */ for (aij = row->ptr; aij != NULL; aij = aij->r_next) { /* due to symmetry only one of inequalities t[j] + t[k] <= 1 and t[k] <= t[j] <= 1 can be considered */ for (aik = aij->r_next; aik != NULL; aik = aik->r_next) { /* create edge packing inequality (2) */ rrr = npp_add_row(npp); rrr->lb = -DBL_MAX, rrr->ub = 1.0; npp_add_aij(npp, rrr, aij->col, aij->val); if (aij->val < 0.0) rrr->ub -= 1.0; npp_add_aij(npp, rrr, aik->col, aik->val); if (aik->val < 0.0) rrr->ub -= 1.0; /* and transform it to covering inequality (3) */ npp_sat_reverse_row(npp, rrr); xassert(npp_sat_is_cover_ineq(npp, rrr) == 1); } } /* remove the original row from the problem */ npp_del_row(npp, row); return; } /*********************************************************************** * npp_sat_encode_sum2 - encode 2-bit summation * * Given a set containing two literals x and y this routine encodes * the equality * * x + y = s + 2 * c, (1) * * where * * s = (x + y) % 2 (2) * * is a binary variable modeling the low sum bit, and * * c = (x + y) / 2 (3) * * is a binary variable modeling the high (carry) sum bit. */ void npp_sat_encode_sum2(NPP *npp, NPPLSE *set, NPPSED *sed) { NPPROW *row; int x, y, s, c; /* the set should contain exactly two literals */ xassert(set != NULL); xassert(set->next != NULL); xassert(set->next->next == NULL); sed->x = set->lit; xassert(sed->x.neg == 0 || sed->x.neg == 1); sed->y = set->next->lit; xassert(sed->y.neg == 0 || sed->y.neg == 1); sed->z.col = NULL, sed->z.neg = 0; /* perform encoding s = (x + y) % 2 */ sed->s = npp_add_col(npp); sed->s->is_int = 1, sed->s->lb = 0.0, sed->s->ub = 1.0; for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { for (s = 0; s <= 1; s++) { if ((x + y) % 2 != s) { /* generate CNF clause to disable infeasible combination */ row = npp_add_row(npp); row->lb = 1.0, row->ub = +DBL_MAX; if (x == sed->x.neg) npp_add_aij(npp, row, sed->x.col, +1.0); else { npp_add_aij(npp, row, sed->x.col, -1.0); row->lb -= 1.0; } if (y == sed->y.neg) npp_add_aij(npp, row, sed->y.col, +1.0); else { npp_add_aij(npp, row, sed->y.col, -1.0); row->lb -= 1.0; } if (s == 0) npp_add_aij(npp, row, sed->s, +1.0); else { npp_add_aij(npp, row, sed->s, -1.0); row->lb -= 1.0; } } } } } /* perform encoding c = (x + y) / 2 */ sed->c = npp_add_col(npp); sed->c->is_int = 1, sed->c->lb = 0.0, sed->c->ub = 1.0; for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { for (c = 0; c <= 1; c++) { if ((x + y) / 2 != c) { /* generate CNF clause to disable infeasible combination */ row = npp_add_row(npp); row->lb = 1.0, row->ub = +DBL_MAX; if (x == sed->x.neg) npp_add_aij(npp, row, sed->x.col, +1.0); else { npp_add_aij(npp, row, sed->x.col, -1.0); row->lb -= 1.0; } if (y == sed->y.neg) npp_add_aij(npp, row, sed->y.col, +1.0); else { npp_add_aij(npp, row, sed->y.col, -1.0); row->lb -= 1.0; } if (c == 0) npp_add_aij(npp, row, sed->c, +1.0); else { npp_add_aij(npp, row, sed->c, -1.0); row->lb -= 1.0; } } } } } return; } /*********************************************************************** * npp_sat_encode_sum3 - encode 3-bit summation * * Given a set containing at least three literals this routine chooses * some literals x, y, z from that set and encodes the equality * * x + y + z = s + 2 * c, (1) * * where * * s = (x + y + z) % 2 (2) * * is a binary variable modeling the low sum bit, and * * c = (x + y + z) / 2 (3) * * is a binary variable modeling the high (carry) sum bit. */ void npp_sat_encode_sum3(NPP *npp, NPPLSE *set, NPPSED *sed) { NPPROW *row; int x, y, z, s, c; /* the set should contain at least three literals */ xassert(set != NULL); xassert(set->next != NULL); xassert(set->next->next != NULL); sed->x = set->lit; xassert(sed->x.neg == 0 || sed->x.neg == 1); sed->y = set->next->lit; xassert(sed->y.neg == 0 || sed->y.neg == 1); sed->z = set->next->next->lit; xassert(sed->z.neg == 0 || sed->z.neg == 1); /* perform encoding s = (x + y + z) % 2 */ sed->s = npp_add_col(npp); sed->s->is_int = 1, sed->s->lb = 0.0, sed->s->ub = 1.0; for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { for (z = 0; z <= 1; z++) { for (s = 0; s <= 1; s++) { if ((x + y + z) % 2 != s) { /* generate CNF clause to disable infeasible combination */ row = npp_add_row(npp); row->lb = 1.0, row->ub = +DBL_MAX; if (x == sed->x.neg) npp_add_aij(npp, row, sed->x.col, +1.0); else { npp_add_aij(npp, row, sed->x.col, -1.0); row->lb -= 1.0; } if (y == sed->y.neg) npp_add_aij(npp, row, sed->y.col, +1.0); else { npp_add_aij(npp, row, sed->y.col, -1.0); row->lb -= 1.0; } if (z == sed->z.neg) npp_add_aij(npp, row, sed->z.col, +1.0); else { npp_add_aij(npp, row, sed->z.col, -1.0); row->lb -= 1.0; } if (s == 0) npp_add_aij(npp, row, sed->s, +1.0); else { npp_add_aij(npp, row, sed->s, -1.0); row->lb -= 1.0; } } } } } } /* perform encoding c = (x + y + z) / 2 */ sed->c = npp_add_col(npp); sed->c->is_int = 1, sed->c->lb = 0.0, sed->c->ub = 1.0; for (x = 0; x <= 1; x++) { for (y = 0; y <= 1; y++) { for (z = 0; z <= 1; z++) { for (c = 0; c <= 1; c++) { if ((x + y + z) / 2 != c) { /* generate CNF clause to disable infeasible combination */ row = npp_add_row(npp); row->lb = 1.0, row->ub = +DBL_MAX; if (x == sed->x.neg) npp_add_aij(npp, row, sed->x.col, +1.0); else { npp_add_aij(npp, row, sed->x.col, -1.0); row->lb -= 1.0; } if (y == sed->y.neg) npp_add_aij(npp, row, sed->y.col, +1.0); else { npp_add_aij(npp, row, sed->y.col, -1.0); row->lb -= 1.0; } if (z == sed->z.neg) npp_add_aij(npp, row, sed->z.col, +1.0); else { npp_add_aij(npp, row, sed->z.col, -1.0); row->lb -= 1.0; } if (c == 0) npp_add_aij(npp, row, sed->c, +1.0); else { npp_add_aij(npp, row, sed->c, -1.0); row->lb -= 1.0; } } } } } } return; } /*********************************************************************** * npp_sat_encode_sum_ax - encode linear combination of 0-1 variables * * PURPOSE * * Given a linear combination of binary variables: * * sum a[j] x[j], (1) * j * * which is the linear form of the specified row, this routine encodes * (i.e. translates to CNF) the following equality: * * n * sum |a[j]| t[j] = sum 2**(k-1) * y[k], (2) * j k=1 * * where t[j] = x[j] (if a[j] > 0) or t[j] = 1 - x[j] (if a[j] < 0), * and y[k] is either t[j] or a new literal created by the routine or * a constant zero. Note that the sum in the right-hand side of (2) can * be thought as a n-bit representation of the sum in the left-hand * side, which is a non-negative integer number. * * ALGORITHM * * First, the number of bits, n, sufficient to represent any value in * the left-hand side of (2) is determined. Obviously, n is the number * of bits sufficient to represent the sum (sum |a[j]|). * * Let * * n * |a[j]| = sum 2**(k-1) b[j,k], (3) * k=1 * * where b[j,k] is k-th bit in a n-bit representation of |a[j]|. Then * * m n * sum |a[j]| * t[j] = sum 2**(k-1) sum b[j,k] * t[j]. (4) * j k=1 j=1 * * Introducing the set * * J[k] = { j : b[j,k] = 1 } (5) * * allows rewriting (4) as follows: * * n * sum |a[j]| * t[j] = sum 2**(k-1) sum t[j]. (6) * j k=1 j in J[k] * * Thus, our goal is to provide |J[k]| <= 1 for all k, in which case * we will have the representation (1). * * Let |J[k]| = 2, i.e. J[k] has exactly two literals u and v. In this * case we can apply the following transformation: * * u + v = s + 2 * c, (7) * * where s and c are, respectively, low (sum) and high (carry) bits of * the sum of two bits. This allows to replace two literals u and v in * J[k] by one literal s, and carry out literal c to J[k+1]. * * If |J[k]| >= 3, i.e. J[k] has at least three literals u, v, and w, * we can apply the following transformation: * * u + v + w = s + 2 * c. (8) * * Again, literal s replaces literals u, v, and w in J[k], and literal * c goes into J[k+1]. * * On exit the routine stores each literal from J[k] in element y[k], * 1 <= k <= n. If J[k] is empty, y[k] is set to constant false. * * RETURNS * * The routine returns n, the number of literals in the right-hand side * of (2), 0 <= n <= NBIT_MAX. If the sum (sum |a[j]|) is too large, so * more than NBIT_MAX (= 31) literals are needed to encode the original * linear combination, the routine returns a negative value. */ #define NBIT_MAX 31 /* maximal number of literals in the right hand-side of (2) */ static NPPLSE *remove_lse(NPP *npp, NPPLSE *set, NPPCOL *col) { /* remove specified literal from specified literal set */ NPPLSE *lse, *prev = NULL; for (lse = set; lse != NULL; prev = lse, lse = lse->next) if (lse->lit.col == col) break; xassert(lse != NULL); if (prev == NULL) set = lse->next; else prev->next = lse->next; dmp_free_atom(npp->pool, lse, sizeof(NPPLSE)); return set; } int npp_sat_encode_sum_ax(NPP *npp, NPPROW *row, NPPLIT y[]) { NPPAIJ *aij; NPPLSE *set[1+NBIT_MAX], *lse; NPPSED sed; int k, n, temp; double sum; /* compute the sum (sum |a[j]|) */ sum = 0.0; for (aij = row->ptr; aij != NULL; aij = aij->r_next) sum += fabs(aij->val); /* determine n, the number of bits in the sum */ temp = (int)sum; if ((double)temp != sum) return -1; /* integer arithmetic error */ for (n = 0; temp > 0; n++, temp >>= 1); xassert(0 <= n && n <= NBIT_MAX); /* build initial sets J[k], 1 <= k <= n; see (5) */ /* set[k] is a pointer to the list of literals in J[k] */ for (k = 1; k <= n; k++) set[k] = NULL; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { temp = (int)fabs(aij->val); xassert((int)temp == fabs(aij->val)); for (k = 1; temp > 0; k++, temp >>= 1) { if (temp & 1) { xassert(k <= n); lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); lse->lit.col = aij->col; lse->lit.neg = (aij->val > 0.0 ? 0 : 1); lse->next = set[k]; set[k] = lse; } } } /* main transformation loop */ for (k = 1; k <= n; k++) { /* reduce J[k] and set y[k] */ for (;;) { if (set[k] == NULL) { /* J[k] is empty */ /* set y[k] to constant false */ y[k].col = NULL, y[k].neg = 0; break; } if (set[k]->next == NULL) { /* J[k] contains one literal */ /* set y[k] to that literal */ y[k] = set[k]->lit; dmp_free_atom(npp->pool, set[k], sizeof(NPPLSE)); break; } if (set[k]->next->next == NULL) { /* J[k] contains two literals */ /* apply transformation (7) */ npp_sat_encode_sum2(npp, set[k], &sed); } else { /* J[k] contains at least three literals */ /* apply transformation (8) */ npp_sat_encode_sum3(npp, set[k], &sed); /* remove third literal from set[k] */ set[k] = remove_lse(npp, set[k], sed.z.col); } /* remove second literal from set[k] */ set[k] = remove_lse(npp, set[k], sed.y.col); /* remove first literal from set[k] */ set[k] = remove_lse(npp, set[k], sed.x.col); /* include new literal s to set[k] */ lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); lse->lit.col = sed.s, lse->lit.neg = 0; lse->next = set[k]; set[k] = lse; /* include new literal c to set[k+1] */ xassert(k < n); /* FIXME: can "overflow" happen? */ lse = dmp_get_atom(npp->pool, sizeof(NPPLSE)); lse->lit.col = sed.c, lse->lit.neg = 0; lse->next = set[k+1]; set[k+1] = lse; } } return n; } /*********************************************************************** * npp_sat_normalize_clause - normalize clause * * This routine normalizes the specified clause, which is a disjunction * of literals, by replacing multiple literals, which refer to the same * binary variable, with a single literal. * * On exit the routine returns the number of literals in the resulting * clause. However, if the specified clause includes both a literal and * its negation, the routine returns a negative value meaning that the * clause is equivalent to the value true. */ int npp_sat_normalize_clause(NPP *npp, int size, NPPLIT lit[]) { int j, k, new_size; xassert(npp == npp); xassert(size >= 0); new_size = 0; for (k = 1; k <= size; k++) { for (j = 1; j <= new_size; j++) { if (lit[k].col == lit[j].col) { /* lit[k] refers to the same variable as lit[j], which is already included in the resulting clause */ if (lit[k].neg == lit[j].neg) { /* ignore lit[k] due to the idempotent law */ goto skip; } else { /* lit[k] is NOT lit[j]; the clause is equivalent to the value true */ return -1; } } } /* include lit[k] in the resulting clause */ lit[++new_size] = lit[k]; skip: ; } return new_size; } /*********************************************************************** * npp_sat_encode_clause - translate clause to cover inequality * * Given a clause * * OR t[j], (1) * j in J * * where t[j] is a literal, i.e. t[j] = x[j] or t[j] = NOT x[j], this * routine translates it to the following equivalent cover inequality, * which is added to the transformed problem: * * sum t[j] >= 1, (2) * j in J * * where t[j] = x[j] or t[j] = 1 - x[j]. * * If necessary, the clause should be normalized before a call to this * routine. */ NPPROW *npp_sat_encode_clause(NPP *npp, int size, NPPLIT lit[]) { NPPROW *row; int k; xassert(size >= 1); row = npp_add_row(npp); row->lb = 1.0, row->ub = +DBL_MAX; for (k = 1; k <= size; k++) { xassert(lit[k].col != NULL); if (lit[k].neg == 0) npp_add_aij(npp, row, lit[k].col, +1.0); else if (lit[k].neg == 1) { npp_add_aij(npp, row, lit[k].col, -1.0); row->lb -= 1.0; } else xassert(lit != lit); } return row; } /*********************************************************************** * npp_sat_encode_geq - encode "not less than" constraint * * PURPOSE * * This routine translates to CNF the following constraint: * * n * sum 2**(k-1) * y[k] >= b, (1) * k=1 * * where y[k] is either a literal (i.e. y[k] = x[k] or y[k] = 1 - x[k]) * or constant false (zero), b is a given lower bound. * * ALGORITHM * * If b < 0, the constraint is redundant, so assume that b >= 0. Let * * n * b = sum 2**(k-1) b[k], (2) * k=1 * * where b[k] is k-th binary digit of b. (Note that if b >= 2**n and * therefore cannot be represented in the form (2), the constraint (1) * is infeasible.) In this case the condition (1) is equivalent to the * following condition: * * y[n] y[n-1] ... y[2] y[1] >= b[n] b[n-1] ... b[2] b[1], (3) * * where ">=" is understood lexicographically. * * Algorithmically the condition (3) can be tested as follows: * * for (k = n; k >= 1; k--) * { if (y[k] < b[k]) * y is less than b; * if (y[k] > b[k]) * y is greater than b; * } * y is equal to b; * * Thus, y is less than b iff there exists k, 1 <= k <= n, for which * the following condition is satisfied: * * y[n] = b[n] AND ... AND y[k+1] = b[k+1] AND y[k] < b[k]. (4) * * Negating the condition (4) we have that y is not less than b iff for * all k, 1 <= k <= n, the following condition is satisfied: * * y[n] != b[n] OR ... OR y[k+1] != b[k+1] OR y[k] >= b[k]. (5) * * Note that if b[k] = 0, the literal y[k] >= b[k] is always true, in * which case the entire clause (5) is true and can be omitted. * * RETURNS * * Normally the routine returns zero. However, if the constraint (1) is * infeasible, the routine returns non-zero. */ int npp_sat_encode_geq(NPP *npp, int n, NPPLIT y[], int rhs) { NPPLIT lit[1+NBIT_MAX]; int j, k, size, temp, b[1+NBIT_MAX]; xassert(0 <= n && n <= NBIT_MAX); /* if the constraint (1) is redundant, do nothing */ if (rhs < 0) return 0; /* determine binary digits of b according to (2) */ for (k = 1, temp = rhs; k <= n; k++, temp >>= 1) b[k] = temp & 1; if (temp != 0) { /* b >= 2**n; the constraint (1) is infeasible */ return 1; } /* main transformation loop */ for (k = 1; k <= n; k++) { /* build the clause (5) for current k */ size = 0; /* clause size = number of literals */ /* add literal y[k] >= b[k] */ if (b[k] == 0) { /* b[k] = 0 -> the literal is true */ goto skip; } else if (y[k].col == NULL) { /* y[k] = 0, b[k] = 1 -> the literal is false */ xassert(y[k].neg == 0); } else { /* add literal y[k] = 1 */ lit[++size] = y[k]; } for (j = k+1; j <= n; j++) { /* add literal y[j] != b[j] */ if (y[j].col == NULL) { xassert(y[j].neg == 0); if (b[j] == 0) { /* y[j] = 0, b[j] = 0 -> the literal is false */ continue; } else { /* y[j] = 0, b[j] = 1 -> the literal is true */ goto skip; } } else { lit[++size] = y[j]; if (b[j] != 0) lit[size].neg = 1 - lit[size].neg; } } /* normalize the clause */ size = npp_sat_normalize_clause(npp, size, lit); if (size < 0) { /* the clause is equivalent to the value true */ goto skip; } if (size == 0) { /* the clause is equivalent to the value false; this means that the constraint (1) is infeasible */ return 2; } /* translate the clause to corresponding cover inequality */ npp_sat_encode_clause(npp, size, lit); skip: ; } return 0; } /*********************************************************************** * npp_sat_encode_leq - encode "not greater than" constraint * * PURPOSE * * This routine translates to CNF the following constraint: * * n * sum 2**(k-1) * y[k] <= b, (1) * k=1 * * where y[k] is either a literal (i.e. y[k] = x[k] or y[k] = 1 - x[k]) * or constant false (zero), b is a given upper bound. * * ALGORITHM * * If b < 0, the constraint is infeasible, so assume that b >= 0. Let * * n * b = sum 2**(k-1) b[k], (2) * k=1 * * where b[k] is k-th binary digit of b. (Note that if b >= 2**n and * therefore cannot be represented in the form (2), the constraint (1) * is redundant.) In this case the condition (1) is equivalent to the * following condition: * * y[n] y[n-1] ... y[2] y[1] <= b[n] b[n-1] ... b[2] b[1], (3) * * where "<=" is understood lexicographically. * * Algorithmically the condition (3) can be tested as follows: * * for (k = n; k >= 1; k--) * { if (y[k] < b[k]) * y is less than b; * if (y[k] > b[k]) * y is greater than b; * } * y is equal to b; * * Thus, y is greater than b iff there exists k, 1 <= k <= n, for which * the following condition is satisfied: * * y[n] = b[n] AND ... AND y[k+1] = b[k+1] AND y[k] > b[k]. (4) * * Negating the condition (4) we have that y is not greater than b iff * for all k, 1 <= k <= n, the following condition is satisfied: * * y[n] != b[n] OR ... OR y[k+1] != b[k+1] OR y[k] <= b[k]. (5) * * Note that if b[k] = 1, the literal y[k] <= b[k] is always true, in * which case the entire clause (5) is true and can be omitted. * * RETURNS * * Normally the routine returns zero. However, if the constraint (1) is * infeasible, the routine returns non-zero. */ int npp_sat_encode_leq(NPP *npp, int n, NPPLIT y[], int rhs) { NPPLIT lit[1+NBIT_MAX]; int j, k, size, temp, b[1+NBIT_MAX]; xassert(0 <= n && n <= NBIT_MAX); /* check if the constraint (1) is infeasible */ if (rhs < 0) return 1; /* determine binary digits of b according to (2) */ for (k = 1, temp = rhs; k <= n; k++, temp >>= 1) b[k] = temp & 1; if (temp != 0) { /* b >= 2**n; the constraint (1) is redundant */ return 0; } /* main transformation loop */ for (k = 1; k <= n; k++) { /* build the clause (5) for current k */ size = 0; /* clause size = number of literals */ /* add literal y[k] <= b[k] */ if (b[k] == 1) { /* b[k] = 1 -> the literal is true */ goto skip; } else if (y[k].col == NULL) { /* y[k] = 0, b[k] = 0 -> the literal is true */ xassert(y[k].neg == 0); goto skip; } else { /* add literal y[k] = 0 */ lit[++size] = y[k]; lit[size].neg = 1 - lit[size].neg; } for (j = k+1; j <= n; j++) { /* add literal y[j] != b[j] */ if (y[j].col == NULL) { xassert(y[j].neg == 0); if (b[j] == 0) { /* y[j] = 0, b[j] = 0 -> the literal is false */ continue; } else { /* y[j] = 0, b[j] = 1 -> the literal is true */ goto skip; } } else { lit[++size] = y[j]; if (b[j] != 0) lit[size].neg = 1 - lit[size].neg; } } /* normalize the clause */ size = npp_sat_normalize_clause(npp, size, lit); if (size < 0) { /* the clause is equivalent to the value true */ goto skip; } if (size == 0) { /* the clause is equivalent to the value false; this means that the constraint (1) is infeasible */ return 2; } /* translate the clause to corresponding cover inequality */ npp_sat_encode_clause(npp, size, lit); skip: ; } return 0; } /*********************************************************************** * npp_sat_encode_row - encode constraint (row) of general type * * PURPOSE * * This routine translates to CNF the following constraint (row): * * L <= sum a[j] x[j] <= U, (1) * j * * where all x[j] are binary variables. * * ALGORITHM * * First, the routine performs substitution x[j] = t[j] for j in J+ * and x[j] = 1 - t[j] for j in J-, where J+ = { j : a[j] > 0 } and * J- = { j : a[j] < 0 }. This gives: * * L <= sum a[j] t[j] + sum a[j] (1 - t[j]) <= U ==> * j in J+ j in J- * * L' <= sum |a[j]| t[j] <= U', (2) * j * * where * * L' = L - sum a[j], U' = U - sum a[j]. (3) * j in J- j in J- * * (Actually only new bounds L' and U' are computed.) * * Then the routine translates to CNF the following equality: * * n * sum |a[j]| t[j] = sum 2**(k-1) * y[k], (4) * j k=1 * * where y[k] is either some t[j] or a new literal or a constant zero * (see the routine npp_sat_encode_sum_ax). * * Finally, the routine translates to CNF the following conditions: * * n * sum 2**(k-1) * y[k] >= L' (5) * k=1 * * and * * n * sum 2**(k-1) * y[k] <= U' (6) * k=1 * * (see the routines npp_sat_encode_geq and npp_sat_encode_leq). * * All resulting clauses are encoded as cover inequalities and included * into the transformed problem. * * Note that on exit the routine removes the specified constraint (row) * from the original problem. * * RETURNS * * The routine returns one of the following codes: * * 0 - translation was successful; * 1 - constraint (1) was found infeasible; * 2 - integer arithmetic error occured. */ int npp_sat_encode_row(NPP *npp, NPPROW *row) { NPPAIJ *aij; NPPLIT y[1+NBIT_MAX]; int n, rhs; double lb, ub; /* the row should not be free */ xassert(!(row->lb == -DBL_MAX && row->ub == +DBL_MAX)); /* compute new bounds L' and U' (3) */ lb = row->lb; ub = row->ub; for (aij = row->ptr; aij != NULL; aij = aij->r_next) { if (aij->val < 0.0) { if (lb != -DBL_MAX) lb -= aij->val; if (ub != -DBL_MAX) ub -= aij->val; } } /* encode the equality (4) */ n = npp_sat_encode_sum_ax(npp, row, y); if (n < 0) return 2; /* integer arithmetic error */ /* encode the condition (5) */ if (lb != -DBL_MAX) { rhs = (int)lb; if ((double)rhs != lb) return 2; /* integer arithmetic error */ if (npp_sat_encode_geq(npp, n, y, rhs) != 0) return 1; /* original constraint is infeasible */ } /* encode the condition (6) */ if (ub != +DBL_MAX) { rhs = (int)ub; if ((double)rhs != ub) return 2; /* integer arithmetic error */ if (npp_sat_encode_leq(npp, n, y, rhs) != 0) return 1; /* original constraint is infeasible */ } /* remove the specified row from the problem */ npp_del_row(npp, row); return 0; } /*********************************************************************** * npp_sat_encode_prob - encode 0-1 feasibility problem * * This routine translates the specified 0-1 feasibility problem to an * equivalent SAT-CNF problem. * * N.B. Currently this is a very crude implementation. * * RETURNS * * 0 success; * * GLP_ENOPFS primal/integer infeasibility detected; * * GLP_ERANGE integer overflow occured. */ int npp_sat_encode_prob(NPP *npp) { NPPROW *row, *next_row, *prev_row; NPPCOL *col, *next_col; int cover = 0, pack = 0, partn = 0, ret; /* process and remove free rows */ for (row = npp->r_head; row != NULL; row = next_row) { next_row = row->next; if (row->lb == -DBL_MAX && row->ub == +DBL_MAX) npp_sat_free_row(npp, row); } /* process and remove fixed columns */ for (col = npp->c_head; col != NULL; col = next_col) { next_col = col->next; if (col->lb == col->ub) xassert(npp_sat_fixed_col(npp, col) == 0); } /* only binary variables should remain */ for (col = npp->c_head; col != NULL; col = col->next) xassert(col->is_int && col->lb == 0.0 && col->ub == 1.0); /* new rows may be added to the end of the row list, so we walk from the end to beginning of the list */ for (row = npp->r_tail; row != NULL; row = prev_row) { prev_row = row->prev; /* process special cases */ ret = npp_sat_is_cover_ineq(npp, row); if (ret != 0) { /* row is covering inequality */ cover++; /* since it already encodes a clause, just transform it to canonical form */ if (ret == 2) { xassert(npp_sat_reverse_row(npp, row) == 0); ret = npp_sat_is_cover_ineq(npp, row); } xassert(ret == 1); continue; } ret = npp_sat_is_partn_eq(npp, row); if (ret != 0) { /* row is partitioning equality */ NPPROW *cov; NPPAIJ *aij; partn++; /* transform it to canonical form */ if (ret == 2) { xassert(npp_sat_reverse_row(npp, row) == 0); ret = npp_sat_is_partn_eq(npp, row); } xassert(ret == 1); /* and split it into covering and packing inequalities, both in canonical forms */ cov = npp_add_row(npp); cov->lb = row->lb, cov->ub = +DBL_MAX; for (aij = row->ptr; aij != NULL; aij = aij->r_next) npp_add_aij(npp, cov, aij->col, aij->val); xassert(npp_sat_is_cover_ineq(npp, cov) == 1); /* the cover inequality already encodes a clause and do not need any further processing */ row->lb = -DBL_MAX; xassert(npp_sat_is_pack_ineq(npp, row) == 1); /* the packing inequality will be processed below */ pack--; } ret = npp_sat_is_pack_ineq(npp, row); if (ret != 0) { /* row is packing inequality */ NPPROW *rrr; int nlit, desired_nlit = 4; pack++; /* transform it to canonical form */ if (ret == 2) { xassert(npp_sat_reverse_row(npp, row) == 0); ret = npp_sat_is_pack_ineq(npp, row); } xassert(ret == 1); /* process the packing inequality */ for (;;) { /* determine the number of literals in the remaining inequality */ nlit = npp_row_nnz(npp, row); if (nlit <= desired_nlit) break; /* split the current inequality into one having not more than desired_nlit literals and remaining one */ rrr = npp_sat_split_pack(npp, row, desired_nlit-1); /* translate the former inequality to CNF and remove it from the original problem */ npp_sat_encode_pack(npp, rrr); } /* translate the remaining inequality to CNF and remove it from the original problem */ npp_sat_encode_pack(npp, row); continue; } /* translate row of general type to CNF and remove it from the original problem */ ret = npp_sat_encode_row(npp, row); if (ret == 0) ; else if (ret == 1) ret = GLP_ENOPFS; else if (ret == 2) ret = GLP_ERANGE; else xassert(ret != ret); if (ret != 0) goto done; } ret = 0; if (cover != 0) xprintf("%d covering inequalities\n", cover); if (pack != 0) xprintf("%d packing inequalities\n", pack); if (partn != 0) xprintf("%d partitioning equalities\n", partn); done: return ret; } /* eof */ glpk-4.52.1/src/glprgr.c0000644000062000006210000001416512175147600014160 0ustar maomkpasswd/* glprgr.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_ERRNO #define _GLPSTD_STDIO #include "env.h" #include "glprgr.h" #define xfault xerror /*********************************************************************** * NAME * * rgr_write_bmp16 - write 16-color raster image in BMP file format * * SYNOPSIS * * #include "glprgr.h" * int rgr_write_bmp16(const char *fname, int m, int n, const char * map[]); * * DESCRIPTION * * The routine rgr_write_bmp16 writes 16-color raster image in * uncompressed BMP file format (Windows bitmap) to a binary file whose * name is specified by the character string fname. * * The parameters m and n specify, respectively, the number of rows and * the numbers of columns (i.e. height and width) of the raster image. * * The character array map has m*n elements. Elements map[0, ..., n-1] * correspond to the first (top) scanline, elements map[n, ..., 2*n-1] * correspond to the second scanline, etc. * * Each element of the array map specifies a color of the corresponding * pixel as 8-bit binary number XXXXIRGB, where four high-order bits (X) * are ignored, I is high intensity bit, R is red color bit, G is green * color bit, and B is blue color bit. Thus, all 16 possible colors are * coded as following hexadecimal numbers: * * 0x00 = black 0x08 = dark gray * 0x01 = blue 0x09 = bright blue * 0x02 = green 0x0A = bright green * 0x03 = cyan 0x0B = bright cyan * 0x04 = red 0x0C = bright red * 0x05 = magenta 0x0D = bright magenta * 0x06 = brown 0x0E = yellow * 0x07 = light gray 0x0F = white * * RETURNS * * If no error occured, the routine returns zero; otherwise, it prints * an appropriate error message and returns non-zero. */ static void put_byte(FILE *fp, int c) { fputc(c, fp); return; } static void put_word(FILE *fp, int w) { /* big endian */ put_byte(fp, w); put_byte(fp, w >> 8); return; } static void put_dword(FILE *fp, int d) { /* big endian */ put_word(fp, d); put_word(fp, d >> 16); return; } int rgr_write_bmp16(const char *fname, int m, int n, const char map[]) { FILE *fp; int offset, bmsize, i, j, b, ret = 0; if (!(1 <= m && m <= 32767)) xfault("rgr_write_bmp16: m = %d; invalid height\n", m); if (!(1 <= n && n <= 32767)) xfault("rgr_write_bmp16: n = %d; invalid width\n", n); fp = fopen(fname, "wb"); if (fp == NULL) { xprintf("rgr_write_bmp16: unable to create `%s' - %s\n", fname, strerror(errno)); ret = 1; goto fini; } offset = 14 + 40 + 16 * 4; bmsize = (4 * n + 31) / 32; /* struct BMPFILEHEADER (14 bytes) */ /* UINT bfType */ put_byte(fp, 'B'), put_byte(fp, 'M'); /* DWORD bfSize */ put_dword(fp, offset + bmsize * 4); /* UINT bfReserved1 */ put_word(fp, 0); /* UNIT bfReserved2 */ put_word(fp, 0); /* DWORD bfOffBits */ put_dword(fp, offset); /* struct BMPINFOHEADER (40 bytes) */ /* DWORD biSize */ put_dword(fp, 40); /* LONG biWidth */ put_dword(fp, n); /* LONG biHeight */ put_dword(fp, m); /* WORD biPlanes */ put_word(fp, 1); /* WORD biBitCount */ put_word(fp, 4); /* DWORD biCompression */ put_dword(fp, 0 /* BI_RGB */); /* DWORD biSizeImage */ put_dword(fp, 0); /* LONG biXPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */); /* LONG biYPelsPerMeter */ put_dword(fp, 2953 /* 75 dpi */); /* DWORD biClrUsed */ put_dword(fp, 0); /* DWORD biClrImportant */ put_dword(fp, 0); /* struct RGBQUAD (16 * 4 = 64 bytes) */ /* CGA-compatible colors: */ /* 0x00 = black */ put_dword(fp, 0x000000); /* 0x01 = blue */ put_dword(fp, 0x000080); /* 0x02 = green */ put_dword(fp, 0x008000); /* 0x03 = cyan */ put_dword(fp, 0x008080); /* 0x04 = red */ put_dword(fp, 0x800000); /* 0x05 = magenta */ put_dword(fp, 0x800080); /* 0x06 = brown */ put_dword(fp, 0x808000); /* 0x07 = light gray */ put_dword(fp, 0xC0C0C0); /* 0x08 = dark gray */ put_dword(fp, 0x808080); /* 0x09 = bright blue */ put_dword(fp, 0x0000FF); /* 0x0A = bright green */ put_dword(fp, 0x00FF00); /* 0x0B = bright cyan */ put_dword(fp, 0x00FFFF); /* 0x0C = bright red */ put_dword(fp, 0xFF0000); /* 0x0D = bright magenta */ put_dword(fp, 0xFF00FF); /* 0x0E = yellow */ put_dword(fp, 0xFFFF00); /* 0x0F = white */ put_dword(fp, 0xFFFFFF); /* pixel data bits */ b = 0; for (i = m - 1; i >= 0; i--) { for (j = 0; j < ((n + 7) / 8) * 8; j++) { b <<= 4; b |= (j < n ? map[i * n + j] & 15 : 0); if (j & 1) put_byte(fp, b); } } fflush(fp); if (ferror(fp)) { xprintf("rgr_write_bmp16: write error on `%s' - %s\n", fname, strerror(errno)); ret = 1; } fini: if (fp != NULL) fclose(fp); return ret; } /* eof */ glpk-4.52.1/src/glprgr.h0000644000062000006210000000246112175147600014161 0ustar maomkpasswd/* glprgr.h (raster graphics) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPRGR_H #define GLPRGR_H #define rgr_write_bmp16 _glp_rgr_write_bmp16 int rgr_write_bmp16(const char *fname, int m, int n, const char map[]); /* write 16-color raster image in BMP file format */ #endif /* eof */ glpk-4.52.1/src/glpscf.c0000644000062000006210000004760412175147600014145 0ustar maomkpasswd/* glpscf.c (Schur complement factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "glpscf.h" #define xfault xerror #define _GLPSCF_DEBUG 0 #define eps 1e-10 /*********************************************************************** * NAME * * scf_create_it - create Schur complement factorization * * SYNOPSIS * * #include "glpscf.h" * SCF *scf_create_it(int n_max); * * DESCRIPTION * * The routine scf_create_it creates the factorization of matrix C, * which initially has no rows and columns. * * The parameter n_max specifies the maximal order of matrix C to be * factorized, 1 <= n_max <= 32767. * * RETURNS * * The routine scf_create_it returns a pointer to the structure SCF, * which defines the factorization. */ SCF *scf_create_it(int n_max) { SCF *scf; #if _GLPSCF_DEBUG xprintf("scf_create_it: warning: debug mode enabled\n"); #endif if (!(1 <= n_max && n_max <= 32767)) xfault("scf_create_it: n_max = %d; invalid parameter\n", n_max); scf = xmalloc(sizeof(SCF)); scf->n_max = n_max; scf->n = 0; scf->f = xcalloc(1 + n_max * n_max, sizeof(double)); scf->u = xcalloc(1 + n_max * (n_max + 1) / 2, sizeof(double)); scf->p = xcalloc(1 + n_max, sizeof(int)); scf->t_opt = SCF_TBG; scf->rank = 0; #if _GLPSCF_DEBUG scf->c = xcalloc(1 + n_max * n_max, sizeof(double)); #else scf->c = NULL; #endif scf->w = xcalloc(1 + n_max, sizeof(double)); return scf; } /*********************************************************************** * The routine f_loc determines location of matrix element F[i,j] in * the one-dimensional array f. */ static int f_loc(SCF *scf, int i, int j) { int n_max = scf->n_max; int n = scf->n; xassert(1 <= i && i <= n); xassert(1 <= j && j <= n); return (i - 1) * n_max + j; } /*********************************************************************** * The routine u_loc determines location of matrix element U[i,j] in * the one-dimensional array u. */ static int u_loc(SCF *scf, int i, int j) { int n_max = scf->n_max; int n = scf->n; xassert(1 <= i && i <= n); xassert(i <= j && j <= n); return (i - 1) * n_max + j - i * (i - 1) / 2; } /*********************************************************************** * The routine bg_transform applies Bartels-Golub version of gaussian * elimination to restore triangular structure of matrix U. * * On entry matrix U has the following structure: * * 1 k n * 1 * * * * * * * * * * * . * * * * * * * * * * . . * * * * * * * * * . . . * * * * * * * * k . . . . * * * * * * * . . . . . * * * * * * . . . . . . * * * * * . . . . . . . * * * * . . . . . . . . * * * n . . . . # # # # # # * * where '#' is a row spike to be eliminated. * * Elements of n-th row are passed separately in locations un[k], ..., * un[n]. On exit the content of the array un is destroyed. * * REFERENCES * * R.H.Bartels, G.H.Golub, "The Simplex Method of Linear Programming * Using LU-decomposition", Comm. ACM, 12, pp. 266-68, 1969. */ static void bg_transform(SCF *scf, int k, double un[]) { int n = scf->n; double *f = scf->f; double *u = scf->u; int j, k1, kj, kk, n1, nj; double t; xassert(1 <= k && k <= n); /* main elimination loop */ for (k = k; k < n; k++) { /* determine location of U[k,k] */ kk = u_loc(scf, k, k); /* determine location of F[k,1] */ k1 = f_loc(scf, k, 1); /* determine location of F[n,1] */ n1 = f_loc(scf, n, 1); /* if |U[k,k]| < |U[n,k]|, interchange k-th and n-th rows to provide |U[k,k]| >= |U[n,k]| */ if (fabs(u[kk]) < fabs(un[k])) { /* interchange k-th and n-th rows of matrix U */ for (j = k, kj = kk; j <= n; j++, kj++) t = u[kj], u[kj] = un[j], un[j] = t; /* interchange k-th and n-th rows of matrix F to keep the main equality F * C = U * P */ for (j = 1, kj = k1, nj = n1; j <= n; j++, kj++, nj++) t = f[kj], f[kj] = f[nj], f[nj] = t; } /* now |U[k,k]| >= |U[n,k]| */ /* if U[k,k] is too small in the magnitude, replace U[k,k] and U[n,k] by exact zero */ if (fabs(u[kk]) < eps) u[kk] = un[k] = 0.0; /* if U[n,k] is already zero, elimination is not needed */ if (un[k] == 0.0) continue; /* compute gaussian multiplier t = U[n,k] / U[k,k] */ t = un[k] / u[kk]; /* apply gaussian elimination to nullify U[n,k] */ /* (n-th row of U) := (n-th row of U) - t * (k-th row of U) */ for (j = k+1, kj = kk+1; j <= n; j++, kj++) un[j] -= t * u[kj]; /* (n-th row of F) := (n-th row of F) - t * (k-th row of F) to keep the main equality F * C = U * P */ for (j = 1, kj = k1, nj = n1; j <= n; j++, kj++, nj++) f[nj] -= t * f[kj]; } /* if U[n,n] is too small in the magnitude, replace it by exact zero */ if (fabs(un[n]) < eps) un[n] = 0.0; /* store U[n,n] in a proper location */ u[u_loc(scf, n, n)] = un[n]; return; } /*********************************************************************** * The routine givens computes the parameters of Givens plane rotation * c = cos(teta) and s = sin(teta) such that: * * ( c -s ) ( a ) ( r ) * ( ) ( ) = ( ) , * ( s c ) ( b ) ( 0 ) * * where a and b are given scalars. * * REFERENCES * * G.H.Golub, C.F.Van Loan, "Matrix Computations", 2nd ed. */ static void givens(double a, double b, double *c, double *s) { double t; if (b == 0.0) (*c) = 1.0, (*s) = 0.0; else if (fabs(a) <= fabs(b)) t = - a / b, (*s) = 1.0 / sqrt(1.0 + t * t), (*c) = (*s) * t; else t = - b / a, (*c) = 1.0 / sqrt(1.0 + t * t), (*s) = (*c) * t; return; } /*---------------------------------------------------------------------- * The routine gr_transform applies Givens plane rotations to restore * triangular structure of matrix U. * * On entry matrix U has the following structure: * * 1 k n * 1 * * * * * * * * * * * . * * * * * * * * * * . . * * * * * * * * * . . . * * * * * * * * k . . . . * * * * * * * . . . . . * * * * * * . . . . . . * * * * * . . . . . . . * * * * . . . . . . . . * * * n . . . . # # # # # # * * where '#' is a row spike to be eliminated. * * Elements of n-th row are passed separately in locations un[k], ..., * un[n]. On exit the content of the array un is destroyed. * * REFERENCES * * R.H.Bartels, G.H.Golub, "The Simplex Method of Linear Programming * Using LU-decomposition", Comm. ACM, 12, pp. 266-68, 1969. */ static void gr_transform(SCF *scf, int k, double un[]) { int n = scf->n; double *f = scf->f; double *u = scf->u; int j, k1, kj, kk, n1, nj; double c, s; xassert(1 <= k && k <= n); /* main elimination loop */ for (k = k; k < n; k++) { /* determine location of U[k,k] */ kk = u_loc(scf, k, k); /* determine location of F[k,1] */ k1 = f_loc(scf, k, 1); /* determine location of F[n,1] */ n1 = f_loc(scf, n, 1); /* if both U[k,k] and U[n,k] are too small in the magnitude, replace them by exact zero */ if (fabs(u[kk]) < eps && fabs(un[k]) < eps) u[kk] = un[k] = 0.0; /* if U[n,k] is already zero, elimination is not needed */ if (un[k] == 0.0) continue; /* compute the parameters of Givens plane rotation */ givens(u[kk], un[k], &c, &s); /* apply Givens rotation to k-th and n-th rows of matrix U */ for (j = k, kj = kk; j <= n; j++, kj++) { double ukj = u[kj], unj = un[j]; u[kj] = c * ukj - s * unj; un[j] = s * ukj + c * unj; } /* apply Givens rotation to k-th and n-th rows of matrix F to keep the main equality F * C = U * P */ for (j = 1, kj = k1, nj = n1; j <= n; j++, kj++, nj++) { double fkj = f[kj], fnj = f[nj]; f[kj] = c * fkj - s * fnj; f[nj] = s * fkj + c * fnj; } } /* if U[n,n] is too small in the magnitude, replace it by exact zero */ if (fabs(un[n]) < eps) un[n] = 0.0; /* store U[n,n] in a proper location */ u[u_loc(scf, n, n)] = un[n]; return; } /*********************************************************************** * The routine transform restores triangular structure of matrix U. * It is a driver to the routines bg_transform and gr_transform (see * comments to these routines above). */ static void transform(SCF *scf, int k, double un[]) { switch (scf->t_opt) { case SCF_TBG: bg_transform(scf, k, un); break; case SCF_TGR: gr_transform(scf, k, un); break; default: xassert(scf != scf); } return; } /*********************************************************************** * The routine estimate_rank estimates the rank of matrix C. * * Since all transformations applied to matrix F are non-singular, * and F is assumed to be well conditioned, from the main equaility * F * C = U * P it follows that rank(C) = rank(U), where rank(U) is * estimated as the number of non-zero diagonal elements of U. */ static int estimate_rank(SCF *scf) { int n_max = scf->n_max; int n = scf->n; double *u = scf->u; int i, ii, inc, rank = 0; for (i = 1, ii = u_loc(scf, i, i), inc = n_max; i <= n; i++, ii += inc, inc--) if (u[ii] != 0.0) rank++; return rank; } #if _GLPSCF_DEBUG /*********************************************************************** * The routine check_error computes the maximal relative error between * left- and right-hand sides of the main equality F * C = U * P. (This * routine is intended only for debugging.) */ static void check_error(SCF *scf, const char *func) { int n = scf->n; double *f = scf->f; double *u = scf->u; int *p = scf->p; double *c = scf->c; int i, j, k; double d, dmax = 0.0, s, t; xassert(c != NULL); for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { /* compute element (i,j) of product F * C */ s = 0.0; for (k = 1; k <= n; k++) s += f[f_loc(scf, i, k)] * c[f_loc(scf, k, j)]; /* compute element (i,j) of product U * P */ k = p[j]; t = (i <= k ? u[u_loc(scf, i, k)] : 0.0); /* compute the maximal relative error */ d = fabs(s - t) / (1.0 + fabs(t)); if (dmax < d) dmax = d; } } if (dmax > 1e-8) xprintf("%s: dmax = %g; relative error too large\n", func, dmax); return; } #endif /*********************************************************************** * NAME * * scf_update_exp - update factorization on expanding C * * SYNOPSIS * * #include "glpscf.h" * int scf_update_exp(SCF *scf, const double x[], const double y[], * double z); * * DESCRIPTION * * The routine scf_update_exp updates the factorization of matrix C on * expanding it by adding a new row and column as follows: * * ( C x ) * new C = ( ) * ( y' z ) * * where x[1,...,n] is a new column, y[1,...,n] is a new row, and z is * a new diagonal element. * * If on entry the factorization is empty, the parameters x and y can * be specified as NULL. * * RETURNS * * 0 The factorization has been successfully updated. * * SCF_ESING * The factorization has been successfully updated, however, new * matrix C is singular within working precision. Note that the new * factorization remains valid. * * SCF_ELIMIT * There is not enough room to expand the factorization, because * n = n_max. The factorization remains unchanged. * * ALGORITHM * * We can see that: * * ( F 0 ) ( C x ) ( FC Fx ) ( UP Fx ) * ( ) ( ) = ( ) = ( ) = * ( 0 1 ) ( y' z ) ( y' z ) ( y' z ) * * ( U Fx ) ( P 0 ) * = ( ) ( ), * ( y'P' z ) ( 0 1 ) * * therefore to keep the main equality F * C = U * P we can take: * * ( F 0 ) ( U Fx ) ( P 0 ) * new F = ( ), new U = ( ), new P = ( ), * ( 0 1 ) ( y'P' z ) ( 0 1 ) * * and eliminate the row spike y'P' in the last row of new U to restore * its upper triangular structure. */ int scf_update_exp(SCF *scf, const double x[], const double y[], double z) { int n_max = scf->n_max; int n = scf->n; double *f = scf->f; double *u = scf->u; int *p = scf->p; #if _GLPSCF_DEBUG double *c = scf->c; #endif double *un = scf->w; int i, ij, in, j, k, nj, ret = 0; double t; /* check if the factorization can be expanded */ if (n == n_max) { /* there is not enough room */ ret = SCF_ELIMIT; goto done; } /* increase the order of the factorization */ scf->n = ++n; /* fill new zero column of matrix F */ for (i = 1, in = f_loc(scf, i, n); i < n; i++, in += n_max) f[in] = 0.0; /* fill new zero row of matrix F */ for (j = 1, nj = f_loc(scf, n, j); j < n; j++, nj++) f[nj] = 0.0; /* fill new unity diagonal element of matrix F */ f[f_loc(scf, n, n)] = 1.0; /* compute new column of matrix U, which is (old F) * x */ for (i = 1; i < n; i++) { /* u[i,n] := (i-th row of old F) * x */ t = 0.0; for (j = 1, ij = f_loc(scf, i, 1); j < n; j++, ij++) t += f[ij] * x[j]; u[u_loc(scf, i, n)] = t; } /* compute new (spiked) row of matrix U, which is (old P) * y */ for (j = 1; j < n; j++) un[j] = y[p[j]]; /* store new diagonal element of matrix U, which is z */ un[n] = z; /* expand matrix P */ p[n] = n; #if _GLPSCF_DEBUG /* expand matrix C */ /* fill its new column, which is x */ for (i = 1, in = f_loc(scf, i, n); i < n; i++, in += n_max) c[in] = x[i]; /* fill its new row, which is y */ for (j = 1, nj = f_loc(scf, n, j); j < n; j++, nj++) c[nj] = y[j]; /* fill its new diagonal element, which is z */ c[f_loc(scf, n, n)] = z; #endif /* restore upper triangular structure of matrix U */ for (k = 1; k < n; k++) if (un[k] != 0.0) break; transform(scf, k, un); /* estimate the rank of matrices C and U */ scf->rank = estimate_rank(scf); if (scf->rank != n) ret = SCF_ESING; #if _GLPSCF_DEBUG /* check that the factorization is accurate enough */ check_error(scf, "scf_update_exp"); #endif done: return ret; } /*********************************************************************** * The routine solve solves the system C * x = b. * * From the main equation F * C = U * P it follows that: * * C * x = b => F * C * x = F * b => U * P * x = F * b => * * P * x = inv(U) * F * b => x = P' * inv(U) * F * b. * * On entry the array x contains right-hand side vector b. On exit this * array contains solution vector x. */ static void solve(SCF *scf, double x[]) { int n = scf->n; double *f = scf->f; double *u = scf->u; int *p = scf->p; double *y = scf->w; int i, j, ij; double t; /* y := F * b */ for (i = 1; i <= n; i++) { /* y[i] = (i-th row of F) * b */ t = 0.0; for (j = 1, ij = f_loc(scf, i, 1); j <= n; j++, ij++) t += f[ij] * x[j]; y[i] = t; } /* y := inv(U) * y */ for (i = n; i >= 1; i--) { t = y[i]; for (j = n, ij = u_loc(scf, i, n); j > i; j--, ij--) t -= u[ij] * y[j]; y[i] = t / u[ij]; } /* x := P' * y */ for (i = 1; i <= n; i++) x[p[i]] = y[i]; return; } /*********************************************************************** * The routine tsolve solves the transposed system C' * x = b. * * From the main equation F * C = U * P it follows that: * * C' * F' = P' * U', * * therefore: * * C' * x = b => C' * F' * inv(F') * x = b => * * P' * U' * inv(F') * x = b => U' * inv(F') * x = P * b => * * inv(F') * x = inv(U') * P * b => x = F' * inv(U') * P * b. * * On entry the array x contains right-hand side vector b. On exit this * array contains solution vector x. */ static void tsolve(SCF *scf, double x[]) { int n = scf->n; double *f = scf->f; double *u = scf->u; int *p = scf->p; double *y = scf->w; int i, j, ij; double t; /* y := P * b */ for (i = 1; i <= n; i++) y[i] = x[p[i]]; /* y := inv(U') * y */ for (i = 1; i <= n; i++) { /* compute y[i] */ ij = u_loc(scf, i, i); t = (y[i] /= u[ij]); /* substitute y[i] in other equations */ for (j = i+1, ij++; j <= n; j++, ij++) y[j] -= u[ij] * t; } /* x := F' * y (computed as linear combination of rows of F) */ for (j = 1; j <= n; j++) x[j] = 0.0; for (i = 1; i <= n; i++) { t = y[i]; /* coefficient of linear combination */ for (j = 1, ij = f_loc(scf, i, 1); j <= n; j++, ij++) x[j] += f[ij] * t; } return; } /*********************************************************************** * NAME * * scf_solve_it - solve either system C * x = b or C' * x = b * * SYNOPSIS * * #include "glpscf.h" * void scf_solve_it(SCF *scf, int tr, double x[]); * * DESCRIPTION * * The routine scf_solve_it solves either the system C * x = b (if tr * is zero) or the system C' * x = b, where C' is a matrix transposed * to C (if tr is non-zero). C is assumed to be non-singular. * * On entry the array x should contain the right-hand side vector b in * locations x[1], ..., x[n], where n is the order of matrix C. On exit * the array x contains the solution vector x in the same locations. */ void scf_solve_it(SCF *scf, int tr, double x[]) { if (scf->rank < scf->n) xfault("scf_solve_it: singular matrix\n"); if (!tr) solve(scf, x); else tsolve(scf, x); return; } void scf_reset_it(SCF *scf) { /* reset factorization for empty matrix C */ scf->n = scf->rank = 0; return; } /*********************************************************************** * NAME * * scf_delete_it - delete Schur complement factorization * * SYNOPSIS * * #include "glpscf.h" * void scf_delete_it(SCF *scf); * * DESCRIPTION * * The routine scf_delete_it deletes the specified factorization and * frees all the memory allocated to this object. */ void scf_delete_it(SCF *scf) { xfree(scf->f); xfree(scf->u); xfree(scf->p); #if _GLPSCF_DEBUG xfree(scf->c); #endif xfree(scf->w); xfree(scf); return; } /* eof */ glpk-4.52.1/src/glpscf.h0000644000062000006210000001076012175147600014143 0ustar maomkpasswd/* glpscf.h (Schur complement factorization) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPSCF_H #define GLPSCF_H /*********************************************************************** * The structure SCF defines the following factorization of a square * nxn matrix C (which is the Schur complement): * * F * C = U * P, * * where F is a square transforming matrix, U is an upper triangular * matrix, P is a permutation matrix. * * It is assumed that matrix C is small and dense, so matrices F and U * are stored in the dense format by rows as follows: * * 1 n n_max 1 n n_max * 1 * * * * * * x x x x 1 * * * * * * x x x x * * * * * * * x x x x . * * * * * x x x x * * * * * * * x x x x . . * * * * x x x x * * * * * * * x x x x . . . * * * x x x x * * * * * * * x x x x . . . . * * x x x x * n * * * * * * x x x x n . . . . . * x x x x * x x x x x x x x x x . . . . . . x x x x * x x x x x x x x x x . . . . . . . x x x * x x x x x x x x x x . . . . . . . . x x * n_max x x x x x x x x x x n_max . . . . . . . . . x * * matrix F matrix U * * where '*' are matrix elements, 'x' are reserved locations. * * Permutation matrix P is stored in row-like format. * * Matrix C normally is not stored. * * REFERENCES * * 1. M.A.Saunders, "LUSOL: A basis package for constrained optimiza- * tion," SCCM, Stanford University, 2006. * * 2. M.A.Saunders, "Notes 5: Basis Updates," CME 318, Stanford Univer- * sity, Spring 2006. * * 3. M.A.Saunders, "Notes 6: LUSOL---a Basis Factorization Package," * ibid. */ typedef struct SCF SCF; struct SCF { /* Schur complement factorization */ int n_max; /* maximal order of matrices C, F, U, P; n_max >= 1 */ int n; /* current order of matrices C, F, U, P; n >= 0 */ double *f; /* double f[1+n_max*n_max]; */ /* matrix F stored by rows */ double *u; /* double u[1+n_max*(n_max+1)/2]; */ /* upper triangle of matrix U stored by rows */ int *p; /* int p[1+n_max]; */ /* matrix P; p[i] = j means that P[i,j] = 1 */ int t_opt; /* type of transformation used to restore triangular structure of matrix U: */ #define SCF_TBG 1 /* Bartels-Golub elimination */ #define SCF_TGR 2 /* Givens plane rotation */ int rank; /* estimated rank of matrices C and U */ double *c; /* double c[1+n_max*n_max]; */ /* matrix C stored in the same format as matrix F and used only for debugging; normally this array is not allocated */ double *w; /* double w[1+n_max]; */ /* working array */ }; /* return codes: */ #define SCF_ESING 1 /* singular matrix */ #define SCF_ELIMIT 2 /* update limit reached */ #define scf_create_it _glp_scf_create_it SCF *scf_create_it(int n_max); /* create Schur complement factorization */ #define scf_update_exp _glp_scf_update_exp int scf_update_exp(SCF *scf, const double x[], const double y[], double z); /* update factorization on expanding C */ #define scf_solve_it _glp_scf_solve_it void scf_solve_it(SCF *scf, int tr, double x[]); /* solve either system C * x = b or C' * x = b */ #define scf_reset_it _glp_scf_reset_it void scf_reset_it(SCF *scf); /* reset factorization for empty matrix C */ #define scf_delete_it _glp_scf_delete_it void scf_delete_it(SCF *scf); /* delete Schur complement factorization */ #endif /* eof */ glpk-4.52.1/src/glpscl.c0000644000062000006210000003732512175147600014152 0ustar maomkpasswd/* glpscl.c (problem scaling routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpapi.h" #include "glplib.h" /*********************************************************************** * min_row_aij - determine minimal |a[i,j]| in i-th row * * This routine returns minimal magnitude of (non-zero) constraint * coefficients in i-th row of the constraint matrix. * * If the parameter scaled is zero, the original constraint matrix A is * assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. * * If i-th row of the matrix is empty, the routine returns 1. */ static double min_row_aij(glp_prob *lp, int i, int scaled) { GLPAIJ *aij; double min_aij, temp; xassert(1 <= i && i <= lp->m); min_aij = 1.0; for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) { temp = fabs(aij->val); if (scaled) temp *= (aij->row->rii * aij->col->sjj); if (aij->r_prev == NULL || min_aij > temp) min_aij = temp; } return min_aij; } /*********************************************************************** * max_row_aij - determine maximal |a[i,j]| in i-th row * * This routine returns maximal magnitude of (non-zero) constraint * coefficients in i-th row of the constraint matrix. * * If the parameter scaled is zero, the original constraint matrix A is * assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. * * If i-th row of the matrix is empty, the routine returns 1. */ static double max_row_aij(glp_prob *lp, int i, int scaled) { GLPAIJ *aij; double max_aij, temp; xassert(1 <= i && i <= lp->m); max_aij = 1.0; for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) { temp = fabs(aij->val); if (scaled) temp *= (aij->row->rii * aij->col->sjj); if (aij->r_prev == NULL || max_aij < temp) max_aij = temp; } return max_aij; } /*********************************************************************** * min_col_aij - determine minimal |a[i,j]| in j-th column * * This routine returns minimal magnitude of (non-zero) constraint * coefficients in j-th column of the constraint matrix. * * If the parameter scaled is zero, the original constraint matrix A is * assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. * * If j-th column of the matrix is empty, the routine returns 1. */ static double min_col_aij(glp_prob *lp, int j, int scaled) { GLPAIJ *aij; double min_aij, temp; xassert(1 <= j && j <= lp->n); min_aij = 1.0; for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) { temp = fabs(aij->val); if (scaled) temp *= (aij->row->rii * aij->col->sjj); if (aij->c_prev == NULL || min_aij > temp) min_aij = temp; } return min_aij; } /*********************************************************************** * max_col_aij - determine maximal |a[i,j]| in j-th column * * This routine returns maximal magnitude of (non-zero) constraint * coefficients in j-th column of the constraint matrix. * * If the parameter scaled is zero, the original constraint matrix A is * assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. * * If j-th column of the matrix is empty, the routine returns 1. */ static double max_col_aij(glp_prob *lp, int j, int scaled) { GLPAIJ *aij; double max_aij, temp; xassert(1 <= j && j <= lp->n); max_aij = 1.0; for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) { temp = fabs(aij->val); if (scaled) temp *= (aij->row->rii * aij->col->sjj); if (aij->c_prev == NULL || max_aij < temp) max_aij = temp; } return max_aij; } /*********************************************************************** * min_mat_aij - determine minimal |a[i,j]| in constraint matrix * * This routine returns minimal magnitude of (non-zero) constraint * coefficients in the constraint matrix. * * If the parameter scaled is zero, the original constraint matrix A is * assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. * * If the matrix is empty, the routine returns 1. */ static double min_mat_aij(glp_prob *lp, int scaled) { int i; double min_aij, temp; min_aij = 1.0; for (i = 1; i <= lp->m; i++) { temp = min_row_aij(lp, i, scaled); if (i == 1 || min_aij > temp) min_aij = temp; } return min_aij; } /*********************************************************************** * max_mat_aij - determine maximal |a[i,j]| in constraint matrix * * This routine returns maximal magnitude of (non-zero) constraint * coefficients in the constraint matrix. * * If the parameter scaled is zero, the original constraint matrix A is * assumed. Otherwise, the scaled constraint matrix R*A*S is assumed. * * If the matrix is empty, the routine returns 1. */ static double max_mat_aij(glp_prob *lp, int scaled) { int i; double max_aij, temp; max_aij = 1.0; for (i = 1; i <= lp->m; i++) { temp = max_row_aij(lp, i, scaled); if (i == 1 || max_aij < temp) max_aij = temp; } return max_aij; } /*********************************************************************** * eq_scaling - perform equilibration scaling * * This routine performs equilibration scaling of rows and columns of * the constraint matrix. * * If the parameter flag is zero, the routine scales rows at first and * then columns. Otherwise, the routine scales columns and then rows. * * Rows are scaled as follows: * * n * a'[i,j] = a[i,j] / max |a[i,j]|, i = 1,...,m. * j=1 * * This makes the infinity (maximum) norm of each row of the matrix * equal to 1. * * Columns are scaled as follows: * * m * a'[i,j] = a[i,j] / max |a[i,j]|, j = 1,...,n. * i=1 * * This makes the infinity (maximum) norm of each column of the matrix * equal to 1. */ static void eq_scaling(glp_prob *lp, int flag) { int i, j, pass; double temp; xassert(flag == 0 || flag == 1); for (pass = 0; pass <= 1; pass++) { if (pass == flag) { /* scale rows */ for (i = 1; i <= lp->m; i++) { temp = max_row_aij(lp, i, 1); glp_set_rii(lp, i, glp_get_rii(lp, i) / temp); } } else { /* scale columns */ for (j = 1; j <= lp->n; j++) { temp = max_col_aij(lp, j, 1); glp_set_sjj(lp, j, glp_get_sjj(lp, j) / temp); } } } return; } /*********************************************************************** * gm_scaling - perform geometric mean scaling * * This routine performs geometric mean scaling of rows and columns of * the constraint matrix. * * If the parameter flag is zero, the routine scales rows at first and * then columns. Otherwise, the routine scales columns and then rows. * * Rows are scaled as follows: * * a'[i,j] = a[i,j] / sqrt(alfa[i] * beta[i]), i = 1,...,m, * * where: * n n * alfa[i] = min |a[i,j]|, beta[i] = max |a[i,j]|. * j=1 j=1 * * This allows decreasing the ratio beta[i] / alfa[i] for each row of * the matrix. * * Columns are scaled as follows: * * a'[i,j] = a[i,j] / sqrt(alfa[j] * beta[j]), j = 1,...,n, * * where: * m m * alfa[j] = min |a[i,j]|, beta[j] = max |a[i,j]|. * i=1 i=1 * * This allows decreasing the ratio beta[j] / alfa[j] for each column * of the matrix. */ static void gm_scaling(glp_prob *lp, int flag) { int i, j, pass; double temp; xassert(flag == 0 || flag == 1); for (pass = 0; pass <= 1; pass++) { if (pass == flag) { /* scale rows */ for (i = 1; i <= lp->m; i++) { temp = min_row_aij(lp, i, 1) * max_row_aij(lp, i, 1); glp_set_rii(lp, i, glp_get_rii(lp, i) / sqrt(temp)); } } else { /* scale columns */ for (j = 1; j <= lp->n; j++) { temp = min_col_aij(lp, j, 1) * max_col_aij(lp, j, 1); glp_set_sjj(lp, j, glp_get_sjj(lp, j) / sqrt(temp)); } } } return; } /*********************************************************************** * max_row_ratio - determine worst scaling "quality" for rows * * This routine returns the worst scaling "quality" for rows of the * currently scaled constraint matrix: * * m * ratio = max ratio[i], * i=1 * where: * n n * ratio[i] = max |a[i,j]| / min |a[i,j]|, 1 <= i <= m, * j=1 j=1 * * is the scaling "quality" of i-th row. */ static double max_row_ratio(glp_prob *lp) { int i; double ratio, temp; ratio = 1.0; for (i = 1; i <= lp->m; i++) { temp = max_row_aij(lp, i, 1) / min_row_aij(lp, i, 1); if (i == 1 || ratio < temp) ratio = temp; } return ratio; } /*********************************************************************** * max_col_ratio - determine worst scaling "quality" for columns * * This routine returns the worst scaling "quality" for columns of the * currently scaled constraint matrix: * * n * ratio = max ratio[j], * j=1 * where: * m m * ratio[j] = max |a[i,j]| / min |a[i,j]|, 1 <= j <= n, * i=1 i=1 * * is the scaling "quality" of j-th column. */ static double max_col_ratio(glp_prob *lp) { int j; double ratio, temp; ratio = 1.0; for (j = 1; j <= lp->n; j++) { temp = max_col_aij(lp, j, 1) / min_col_aij(lp, j, 1); if (j == 1 || ratio < temp) ratio = temp; } return ratio; } /*********************************************************************** * gm_iterate - perform iterative geometric mean scaling * * This routine performs iterative geometric mean scaling of rows and * columns of the constraint matrix. * * The parameter it_max specifies the maximal number of iterations. * Recommended value of it_max is 15. * * The parameter tau specifies a minimal improvement of the scaling * "quality" on each iteration, 0 < tau < 1. It means than the scaling * process continues while the following condition is satisfied: * * ratio[k] <= tau * ratio[k-1], * * where ratio = max |a[i,j]| / min |a[i,j]| is the scaling "quality" * to be minimized, k is the iteration number. Recommended value of tau * is 0.90. */ static void gm_iterate(glp_prob *lp, int it_max, double tau) { int k, flag; double ratio = 0.0, r_old; /* if the scaling "quality" for rows is better than for columns, the rows are scaled first; otherwise, the columns are scaled first */ flag = (max_row_ratio(lp) > max_col_ratio(lp)); for (k = 1; k <= it_max; k++) { /* save the scaling "quality" from previous iteration */ r_old = ratio; /* determine the current scaling "quality" */ ratio = max_mat_aij(lp, 1) / min_mat_aij(lp, 1); #if 0 xprintf("k = %d; ratio = %g\n", k, ratio); #endif /* if improvement is not enough, terminate scaling */ if (k > 1 && ratio > tau * r_old) break; /* otherwise, perform another iteration */ gm_scaling(lp, flag); } return; } /*********************************************************************** * NAME * * scale_prob - scale problem data * * SYNOPSIS * * #include "glpscl.h" * void scale_prob(glp_prob *lp, int flags); * * DESCRIPTION * * The routine scale_prob performs automatic scaling of problem data * for the specified problem object. */ static void scale_prob(glp_prob *lp, int flags) { static const char *fmt = "%s: min|aij| = %10.3e max|aij| = %10.3e ratio = %10.3e\n"; double min_aij, max_aij, ratio; xprintf("Scaling...\n"); /* cancel the current scaling effect */ glp_unscale_prob(lp); /* report original scaling "quality" */ min_aij = min_mat_aij(lp, 1); max_aij = max_mat_aij(lp, 1); ratio = max_aij / min_aij; xprintf(fmt, " A", min_aij, max_aij, ratio); /* check if the problem is well scaled */ if (min_aij >= 0.10 && max_aij <= 10.0) { xprintf("Problem data seem to be well scaled\n"); /* skip scaling, if required */ if (flags & GLP_SF_SKIP) goto done; } /* perform iterative geometric mean scaling, if required */ if (flags & GLP_SF_GM) { gm_iterate(lp, 15, 0.90); min_aij = min_mat_aij(lp, 1); max_aij = max_mat_aij(lp, 1); ratio = max_aij / min_aij; xprintf(fmt, "GM", min_aij, max_aij, ratio); } /* perform equilibration scaling, if required */ if (flags & GLP_SF_EQ) { eq_scaling(lp, max_row_ratio(lp) > max_col_ratio(lp)); min_aij = min_mat_aij(lp, 1); max_aij = max_mat_aij(lp, 1); ratio = max_aij / min_aij; xprintf(fmt, "EQ", min_aij, max_aij, ratio); } /* round scale factors to nearest power of two, if required */ if (flags & GLP_SF_2N) { int i, j; for (i = 1; i <= lp->m; i++) glp_set_rii(lp, i, round2n(glp_get_rii(lp, i))); for (j = 1; j <= lp->n; j++) glp_set_sjj(lp, j, round2n(glp_get_sjj(lp, j))); min_aij = min_mat_aij(lp, 1); max_aij = max_mat_aij(lp, 1); ratio = max_aij / min_aij; xprintf(fmt, "2N", min_aij, max_aij, ratio); } done: return; } /*********************************************************************** * NAME * * glp_scale_prob - scale problem data * * SYNOPSIS * * void glp_scale_prob(glp_prob *lp, int flags); * * DESCRIPTION * * The routine glp_scale_prob performs automatic scaling of problem * data for the specified problem object. * * The parameter flags specifies scaling options used by the routine. * Options can be combined with the bitwise OR operator and may be the * following: * * GLP_SF_GM perform geometric mean scaling; * GLP_SF_EQ perform equilibration scaling; * GLP_SF_2N round scale factors to nearest power of two; * GLP_SF_SKIP skip scaling, if the problem is well scaled. * * The parameter flags may be specified as GLP_SF_AUTO, in which case * the routine chooses scaling options automatically. */ void glp_scale_prob(glp_prob *lp, int flags) { if (flags & ~(GLP_SF_GM | GLP_SF_EQ | GLP_SF_2N | GLP_SF_SKIP | GLP_SF_AUTO)) xerror("glp_scale_prob: flags = 0x%02X; invalid scaling option" "s\n", flags); if (flags & GLP_SF_AUTO) flags = (GLP_SF_GM | GLP_SF_EQ | GLP_SF_SKIP); scale_prob(lp, flags); return; } /* eof */ glpk-4.52.1/src/glpsdf.c0000644000062000006210000001601112175147600014132 0ustar maomkpasswd/* glpsdf.c (plain data file reading routines) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #if 1 /* 11/VI-2013 */ #include "env2.h" #endif #include "glpapi.h" #include "glpsdf.h" #include "glplib.h" struct glp_data { /* plain data file */ char *fname; /* name of data file */ XFILE *fp; /* stream assigned to data file */ void *jump; /* jmp_buf jump; */ /* label for go to in case of error */ int count; /* line count */ int c; /* current character of XEOF */ char item[255+1]; /* current data item */ }; static void next_char(glp_data *data); glp_data *glp_sdf_open_file(const char *fname) { /* open plain data file */ glp_data *data = NULL; XFILE *fp; jmp_buf jump; fp = xfopen(fname, "r"); if (fp == NULL) { xprintf("Unable to open `%s' - %s\n", fname, xerrmsg()); goto done; } data = xmalloc(sizeof(glp_data)); data->fname = xmalloc(strlen(fname)+1); strcpy(data->fname, fname); data->fp = fp; data->jump = NULL; data->count = 0; data->c = '\n'; data->item[0] = '\0'; /* read the very first character */ if (setjmp(jump)) { glp_sdf_close_file(data); data = NULL; goto done; } data->jump = jump; next_char(data); data->jump = NULL; done: return data; } void glp_sdf_set_jump(glp_data *data, void *jump) { /* set up error handling */ data->jump = jump; return; } void glp_sdf_error(glp_data *data, const char *fmt, ...) { /* print error message */ va_list arg; xprintf("%s:%d: ", data->fname, data->count); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); if (data->jump == NULL) xerror(""); else longjmp(data->jump, 1); /* no return */ } void glp_sdf_warning(glp_data *data, const char *fmt, ...) { /* print warning message */ va_list arg; xprintf("%s:%d: warning: ", data->fname, data->count); va_start(arg, fmt); xvprintf(fmt, arg); va_end(arg); return; } static void next_char(glp_data *data) { /* read next character */ int c; if (data->c == XEOF) glp_sdf_error(data, "unexpected end of file\n"); else if (data->c == '\n') data->count++; c = xfgetc(data->fp); if (c < 0) { if (xferror(data->fp)) glp_sdf_error(data, "read error - %s\n", xerrmsg()); else if (data->c == '\n') c = XEOF; else { glp_sdf_warning(data, "missing final end of line\n"); c = '\n'; } } else if (c == '\n') ; else if (isspace(c)) c = ' '; else if (iscntrl(c)) glp_sdf_error(data, "invalid control character 0x%02X\n", c); data->c = c; return; } static void skip_pad(glp_data *data) { /* skip uninteresting characters and comments */ loop: while (data->c == ' ' || data->c == '\n') next_char(data); if (data->c == '/') { next_char(data); if (data->c != '*') glp_sdf_error(data, "invalid use of slash\n"); next_char(data); for (;;) { if (data->c == '*') { next_char(data); if (data->c == '/') { next_char(data); break; } } next_char(data); } goto loop; } return; } static void next_item(glp_data *data) { /* read next item */ int len; skip_pad(data); len = 0; while (!(data->c == ' ' || data->c == '\n')) { data->item[len++] = (char)data->c; if (len == sizeof(data->item)) glp_sdf_error(data, "data item `%.31s...' too long\n", data->item); next_char(data); } data->item[len] = '\0'; return; } int glp_sdf_read_int(glp_data *data) { /* read integer number */ int x; next_item(data); switch (str2int(data->item, &x)) { case 0: break; case 1: glp_sdf_error(data, "integer `%s' out of range\n", data->item); case 2: glp_sdf_error(data, "cannot convert `%s' to integer\n", data->item); default: xassert(data != data); } return x; } double glp_sdf_read_num(glp_data *data) { /* read floating-point number */ double x; next_item(data); switch (str2num(data->item, &x)) { case 0: break; case 1: glp_sdf_error(data, "number `%s' out of range\n", data->item); case 2: glp_sdf_error(data, "cannot convert `%s' to number\n", data->item); default: xassert(data != data); } return x; } const char *glp_sdf_read_item(glp_data *data) { /* read data item */ next_item(data); return data->item; } const char *glp_sdf_read_text(glp_data *data) { /* read text until end of line */ int c, len = 0; for (;;) { c = data->c; next_char(data); if (c == ' ') { /* ignore initial spaces */ if (len == 0) continue; /* and multiple ones */ if (data->item[len-1] == ' ') continue; } else if (c == '\n') { /* remove trailing space */ if (len > 0 && data->item[len-1] == ' ') len--; /* and stop reading */ break; } /* add current character to the buffer */ data->item[len++] = (char)c; if (len == sizeof(data->item)) glp_sdf_error(data, "line too long\n", data->item); } data->item[len] = '\0'; return data->item; } int glp_sdf_line(glp_data *data) { /* determine current line number */ return data->count; } void glp_sdf_close_file(glp_data *data) { /* close plain data file */ xfclose(data->fp); xfree(data->fname); xfree(data); return; } /* eof */ glpk-4.52.1/src/glpsdf.h0000644000062000006210000000364712175147600014152 0ustar maomkpasswd/* glpsdf.h */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPSDF_H #define GLPSDF_H typedef struct glp_data glp_data; /* plain data file */ glp_data *glp_sdf_open_file(const char *fname); /* open plain data file */ void glp_sdf_set_jump(glp_data *data, void *jump); /* set up error handling */ void glp_sdf_error(glp_data *data, const char *fmt, ...); /* print error message */ void glp_sdf_warning(glp_data *data, const char *fmt, ...); /* print warning message */ int glp_sdf_read_int(glp_data *data); /* read integer number */ double glp_sdf_read_num(glp_data *data); /* read floating-point number */ const char *glp_sdf_read_item(glp_data *data); /* read data item */ const char *glp_sdf_read_text(glp_data *data); /* read text until end of line */ int glp_sdf_line(glp_data *data); /* determine current line number */ void glp_sdf_close_file(glp_data *data); /* close plain data file */ #endif /* eof */ glpk-4.52.1/src/glpspm.c0000644000062000006210000006053012175147600014162 0ustar maomkpasswd/* glpspm.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glphbm.h" #include "glprgr.h" #include "glpspm.h" #include "env.h" /*********************************************************************** * NAME * * spm_create_mat - create general sparse matrix * * SYNOPSIS * * #include "glpspm.h" * SPM *spm_create_mat(int m, int n); * * DESCRIPTION * * The routine spm_create_mat creates a general sparse matrix having * m rows and n columns. Being created the matrix is zero (empty), i.e. * has no elements. * * RETURNS * * The routine returns a pointer to the matrix created. */ SPM *spm_create_mat(int m, int n) { SPM *A; xassert(0 <= m && m < INT_MAX); xassert(0 <= n && n < INT_MAX); A = xmalloc(sizeof(SPM)); A->m = m; A->n = n; if (m == 0 || n == 0) { A->pool = NULL; A->row = NULL; A->col = NULL; } else { int i, j; A->pool = dmp_create_pool(); A->row = xcalloc(1+m, sizeof(SPME *)); for (i = 1; i <= m; i++) A->row[i] = NULL; A->col = xcalloc(1+n, sizeof(SPME *)); for (j = 1; j <= n; j++) A->col[j] = NULL; } return A; } /*********************************************************************** * NAME * * spm_new_elem - add new element to sparse matrix * * SYNOPSIS * * #include "glpspm.h" * SPME *spm_new_elem(SPM *A, int i, int j, double val); * * DESCRIPTION * * The routine spm_new_elem adds a new element to the specified sparse * matrix. Parameters i, j, and val specify the row number, the column * number, and a numerical value of the element, respectively. * * RETURNS * * The routine returns a pointer to the new element added. */ SPME *spm_new_elem(SPM *A, int i, int j, double val) { SPME *e; xassert(1 <= i && i <= A->m); xassert(1 <= j && j <= A->n); e = dmp_get_atom(A->pool, sizeof(SPME)); e->i = i; e->j = j; e->val = val; e->r_prev = NULL; e->r_next = A->row[i]; if (e->r_next != NULL) e->r_next->r_prev = e; e->c_prev = NULL; e->c_next = A->col[j]; if (e->c_next != NULL) e->c_next->c_prev = e; A->row[i] = A->col[j] = e; return e; } /*********************************************************************** * NAME * * spm_delete_mat - delete general sparse matrix * * SYNOPSIS * * #include "glpspm.h" * void spm_delete_mat(SPM *A); * * DESCRIPTION * * The routine deletes the specified general sparse matrix freeing all * the memory allocated to this object. */ void spm_delete_mat(SPM *A) { /* delete sparse matrix */ if (A->pool != NULL) dmp_delete_pool(A->pool); if (A->row != NULL) xfree(A->row); if (A->col != NULL) xfree(A->col); xfree(A); return; } /*********************************************************************** * NAME * * spm_test_mat_e - create test sparse matrix of E(n,c) class * * SYNOPSIS * * #include "glpspm.h" * SPM *spm_test_mat_e(int n, int c); * * DESCRIPTION * * The routine spm_test_mat_e creates a test sparse matrix of E(n,c) * class as described in the book: Ole 0sterby, Zahari Zlatev. Direct * Methods for Sparse Matrices. Springer-Verlag, 1983. * * Matrix of E(n,c) class is a symmetric positive definite matrix of * the order n. It has the number 4 on its main diagonal and the number * -1 on its four co-diagonals, two of which are neighbour to the main * diagonal and two others are shifted from the main diagonal on the * distance c. * * It is necessary that n >= 3 and 2 <= c <= n-1. * * RETURNS * * The routine returns a pointer to the matrix created. */ SPM *spm_test_mat_e(int n, int c) { SPM *A; int i; xassert(n >= 3 && 2 <= c && c <= n-1); A = spm_create_mat(n, n); for (i = 1; i <= n; i++) spm_new_elem(A, i, i, 4.0); for (i = 1; i <= n-1; i++) { spm_new_elem(A, i, i+1, -1.0); spm_new_elem(A, i+1, i, -1.0); } for (i = 1; i <= n-c; i++) { spm_new_elem(A, i, i+c, -1.0); spm_new_elem(A, i+c, i, -1.0); } return A; } /*********************************************************************** * NAME * * spm_test_mat_d - create test sparse matrix of D(n,c) class * * SYNOPSIS * * #include "glpspm.h" * SPM *spm_test_mat_d(int n, int c); * * DESCRIPTION * * The routine spm_test_mat_d creates a test sparse matrix of D(n,c) * class as described in the book: Ole 0sterby, Zahari Zlatev. Direct * Methods for Sparse Matrices. Springer-Verlag, 1983. * * Matrix of D(n,c) class is a non-singular matrix of the order n. It * has unity main diagonal, three co-diagonals above the main diagonal * on the distance c, which are cyclically continued below the main * diagonal, and a triangle block of the size 10x10 in the upper right * corner. * * It is necessary that n >= 14 and 1 <= c <= n-13. * * RETURNS * * The routine returns a pointer to the matrix created. */ SPM *spm_test_mat_d(int n, int c) { SPM *A; int i, j; xassert(n >= 14 && 1 <= c && c <= n-13); A = spm_create_mat(n, n); for (i = 1; i <= n; i++) spm_new_elem(A, i, i, 1.0); for (i = 1; i <= n-c; i++) spm_new_elem(A, i, i+c, (double)(i+1)); for (i = n-c+1; i <= n; i++) spm_new_elem(A, i, i-n+c, (double)(i+1)); for (i = 1; i <= n-c-1; i++) spm_new_elem(A, i, i+c+1, (double)(-i)); for (i = n-c; i <= n; i++) spm_new_elem(A, i, i-n+c+1, (double)(-i)); for (i = 1; i <= n-c-2; i++) spm_new_elem(A, i, i+c+2, 16.0); for (i = n-c-1; i <= n; i++) spm_new_elem(A, i, i-n+c+2, 16.0); for (j = 1; j <= 10; j++) for (i = 1; i <= 11-j; i++) spm_new_elem(A, i, n-11+i+j, 100.0 * (double)j); return A; } /*********************************************************************** * NAME * * spm_show_mat - write sparse matrix pattern in BMP file format * * SYNOPSIS * * #include "glpspm.h" * int spm_show_mat(const SPM *A, const char *fname); * * DESCRIPTION * * The routine spm_show_mat writes pattern of the specified sparse * matrix in uncompressed BMP file format (Windows bitmap) to a binary * file whose name is specified by the character string fname. * * Each pixel corresponds to one matrix element. The pixel colors have * the following meaning: * * Black structurally zero element * White positive element * Cyan negative element * Green zero element * Red duplicate element * * RETURNS * * If no error occured, the routine returns zero. Otherwise, it prints * an appropriate error message and returns non-zero. */ int spm_show_mat(const SPM *A, const char *fname) { int m = A->m; int n = A->n; int i, j, k, ret; char *map; xprintf("spm_show_mat: writing matrix pattern to `%s'...\n", fname); xassert(1 <= m && m <= 32767); xassert(1 <= n && n <= 32767); map = xmalloc(m * n); memset(map, 0x08, m * n); for (i = 1; i <= m; i++) { SPME *e; for (e = A->row[i]; e != NULL; e = e->r_next) { j = e->j; xassert(1 <= j && j <= n); k = n * (i - 1) + (j - 1); if (map[k] != 0x08) map[k] = 0x0C; else if (e->val > 0.0) map[k] = 0x0F; else if (e->val < 0.0) map[k] = 0x0B; else map[k] = 0x0A; } } ret = rgr_write_bmp16(fname, m, n, map); xfree(map); return ret; } /*********************************************************************** * NAME * * spm_read_hbm - read sparse matrix in Harwell-Boeing format * * SYNOPSIS * * #include "glpspm.h" * SPM *spm_read_hbm(const char *fname); * * DESCRIPTION * * The routine spm_read_hbm reads a sparse matrix in the Harwell-Boeing * format from a text file whose name is the character string fname. * * Detailed description of the Harwell-Boeing format recognised by this * routine can be found in the following report: * * I.S.Duff, R.G.Grimes, J.G.Lewis. User's Guide for the Harwell-Boeing * Sparse Matrix Collection (Release I), TR/PA/92/86, October 1992. * * NOTE * * The routine spm_read_hbm reads the matrix "as is", due to which zero * and/or duplicate elements can appear in the matrix. * * RETURNS * * If no error occured, the routine returns a pointer to the matrix * created. Otherwise, the routine prints an appropriate error message * and returns NULL. */ SPM *spm_read_hbm(const char *fname) { SPM *A = NULL; HBM *hbm; int nrow, ncol, nnzero, i, j, beg, end, ptr, *colptr, *rowind; double val, *values; char *mxtype; hbm = hbm_read_mat(fname); if (hbm == NULL) { xprintf("spm_read_hbm: unable to read matrix\n"); goto fini; } mxtype = hbm->mxtype; nrow = hbm->nrow; ncol = hbm->ncol; nnzero = hbm->nnzero; colptr = hbm->colptr; rowind = hbm->rowind; values = hbm->values; if (!(strcmp(mxtype, "RSA") == 0 || strcmp(mxtype, "PSA") == 0 || strcmp(mxtype, "RUA") == 0 || strcmp(mxtype, "PUA") == 0 || strcmp(mxtype, "RRA") == 0 || strcmp(mxtype, "PRA") == 0)) { xprintf("spm_read_hbm: matrix type `%s' not supported\n", mxtype); goto fini; } A = spm_create_mat(nrow, ncol); if (mxtype[1] == 'S' || mxtype[1] == 'U') xassert(nrow == ncol); for (j = 1; j <= ncol; j++) { beg = colptr[j]; end = colptr[j+1]; xassert(1 <= beg && beg <= end && end <= nnzero + 1); for (ptr = beg; ptr < end; ptr++) { i = rowind[ptr]; xassert(1 <= i && i <= nrow); if (mxtype[0] == 'R') val = values[ptr]; else val = 1.0; spm_new_elem(A, i, j, val); if (mxtype[1] == 'S' && i != j) spm_new_elem(A, j, i, val); } } fini: if (hbm != NULL) hbm_free_mat(hbm); return A; } /*********************************************************************** * NAME * * spm_count_nnz - determine number of non-zeros in sparse matrix * * SYNOPSIS * * #include "glpspm.h" * int spm_count_nnz(const SPM *A); * * RETURNS * * The routine spm_count_nnz returns the number of structural non-zero * elements in the specified sparse matrix. */ int spm_count_nnz(const SPM *A) { SPME *e; int i, nnz = 0; for (i = 1; i <= A->m; i++) for (e = A->row[i]; e != NULL; e = e->r_next) nnz++; return nnz; } /*********************************************************************** * NAME * * spm_drop_zeros - remove zero elements from sparse matrix * * SYNOPSIS * * #include "glpspm.h" * int spm_drop_zeros(SPM *A, double eps); * * DESCRIPTION * * The routine spm_drop_zeros removes all elements from the specified * sparse matrix, whose absolute value is less than eps. * * If the parameter eps is 0, only zero elements are removed from the * matrix. * * RETURNS * * The routine returns the number of elements removed. */ int spm_drop_zeros(SPM *A, double eps) { SPME *e, *next; int i, count = 0; for (i = 1; i <= A->m; i++) { for (e = A->row[i]; e != NULL; e = next) { next = e->r_next; if (e->val == 0.0 || fabs(e->val) < eps) { /* remove element from the row list */ if (e->r_prev == NULL) A->row[e->i] = e->r_next; else e->r_prev->r_next = e->r_next; if (e->r_next == NULL) ; else e->r_next->r_prev = e->r_prev; /* remove element from the column list */ if (e->c_prev == NULL) A->col[e->j] = e->c_next; else e->c_prev->c_next = e->c_next; if (e->c_next == NULL) ; else e->c_next->c_prev = e->c_prev; /* return element to the memory pool */ dmp_free_atom(A->pool, e, sizeof(SPME)); count++; } } } return count; } /*********************************************************************** * NAME * * spm_read_mat - read sparse matrix from text file * * SYNOPSIS * * #include "glpspm.h" * SPM *spm_read_mat(const char *fname); * * DESCRIPTION * * The routine reads a sparse matrix from a text file whose name is * specified by the parameter fname. * * For the file format see description of the routine spm_write_mat. * * RETURNS * * On success the routine returns a pointer to the matrix created, * otherwise NULL. */ #if 1 SPM *spm_read_mat(const char *fname) { xassert(fname != fname); return NULL; } #else SPM *spm_read_mat(const char *fname) { SPM *A = NULL; PDS *pds; jmp_buf jump; int i, j, k, m, n, nnz, fail = 0; double val; xprintf("spm_read_mat: reading matrix from `%s'...\n", fname); pds = pds_open_file(fname); if (pds == NULL) { xprintf("spm_read_mat: unable to open `%s' - %s\n", fname, strerror(errno)); fail = 1; goto done; } if (setjmp(jump)) { fail = 1; goto done; } pds_set_jump(pds, jump); /* number of rows, number of columns, number of non-zeros */ m = pds_scan_int(pds); if (m < 0) pds_error(pds, "invalid number of rows\n"); n = pds_scan_int(pds); if (n < 0) pds_error(pds, "invalid number of columns\n"); nnz = pds_scan_int(pds); if (nnz < 0) pds_error(pds, "invalid number of non-zeros\n"); /* create matrix */ xprintf("spm_read_mat: %d rows, %d columns, %d non-zeros\n", m, n, nnz); A = spm_create_mat(m, n); /* read matrix elements */ for (k = 1; k <= nnz; k++) { /* row index, column index, element value */ i = pds_scan_int(pds); if (!(1 <= i && i <= m)) pds_error(pds, "row index out of range\n"); j = pds_scan_int(pds); if (!(1 <= j && j <= n)) pds_error(pds, "column index out of range\n"); val = pds_scan_num(pds); /* add new element to the matrix */ spm_new_elem(A, i, j, val); } xprintf("spm_read_mat: %d lines were read\n", pds->count); done: if (pds != NULL) pds_close_file(pds); if (fail && A != NULL) spm_delete_mat(A), A = NULL; return A; } #endif /*********************************************************************** * NAME * * spm_write_mat - write sparse matrix to text file * * SYNOPSIS * * #include "glpspm.h" * int spm_write_mat(const SPM *A, const char *fname); * * DESCRIPTION * * The routine spm_write_mat writes the specified sparse matrix to a * text file whose name is specified by the parameter fname. This file * can be read back with the routine spm_read_mat. * * RETURNS * * On success the routine returns zero, otherwise non-zero. * * FILE FORMAT * * The file created by the routine spm_write_mat is a plain text file, * which contains the following information: * * m n nnz * row[1] col[1] val[1] * row[2] col[2] val[2] * . . . * row[nnz] col[nnz] val[nnz] * * where: * m is the number of rows; * n is the number of columns; * nnz is the number of non-zeros; * row[k], k = 1,...,nnz, are row indices; * col[k], k = 1,...,nnz, are column indices; * val[k], k = 1,...,nnz, are element values. */ #if 1 int spm_write_mat(const SPM *A, const char *fname) { xassert(A != A); xassert(fname != fname); return 0; } #else int spm_write_mat(const SPM *A, const char *fname) { FILE *fp; int i, nnz, ret = 0; xprintf("spm_write_mat: writing matrix to `%s'...\n", fname); fp = fopen(fname, "w"); if (fp == NULL) { xprintf("spm_write_mat: unable to create `%s' - %s\n", fname, strerror(errno)); ret = 1; goto done; } /* number of rows, number of columns, number of non-zeros */ nnz = spm_count_nnz(A); fprintf(fp, "%d %d %d\n", A->m, A->n, nnz); /* walk through rows of the matrix */ for (i = 1; i <= A->m; i++) { SPME *e; /* walk through elements of i-th row */ for (e = A->row[i]; e != NULL; e = e->r_next) { /* row index, column index, element value */ fprintf(fp, "%d %d %.*g\n", e->i, e->j, DBL_DIG, e->val); } } fflush(fp); if (ferror(fp)) { xprintf("spm_write_mat: writing error on `%s' - %s\n", fname, strerror(errno)); ret = 1; goto done; } xprintf("spm_write_mat: %d lines were written\n", 1 + nnz); done: if (fp != NULL) fclose(fp); return ret; } #endif /*********************************************************************** * NAME * * spm_transpose - transpose sparse matrix * * SYNOPSIS * * #include "glpspm.h" * SPM *spm_transpose(const SPM *A); * * RETURNS * * The routine computes and returns sparse matrix B, which is a matrix * transposed to sparse matrix A. */ SPM *spm_transpose(const SPM *A) { SPM *B; int i; B = spm_create_mat(A->n, A->m); for (i = 1; i <= A->m; i++) { SPME *e; for (e = A->row[i]; e != NULL; e = e->r_next) spm_new_elem(B, e->j, i, e->val); } return B; } SPM *spm_add_sym(const SPM *A, const SPM *B) { /* add two sparse matrices (symbolic phase) */ SPM *C; int i, j, *flag; xassert(A->m == B->m); xassert(A->n == B->n); /* create resultant matrix */ C = spm_create_mat(A->m, A->n); /* allocate and clear the flag array */ flag = xcalloc(1+C->n, sizeof(int)); for (j = 1; j <= C->n; j++) flag[j] = 0; /* compute pattern of C = A + B */ for (i = 1; i <= C->m; i++) { SPME *e; /* at the beginning i-th row of C is empty */ /* (i-th row of C) := (i-th row of C) union (i-th row of A) */ for (e = A->row[i]; e != NULL; e = e->r_next) { /* (note that i-th row of A may have duplicate elements) */ j = e->j; if (!flag[j]) { spm_new_elem(C, i, j, 0.0); flag[j] = 1; } } /* (i-th row of C) := (i-th row of C) union (i-th row of B) */ for (e = B->row[i]; e != NULL; e = e->r_next) { /* (note that i-th row of B may have duplicate elements) */ j = e->j; if (!flag[j]) { spm_new_elem(C, i, j, 0.0); flag[j] = 1; } } /* reset the flag array */ for (e = C->row[i]; e != NULL; e = e->r_next) flag[e->j] = 0; } /* check and deallocate the flag array */ for (j = 1; j <= C->n; j++) xassert(!flag[j]); xfree(flag); return C; } void spm_add_num(SPM *C, double alfa, const SPM *A, double beta, const SPM *B) { /* add two sparse matrices (numeric phase) */ int i, j; double *work; /* allocate and clear the working array */ work = xcalloc(1+C->n, sizeof(double)); for (j = 1; j <= C->n; j++) work[j] = 0.0; /* compute matrix C = alfa * A + beta * B */ for (i = 1; i <= C->n; i++) { SPME *e; /* work := alfa * (i-th row of A) + beta * (i-th row of B) */ /* (note that A and/or B may have duplicate elements) */ for (e = A->row[i]; e != NULL; e = e->r_next) work[e->j] += alfa * e->val; for (e = B->row[i]; e != NULL; e = e->r_next) work[e->j] += beta * e->val; /* (i-th row of C) := work, work := 0 */ for (e = C->row[i]; e != NULL; e = e->r_next) { j = e->j; e->val = work[j]; work[j] = 0.0; } } /* check and deallocate the working array */ for (j = 1; j <= C->n; j++) xassert(work[j] == 0.0); xfree(work); return; } SPM *spm_add_mat(double alfa, const SPM *A, double beta, const SPM *B) { /* add two sparse matrices (driver routine) */ SPM *C; C = spm_add_sym(A, B); spm_add_num(C, alfa, A, beta, B); return C; } SPM *spm_mul_sym(const SPM *A, const SPM *B) { /* multiply two sparse matrices (symbolic phase) */ int i, j, k, *flag; SPM *C; xassert(A->n == B->m); /* create resultant matrix */ C = spm_create_mat(A->m, B->n); /* allocate and clear the flag array */ flag = xcalloc(1+C->n, sizeof(int)); for (j = 1; j <= C->n; j++) flag[j] = 0; /* compute pattern of C = A * B */ for (i = 1; i <= C->m; i++) { SPME *e, *ee; /* compute pattern of i-th row of C */ for (e = A->row[i]; e != NULL; e = e->r_next) { k = e->j; for (ee = B->row[k]; ee != NULL; ee = ee->r_next) { j = ee->j; /* if a[i,k] != 0 and b[k,j] != 0 then c[i,j] != 0 */ if (!flag[j]) { /* c[i,j] does not exist, so create it */ spm_new_elem(C, i, j, 0.0); flag[j] = 1; } } } /* reset the flag array */ for (e = C->row[i]; e != NULL; e = e->r_next) flag[e->j] = 0; } /* check and deallocate the flag array */ for (j = 1; j <= C->n; j++) xassert(!flag[j]); xfree(flag); return C; } void spm_mul_num(SPM *C, const SPM *A, const SPM *B) { /* multiply two sparse matrices (numeric phase) */ int i, j; double *work; /* allocate and clear the working array */ work = xcalloc(1+A->n, sizeof(double)); for (j = 1; j <= A->n; j++) work[j] = 0.0; /* compute matrix C = A * B */ for (i = 1; i <= C->m; i++) { SPME *e, *ee; double temp; /* work := (i-th row of A) */ /* (note that A may have duplicate elements) */ for (e = A->row[i]; e != NULL; e = e->r_next) work[e->j] += e->val; /* compute i-th row of C */ for (e = C->row[i]; e != NULL; e = e->r_next) { j = e->j; /* c[i,j] := work * (j-th column of B) */ temp = 0.0; for (ee = B->col[j]; ee != NULL; ee = ee->c_next) temp += work[ee->i] * ee->val; e->val = temp; } /* reset the working array */ for (e = A->row[i]; e != NULL; e = e->r_next) work[e->j] = 0.0; } /* check and deallocate the working array */ for (j = 1; j <= A->n; j++) xassert(work[j] == 0.0); xfree(work); return; } SPM *spm_mul_mat(const SPM *A, const SPM *B) { /* multiply two sparse matrices (driver routine) */ SPM *C; C = spm_mul_sym(A, B); spm_mul_num(C, A, B); return C; } PER *spm_create_per(int n) { /* create permutation matrix */ PER *P; int k; xassert(n >= 0); P = xmalloc(sizeof(PER)); P->n = n; P->row = xcalloc(1+n, sizeof(int)); P->col = xcalloc(1+n, sizeof(int)); /* initially it is identity matrix */ for (k = 1; k <= n; k++) P->row[k] = P->col[k] = k; return P; } void spm_check_per(PER *P) { /* check permutation matrix for correctness */ int i, j; xassert(P->n >= 0); for (i = 1; i <= P->n; i++) { j = P->row[i]; xassert(1 <= j && j <= P->n); xassert(P->col[j] == i); } return; } void spm_delete_per(PER *P) { /* delete permutation matrix */ xfree(P->row); xfree(P->col); xfree(P); return; } /* eof */ glpk-4.52.1/src/glpspm.h0000644000062000006210000001175112175147600014170 0ustar maomkpasswd/* glpspm.h (general sparse matrix) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPSPM_H #define GLPSPM_H #include "dmp.h" typedef struct SPM SPM; typedef struct SPME SPME; struct SPM { /* general sparse matrix */ int m; /* number of rows, m >= 0 */ int n; /* number of columns, n >= 0 */ DMP *pool; /* memory pool to store matrix elements */ SPME **row; /* SPME *row[1+m]; */ /* row[i], 1 <= i <= m, is a pointer to i-th row list */ SPME **col; /* SPME *col[1+n]; */ /* col[j], 1 <= j <= n, is a pointer to j-th column list */ }; struct SPME { /* sparse matrix element */ int i; /* row number */ int j; /* column number */ double val; /* element value */ SPME *r_prev; /* pointer to previous element in the same row */ SPME *r_next; /* pointer to next element in the same row */ SPME *c_prev; /* pointer to previous element in the same column */ SPME *c_next; /* pointer to next element in the same column */ }; typedef struct PER PER; struct PER { /* permutation matrix */ int n; /* matrix order, n >= 0 */ int *row; /* int row[1+n]; */ /* row[i] = j means p[i,j] = 1 */ int *col; /* int col[1+n]; */ /* col[j] = i means p[i,j] = 1 */ }; #define spm_create_mat _glp_spm_create_mat SPM *spm_create_mat(int m, int n); /* create general sparse matrix */ #define spm_new_elem _glp_spm_new_elem SPME *spm_new_elem(SPM *A, int i, int j, double val); /* add new element to sparse matrix */ #define spm_delete_mat _glp_spm_delete_mat void spm_delete_mat(SPM *A); /* delete general sparse matrix */ #define spm_test_mat_e _glp_spm_test_mat_e SPM *spm_test_mat_e(int n, int c); /* create test sparse matrix of E(n,c) class */ #define spm_test_mat_d _glp_spm_test_mat_d SPM *spm_test_mat_d(int n, int c); /* create test sparse matrix of D(n,c) class */ #define spm_show_mat _glp_spm_show_mat int spm_show_mat(const SPM *A, const char *fname); /* write sparse matrix pattern in BMP file format */ #define spm_read_hbm _glp_spm_read_hbm SPM *spm_read_hbm(const char *fname); /* read sparse matrix in Harwell-Boeing format */ #define spm_count_nnz _glp_spm_count_nnz int spm_count_nnz(const SPM *A); /* determine number of non-zeros in sparse matrix */ #define spm_drop_zeros _glp_spm_drop_zeros int spm_drop_zeros(SPM *A, double eps); /* remove zero elements from sparse matrix */ #define spm_read_mat _glp_spm_read_mat SPM *spm_read_mat(const char *fname); /* read sparse matrix from text file */ #define spm_write_mat _glp_spm_write_mat int spm_write_mat(const SPM *A, const char *fname); /* write sparse matrix to text file */ #define spm_transpose _glp_spm_transpose SPM *spm_transpose(const SPM *A); /* transpose sparse matrix */ #define spm_add_sym _glp_spm_add_sym SPM *spm_add_sym(const SPM *A, const SPM *B); /* add two sparse matrices (symbolic phase) */ #define spm_add_num _glp_spm_add_num void spm_add_num(SPM *C, double alfa, const SPM *A, double beta, const SPM *B); /* add two sparse matrices (numeric phase) */ #define spm_add_mat _glp_spm_add_mat SPM *spm_add_mat(double alfa, const SPM *A, double beta, const SPM *B); /* add two sparse matrices (driver routine) */ #define spm_mul_sym _glp_spm_mul_sym SPM *spm_mul_sym(const SPM *A, const SPM *B); /* multiply two sparse matrices (symbolic phase) */ #define spm_mul_num _glp_spm_mul_num void spm_mul_num(SPM *C, const SPM *A, const SPM *B); /* multiply two sparse matrices (numeric phase) */ #define spm_mul_mat _glp_spm_mul_mat SPM *spm_mul_mat(const SPM *A, const SPM *B); /* multiply two sparse matrices (driver routine) */ #define spm_create_per _glp_spm_create_per PER *spm_create_per(int n); /* create permutation matrix */ #define spm_check_per _glp_spm_check_per void spm_check_per(PER *P); /* check permutation matrix for correctness */ #define spm_delete_per _glp_spm_delete_per void spm_delete_per(PER *P); /* delete permutation matrix */ #endif /* eof */ glpk-4.52.1/src/glpspx.h0000644000062000006210000000267012175147600014203 0ustar maomkpasswd/* glpspx.h (core simplex solvers) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPSPX_H #define GLPSPX_H #include "glpapi.h" #define spx_primal _glp_spx_primal int spx_primal(glp_prob *lp, const glp_smcp *parm); /* core LP solver based on the primal simplex method */ #define spx_dual _glp_spx_dual int spx_dual(glp_prob *lp, const glp_smcp *parm); /* core LP solver based on the dual simplex method */ #endif /* eof */ glpk-4.52.1/src/glpspx01.c0000644000062000006210000030210112175147600014327 0ustar maomkpasswd/* glpspx01.c (primal simplex method) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpspx.h" struct csa { /* common storage area */ /*--------------------------------------------------------------*/ /* LP data */ int m; /* number of rows (auxiliary variables), m > 0 */ int n; /* number of columns (structural variables), n > 0 */ char *type; /* char type[1+m+n]; */ /* type[0] is not used; type[k], 1 <= k <= m+n, is the type of variable x[k]: GLP_FR - free variable GLP_LO - variable with lower bound GLP_UP - variable with upper bound GLP_DB - double-bounded variable GLP_FX - fixed variable */ double *lb; /* double lb[1+m+n]; */ /* lb[0] is not used; lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; if x[k] has no lower bound, lb[k] is zero */ double *ub; /* double ub[1+m+n]; */ /* ub[0] is not used; ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; if x[k] has no upper bound, ub[k] is zero; if x[k] is of fixed type, ub[k] is the same as lb[k] */ double *coef; /* double coef[1+m+n]; */ /* coef[0] is not used; coef[k], 1 <= k <= m+n, is an objective coefficient at variable x[k] (note that on phase I auxiliary variables also may have non-zero objective coefficients) */ /*--------------------------------------------------------------*/ /* original objective function */ double *obj; /* double obj[1+n]; */ /* obj[0] is a constant term of the original objective function; obj[j], 1 <= j <= n, is an original objective coefficient at structural variable x[m+j] */ double zeta; /* factor used to scale original objective coefficients; its sign defines original optimization direction: zeta > 0 means minimization, zeta < 0 means maximization */ /*--------------------------------------------------------------*/ /* constraint matrix A; it has m rows and n columns and is stored by columns */ int *A_ptr; /* int A_ptr[1+n+1]; */ /* A_ptr[0] is not used; A_ptr[j], 1 <= j <= n, is starting position of j-th column in arrays A_ind and A_val; note that A_ptr[1] is always 1; A_ptr[n+1] indicates the position after the last element in arrays A_ind and A_val */ int *A_ind; /* int A_ind[A_ptr[n+1]]; */ /* row indices */ double *A_val; /* double A_val[A_ptr[n+1]]; */ /* non-zero element values */ /*--------------------------------------------------------------*/ /* basis header */ int *head; /* int head[1+m+n]; */ /* head[0] is not used; head[i], 1 <= i <= m, is the ordinal number of basic variable xB[i]; head[i] = k means that xB[i] = x[k] and i-th column of matrix B is k-th column of matrix (I|-A); head[m+j], 1 <= j <= n, is the ordinal number of non-basic variable xN[j]; head[m+j] = k means that xN[j] = x[k] and j-th column of matrix N is k-th column of matrix (I|-A) */ char *stat; /* char stat[1+n]; */ /* stat[0] is not used; stat[j], 1 <= j <= n, is the status of non-basic variable xN[j], which defines its active bound: GLP_NL - lower bound is active GLP_NU - upper bound is active GLP_NF - free variable GLP_NS - fixed variable */ /*--------------------------------------------------------------*/ /* matrix B is the basis matrix; it is composed from columns of the augmented constraint matrix (I|-A) corresponding to basic variables and stored in a factorized (invertable) form */ int valid; /* factorization is valid only if this flag is set */ BFD *bfd; /* BFD bfd[1:m,1:m]; */ /* factorized (invertable) form of the basis matrix */ /*--------------------------------------------------------------*/ /* matrix N is a matrix composed from columns of the augmented constraint matrix (I|-A) corresponding to non-basic variables except fixed ones; it is stored by rows and changes every time the basis changes */ int *N_ptr; /* int N_ptr[1+m+1]; */ /* N_ptr[0] is not used; N_ptr[i], 1 <= i <= m, is starting position of i-th row in arrays N_ind and N_val; note that N_ptr[1] is always 1; N_ptr[m+1] indicates the position after the last element in arrays N_ind and N_val */ int *N_len; /* int N_len[1+m]; */ /* N_len[0] is not used; N_len[i], 1 <= i <= m, is length of i-th row (0 to n) */ int *N_ind; /* int N_ind[N_ptr[m+1]]; */ /* column indices */ double *N_val; /* double N_val[N_ptr[m+1]]; */ /* non-zero element values */ /*--------------------------------------------------------------*/ /* working parameters */ int phase; /* search phase: 0 - not determined yet 1 - search for primal feasible solution 2 - search for optimal solution */ #if 0 /* 10/VI-2013 */ glp_long tm_beg; /* time value at the beginning of the search */ #else double tm_beg; #endif int it_beg; /* simplex iteration count at the beginning of the search */ int it_cnt; /* simplex iteration count; it increases by one every time the basis changes (including the case when a non-basic variable jumps to its opposite bound) */ int it_dpy; /* simplex iteration count at the most recent display output */ /*--------------------------------------------------------------*/ /* basic solution components */ double *bbar; /* double bbar[1+m]; */ /* bbar[0] is not used; bbar[i], 1 <= i <= m, is primal value of basic variable xB[i] (if xB[i] is free, its primal value is not updated) */ double *cbar; /* double cbar[1+n]; */ /* cbar[0] is not used; cbar[j], 1 <= j <= n, is reduced cost of non-basic variable xN[j] (if xN[j] is fixed, its reduced cost is not updated) */ /*--------------------------------------------------------------*/ /* the following pricing technique options may be used: GLP_PT_STD - standard ("textbook") pricing; GLP_PT_PSE - projected steepest edge; GLP_PT_DVX - Devex pricing (not implemented yet); in case of GLP_PT_STD the reference space is not used, and all steepest edge coefficients are set to 1 */ int refct; /* this count is set to an initial value when the reference space is defined and decreases by one every time the basis changes; once this count reaches zero, the reference space is redefined again */ char *refsp; /* char refsp[1+m+n]; */ /* refsp[0] is not used; refsp[k], 1 <= k <= m+n, is the flag which means that variable x[k] belongs to the current reference space */ double *gamma; /* double gamma[1+n]; */ /* gamma[0] is not used; gamma[j], 1 <= j <= n, is the steepest edge coefficient for non-basic variable xN[j]; if xN[j] is fixed, gamma[j] is not used and just set to 1 */ /*--------------------------------------------------------------*/ /* non-basic variable xN[q] chosen to enter the basis */ int q; /* index of the non-basic variable xN[q] chosen, 1 <= q <= n; if the set of eligible non-basic variables is empty and thus no variable has been chosen, q is set to 0 */ /*--------------------------------------------------------------*/ /* pivot column of the simplex table corresponding to non-basic variable xN[q] chosen is the following vector: T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], where B is the current basis matrix, N[q] is a column of the matrix (I|-A) corresponding to xN[q] */ int tcol_nnz; /* number of non-zero components, 0 <= nnz <= m */ int *tcol_ind; /* int tcol_ind[1+m]; */ /* tcol_ind[0] is not used; tcol_ind[t], 1 <= t <= nnz, is an index of non-zero component, i.e. tcol_ind[t] = i means that tcol_vec[i] != 0 */ double *tcol_vec; /* double tcol_vec[1+m]; */ /* tcol_vec[0] is not used; tcol_vec[i], 1 <= i <= m, is a numeric value of i-th component of the column */ double tcol_max; /* infinity (maximum) norm of the column (max |tcol_vec[i]|) */ int tcol_num; /* number of significant non-zero components, which means that: |tcol_vec[i]| >= eps for i in tcol_ind[1,...,num], |tcol_vec[i]| < eps for i in tcol_ind[num+1,...,nnz], where eps is a pivot tolerance */ /*--------------------------------------------------------------*/ /* basic variable xB[p] chosen to leave the basis */ int p; /* index of the basic variable xB[p] chosen, 1 <= p <= m; p = 0 means that no basic variable reaches its bound; p < 0 means that non-basic variable xN[q] reaches its opposite bound before any basic variable */ int p_stat; /* new status (GLP_NL, GLP_NU, or GLP_NS) to be assigned to xB[p] once it has left the basis */ double teta; /* change of non-basic variable xN[q] (see above), on which xB[p] (or, if p < 0, xN[q] itself) reaches its bound */ /*--------------------------------------------------------------*/ /* pivot row of the simplex table corresponding to basic variable xB[p] chosen is the following vector: T' * e[p] = - N' * inv(B') * e[p] = - N' * rho, where B' is a matrix transposed to the current basis matrix, N' is a matrix, whose rows are columns of the matrix (I|-A) corresponding to non-basic non-fixed variables */ int trow_nnz; /* number of non-zero components, 0 <= nnz <= n */ int *trow_ind; /* int trow_ind[1+n]; */ /* trow_ind[0] is not used; trow_ind[t], 1 <= t <= nnz, is an index of non-zero component, i.e. trow_ind[t] = j means that trow_vec[j] != 0 */ double *trow_vec; /* int trow_vec[1+n]; */ /* trow_vec[0] is not used; trow_vec[j], 1 <= j <= n, is a numeric value of j-th component of the row */ /*--------------------------------------------------------------*/ /* working arrays */ double *work1; /* double work1[1+m]; */ double *work2; /* double work2[1+m]; */ double *work3; /* double work3[1+m]; */ double *work4; /* double work4[1+m]; */ }; static const double kappa = 0.10; /*********************************************************************** * alloc_csa - allocate common storage area * * This routine allocates all arrays in the common storage area (CSA) * and returns a pointer to the CSA. */ static struct csa *alloc_csa(glp_prob *lp) { struct csa *csa; int m = lp->m; int n = lp->n; int nnz = lp->nnz; csa = xmalloc(sizeof(struct csa)); xassert(m > 0 && n > 0); csa->m = m; csa->n = n; csa->type = xcalloc(1+m+n, sizeof(char)); csa->lb = xcalloc(1+m+n, sizeof(double)); csa->ub = xcalloc(1+m+n, sizeof(double)); csa->coef = xcalloc(1+m+n, sizeof(double)); csa->obj = xcalloc(1+n, sizeof(double)); csa->A_ptr = xcalloc(1+n+1, sizeof(int)); csa->A_ind = xcalloc(1+nnz, sizeof(int)); csa->A_val = xcalloc(1+nnz, sizeof(double)); csa->head = xcalloc(1+m+n, sizeof(int)); csa->stat = xcalloc(1+n, sizeof(char)); csa->N_ptr = xcalloc(1+m+1, sizeof(int)); csa->N_len = xcalloc(1+m, sizeof(int)); csa->N_ind = NULL; /* will be allocated later */ csa->N_val = NULL; /* will be allocated later */ csa->bbar = xcalloc(1+m, sizeof(double)); csa->cbar = xcalloc(1+n, sizeof(double)); csa->refsp = xcalloc(1+m+n, sizeof(char)); csa->gamma = xcalloc(1+n, sizeof(double)); csa->tcol_ind = xcalloc(1+m, sizeof(int)); csa->tcol_vec = xcalloc(1+m, sizeof(double)); csa->trow_ind = xcalloc(1+n, sizeof(int)); csa->trow_vec = xcalloc(1+n, sizeof(double)); csa->work1 = xcalloc(1+m, sizeof(double)); csa->work2 = xcalloc(1+m, sizeof(double)); csa->work3 = xcalloc(1+m, sizeof(double)); csa->work4 = xcalloc(1+m, sizeof(double)); return csa; } /*********************************************************************** * init_csa - initialize common storage area * * This routine initializes all data structures in the common storage * area (CSA). */ static void alloc_N(struct csa *csa); static void build_N(struct csa *csa); static void init_csa(struct csa *csa, glp_prob *lp) { int m = csa->m; int n = csa->n; char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; double *coef = csa->coef; double *obj = csa->obj; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; char *stat = csa->stat; char *refsp = csa->refsp; double *gamma = csa->gamma; int i, j, k, loc; double cmax; /* auxiliary variables */ for (i = 1; i <= m; i++) { GLPROW *row = lp->row[i]; type[i] = (char)row->type; lb[i] = row->lb * row->rii; ub[i] = row->ub * row->rii; coef[i] = 0.0; } /* structural variables */ for (j = 1; j <= n; j++) { GLPCOL *col = lp->col[j]; type[m+j] = (char)col->type; lb[m+j] = col->lb / col->sjj; ub[m+j] = col->ub / col->sjj; coef[m+j] = col->coef * col->sjj; } /* original objective function */ obj[0] = lp->c0; memcpy(&obj[1], &coef[m+1], n * sizeof(double)); /* factor used to scale original objective coefficients */ cmax = 0.0; for (j = 1; j <= n; j++) if (cmax < fabs(obj[j])) cmax = fabs(obj[j]); if (cmax == 0.0) cmax = 1.0; switch (lp->dir) { case GLP_MIN: csa->zeta = + 1.0 / cmax; break; case GLP_MAX: csa->zeta = - 1.0 / cmax; break; default: xassert(lp != lp); } #if 1 if (fabs(csa->zeta) < 1.0) csa->zeta *= 1000.0; #endif /* matrix A (by columns) */ loc = 1; for (j = 1; j <= n; j++) { GLPAIJ *aij; A_ptr[j] = loc; for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) { A_ind[loc] = aij->row->i; A_val[loc] = aij->row->rii * aij->val * aij->col->sjj; loc++; } } A_ptr[n+1] = loc; xassert(loc == lp->nnz+1); /* basis header */ xassert(lp->valid); memcpy(&head[1], &lp->head[1], m * sizeof(int)); k = 0; for (i = 1; i <= m; i++) { GLPROW *row = lp->row[i]; if (row->stat != GLP_BS) { k++; xassert(k <= n); head[m+k] = i; stat[k] = (char)row->stat; } } for (j = 1; j <= n; j++) { GLPCOL *col = lp->col[j]; if (col->stat != GLP_BS) { k++; xassert(k <= n); head[m+k] = m + j; stat[k] = (char)col->stat; } } xassert(k == n); /* factorization of matrix B */ csa->valid = 1, lp->valid = 0; csa->bfd = lp->bfd, lp->bfd = NULL; /* matrix N (by rows) */ alloc_N(csa); build_N(csa); /* working parameters */ csa->phase = 0; csa->tm_beg = xtime(); csa->it_beg = csa->it_cnt = lp->it_cnt; csa->it_dpy = -1; /* reference space and steepest edge coefficients */ csa->refct = 0; memset(&refsp[1], 0, (m+n) * sizeof(char)); for (j = 1; j <= n; j++) gamma[j] = 1.0; return; } /*********************************************************************** * invert_B - compute factorization of the basis matrix * * This routine computes factorization of the current basis matrix B. * * If the operation is successful, the routine returns zero, otherwise * non-zero. */ static int inv_col(void *info, int i, int ind[], double val[]) { /* this auxiliary routine returns row indices and numeric values of non-zero elements of i-th column of the basis matrix */ struct csa *csa = info; int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; int k, len, ptr, t; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); #endif k = head[i]; /* B[i] is k-th column of (I|-A) */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* B[i] is k-th column of submatrix I */ len = 1; ind[1] = k; val[1] = 1.0; } else { /* B[i] is (k-m)-th column of submatrix (-A) */ ptr = A_ptr[k-m]; len = A_ptr[k-m+1] - ptr; memcpy(&ind[1], &A_ind[ptr], len * sizeof(int)); memcpy(&val[1], &A_val[ptr], len * sizeof(double)); for (t = 1; t <= len; t++) val[t] = - val[t]; } return len; } static int invert_B(struct csa *csa) { int ret; ret = bfd_factorize(csa->bfd, csa->m, NULL, inv_col, csa); csa->valid = (ret == 0); return ret; } /*********************************************************************** * update_B - update factorization of the basis matrix * * This routine replaces i-th column of the basis matrix B by k-th * column of the augmented constraint matrix (I|-A) and then updates * the factorization of B. * * If the factorization has been successfully updated, the routine * returns zero, otherwise non-zero. */ static int update_B(struct csa *csa, int i, int k) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int ret; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* new i-th column of B is k-th column of I */ int ind[1+1]; double val[1+1]; ind[1] = k; val[1] = 1.0; xassert(csa->valid); ret = bfd_update_it(csa->bfd, i, 0, 1, ind, val); } else { /* new i-th column of B is (k-m)-th column of (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; double *val = csa->work1; int beg, end, ptr, len; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; len = 0; for (ptr = beg; ptr < end; ptr++) val[++len] = - A_val[ptr]; xassert(csa->valid); ret = bfd_update_it(csa->bfd, i, 0, len, &A_ind[beg-1], val); } csa->valid = (ret == 0); return ret; } /*********************************************************************** * error_ftran - compute residual vector r = h - B * x * * This routine computes the residual vector r = h - B * x, where B is * the current basis matrix, h is the vector of right-hand sides, x is * the solution vector. */ static void error_ftran(struct csa *csa, double h[], double x[], double r[]) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; int i, k, beg, end, ptr; double temp; /* compute the residual vector: r = h - B * x = h - B[1] * x[1] - ... - B[m] * x[m], where B[1], ..., B[m] are columns of matrix B */ memcpy(&r[1], &h[1], m * sizeof(double)); for (i = 1; i <= m; i++) { temp = x[i]; if (temp == 0.0) continue; k = head[i]; /* B[i] is k-th column of (I|-A) */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* B[i] is k-th column of submatrix I */ r[k] -= temp; } else { /* B[i] is (k-m)-th column of submatrix (-A) */ beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) r[A_ind[ptr]] += A_val[ptr] * temp; } } return; } /*********************************************************************** * refine_ftran - refine solution of B * x = h * * This routine performs one iteration to refine the solution of * the system B * x = h, where B is the current basis matrix, h is the * vector of right-hand sides, x is the solution vector. */ static void refine_ftran(struct csa *csa, double h[], double x[]) { int m = csa->m; double *r = csa->work1; double *d = csa->work1; int i; /* compute the residual vector r = h - B * x */ error_ftran(csa, h, x, r); /* compute the correction vector d = inv(B) * r */ xassert(csa->valid); bfd_ftran(csa->bfd, d); /* refine the solution vector (new x) = (old x) + d */ for (i = 1; i <= m; i++) x[i] += d[i]; return; } /*********************************************************************** * error_btran - compute residual vector r = h - B'* x * * This routine computes the residual vector r = h - B'* x, where B' * is a matrix transposed to the current basis matrix, h is the vector * of right-hand sides, x is the solution vector. */ static void error_btran(struct csa *csa, double h[], double x[], double r[]) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; int i, k, beg, end, ptr; double temp; /* compute the residual vector r = b - B'* x */ for (i = 1; i <= m; i++) { /* r[i] := b[i] - (i-th column of B)'* x */ k = head[i]; /* B[i] is k-th column of (I|-A) */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif temp = h[i]; if (k <= m) { /* B[i] is k-th column of submatrix I */ temp -= x[k]; } else { /* B[i] is (k-m)-th column of submatrix (-A) */ beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) temp += A_val[ptr] * x[A_ind[ptr]]; } r[i] = temp; } return; } /*********************************************************************** * refine_btran - refine solution of B'* x = h * * This routine performs one iteration to refine the solution of the * system B'* x = h, where B' is a matrix transposed to the current * basis matrix, h is the vector of right-hand sides, x is the solution * vector. */ static void refine_btran(struct csa *csa, double h[], double x[]) { int m = csa->m; double *r = csa->work1; double *d = csa->work1; int i; /* compute the residual vector r = h - B'* x */ error_btran(csa, h, x, r); /* compute the correction vector d = inv(B') * r */ xassert(csa->valid); bfd_btran(csa->bfd, d); /* refine the solution vector (new x) = (old x) + d */ for (i = 1; i <= m; i++) x[i] += d[i]; return; } /*********************************************************************** * alloc_N - allocate matrix N * * This routine determines maximal row lengths of matrix N, sets its * row pointers, and then allocates arrays N_ind and N_val. * * Note that some fixed structural variables may temporarily become * double-bounded, so corresponding columns of matrix A should not be * ignored on calculating maximal row lengths of matrix N. */ static void alloc_N(struct csa *csa) { int m = csa->m; int n = csa->n; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; int *N_ptr = csa->N_ptr; int *N_len = csa->N_len; int i, j, beg, end, ptr; /* determine number of non-zeros in each row of the augmented constraint matrix (I|-A) */ for (i = 1; i <= m; i++) N_len[i] = 1; for (j = 1; j <= n; j++) { beg = A_ptr[j]; end = A_ptr[j+1]; for (ptr = beg; ptr < end; ptr++) N_len[A_ind[ptr]]++; } /* determine maximal row lengths of matrix N and set its row pointers */ N_ptr[1] = 1; for (i = 1; i <= m; i++) { /* row of matrix N cannot have more than n non-zeros */ if (N_len[i] > n) N_len[i] = n; N_ptr[i+1] = N_ptr[i] + N_len[i]; } /* now maximal number of non-zeros in matrix N is known */ csa->N_ind = xcalloc(N_ptr[m+1], sizeof(int)); csa->N_val = xcalloc(N_ptr[m+1], sizeof(double)); return; } /*********************************************************************** * add_N_col - add column of matrix (I|-A) to matrix N * * This routine adds j-th column to matrix N which is k-th column of * the augmented constraint matrix (I|-A). (It is assumed that old j-th * column was previously removed from matrix N.) */ static void add_N_col(struct csa *csa, int j, int k) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *N_ptr = csa->N_ptr; int *N_len = csa->N_len; int *N_ind = csa->N_ind; double *N_val = csa->N_val; int pos; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* N[j] is k-th column of submatrix I */ pos = N_ptr[k] + (N_len[k]++); #ifdef GLP_DEBUG xassert(pos < N_ptr[k+1]); #endif N_ind[pos] = j; N_val[pos] = 1.0; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int i, beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) { i = A_ind[ptr]; /* row number */ pos = N_ptr[i] + (N_len[i]++); #ifdef GLP_DEBUG xassert(pos < N_ptr[i+1]); #endif N_ind[pos] = j; N_val[pos] = - A_val[ptr]; } } return; } /*********************************************************************** * del_N_col - remove column of matrix (I|-A) from matrix N * * This routine removes j-th column from matrix N which is k-th column * of the augmented constraint matrix (I|-A). */ static void del_N_col(struct csa *csa, int j, int k) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *N_ptr = csa->N_ptr; int *N_len = csa->N_len; int *N_ind = csa->N_ind; double *N_val = csa->N_val; int pos, head, tail; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* N[j] is k-th column of submatrix I */ /* find element in k-th row of N */ head = N_ptr[k]; for (pos = head; N_ind[pos] != j; pos++) /* nop */; /* and remove it from the row list */ tail = head + (--N_len[k]); #ifdef GLP_DEBUG xassert(pos <= tail); #endif N_ind[pos] = N_ind[tail]; N_val[pos] = N_val[tail]; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; int i, beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) { i = A_ind[ptr]; /* row number */ /* find element in i-th row of N */ head = N_ptr[i]; for (pos = head; N_ind[pos] != j; pos++) /* nop */; /* and remove it from the row list */ tail = head + (--N_len[i]); #ifdef GLP_DEBUG xassert(pos <= tail); #endif N_ind[pos] = N_ind[tail]; N_val[pos] = N_val[tail]; } } return; } /*********************************************************************** * build_N - build matrix N for current basis * * This routine builds matrix N for the current basis from columns * of the augmented constraint matrix (I|-A) corresponding to non-basic * non-fixed variables. */ static void build_N(struct csa *csa) { int m = csa->m; int n = csa->n; int *head = csa->head; char *stat = csa->stat; int *N_len = csa->N_len; int j, k; /* N := empty matrix */ memset(&N_len[1], 0, m * sizeof(int)); /* go through non-basic columns of matrix (I|-A) */ for (j = 1; j <= n; j++) { if (stat[j] != GLP_NS) { /* xN[j] is non-fixed; add j-th column to matrix N which is k-th column of matrix (I|-A) */ k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif add_N_col(csa, j, k); } } return; } /*********************************************************************** * get_xN - determine current value of non-basic variable xN[j] * * This routine returns the current value of non-basic variable xN[j], * which is a value of its active bound. */ static double get_xN(struct csa *csa, int j) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif double *lb = csa->lb; double *ub = csa->ub; int *head = csa->head; char *stat = csa->stat; int k; double xN; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif switch (stat[j]) { case GLP_NL: /* x[k] is on its lower bound */ xN = lb[k]; break; case GLP_NU: /* x[k] is on its upper bound */ xN = ub[k]; break; case GLP_NF: /* x[k] is free non-basic variable */ xN = 0.0; break; case GLP_NS: /* x[k] is fixed non-basic variable */ xN = lb[k]; break; default: xassert(stat != stat); } return xN; } /*********************************************************************** * eval_beta - compute primal values of basic variables * * This routine computes current primal values of all basic variables: * * beta = - inv(B) * N * xN, * * where B is the current basis matrix, N is a matrix built of columns * of matrix (I|-A) corresponding to non-basic variables, and xN is the * vector of current values of non-basic variables. */ static void eval_beta(struct csa *csa, double beta[]) { int m = csa->m; int n = csa->n; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; double *h = csa->work2; int i, j, k, beg, end, ptr; double xN; /* compute the right-hand side vector: h := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n], where N[1], ..., N[n] are columns of matrix N */ for (i = 1; i <= m; i++) h[i] = 0.0; for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* determine current value of xN[j] */ xN = get_xN(csa, j); if (xN == 0.0) continue; if (k <= m) { /* N[j] is k-th column of submatrix I */ h[k] -= xN; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] += xN * A_val[ptr]; } } /* solve system B * beta = h */ memcpy(&beta[1], &h[1], m * sizeof(double)); xassert(csa->valid); bfd_ftran(csa->bfd, beta); /* and refine the solution */ refine_ftran(csa, h, beta); return; } /*********************************************************************** * eval_pi - compute vector of simplex multipliers * * This routine computes the vector of current simplex multipliers: * * pi = inv(B') * cB, * * where B' is a matrix transposed to the current basis matrix, cB is * a subvector of objective coefficients at basic variables. */ static void eval_pi(struct csa *csa, double pi[]) { int m = csa->m; double *c = csa->coef; int *head = csa->head; double *cB = csa->work2; int i; /* construct the right-hand side vector cB */ for (i = 1; i <= m; i++) cB[i] = c[head[i]]; /* solve system B'* pi = cB */ memcpy(&pi[1], &cB[1], m * sizeof(double)); xassert(csa->valid); bfd_btran(csa->bfd, pi); /* and refine the solution */ refine_btran(csa, cB, pi); return; } /*********************************************************************** * eval_cost - compute reduced cost of non-basic variable xN[j] * * This routine computes the current reduced cost of non-basic variable * xN[j]: * * d[j] = cN[j] - N'[j] * pi, * * where cN[j] is the objective coefficient at variable xN[j], N[j] is * a column of the augmented constraint matrix (I|-A) corresponding to * xN[j], pi is the vector of simplex multipliers. */ static double eval_cost(struct csa *csa, double pi[], int j) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif double *coef = csa->coef; int *head = csa->head; int k; double dj; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif dj = coef[k]; if (k <= m) { /* N[j] is k-th column of submatrix I */ dj -= pi[k]; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) dj += A_val[ptr] * pi[A_ind[ptr]]; } return dj; } /*********************************************************************** * eval_bbar - compute and store primal values of basic variables * * This routine computes primal values of all basic variables and then * stores them in the solution array. */ static void eval_bbar(struct csa *csa) { eval_beta(csa, csa->bbar); return; } /*********************************************************************** * eval_cbar - compute and store reduced costs of non-basic variables * * This routine computes reduced costs of all non-basic variables and * then stores them in the solution array. */ static void eval_cbar(struct csa *csa) { #ifdef GLP_DEBUG int m = csa->m; #endif int n = csa->n; #ifdef GLP_DEBUG int *head = csa->head; #endif double *cbar = csa->cbar; double *pi = csa->work3; int j; #ifdef GLP_DEBUG int k; #endif /* compute simplex multipliers */ eval_pi(csa, pi); /* compute and store reduced costs */ for (j = 1; j <= n; j++) { #ifdef GLP_DEBUG k = head[m+j]; /* x[k] = xN[j] */ xassert(1 <= k && k <= m+n); #endif cbar[j] = eval_cost(csa, pi, j); } return; } /*********************************************************************** * reset_refsp - reset the reference space * * This routine resets (redefines) the reference space used in the * projected steepest edge pricing algorithm. */ static void reset_refsp(struct csa *csa) { int m = csa->m; int n = csa->n; int *head = csa->head; char *refsp = csa->refsp; double *gamma = csa->gamma; int j, k; xassert(csa->refct == 0); csa->refct = 1000; memset(&refsp[1], 0, (m+n) * sizeof(char)); for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ refsp[k] = 1; gamma[j] = 1.0; } return; } /*********************************************************************** * eval_gamma - compute steepest edge coefficient * * This routine computes the steepest edge coefficient for non-basic * variable xN[j] using its direct definition: * * gamma[j] = delta[j] + sum alfa[i,j]^2, * i in R * * where delta[j] = 1, if xN[j] is in the current reference space, * and 0 otherwise; R is a set of basic variables xB[i], which are in * the current reference space; alfa[i,j] are elements of the current * simplex table. * * NOTE: The routine is intended only for debugginig purposes. */ static double eval_gamma(struct csa *csa, int j) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *head = csa->head; char *refsp = csa->refsp; double *alfa = csa->work3; double *h = csa->work3; int i, k; double gamma; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* construct the right-hand side vector h = - N[j] */ for (i = 1; i <= m; i++) h[i] = 0.0; if (k <= m) { /* N[j] is k-th column of submatrix I */ h[k] = -1.0; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] = A_val[ptr]; } /* solve system B * alfa = h */ xassert(csa->valid); bfd_ftran(csa->bfd, alfa); /* compute gamma */ gamma = (refsp[k] ? 1.0 : 0.0); for (i = 1; i <= m; i++) { k = head[i]; #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (refsp[k]) gamma += alfa[i] * alfa[i]; } return gamma; } /*********************************************************************** * chuzc - choose non-basic variable (column of the simplex table) * * This routine chooses non-basic variable xN[q], which has largest * weighted reduced cost: * * |d[q]| / sqrt(gamma[q]) = max |d[j]| / sqrt(gamma[j]), * j in J * * where J is a subset of eligible non-basic variables xN[j], d[j] is * reduced cost of xN[j], gamma[j] is the steepest edge coefficient. * * The working objective function is always minimized, so the sign of * d[q] determines direction, in which xN[q] has to change: * * if d[q] < 0, xN[q] has to increase; * * if d[q] > 0, xN[q] has to decrease. * * If |d[j]| <= tol_dj, where tol_dj is a specified tolerance, xN[j] * is not included in J and therefore ignored. (It is assumed that the * working objective row is appropriately scaled, i.e. max|c[k]| = 1.) * * If J is empty and no variable has been chosen, q is set to 0. */ static void chuzc(struct csa *csa, double tol_dj) { int n = csa->n; char *stat = csa->stat; double *cbar = csa->cbar; double *gamma = csa->gamma; int j, q; double dj, best, temp; /* nothing is chosen so far */ q = 0, best = 0.0; /* look through the list of non-basic variables */ for (j = 1; j <= n; j++) { dj = cbar[j]; switch (stat[j]) { case GLP_NL: /* xN[j] can increase */ if (dj >= - tol_dj) continue; break; case GLP_NU: /* xN[j] can decrease */ if (dj <= + tol_dj) continue; break; case GLP_NF: /* xN[j] can change in any direction */ if (- tol_dj <= dj && dj <= + tol_dj) continue; break; case GLP_NS: /* xN[j] cannot change at all */ continue; default: xassert(stat != stat); } /* xN[j] is eligible non-basic variable; choose one which has largest weighted reduced cost */ #ifdef GLP_DEBUG xassert(gamma[j] > 0.0); #endif temp = (dj * dj) / gamma[j]; if (best < temp) q = j, best = temp; } /* store the index of non-basic variable xN[q] chosen */ csa->q = q; return; } /*********************************************************************** * eval_tcol - compute pivot column of the simplex table * * This routine computes the pivot column of the simplex table, which * corresponds to non-basic variable xN[q] chosen. * * The pivot column is the following vector: * * tcol = T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], * * where B is the current basis matrix, N[q] is a column of the matrix * (I|-A) corresponding to variable xN[q]. */ static void eval_tcol(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *head = csa->head; int q = csa->q; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; double *h = csa->tcol_vec; int i, k, nnz; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif k = head[m+q]; /* x[k] = xN[q] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* construct the right-hand side vector h = - N[q] */ for (i = 1; i <= m; i++) h[i] = 0.0; if (k <= m) { /* N[q] is k-th column of submatrix I */ h[k] = -1.0; } else { /* N[q] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] = A_val[ptr]; } /* solve system B * tcol = h */ xassert(csa->valid); bfd_ftran(csa->bfd, tcol_vec); /* construct sparse pattern of the pivot column */ nnz = 0; for (i = 1; i <= m; i++) { if (tcol_vec[i] != 0.0) tcol_ind[++nnz] = i; } csa->tcol_nnz = nnz; return; } /*********************************************************************** * refine_tcol - refine pivot column of the simplex table * * This routine refines the pivot column of the simplex table assuming * that it was previously computed by the routine eval_tcol. */ static void refine_tcol(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *head = csa->head; int q = csa->q; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; double *h = csa->work3; int i, k, nnz; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif k = head[m+q]; /* x[k] = xN[q] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* construct the right-hand side vector h = - N[q] */ for (i = 1; i <= m; i++) h[i] = 0.0; if (k <= m) { /* N[q] is k-th column of submatrix I */ h[k] = -1.0; } else { /* N[q] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] = A_val[ptr]; } /* refine solution of B * tcol = h */ refine_ftran(csa, h, tcol_vec); /* construct sparse pattern of the pivot column */ nnz = 0; for (i = 1; i <= m; i++) { if (tcol_vec[i] != 0.0) tcol_ind[++nnz] = i; } csa->tcol_nnz = nnz; return; } /*********************************************************************** * sort_tcol - sort pivot column of the simplex table * * This routine reorders the list of non-zero elements of the pivot * column to put significant elements, whose magnitude is not less than * a specified tolerance, in front of the list, and stores the number * of significant elements in tcol_num. */ static void sort_tcol(struct csa *csa, double tol_piv) { #ifdef GLP_DEBUG int m = csa->m; #endif int nnz = csa->tcol_nnz; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; int i, num, pos; double big, eps, temp; /* compute infinity (maximum) norm of the column */ big = 0.0; for (pos = 1; pos <= nnz; pos++) { #ifdef GLP_DEBUG i = tcol_ind[pos]; xassert(1 <= i && i <= m); #endif temp = fabs(tcol_vec[tcol_ind[pos]]); if (big < temp) big = temp; } csa->tcol_max = big; /* determine absolute pivot tolerance */ eps = tol_piv * (1.0 + 0.01 * big); /* move significant column components to front of the list */ for (num = 0; num < nnz; ) { i = tcol_ind[nnz]; if (fabs(tcol_vec[i]) < eps) nnz--; else { num++; tcol_ind[nnz] = tcol_ind[num]; tcol_ind[num] = i; } } csa->tcol_num = num; return; } /*********************************************************************** * chuzr - choose basic variable (row of the simplex table) * * This routine chooses basic variable xB[p], which reaches its bound * first on changing non-basic variable xN[q] in valid direction. * * The parameter rtol is a relative tolerance used to relax bounds of * basic variables. If rtol = 0, the routine implements the standard * ratio test. Otherwise, if rtol > 0, the routine implements Harris' * two-pass ratio test. In the latter case rtol should be about three * times less than a tolerance used to check primal feasibility. */ static void chuzr(struct csa *csa, double rtol) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; double *coef = csa->coef; int *head = csa->head; int phase = csa->phase; double *bbar = csa->bbar; double *cbar = csa->cbar; int q = csa->q; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; int tcol_num = csa->tcol_num; int i, i_stat, k, p, p_stat, pos; double alfa, big, delta, s, t, teta, tmax; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif /* s := - sign(d[q]), where d[q] is reduced cost of xN[q] */ #ifdef GLP_DEBUG xassert(cbar[q] != 0.0); #endif s = (cbar[q] > 0.0 ? -1.0 : +1.0); /*** FIRST PASS ***/ k = head[m+q]; /* x[k] = xN[q] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (type[k] == GLP_DB) { /* xN[q] has both lower and upper bounds */ p = -1, p_stat = 0, teta = ub[k] - lb[k], big = 1.0; } else { /* xN[q] has no opposite bound */ p = 0, p_stat = 0, teta = DBL_MAX, big = 0.0; } /* walk through significant elements of the pivot column */ for (pos = 1; pos <= tcol_num; pos++) { i = tcol_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); #endif k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif alfa = s * tcol_vec[i]; #ifdef GLP_DEBUG xassert(alfa != 0.0); #endif /* xB[i] = ... + alfa * xN[q] + ..., and due to s we need to consider the only case when xN[q] is increasing */ if (alfa > 0.0) { /* xB[i] is increasing */ if (phase == 1 && coef[k] < 0.0) { /* xB[i] violates its lower bound, which plays the role of an upper bound on phase I */ delta = rtol * (1.0 + kappa * fabs(lb[k])); t = ((lb[k] + delta) - bbar[i]) / alfa; i_stat = GLP_NL; } else if (phase == 1 && coef[k] > 0.0) { /* xB[i] violates its upper bound, which plays the role of an lower bound on phase I */ continue; } else if (type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX) { /* xB[i] is within its bounds and has an upper bound */ delta = rtol * (1.0 + kappa * fabs(ub[k])); t = ((ub[k] + delta) - bbar[i]) / alfa; i_stat = GLP_NU; } else { /* xB[i] is within its bounds and has no upper bound */ continue; } } else { /* xB[i] is decreasing */ if (phase == 1 && coef[k] > 0.0) { /* xB[i] violates its upper bound, which plays the role of an lower bound on phase I */ delta = rtol * (1.0 + kappa * fabs(ub[k])); t = ((ub[k] - delta) - bbar[i]) / alfa; i_stat = GLP_NU; } else if (phase == 1 && coef[k] < 0.0) { /* xB[i] violates its lower bound, which plays the role of an upper bound on phase I */ continue; } else if (type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX) { /* xB[i] is within its bounds and has an lower bound */ delta = rtol * (1.0 + kappa * fabs(lb[k])); t = ((lb[k] - delta) - bbar[i]) / alfa; i_stat = GLP_NL; } else { /* xB[i] is within its bounds and has no lower bound */ continue; } } /* t is a change of xN[q], on which xB[i] reaches its bound (possibly relaxed); since the basic solution is assumed to be primal feasible (or pseudo feasible on phase I), t has to be non-negative by definition; however, it may happen that xB[i] slightly (i.e. within a tolerance) violates its bound, that leads to negative t; in the latter case, if xB[i] is chosen, negative t means that xN[q] changes in wrong direction; if pivot alfa[i,q] is close to zero, even small bound violation of xB[i] may lead to a large change of xN[q] in wrong direction; let, for example, xB[i] >= 0 and in the current basis its value be -5e-9; let also xN[q] be on its zero bound and should increase; from the ratio test rule it follows that the pivot alfa[i,q] < 0; however, if alfa[i,q] is, say, -1e-9, the change of xN[q] in wrong direction is 5e-9 / (-1e-9) = -5, and using it for updating values of other basic variables will give absolutely wrong results; therefore, if t is negative, we should replace it by exact zero assuming that xB[i] is exactly on its bound, and the violation appears due to round-off errors */ if (t < 0.0) t = 0.0; /* apply minimal ratio test */ if (teta > t || teta == t && big < fabs(alfa)) p = i, p_stat = i_stat, teta = t, big = fabs(alfa); } /* the second pass is skipped in the following cases: */ /* if the standard ratio test is used */ if (rtol == 0.0) goto done; /* if xN[q] reaches its opposite bound or if no basic variable has been chosen on the first pass */ if (p <= 0) goto done; /* if xB[p] is a blocking variable, i.e. if it prevents xN[q] from any change */ if (teta == 0.0) goto done; /*** SECOND PASS ***/ /* here tmax is a maximal change of xN[q], on which the solution remains primal feasible (or pseudo feasible on phase I) within a tolerance */ #if 0 tmax = (1.0 + 10.0 * DBL_EPSILON) * teta; #else tmax = teta; #endif /* nothing is chosen so far */ p = 0, p_stat = 0, teta = DBL_MAX, big = 0.0; /* walk through significant elements of the pivot column */ for (pos = 1; pos <= tcol_num; pos++) { i = tcol_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); #endif k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif alfa = s * tcol_vec[i]; #ifdef GLP_DEBUG xassert(alfa != 0.0); #endif /* xB[i] = ... + alfa * xN[q] + ..., and due to s we need to consider the only case when xN[q] is increasing */ if (alfa > 0.0) { /* xB[i] is increasing */ if (phase == 1 && coef[k] < 0.0) { /* xB[i] violates its lower bound, which plays the role of an upper bound on phase I */ t = (lb[k] - bbar[i]) / alfa; i_stat = GLP_NL; } else if (phase == 1 && coef[k] > 0.0) { /* xB[i] violates its upper bound, which plays the role of an lower bound on phase I */ continue; } else if (type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX) { /* xB[i] is within its bounds and has an upper bound */ t = (ub[k] - bbar[i]) / alfa; i_stat = GLP_NU; } else { /* xB[i] is within its bounds and has no upper bound */ continue; } } else { /* xB[i] is decreasing */ if (phase == 1 && coef[k] > 0.0) { /* xB[i] violates its upper bound, which plays the role of an lower bound on phase I */ t = (ub[k] - bbar[i]) / alfa; i_stat = GLP_NU; } else if (phase == 1 && coef[k] < 0.0) { /* xB[i] violates its lower bound, which plays the role of an upper bound on phase I */ continue; } else if (type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX) { /* xB[i] is within its bounds and has an lower bound */ t = (lb[k] - bbar[i]) / alfa; i_stat = GLP_NL; } else { /* xB[i] is within its bounds and has no lower bound */ continue; } } /* (see comments for the first pass) */ if (t < 0.0) t = 0.0; /* t is a change of xN[q], on which xB[i] reaches its bound; if t <= tmax, all basic variables can violate their bounds only within relaxation tolerance delta; we can use this freedom and choose basic variable having largest influence coefficient to avoid possible numeric instability */ if (t <= tmax && big < fabs(alfa)) p = i, p_stat = i_stat, teta = t, big = fabs(alfa); } /* something must be chosen on the second pass */ xassert(p != 0); done: /* store the index and status of basic variable xB[p] chosen */ csa->p = p; if (p > 0 && type[head[p]] == GLP_FX) csa->p_stat = GLP_NS; else csa->p_stat = p_stat; /* store corresponding change of non-basic variable xN[q] */ #ifdef GLP_DEBUG xassert(teta >= 0.0); #endif csa->teta = s * teta; return; } /*********************************************************************** * eval_rho - compute pivot row of the inverse * * This routine computes the pivot (p-th) row of the inverse inv(B), * which corresponds to basic variable xB[p] chosen: * * rho = inv(B') * e[p], * * where B' is a matrix transposed to the current basis matrix, e[p] * is unity vector. */ static void eval_rho(struct csa *csa, double rho[]) { int m = csa->m; int p = csa->p; double *e = rho; int i; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); #endif /* construct the right-hand side vector e[p] */ for (i = 1; i <= m; i++) e[i] = 0.0; e[p] = 1.0; /* solve system B'* rho = e[p] */ xassert(csa->valid); bfd_btran(csa->bfd, rho); return; } /*********************************************************************** * refine_rho - refine pivot row of the inverse * * This routine refines the pivot row of the inverse inv(B) assuming * that it was previously computed by the routine eval_rho. */ static void refine_rho(struct csa *csa, double rho[]) { int m = csa->m; int p = csa->p; double *e = csa->work3; int i; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); #endif /* construct the right-hand side vector e[p] */ for (i = 1; i <= m; i++) e[i] = 0.0; e[p] = 1.0; /* refine solution of B'* rho = e[p] */ refine_btran(csa, e, rho); return; } /*********************************************************************** * eval_trow - compute pivot row of the simplex table * * This routine computes the pivot row of the simplex table, which * corresponds to basic variable xB[p] chosen. * * The pivot row is the following vector: * * trow = T'* e[p] = - N'* inv(B') * e[p] = - N' * rho, * * where rho is the pivot row of the inverse inv(B) previously computed * by the routine eval_rho. * * Note that elements of the pivot row corresponding to fixed non-basic * variables are not computed. */ static void eval_trow(struct csa *csa, double rho[]) { int m = csa->m; int n = csa->n; #ifdef GLP_DEBUG char *stat = csa->stat; #endif int *N_ptr = csa->N_ptr; int *N_len = csa->N_len; int *N_ind = csa->N_ind; double *N_val = csa->N_val; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int i, j, beg, end, ptr, nnz; double temp; /* clear the pivot row */ for (j = 1; j <= n; j++) trow_vec[j] = 0.0; /* compute the pivot row as a linear combination of rows of the matrix N: trow = - rho[1] * N'[1] - ... - rho[m] * N'[m] */ for (i = 1; i <= m; i++) { temp = rho[i]; if (temp == 0.0) continue; /* trow := trow - rho[i] * N'[i] */ beg = N_ptr[i]; end = beg + N_len[i]; for (ptr = beg; ptr < end; ptr++) { #ifdef GLP_DEBUG j = N_ind[ptr]; xassert(1 <= j && j <= n); xassert(stat[j] != GLP_NS); #endif trow_vec[N_ind[ptr]] -= temp * N_val[ptr]; } } /* construct sparse pattern of the pivot row */ nnz = 0; for (j = 1; j <= n; j++) { if (trow_vec[j] != 0.0) trow_ind[++nnz] = j; } csa->trow_nnz = nnz; return; } /*********************************************************************** * update_bbar - update values of basic variables * * This routine updates values of all basic variables for the adjacent * basis. */ static void update_bbar(struct csa *csa) { #ifdef GLP_DEBUG int m = csa->m; int n = csa->n; #endif double *bbar = csa->bbar; int q = csa->q; int tcol_nnz = csa->tcol_nnz; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; int p = csa->p; double teta = csa->teta; int i, pos; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); xassert(p < 0 || 1 <= p && p <= m); #endif /* if xN[q] leaves the basis, compute its value in the adjacent basis, where it will replace xB[p] */ if (p > 0) bbar[p] = get_xN(csa, q) + teta; /* update values of other basic variables (except xB[p], because it will be replaced by xN[q]) */ if (teta == 0.0) goto done; for (pos = 1; pos <= tcol_nnz; pos++) { i = tcol_ind[pos]; /* skip xB[p] */ if (i == p) continue; /* (change of xB[i]) = alfa[i,q] * (change of xN[q]) */ bbar[i] += tcol_vec[i] * teta; } done: return; } /*********************************************************************** * reeval_cost - recompute reduced cost of non-basic variable xN[q] * * This routine recomputes reduced cost of non-basic variable xN[q] for * the current basis more accurately using its direct definition: * * d[q] = cN[q] - N'[q] * pi = * * = cN[q] - N'[q] * (inv(B') * cB) = * * = cN[q] - (cB' * inv(B) * N[q]) = * * = cN[q] + cB' * (pivot column). * * It is assumed that the pivot column of the simplex table is already * computed. */ static double reeval_cost(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif double *coef = csa->coef; int *head = csa->head; int q = csa->q; int tcol_nnz = csa->tcol_nnz; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; int i, pos; double dq; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif dq = coef[head[m+q]]; for (pos = 1; pos <= tcol_nnz; pos++) { i = tcol_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); #endif dq += coef[head[i]] * tcol_vec[i]; } return dq; } /*********************************************************************** * update_cbar - update reduced costs of non-basic variables * * This routine updates reduced costs of all (except fixed) non-basic * variables for the adjacent basis. */ static void update_cbar(struct csa *csa) { #ifdef GLP_DEBUG int n = csa->n; #endif double *cbar = csa->cbar; int q = csa->q; int trow_nnz = csa->trow_nnz; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int j, pos; double new_dq; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif /* compute reduced cost of xB[p] in the adjacent basis, where it will replace xN[q] */ #ifdef GLP_DEBUG xassert(trow_vec[q] != 0.0); #endif new_dq = (cbar[q] /= trow_vec[q]); /* update reduced costs of other non-basic variables (except xN[q], because it will be replaced by xB[p]) */ for (pos = 1; pos <= trow_nnz; pos++) { j = trow_ind[pos]; /* skip xN[q] */ if (j == q) continue; cbar[j] -= trow_vec[j] * new_dq; } return; } /*********************************************************************** * update_gamma - update steepest edge coefficients * * This routine updates steepest-edge coefficients for the adjacent * basis. */ static void update_gamma(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; char *refsp = csa->refsp; double *gamma = csa->gamma; int q = csa->q; int tcol_nnz = csa->tcol_nnz; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; int p = csa->p; int trow_nnz = csa->trow_nnz; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; double *u = csa->work3; int i, j, k, pos, beg, end, ptr; double gamma_q, delta_q, pivot, s, t, t1, t2; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); #endif /* the basis changes, so decrease the count */ xassert(csa->refct > 0); csa->refct--; /* recompute gamma[q] for the current basis more accurately and compute auxiliary vector u */ gamma_q = delta_q = (refsp[head[m+q]] ? 1.0 : 0.0); for (i = 1; i <= m; i++) u[i] = 0.0; for (pos = 1; pos <= tcol_nnz; pos++) { i = tcol_ind[pos]; if (refsp[head[i]]) { u[i] = t = tcol_vec[i]; gamma_q += t * t; } else u[i] = 0.0; } xassert(csa->valid); bfd_btran(csa->bfd, u); /* update gamma[k] for other non-basic variables (except fixed variables and xN[q], because it will be replaced by xB[p]) */ pivot = trow_vec[q]; #ifdef GLP_DEBUG xassert(pivot != 0.0); #endif for (pos = 1; pos <= trow_nnz; pos++) { j = trow_ind[pos]; /* skip xN[q] */ if (j == q) continue; /* compute t */ t = trow_vec[j] / pivot; /* compute inner product s = N'[j] * u */ k = head[m+j]; /* x[k] = xN[j] */ if (k <= m) s = u[k]; else { s = 0.0; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) s -= A_val[ptr] * u[A_ind[ptr]]; } /* compute gamma[k] for the adjacent basis */ t1 = gamma[j] + t * t * gamma_q + 2.0 * t * s; t2 = (refsp[k] ? 1.0 : 0.0) + delta_q * t * t; gamma[j] = (t1 >= t2 ? t1 : t2); if (gamma[j] < DBL_EPSILON) gamma[j] = DBL_EPSILON; } /* compute gamma[q] for the adjacent basis */ if (type[head[p]] == GLP_FX) gamma[q] = 1.0; else { gamma[q] = gamma_q / (pivot * pivot); if (gamma[q] < DBL_EPSILON) gamma[q] = DBL_EPSILON; } return; } /*********************************************************************** * err_in_bbar - compute maximal relative error in primal solution * * This routine returns maximal relative error: * * max |beta[i] - bbar[i]| / (1 + |beta[i]|), * * where beta and bbar are, respectively, directly computed and the * current (updated) values of basic variables. * * NOTE: The routine is intended only for debugginig purposes. */ static double err_in_bbar(struct csa *csa) { int m = csa->m; double *bbar = csa->bbar; int i; double e, emax, *beta; beta = xcalloc(1+m, sizeof(double)); eval_beta(csa, beta); emax = 0.0; for (i = 1; i <= m; i++) { e = fabs(beta[i] - bbar[i]) / (1.0 + fabs(beta[i])); if (emax < e) emax = e; } xfree(beta); return emax; } /*********************************************************************** * err_in_cbar - compute maximal relative error in dual solution * * This routine returns maximal relative error: * * max |cost[j] - cbar[j]| / (1 + |cost[j]|), * * where cost and cbar are, respectively, directly computed and the * current (updated) reduced costs of non-basic non-fixed variables. * * NOTE: The routine is intended only for debugginig purposes. */ static double err_in_cbar(struct csa *csa) { int m = csa->m; int n = csa->n; char *stat = csa->stat; double *cbar = csa->cbar; int j; double e, emax, cost, *pi; pi = xcalloc(1+m, sizeof(double)); eval_pi(csa, pi); emax = 0.0; for (j = 1; j <= n; j++) { if (stat[j] == GLP_NS) continue; cost = eval_cost(csa, pi, j); e = fabs(cost - cbar[j]) / (1.0 + fabs(cost)); if (emax < e) emax = e; } xfree(pi); return emax; } /*********************************************************************** * err_in_gamma - compute maximal relative error in steepest edge cff. * * This routine returns maximal relative error: * * max |gamma'[j] - gamma[j]| / (1 + |gamma'[j]), * * where gamma'[j] and gamma[j] are, respectively, directly computed * and the current (updated) steepest edge coefficients for non-basic * non-fixed variable x[j]. * * NOTE: The routine is intended only for debugginig purposes. */ static double err_in_gamma(struct csa *csa) { int n = csa->n; char *stat = csa->stat; double *gamma = csa->gamma; int j; double e, emax, temp; emax = 0.0; for (j = 1; j <= n; j++) { if (stat[j] == GLP_NS) { xassert(gamma[j] == 1.0); continue; } temp = eval_gamma(csa, j); e = fabs(temp - gamma[j]) / (1.0 + fabs(temp)); if (emax < e) emax = e; } return emax; } /*********************************************************************** * change_basis - change basis header * * This routine changes the basis header to make it corresponding to * the adjacent basis. */ static void change_basis(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; char *type = csa->type; #endif int *head = csa->head; char *stat = csa->stat; int q = csa->q; int p = csa->p; int p_stat = csa->p_stat; int k; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif if (p < 0) { /* xN[q] goes to its opposite bound */ #ifdef GLP_DEBUG k = head[m+q]; /* x[k] = xN[q] */ xassert(1 <= k && k <= m+n); xassert(type[k] == GLP_DB); #endif switch (stat[q]) { case GLP_NL: /* xN[q] increases */ stat[q] = GLP_NU; break; case GLP_NU: /* xN[q] decreases */ stat[q] = GLP_NL; break; default: xassert(stat != stat); } } else { /* xB[p] leaves the basis, xN[q] enters the basis */ #ifdef GLP_DEBUG xassert(1 <= p && p <= m); k = head[p]; /* x[k] = xB[p] */ switch (p_stat) { case GLP_NL: /* xB[p] goes to its lower bound */ xassert(type[k] == GLP_LO || type[k] == GLP_DB); break; case GLP_NU: /* xB[p] goes to its upper bound */ xassert(type[k] == GLP_UP || type[k] == GLP_DB); break; case GLP_NS: /* xB[p] goes to its fixed value */ xassert(type[k] == GLP_NS); break; default: xassert(p_stat != p_stat); } #endif /* xB[p] <-> xN[q] */ k = head[p], head[p] = head[m+q], head[m+q] = k; stat[q] = (char)p_stat; } return; } /*********************************************************************** * set_aux_obj - construct auxiliary objective function * * The auxiliary objective function is a separable piecewise linear * convex function, which is the sum of primal infeasibilities: * * z = t[1] + ... + t[m+n] -> minimize, * * where: * * / lb[k] - x[k], if x[k] < lb[k] * | * t[k] = < 0, if lb[k] <= x[k] <= ub[k] * | * \ x[k] - ub[k], if x[k] > ub[k] * * This routine computes objective coefficients for the current basis * and returns the number of non-zero terms t[k]. */ static int set_aux_obj(struct csa *csa, double tol_bnd) { int m = csa->m; int n = csa->n; char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; double *coef = csa->coef; int *head = csa->head; double *bbar = csa->bbar; int i, k, cnt = 0; double eps; /* use a bit more restrictive tolerance */ tol_bnd *= 0.90; /* clear all objective coefficients */ for (k = 1; k <= m+n; k++) coef[k] = 0.0; /* walk through the list of basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ if (type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX) { /* x[k] has lower bound */ eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); if (bbar[i] < lb[k] - eps) { /* and violates it */ coef[k] = -1.0; cnt++; } } if (type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX) { /* x[k] has upper bound */ eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); if (bbar[i] > ub[k] + eps) { /* and violates it */ coef[k] = +1.0; cnt++; } } } return cnt; } /*********************************************************************** * set_orig_obj - restore original objective function * * This routine assigns scaled original objective coefficients to the * working objective function. */ static void set_orig_obj(struct csa *csa) { int m = csa->m; int n = csa->n; double *coef = csa->coef; double *obj = csa->obj; double zeta = csa->zeta; int i, j; for (i = 1; i <= m; i++) coef[i] = 0.0; for (j = 1; j <= n; j++) coef[m+j] = zeta * obj[j]; return; } /*********************************************************************** * check_stab - check numerical stability of basic solution * * If the current basic solution is primal feasible (or pseudo feasible * on phase I) within a tolerance, this routine returns zero, otherwise * it returns non-zero. */ static int check_stab(struct csa *csa, double tol_bnd) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; double *coef = csa->coef; int *head = csa->head; int phase = csa->phase; double *bbar = csa->bbar; int i, k; double eps; /* walk through the list of basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (phase == 1 && coef[k] < 0.0) { /* x[k] must not be greater than its lower bound */ #ifdef GLP_DEBUG xassert(type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX); #endif eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); if (bbar[i] > lb[k] + eps) return 1; } else if (phase == 1 && coef[k] > 0.0) { /* x[k] must not be less than its upper bound */ #ifdef GLP_DEBUG xassert(type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX); #endif eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); if (bbar[i] < ub[k] - eps) return 1; } else { /* either phase = 1 and coef[k] = 0, or phase = 2 */ if (type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX) { /* x[k] must not be less than its lower bound */ eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); if (bbar[i] < lb[k] - eps) return 1; } if (type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX) { /* x[k] must not be greater then its upper bound */ eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); if (bbar[i] > ub[k] + eps) return 1; } } } /* basic solution is primal feasible within a tolerance */ return 0; } /*********************************************************************** * check_feas - check primal feasibility of basic solution * * If the current basic solution is primal feasible within a tolerance, * this routine returns zero, otherwise it returns non-zero. */ static int check_feas(struct csa *csa, double tol_bnd) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; char *type = csa->type; #endif double *lb = csa->lb; double *ub = csa->ub; double *coef = csa->coef; int *head = csa->head; double *bbar = csa->bbar; int i, k; double eps; xassert(csa->phase == 1); /* walk through the list of basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (coef[k] < 0.0) { /* check if x[k] still violates its lower bound */ #ifdef GLP_DEBUG xassert(type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX); #endif eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); if (bbar[i] < lb[k] - eps) return 1; } else if (coef[k] > 0.0) { /* check if x[k] still violates its upper bound */ #ifdef GLP_DEBUG xassert(type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX); #endif eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); if (bbar[i] > ub[k] + eps) return 1; } } /* basic solution is primal feasible within a tolerance */ return 0; } /*********************************************************************** * eval_obj - compute original objective function * * This routine computes the current value of the original objective * function. */ static double eval_obj(struct csa *csa) { int m = csa->m; int n = csa->n; double *obj = csa->obj; int *head = csa->head; double *bbar = csa->bbar; int i, j, k; double sum; sum = obj[0]; /* walk through the list of basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k > m) sum += obj[k-m] * bbar[i]; } /* walk through the list of non-basic variables */ for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k > m) sum += obj[k-m] * get_xN(csa, j); } return sum; } /*********************************************************************** * display - display the search progress * * This routine displays some information about the search progress * that includes: * * the search phase; * * the number of simplex iterations performed by the solver; * * the original objective value; * * the sum of (scaled) primal infeasibilities; * * the number of basic fixed variables. */ static void display(struct csa *csa, const glp_smcp *parm, int spec) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; int phase = csa->phase; int *head = csa->head; double *bbar = csa->bbar; int i, k, cnt; double sum; if (parm->msg_lev < GLP_MSG_ON) goto skip; if (parm->out_dly > 0 && 1000.0 * xdifftime(xtime(), csa->tm_beg) < parm->out_dly) goto skip; if (csa->it_cnt == csa->it_dpy) goto skip; if (!spec && csa->it_cnt % parm->out_frq != 0) goto skip; /* compute the sum of primal infeasibilities and determine the number of basic fixed variables */ sum = 0.0, cnt = 0; for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX) { /* x[k] has lower bound */ if (bbar[i] < lb[k]) sum += (lb[k] - bbar[i]); } if (type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX) { /* x[k] has upper bound */ if (bbar[i] > ub[k]) sum += (bbar[i] - ub[k]); } if (type[k] == GLP_FX) cnt++; } xprintf("%c%6d: obj = %17.9e infeas = %10.3e (%d)\n", phase == 1 ? ' ' : '*', csa->it_cnt, eval_obj(csa), sum, cnt); csa->it_dpy = csa->it_cnt; skip: return; } /*********************************************************************** * store_sol - store basic solution back to the problem object * * This routine stores basic solution components back to the problem * object. */ static void store_sol(struct csa *csa, glp_prob *lp, int p_stat, int d_stat, int ray) { int m = csa->m; int n = csa->n; double zeta = csa->zeta; int *head = csa->head; char *stat = csa->stat; double *bbar = csa->bbar; double *cbar = csa->cbar; int i, j, k; #ifdef GLP_DEBUG xassert(lp->m == m); xassert(lp->n == n); #endif /* basis factorization */ #ifdef GLP_DEBUG xassert(!lp->valid && lp->bfd == NULL); xassert(csa->valid && csa->bfd != NULL); #endif lp->valid = 1, csa->valid = 0; lp->bfd = csa->bfd, csa->bfd = NULL; memcpy(&lp->head[1], &head[1], m * sizeof(int)); /* basic solution status */ lp->pbs_stat = p_stat; lp->dbs_stat = d_stat; /* objective function value */ lp->obj_val = eval_obj(csa); /* simplex iteration count */ lp->it_cnt = csa->it_cnt; /* unbounded ray */ lp->some = ray; /* basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { GLPROW *row = lp->row[k]; row->stat = GLP_BS; row->bind = i; row->prim = bbar[i] / row->rii; row->dual = 0.0; } else { GLPCOL *col = lp->col[k-m]; col->stat = GLP_BS; col->bind = i; col->prim = bbar[i] * col->sjj; col->dual = 0.0; } } /* non-basic variables */ for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { GLPROW *row = lp->row[k]; row->stat = stat[j]; row->bind = 0; #if 0 row->prim = get_xN(csa, j) / row->rii; #else switch (stat[j]) { case GLP_NL: row->prim = row->lb; break; case GLP_NU: row->prim = row->ub; break; case GLP_NF: row->prim = 0.0; break; case GLP_NS: row->prim = row->lb; break; default: xassert(stat != stat); } #endif row->dual = (cbar[j] * row->rii) / zeta; } else { GLPCOL *col = lp->col[k-m]; col->stat = stat[j]; col->bind = 0; #if 0 col->prim = get_xN(csa, j) * col->sjj; #else switch (stat[j]) { case GLP_NL: col->prim = col->lb; break; case GLP_NU: col->prim = col->ub; break; case GLP_NF: col->prim = 0.0; break; case GLP_NS: col->prim = col->lb; break; default: xassert(stat != stat); } #endif col->dual = (cbar[j] / col->sjj) / zeta; } } return; } /*********************************************************************** * free_csa - deallocate common storage area * * This routine frees all the memory allocated to arrays in the common * storage area (CSA). */ static void free_csa(struct csa *csa) { xfree(csa->type); xfree(csa->lb); xfree(csa->ub); xfree(csa->coef); xfree(csa->obj); xfree(csa->A_ptr); xfree(csa->A_ind); xfree(csa->A_val); xfree(csa->head); xfree(csa->stat); xfree(csa->N_ptr); xfree(csa->N_len); xfree(csa->N_ind); xfree(csa->N_val); xfree(csa->bbar); xfree(csa->cbar); xfree(csa->refsp); xfree(csa->gamma); xfree(csa->tcol_ind); xfree(csa->tcol_vec); xfree(csa->trow_ind); xfree(csa->trow_vec); xfree(csa->work1); xfree(csa->work2); xfree(csa->work3); xfree(csa->work4); xfree(csa); return; } /*********************************************************************** * spx_primal - core LP solver based on the primal simplex method * * SYNOPSIS * * #include "glpspx.h" * int spx_primal(glp_prob *lp, const glp_smcp *parm); * * DESCRIPTION * * The routine spx_primal is a core LP solver based on the two-phase * primal simplex method. * * RETURNS * * 0 LP instance has been successfully solved. * * GLP_EITLIM * Iteration limit has been exhausted. * * GLP_ETMLIM * Time limit has been exhausted. * * GLP_EFAIL * The solver failed to solve LP instance. */ int spx_primal(glp_prob *lp, const glp_smcp *parm) { struct csa *csa; int binv_st = 2; /* status of basis matrix factorization: 0 - invalid; 1 - just computed; 2 - updated */ int bbar_st = 0; /* status of primal values of basic variables: 0 - invalid; 1 - just computed; 2 - updated */ int cbar_st = 0; /* status of reduced costs of non-basic variables: 0 - invalid; 1 - just computed; 2 - updated */ int rigorous = 0; /* rigorous mode flag; this flag is used to enable iterative refinement on computing pivot rows and columns of the simplex table */ int check = 0; int p_stat, d_stat, ret; /* allocate and initialize the common storage area */ csa = alloc_csa(lp); init_csa(csa, lp); if (parm->msg_lev >= GLP_MSG_DBG) xprintf("Objective scale factor = %g\n", csa->zeta); loop: /* main loop starts here */ /* compute factorization of the basis matrix */ if (binv_st == 0) { ret = invert_B(csa); if (ret != 0) { if (parm->msg_lev >= GLP_MSG_ERR) { xprintf("Error: unable to factorize the basis matrix (%d" ")\n", ret); xprintf("Sorry, basis recovery procedure not implemented" " yet\n"); } xassert(!lp->valid && lp->bfd == NULL); lp->bfd = csa->bfd, csa->bfd = NULL; lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; lp->obj_val = 0.0; lp->it_cnt = csa->it_cnt; lp->some = 0; ret = GLP_EFAIL; goto done; } csa->valid = 1; binv_st = 1; /* just computed */ /* invalidate basic solution components */ bbar_st = cbar_st = 0; } /* compute primal values of basic variables */ if (bbar_st == 0) { eval_bbar(csa); bbar_st = 1; /* just computed */ /* determine the search phase, if not determined yet */ if (csa->phase == 0) { if (set_aux_obj(csa, parm->tol_bnd) > 0) { /* current basic solution is primal infeasible */ /* start to minimize the sum of infeasibilities */ csa->phase = 1; } else { /* current basic solution is primal feasible */ /* start to minimize the original objective function */ set_orig_obj(csa); csa->phase = 2; } xassert(check_stab(csa, parm->tol_bnd) == 0); /* working objective coefficients have been changed, so invalidate reduced costs */ cbar_st = 0; display(csa, parm, 1); } /* make sure that the current basic solution remains primal feasible (or pseudo feasible on phase I) */ if (check_stab(csa, parm->tol_bnd)) { /* there are excessive bound violations due to round-off errors */ if (parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: numerical instability (primal simplex," " phase %s)\n", csa->phase == 1 ? "I" : "II"); /* restart the search */ csa->phase = 0; binv_st = 0; rigorous = 5; goto loop; } } xassert(csa->phase == 1 || csa->phase == 2); /* on phase I we do not need to wait until the current basic solution becomes dual feasible; it is sufficient to make sure that no basic variable violates its bounds */ if (csa->phase == 1 && !check_feas(csa, parm->tol_bnd)) { /* the current basis is primal feasible; switch to phase II */ csa->phase = 2; set_orig_obj(csa); cbar_st = 0; display(csa, parm, 1); } /* compute reduced costs of non-basic variables */ if (cbar_st == 0) { eval_cbar(csa); cbar_st = 1; /* just computed */ } /* redefine the reference space, if required */ switch (parm->pricing) { case GLP_PT_STD: break; case GLP_PT_PSE: if (csa->refct == 0) reset_refsp(csa); break; default: xassert(parm != parm); } /* at this point the basis factorization and all basic solution components are valid */ xassert(binv_st && bbar_st && cbar_st); /* check accuracy of current basic solution components (only for debugging) */ if (check) { double e_bbar = err_in_bbar(csa); double e_cbar = err_in_cbar(csa); double e_gamma = (parm->pricing == GLP_PT_PSE ? err_in_gamma(csa) : 0.0); xprintf("e_bbar = %10.3e; e_cbar = %10.3e; e_gamma = %10.3e\n", e_bbar, e_cbar, e_gamma); xassert(e_bbar <= 1e-5 && e_cbar <= 1e-5 && e_gamma <= 1e-3); } /* check if the iteration limit has been exhausted */ if (parm->it_lim < INT_MAX && csa->it_cnt - csa->it_beg >= parm->it_lim) { if (bbar_st != 1 || csa->phase == 2 && cbar_st != 1) { if (bbar_st != 1) bbar_st = 0; if (csa->phase == 2 && cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); if (parm->msg_lev >= GLP_MSG_ALL) xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); switch (csa->phase) { case 1: p_stat = GLP_INFEAS; set_orig_obj(csa); eval_cbar(csa); break; case 2: p_stat = GLP_FEAS; break; default: xassert(csa != csa); } chuzc(csa, parm->tol_dj); d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); store_sol(csa, lp, p_stat, d_stat, 0); ret = GLP_EITLIM; goto done; } /* check if the time limit has been exhausted */ if (parm->tm_lim < INT_MAX && 1000.0 * xdifftime(xtime(), csa->tm_beg) >= parm->tm_lim) { if (bbar_st != 1 || csa->phase == 2 && cbar_st != 1) { if (bbar_st != 1) bbar_st = 0; if (csa->phase == 2 && cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); if (parm->msg_lev >= GLP_MSG_ALL) xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); switch (csa->phase) { case 1: p_stat = GLP_INFEAS; set_orig_obj(csa); eval_cbar(csa); break; case 2: p_stat = GLP_FEAS; break; default: xassert(csa != csa); } chuzc(csa, parm->tol_dj); d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); store_sol(csa, lp, p_stat, d_stat, 0); ret = GLP_ETMLIM; goto done; } /* display the search progress */ display(csa, parm, 0); /* choose non-basic variable xN[q] */ chuzc(csa, parm->tol_dj); if (csa->q == 0) { if (bbar_st != 1 || cbar_st != 1) { if (bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); switch (csa->phase) { case 1: if (parm->msg_lev >= GLP_MSG_ALL) #if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); #else xprintf("LP HAS NO PRIMAL FEASIBLE SOLUTION\n"); #endif p_stat = GLP_NOFEAS; set_orig_obj(csa); eval_cbar(csa); chuzc(csa, parm->tol_dj); d_stat = (csa->q == 0 ? GLP_FEAS : GLP_INFEAS); break; case 2: if (parm->msg_lev >= GLP_MSG_ALL) #if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ xprintf("OPTIMAL SOLUTION FOUND\n"); #else xprintf("OPTIMAL LP SOLUTION FOUND\n"); #endif p_stat = d_stat = GLP_FEAS; break; default: xassert(csa != csa); } store_sol(csa, lp, p_stat, d_stat, 0); ret = 0; goto done; } /* compute pivot column of the simplex table */ eval_tcol(csa); if (rigorous) refine_tcol(csa); sort_tcol(csa, parm->tol_piv); /* check accuracy of the reduced cost of xN[q] */ { double d1 = csa->cbar[csa->q]; /* less accurate */ double d2 = reeval_cost(csa); /* more accurate */ xassert(d1 != 0.0); if (fabs(d1 - d2) > 1e-5 * (1.0 + fabs(d2)) || !(d1 < 0.0 && d2 < 0.0 || d1 > 0.0 && d2 > 0.0)) { if (parm->msg_lev >= GLP_MSG_DBG) xprintf("d1 = %.12g; d2 = %.12g\n", d1, d2); if (cbar_st != 1 || !rigorous) { if (cbar_st != 1) cbar_st = 0; rigorous = 5; goto loop; } } /* replace cbar[q] by more accurate value keeping its sign */ if (d1 > 0.0) csa->cbar[csa->q] = (d2 > 0.0 ? d2 : +DBL_EPSILON); else csa->cbar[csa->q] = (d2 < 0.0 ? d2 : -DBL_EPSILON); } /* choose basic variable xB[p] */ switch (parm->r_test) { case GLP_RT_STD: chuzr(csa, 0.0); break; case GLP_RT_HAR: chuzr(csa, 0.30 * parm->tol_bnd); break; default: xassert(parm != parm); } if (csa->p == 0) { if (bbar_st != 1 || cbar_st != 1 || !rigorous) { if (bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; rigorous = 1; goto loop; } display(csa, parm, 1); switch (csa->phase) { case 1: if (parm->msg_lev >= GLP_MSG_ERR) xprintf("Error: unable to choose basic variable on ph" "ase I\n"); xassert(!lp->valid && lp->bfd == NULL); lp->bfd = csa->bfd, csa->bfd = NULL; lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; lp->obj_val = 0.0; lp->it_cnt = csa->it_cnt; lp->some = 0; ret = GLP_EFAIL; break; case 2: if (parm->msg_lev >= GLP_MSG_ALL) #if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); #else xprintf("LP HAS UNBOUNDED PRIMAL SOLUTION\n"); #endif store_sol(csa, lp, GLP_FEAS, GLP_NOFEAS, csa->head[csa->m+csa->q]); ret = 0; break; default: xassert(csa != csa); } goto done; } /* check if the pivot element is acceptable */ if (csa->p > 0) { double piv = csa->tcol_vec[csa->p]; double eps = 1e-5 * (1.0 + 0.01 * csa->tcol_max); if (fabs(piv) < eps) { if (parm->msg_lev >= GLP_MSG_DBG) xprintf("piv = %.12g; eps = %g\n", piv, eps); if (!rigorous) { rigorous = 5; goto loop; } } } /* now xN[q] and xB[p] have been chosen anyhow */ /* compute pivot row of the simplex table */ if (csa->p > 0) { double *rho = csa->work4; eval_rho(csa, rho); if (rigorous) refine_rho(csa, rho); eval_trow(csa, rho); } /* accuracy check based on the pivot element */ if (csa->p > 0) { double piv1 = csa->tcol_vec[csa->p]; /* more accurate */ double piv2 = csa->trow_vec[csa->q]; /* less accurate */ xassert(piv1 != 0.0); if (fabs(piv1 - piv2) > 1e-8 * (1.0 + fabs(piv1)) || !(piv1 > 0.0 && piv2 > 0.0 || piv1 < 0.0 && piv2 < 0.0)) { if (parm->msg_lev >= GLP_MSG_DBG) xprintf("piv1 = %.12g; piv2 = %.12g\n", piv1, piv2); if (binv_st != 1 || !rigorous) { if (binv_st != 1) binv_st = 0; rigorous = 5; goto loop; } /* use more accurate version in the pivot row */ if (csa->trow_vec[csa->q] == 0.0) { csa->trow_nnz++; xassert(csa->trow_nnz <= csa->n); csa->trow_ind[csa->trow_nnz] = csa->q; } csa->trow_vec[csa->q] = piv1; } } /* update primal values of basic variables */ update_bbar(csa); bbar_st = 2; /* updated */ /* update reduced costs of non-basic variables */ if (csa->p > 0) { update_cbar(csa); cbar_st = 2; /* updated */ /* on phase I objective coefficient of xB[p] in the adjacent basis becomes zero */ if (csa->phase == 1) { int k = csa->head[csa->p]; /* x[k] = xB[p] -> xN[q] */ csa->cbar[csa->q] -= csa->coef[k]; csa->coef[k] = 0.0; } } /* update steepest edge coefficients */ if (csa->p > 0) { switch (parm->pricing) { case GLP_PT_STD: break; case GLP_PT_PSE: if (csa->refct > 0) update_gamma(csa); break; default: xassert(parm != parm); } } /* update factorization of the basis matrix */ if (csa->p > 0) { ret = update_B(csa, csa->p, csa->head[csa->m+csa->q]); if (ret == 0) binv_st = 2; /* updated */ else { csa->valid = 0; binv_st = 0; /* invalid */ } } /* update matrix N */ if (csa->p > 0) { del_N_col(csa, csa->q, csa->head[csa->m+csa->q]); if (csa->type[csa->head[csa->p]] != GLP_FX) add_N_col(csa, csa->q, csa->head[csa->p]); } /* change the basis header */ change_basis(csa); /* iteration complete */ csa->it_cnt++; if (rigorous > 0) rigorous--; goto loop; done: /* deallocate the common storage area */ free_csa(csa); /* return to the calling program */ return ret; } /* eof */ glpk-4.52.1/src/glpspx02.c0000644000062000006210000031021412175147600014334 0ustar maomkpasswd/* glpspx02.c (dual simplex method) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpspx.h" #define GLP_DEBUG 1 #if 0 #define GLP_LONG_STEP 1 #endif struct csa { /* common storage area */ /*--------------------------------------------------------------*/ /* LP data */ int m; /* number of rows (auxiliary variables), m > 0 */ int n; /* number of columns (structural variables), n > 0 */ char *type; /* char type[1+m+n]; */ /* type[0] is not used; type[k], 1 <= k <= m+n, is the type of variable x[k]: GLP_FR - free variable GLP_LO - variable with lower bound GLP_UP - variable with upper bound GLP_DB - double-bounded variable GLP_FX - fixed variable */ double *lb; /* double lb[1+m+n]; */ /* lb[0] is not used; lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; if x[k] has no lower bound, lb[k] is zero */ double *ub; /* double ub[1+m+n]; */ /* ub[0] is not used; ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; if x[k] has no upper bound, ub[k] is zero; if x[k] is of fixed type, ub[k] is the same as lb[k] */ double *coef; /* double coef[1+m+n]; */ /* coef[0] is not used; coef[k], 1 <= k <= m+n, is an objective coefficient at variable x[k] */ /*--------------------------------------------------------------*/ /* original bounds of variables */ char *orig_type; /* char orig_type[1+m+n]; */ double *orig_lb; /* double orig_lb[1+m+n]; */ double *orig_ub; /* double orig_ub[1+m+n]; */ /*--------------------------------------------------------------*/ /* original objective function */ double *obj; /* double obj[1+n]; */ /* obj[0] is a constant term of the original objective function; obj[j], 1 <= j <= n, is an original objective coefficient at structural variable x[m+j] */ double zeta; /* factor used to scale original objective coefficients; its sign defines original optimization direction: zeta > 0 means minimization, zeta < 0 means maximization */ /*--------------------------------------------------------------*/ /* constraint matrix A; it has m rows and n columns and is stored by columns */ int *A_ptr; /* int A_ptr[1+n+1]; */ /* A_ptr[0] is not used; A_ptr[j], 1 <= j <= n, is starting position of j-th column in arrays A_ind and A_val; note that A_ptr[1] is always 1; A_ptr[n+1] indicates the position after the last element in arrays A_ind and A_val */ int *A_ind; /* int A_ind[A_ptr[n+1]]; */ /* row indices */ double *A_val; /* double A_val[A_ptr[n+1]]; */ /* non-zero element values */ #if 1 /* 06/IV-2009 */ /* constraint matrix A stored by rows */ int *AT_ptr; /* int AT_ptr[1+m+1]; */ /* AT_ptr[0] is not used; AT_ptr[i], 1 <= i <= m, is starting position of i-th row in arrays AT_ind and AT_val; note that AT_ptr[1] is always 1; AT_ptr[m+1] indicates the position after the last element in arrays AT_ind and AT_val */ int *AT_ind; /* int AT_ind[AT_ptr[m+1]]; */ /* column indices */ double *AT_val; /* double AT_val[AT_ptr[m+1]]; */ /* non-zero element values */ #endif /*--------------------------------------------------------------*/ /* basis header */ int *head; /* int head[1+m+n]; */ /* head[0] is not used; head[i], 1 <= i <= m, is the ordinal number of basic variable xB[i]; head[i] = k means that xB[i] = x[k] and i-th column of matrix B is k-th column of matrix (I|-A); head[m+j], 1 <= j <= n, is the ordinal number of non-basic variable xN[j]; head[m+j] = k means that xN[j] = x[k] and j-th column of matrix N is k-th column of matrix (I|-A) */ #if 1 /* 06/IV-2009 */ int *bind; /* int bind[1+m+n]; */ /* bind[0] is not used; bind[k], 1 <= k <= m+n, is the position of k-th column of the matrix (I|-A) in the matrix (B|N); that is, bind[k] = k' means that head[k'] = k */ #endif char *stat; /* char stat[1+n]; */ /* stat[0] is not used; stat[j], 1 <= j <= n, is the status of non-basic variable xN[j], which defines its active bound: GLP_NL - lower bound is active GLP_NU - upper bound is active GLP_NF - free variable GLP_NS - fixed variable */ /*--------------------------------------------------------------*/ /* matrix B is the basis matrix; it is composed from columns of the augmented constraint matrix (I|-A) corresponding to basic variables and stored in a factorized (invertable) form */ int valid; /* factorization is valid only if this flag is set */ BFD *bfd; /* BFD bfd[1:m,1:m]; */ /* factorized (invertable) form of the basis matrix */ #if 0 /* 06/IV-2009 */ /*--------------------------------------------------------------*/ /* matrix N is a matrix composed from columns of the augmented constraint matrix (I|-A) corresponding to non-basic variables except fixed ones; it is stored by rows and changes every time the basis changes */ int *N_ptr; /* int N_ptr[1+m+1]; */ /* N_ptr[0] is not used; N_ptr[i], 1 <= i <= m, is starting position of i-th row in arrays N_ind and N_val; note that N_ptr[1] is always 1; N_ptr[m+1] indicates the position after the last element in arrays N_ind and N_val */ int *N_len; /* int N_len[1+m]; */ /* N_len[0] is not used; N_len[i], 1 <= i <= m, is length of i-th row (0 to n) */ int *N_ind; /* int N_ind[N_ptr[m+1]]; */ /* column indices */ double *N_val; /* double N_val[N_ptr[m+1]]; */ /* non-zero element values */ #endif /*--------------------------------------------------------------*/ /* working parameters */ int phase; /* search phase: 0 - not determined yet 1 - search for dual feasible solution 2 - search for optimal solution */ #if 0 /* 10/VI-2013 */ glp_long tm_beg; #else double tm_beg; #endif /* time value at the beginning of the search */ int it_beg; /* simplex iteration count at the beginning of the search */ int it_cnt; /* simplex iteration count; it increases by one every time the basis changes */ int it_dpy; /* simplex iteration count at the most recent display output */ /*--------------------------------------------------------------*/ /* basic solution components */ double *bbar; /* double bbar[1+m]; */ /* bbar[0] is not used on phase I; on phase II it is the current value of the original objective function; bbar[i], 1 <= i <= m, is primal value of basic variable xB[i] (if xB[i] is free, its primal value is not updated) */ double *cbar; /* double cbar[1+n]; */ /* cbar[0] is not used; cbar[j], 1 <= j <= n, is reduced cost of non-basic variable xN[j] (if xN[j] is fixed, its reduced cost is not updated) */ /*--------------------------------------------------------------*/ /* the following pricing technique options may be used: GLP_PT_STD - standard ("textbook") pricing; GLP_PT_PSE - projected steepest edge; GLP_PT_DVX - Devex pricing (not implemented yet); in case of GLP_PT_STD the reference space is not used, and all steepest edge coefficients are set to 1 */ int refct; /* this count is set to an initial value when the reference space is defined and decreases by one every time the basis changes; once this count reaches zero, the reference space is redefined again */ char *refsp; /* char refsp[1+m+n]; */ /* refsp[0] is not used; refsp[k], 1 <= k <= m+n, is the flag which means that variable x[k] belongs to the current reference space */ double *gamma; /* double gamma[1+m]; */ /* gamma[0] is not used; gamma[i], 1 <= i <= n, is the steepest edge coefficient for basic variable xB[i]; if xB[i] is free, gamma[i] is not used and just set to 1 */ /*--------------------------------------------------------------*/ /* basic variable xB[p] chosen to leave the basis */ int p; /* index of the basic variable xB[p] chosen, 1 <= p <= m; if the set of eligible basic variables is empty (i.e. if the current basic solution is primal feasible within a tolerance) and thus no variable has been chosen, p is set to 0 */ double delta; /* change of xB[p] in the adjacent basis; delta > 0 means that xB[p] violates its lower bound and will increase to achieve it in the adjacent basis; delta < 0 means that xB[p] violates its upper bound and will decrease to achieve it in the adjacent basis */ /*--------------------------------------------------------------*/ /* pivot row of the simplex table corresponding to basic variable xB[p] chosen is the following vector: T' * e[p] = - N' * inv(B') * e[p] = - N' * rho, where B' is a matrix transposed to the current basis matrix, N' is a matrix, whose rows are columns of the matrix (I|-A) corresponding to non-basic non-fixed variables */ int trow_nnz; /* number of non-zero components, 0 <= nnz <= n */ int *trow_ind; /* int trow_ind[1+n]; */ /* trow_ind[0] is not used; trow_ind[t], 1 <= t <= nnz, is an index of non-zero component, i.e. trow_ind[t] = j means that trow_vec[j] != 0 */ double *trow_vec; /* int trow_vec[1+n]; */ /* trow_vec[0] is not used; trow_vec[j], 1 <= j <= n, is a numeric value of j-th component of the row */ double trow_max; /* infinity (maximum) norm of the row (max |trow_vec[j]|) */ int trow_num; /* number of significant non-zero components, which means that: |trow_vec[j]| >= eps for j in trow_ind[1,...,num], |tcol_vec[j]| < eps for j in trow_ind[num+1,...,nnz], where eps is a pivot tolerance */ /*--------------------------------------------------------------*/ #ifdef GLP_LONG_STEP /* 07/IV-2009 */ int nbps; /* number of breakpoints, 0 <= nbps <= n */ struct bkpt { int j; /* index of non-basic variable xN[j], 1 <= j <= n */ double t; /* value of dual ray parameter at breakpoint, t >= 0 */ double dz; /* dz = zeta(t = t[k]) - zeta(t = 0) */ } *bkpt; /* struct bkpt bkpt[1+n]; */ /* bkpt[0] is not used; bkpt[k], 1 <= k <= nbps, is k-th breakpoint of the dual objective */ #endif /*--------------------------------------------------------------*/ /* non-basic variable xN[q] chosen to enter the basis */ int q; /* index of the non-basic variable xN[q] chosen, 1 <= q <= n; if no variable has been chosen, q is set to 0 */ double new_dq; /* reduced cost of xN[q] in the adjacent basis (it is the change of lambdaB[p]) */ /*--------------------------------------------------------------*/ /* pivot column of the simplex table corresponding to non-basic variable xN[q] chosen is the following vector: T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], where B is the current basis matrix, N[q] is a column of the matrix (I|-A) corresponding to xN[q] */ int tcol_nnz; /* number of non-zero components, 0 <= nnz <= m */ int *tcol_ind; /* int tcol_ind[1+m]; */ /* tcol_ind[0] is not used; tcol_ind[t], 1 <= t <= nnz, is an index of non-zero component, i.e. tcol_ind[t] = i means that tcol_vec[i] != 0 */ double *tcol_vec; /* double tcol_vec[1+m]; */ /* tcol_vec[0] is not used; tcol_vec[i], 1 <= i <= m, is a numeric value of i-th component of the column */ /*--------------------------------------------------------------*/ /* working arrays */ double *work1; /* double work1[1+m]; */ double *work2; /* double work2[1+m]; */ double *work3; /* double work3[1+m]; */ double *work4; /* double work4[1+m]; */ }; static const double kappa = 0.10; /*********************************************************************** * alloc_csa - allocate common storage area * * This routine allocates all arrays in the common storage area (CSA) * and returns a pointer to the CSA. */ static struct csa *alloc_csa(glp_prob *lp) { struct csa *csa; int m = lp->m; int n = lp->n; int nnz = lp->nnz; csa = xmalloc(sizeof(struct csa)); xassert(m > 0 && n > 0); csa->m = m; csa->n = n; csa->type = xcalloc(1+m+n, sizeof(char)); csa->lb = xcalloc(1+m+n, sizeof(double)); csa->ub = xcalloc(1+m+n, sizeof(double)); csa->coef = xcalloc(1+m+n, sizeof(double)); csa->orig_type = xcalloc(1+m+n, sizeof(char)); csa->orig_lb = xcalloc(1+m+n, sizeof(double)); csa->orig_ub = xcalloc(1+m+n, sizeof(double)); csa->obj = xcalloc(1+n, sizeof(double)); csa->A_ptr = xcalloc(1+n+1, sizeof(int)); csa->A_ind = xcalloc(1+nnz, sizeof(int)); csa->A_val = xcalloc(1+nnz, sizeof(double)); #if 1 /* 06/IV-2009 */ csa->AT_ptr = xcalloc(1+m+1, sizeof(int)); csa->AT_ind = xcalloc(1+nnz, sizeof(int)); csa->AT_val = xcalloc(1+nnz, sizeof(double)); #endif csa->head = xcalloc(1+m+n, sizeof(int)); #if 1 /* 06/IV-2009 */ csa->bind = xcalloc(1+m+n, sizeof(int)); #endif csa->stat = xcalloc(1+n, sizeof(char)); #if 0 /* 06/IV-2009 */ csa->N_ptr = xcalloc(1+m+1, sizeof(int)); csa->N_len = xcalloc(1+m, sizeof(int)); csa->N_ind = NULL; /* will be allocated later */ csa->N_val = NULL; /* will be allocated later */ #endif csa->bbar = xcalloc(1+m, sizeof(double)); csa->cbar = xcalloc(1+n, sizeof(double)); csa->refsp = xcalloc(1+m+n, sizeof(char)); csa->gamma = xcalloc(1+m, sizeof(double)); csa->trow_ind = xcalloc(1+n, sizeof(int)); csa->trow_vec = xcalloc(1+n, sizeof(double)); #ifdef GLP_LONG_STEP /* 07/IV-2009 */ csa->bkpt = xcalloc(1+n, sizeof(struct bkpt)); #endif csa->tcol_ind = xcalloc(1+m, sizeof(int)); csa->tcol_vec = xcalloc(1+m, sizeof(double)); csa->work1 = xcalloc(1+m, sizeof(double)); csa->work2 = xcalloc(1+m, sizeof(double)); csa->work3 = xcalloc(1+m, sizeof(double)); csa->work4 = xcalloc(1+m, sizeof(double)); return csa; } /*********************************************************************** * init_csa - initialize common storage area * * This routine initializes all data structures in the common storage * area (CSA). */ static void init_csa(struct csa *csa, glp_prob *lp) { int m = csa->m; int n = csa->n; char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; double *coef = csa->coef; char *orig_type = csa->orig_type; double *orig_lb = csa->orig_lb; double *orig_ub = csa->orig_ub; double *obj = csa->obj; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; #if 1 /* 06/IV-2009 */ int *AT_ptr = csa->AT_ptr; int *AT_ind = csa->AT_ind; double *AT_val = csa->AT_val; #endif int *head = csa->head; #if 1 /* 06/IV-2009 */ int *bind = csa->bind; #endif char *stat = csa->stat; char *refsp = csa->refsp; double *gamma = csa->gamma; int i, j, k, loc; double cmax; /* auxiliary variables */ for (i = 1; i <= m; i++) { GLPROW *row = lp->row[i]; type[i] = (char)row->type; lb[i] = row->lb * row->rii; ub[i] = row->ub * row->rii; coef[i] = 0.0; } /* structural variables */ for (j = 1; j <= n; j++) { GLPCOL *col = lp->col[j]; type[m+j] = (char)col->type; lb[m+j] = col->lb / col->sjj; ub[m+j] = col->ub / col->sjj; coef[m+j] = col->coef * col->sjj; } /* original bounds of variables */ memcpy(&orig_type[1], &type[1], (m+n) * sizeof(char)); memcpy(&orig_lb[1], &lb[1], (m+n) * sizeof(double)); memcpy(&orig_ub[1], &ub[1], (m+n) * sizeof(double)); /* original objective function */ obj[0] = lp->c0; memcpy(&obj[1], &coef[m+1], n * sizeof(double)); /* factor used to scale original objective coefficients */ cmax = 0.0; for (j = 1; j <= n; j++) if (cmax < fabs(obj[j])) cmax = fabs(obj[j]); if (cmax == 0.0) cmax = 1.0; switch (lp->dir) { case GLP_MIN: csa->zeta = + 1.0 / cmax; break; case GLP_MAX: csa->zeta = - 1.0 / cmax; break; default: xassert(lp != lp); } #if 1 if (fabs(csa->zeta) < 1.0) csa->zeta *= 1000.0; #endif /* scale working objective coefficients */ for (j = 1; j <= n; j++) coef[m+j] *= csa->zeta; /* matrix A (by columns) */ loc = 1; for (j = 1; j <= n; j++) { GLPAIJ *aij; A_ptr[j] = loc; for (aij = lp->col[j]->ptr; aij != NULL; aij = aij->c_next) { A_ind[loc] = aij->row->i; A_val[loc] = aij->row->rii * aij->val * aij->col->sjj; loc++; } } A_ptr[n+1] = loc; xassert(loc-1 == lp->nnz); #if 1 /* 06/IV-2009 */ /* matrix A (by rows) */ loc = 1; for (i = 1; i <= m; i++) { GLPAIJ *aij; AT_ptr[i] = loc; for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next) { AT_ind[loc] = aij->col->j; AT_val[loc] = aij->row->rii * aij->val * aij->col->sjj; loc++; } } AT_ptr[m+1] = loc; xassert(loc-1 == lp->nnz); #endif /* basis header */ xassert(lp->valid); memcpy(&head[1], &lp->head[1], m * sizeof(int)); k = 0; for (i = 1; i <= m; i++) { GLPROW *row = lp->row[i]; if (row->stat != GLP_BS) { k++; xassert(k <= n); head[m+k] = i; stat[k] = (char)row->stat; } } for (j = 1; j <= n; j++) { GLPCOL *col = lp->col[j]; if (col->stat != GLP_BS) { k++; xassert(k <= n); head[m+k] = m + j; stat[k] = (char)col->stat; } } xassert(k == n); #if 1 /* 06/IV-2009 */ for (k = 1; k <= m+n; k++) bind[head[k]] = k; #endif /* factorization of matrix B */ csa->valid = 1, lp->valid = 0; csa->bfd = lp->bfd, lp->bfd = NULL; #if 0 /* 06/IV-2009 */ /* matrix N (by rows) */ alloc_N(csa); build_N(csa); #endif /* working parameters */ csa->phase = 0; csa->tm_beg = xtime(); csa->it_beg = csa->it_cnt = lp->it_cnt; csa->it_dpy = -1; /* reference space and steepest edge coefficients */ csa->refct = 0; memset(&refsp[1], 0, (m+n) * sizeof(char)); for (i = 1; i <= m; i++) gamma[i] = 1.0; return; } #if 1 /* copied from primal */ /*********************************************************************** * invert_B - compute factorization of the basis matrix * * This routine computes factorization of the current basis matrix B. * * If the operation is successful, the routine returns zero, otherwise * non-zero. */ static int inv_col(void *info, int i, int ind[], double val[]) { /* this auxiliary routine returns row indices and numeric values of non-zero elements of i-th column of the basis matrix */ struct csa *csa = info; int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; int k, len, ptr, t; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); #endif k = head[i]; /* B[i] is k-th column of (I|-A) */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* B[i] is k-th column of submatrix I */ len = 1; ind[1] = k; val[1] = 1.0; } else { /* B[i] is (k-m)-th column of submatrix (-A) */ ptr = A_ptr[k-m]; len = A_ptr[k-m+1] - ptr; memcpy(&ind[1], &A_ind[ptr], len * sizeof(int)); memcpy(&val[1], &A_val[ptr], len * sizeof(double)); for (t = 1; t <= len; t++) val[t] = - val[t]; } return len; } static int invert_B(struct csa *csa) { int ret; ret = bfd_factorize(csa->bfd, csa->m, NULL, inv_col, csa); csa->valid = (ret == 0); return ret; } #endif #if 1 /* copied from primal */ /*********************************************************************** * update_B - update factorization of the basis matrix * * This routine replaces i-th column of the basis matrix B by k-th * column of the augmented constraint matrix (I|-A) and then updates * the factorization of B. * * If the factorization has been successfully updated, the routine * returns zero, otherwise non-zero. */ static int update_B(struct csa *csa, int i, int k) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int ret; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* new i-th column of B is k-th column of I */ int ind[1+1]; double val[1+1]; ind[1] = k; val[1] = 1.0; xassert(csa->valid); ret = bfd_update_it(csa->bfd, i, 0, 1, ind, val); } else { /* new i-th column of B is (k-m)-th column of (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; double *val = csa->work1; int beg, end, ptr, len; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; len = 0; for (ptr = beg; ptr < end; ptr++) val[++len] = - A_val[ptr]; xassert(csa->valid); ret = bfd_update_it(csa->bfd, i, 0, len, &A_ind[beg-1], val); } csa->valid = (ret == 0); return ret; } #endif #if 1 /* copied from primal */ /*********************************************************************** * error_ftran - compute residual vector r = h - B * x * * This routine computes the residual vector r = h - B * x, where B is * the current basis matrix, h is the vector of right-hand sides, x is * the solution vector. */ static void error_ftran(struct csa *csa, double h[], double x[], double r[]) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; int i, k, beg, end, ptr; double temp; /* compute the residual vector: r = h - B * x = h - B[1] * x[1] - ... - B[m] * x[m], where B[1], ..., B[m] are columns of matrix B */ memcpy(&r[1], &h[1], m * sizeof(double)); for (i = 1; i <= m; i++) { temp = x[i]; if (temp == 0.0) continue; k = head[i]; /* B[i] is k-th column of (I|-A) */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { /* B[i] is k-th column of submatrix I */ r[k] -= temp; } else { /* B[i] is (k-m)-th column of submatrix (-A) */ beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) r[A_ind[ptr]] += A_val[ptr] * temp; } } return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * refine_ftran - refine solution of B * x = h * * This routine performs one iteration to refine the solution of * the system B * x = h, where B is the current basis matrix, h is the * vector of right-hand sides, x is the solution vector. */ static void refine_ftran(struct csa *csa, double h[], double x[]) { int m = csa->m; double *r = csa->work1; double *d = csa->work1; int i; /* compute the residual vector r = h - B * x */ error_ftran(csa, h, x, r); /* compute the correction vector d = inv(B) * r */ xassert(csa->valid); bfd_ftran(csa->bfd, d); /* refine the solution vector (new x) = (old x) + d */ for (i = 1; i <= m; i++) x[i] += d[i]; return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * error_btran - compute residual vector r = h - B'* x * * This routine computes the residual vector r = h - B'* x, where B' * is a matrix transposed to the current basis matrix, h is the vector * of right-hand sides, x is the solution vector. */ static void error_btran(struct csa *csa, double h[], double x[], double r[]) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; int i, k, beg, end, ptr; double temp; /* compute the residual vector r = b - B'* x */ for (i = 1; i <= m; i++) { /* r[i] := b[i] - (i-th column of B)'* x */ k = head[i]; /* B[i] is k-th column of (I|-A) */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif temp = h[i]; if (k <= m) { /* B[i] is k-th column of submatrix I */ temp -= x[k]; } else { /* B[i] is (k-m)-th column of submatrix (-A) */ beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) temp += A_val[ptr] * x[A_ind[ptr]]; } r[i] = temp; } return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * refine_btran - refine solution of B'* x = h * * This routine performs one iteration to refine the solution of the * system B'* x = h, where B' is a matrix transposed to the current * basis matrix, h is the vector of right-hand sides, x is the solution * vector. */ static void refine_btran(struct csa *csa, double h[], double x[]) { int m = csa->m; double *r = csa->work1; double *d = csa->work1; int i; /* compute the residual vector r = h - B'* x */ error_btran(csa, h, x, r); /* compute the correction vector d = inv(B') * r */ xassert(csa->valid); bfd_btran(csa->bfd, d); /* refine the solution vector (new x) = (old x) + d */ for (i = 1; i <= m; i++) x[i] += d[i]; return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * get_xN - determine current value of non-basic variable xN[j] * * This routine returns the current value of non-basic variable xN[j], * which is a value of its active bound. */ static double get_xN(struct csa *csa, int j) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif double *lb = csa->lb; double *ub = csa->ub; int *head = csa->head; char *stat = csa->stat; int k; double xN; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif switch (stat[j]) { case GLP_NL: /* x[k] is on its lower bound */ xN = lb[k]; break; case GLP_NU: /* x[k] is on its upper bound */ xN = ub[k]; break; case GLP_NF: /* x[k] is free non-basic variable */ xN = 0.0; break; case GLP_NS: /* x[k] is fixed non-basic variable */ xN = lb[k]; break; default: xassert(stat != stat); } return xN; } #endif #if 1 /* copied from primal */ /*********************************************************************** * eval_beta - compute primal values of basic variables * * This routine computes current primal values of all basic variables: * * beta = - inv(B) * N * xN, * * where B is the current basis matrix, N is a matrix built of columns * of matrix (I|-A) corresponding to non-basic variables, and xN is the * vector of current values of non-basic variables. */ static void eval_beta(struct csa *csa, double beta[]) { int m = csa->m; int n = csa->n; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; double *h = csa->work2; int i, j, k, beg, end, ptr; double xN; /* compute the right-hand side vector: h := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n], where N[1], ..., N[n] are columns of matrix N */ for (i = 1; i <= m; i++) h[i] = 0.0; for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* determine current value of xN[j] */ xN = get_xN(csa, j); if (xN == 0.0) continue; if (k <= m) { /* N[j] is k-th column of submatrix I */ h[k] -= xN; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] += xN * A_val[ptr]; } } /* solve system B * beta = h */ memcpy(&beta[1], &h[1], m * sizeof(double)); xassert(csa->valid); bfd_ftran(csa->bfd, beta); /* and refine the solution */ refine_ftran(csa, h, beta); return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * eval_pi - compute vector of simplex multipliers * * This routine computes the vector of current simplex multipliers: * * pi = inv(B') * cB, * * where B' is a matrix transposed to the current basis matrix, cB is * a subvector of objective coefficients at basic variables. */ static void eval_pi(struct csa *csa, double pi[]) { int m = csa->m; double *c = csa->coef; int *head = csa->head; double *cB = csa->work2; int i; /* construct the right-hand side vector cB */ for (i = 1; i <= m; i++) cB[i] = c[head[i]]; /* solve system B'* pi = cB */ memcpy(&pi[1], &cB[1], m * sizeof(double)); xassert(csa->valid); bfd_btran(csa->bfd, pi); /* and refine the solution */ refine_btran(csa, cB, pi); return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * eval_cost - compute reduced cost of non-basic variable xN[j] * * This routine computes the current reduced cost of non-basic variable * xN[j]: * * d[j] = cN[j] - N'[j] * pi, * * where cN[j] is the objective coefficient at variable xN[j], N[j] is * a column of the augmented constraint matrix (I|-A) corresponding to * xN[j], pi is the vector of simplex multipliers. */ static double eval_cost(struct csa *csa, double pi[], int j) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif double *coef = csa->coef; int *head = csa->head; int k; double dj; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif dj = coef[k]; if (k <= m) { /* N[j] is k-th column of submatrix I */ dj -= pi[k]; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) dj += A_val[ptr] * pi[A_ind[ptr]]; } return dj; } #endif #if 1 /* copied from primal */ /*********************************************************************** * eval_bbar - compute and store primal values of basic variables * * This routine computes primal values of all basic variables and then * stores them in the solution array. */ static void eval_bbar(struct csa *csa) { eval_beta(csa, csa->bbar); return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * eval_cbar - compute and store reduced costs of non-basic variables * * This routine computes reduced costs of all non-basic variables and * then stores them in the solution array. */ static void eval_cbar(struct csa *csa) { #ifdef GLP_DEBUG int m = csa->m; #endif int n = csa->n; #ifdef GLP_DEBUG int *head = csa->head; #endif double *cbar = csa->cbar; double *pi = csa->work3; int j; #ifdef GLP_DEBUG int k; #endif /* compute simplex multipliers */ eval_pi(csa, pi); /* compute and store reduced costs */ for (j = 1; j <= n; j++) { #ifdef GLP_DEBUG k = head[m+j]; /* x[k] = xN[j] */ xassert(1 <= k && k <= m+n); #endif cbar[j] = eval_cost(csa, pi, j); } return; } #endif /*********************************************************************** * reset_refsp - reset the reference space * * This routine resets (redefines) the reference space used in the * projected steepest edge pricing algorithm. */ static void reset_refsp(struct csa *csa) { int m = csa->m; int n = csa->n; int *head = csa->head; char *refsp = csa->refsp; double *gamma = csa->gamma; int i, k; xassert(csa->refct == 0); csa->refct = 1000; memset(&refsp[1], 0, (m+n) * sizeof(char)); for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ refsp[k] = 1; gamma[i] = 1.0; } return; } /*********************************************************************** * eval_gamma - compute steepest edge coefficients * * This routine computes the vector of steepest edge coefficients for * all basic variables (except free ones) using its direct definition: * * gamma[i] = eta[i] + sum alfa[i,j]^2, i = 1,...,m, * j in C * * where eta[i] = 1 means that xB[i] is in the current reference space, * and 0 otherwise; C is a set of non-basic non-fixed variables xN[j], * which are in the current reference space; alfa[i,j] are elements of * the current simplex table. * * NOTE: The routine is intended only for debugginig purposes. */ static void eval_gamma(struct csa *csa, double gamma[]) { int m = csa->m; int n = csa->n; char *type = csa->type; int *head = csa->head; char *refsp = csa->refsp; double *alfa = csa->work3; double *h = csa->work3; int i, j, k; /* gamma[i] := eta[i] (or 1, if xB[i] is free) */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (type[k] == GLP_FR) gamma[i] = 1.0; else gamma[i] = (refsp[k] ? 1.0 : 0.0); } /* compute columns of the current simplex table */ for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* skip column, if xN[j] is not in C */ if (!refsp[k]) continue; #ifdef GLP_DEBUG /* set C must not contain fixed variables */ xassert(type[k] != GLP_FX); #endif /* construct the right-hand side vector h = - N[j] */ for (i = 1; i <= m; i++) h[i] = 0.0; if (k <= m) { /* N[j] is k-th column of submatrix I */ h[k] = -1.0; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] = A_val[ptr]; } /* solve system B * alfa = h */ xassert(csa->valid); bfd_ftran(csa->bfd, alfa); /* gamma[i] := gamma[i] + alfa[i,j]^2 */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ if (type[k] != GLP_FR) gamma[i] += alfa[i] * alfa[i]; } } return; } /*********************************************************************** * chuzr - choose basic variable (row of the simplex table) * * This routine chooses basic variable xB[p] having largest weighted * bound violation: * * |r[p]| / sqrt(gamma[p]) = max |r[i]| / sqrt(gamma[i]), * i in I * * / lB[i] - beta[i], if beta[i] < lB[i] * | * r[i] = < 0, if lB[i] <= beta[i] <= uB[i] * | * \ uB[i] - beta[i], if beta[i] > uB[i] * * where beta[i] is primal value of xB[i] in the current basis, lB[i] * and uB[i] are lower and upper bounds of xB[i], I is a subset of * eligible basic variables, which significantly violates their bounds, * gamma[i] is the steepest edge coefficient. * * If |r[i]| is less than a specified tolerance, xB[i] is not included * in I and therefore ignored. * * If I is empty and no variable has been chosen, p is set to 0. */ static void chuzr(struct csa *csa, double tol_bnd) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; int *head = csa->head; double *bbar = csa->bbar; double *gamma = csa->gamma; int i, k, p; double delta, best, eps, ri, temp; /* nothing is chosen so far */ p = 0, delta = 0.0, best = 0.0; /* look through the list of basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* determine bound violation ri[i] */ ri = 0.0; if (type[k] == GLP_LO || type[k] == GLP_DB || type[k] == GLP_FX) { /* xB[i] has lower bound */ eps = tol_bnd * (1.0 + kappa * fabs(lb[k])); if (bbar[i] < lb[k] - eps) { /* and significantly violates it */ ri = lb[k] - bbar[i]; } } if (type[k] == GLP_UP || type[k] == GLP_DB || type[k] == GLP_FX) { /* xB[i] has upper bound */ eps = tol_bnd * (1.0 + kappa * fabs(ub[k])); if (bbar[i] > ub[k] + eps) { /* and significantly violates it */ ri = ub[k] - bbar[i]; } } /* if xB[i] is not eligible, skip it */ if (ri == 0.0) continue; /* xB[i] is eligible basic variable; choose one with largest weighted bound violation */ #ifdef GLP_DEBUG xassert(gamma[i] >= 0.0); #endif temp = gamma[i]; if (temp < DBL_EPSILON) temp = DBL_EPSILON; temp = (ri * ri) / temp; if (best < temp) p = i, delta = ri, best = temp; } /* store the index of basic variable xB[p] chosen and its change in the adjacent basis */ csa->p = p; csa->delta = delta; return; } #if 1 /* copied from primal */ /*********************************************************************** * eval_rho - compute pivot row of the inverse * * This routine computes the pivot (p-th) row of the inverse inv(B), * which corresponds to basic variable xB[p] chosen: * * rho = inv(B') * e[p], * * where B' is a matrix transposed to the current basis matrix, e[p] * is unity vector. */ static void eval_rho(struct csa *csa, double rho[]) { int m = csa->m; int p = csa->p; double *e = rho; int i; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); #endif /* construct the right-hand side vector e[p] */ for (i = 1; i <= m; i++) e[i] = 0.0; e[p] = 1.0; /* solve system B'* rho = e[p] */ xassert(csa->valid); bfd_btran(csa->bfd, rho); return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * refine_rho - refine pivot row of the inverse * * This routine refines the pivot row of the inverse inv(B) assuming * that it was previously computed by the routine eval_rho. */ static void refine_rho(struct csa *csa, double rho[]) { int m = csa->m; int p = csa->p; double *e = csa->work3; int i; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); #endif /* construct the right-hand side vector e[p] */ for (i = 1; i <= m; i++) e[i] = 0.0; e[p] = 1.0; /* refine solution of B'* rho = e[p] */ refine_btran(csa, e, rho); return; } #endif #if 1 /* 06/IV-2009 */ /*********************************************************************** * eval_trow - compute pivot row of the simplex table * * This routine computes the pivot row of the simplex table, which * corresponds to basic variable xB[p] chosen. * * The pivot row is the following vector: * * trow = T'* e[p] = - N'* inv(B') * e[p] = - N' * rho, * * where rho is the pivot row of the inverse inv(B) previously computed * by the routine eval_rho. * * Note that elements of the pivot row corresponding to fixed non-basic * variables are not computed. * * NOTES * * Computing pivot row of the simplex table is one of the most time * consuming operations, and for some instances it may take more than * 50% of the total solution time. * * In the current implementation there are two routines to compute the * pivot row. The routine eval_trow1 computes elements of the pivot row * as inner products of columns of the matrix N and the vector rho; it * is used when the vector rho is relatively dense. The routine * eval_trow2 computes the pivot row as a linear combination of rows of * the matrix N; it is used when the vector rho is relatively sparse. */ static void eval_trow1(struct csa *csa, double rho[]) { int m = csa->m; int n = csa->n; int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int *head = csa->head; char *stat = csa->stat; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int j, k, beg, end, ptr, nnz; double temp; /* compute the pivot row as inner products of columns of the matrix N and vector rho: trow[j] = - rho * N[j] */ nnz = 0; for (j = 1; j <= n; j++) { if (stat[j] == GLP_NS) { /* xN[j] is fixed */ trow_vec[j] = 0.0; continue; } k = head[m+j]; /* x[k] = xN[j] */ if (k <= m) { /* N[j] is k-th column of submatrix I */ temp = - rho[k]; } else { /* N[j] is (k-m)-th column of submatrix (-A) */ beg = A_ptr[k-m], end = A_ptr[k-m+1]; temp = 0.0; for (ptr = beg; ptr < end; ptr++) temp += rho[A_ind[ptr]] * A_val[ptr]; } if (temp != 0.0) trow_ind[++nnz] = j; trow_vec[j] = temp; } csa->trow_nnz = nnz; return; } static void eval_trow2(struct csa *csa, double rho[]) { int m = csa->m; int n = csa->n; int *AT_ptr = csa->AT_ptr; int *AT_ind = csa->AT_ind; double *AT_val = csa->AT_val; int *bind = csa->bind; char *stat = csa->stat; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int i, j, beg, end, ptr, nnz; double temp; /* clear the pivot row */ for (j = 1; j <= n; j++) trow_vec[j] = 0.0; /* compute the pivot row as a linear combination of rows of the matrix N: trow = - rho[1] * N'[1] - ... - rho[m] * N'[m] */ for (i = 1; i <= m; i++) { temp = rho[i]; if (temp == 0.0) continue; /* trow := trow - rho[i] * N'[i] */ j = bind[i] - m; /* x[i] = xN[j] */ if (j >= 1 && stat[j] != GLP_NS) trow_vec[j] -= temp; beg = AT_ptr[i], end = AT_ptr[i+1]; for (ptr = beg; ptr < end; ptr++) { j = bind[m + AT_ind[ptr]] - m; /* x[k] = xN[j] */ if (j >= 1 && stat[j] != GLP_NS) trow_vec[j] += temp * AT_val[ptr]; } } /* construct sparse pattern of the pivot row */ nnz = 0; for (j = 1; j <= n; j++) { if (trow_vec[j] != 0.0) trow_ind[++nnz] = j; } csa->trow_nnz = nnz; return; } static void eval_trow(struct csa *csa, double rho[]) { int m = csa->m; int i, nnz; double dens; /* determine the density of the vector rho */ nnz = 0; for (i = 1; i <= m; i++) if (rho[i] != 0.0) nnz++; dens = (double)nnz / (double)m; if (dens >= 0.20) { /* rho is relatively dense */ eval_trow1(csa, rho); } else { /* rho is relatively sparse */ eval_trow2(csa, rho); } return; } #endif /*********************************************************************** * sort_trow - sort pivot row of the simplex table * * This routine reorders the list of non-zero elements of the pivot * row to put significant elements, whose magnitude is not less than * a specified tolerance, in front of the list, and stores the number * of significant elements in trow_num. */ static void sort_trow(struct csa *csa, double tol_piv) { #ifdef GLP_DEBUG int n = csa->n; char *stat = csa->stat; #endif int nnz = csa->trow_nnz; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int j, num, pos; double big, eps, temp; /* compute infinity (maximum) norm of the row */ big = 0.0; for (pos = 1; pos <= nnz; pos++) { #ifdef GLP_DEBUG j = trow_ind[pos]; xassert(1 <= j && j <= n); xassert(stat[j] != GLP_NS); #endif temp = fabs(trow_vec[trow_ind[pos]]); if (big < temp) big = temp; } csa->trow_max = big; /* determine absolute pivot tolerance */ eps = tol_piv * (1.0 + 0.01 * big); /* move significant row components to the front of the list */ for (num = 0; num < nnz; ) { j = trow_ind[nnz]; if (fabs(trow_vec[j]) < eps) nnz--; else { num++; trow_ind[nnz] = trow_ind[num]; trow_ind[num] = j; } } csa->trow_num = num; return; } #ifdef GLP_LONG_STEP /* 07/IV-2009 */ static int ls_func(const void *p1_, const void *p2_) { const struct bkpt *p1 = p1_, *p2 = p2_; if (p1->t < p2->t) return -1; if (p1->t > p2->t) return +1; return 0; } static int ls_func1(const void *p1_, const void *p2_) { const struct bkpt *p1 = p1_, *p2 = p2_; if (p1->dz < p2->dz) return -1; if (p1->dz > p2->dz) return +1; return 0; } static void long_step(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; int *head = csa->head; char *stat = csa->stat; double *cbar = csa->cbar; double delta = csa->delta; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int trow_num = csa->trow_num; struct bkpt *bkpt = csa->bkpt; int j, k, kk, nbps, pos; double alfa, s, slope, dzmax; /* delta > 0 means that xB[p] violates its lower bound, so to increase the dual objective lambdaB[p] must increase; delta < 0 means that xB[p] violates its upper bound, so to increase the dual objective lambdaB[p] must decrease */ /* s := sign(delta) */ s = (delta > 0.0 ? +1.0 : -1.0); /* determine breakpoints of the dual objective */ nbps = 0; for (pos = 1; pos <= trow_num; pos++) { j = trow_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); xassert(stat[j] != GLP_NS); #endif /* if there is free non-basic variable, switch to the standard ratio test */ if (stat[j] == GLP_NF) { nbps = 0; goto done; } /* lambdaN[j] = ... - alfa * t - ..., where t = s * lambdaB[i] is the dual ray parameter, t >= 0 */ alfa = s * trow_vec[j]; #ifdef GLP_DEBUG xassert(alfa != 0.0); xassert(stat[j] == GLP_NL || stat[j] == GLP_NU); #endif if (alfa > 0.0 && stat[j] == GLP_NL || alfa < 0.0 && stat[j] == GLP_NU) { /* either lambdaN[j] >= 0 (if stat = GLP_NL) and decreases or lambdaN[j] <= 0 (if stat = GLP_NU) and increases; in both cases we have a breakpoint */ nbps++; #ifdef GLP_DEBUG xassert(nbps <= n); #endif bkpt[nbps].j = j; bkpt[nbps].t = cbar[j] / alfa; /* if (stat[j] == GLP_NL && cbar[j] < 0.0 || stat[j] == GLP_NU && cbar[j] > 0.0) xprintf("%d %g\n", stat[j], cbar[j]); */ /* if t is negative, replace it by exact zero (see comments in the routine chuzc) */ if (bkpt[nbps].t < 0.0) bkpt[nbps].t = 0.0; } } /* if there are less than two breakpoints, switch to the standard ratio test */ if (nbps < 2) { nbps = 0; goto done; } /* sort breakpoints by ascending the dual ray parameter, t */ qsort(&bkpt[1], nbps, sizeof(struct bkpt), ls_func); /* determine last breakpoint, at which the dual objective still greater than at t = 0 */ dzmax = 0.0; slope = fabs(delta); /* initial slope */ for (kk = 1; kk <= nbps; kk++) { if (kk == 1) bkpt[kk].dz = 0.0 + slope * (bkpt[kk].t - 0.0); else bkpt[kk].dz = bkpt[kk-1].dz + slope * (bkpt[kk].t - bkpt[kk-1].t); if (dzmax < bkpt[kk].dz) dzmax = bkpt[kk].dz; else if (bkpt[kk].dz < 0.05 * (1.0 + dzmax)) { nbps = kk - 1; break; } j = bkpt[kk].j; k = head[m+j]; /* x[k] = xN[j] */ if (type[k] == GLP_DB) slope -= fabs(trow_vec[j]) * (ub[k] - lb[k]); else { nbps = kk; break; } } /* if there are less than two breakpoints, switch to the standard ratio test */ if (nbps < 2) { nbps = 0; goto done; } /* sort breakpoints by ascending the dual change, dz */ qsort(&bkpt[1], nbps, sizeof(struct bkpt), ls_func1); /* for (kk = 1; kk <= nbps; kk++) xprintf("%d; t = %g; dz = %g\n", kk, bkpt[kk].t, bkpt[kk].dz); */ done: csa->nbps = nbps; return; } #endif /*********************************************************************** * chuzc - choose non-basic variable (column of the simplex table) * * This routine chooses non-basic variable xN[q], which being entered * in the basis keeps dual feasibility of the basic solution. * * The parameter rtol is a relative tolerance used to relax zero bounds * of reduced costs of non-basic variables. If rtol = 0, the routine * implements the standard ratio test. Otherwise, if rtol > 0, the * routine implements Harris' two-pass ratio test. In the latter case * rtol should be about three times less than a tolerance used to check * dual feasibility. */ static void chuzc(struct csa *csa, double rtol) { #ifdef GLP_DEBUG int m = csa->m; int n = csa->n; #endif char *stat = csa->stat; double *cbar = csa->cbar; #ifdef GLP_DEBUG int p = csa->p; #endif double delta = csa->delta; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int trow_num = csa->trow_num; int j, pos, q; double alfa, big, s, t, teta, tmax; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); #endif /* delta > 0 means that xB[p] violates its lower bound and goes to it in the adjacent basis, so lambdaB[p] is increasing from its lower zero bound; delta < 0 means that xB[p] violates its upper bound and goes to it in the adjacent basis, so lambdaB[p] is decreasing from its upper zero bound */ #ifdef GLP_DEBUG xassert(delta != 0.0); #endif /* s := sign(delta) */ s = (delta > 0.0 ? +1.0 : -1.0); /*** FIRST PASS ***/ /* nothing is chosen so far */ q = 0, teta = DBL_MAX, big = 0.0; /* walk through significant elements of the pivot row */ for (pos = 1; pos <= trow_num; pos++) { j = trow_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif alfa = s * trow_vec[j]; #ifdef GLP_DEBUG xassert(alfa != 0.0); #endif /* lambdaN[j] = ... - alfa * lambdaB[p] - ..., and due to s we need to consider only increasing lambdaB[p] */ if (alfa > 0.0) { /* lambdaN[j] is decreasing */ if (stat[j] == GLP_NL || stat[j] == GLP_NF) { /* lambdaN[j] has zero lower bound */ t = (cbar[j] + rtol) / alfa; } else { /* lambdaN[j] has no lower bound */ continue; } } else { /* lambdaN[j] is increasing */ if (stat[j] == GLP_NU || stat[j] == GLP_NF) { /* lambdaN[j] has zero upper bound */ t = (cbar[j] - rtol) / alfa; } else { /* lambdaN[j] has no upper bound */ continue; } } /* t is a change of lambdaB[p], on which lambdaN[j] reaches its zero bound (possibly relaxed); since the basic solution is assumed to be dual feasible, t has to be non-negative by definition; however, it may happen that lambdaN[j] slightly (i.e. within a tolerance) violates its zero bound, that leads to negative t; in the latter case, if xN[j] is chosen, negative t means that lambdaB[p] changes in wrong direction that may cause wrong results on updating reduced costs; thus, if t is negative, we should replace it by exact zero assuming that lambdaN[j] is exactly on its zero bound, and violation appears due to round-off errors */ if (t < 0.0) t = 0.0; /* apply minimal ratio test */ if (teta > t || teta == t && big < fabs(alfa)) q = j, teta = t, big = fabs(alfa); } /* the second pass is skipped in the following cases: */ /* if the standard ratio test is used */ if (rtol == 0.0) goto done; /* if no non-basic variable has been chosen on the first pass */ if (q == 0) goto done; /* if lambdaN[q] prevents lambdaB[p] from any change */ if (teta == 0.0) goto done; /*** SECOND PASS ***/ /* here tmax is a maximal change of lambdaB[p], on which the solution remains dual feasible within a tolerance */ #if 0 tmax = (1.0 + 10.0 * DBL_EPSILON) * teta; #else tmax = teta; #endif /* nothing is chosen so far */ q = 0, teta = DBL_MAX, big = 0.0; /* walk through significant elements of the pivot row */ for (pos = 1; pos <= trow_num; pos++) { j = trow_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif alfa = s * trow_vec[j]; #ifdef GLP_DEBUG xassert(alfa != 0.0); #endif /* lambdaN[j] = ... - alfa * lambdaB[p] - ..., and due to s we need to consider only increasing lambdaB[p] */ if (alfa > 0.0) { /* lambdaN[j] is decreasing */ if (stat[j] == GLP_NL || stat[j] == GLP_NF) { /* lambdaN[j] has zero lower bound */ t = cbar[j] / alfa; } else { /* lambdaN[j] has no lower bound */ continue; } } else { /* lambdaN[j] is increasing */ if (stat[j] == GLP_NU || stat[j] == GLP_NF) { /* lambdaN[j] has zero upper bound */ t = cbar[j] / alfa; } else { /* lambdaN[j] has no upper bound */ continue; } } /* (see comments for the first pass) */ if (t < 0.0) t = 0.0; /* t is a change of lambdaB[p], on which lambdaN[j] reaches its zero (lower or upper) bound; if t <= tmax, all reduced costs can violate their zero bounds only within relaxation tolerance rtol, so we can choose non-basic variable having largest influence coefficient to avoid possible numerical instability */ if (t <= tmax && big < fabs(alfa)) q = j, teta = t, big = fabs(alfa); } /* something must be chosen on the second pass */ xassert(q != 0); done: /* store the index of non-basic variable xN[q] chosen */ csa->q = q; /* store reduced cost of xN[q] in the adjacent basis */ csa->new_dq = s * teta; return; } #if 1 /* copied from primal */ /*********************************************************************** * eval_tcol - compute pivot column of the simplex table * * This routine computes the pivot column of the simplex table, which * corresponds to non-basic variable xN[q] chosen. * * The pivot column is the following vector: * * tcol = T * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], * * where B is the current basis matrix, N[q] is a column of the matrix * (I|-A) corresponding to variable xN[q]. */ static void eval_tcol(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *head = csa->head; int q = csa->q; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; double *h = csa->tcol_vec; int i, k, nnz; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif k = head[m+q]; /* x[k] = xN[q] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* construct the right-hand side vector h = - N[q] */ for (i = 1; i <= m; i++) h[i] = 0.0; if (k <= m) { /* N[q] is k-th column of submatrix I */ h[k] = -1.0; } else { /* N[q] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] = A_val[ptr]; } /* solve system B * tcol = h */ xassert(csa->valid); bfd_ftran(csa->bfd, tcol_vec); /* construct sparse pattern of the pivot column */ nnz = 0; for (i = 1; i <= m; i++) { if (tcol_vec[i] != 0.0) tcol_ind[++nnz] = i; } csa->tcol_nnz = nnz; return; } #endif #if 1 /* copied from primal */ /*********************************************************************** * refine_tcol - refine pivot column of the simplex table * * This routine refines the pivot column of the simplex table assuming * that it was previously computed by the routine eval_tcol. */ static void refine_tcol(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif int *head = csa->head; int q = csa->q; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; double *h = csa->work3; int i, k, nnz; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif k = head[m+q]; /* x[k] = xN[q] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* construct the right-hand side vector h = - N[q] */ for (i = 1; i <= m; i++) h[i] = 0.0; if (k <= m) { /* N[q] is k-th column of submatrix I */ h[k] = -1.0; } else { /* N[q] is (k-m)-th column of submatrix (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) h[A_ind[ptr]] = A_val[ptr]; } /* refine solution of B * tcol = h */ refine_ftran(csa, h, tcol_vec); /* construct sparse pattern of the pivot column */ nnz = 0; for (i = 1; i <= m; i++) { if (tcol_vec[i] != 0.0) tcol_ind[++nnz] = i; } csa->tcol_nnz = nnz; return; } #endif /*********************************************************************** * update_cbar - update reduced costs of non-basic variables * * This routine updates reduced costs of all (except fixed) non-basic * variables for the adjacent basis. */ static void update_cbar(struct csa *csa) { #ifdef GLP_DEBUG int n = csa->n; #endif double *cbar = csa->cbar; int trow_nnz = csa->trow_nnz; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int q = csa->q; double new_dq = csa->new_dq; int j, pos; #ifdef GLP_DEBUG xassert(1 <= q && q <= n); #endif /* set new reduced cost of xN[q] */ cbar[q] = new_dq; /* update reduced costs of other non-basic variables */ if (new_dq == 0.0) goto done; for (pos = 1; pos <= trow_nnz; pos++) { j = trow_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif if (j != q) cbar[j] -= trow_vec[j] * new_dq; } done: return; } /*********************************************************************** * update_bbar - update values of basic variables * * This routine updates values of all basic variables for the adjacent * basis. */ static void update_bbar(struct csa *csa) { #ifdef GLP_DEBUG int m = csa->m; int n = csa->n; #endif double *bbar = csa->bbar; int p = csa->p; double delta = csa->delta; int q = csa->q; int tcol_nnz = csa->tcol_nnz; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; int i, pos; double teta; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); #endif /* determine the change of xN[q] in the adjacent basis */ #ifdef GLP_DEBUG xassert(tcol_vec[p] != 0.0); #endif teta = delta / tcol_vec[p]; /* set new primal value of xN[q] */ bbar[p] = get_xN(csa, q) + teta; /* update primal values of other basic variables */ if (teta == 0.0) goto done; for (pos = 1; pos <= tcol_nnz; pos++) { i = tcol_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); #endif if (i != p) bbar[i] += tcol_vec[i] * teta; } done: return; } /*********************************************************************** * update_gamma - update steepest edge coefficients * * This routine updates steepest-edge coefficients for the adjacent * basis. */ static void update_gamma(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; int *head = csa->head; char *refsp = csa->refsp; double *gamma = csa->gamma; int p = csa->p; int trow_nnz = csa->trow_nnz; int *trow_ind = csa->trow_ind; double *trow_vec = csa->trow_vec; int q = csa->q; int tcol_nnz = csa->tcol_nnz; int *tcol_ind = csa->tcol_ind; double *tcol_vec = csa->tcol_vec; double *u = csa->work3; int i, j, k,pos; double gamma_p, eta_p, pivot, t, t1, t2; #ifdef GLP_DEBUG xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); #endif /* the basis changes, so decrease the count */ xassert(csa->refct > 0); csa->refct--; /* recompute gamma[p] for the current basis more accurately and compute auxiliary vector u */ #ifdef GLP_DEBUG xassert(type[head[p]] != GLP_FR); #endif gamma_p = eta_p = (refsp[head[p]] ? 1.0 : 0.0); for (i = 1; i <= m; i++) u[i] = 0.0; for (pos = 1; pos <= trow_nnz; pos++) { j = trow_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= j && j <= n); #endif k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); xassert(type[k] != GLP_FX); #endif if (!refsp[k]) continue; t = trow_vec[j]; gamma_p += t * t; /* u := u + N[j] * delta[j] * trow[j] */ if (k <= m) { /* N[k] = k-j stolbec submatrix I */ u[k] += t; } else { /* N[k] = k-m-k stolbec (-A) */ int *A_ptr = csa->A_ptr; int *A_ind = csa->A_ind; double *A_val = csa->A_val; int beg, end, ptr; beg = A_ptr[k-m]; end = A_ptr[k-m+1]; for (ptr = beg; ptr < end; ptr++) u[A_ind[ptr]] -= t * A_val[ptr]; } } xassert(csa->valid); bfd_ftran(csa->bfd, u); /* update gamma[i] for other basic variables (except xB[p] and free variables) */ pivot = tcol_vec[p]; #ifdef GLP_DEBUG xassert(pivot != 0.0); #endif for (pos = 1; pos <= tcol_nnz; pos++) { i = tcol_ind[pos]; #ifdef GLP_DEBUG xassert(1 <= i && i <= m); #endif k = head[i]; #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif /* skip xB[p] */ if (i == p) continue; /* skip free basic variable */ if (type[head[i]] == GLP_FR) { #ifdef GLP_DEBUG xassert(gamma[i] == 1.0); #endif continue; } /* compute gamma[i] for the adjacent basis */ t = tcol_vec[i] / pivot; t1 = gamma[i] + t * t * gamma_p + 2.0 * t * u[i]; t2 = (refsp[k] ? 1.0 : 0.0) + eta_p * t * t; gamma[i] = (t1 >= t2 ? t1 : t2); /* (though gamma[i] can be exact zero, because the reference space does not include non-basic fixed variables) */ if (gamma[i] < DBL_EPSILON) gamma[i] = DBL_EPSILON; } /* compute gamma[p] for the adjacent basis */ if (type[head[m+q]] == GLP_FR) gamma[p] = 1.0; else { gamma[p] = gamma_p / (pivot * pivot); if (gamma[p] < DBL_EPSILON) gamma[p] = DBL_EPSILON; } /* if xB[p], which becomes xN[q] in the adjacent basis, is fixed and belongs to the reference space, remove it from there, and change all gamma's appropriately */ k = head[p]; if (type[k] == GLP_FX && refsp[k]) { refsp[k] = 0; for (pos = 1; pos <= tcol_nnz; pos++) { i = tcol_ind[pos]; if (i == p) { if (type[head[m+q]] == GLP_FR) continue; t = 1.0 / tcol_vec[p]; } else { if (type[head[i]] == GLP_FR) continue; t = tcol_vec[i] / tcol_vec[p]; } gamma[i] -= t * t; if (gamma[i] < DBL_EPSILON) gamma[i] = DBL_EPSILON; } } return; } #if 1 /* copied from primal */ /*********************************************************************** * err_in_bbar - compute maximal relative error in primal solution * * This routine returns maximal relative error: * * max |beta[i] - bbar[i]| / (1 + |beta[i]|), * * where beta and bbar are, respectively, directly computed and the * current (updated) values of basic variables. * * NOTE: The routine is intended only for debugginig purposes. */ static double err_in_bbar(struct csa *csa) { int m = csa->m; double *bbar = csa->bbar; int i; double e, emax, *beta; beta = xcalloc(1+m, sizeof(double)); eval_beta(csa, beta); emax = 0.0; for (i = 1; i <= m; i++) { e = fabs(beta[i] - bbar[i]) / (1.0 + fabs(beta[i])); if (emax < e) emax = e; } xfree(beta); return emax; } #endif #if 1 /* copied from primal */ /*********************************************************************** * err_in_cbar - compute maximal relative error in dual solution * * This routine returns maximal relative error: * * max |cost[j] - cbar[j]| / (1 + |cost[j]|), * * where cost and cbar are, respectively, directly computed and the * current (updated) reduced costs of non-basic non-fixed variables. * * NOTE: The routine is intended only for debugginig purposes. */ static double err_in_cbar(struct csa *csa) { int m = csa->m; int n = csa->n; char *stat = csa->stat; double *cbar = csa->cbar; int j; double e, emax, cost, *pi; pi = xcalloc(1+m, sizeof(double)); eval_pi(csa, pi); emax = 0.0; for (j = 1; j <= n; j++) { if (stat[j] == GLP_NS) continue; cost = eval_cost(csa, pi, j); e = fabs(cost - cbar[j]) / (1.0 + fabs(cost)); if (emax < e) emax = e; } xfree(pi); return emax; } #endif /*********************************************************************** * err_in_gamma - compute maximal relative error in steepest edge cff. * * This routine returns maximal relative error: * * max |gamma'[j] - gamma[j]| / (1 + |gamma'[j]), * * where gamma'[j] and gamma[j] are, respectively, directly computed * and the current (updated) steepest edge coefficients for non-basic * non-fixed variable x[j]. * * NOTE: The routine is intended only for debugginig purposes. */ static double err_in_gamma(struct csa *csa) { int m = csa->m; char *type = csa->type; int *head = csa->head; double *gamma = csa->gamma; double *exact = csa->work4; int i; double e, emax, temp; eval_gamma(csa, exact); emax = 0.0; for (i = 1; i <= m; i++) { if (type[head[i]] == GLP_FR) { xassert(gamma[i] == 1.0); xassert(exact[i] == 1.0); continue; } temp = exact[i]; e = fabs(temp - gamma[i]) / (1.0 + fabs(temp)); if (emax < e) emax = e; } return emax; } /*********************************************************************** * change_basis - change basis header * * This routine changes the basis header to make it corresponding to * the adjacent basis. */ static void change_basis(struct csa *csa) { int m = csa->m; #ifdef GLP_DEBUG int n = csa->n; #endif char *type = csa->type; int *head = csa->head; #if 1 /* 06/IV-2009 */ int *bind = csa->bind; #endif char *stat = csa->stat; int p = csa->p; double delta = csa->delta; int q = csa->q; int k; /* xB[p] leaves the basis, xN[q] enters the basis */ #ifdef GLP_DEBUG xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); #endif /* xB[p] <-> xN[q] */ k = head[p], head[p] = head[m+q], head[m+q] = k; #if 1 /* 06/IV-2009 */ bind[head[p]] = p, bind[head[m+q]] = m + q; #endif if (type[k] == GLP_FX) stat[q] = GLP_NS; else if (delta > 0.0) { #ifdef GLP_DEBUG xassert(type[k] == GLP_LO || type[k] == GLP_DB); #endif stat[q] = GLP_NL; } else /* delta < 0.0 */ { #ifdef GLP_DEBUG xassert(type[k] == GLP_UP || type[k] == GLP_DB); #endif stat[q] = GLP_NU; } return; } /*********************************************************************** * check_feas - check dual feasibility of basic solution * * If the current basic solution is dual feasible within a tolerance, * this routine returns zero, otherwise it returns non-zero. */ static int check_feas(struct csa *csa, double tol_dj) { int m = csa->m; int n = csa->n; char *orig_type = csa->orig_type; int *head = csa->head; double *cbar = csa->cbar; int j, k; for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (cbar[j] < - tol_dj) if (orig_type[k] == GLP_LO || orig_type[k] == GLP_FR) return 1; if (cbar[j] > + tol_dj) if (orig_type[k] == GLP_UP || orig_type[k] == GLP_FR) return 1; } return 0; } /*********************************************************************** * set_aux_bnds - assign auxiliary bounds to variables * * This routine assigns auxiliary bounds to variables to construct an * LP problem solved on phase I. */ static void set_aux_bnds(struct csa *csa) { int m = csa->m; int n = csa->n; char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; char *orig_type = csa->orig_type; int *head = csa->head; char *stat = csa->stat; double *cbar = csa->cbar; int j, k; for (k = 1; k <= m+n; k++) { switch (orig_type[k]) { case GLP_FR: #if 0 type[k] = GLP_DB, lb[k] = -1.0, ub[k] = +1.0; #else /* to force free variables to enter the basis */ type[k] = GLP_DB, lb[k] = -1e3, ub[k] = +1e3; #endif break; case GLP_LO: type[k] = GLP_DB, lb[k] = 0.0, ub[k] = +1.0; break; case GLP_UP: type[k] = GLP_DB, lb[k] = -1.0, ub[k] = 0.0; break; case GLP_DB: case GLP_FX: type[k] = GLP_FX, lb[k] = ub[k] = 0.0; break; default: xassert(orig_type != orig_type); } } for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (type[k] == GLP_FX) stat[j] = GLP_NS; else if (cbar[j] >= 0.0) stat[j] = GLP_NL; else stat[j] = GLP_NU; } return; } /*********************************************************************** * set_orig_bnds - restore original bounds of variables * * This routine restores original types and bounds of variables and * determines statuses of non-basic variables assuming that the current * basis is dual feasible. */ static void set_orig_bnds(struct csa *csa) { int m = csa->m; int n = csa->n; char *type = csa->type; double *lb = csa->lb; double *ub = csa->ub; char *orig_type = csa->orig_type; double *orig_lb = csa->orig_lb; double *orig_ub = csa->orig_ub; int *head = csa->head; char *stat = csa->stat; double *cbar = csa->cbar; int j, k; memcpy(&type[1], &orig_type[1], (m+n) * sizeof(char)); memcpy(&lb[1], &orig_lb[1], (m+n) * sizeof(double)); memcpy(&ub[1], &orig_ub[1], (m+n) * sizeof(double)); for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif switch (type[k]) { case GLP_FR: stat[j] = GLP_NF; break; case GLP_LO: stat[j] = GLP_NL; break; case GLP_UP: stat[j] = GLP_NU; break; case GLP_DB: if (cbar[j] >= +DBL_EPSILON) stat[j] = GLP_NL; else if (cbar[j] <= -DBL_EPSILON) stat[j] = GLP_NU; else if (fabs(lb[k]) <= fabs(ub[k])) stat[j] = GLP_NL; else stat[j] = GLP_NU; break; case GLP_FX: stat[j] = GLP_NS; break; default: xassert(type != type); } } return; } /*********************************************************************** * check_stab - check numerical stability of basic solution * * If the current basic solution is dual feasible within a tolerance, * this routine returns zero, otherwise it returns non-zero. */ static int check_stab(struct csa *csa, double tol_dj) { int n = csa->n; char *stat = csa->stat; double *cbar = csa->cbar; int j; for (j = 1; j <= n; j++) { if (cbar[j] < - tol_dj) if (stat[j] == GLP_NL || stat[j] == GLP_NF) return 1; if (cbar[j] > + tol_dj) if (stat[j] == GLP_NU || stat[j] == GLP_NF) return 1; } return 0; } #if 1 /* copied from primal */ /*********************************************************************** * eval_obj - compute original objective function * * This routine computes the current value of the original objective * function. */ static double eval_obj(struct csa *csa) { int m = csa->m; int n = csa->n; double *obj = csa->obj; int *head = csa->head; double *bbar = csa->bbar; int i, j, k; double sum; sum = obj[0]; /* walk through the list of basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k > m) sum += obj[k-m] * bbar[i]; } /* walk through the list of non-basic variables */ for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k > m) sum += obj[k-m] * get_xN(csa, j); } return sum; } #endif /*********************************************************************** * display - display the search progress * * This routine displays some information about the search progress. */ static void display(struct csa *csa, const glp_smcp *parm, int spec) { int m = csa->m; int n = csa->n; double *coef = csa->coef; char *orig_type = csa->orig_type; int *head = csa->head; char *stat = csa->stat; int phase = csa->phase; double *bbar = csa->bbar; double *cbar = csa->cbar; int i, j, cnt; double sum; if (parm->msg_lev < GLP_MSG_ON) goto skip; if (parm->out_dly > 0 && 1000.0 * xdifftime(xtime(), csa->tm_beg) < parm->out_dly) goto skip; if (csa->it_cnt == csa->it_dpy) goto skip; if (!spec && csa->it_cnt % parm->out_frq != 0) goto skip; /* compute the sum of dual infeasibilities */ sum = 0.0; if (phase == 1) { for (i = 1; i <= m; i++) sum -= coef[head[i]] * bbar[i]; for (j = 1; j <= n; j++) sum -= coef[head[m+j]] * get_xN(csa, j); } else { for (j = 1; j <= n; j++) { if (cbar[j] < 0.0) if (stat[j] == GLP_NL || stat[j] == GLP_NF) sum -= cbar[j]; if (cbar[j] > 0.0) if (stat[j] == GLP_NU || stat[j] == GLP_NF) sum += cbar[j]; } } /* determine the number of basic fixed variables */ cnt = 0; for (i = 1; i <= m; i++) if (orig_type[head[i]] == GLP_FX) cnt++; if (csa->phase == 1) xprintf(" %6d: %24s infeas = %10.3e (%d)\n", csa->it_cnt, "", sum, cnt); else xprintf("|%6d: obj = %17.9e infeas = %10.3e (%d)\n", csa->it_cnt, eval_obj(csa), sum, cnt); csa->it_dpy = csa->it_cnt; skip: return; } #if 1 /* copied from primal */ /*********************************************************************** * store_sol - store basic solution back to the problem object * * This routine stores basic solution components back to the problem * object. */ static void store_sol(struct csa *csa, glp_prob *lp, int p_stat, int d_stat, int ray) { int m = csa->m; int n = csa->n; double zeta = csa->zeta; int *head = csa->head; char *stat = csa->stat; double *bbar = csa->bbar; double *cbar = csa->cbar; int i, j, k; #ifdef GLP_DEBUG xassert(lp->m == m); xassert(lp->n == n); #endif /* basis factorization */ #ifdef GLP_DEBUG xassert(!lp->valid && lp->bfd == NULL); xassert(csa->valid && csa->bfd != NULL); #endif lp->valid = 1, csa->valid = 0; lp->bfd = csa->bfd, csa->bfd = NULL; memcpy(&lp->head[1], &head[1], m * sizeof(int)); /* basic solution status */ lp->pbs_stat = p_stat; lp->dbs_stat = d_stat; /* objective function value */ lp->obj_val = eval_obj(csa); /* simplex iteration count */ lp->it_cnt = csa->it_cnt; /* unbounded ray */ lp->some = ray; /* basic variables */ for (i = 1; i <= m; i++) { k = head[i]; /* x[k] = xB[i] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { GLPROW *row = lp->row[k]; row->stat = GLP_BS; row->bind = i; row->prim = bbar[i] / row->rii; row->dual = 0.0; } else { GLPCOL *col = lp->col[k-m]; col->stat = GLP_BS; col->bind = i; col->prim = bbar[i] * col->sjj; col->dual = 0.0; } } /* non-basic variables */ for (j = 1; j <= n; j++) { k = head[m+j]; /* x[k] = xN[j] */ #ifdef GLP_DEBUG xassert(1 <= k && k <= m+n); #endif if (k <= m) { GLPROW *row = lp->row[k]; row->stat = stat[j]; row->bind = 0; #if 0 row->prim = get_xN(csa, j) / row->rii; #else switch (stat[j]) { case GLP_NL: row->prim = row->lb; break; case GLP_NU: row->prim = row->ub; break; case GLP_NF: row->prim = 0.0; break; case GLP_NS: row->prim = row->lb; break; default: xassert(stat != stat); } #endif row->dual = (cbar[j] * row->rii) / zeta; } else { GLPCOL *col = lp->col[k-m]; col->stat = stat[j]; col->bind = 0; #if 0 col->prim = get_xN(csa, j) * col->sjj; #else switch (stat[j]) { case GLP_NL: col->prim = col->lb; break; case GLP_NU: col->prim = col->ub; break; case GLP_NF: col->prim = 0.0; break; case GLP_NS: col->prim = col->lb; break; default: xassert(stat != stat); } #endif col->dual = (cbar[j] / col->sjj) / zeta; } } return; } #endif /*********************************************************************** * free_csa - deallocate common storage area * * This routine frees all the memory allocated to arrays in the common * storage area (CSA). */ static void free_csa(struct csa *csa) { xfree(csa->type); xfree(csa->lb); xfree(csa->ub); xfree(csa->coef); xfree(csa->orig_type); xfree(csa->orig_lb); xfree(csa->orig_ub); xfree(csa->obj); xfree(csa->A_ptr); xfree(csa->A_ind); xfree(csa->A_val); #if 1 /* 06/IV-2009 */ xfree(csa->AT_ptr); xfree(csa->AT_ind); xfree(csa->AT_val); #endif xfree(csa->head); #if 1 /* 06/IV-2009 */ xfree(csa->bind); #endif xfree(csa->stat); #if 0 /* 06/IV-2009 */ xfree(csa->N_ptr); xfree(csa->N_len); xfree(csa->N_ind); xfree(csa->N_val); #endif xfree(csa->bbar); xfree(csa->cbar); xfree(csa->refsp); xfree(csa->gamma); xfree(csa->trow_ind); xfree(csa->trow_vec); #ifdef GLP_LONG_STEP /* 07/IV-2009 */ xfree(csa->bkpt); #endif xfree(csa->tcol_ind); xfree(csa->tcol_vec); xfree(csa->work1); xfree(csa->work2); xfree(csa->work3); xfree(csa->work4); xfree(csa); return; } /*********************************************************************** * spx_dual - core LP solver based on the dual simplex method * * SYNOPSIS * * #include "glpspx.h" * int spx_dual(glp_prob *lp, const glp_smcp *parm); * * DESCRIPTION * * The routine spx_dual is a core LP solver based on the two-phase dual * simplex method. * * RETURNS * * 0 LP instance has been successfully solved. * * GLP_EOBJLL * Objective lower limit has been reached (maximization). * * GLP_EOBJUL * Objective upper limit has been reached (minimization). * * GLP_EITLIM * Iteration limit has been exhausted. * * GLP_ETMLIM * Time limit has been exhausted. * * GLP_EFAIL * The solver failed to solve LP instance. */ int spx_dual(glp_prob *lp, const glp_smcp *parm) { struct csa *csa; int binv_st = 2; /* status of basis matrix factorization: 0 - invalid; 1 - just computed; 2 - updated */ int bbar_st = 0; /* status of primal values of basic variables: 0 - invalid; 1 - just computed; 2 - updated */ int cbar_st = 0; /* status of reduced costs of non-basic variables: 0 - invalid; 1 - just computed; 2 - updated */ int rigorous = 0; /* rigorous mode flag; this flag is used to enable iterative refinement on computing pivot rows and columns of the simplex table */ int check = 0; int p_stat, d_stat, ret; #if 1 /* 16/VII-2013 */ int degen = 0; /* degenerated step count */ #endif /* allocate and initialize the common storage area */ csa = alloc_csa(lp); init_csa(csa, lp); if (parm->msg_lev >= GLP_MSG_DBG) xprintf("Objective scale factor = %g\n", csa->zeta); loop: /* main loop starts here */ /* compute factorization of the basis matrix */ if (binv_st == 0) { ret = invert_B(csa); if (ret != 0) { if (parm->msg_lev >= GLP_MSG_ERR) { xprintf("Error: unable to factorize the basis matrix (%d" ")\n", ret); xprintf("Sorry, basis recovery procedure not implemented" " yet\n"); } xassert(!lp->valid && lp->bfd == NULL); lp->bfd = csa->bfd, csa->bfd = NULL; lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; lp->obj_val = 0.0; lp->it_cnt = csa->it_cnt; lp->some = 0; ret = GLP_EFAIL; goto done; } csa->valid = 1; binv_st = 1; /* just computed */ /* invalidate basic solution components */ bbar_st = cbar_st = 0; } #if 1 /* 16/VII-2013 */ if (degen >= 5000 && parm->meth == GLP_DUALP) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: dual degeneracy; switching to primal simp" "lex\n"); store_sol(csa, lp, GLP_UNDEF, GLP_UNDEF, 0); ret = GLP_EFAIL; goto done; } #endif /* compute reduced costs of non-basic variables */ if (cbar_st == 0) { eval_cbar(csa); cbar_st = 1; /* just computed */ /* determine the search phase, if not determined yet */ if (csa->phase == 0) { if (check_feas(csa, 0.90 * parm->tol_dj) != 0) { /* current basic solution is dual infeasible */ /* start searching for dual feasible solution */ csa->phase = 1; set_aux_bnds(csa); } else { /* current basic solution is dual feasible */ /* start searching for optimal solution */ csa->phase = 2; set_orig_bnds(csa); } xassert(check_stab(csa, parm->tol_dj) == 0); /* some non-basic double-bounded variables might become fixed (on phase I) or vice versa (on phase II) */ #if 0 /* 06/IV-2009 */ build_N(csa); #endif csa->refct = 0; /* bounds of non-basic variables have been changed, so invalidate primal values */ bbar_st = 0; } /* make sure that the current basic solution remains dual feasible */ if (check_stab(csa, parm->tol_dj) != 0) { if (parm->msg_lev >= GLP_MSG_ERR) xprintf("Warning: numerical instability (dual simplex, p" "hase %s)\n", csa->phase == 1 ? "I" : "II"); #if 1 if (parm->meth == GLP_DUALP) { store_sol(csa, lp, GLP_UNDEF, GLP_UNDEF, 0); ret = GLP_EFAIL; goto done; } #endif /* restart the search */ csa->phase = 0; binv_st = 0; rigorous = 5; goto loop; } } xassert(csa->phase == 1 || csa->phase == 2); /* on phase I we do not need to wait until the current basic solution becomes primal feasible; it is sufficient to make sure that all reduced costs have correct signs */ if (csa->phase == 1 && check_feas(csa, parm->tol_dj) == 0) { /* the current basis is dual feasible; switch to phase II */ display(csa, parm, 1); csa->phase = 2; if (cbar_st != 1) { eval_cbar(csa); cbar_st = 1; } set_orig_bnds(csa); #if 0 /* 06/IV-2009 */ build_N(csa); #endif csa->refct = 0; bbar_st = 0; } /* compute primal values of basic variables */ if (bbar_st == 0) { eval_bbar(csa); if (csa->phase == 2) csa->bbar[0] = eval_obj(csa); bbar_st = 1; /* just computed */ } /* redefine the reference space, if required */ switch (parm->pricing) { case GLP_PT_STD: break; case GLP_PT_PSE: if (csa->refct == 0) reset_refsp(csa); break; default: xassert(parm != parm); } /* at this point the basis factorization and all basic solution components are valid */ xassert(binv_st && bbar_st && cbar_st); /* check accuracy of current basic solution components (only for debugging) */ if (check) { double e_bbar = err_in_bbar(csa); double e_cbar = err_in_cbar(csa); double e_gamma = (parm->pricing == GLP_PT_PSE ? err_in_gamma(csa) : 0.0); xprintf("e_bbar = %10.3e; e_cbar = %10.3e; e_gamma = %10.3e\n", e_bbar, e_cbar, e_gamma); xassert(e_bbar <= 1e-5 && e_cbar <= 1e-5 && e_gamma <= 1e-3); } /* if the objective has to be maximized, check if it has reached its lower limit */ if (csa->phase == 2 && csa->zeta < 0.0 && parm->obj_ll > -DBL_MAX && csa->bbar[0] <= parm->obj_ll) { if (bbar_st != 1 || cbar_st != 1) { if (bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); if (parm->msg_lev >= GLP_MSG_ALL) xprintf("OBJECTIVE LOWER LIMIT REACHED; SEARCH TERMINATED\n" ); store_sol(csa, lp, GLP_INFEAS, GLP_FEAS, 0); ret = GLP_EOBJLL; goto done; } /* if the objective has to be minimized, check if it has reached its upper limit */ if (csa->phase == 2 && csa->zeta > 0.0 && parm->obj_ul < +DBL_MAX && csa->bbar[0] >= parm->obj_ul) { if (bbar_st != 1 || cbar_st != 1) { if (bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); if (parm->msg_lev >= GLP_MSG_ALL) xprintf("OBJECTIVE UPPER LIMIT REACHED; SEARCH TERMINATED\n" ); store_sol(csa, lp, GLP_INFEAS, GLP_FEAS, 0); ret = GLP_EOBJUL; goto done; } /* check if the iteration limit has been exhausted */ if (parm->it_lim < INT_MAX && csa->it_cnt - csa->it_beg >= parm->it_lim) { if (csa->phase == 2 && bbar_st != 1 || cbar_st != 1) { if (csa->phase == 2 && bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); if (parm->msg_lev >= GLP_MSG_ALL) xprintf("ITERATION LIMIT EXCEEDED; SEARCH TERMINATED\n"); switch (csa->phase) { case 1: d_stat = GLP_INFEAS; set_orig_bnds(csa); eval_bbar(csa); break; case 2: d_stat = GLP_FEAS; break; default: xassert(csa != csa); } store_sol(csa, lp, GLP_INFEAS, d_stat, 0); ret = GLP_EITLIM; goto done; } /* check if the time limit has been exhausted */ if (parm->tm_lim < INT_MAX && 1000.0 * xdifftime(xtime(), csa->tm_beg) >= parm->tm_lim) { if (csa->phase == 2 && bbar_st != 1 || cbar_st != 1) { if (csa->phase == 2 && bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); if (parm->msg_lev >= GLP_MSG_ALL) xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); switch (csa->phase) { case 1: d_stat = GLP_INFEAS; set_orig_bnds(csa); eval_bbar(csa); break; case 2: d_stat = GLP_FEAS; break; default: xassert(csa != csa); } store_sol(csa, lp, GLP_INFEAS, d_stat, 0); ret = GLP_ETMLIM; goto done; } /* display the search progress */ display(csa, parm, 0); /* choose basic variable xB[p] */ chuzr(csa, parm->tol_bnd); if (csa->p == 0) { if (bbar_st != 1 || cbar_st != 1) { if (bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; goto loop; } display(csa, parm, 1); switch (csa->phase) { case 1: if (parm->msg_lev >= GLP_MSG_ALL) #if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ xprintf("PROBLEM HAS NO DUAL FEASIBLE SOLUTION\n"); #else xprintf("LP HAS NO DUAL FEASIBLE SOLUTION\n"); #endif set_orig_bnds(csa); eval_bbar(csa); p_stat = GLP_INFEAS, d_stat = GLP_NOFEAS; break; case 2: if (parm->msg_lev >= GLP_MSG_ALL) #if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ xprintf("OPTIMAL SOLUTION FOUND\n"); #else xprintf("OPTIMAL LP SOLUTION FOUND\n"); #endif p_stat = d_stat = GLP_FEAS; break; default: xassert(csa != csa); } store_sol(csa, lp, p_stat, d_stat, 0); ret = 0; goto done; } /* compute pivot row of the simplex table */ { double *rho = csa->work4; eval_rho(csa, rho); if (rigorous) refine_rho(csa, rho); eval_trow(csa, rho); sort_trow(csa, parm->tol_bnd); } /* unlike primal simplex there is no need to check accuracy of the primal value of xB[p] (which might be computed using the pivot row), since bbar is a result of FTRAN */ #ifdef GLP_LONG_STEP /* 07/IV-2009 */ long_step(csa); if (csa->nbps > 0) { csa->q = csa->bkpt[csa->nbps].j; if (csa->delta > 0.0) csa->new_dq = + csa->bkpt[csa->nbps].t; else csa->new_dq = - csa->bkpt[csa->nbps].t; } else #endif /* choose non-basic variable xN[q] */ switch (parm->r_test) { case GLP_RT_STD: chuzc(csa, 0.0); break; case GLP_RT_HAR: chuzc(csa, 0.30 * parm->tol_dj); break; default: xassert(parm != parm); } if (csa->q == 0) { if (bbar_st != 1 || cbar_st != 1 || !rigorous) { if (bbar_st != 1) bbar_st = 0; if (cbar_st != 1) cbar_st = 0; rigorous = 1; goto loop; } display(csa, parm, 1); switch (csa->phase) { case 1: if (parm->msg_lev >= GLP_MSG_ERR) xprintf("Error: unable to choose non-basic variable o" "n phase I\n"); xassert(!lp->valid && lp->bfd == NULL); lp->bfd = csa->bfd, csa->bfd = NULL; lp->pbs_stat = lp->dbs_stat = GLP_UNDEF; lp->obj_val = 0.0; lp->it_cnt = csa->it_cnt; lp->some = 0; ret = GLP_EFAIL; break; case 2: if (parm->msg_lev >= GLP_MSG_ALL) #if 0 /* 13/VII-2013; suggested by Prof. Fischetti */ xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); #else xprintf("LP HAS UNBOUNDED DUAL SOLUTION\n"); #endif store_sol(csa, lp, GLP_NOFEAS, GLP_FEAS, csa->head[csa->p]); ret = 0; break; default: xassert(csa != csa); } goto done; } /* check if the pivot element is acceptable */ { double piv = csa->trow_vec[csa->q]; double eps = 1e-5 * (1.0 + 0.01 * csa->trow_max); if (fabs(piv) < eps) { if (parm->msg_lev >= GLP_MSG_DBG) xprintf("piv = %.12g; eps = %g\n", piv, eps); if (!rigorous) { rigorous = 5; goto loop; } } } /* now xN[q] and xB[p] have been chosen anyhow */ /* compute pivot column of the simplex table */ eval_tcol(csa); if (rigorous) refine_tcol(csa); /* accuracy check based on the pivot element */ { double piv1 = csa->tcol_vec[csa->p]; /* more accurate */ double piv2 = csa->trow_vec[csa->q]; /* less accurate */ xassert(piv1 != 0.0); if (fabs(piv1 - piv2) > 1e-8 * (1.0 + fabs(piv1)) || !(piv1 > 0.0 && piv2 > 0.0 || piv1 < 0.0 && piv2 < 0.0)) { if (parm->msg_lev >= GLP_MSG_DBG) xprintf("piv1 = %.12g; piv2 = %.12g\n", piv1, piv2); if (binv_st != 1 || !rigorous) { if (binv_st != 1) binv_st = 0; rigorous = 5; goto loop; } /* (not a good idea; should be revised later) */ if (csa->tcol_vec[csa->p] == 0.0) { csa->tcol_nnz++; xassert(csa->tcol_nnz <= csa->m); csa->tcol_ind[csa->tcol_nnz] = csa->p; } csa->tcol_vec[csa->p] = piv2; } } /* update primal values of basic variables */ #ifdef GLP_LONG_STEP /* 07/IV-2009 */ if (csa->nbps > 0) { int kk, j, k; for (kk = 1; kk < csa->nbps; kk++) { if (csa->bkpt[kk].t >= csa->bkpt[csa->nbps].t) continue; j = csa->bkpt[kk].j; k = csa->head[csa->m + j]; xassert(csa->type[k] == GLP_DB); if (csa->stat[j] == GLP_NL) csa->stat[j] = GLP_NU; else csa->stat[j] = GLP_NL; } } bbar_st = 0; #else update_bbar(csa); if (csa->phase == 2) csa->bbar[0] += (csa->cbar[csa->q] / csa->zeta) * (csa->delta / csa->tcol_vec[csa->p]); bbar_st = 2; /* updated */ #endif /* update reduced costs of non-basic variables */ update_cbar(csa); cbar_st = 2; /* updated */ /* update steepest edge coefficients */ switch (parm->pricing) { case GLP_PT_STD: break; case GLP_PT_PSE: if (csa->refct > 0) update_gamma(csa); break; default: xassert(parm != parm); } /* update factorization of the basis matrix */ ret = update_B(csa, csa->p, csa->head[csa->m+csa->q]); if (ret == 0) binv_st = 2; /* updated */ else { csa->valid = 0; binv_st = 0; /* invalid */ } #if 0 /* 06/IV-2009 */ /* update matrix N */ del_N_col(csa, csa->q, csa->head[csa->m+csa->q]); if (csa->type[csa->head[csa->p]] != GLP_FX) add_N_col(csa, csa->q, csa->head[csa->p]); #endif /* change the basis header */ change_basis(csa); /* iteration complete */ csa->it_cnt++; #if 1 /* 16/VII-2013 */ if (-1e-9 <= csa->new_dq && csa->new_dq <= +1e-9) { /* degenerated step */ degen++; } else { /* non-degenerated step */ degen = 0; } #endif if (rigorous > 0) rigorous--; goto loop; done: /* deallocate the common storage area */ free_csa(csa); /* return to the calling program */ return ret; } /* eof */ glpk-4.52.1/src/glpsql.c0000644000062000006210000013200512175147600014157 0ustar maomkpasswd/* glpsql.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Author: Heinrich Schuchardt . * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include "glpmpl.h" #include "glpsql.h" #ifdef ODBC_DLNAME #define HAVE_ODBC #define libodbc ODBC_DLNAME #define h_odbc (get_env_ptr()->h_odbc) #endif #ifdef MYSQL_DLNAME #define HAVE_MYSQL #define libmysql MYSQL_DLNAME #define h_mysql (get_env_ptr()->h_mysql) #endif static void *db_iodbc_open_int(TABDCA *dca, int mode, const char **sqllines); static void *db_mysql_open_int(TABDCA *dca, int mode, const char **sqllines); /**********************************************************************/ #if defined(HAVE_ODBC) || defined(HAVE_MYSQL) #define SQL_FIELD_MAX 100 /* maximal field count */ #define SQL_FDLEN_MAX 255 /* maximal field length */ /*********************************************************************** * NAME * * args_concat - concatenate arguments * * SYNOPSIS * * static char **args_concat(TABDCA *dca); * * DESCRIPTION * * The arguments passed in dca are SQL statements. A SQL statement may * be split over multiple arguments. The last argument of a SQL * statement will be terminated with a semilocon. Each SQL statement is * merged into a single zero terminated string. Boundaries between * arguments are replaced by space. * * RETURNS * * Buffer with SQL statements */ static char **args_concat(TABDCA *dca) { const char *arg; int i; int j; int j0; int j1; int len; int lentot; int narg; int nline = 0; void *ret; char **sqllines = NULL; narg = mpl_tab_num_args(dca); /* The SQL statements start with argument 3. */ if (narg < 3) return NULL; /* Count the SQL statements */ for (j = 3; j <= narg; j++) { arg = mpl_tab_get_arg(dca, j); len = strlen(arg); if (arg[len-1] == ';' || j == narg) nline ++; } /* Allocate string buffer. */ sqllines = (char **) xmalloc((nline+1) * sizeof(char **)); /* Join arguments */ sqllines[0] = NULL; j0 = 3; i = 0; lentot = 0; for (j = 3; j <= narg; j++) { arg = mpl_tab_get_arg(dca, j); len = strlen(arg); /* add length of part */ lentot += len; /* add length of space separating parts or 0x00 at end of SQL statement */ lentot++; if (arg[len-1] == ';' || j == narg) { /* Join arguments for a single SQL statement */ sqllines[i] = xmalloc(lentot); sqllines[i+1] = NULL; sqllines[i][0] = 0x00; for (j1 = j0; j1 <= j; j1++) { if(j1>j0) strcat(sqllines[i], " "); strcat(sqllines[i], mpl_tab_get_arg(dca, j1)); } len = strlen(sqllines[i]); if (sqllines[i][len-1] == ';') sqllines[i][len-1] = 0x00; j0 = j+1; i++; lentot = 0; } } return sqllines; } /*********************************************************************** * NAME * * free_buffer - free multiline string buffer * * SYNOPSIS * * static void free_buffer(char **buf); * * DESCRIPTION * * buf is a list of strings terminated by NULL. * The memory for the strings and for the list is released. */ static void free_buffer(char **buf) { int i; for(i = 0; buf[i] != NULL; i++) xfree(buf[i]); xfree(buf); } static int db_escaped_string_length(const char* from) /* length of escaped string */ { int count; const char *pointer; for (pointer = from, count = 0; *pointer != (char) '\0'; pointer++, count++) { switch (*pointer) { case '\'': count++; break; } } return count; } static int db_escape_string (char *to, const char *from) /* escape string*/ { const char *source = from; char *target = to; unsigned int remaining; remaining = strlen(from); if (to == NULL) to = (char *) (from + remaining); while (remaining > 0) { switch (*source) { case '\'': *target = '\''; target++; *target = '\''; break; default: *target = *source; } source++; target++; remaining--; } /* Write the terminating NUL character. */ *target = '\0'; return target - to; } static char *db_generate_select_stmt(TABDCA *dca) /* generate select statement */ { char *arg; char const *field; char *query; int j; int narg; int nf; int total; total = 50; nf = mpl_tab_num_flds(dca); narg = mpl_tab_num_args(dca); for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) { field = mpl_tab_get_name(dca, j); total += strlen(field); total += 2; } arg = (char *) mpl_tab_get_arg(dca, narg); total += strlen(arg); query = xmalloc( total * sizeof(char)); strcpy (query, "SELECT "); for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) { field = mpl_tab_get_name(dca, j); strcat(query, field); if ( j < nf ) strcat(query, ", "); } strcat(query, " FROM "); strcat(query, arg); return query; } static char *db_generate_insert_stmt(TABDCA *dca) /* generate insert statement */ { char *arg; char const *field; char *query; int j; int narg; int nf; int total; total = 50; nf = mpl_tab_num_flds(dca); narg = mpl_tab_num_args(dca); for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) { field = mpl_tab_get_name(dca, j); total += strlen(field); total += 5; } arg = (char *) mpl_tab_get_arg(dca, narg); total += strlen(arg); query = xmalloc( (total+1) * sizeof(char)); strcpy (query, "INSERT INTO "); strcat(query, arg); strcat(query, " ( "); for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) { field = mpl_tab_get_name(dca, j); strcat(query, field); if ( j < nf ) strcat(query, ", "); } strcat(query, " ) VALUES ( "); for (j=1; j <= nf && j <= SQL_FIELD_MAX; j++) { strcat(query, "?"); if ( j < nf ) strcat(query, ", "); } strcat(query, " )"); return query; } #endif /**********************************************************************/ #ifndef HAVE_ODBC void *db_iodbc_open(TABDCA *dca, int mode) { xassert(dca == dca); xassert(mode == mode); xprintf("iODBC table driver not supported\n"); return NULL; } int db_iodbc_read(TABDCA *dca, void *link) { xassert(dca != dca); xassert(link != link); return 0; } int db_iodbc_write(TABDCA *dca, void *link) { xassert(dca != dca); xassert(link != link); return 0; } int db_iodbc_close(TABDCA *dca, void *link) { xassert(dca != dca); xassert(link != link); return 0; } #else #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) #include #endif #include #include struct db_odbc { int mode; /*'R' = Read, 'W' = Write*/ SQLHDBC hdbc; /*connection handle*/ SQLHENV henv; /*environment handle*/ SQLHSTMT hstmt; /*statement handle*/ SQLSMALLINT nresultcols; /* columns in result*/ SQLULEN collen[SQL_FIELD_MAX+1]; SQLLEN outlen[SQL_FIELD_MAX+1]; SQLSMALLINT coltype[SQL_FIELD_MAX+1]; SQLCHAR data[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; SQLCHAR colname[SQL_FIELD_MAX+1][SQL_FDLEN_MAX+1]; int isnumeric[SQL_FIELD_MAX+1]; int nf; /* number of fields in the csv file */ int ref[1+SQL_FIELD_MAX]; /* ref[k] = k', if k-th field of the csv file corresponds to k'-th field in the table statement; if ref[k] = 0, k-th field of the csv file is ignored */ SQLCHAR *query; /* query generated by db_iodbc_open */ }; SQLRETURN SQL_API dl_SQLAllocHandle ( SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle) { typedef SQLRETURN SQL_API ep_SQLAllocHandle( SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE *OutputHandle); ep_SQLAllocHandle *fn; fn = (ep_SQLAllocHandle *) xdlsym(h_odbc, "SQLAllocHandle"); xassert(fn != NULL); return (*fn)(HandleType, InputHandle, OutputHandle); } SQLRETURN SQL_API dl_SQLBindCol ( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValue, SQLLEN BufferLength, SQLLEN *StrLen_or_Ind) { typedef SQLRETURN SQL_API ep_SQLBindCol( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValue, SQLLEN BufferLength, SQLLEN *StrLen_or_Ind); ep_SQLBindCol *fn; fn = (ep_SQLBindCol *) xdlsym(h_odbc, "SQLBindCol"); xassert(fn != NULL); return (*fn)(StatementHandle, ColumnNumber, TargetType, TargetValue, BufferLength, StrLen_or_Ind); } SQLRETURN SQL_API dl_SQLCloseCursor ( SQLHSTMT StatementHandle) { typedef SQLRETURN SQL_API ep_SQLCloseCursor ( SQLHSTMT StatementHandle); ep_SQLCloseCursor *fn; fn = (ep_SQLCloseCursor *) xdlsym(h_odbc, "SQLCloseCursor"); xassert(fn != NULL); return (*fn)(StatementHandle); } SQLRETURN SQL_API dl_SQLDisconnect ( SQLHDBC ConnectionHandle) { typedef SQLRETURN SQL_API ep_SQLDisconnect( SQLHDBC ConnectionHandle); ep_SQLDisconnect *fn; fn = (ep_SQLDisconnect *) xdlsym(h_odbc, "SQLDisconnect"); xassert(fn != NULL); return (*fn)(ConnectionHandle); } SQLRETURN SQL_API dl_SQLDriverConnect ( SQLHDBC hdbc, SQLHWND hwnd, SQLCHAR *szConnStrIn, SQLSMALLINT cbConnStrIn, SQLCHAR *szConnStrOut, SQLSMALLINT cbConnStrOutMax, SQLSMALLINT *pcbConnStrOut, SQLUSMALLINT fDriverCompletion) { typedef SQLRETURN SQL_API ep_SQLDriverConnect( SQLHDBC hdbc, SQLHWND hwnd, SQLCHAR * szConnStrIn, SQLSMALLINT cbConnStrIn, SQLCHAR * szConnStrOut, SQLSMALLINT cbConnStrOutMax, SQLSMALLINT * pcbConnStrOut, SQLUSMALLINT fDriverCompletion); ep_SQLDriverConnect *fn; fn = (ep_SQLDriverConnect *) xdlsym(h_odbc, "SQLDriverConnect"); xassert(fn != NULL); return (*fn)(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion); } SQLRETURN SQL_API dl_SQLEndTran ( SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT CompletionType) { typedef SQLRETURN SQL_API ep_SQLEndTran ( SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT CompletionType); ep_SQLEndTran *fn; fn = (ep_SQLEndTran *) xdlsym(h_odbc, "SQLEndTran"); xassert(fn != NULL); return (*fn)(HandleType, Handle, CompletionType); } SQLRETURN SQL_API dl_SQLExecDirect ( SQLHSTMT StatementHandle, SQLCHAR * StatementText, SQLINTEGER TextLength) { typedef SQLRETURN SQL_API ep_SQLExecDirect ( SQLHSTMT StatementHandle, SQLCHAR * StatementText, SQLINTEGER TextLength); ep_SQLExecDirect *fn; fn = (ep_SQLExecDirect *) xdlsym(h_odbc, "SQLExecDirect"); xassert(fn != NULL); return (*fn)(StatementHandle, StatementText, TextLength); } SQLRETURN SQL_API dl_SQLFetch ( SQLHSTMT StatementHandle) { typedef SQLRETURN SQL_API ep_SQLFetch ( SQLHSTMT StatementHandle); ep_SQLFetch *fn; fn = (ep_SQLFetch*) xdlsym(h_odbc, "SQLFetch"); xassert(fn != NULL); return (*fn)(StatementHandle); } SQLRETURN SQL_API dl_SQLFreeHandle ( SQLSMALLINT HandleType, SQLHANDLE Handle) { typedef SQLRETURN SQL_API ep_SQLFreeHandle ( SQLSMALLINT HandleType, SQLHANDLE Handle); ep_SQLFreeHandle *fn; fn = (ep_SQLFreeHandle *) xdlsym(h_odbc, "SQLFreeHandle"); xassert(fn != NULL); return (*fn)(HandleType, Handle); } SQLRETURN SQL_API dl_SQLDescribeCol ( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLCHAR * ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT * NameLength, SQLSMALLINT * DataType, SQLULEN * ColumnSize, SQLSMALLINT * DecimalDigits, SQLSMALLINT * Nullable) { typedef SQLRETURN SQL_API ep_SQLDescribeCol ( SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLCHAR *ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT *NameLength, SQLSMALLINT *DataType, SQLULEN *ColumnSize, SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable); ep_SQLDescribeCol *fn; fn = (ep_SQLDescribeCol *) xdlsym(h_odbc, "SQLDescribeCol"); xassert(fn != NULL); return (*fn)(StatementHandle, ColumnNumber, ColumnName, BufferLength, NameLength, DataType, ColumnSize, DecimalDigits, Nullable); } SQLRETURN SQL_API dl_SQLGetDiagRec ( SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLCHAR *Sqlstate, SQLINTEGER *NativeError, SQLCHAR *MessageText, SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) { typedef SQLRETURN SQL_API ep_SQLGetDiagRec ( SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLCHAR *Sqlstate, SQLINTEGER *NativeError, SQLCHAR *MessageText, SQLSMALLINT BufferLength, SQLSMALLINT *TextLength); ep_SQLGetDiagRec *fn; fn = (ep_SQLGetDiagRec *) xdlsym(h_odbc, "SQLGetDiagRec"); xassert(fn != NULL); return (*fn)(HandleType, Handle, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength); } SQLRETURN SQL_API dl_SQLGetInfo ( SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValue, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength) { typedef SQLRETURN SQL_API ep_SQLGetInfo ( SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValue, SQLSMALLINT BufferLength, SQLSMALLINT *StringLength); ep_SQLGetInfo *fn; fn = (ep_SQLGetInfo *) xdlsym(h_odbc, "SQLGetInfo"); xassert(fn != NULL); return (*fn)(ConnectionHandle, InfoType, InfoValue, BufferLength, StringLength); } SQLRETURN SQL_API dl_SQLNumResultCols ( SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount) { typedef SQLRETURN SQL_API ep_SQLNumResultCols ( SQLHSTMT StatementHandle, SQLSMALLINT *ColumnCount); ep_SQLNumResultCols *fn; fn = (ep_SQLNumResultCols *) xdlsym(h_odbc, "SQLNumResultCols"); xassert(fn != NULL); return (*fn)(StatementHandle, ColumnCount); } SQLRETURN SQL_API dl_SQLSetConnectAttr ( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength) { typedef SQLRETURN SQL_API ep_SQLSetConnectAttr ( SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength); ep_SQLSetConnectAttr *fn; fn = (ep_SQLSetConnectAttr *) xdlsym(h_odbc, "SQLSetConnectAttr"); xassert(fn != NULL); return (*fn)(ConnectionHandle, Attribute, Value, StringLength); } SQLRETURN SQL_API dl_SQLSetEnvAttr ( SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength) { typedef SQLRETURN SQL_API ep_SQLSetEnvAttr ( SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength); ep_SQLSetEnvAttr *fn; fn = (ep_SQLSetEnvAttr *) xdlsym(h_odbc, "SQLSetEnvAttr"); xassert(fn != NULL); return (*fn)(EnvironmentHandle, Attribute, Value, StringLength); } static void extract_error( char *fn, SQLHANDLE handle, SQLSMALLINT type); static int is_numeric( SQLSMALLINT coltype); /*********************************************************************** * NAME * * db_iodbc_open - open connection to ODBC data base * * SYNOPSIS * * #include "glpsql.h" * void *db_iodbc_open(TABDCA *dca, int mode); * * DESCRIPTION * * The routine db_iodbc_open opens a connection to an ODBC data base. * It then executes the sql statements passed. * * In the case of table read the SELECT statement is executed. * * In the case of table write the INSERT statement is prepared. * RETURNS * * The routine returns a pointer to data storage area created. */ void *db_iodbc_open(TABDCA *dca, int mode) { void *ret; char **sqllines; sqllines = args_concat(dca); if (sqllines == NULL) { xprintf("Missing arguments in table statement.\n" "Please, supply table driver, dsn, and query.\n"); return NULL; } ret = db_iodbc_open_int(dca, mode, (const char **) sqllines); free_buffer(sqllines); return ret; } static void *db_iodbc_open_int(TABDCA *dca, int mode, const char **sqllines) { struct db_odbc *sql; SQLRETURN ret; SQLCHAR FAR *dsn; SQLCHAR info[256]; SQLSMALLINT colnamelen; SQLSMALLINT nullable; SQLSMALLINT scale; const char *arg; int narg; int i, j; int total; if (libodbc == NULL) { xprintf("No loader for shared ODBC library available\n"); return NULL; } if (h_odbc == NULL) { h_odbc = xdlopen(libodbc); if (h_odbc == NULL) { xprintf("unable to open library %s\n", libodbc); xprintf("%s\n", xerrmsg()); return NULL; } } sql = (struct db_odbc *) xmalloc(sizeof(struct db_odbc)); if (sql == NULL) return NULL; sql->mode = mode; sql->hdbc = NULL; sql->henv = NULL; sql->hstmt = NULL; sql->query = NULL; narg = mpl_tab_num_args(dca); dsn = (SQLCHAR FAR *) mpl_tab_get_arg(dca, 2); /* allocate an environment handle */ ret = dl_SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &(sql->henv)); /* set attribute to enable application to run as ODBC 3.0 application */ ret = dl_SQLSetEnvAttr(sql->henv, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0); /* allocate a connection handle */ ret = dl_SQLAllocHandle(SQL_HANDLE_DBC, sql->henv, &(sql->hdbc)); /* connect */ ret = dl_SQLDriverConnect(sql->hdbc, NULL, dsn, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE); if (SQL_SUCCEEDED(ret)) { /* output information about data base connection */ xprintf("Connected to "); dl_SQLGetInfo(sql->hdbc, SQL_DBMS_NAME, (SQLPOINTER)info, sizeof(info), NULL); xprintf("%s ", info); dl_SQLGetInfo(sql->hdbc, SQL_DBMS_VER, (SQLPOINTER)info, sizeof(info), NULL); xprintf("%s - ", info); dl_SQLGetInfo(sql->hdbc, SQL_DATABASE_NAME, (SQLPOINTER)info, sizeof(info), NULL); xprintf("%s\n", info); } else { /* describe error */ xprintf("Failed to connect\n"); extract_error("SQLDriverConnect", sql->hdbc, SQL_HANDLE_DBC); dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); xfree(sql); return NULL; } /* set AUTOCOMMIT on*/ ret = dl_SQLSetConnectAttr(sql->hdbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0); /* allocate a statement handle */ ret = dl_SQLAllocHandle(SQL_HANDLE_STMT, sql->hdbc, &(sql->hstmt)); /* initialization queries */ for(j = 0; sqllines[j+1] != NULL; j++) { sql->query = (SQLCHAR *) sqllines[j]; xprintf("%s\n", sql->query); ret = dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS); switch (ret) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: case SQL_NO_DATA_FOUND: break; default: xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", sql->query); extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); dl_SQLDisconnect(sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); xfree(sql); return NULL; } /* commit statement */ dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); } if ( sql->mode == 'R' ) { sql->nf = mpl_tab_num_flds(dca); for(j = 0; sqllines[j] != NULL; j++) arg = sqllines[j]; total = strlen(arg); if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) { total = strlen(arg); sql->query = xmalloc( (total+1) * sizeof(char)); strcpy (sql->query, arg); } else { sql->query = db_generate_select_stmt(dca); } xprintf("%s\n", sql->query); if (dl_SQLExecDirect(sql->hstmt, sql->query, SQL_NTS) != SQL_SUCCESS) { xprintf("db_iodbc_open: Query\n\"%s\"\nfailed.\n", sql->query); extract_error("SQLExecDirect", sql->hstmt, SQL_HANDLE_STMT); dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); dl_SQLDisconnect(sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); xfree(sql->query); xfree(sql); return NULL; } xfree(sql->query); /* determine number of result columns */ ret = dl_SQLNumResultCols(sql->hstmt, &sql->nresultcols); total = sql->nresultcols; if (total > SQL_FIELD_MAX) { xprintf("db_iodbc_open: Too many fields (> %d) in query.\n" "\"%s\"\n", SQL_FIELD_MAX, sql->query); dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); dl_SQLDisconnect(sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); xfree(sql->query); return NULL; } for (i = 1; i <= total; i++) { /* return a set of attributes for a column */ ret = dl_SQLDescribeCol(sql->hstmt, (SQLSMALLINT) i, sql->colname[i], SQL_FDLEN_MAX, &colnamelen, &(sql->coltype[i]), &(sql->collen[i]), &scale, &nullable); sql->isnumeric[i] = is_numeric(sql->coltype[i]); /* bind columns to program vars, converting all types to CHAR*/ if (sql->isnumeric[i]) { dl_SQLBindCol(sql->hstmt, i, SQL_DOUBLE, sql->data[i], SQL_FDLEN_MAX, &(sql->outlen[i])); } else { dl_SQLBindCol(sql->hstmt, i, SQL_CHAR, sql->data[i], SQL_FDLEN_MAX, &(sql->outlen[i])); } for (j = sql->nf; j >= 1; j--) { if (strcmp(mpl_tab_get_name(dca, j), sql->colname[i]) == 0) break; } sql->ref[i] = j; } } else if ( sql->mode == 'W' ) { for(j = 0; sqllines[j] != NULL; j++) arg = sqllines[j]; if ( NULL != strchr(arg, '?') ) { total = strlen(arg); sql->query = xmalloc( (total+1) * sizeof(char)); strcpy (sql->query, arg); } else { sql->query = db_generate_insert_stmt(dca); } xprintf("%s\n", sql->query); } return sql; } int db_iodbc_read(TABDCA *dca, void *link) { struct db_odbc *sql; SQLRETURN ret; char buf[SQL_FDLEN_MAX+1]; int i; int len; double num; sql = (struct db_odbc *) link; xassert(sql != NULL); xassert(sql->mode == 'R'); ret=dl_SQLFetch(sql->hstmt); if (ret== SQL_ERROR) return -1; if (ret== SQL_NO_DATA_FOUND) return -1; /*EOF*/ for (i=1; i <= sql->nresultcols; i++) { if (sql->ref[i] > 0) { len = sql->outlen[i]; if (len != SQL_NULL_DATA) { if (sql->isnumeric[i]) { mpl_tab_set_num(dca, sql->ref[i], *((const double *) sql->data[i])); } else { if (len > SQL_FDLEN_MAX) len = SQL_FDLEN_MAX; else if (len < 0) len = 0; strncpy(buf, (const char *) sql->data[i], len); buf[len] = 0x00; mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); } } } } return 0; } int db_iodbc_write(TABDCA *dca, void *link) { struct db_odbc *sql; char *part; char *query; char *template; char num[50]; int k; int len; int nf; sql = (struct db_odbc *) link; xassert(sql != NULL); xassert(sql->mode == 'W'); len = strlen(sql->query); template = (char *) xmalloc( (len + 1) * sizeof(char) ); strcpy(template, sql->query); nf = mpl_tab_num_flds(dca); for (k = 1; k <= nf; k++) { switch (mpl_tab_get_type(dca, k)) { case 'N': len += 20; break; case 'S': len += db_escaped_string_length(mpl_tab_get_str(dca, k)); len += 2; break; default: xassert(dca != dca); } } query = xmalloc( (len + 1 ) * sizeof(char) ); query[0] = 0x00; for (k = 1, part = strtok (template, "?"); (part != NULL); part = strtok (NULL, "?"), k++) { if (k > nf) break; strcat( query, part ); switch (mpl_tab_get_type(dca, k)) { case 'N': #if 0 /* 02/XI-2010 by xypron */ sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); #else sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); #endif strcat( query, num ); break; case 'S': strcat( query, "'"); db_escape_string( query + strlen(query), mpl_tab_get_str(dca, k) ); strcat( query, "'"); break; default: xassert(dca != dca); } } if (part != NULL) strcat(query, part); if (dl_SQLExecDirect(sql->hstmt, (SQLCHAR *) query, SQL_NTS) != SQL_SUCCESS) { xprintf("db_iodbc_write: Query\n\"%s\"\nfailed.\n", query); extract_error("SQLExecDirect", sql->hdbc, SQL_HANDLE_DBC); xfree(query); xfree(template); return 1; } xfree(query); xfree(template); return 0; } int db_iodbc_close(TABDCA *dca, void *link) { struct db_odbc *sql; sql = (struct db_odbc *) link; xassert(sql != NULL); /* Commit */ if ( sql->mode == 'W' ) dl_SQLEndTran(SQL_HANDLE_ENV, sql->henv, SQL_COMMIT); if ( sql->mode == 'R' ) dl_SQLCloseCursor(sql->hstmt); dl_SQLFreeHandle(SQL_HANDLE_STMT, sql->hstmt); dl_SQLDisconnect(sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_DBC, sql->hdbc); dl_SQLFreeHandle(SQL_HANDLE_ENV, sql->henv); if ( sql->mode == 'W' ) xfree(sql->query); xfree(sql); dca->link = NULL; return 0; } static void extract_error( char *fn, SQLHANDLE handle, SQLSMALLINT type) { SQLINTEGER i = 0; SQLINTEGER native; SQLCHAR state[ 7 ]; SQLCHAR text[256]; SQLSMALLINT len; SQLRETURN ret; xprintf("\nThe driver reported the following diagnostics whilst " "running %s\n", fn); do { ret = dl_SQLGetDiagRec(type, handle, ++i, state, &native, text, sizeof(text), &len ); if (SQL_SUCCEEDED(ret)) xprintf("%s:%ld:%ld:%s\n", state, i, native, text); } while( ret == SQL_SUCCESS ); } static int is_numeric(SQLSMALLINT coltype) { int ret = 0; switch (coltype) { case SQL_DECIMAL: case SQL_NUMERIC: case SQL_SMALLINT: case SQL_INTEGER: case SQL_REAL: case SQL_FLOAT: case SQL_DOUBLE: case SQL_TINYINT: case SQL_BIGINT: ret = 1; break; } return ret; } #endif /**********************************************************************/ #ifndef HAVE_MYSQL void *db_mysql_open(TABDCA *dca, int mode) { xassert(dca == dca); xassert(mode == mode); xprintf("MySQL table driver not supported\n"); return NULL; } int db_mysql_read(TABDCA *dca, void *link) { xassert(dca != dca); xassert(link != link); return 0; } int db_mysql_write(TABDCA *dca, void *link) { xassert(dca != dca); xassert(link != link); return 0; } int db_mysql_close(TABDCA *dca, void *link) { xassert(dca != dca); xassert(link != link); return 0; } #else #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__WOE__) #include #endif #ifdef __CYGWIN__ #define byte_defined 1 #endif #include #include #include struct db_mysql { int mode; /*'R' = Read, 'W' = Write*/ MYSQL *con; /*connection*/ MYSQL_RES *res; /*result*/ int nf; /* number of fields in the csv file */ int ref[1+SQL_FIELD_MAX]; /* ref[k] = k', if k-th field of the csv file corresponds to k'-th field in the table statement; if ref[k] = 0, k-th field of the csv file is ignored */ char *query; /* query generated by db_mysql_open */ }; void STDCALL dl_mysql_close(MYSQL *sock) { typedef void STDCALL ep_mysql_close(MYSQL *sock); ep_mysql_close *fn; fn = (ep_mysql_close *) xdlsym(h_mysql, "mysql_close"); xassert(fn != NULL); return (*fn)(sock); } const char * STDCALL dl_mysql_error(MYSQL *mysql) { typedef const char * STDCALL ep_mysql_error(MYSQL *mysql); ep_mysql_error *fn; fn = (ep_mysql_error *) xdlsym(h_mysql, "mysql_error"); xassert(fn != NULL); return (*fn)(mysql); } MYSQL_FIELD * STDCALL dl_mysql_fetch_fields(MYSQL_RES *res) { typedef MYSQL_FIELD * STDCALL ep_mysql_fetch_fields(MYSQL_RES *res); ep_mysql_fetch_fields *fn; fn = (ep_mysql_fetch_fields *) xdlsym(h_mysql, "mysql_fetch_fields"); xassert(fn != NULL); return (*fn)(res); } unsigned long * STDCALL dl_mysql_fetch_lengths(MYSQL_RES *result) { typedef unsigned long * STDCALL ep_mysql_fetch_lengths(MYSQL_RES *result); ep_mysql_fetch_lengths *fn; fn = (ep_mysql_fetch_lengths *) xdlsym(h_mysql, "mysql_fetch_lengths"); xassert(fn != NULL); return (*fn)(result); } MYSQL_ROW STDCALL dl_mysql_fetch_row(MYSQL_RES *result) { typedef MYSQL_ROW STDCALL ep_mysql_fetch_row(MYSQL_RES *result); ep_mysql_fetch_row *fn; fn = (ep_mysql_fetch_row *) xdlsym(h_mysql, "mysql_fetch_row"); xassert(fn != NULL); return (*fn)(result); } unsigned int STDCALL dl_mysql_field_count(MYSQL *mysql) { typedef unsigned int STDCALL ep_mysql_field_count(MYSQL *mysql); ep_mysql_field_count *fn; fn = (ep_mysql_field_count *) xdlsym(h_mysql, "mysql_field_count"); xassert(fn != NULL); return (*fn)(mysql); } MYSQL * STDCALL dl_mysql_init(MYSQL *mysql) { typedef MYSQL * STDCALL ep_mysql_init(MYSQL *mysql); ep_mysql_init *fn; fn = (ep_mysql_init *) xdlsym(h_mysql, "mysql_init"); xassert(fn != NULL); return (*fn)(mysql); } unsigned int STDCALL dl_mysql_num_fields(MYSQL_RES *res) { typedef unsigned int STDCALL ep_mysql_num_fields(MYSQL_RES *res); ep_mysql_num_fields *fn; fn = (ep_mysql_num_fields *) xdlsym(h_mysql, "mysql_num_fields"); xassert(fn != NULL); return (*fn)(res); } int STDCALL dl_mysql_query(MYSQL *mysql, const char *q) { typedef int STDCALL ep_mysql_query(MYSQL *mysql, const char *q); ep_mysql_query *fn; fn = (ep_mysql_query *) xdlsym(h_mysql, "mysql_query"); xassert(fn != NULL); return (*fn)(mysql, q); } MYSQL * STDCALL dl_mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag) { typedef MYSQL * STDCALL ep_mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag); ep_mysql_real_connect *fn; fn = (ep_mysql_real_connect *) xdlsym(h_mysql, "mysql_real_connect"); xassert(fn != NULL); return (*fn)(mysql, host, user, passwd, db, port, unix_socket, clientflag); } MYSQL_RES * STDCALL dl_mysql_use_result(MYSQL *mysql) { typedef MYSQL_RES * STDCALL ep_mysql_use_result(MYSQL *mysql); ep_mysql_use_result *fn; fn = (ep_mysql_use_result *) xdlsym(h_mysql, "mysql_use_result"); xassert(fn != NULL); return (*fn)(mysql); } /*********************************************************************** * NAME * * db_mysql_open - open connection to ODBC data base * * SYNOPSIS * * #include "glpsql.h" * void *db_mysql_open(TABDCA *dca, int mode); * * DESCRIPTION * * The routine db_mysql_open opens a connection to a MySQL data base. * It then executes the sql statements passed. * * In the case of table read the SELECT statement is executed. * * In the case of table write the INSERT statement is prepared. * RETURNS * * The routine returns a pointer to data storage area created. */ void *db_mysql_open(TABDCA *dca, int mode) { void *ret; char **sqllines; sqllines = args_concat(dca); if (sqllines == NULL) { xprintf("Missing arguments in table statement.\n" "Please, supply table driver, dsn, and query.\n"); return NULL; } ret = db_mysql_open_int(dca, mode, (const char **) sqllines); free_buffer(sqllines); return ret; } static void *db_mysql_open_int(TABDCA *dca, int mode, const char **sqllines) { struct db_mysql *sql = NULL; char *arg = NULL; const char *field; MYSQL_FIELD *fields; char *keyword; char *value; char *query; char *dsn; /* "Server=[server_name];Database=[database_name];UID=[username];*/ /* PWD=[password];Port=[port]"*/ char *server = NULL; /* Server */ char *user = NULL; /* UID */ char *password = NULL; /* PWD */ char *database = NULL; /* Database */ unsigned int port = 0; /* Port */ int narg; int i, j, total; if (libmysql == NULL) { xprintf("No loader for shared MySQL library available\n"); return NULL; } if (h_mysql == NULL) { h_mysql = xdlopen(libmysql); if (h_mysql == NULL) { xprintf("unable to open library %s\n", libmysql); xprintf("%s\n", xerrmsg()); return NULL; } } sql = (struct db_mysql *) xmalloc(sizeof(struct db_mysql)); if (sql == NULL) return NULL; sql->mode = mode; sql->res = NULL; sql->query = NULL; sql->nf = mpl_tab_num_flds(dca); narg = mpl_tab_num_args(dca); if (narg < 3 ) xprintf("MySQL driver: string list too short \n"); /* get connection string*/ dsn = (char *) mpl_tab_get_arg(dca, 2); /* copy connection string*/ i = strlen(dsn); i++; arg = xmalloc(i * sizeof(char)); strcpy(arg, dsn); /*tokenize connection string*/ for (i = 1, keyword = strtok (arg, "="); (keyword != NULL); keyword = strtok (NULL, "="), i++) { value = strtok (NULL, ";"); if (value==NULL) { xprintf("db_mysql_open: Missing value for keyword %s\n", keyword); xfree(arg); xfree(sql); return NULL; } if (0 == strcmp(keyword, "Server")) server = value; else if (0 == strcmp(keyword, "Database")) database = value; else if (0 == strcmp(keyword, "UID")) user = value; else if (0 == strcmp(keyword, "PWD")) password = value; else if (0 == strcmp(keyword, "Port")) port = (unsigned int) atol(value); } /* Connect to database */ sql->con = dl_mysql_init(NULL); if (!dl_mysql_real_connect(sql->con, server, user, password, database, port, NULL, 0)) { xprintf("db_mysql_open: Connect failed\n"); xprintf("%s\n", dl_mysql_error(sql->con)); xfree(arg); xfree(sql); return NULL; } xfree(arg); for(j = 0; sqllines[j+1] != NULL; j++) { query = (char *) sqllines[j]; xprintf("%s\n", query); if (dl_mysql_query(sql->con, query)) { xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); xprintf("%s\n",dl_mysql_error(sql->con)); dl_mysql_close(sql->con); xfree(sql); return NULL; } } if ( sql->mode == 'R' ) { sql->nf = mpl_tab_num_flds(dca); for(j = 0; sqllines[j] != NULL; j++) arg = (char *) sqllines[j]; total = strlen(arg); if (total > 7 && 0 == strncmp(arg, "SELECT ", 7)) { total = strlen(arg); query = xmalloc( (total+1) * sizeof(char)); strcpy (query, arg); } else { query = db_generate_select_stmt(dca); } xprintf("%s\n", query); if (dl_mysql_query(sql->con, query)) { xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); xprintf("%s\n",dl_mysql_error(sql->con)); dl_mysql_close(sql->con); xfree(query); xfree(sql); return NULL; } xfree(query); sql->res = dl_mysql_use_result(sql->con); if (sql->res) { /* create references between query results and table fields*/ total = dl_mysql_num_fields(sql->res); if (total > SQL_FIELD_MAX) { xprintf("db_mysql_open: Too many fields (> %d) in query.\n" "\"%s\"\n", SQL_FIELD_MAX, query); xprintf("%s\n",dl_mysql_error(sql->con)); dl_mysql_close(sql->con); xfree(query); xfree(sql); return NULL; } fields = dl_mysql_fetch_fields(sql->res); for (i = 1; i <= total; i++) { for (j = sql->nf; j >= 1; j--) { if (strcmp(mpl_tab_get_name(dca, j), fields[i-1].name) == 0) break; } sql->ref[i] = j; } } else { if(dl_mysql_field_count(sql->con) == 0) { xprintf("db_mysql_open: Query was not a SELECT\n\"%s\"\n", query); xprintf("%s\n",dl_mysql_error(sql->con)); xfree(query); xfree(sql); return NULL; } else { xprintf("db_mysql_open: Query\n\"%s\"\nfailed.\n", query); xprintf("%s\n",dl_mysql_error(sql->con)); xfree(query); xfree(sql); return NULL; } } } else if ( sql->mode == 'W' ) { for(j = 0; sqllines[j] != NULL; j++) arg = (char *) sqllines[j]; if ( NULL != strchr(arg, '?') ) { total = strlen(arg); query = xmalloc( (total+1) * sizeof(char)); strcpy (query, arg); } else query = db_generate_insert_stmt(dca); sql->query = query; xprintf("%s\n", query); } return sql; } int db_mysql_read(TABDCA *dca, void *link) { struct db_mysql *sql; char buf[255+1]; char **row; unsigned long *lengths; MYSQL_FIELD *fields; double num; int len; unsigned long num_fields; int i; sql = (struct db_mysql *) link; xassert(sql != NULL); xassert(sql->mode == 'R'); if (NULL == sql->res) { xprintf("db_mysql_read: no result set available"); return 1; } if (NULL==(row = (char **)dl_mysql_fetch_row(sql->res))) { return -1; /*EOF*/ } lengths = dl_mysql_fetch_lengths(sql->res); fields = dl_mysql_fetch_fields(sql->res); num_fields = dl_mysql_num_fields(sql->res); for (i=1; i <= num_fields; i++) { if (row[i-1] != NULL) { len = (size_t) lengths[i-1]; if (len > 255) len = 255; strncpy(buf, (const char *) row[i-1], len); buf[len] = 0x00; if (0 != (fields[i-1].flags & NUM_FLAG)) { strspx(buf); /* remove spaces*/ if (str2num(buf, &num) != 0) { xprintf("'%s' cannot be converted to a number.\n", buf); return 1; } if (sql->ref[i] > 0) mpl_tab_set_num(dca, sql->ref[i], num); } else { if (sql->ref[i] > 0) mpl_tab_set_str(dca, sql->ref[i], strtrim(buf)); } } } return 0; } int db_mysql_write(TABDCA *dca, void *link) { struct db_mysql *sql; char *part; char *query; char *template; char num[50]; int k; int len; int nf; sql = (struct db_mysql *) link; xassert(sql != NULL); xassert(sql->mode == 'W'); len = strlen(sql->query); template = (char *) xmalloc( (len + 1) * sizeof(char) ); strcpy(template, sql->query); nf = mpl_tab_num_flds(dca); for (k = 1; k <= nf; k++) { switch (mpl_tab_get_type(dca, k)) { case 'N': len += 20; break; case 'S': len += db_escaped_string_length(mpl_tab_get_str(dca, k)); len += 2; break; default: xassert(dca != dca); } } query = xmalloc( (len + 1 ) * sizeof(char) ); query[0] = 0x00; for (k = 1, part = strtok (template, "?"); (part != NULL); part = strtok (NULL, "?"), k++) { if (k > nf) break; strcat( query, part ); switch (mpl_tab_get_type(dca, k)) { case 'N': #if 0 /* 02/XI-2010 by xypron */ sprintf(num, "%-18g",mpl_tab_get_num(dca, k)); #else sprintf(num, "%.*g", DBL_DIG, mpl_tab_get_num(dca, k)); #endif strcat( query, num ); break; case 'S': strcat( query, "'"); db_escape_string( query + strlen(query), mpl_tab_get_str(dca, k) ); strcat( query, "'"); break; default: xassert(dca != dca); } } if (part != NULL) strcat(query, part); if (dl_mysql_query(sql->con, query)) { xprintf("db_mysql_write: Query\n\"%s\"\nfailed.\n", query); xprintf("%s\n",dl_mysql_error(sql->con)); xfree(query); xfree(template); return 1; } xfree(query); xfree(template); return 0; } int db_mysql_close(TABDCA *dca, void *link) { struct db_mysql *sql; sql = (struct db_mysql *) link; xassert(sql != NULL); dl_mysql_close(sql->con); if ( sql->mode == 'W' ) xfree(sql->query); xfree(sql); dca->link = NULL; return 0; } #endif /* eof */ glpk-4.52.1/src/glpsql.h0000644000062000006210000000415712175147600014172 0ustar maomkpasswd/* glpsql.h */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Author: Heinrich Schuchardt . * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPSQL_H #define GLPSQL_H #define db_iodbc_open _glp_db_iodbc_open void *db_iodbc_open(TABDCA *dca, int mode); /* open iODBC database connection */ #define db_iodbc_read _glp_db_iodbc_read int db_iodbc_read(TABDCA *dca, void *link); /* read data from iODBC */ #define db_iodbc_write _glp_db_iodbc_write int db_iodbc_write(TABDCA *dca, void *link); /* write data to iODBC */ #define db_iodbc_close _glp_db_iodbc_close int db_iodbc_close(TABDCA *dca, void *link); /* close iODBC database connection */ #define db_mysql_open _glp_db_mysql_open void *db_mysql_open(TABDCA *dca, int mode); /* open MySQL database connection */ #define db_mysql_read _glp_db_mysql_read int db_mysql_read(TABDCA *dca, void *link); /* read data from MySQL */ #define db_mysql_write _glp_db_mysql_write int db_mysql_write(TABDCA *dca, void *link); /* write data to MySQL */ #define db_mysql_close _glp_db_mysql_close int db_mysql_close(TABDCA *dca, void *link); /* close MySQL database connection */ #endif /* eof */ glpk-4.52.1/src/glpssx.h0000644000062000006210000004032312175147600014203 0ustar maomkpasswd/* glpssx.h (simplex method, bignum arithmetic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPSSX_H #define GLPSSX_H #include "glpbfx.h" #include "env.h" typedef struct SSX SSX; struct SSX { /* simplex solver workspace */ /*---------------------------------------------------------------------- // LP PROBLEM DATA // // It is assumed that LP problem has the following statement: // // minimize (or maximize) // // z = c[1]*x[1] + ... + c[m+n]*x[m+n] + c[0] (1) // // subject to equality constraints // // x[1] - a[1,1]*x[m+1] - ... - a[1,n]*x[m+n] = 0 // // . . . . . . . (2) // // x[m] - a[m,1]*x[m+1] + ... - a[m,n]*x[m+n] = 0 // // and bounds of variables // // l[1] <= x[1] <= u[1] // // . . . . . . . (3) // // l[m+n] <= x[m+n] <= u[m+n] // // where: // x[1], ..., x[m] - auxiliary variables; // x[m+1], ..., x[m+n] - structural variables; // z - objective function; // c[1], ..., c[m+n] - coefficients of the objective function; // c[0] - constant term of the objective function; // a[1,1], ..., a[m,n] - constraint coefficients; // l[1], ..., l[m+n] - lower bounds of variables; // u[1], ..., u[m+n] - upper bounds of variables. // // Bounds of variables can be finite as well as inifinite. Besides, // lower and upper bounds can be equal to each other. So the following // five types of variables are possible: // // Bounds of variable Type of variable // ------------------------------------------------- // -inf < x[k] < +inf Free (unbounded) variable // l[k] <= x[k] < +inf Variable with lower bound // -inf < x[k] <= u[k] Variable with upper bound // l[k] <= x[k] <= u[k] Double-bounded variable // l[k] = x[k] = u[k] Fixed variable // // Using vector-matrix notations the LP problem (1)-(3) can be written // as follows: // // minimize (or maximize) // // z = c * x + c[0] (4) // // subject to equality constraints // // xR - A * xS = 0 (5) // // and bounds of variables // // l <= x <= u (6) // // where: // xR - vector of auxiliary variables; // xS - vector of structural variables; // x = (xR, xS) - vector of all variables; // z - objective function; // c - vector of objective coefficients; // c[0] - constant term of the objective function; // A - matrix of constraint coefficients (has m rows // and n columns); // l - vector of lower bounds of variables; // u - vector of upper bounds of variables. // // The simplex method makes no difference between auxiliary and // structural variables, so it is convenient to think the system of // equality constraints (5) written in a homogeneous form: // // (I | -A) * x = 0, (7) // // where (I | -A) is an augmented (m+n)xm constraint matrix, I is mxm // unity matrix whose columns correspond to auxiliary variables, and A // is the original mxn constraint matrix whose columns correspond to // structural variables. Note that only the matrix A is stored. ----------------------------------------------------------------------*/ int m; /* number of rows (auxiliary variables), m > 0 */ int n; /* number of columns (structural variables), n > 0 */ int *type; /* int type[1+m+n]; */ /* type[0] is not used; type[k], 1 <= k <= m+n, is the type of variable x[k]: */ #define SSX_FR 0 /* free (unbounded) variable */ #define SSX_LO 1 /* variable with lower bound */ #define SSX_UP 2 /* variable with upper bound */ #define SSX_DB 3 /* double-bounded variable */ #define SSX_FX 4 /* fixed variable */ mpq_t *lb; /* mpq_t lb[1+m+n]; alias: l */ /* lb[0] is not used; lb[k], 1 <= k <= m+n, is an lower bound of variable x[k]; if x[k] has no lower bound, lb[k] is zero */ mpq_t *ub; /* mpq_t ub[1+m+n]; alias: u */ /* ub[0] is not used; ub[k], 1 <= k <= m+n, is an upper bound of variable x[k]; if x[k] has no upper bound, ub[k] is zero; if x[k] is of fixed type, ub[k] is equal to lb[k] */ int dir; /* optimization direction (sense of the objective function): */ #define SSX_MIN 0 /* minimization */ #define SSX_MAX 1 /* maximization */ mpq_t *coef; /* mpq_t coef[1+m+n]; alias: c */ /* coef[0] is a constant term of the objective function; coef[k], 1 <= k <= m+n, is a coefficient of the objective function at variable x[k]; note that auxiliary variables also may have non-zero objective coefficients */ int *A_ptr; /* int A_ptr[1+n+1]; */ int *A_ind; /* int A_ind[A_ptr[n+1]]; */ mpq_t *A_val; /* mpq_t A_val[A_ptr[n+1]]; */ /* constraint matrix A (see (5)) in storage-by-columns format */ /*---------------------------------------------------------------------- // LP BASIS AND CURRENT BASIC SOLUTION // // The LP basis is defined by the following partition of the augmented // constraint matrix (7): // // (B | N) = (I | -A) * Q, (8) // // where B is a mxm non-singular basis matrix whose columns correspond // to basic variables xB, N is a mxn matrix whose columns correspond to // non-basic variables xN, and Q is a permutation (m+n)x(m+n) matrix. // // From (7) and (8) it follows that // // (I | -A) * x = (I | -A) * Q * Q' * x = (B | N) * (xB, xN), // // therefore // // (xB, xN) = Q' * x, (9) // // where x is the vector of all variables in the original order, xB is // a vector of basic variables, xN is a vector of non-basic variables, // Q' = inv(Q) is a matrix transposed to Q. // // Current values of non-basic variables xN[j], j = 1, ..., n, are not // stored; they are defined implicitly by their statuses as follows: // // 0, if xN[j] is free variable // lN[j], if xN[j] is on its lower bound (10) // uN[j], if xN[j] is on its upper bound // lN[j] = uN[j], if xN[j] is fixed variable // // where lN[j] and uN[j] are lower and upper bounds of xN[j]. // // Current values of basic variables xB[i], i = 1, ..., m, are computed // as follows: // // beta = - inv(B) * N * xN, (11) // // where current values of xN are defined by (10). // // Current values of simplex multipliers pi[i], i = 1, ..., m (which // are values of Lagrange multipliers for equality constraints (7) also // called shadow prices) are computed as follows: // // pi = inv(B') * cB, (12) // // where B' is a matrix transposed to B, cB is a vector of objective // coefficients at basic variables xB. // // Current values of reduced costs d[j], j = 1, ..., n, (which are // values of Langrange multipliers for active inequality constraints // corresponding to non-basic variables) are computed as follows: // // d = cN - N' * pi, (13) // // where N' is a matrix transposed to N, cN is a vector of objective // coefficients at non-basic variables xN. ----------------------------------------------------------------------*/ int *stat; /* int stat[1+m+n]; */ /* stat[0] is not used; stat[k], 1 <= k <= m+n, is the status of variable x[k]: */ #define SSX_BS 0 /* basic variable */ #define SSX_NL 1 /* non-basic variable on lower bound */ #define SSX_NU 2 /* non-basic variable on upper bound */ #define SSX_NF 3 /* non-basic free variable */ #define SSX_NS 4 /* non-basic fixed variable */ int *Q_row; /* int Q_row[1+m+n]; */ /* matrix Q in row-like format; Q_row[0] is not used; Q_row[i] = j means that q[i,j] = 1 */ int *Q_col; /* int Q_col[1+m+n]; */ /* matrix Q in column-like format; Q_col[0] is not used; Q_col[j] = i means that q[i,j] = 1 */ /* if k-th column of the matrix (I | A) is k'-th column of the matrix (B | N), then Q_row[k] = k' and Q_col[k'] = k; if x[k] is xB[i], then Q_row[k] = i and Q_col[i] = k; if x[k] is xN[j], then Q_row[k] = m+j and Q_col[m+j] = k */ BFX *binv; /* invertable form of the basis matrix B */ mpq_t *bbar; /* mpq_t bbar[1+m]; alias: beta */ /* bbar[0] is a value of the objective function; bbar[i], 1 <= i <= m, is a value of basic variable xB[i] */ mpq_t *pi; /* mpq_t pi[1+m]; */ /* pi[0] is not used; pi[i], 1 <= i <= m, is a simplex multiplier corresponding to i-th row (equality constraint) */ mpq_t *cbar; /* mpq_t cbar[1+n]; alias: d */ /* cbar[0] is not used; cbar[j], 1 <= j <= n, is a reduced cost of non-basic variable xN[j] */ /*---------------------------------------------------------------------- // SIMPLEX TABLE // // Due to (8) and (9) the system of equality constraints (7) for the // current basis can be written as follows: // // xB = A~ * xN, (14) // // where // // A~ = - inv(B) * N (15) // // is a mxn matrix called the simplex table. // // The revised simplex method uses only two components of A~, namely, // pivot column corresponding to non-basic variable xN[q] chosen to // enter the basis, and pivot row corresponding to basic variable xB[p] // chosen to leave the basis. // // Pivot column alfa_q is q-th column of A~, so // // alfa_q = A~ * e[q] = - inv(B) * N * e[q] = - inv(B) * N[q], (16) // // where N[q] is q-th column of the matrix N. // // Pivot row alfa_p is p-th row of A~ or, equivalently, p-th column of // A~', a matrix transposed to A~, so // // alfa_p = A~' * e[p] = - N' * inv(B') * e[p] = - N' * rho_p, (17) // // where (*)' means transposition, and // // rho_p = inv(B') * e[p], (18) // // is p-th column of inv(B') or, that is the same, p-th row of inv(B). ----------------------------------------------------------------------*/ int p; /* number of basic variable xB[p], 1 <= p <= m, chosen to leave the basis */ mpq_t *rho; /* mpq_t rho[1+m]; */ /* p-th row of the inverse inv(B); see (18) */ mpq_t *ap; /* mpq_t ap[1+n]; */ /* p-th row of the simplex table; see (17) */ int q; /* number of non-basic variable xN[q], 1 <= q <= n, chosen to enter the basis */ mpq_t *aq; /* mpq_t aq[1+m]; */ /* q-th column of the simplex table; see (16) */ /*--------------------------------------------------------------------*/ int q_dir; /* direction in which non-basic variable xN[q] should change on moving to the adjacent vertex of the polyhedron: +1 means that xN[q] increases -1 means that xN[q] decreases */ int p_stat; /* non-basic status which should be assigned to basic variable xB[p] when it has left the basis and become xN[q] */ mpq_t delta; /* actual change of xN[q] in the adjacent basis (it has the same sign as q_dir) */ /*--------------------------------------------------------------------*/ int it_lim; /* simplex iterations limit; if this value is positive, it is decreased by one each time when one simplex iteration has been performed, and reaching zero value signals the solver to stop the search; negative value means no iterations limit */ int it_cnt; /* simplex iterations count; this count is increased by one each time when one simplex iteration has been performed */ double tm_lim; /* searching time limit, in seconds; if this value is positive, it is decreased each time when one simplex iteration has been performed by the amount of time spent for the iteration, and reaching zero value signals the solver to stop the search; negative value means no time limit */ double out_frq; /* output frequency, in seconds; this parameter specifies how frequently the solver sends information about the progress of the search to the standard output */ #if 0 /* 10/VI-2013 */ glp_long tm_beg; #else double tm_beg; #endif /* starting time of the search, in seconds; the total time of the search is the difference between xtime() and tm_beg */ #if 0 /* 10/VI-2013 */ glp_long tm_lag; #else double tm_lag; #endif /* the most recent time, in seconds, at which the progress of the the search was displayed */ }; #define ssx_create _glp_ssx_create #define ssx_factorize _glp_ssx_factorize #define ssx_get_xNj _glp_ssx_get_xNj #define ssx_eval_bbar _glp_ssx_eval_bbar #define ssx_eval_pi _glp_ssx_eval_pi #define ssx_eval_dj _glp_ssx_eval_dj #define ssx_eval_cbar _glp_ssx_eval_cbar #define ssx_eval_rho _glp_ssx_eval_rho #define ssx_eval_row _glp_ssx_eval_row #define ssx_eval_col _glp_ssx_eval_col #define ssx_chuzc _glp_ssx_chuzc #define ssx_chuzr _glp_ssx_chuzr #define ssx_update_bbar _glp_ssx_update_bbar #define ssx_update_pi _glp_ssx_update_pi #define ssx_update_cbar _glp_ssx_update_cbar #define ssx_change_basis _glp_ssx_change_basis #define ssx_delete _glp_ssx_delete #define ssx_phase_I _glp_ssx_phase_I #define ssx_phase_II _glp_ssx_phase_II #define ssx_driver _glp_ssx_driver SSX *ssx_create(int m, int n, int nnz); /* create simplex solver workspace */ int ssx_factorize(SSX *ssx); /* factorize the current basis matrix */ void ssx_get_xNj(SSX *ssx, int j, mpq_t x); /* determine value of non-basic variable */ void ssx_eval_bbar(SSX *ssx); /* compute values of basic variables */ void ssx_eval_pi(SSX *ssx); /* compute values of simplex multipliers */ void ssx_eval_dj(SSX *ssx, int j, mpq_t dj); /* compute reduced cost of non-basic variable */ void ssx_eval_cbar(SSX *ssx); /* compute reduced costs of all non-basic variables */ void ssx_eval_rho(SSX *ssx); /* compute p-th row of the inverse */ void ssx_eval_row(SSX *ssx); /* compute pivot row of the simplex table */ void ssx_eval_col(SSX *ssx); /* compute pivot column of the simplex table */ void ssx_chuzc(SSX *ssx); /* choose pivot column */ void ssx_chuzr(SSX *ssx); /* choose pivot row */ void ssx_update_bbar(SSX *ssx); /* update values of basic variables */ void ssx_update_pi(SSX *ssx); /* update simplex multipliers */ void ssx_update_cbar(SSX *ssx); /* update reduced costs of non-basic variables */ void ssx_change_basis(SSX *ssx); /* change current basis to adjacent one */ void ssx_delete(SSX *ssx); /* delete simplex solver workspace */ int ssx_phase_I(SSX *ssx); /* find primal feasible solution */ int ssx_phase_II(SSX *ssx); /* find optimal solution */ int ssx_driver(SSX *ssx); /* base driver to exact simplex method */ #endif /* eof */ glpk-4.52.1/src/glpssx01.c0000644000062000006210000006616512175147600014353 0ustar maomkpasswd/* glpssx01.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "glpssx.h" #define xfault xerror /*---------------------------------------------------------------------- // ssx_create - create simplex solver workspace. // // This routine creates the workspace used by simplex solver routines, // and returns a pointer to it. // // Parameters m, n, and nnz specify, respectively, the number of rows, // columns, and non-zero constraint coefficients. // // This routine only allocates the memory for the workspace components, // so the workspace needs to be saturated by data. */ SSX *ssx_create(int m, int n, int nnz) { SSX *ssx; int i, j, k; if (m < 1) xfault("ssx_create: m = %d; invalid number of rows\n", m); if (n < 1) xfault("ssx_create: n = %d; invalid number of columns\n", n); if (nnz < 0) xfault("ssx_create: nnz = %d; invalid number of non-zero const" "raint coefficients\n", nnz); ssx = xmalloc(sizeof(SSX)); ssx->m = m; ssx->n = n; ssx->type = xcalloc(1+m+n, sizeof(int)); ssx->lb = xcalloc(1+m+n, sizeof(mpq_t)); for (k = 1; k <= m+n; k++) mpq_init(ssx->lb[k]); ssx->ub = xcalloc(1+m+n, sizeof(mpq_t)); for (k = 1; k <= m+n; k++) mpq_init(ssx->ub[k]); ssx->coef = xcalloc(1+m+n, sizeof(mpq_t)); for (k = 0; k <= m+n; k++) mpq_init(ssx->coef[k]); ssx->A_ptr = xcalloc(1+n+1, sizeof(int)); ssx->A_ptr[n+1] = nnz+1; ssx->A_ind = xcalloc(1+nnz, sizeof(int)); ssx->A_val = xcalloc(1+nnz, sizeof(mpq_t)); for (k = 1; k <= nnz; k++) mpq_init(ssx->A_val[k]); ssx->stat = xcalloc(1+m+n, sizeof(int)); ssx->Q_row = xcalloc(1+m+n, sizeof(int)); ssx->Q_col = xcalloc(1+m+n, sizeof(int)); ssx->binv = bfx_create_binv(); ssx->bbar = xcalloc(1+m, sizeof(mpq_t)); for (i = 0; i <= m; i++) mpq_init(ssx->bbar[i]); ssx->pi = xcalloc(1+m, sizeof(mpq_t)); for (i = 1; i <= m; i++) mpq_init(ssx->pi[i]); ssx->cbar = xcalloc(1+n, sizeof(mpq_t)); for (j = 1; j <= n; j++) mpq_init(ssx->cbar[j]); ssx->rho = xcalloc(1+m, sizeof(mpq_t)); for (i = 1; i <= m; i++) mpq_init(ssx->rho[i]); ssx->ap = xcalloc(1+n, sizeof(mpq_t)); for (j = 1; j <= n; j++) mpq_init(ssx->ap[j]); ssx->aq = xcalloc(1+m, sizeof(mpq_t)); for (i = 1; i <= m; i++) mpq_init(ssx->aq[i]); mpq_init(ssx->delta); return ssx; } /*---------------------------------------------------------------------- // ssx_factorize - factorize the current basis matrix. // // This routine computes factorization of the current basis matrix B // and returns the singularity flag. If the matrix B is non-singular, // the flag is zero, otherwise non-zero. */ static int basis_col(void *info, int j, int ind[], mpq_t val[]) { /* this auxiliary routine provides row indices and numeric values of non-zero elements in j-th column of the matrix B */ SSX *ssx = info; int m = ssx->m; int n = ssx->n; int *A_ptr = ssx->A_ptr; int *A_ind = ssx->A_ind; mpq_t *A_val = ssx->A_val; int *Q_col = ssx->Q_col; int k, len, ptr; xassert(1 <= j && j <= m); k = Q_col[j]; /* x[k] = xB[j] */ xassert(1 <= k && k <= m+n); /* j-th column of the matrix B is k-th column of the augmented constraint matrix (I | -A) */ if (k <= m) { /* it is a column of the unity matrix I */ len = 1, ind[1] = k, mpq_set_si(val[1], 1, 1); } else { /* it is a column of the original constraint matrix -A */ len = 0; for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) { len++; ind[len] = A_ind[ptr]; mpq_neg(val[len], A_val[ptr]); } } return len; } int ssx_factorize(SSX *ssx) { int ret; ret = bfx_factorize(ssx->binv, ssx->m, basis_col, ssx); return ret; } /*---------------------------------------------------------------------- // ssx_get_xNj - determine value of non-basic variable. // // This routine determines the value of non-basic variable xN[j] in the // current basic solution defined as follows: // // 0, if xN[j] is free variable // lN[j], if xN[j] is on its lower bound // uN[j], if xN[j] is on its upper bound // lN[j] = uN[j], if xN[j] is fixed variable // // where lN[j] and uN[j] are lower and upper bounds of xN[j]. */ void ssx_get_xNj(SSX *ssx, int j, mpq_t x) { int m = ssx->m; int n = ssx->n; mpq_t *lb = ssx->lb; mpq_t *ub = ssx->ub; int *stat = ssx->stat; int *Q_col = ssx->Q_col; int k; xassert(1 <= j && j <= n); k = Q_col[m+j]; /* x[k] = xN[j] */ xassert(1 <= k && k <= m+n); switch (stat[k]) { case SSX_NL: /* xN[j] is on its lower bound */ mpq_set(x, lb[k]); break; case SSX_NU: /* xN[j] is on its upper bound */ mpq_set(x, ub[k]); break; case SSX_NF: /* xN[j] is free variable */ mpq_set_si(x, 0, 1); break; case SSX_NS: /* xN[j] is fixed variable */ mpq_set(x, lb[k]); break; default: xassert(stat != stat); } return; } /*---------------------------------------------------------------------- // ssx_eval_bbar - compute values of basic variables. // // This routine computes values of basic variables xB in the current // basic solution as follows: // // beta = - inv(B) * N * xN, // // where B is the basis matrix, N is the matrix of non-basic columns, // xN is a vector of current values of non-basic variables. */ void ssx_eval_bbar(SSX *ssx) { int m = ssx->m; int n = ssx->n; mpq_t *coef = ssx->coef; int *A_ptr = ssx->A_ptr; int *A_ind = ssx->A_ind; mpq_t *A_val = ssx->A_val; int *Q_col = ssx->Q_col; mpq_t *bbar = ssx->bbar; int i, j, k, ptr; mpq_t x, temp; mpq_init(x); mpq_init(temp); /* bbar := 0 */ for (i = 1; i <= m; i++) mpq_set_si(bbar[i], 0, 1); /* bbar := - N * xN = - N[1] * xN[1] - ... - N[n] * xN[n] */ for (j = 1; j <= n; j++) { ssx_get_xNj(ssx, j, x); if (mpq_sgn(x) == 0) continue; k = Q_col[m+j]; /* x[k] = xN[j] */ if (k <= m) { /* N[j] is a column of the unity matrix I */ mpq_sub(bbar[k], bbar[k], x); } else { /* N[j] is a column of the original constraint matrix -A */ for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) { mpq_mul(temp, A_val[ptr], x); mpq_add(bbar[A_ind[ptr]], bbar[A_ind[ptr]], temp); } } } /* bbar := inv(B) * bbar */ bfx_ftran(ssx->binv, bbar, 0); #if 1 /* compute value of the objective function */ /* bbar[0] := c[0] */ mpq_set(bbar[0], coef[0]); /* bbar[0] := bbar[0] + sum{i in B} cB[i] * xB[i] */ for (i = 1; i <= m; i++) { k = Q_col[i]; /* x[k] = xB[i] */ if (mpq_sgn(coef[k]) == 0) continue; mpq_mul(temp, coef[k], bbar[i]); mpq_add(bbar[0], bbar[0], temp); } /* bbar[0] := bbar[0] + sum{j in N} cN[j] * xN[j] */ for (j = 1; j <= n; j++) { k = Q_col[m+j]; /* x[k] = xN[j] */ if (mpq_sgn(coef[k]) == 0) continue; ssx_get_xNj(ssx, j, x); mpq_mul(temp, coef[k], x); mpq_add(bbar[0], bbar[0], temp); } #endif mpq_clear(x); mpq_clear(temp); return; } /*---------------------------------------------------------------------- // ssx_eval_pi - compute values of simplex multipliers. // // This routine computes values of simplex multipliers (shadow prices) // pi in the current basic solution as follows: // // pi = inv(B') * cB, // // where B' is a matrix transposed to the basis matrix B, cB is a vector // of objective coefficients at basic variables xB. */ void ssx_eval_pi(SSX *ssx) { int m = ssx->m; mpq_t *coef = ssx->coef; int *Q_col = ssx->Q_col; mpq_t *pi = ssx->pi; int i; /* pi := cB */ for (i = 1; i <= m; i++) mpq_set(pi[i], coef[Q_col[i]]); /* pi := inv(B') * cB */ bfx_btran(ssx->binv, pi); return; } /*---------------------------------------------------------------------- // ssx_eval_dj - compute reduced cost of non-basic variable. // // This routine computes reduced cost d[j] of non-basic variable xN[j] // in the current basic solution as follows: // // d[j] = cN[j] - N[j] * pi, // // where cN[j] is an objective coefficient at xN[j], N[j] is a column // of the augmented constraint matrix (I | -A) corresponding to xN[j], // pi is the vector of simplex multipliers (shadow prices). */ void ssx_eval_dj(SSX *ssx, int j, mpq_t dj) { int m = ssx->m; int n = ssx->n; mpq_t *coef = ssx->coef; int *A_ptr = ssx->A_ptr; int *A_ind = ssx->A_ind; mpq_t *A_val = ssx->A_val; int *Q_col = ssx->Q_col; mpq_t *pi = ssx->pi; int k, ptr, end; mpq_t temp; mpq_init(temp); xassert(1 <= j && j <= n); k = Q_col[m+j]; /* x[k] = xN[j] */ xassert(1 <= k && k <= m+n); /* j-th column of the matrix N is k-th column of the augmented constraint matrix (I | -A) */ if (k <= m) { /* it is a column of the unity matrix I */ mpq_sub(dj, coef[k], pi[k]); } else { /* it is a column of the original constraint matrix -A */ mpq_set(dj, coef[k]); for (ptr = A_ptr[k-m], end = A_ptr[k-m+1]; ptr < end; ptr++) { mpq_mul(temp, A_val[ptr], pi[A_ind[ptr]]); mpq_add(dj, dj, temp); } } mpq_clear(temp); return; } /*---------------------------------------------------------------------- // ssx_eval_cbar - compute reduced costs of all non-basic variables. // // This routine computes the vector of reduced costs pi in the current // basic solution for all non-basic variables, including fixed ones. */ void ssx_eval_cbar(SSX *ssx) { int n = ssx->n; mpq_t *cbar = ssx->cbar; int j; for (j = 1; j <= n; j++) ssx_eval_dj(ssx, j, cbar[j]); return; } /*---------------------------------------------------------------------- // ssx_eval_rho - compute p-th row of the inverse. // // This routine computes p-th row of the matrix inv(B), where B is the // current basis matrix. // // p-th row of the inverse is computed using the following formula: // // rho = inv(B') * e[p], // // where B' is a matrix transposed to B, e[p] is a unity vector, which // contains one in p-th position. */ void ssx_eval_rho(SSX *ssx) { int m = ssx->m; int p = ssx->p; mpq_t *rho = ssx->rho; int i; xassert(1 <= p && p <= m); /* rho := 0 */ for (i = 1; i <= m; i++) mpq_set_si(rho[i], 0, 1); /* rho := e[p] */ mpq_set_si(rho[p], 1, 1); /* rho := inv(B') * rho */ bfx_btran(ssx->binv, rho); return; } /*---------------------------------------------------------------------- // ssx_eval_row - compute pivot row of the simplex table. // // This routine computes p-th (pivot) row of the current simplex table // A~ = - inv(B) * N using the following formula: // // A~[p] = - N' * inv(B') * e[p] = - N' * rho[p], // // where N' is a matrix transposed to the matrix N, rho[p] is p-th row // of the inverse inv(B). */ void ssx_eval_row(SSX *ssx) { int m = ssx->m; int n = ssx->n; int *A_ptr = ssx->A_ptr; int *A_ind = ssx->A_ind; mpq_t *A_val = ssx->A_val; int *Q_col = ssx->Q_col; mpq_t *rho = ssx->rho; mpq_t *ap = ssx->ap; int j, k, ptr; mpq_t temp; mpq_init(temp); for (j = 1; j <= n; j++) { /* ap[j] := - N'[j] * rho (inner product) */ k = Q_col[m+j]; /* x[k] = xN[j] */ if (k <= m) mpq_neg(ap[j], rho[k]); else { mpq_set_si(ap[j], 0, 1); for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) { mpq_mul(temp, A_val[ptr], rho[A_ind[ptr]]); mpq_add(ap[j], ap[j], temp); } } } mpq_clear(temp); return; } /*---------------------------------------------------------------------- // ssx_eval_col - compute pivot column of the simplex table. // // This routine computes q-th (pivot) column of the current simplex // table A~ = - inv(B) * N using the following formula: // // A~[q] = - inv(B) * N[q], // // where N[q] is q-th column of the matrix N corresponding to chosen // non-basic variable xN[q]. */ void ssx_eval_col(SSX *ssx) { int m = ssx->m; int n = ssx->n; int *A_ptr = ssx->A_ptr; int *A_ind = ssx->A_ind; mpq_t *A_val = ssx->A_val; int *Q_col = ssx->Q_col; int q = ssx->q; mpq_t *aq = ssx->aq; int i, k, ptr; xassert(1 <= q && q <= n); /* aq := 0 */ for (i = 1; i <= m; i++) mpq_set_si(aq[i], 0, 1); /* aq := N[q] */ k = Q_col[m+q]; /* x[k] = xN[q] */ if (k <= m) { /* N[q] is a column of the unity matrix I */ mpq_set_si(aq[k], 1, 1); } else { /* N[q] is a column of the original constraint matrix -A */ for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) mpq_neg(aq[A_ind[ptr]], A_val[ptr]); } /* aq := inv(B) * aq */ bfx_ftran(ssx->binv, aq, 1); /* aq := - aq */ for (i = 1; i <= m; i++) mpq_neg(aq[i], aq[i]); return; } /*---------------------------------------------------------------------- // ssx_chuzc - choose pivot column. // // This routine chooses non-basic variable xN[q] whose reduced cost // indicates possible improving of the objective function to enter it // in the basis. // // Currently the standard (textbook) pricing is used, i.e. that // non-basic variable is preferred which has greatest reduced cost (in // magnitude). // // If xN[q] has been chosen, the routine stores its number q and also // sets the flag q_dir that indicates direction in which xN[q] has to // change (+1 means increasing, -1 means decreasing). // // If the choice cannot be made, because the current basic solution is // dual feasible, the routine sets the number q to 0. */ void ssx_chuzc(SSX *ssx) { int m = ssx->m; int n = ssx->n; int dir = (ssx->dir == SSX_MIN ? +1 : -1); int *Q_col = ssx->Q_col; int *stat = ssx->stat; mpq_t *cbar = ssx->cbar; int j, k, s, q, q_dir; double best, temp; /* nothing is chosen so far */ q = 0, q_dir = 0, best = 0.0; /* look through the list of non-basic variables */ for (j = 1; j <= n; j++) { k = Q_col[m+j]; /* x[k] = xN[j] */ s = dir * mpq_sgn(cbar[j]); if ((stat[k] == SSX_NF || stat[k] == SSX_NL) && s < 0 || (stat[k] == SSX_NF || stat[k] == SSX_NU) && s > 0) { /* reduced cost of xN[j] indicates possible improving of the objective function */ temp = fabs(mpq_get_d(cbar[j])); xassert(temp != 0.0); if (q == 0 || best < temp) q = j, q_dir = - s, best = temp; } } ssx->q = q, ssx->q_dir = q_dir; return; } /*---------------------------------------------------------------------- // ssx_chuzr - choose pivot row. // // This routine looks through elements of q-th column of the simplex // table and chooses basic variable xB[p] which should leave the basis. // // The choice is based on the standard (textbook) ratio test. // // If xB[p] has been chosen, the routine stores its number p and also // sets its non-basic status p_stat which should be assigned to xB[p] // when it has left the basis and become xN[q]. // // Special case p < 0 means that xN[q] is double-bounded variable and // it reaches its opposite bound before any basic variable does that, // so the current basis remains unchanged. // // If the choice cannot be made, because xN[q] can infinitely change in // the feasible direction, the routine sets the number p to 0. */ void ssx_chuzr(SSX *ssx) { int m = ssx->m; int n = ssx->n; int *type = ssx->type; mpq_t *lb = ssx->lb; mpq_t *ub = ssx->ub; int *Q_col = ssx->Q_col; mpq_t *bbar = ssx->bbar; int q = ssx->q; mpq_t *aq = ssx->aq; int q_dir = ssx->q_dir; int i, k, s, t, p, p_stat; mpq_t teta, temp; mpq_init(teta); mpq_init(temp); xassert(1 <= q && q <= n); xassert(q_dir == +1 || q_dir == -1); /* nothing is chosen so far */ p = 0, p_stat = 0; /* look through the list of basic variables */ for (i = 1; i <= m; i++) { s = q_dir * mpq_sgn(aq[i]); if (s < 0) { /* xB[i] decreases */ k = Q_col[i]; /* x[k] = xB[i] */ t = type[k]; if (t == SSX_LO || t == SSX_DB || t == SSX_FX) { /* xB[i] has finite lower bound */ mpq_sub(temp, bbar[i], lb[k]); mpq_div(temp, temp, aq[i]); mpq_abs(temp, temp); if (p == 0 || mpq_cmp(teta, temp) > 0) { p = i; p_stat = (t == SSX_FX ? SSX_NS : SSX_NL); mpq_set(teta, temp); } } } else if (s > 0) { /* xB[i] increases */ k = Q_col[i]; /* x[k] = xB[i] */ t = type[k]; if (t == SSX_UP || t == SSX_DB || t == SSX_FX) { /* xB[i] has finite upper bound */ mpq_sub(temp, bbar[i], ub[k]); mpq_div(temp, temp, aq[i]); mpq_abs(temp, temp); if (p == 0 || mpq_cmp(teta, temp) > 0) { p = i; p_stat = (t == SSX_FX ? SSX_NS : SSX_NU); mpq_set(teta, temp); } } } /* if something has been chosen and the ratio test indicates exact degeneracy, the search can be finished */ if (p != 0 && mpq_sgn(teta) == 0) break; } /* if xN[q] is double-bounded, check if it can reach its opposite bound before any basic variable */ k = Q_col[m+q]; /* x[k] = xN[q] */ if (type[k] == SSX_DB) { mpq_sub(temp, ub[k], lb[k]); if (p == 0 || mpq_cmp(teta, temp) > 0) { p = -1; p_stat = -1; mpq_set(teta, temp); } } ssx->p = p; ssx->p_stat = p_stat; /* if xB[p] has been chosen, determine its actual change in the adjacent basis (it has the same sign as q_dir) */ if (p != 0) { xassert(mpq_sgn(teta) >= 0); if (q_dir > 0) mpq_set(ssx->delta, teta); else mpq_neg(ssx->delta, teta); } mpq_clear(teta); mpq_clear(temp); return; } /*---------------------------------------------------------------------- // ssx_update_bbar - update values of basic variables. // // This routine recomputes the current values of basic variables for // the adjacent basis. // // The simplex table for the current basis is the following: // // xB[i] = sum{j in 1..n} alfa[i,j] * xN[q], i = 1,...,m // // therefore // // delta xB[i] = alfa[i,q] * delta xN[q], i = 1,...,m // // where delta xN[q] = xN.new[q] - xN[q] is the change of xN[q] in the // adjacent basis, and delta xB[i] = xB.new[i] - xB[i] is the change of // xB[i]. This gives formulae for recomputing values of xB[i]: // // xB.new[p] = xN[q] + delta xN[q] // // (because xN[q] becomes xB[p] in the adjacent basis), and // // xB.new[i] = xB[i] + alfa[i,q] * delta xN[q], i != p // // for other basic variables. */ void ssx_update_bbar(SSX *ssx) { int m = ssx->m; int n = ssx->n; mpq_t *bbar = ssx->bbar; mpq_t *cbar = ssx->cbar; int p = ssx->p; int q = ssx->q; mpq_t *aq = ssx->aq; int i; mpq_t temp; mpq_init(temp); xassert(1 <= q && q <= n); if (p < 0) { /* xN[q] is double-bounded and goes to its opposite bound */ /* nop */; } else { /* xN[q] becomes xB[p] in the adjacent basis */ /* xB.new[p] = xN[q] + delta xN[q] */ xassert(1 <= p && p <= m); ssx_get_xNj(ssx, q, temp); mpq_add(bbar[p], temp, ssx->delta); } /* update values of other basic variables depending on xN[q] */ for (i = 1; i <= m; i++) { if (i == p) continue; /* xB.new[i] = xB[i] + alfa[i,q] * delta xN[q] */ if (mpq_sgn(aq[i]) == 0) continue; mpq_mul(temp, aq[i], ssx->delta); mpq_add(bbar[i], bbar[i], temp); } #if 1 /* update value of the objective function */ /* z.new = z + d[q] * delta xN[q] */ mpq_mul(temp, cbar[q], ssx->delta); mpq_add(bbar[0], bbar[0], temp); #endif mpq_clear(temp); return; } /*---------------------------------------------------------------------- -- ssx_update_pi - update simplex multipliers. -- -- This routine recomputes the vector of simplex multipliers for the -- adjacent basis. */ void ssx_update_pi(SSX *ssx) { int m = ssx->m; int n = ssx->n; mpq_t *pi = ssx->pi; mpq_t *cbar = ssx->cbar; int p = ssx->p; int q = ssx->q; mpq_t *aq = ssx->aq; mpq_t *rho = ssx->rho; int i; mpq_t new_dq, temp; mpq_init(new_dq); mpq_init(temp); xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); /* compute d[q] in the adjacent basis */ mpq_div(new_dq, cbar[q], aq[p]); /* update the vector of simplex multipliers */ for (i = 1; i <= m; i++) { if (mpq_sgn(rho[i]) == 0) continue; mpq_mul(temp, new_dq, rho[i]); mpq_sub(pi[i], pi[i], temp); } mpq_clear(new_dq); mpq_clear(temp); return; } /*---------------------------------------------------------------------- // ssx_update_cbar - update reduced costs of non-basic variables. // // This routine recomputes the vector of reduced costs of non-basic // variables for the adjacent basis. */ void ssx_update_cbar(SSX *ssx) { int m = ssx->m; int n = ssx->n; mpq_t *cbar = ssx->cbar; int p = ssx->p; int q = ssx->q; mpq_t *ap = ssx->ap; int j; mpq_t temp; mpq_init(temp); xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); /* compute d[q] in the adjacent basis */ /* d.new[q] = d[q] / alfa[p,q] */ mpq_div(cbar[q], cbar[q], ap[q]); /* update reduced costs of other non-basic variables */ for (j = 1; j <= n; j++) { if (j == q) continue; /* d.new[j] = d[j] - (alfa[p,j] / alfa[p,q]) * d[q] */ if (mpq_sgn(ap[j]) == 0) continue; mpq_mul(temp, ap[j], cbar[q]); mpq_sub(cbar[j], cbar[j], temp); } mpq_clear(temp); return; } /*---------------------------------------------------------------------- // ssx_change_basis - change current basis to adjacent one. // // This routine changes the current basis to the adjacent one swapping // basic variable xB[p] and non-basic variable xN[q]. */ void ssx_change_basis(SSX *ssx) { int m = ssx->m; int n = ssx->n; int *type = ssx->type; int *stat = ssx->stat; int *Q_row = ssx->Q_row; int *Q_col = ssx->Q_col; int p = ssx->p; int q = ssx->q; int p_stat = ssx->p_stat; int k, kp, kq; if (p < 0) { /* special case: xN[q] goes to its opposite bound */ xassert(1 <= q && q <= n); k = Q_col[m+q]; /* x[k] = xN[q] */ xassert(type[k] == SSX_DB); switch (stat[k]) { case SSX_NL: stat[k] = SSX_NU; break; case SSX_NU: stat[k] = SSX_NL; break; default: xassert(stat != stat); } } else { /* xB[p] leaves the basis, xN[q] enters the basis */ xassert(1 <= p && p <= m); xassert(1 <= q && q <= n); kp = Q_col[p]; /* x[kp] = xB[p] */ kq = Q_col[m+q]; /* x[kq] = xN[q] */ /* check non-basic status of xB[p] which becomes xN[q] */ switch (type[kp]) { case SSX_FR: xassert(p_stat == SSX_NF); break; case SSX_LO: xassert(p_stat == SSX_NL); break; case SSX_UP: xassert(p_stat == SSX_NU); break; case SSX_DB: xassert(p_stat == SSX_NL || p_stat == SSX_NU); break; case SSX_FX: xassert(p_stat == SSX_NS); break; default: xassert(type != type); } /* swap xB[p] and xN[q] */ stat[kp] = (char)p_stat, stat[kq] = SSX_BS; Q_row[kp] = m+q, Q_row[kq] = p; Q_col[p] = kq, Q_col[m+q] = kp; /* update factorization of the basis matrix */ if (bfx_update(ssx->binv, p)) { if (ssx_factorize(ssx)) xassert(("Internal error: basis matrix is singular", 0)); } } return; } /*---------------------------------------------------------------------- // ssx_delete - delete simplex solver workspace. // // This routine deletes the simplex solver workspace freeing all the // memory allocated to this object. */ void ssx_delete(SSX *ssx) { int m = ssx->m; int n = ssx->n; int nnz = ssx->A_ptr[n+1]-1; int i, j, k; xfree(ssx->type); for (k = 1; k <= m+n; k++) mpq_clear(ssx->lb[k]); xfree(ssx->lb); for (k = 1; k <= m+n; k++) mpq_clear(ssx->ub[k]); xfree(ssx->ub); for (k = 0; k <= m+n; k++) mpq_clear(ssx->coef[k]); xfree(ssx->coef); xfree(ssx->A_ptr); xfree(ssx->A_ind); for (k = 1; k <= nnz; k++) mpq_clear(ssx->A_val[k]); xfree(ssx->A_val); xfree(ssx->stat); xfree(ssx->Q_row); xfree(ssx->Q_col); bfx_delete_binv(ssx->binv); for (i = 0; i <= m; i++) mpq_clear(ssx->bbar[i]); xfree(ssx->bbar); for (i = 1; i <= m; i++) mpq_clear(ssx->pi[i]); xfree(ssx->pi); for (j = 1; j <= n; j++) mpq_clear(ssx->cbar[j]); xfree(ssx->cbar); for (i = 1; i <= m; i++) mpq_clear(ssx->rho[i]); xfree(ssx->rho); for (j = 1; j <= n; j++) mpq_clear(ssx->ap[j]); xfree(ssx->ap); for (i = 1; i <= m; i++) mpq_clear(ssx->aq[i]); xfree(ssx->aq); mpq_clear(ssx->delta); xfree(ssx); return; } /* eof */ glpk-4.52.1/src/glpssx02.c0000644000062000006210000004071412175147600014344 0ustar maomkpasswd/* glpssx02.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "glpssx.h" static void show_progress(SSX *ssx, int phase) { /* this auxiliary routine displays information about progress of the search */ int i, def = 0; for (i = 1; i <= ssx->m; i++) if (ssx->type[ssx->Q_col[i]] == SSX_FX) def++; xprintf("%s%6d: %s = %22.15g (%d)\n", phase == 1 ? " " : "*", ssx->it_cnt, phase == 1 ? "infsum" : "objval", mpq_get_d(ssx->bbar[0]), def); #if 0 ssx->tm_lag = utime(); #else ssx->tm_lag = xtime(); #endif return; } /*---------------------------------------------------------------------- // ssx_phase_I - find primal feasible solution. // // This routine implements phase I of the primal simplex method. // // On exit the routine returns one of the following codes: // // 0 - feasible solution found; // 1 - problem has no feasible solution; // 2 - iterations limit exceeded; // 3 - time limit exceeded. ----------------------------------------------------------------------*/ int ssx_phase_I(SSX *ssx) { int m = ssx->m; int n = ssx->n; int *type = ssx->type; mpq_t *lb = ssx->lb; mpq_t *ub = ssx->ub; mpq_t *coef = ssx->coef; int *A_ptr = ssx->A_ptr; int *A_ind = ssx->A_ind; mpq_t *A_val = ssx->A_val; int *Q_col = ssx->Q_col; mpq_t *bbar = ssx->bbar; mpq_t *pi = ssx->pi; mpq_t *cbar = ssx->cbar; int *orig_type, orig_dir; mpq_t *orig_lb, *orig_ub, *orig_coef; int i, k, ret; /* save components of the original LP problem, which are changed by the routine */ orig_type = xcalloc(1+m+n, sizeof(int)); orig_lb = xcalloc(1+m+n, sizeof(mpq_t)); orig_ub = xcalloc(1+m+n, sizeof(mpq_t)); orig_coef = xcalloc(1+m+n, sizeof(mpq_t)); for (k = 1; k <= m+n; k++) { orig_type[k] = type[k]; mpq_init(orig_lb[k]); mpq_set(orig_lb[k], lb[k]); mpq_init(orig_ub[k]); mpq_set(orig_ub[k], ub[k]); } orig_dir = ssx->dir; for (k = 0; k <= m+n; k++) { mpq_init(orig_coef[k]); mpq_set(orig_coef[k], coef[k]); } /* build an artificial basic solution, which is primal feasible, and also build an auxiliary objective function to minimize the sum of infeasibilities for the original problem */ ssx->dir = SSX_MIN; for (k = 0; k <= m+n; k++) mpq_set_si(coef[k], 0, 1); mpq_set_si(bbar[0], 0, 1); for (i = 1; i <= m; i++) { int t; k = Q_col[i]; /* x[k] = xB[i] */ t = type[k]; if (t == SSX_LO || t == SSX_DB || t == SSX_FX) { /* in the original problem x[k] has lower bound */ if (mpq_cmp(bbar[i], lb[k]) < 0) { /* which is violated */ type[k] = SSX_UP; mpq_set(ub[k], lb[k]); mpq_set_si(lb[k], 0, 1); mpq_set_si(coef[k], -1, 1); mpq_add(bbar[0], bbar[0], ub[k]); mpq_sub(bbar[0], bbar[0], bbar[i]); } } if (t == SSX_UP || t == SSX_DB || t == SSX_FX) { /* in the original problem x[k] has upper bound */ if (mpq_cmp(bbar[i], ub[k]) > 0) { /* which is violated */ type[k] = SSX_LO; mpq_set(lb[k], ub[k]); mpq_set_si(ub[k], 0, 1); mpq_set_si(coef[k], +1, 1); mpq_add(bbar[0], bbar[0], bbar[i]); mpq_sub(bbar[0], bbar[0], lb[k]); } } } /* now the initial basic solution should be primal feasible due to changes of bounds of some basic variables, which turned to implicit artifical variables */ /* compute simplex multipliers and reduced costs */ ssx_eval_pi(ssx); ssx_eval_cbar(ssx); /* display initial progress of the search */ show_progress(ssx, 1); /* main loop starts here */ for (;;) { /* display current progress of the search */ #if 0 if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001) #else if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001) #endif show_progress(ssx, 1); /* we do not need to wait until all artificial variables have left the basis */ if (mpq_sgn(bbar[0]) == 0) { /* the sum of infeasibilities is zero, therefore the current solution is primal feasible for the original problem */ ret = 0; break; } /* check if the iterations limit has been exhausted */ if (ssx->it_lim == 0) { ret = 2; break; } /* check if the time limit has been exhausted */ #if 0 if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg) #else if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg)) #endif { ret = 3; break; } /* choose non-basic variable xN[q] */ ssx_chuzc(ssx); /* if xN[q] cannot be chosen, the sum of infeasibilities is minimal but non-zero; therefore the original problem has no primal feasible solution */ if (ssx->q == 0) { ret = 1; break; } /* compute q-th column of the simplex table */ ssx_eval_col(ssx); /* choose basic variable xB[p] */ ssx_chuzr(ssx); /* the sum of infeasibilities cannot be negative, therefore the auxiliary lp problem cannot have unbounded solution */ xassert(ssx->p != 0); /* update values of basic variables */ ssx_update_bbar(ssx); if (ssx->p > 0) { /* compute p-th row of the inverse inv(B) */ ssx_eval_rho(ssx); /* compute p-th row of the simplex table */ ssx_eval_row(ssx); xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0); /* update simplex multipliers */ ssx_update_pi(ssx); /* update reduced costs of non-basic variables */ ssx_update_cbar(ssx); } /* xB[p] is leaving the basis; if it is implicit artificial variable, the corresponding residual vanishes; therefore bounds of this variable should be restored to the original values */ if (ssx->p > 0) { k = Q_col[ssx->p]; /* x[k] = xB[p] */ if (type[k] != orig_type[k]) { /* x[k] is implicit artificial variable */ type[k] = orig_type[k]; mpq_set(lb[k], orig_lb[k]); mpq_set(ub[k], orig_ub[k]); xassert(ssx->p_stat == SSX_NL || ssx->p_stat == SSX_NU); ssx->p_stat = (ssx->p_stat == SSX_NL ? SSX_NU : SSX_NL); if (type[k] == SSX_FX) ssx->p_stat = SSX_NS; /* nullify the objective coefficient at x[k] */ mpq_set_si(coef[k], 0, 1); /* since coef[k] has been changed, we need to compute new reduced cost of x[k], which it will have in the adjacent basis */ /* the formula d[j] = cN[j] - pi' * N[j] is used (note that the vector pi is not changed, because it depends on objective coefficients at basic variables, but in the adjacent basis, for which the vector pi has been just recomputed, x[k] is non-basic) */ if (k <= m) { /* x[k] is auxiliary variable */ mpq_neg(cbar[ssx->q], pi[k]); } else { /* x[k] is structural variable */ int ptr; mpq_t temp; mpq_init(temp); mpq_set_si(cbar[ssx->q], 0, 1); for (ptr = A_ptr[k-m]; ptr < A_ptr[k-m+1]; ptr++) { mpq_mul(temp, pi[A_ind[ptr]], A_val[ptr]); mpq_add(cbar[ssx->q], cbar[ssx->q], temp); } mpq_clear(temp); } } } /* jump to the adjacent vertex of the polyhedron */ ssx_change_basis(ssx); /* one simplex iteration has been performed */ if (ssx->it_lim > 0) ssx->it_lim--; ssx->it_cnt++; } /* display final progress of the search */ show_progress(ssx, 1); /* restore components of the original problem, which were changed by the routine */ for (k = 1; k <= m+n; k++) { type[k] = orig_type[k]; mpq_set(lb[k], orig_lb[k]); mpq_clear(orig_lb[k]); mpq_set(ub[k], orig_ub[k]); mpq_clear(orig_ub[k]); } ssx->dir = orig_dir; for (k = 0; k <= m+n; k++) { mpq_set(coef[k], orig_coef[k]); mpq_clear(orig_coef[k]); } xfree(orig_type); xfree(orig_lb); xfree(orig_ub); xfree(orig_coef); /* return to the calling program */ return ret; } /*---------------------------------------------------------------------- // ssx_phase_II - find optimal solution. // // This routine implements phase II of the primal simplex method. // // On exit the routine returns one of the following codes: // // 0 - optimal solution found; // 1 - problem has unbounded solution; // 2 - iterations limit exceeded; // 3 - time limit exceeded. ----------------------------------------------------------------------*/ int ssx_phase_II(SSX *ssx) { int ret; /* display initial progress of the search */ show_progress(ssx, 2); /* main loop starts here */ for (;;) { /* display current progress of the search */ #if 0 if (utime() - ssx->tm_lag >= ssx->out_frq - 0.001) #else if (xdifftime(xtime(), ssx->tm_lag) >= ssx->out_frq - 0.001) #endif show_progress(ssx, 2); /* check if the iterations limit has been exhausted */ if (ssx->it_lim == 0) { ret = 2; break; } /* check if the time limit has been exhausted */ #if 0 if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= utime() - ssx->tm_beg) #else if (ssx->tm_lim >= 0.0 && ssx->tm_lim <= xdifftime(xtime(), ssx->tm_beg)) #endif { ret = 3; break; } /* choose non-basic variable xN[q] */ ssx_chuzc(ssx); /* if xN[q] cannot be chosen, the current basic solution is dual feasible and therefore optimal */ if (ssx->q == 0) { ret = 0; break; } /* compute q-th column of the simplex table */ ssx_eval_col(ssx); /* choose basic variable xB[p] */ ssx_chuzr(ssx); /* if xB[p] cannot be chosen, the problem has no dual feasible solution (i.e. unbounded) */ if (ssx->p == 0) { ret = 1; break; } /* update values of basic variables */ ssx_update_bbar(ssx); if (ssx->p > 0) { /* compute p-th row of the inverse inv(B) */ ssx_eval_rho(ssx); /* compute p-th row of the simplex table */ ssx_eval_row(ssx); xassert(mpq_cmp(ssx->aq[ssx->p], ssx->ap[ssx->q]) == 0); #if 0 /* update simplex multipliers */ ssx_update_pi(ssx); #endif /* update reduced costs of non-basic variables */ ssx_update_cbar(ssx); } /* jump to the adjacent vertex of the polyhedron */ ssx_change_basis(ssx); /* one simplex iteration has been performed */ if (ssx->it_lim > 0) ssx->it_lim--; ssx->it_cnt++; } /* display final progress of the search */ show_progress(ssx, 2); /* return to the calling program */ return ret; } /*---------------------------------------------------------------------- // ssx_driver - base driver to exact simplex method. // // This routine is a base driver to a version of the primal simplex // method using exact (bignum) arithmetic. // // On exit the routine returns one of the following codes: // // 0 - optimal solution found; // 1 - problem has no feasible solution; // 2 - problem has unbounded solution; // 3 - iterations limit exceeded (phase I); // 4 - iterations limit exceeded (phase II); // 5 - time limit exceeded (phase I); // 6 - time limit exceeded (phase II); // 7 - initial basis matrix is exactly singular. ----------------------------------------------------------------------*/ int ssx_driver(SSX *ssx) { int m = ssx->m; int *type = ssx->type; mpq_t *lb = ssx->lb; mpq_t *ub = ssx->ub; int *Q_col = ssx->Q_col; mpq_t *bbar = ssx->bbar; int i, k, ret; ssx->tm_beg = xtime(); /* factorize the initial basis matrix */ if (ssx_factorize(ssx)) { xprintf("Initial basis matrix is singular\n"); ret = 7; goto done; } /* compute values of basic variables */ ssx_eval_bbar(ssx); /* check if the initial basic solution is primal feasible */ for (i = 1; i <= m; i++) { int t; k = Q_col[i]; /* x[k] = xB[i] */ t = type[k]; if (t == SSX_LO || t == SSX_DB || t == SSX_FX) { /* x[k] has lower bound */ if (mpq_cmp(bbar[i], lb[k]) < 0) { /* which is violated */ break; } } if (t == SSX_UP || t == SSX_DB || t == SSX_FX) { /* x[k] has upper bound */ if (mpq_cmp(bbar[i], ub[k]) > 0) { /* which is violated */ break; } } } if (i > m) { /* no basic variable violates its bounds */ ret = 0; goto skip; } /* phase I: find primal feasible solution */ ret = ssx_phase_I(ssx); switch (ret) { case 0: ret = 0; break; case 1: xprintf("PROBLEM HAS NO FEASIBLE SOLUTION\n"); ret = 1; break; case 2: xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n"); ret = 3; break; case 3: xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); ret = 5; break; default: xassert(ret != ret); } /* compute values of basic variables (actually only the objective value needs to be computed) */ ssx_eval_bbar(ssx); skip: /* compute simplex multipliers */ ssx_eval_pi(ssx); /* compute reduced costs of non-basic variables */ ssx_eval_cbar(ssx); /* if phase I failed, do not start phase II */ if (ret != 0) goto done; /* phase II: find optimal solution */ ret = ssx_phase_II(ssx); switch (ret) { case 0: xprintf("OPTIMAL SOLUTION FOUND\n"); ret = 0; break; case 1: xprintf("PROBLEM HAS UNBOUNDED SOLUTION\n"); ret = 2; break; case 2: xprintf("ITERATIONS LIMIT EXCEEDED; SEARCH TERMINATED\n"); ret = 4; break; case 3: xprintf("TIME LIMIT EXCEEDED; SEARCH TERMINATED\n"); ret = 6; break; default: xassert(ret != ret); } done: /* decrease the time limit by the spent amount of time */ if (ssx->tm_lim >= 0.0) #if 0 { ssx->tm_lim -= utime() - ssx->tm_beg; #else { ssx->tm_lim -= xdifftime(xtime(), ssx->tm_beg); #endif if (ssx->tm_lim < 0.0) ssx->tm_lim = 0.0; } return ret; } /* eof */ glpk-4.52.1/src/glptsp.c0000644000062000006210000005712512175147600014177 0ustar maomkpasswd/* glptsp.c */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define _GLPSTD_ERRNO #define _GLPSTD_STDIO #include "env.h" #include "glplib.h" #include "glptsp.h" #define xfault xerror /*---------------------------------------------------------------------- -- tsp_read_data - read TSP instance data. -- -- *Synopsis* -- -- #include "glptsp.h" -- TSP *tsp_read_data(char *fname); -- -- *Description* -- -- The routine tsp_read_data reads a TSP (or related problem) instance -- data from the text file, whose name is the character string fname. -- -- For detailed description of the format recognized by the routine see -- the report: G.Reinelt, TSPLIB 95. -- -- *Returns* -- -- If no error occurred, the routine tsp_read_data returns a pointer to -- the TSP instance data block, which contains loaded data. In the case -- of error the routine prints an error message and returns NULL. */ struct dsa { /* dynamic storage area used by the routine tsp_read_data */ char *fname; /* name of the input text file */ FILE *fp; /* stream assigned to the input text file */ int seqn; /* line sequential number */ int c; /* current character */ char token[255+1]; /* current token */ }; static int get_char(struct dsa *dsa) { dsa->c = fgetc(dsa->fp); if (ferror(dsa->fp)) { xprintf("%s:%d: read error - %s\n", dsa->fname, dsa->seqn, strerror(errno)); return 1; } if (feof(dsa->fp)) dsa->c = EOF; else if (dsa->c == '\n') dsa->seqn++; else if (isspace(dsa->c)) dsa->c = ' '; else if (iscntrl(dsa->c)) { xprintf("%s:%d: invalid control character 0x%02X\n", dsa->fname, dsa->seqn, dsa->c); return 1; } return 0; } static int skip_spaces(struct dsa *dsa, int across) { while (dsa->c == ' ' || (across && dsa->c == '\n')) if (get_char(dsa)) return 1; return 0; } static int scan_keyword(struct dsa *dsa) { int len = 0; if (skip_spaces(dsa, 0)) return 1; dsa->token[0] = '\0'; while (isalnum(dsa->c) || dsa->c == '_') { if (len == 31) { xprintf("%s:%d: keyword `%s...' too long\n", dsa->fname, dsa->seqn, dsa->token); return 1; } dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; if (get_char(dsa)) return 1; } if (len == 0) { xprintf("%s:%d: missing keyword\n", dsa->fname, dsa->seqn); return 1; } return 0; } static int check_colon(struct dsa *dsa) { if (skip_spaces(dsa, 0)) return 1; if (dsa->c != ':') { xprintf("%s:%d: missing colon after `%s'\n", dsa->fname, dsa->seqn, dsa->token); return 1; } if (get_char(dsa)) return 1; return 0; } static int scan_token(struct dsa *dsa, int across) { int len = 0; if (skip_spaces(dsa, across)) return 1; dsa->token[0] = '\0'; while (!(dsa->c == EOF || dsa->c == '\n' || dsa->c == ' ')) { if (len == 255) { dsa->token[31] = '\0'; xprintf("%s:%d: token `%s...' too long\n", dsa->fname, dsa->seqn, dsa->token); return 1; } dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; if (get_char(dsa)) return 1; } return 0; } static int check_newline(struct dsa *dsa) { if (skip_spaces(dsa, 0)) return 1; if (!(dsa->c == EOF || dsa->c == '\n')) { xprintf("%s:%d: extra symbols detected\n", dsa->fname, dsa->seqn); return 1; } if (get_char(dsa)) return 1; return 0; } static int scan_comment(struct dsa *dsa) { int len = 0; if (skip_spaces(dsa, 0)) return 1; dsa->token[0] = '\0'; while (!(dsa->c == EOF || dsa->c == '\n')) { if (len == 255) { xprintf("%s:%d: comment too long\n", dsa->fname, dsa->seqn) ; return 1; } dsa->token[len++] = (char)dsa->c, dsa->token[len] = '\0'; if (get_char(dsa)) return 1; } return 0; } static int scan_integer(struct dsa *dsa, int across, int *val) { if (scan_token(dsa, across)) return 1; if (strlen(dsa->token) == 0) { xprintf("%s:%d: missing integer\n", dsa->fname, dsa->seqn); return 1; } if (str2int(dsa->token, val)) { xprintf("%s:%d: integer `%s' invalid\n", dsa->fname, dsa->seqn , dsa->token); return 1; } return 0; } static int scan_number(struct dsa *dsa, int across, double *val) { if (scan_token(dsa, across)) return 1; if (strlen(dsa->token) == 0) { xprintf("%s:%d: missing number\n", dsa->fname, dsa->seqn); return 1; } if (str2num(dsa->token, val)) { xprintf("%s:%d: number `%s' invalid\n", dsa->fname, dsa->seqn, dsa->token); return 1; } return 0; } TSP *tsp_read_data(char *fname) { struct dsa _dsa, *dsa = &_dsa; TSP *tsp = NULL; dsa->fname = fname; xprintf("tsp_read_data: reading TSP data from `%s'...\n", dsa->fname); dsa->fp = fopen(dsa->fname, "r"); if (dsa->fp == NULL) { xprintf("tsp_read_data: unable to open `%s' - %s\n", dsa->fname, strerror(errno)); goto fail; } tsp = xmalloc(sizeof(TSP)); tsp->name = NULL; tsp->type = TSP_UNDEF; tsp->comment = NULL; tsp->dimension = 0; tsp->edge_weight_type = TSP_UNDEF; tsp->edge_weight_format = TSP_UNDEF; tsp->display_data_type = TSP_UNDEF; tsp->node_x_coord = NULL; tsp->node_y_coord = NULL; tsp->dply_x_coord = NULL; tsp->dply_y_coord = NULL; tsp->tour = NULL; tsp->edge_weight = NULL; dsa->seqn = 1; if (get_char(dsa)) goto fail; loop: if (scan_keyword(dsa)) goto fail; if (strcmp(dsa->token, "NAME") == 0) { if (tsp->name != NULL) { xprintf("%s:%d: NAME entry multiply defined\n", dsa->fname, dsa->seqn); goto fail; } if (check_colon(dsa)) goto fail; if (scan_token(dsa, 0)) goto fail; if (strlen(dsa->token) == 0) { xprintf("%s:%d: NAME entry incomplete\n", dsa->fname, dsa->seqn); goto fail; } tsp->name = xmalloc(strlen(dsa->token) + 1); strcpy(tsp->name, dsa->token); xprintf("tsp_read_data: NAME: %s\n", tsp->name); if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "TYPE") == 0) { if (tsp->type != TSP_UNDEF) { xprintf("%s:%d: TYPE entry multiply defined\n", dsa->fname, dsa->seqn); goto fail; } if (check_colon(dsa)) goto fail; if (scan_keyword(dsa)) goto fail; if (strcmp(dsa->token, "TSP") == 0) tsp->type = TSP_TSP; else if (strcmp(dsa->token, "ATSP") == 0) tsp->type = TSP_ATSP; else if (strcmp(dsa->token, "TOUR") == 0) tsp->type = TSP_TOUR; else { xprintf("%s:%d: data type `%s' not recognized\n", dsa->fname, dsa->seqn, dsa->token); goto fail; } xprintf("tsp_read_data: TYPE: %s\n", dsa->token); if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "COMMENT") == 0) { if (tsp->comment != NULL) { xprintf("%s:%d: COMMENT entry multiply defined\n", dsa->fname, dsa->seqn); goto fail; } if (check_colon(dsa)) goto fail; if (scan_comment(dsa)) goto fail; tsp->comment = xmalloc(strlen(dsa->token) + 1); strcpy(tsp->comment, dsa->token); xprintf("tsp_read_data: COMMENT: %s\n", tsp->comment); if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "DIMENSION") == 0) { if (tsp->dimension != 0) { xprintf("%s:%d: DIMENSION entry multiply defined\n", dsa->fname, dsa->seqn); goto fail; } if (check_colon(dsa)) goto fail; if (scan_integer(dsa, 0, &tsp->dimension)) goto fail; if (tsp->dimension < 1) { xprintf("%s:%d: invalid dimension\n", dsa->fname, dsa->seqn); goto fail; } xprintf("tsp_read_data: DIMENSION: %d\n", tsp->dimension); if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "EDGE_WEIGHT_TYPE") == 0) { if (tsp->edge_weight_type != TSP_UNDEF) { xprintf("%s:%d: EDGE_WEIGHT_TYPE entry multiply defined\n", dsa->fname, dsa->seqn); goto fail; } if (check_colon(dsa)) goto fail; if (scan_keyword(dsa)) goto fail; if (strcmp(dsa->token, "GEO") == 0) tsp->edge_weight_type = TSP_GEO; else if (strcmp(dsa->token, "EUC_2D") == 0) tsp->edge_weight_type = TSP_EUC_2D; else if (strcmp(dsa->token, "ATT") == 0) tsp->edge_weight_type = TSP_ATT; else if (strcmp(dsa->token, "EXPLICIT") == 0) tsp->edge_weight_type = TSP_EXPLICIT; else if (strcmp(dsa->token, "CEIL_2D") == 0) tsp->edge_weight_type = TSP_CEIL_2D; else { xprintf("%s:%d: edge weight type `%s' not recognized\n", dsa->fname, dsa->seqn, dsa->token); goto fail; } xprintf("tsp_read_data: EDGE_WEIGHT_TYPE: %s\n", dsa->token); if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "EDGE_WEIGHT_FORMAT") == 0) { if (tsp->edge_weight_format != TSP_UNDEF) { xprintf( "%s:%d: EDGE_WEIGHT_FORMAT entry multiply defined\n", dsa->fname, dsa->seqn); goto fail; } if (check_colon(dsa)) goto fail; if (scan_keyword(dsa)) goto fail; if (strcmp(dsa->token, "UPPER_ROW") == 0) tsp->edge_weight_format = TSP_UPPER_ROW; else if (strcmp(dsa->token, "FULL_MATRIX") == 0) tsp->edge_weight_format = TSP_FULL_MATRIX; else if (strcmp(dsa->token, "FUNCTION") == 0) tsp->edge_weight_format = TSP_FUNCTION; else if (strcmp(dsa->token, "LOWER_DIAG_ROW") == 0) tsp->edge_weight_format = TSP_LOWER_DIAG_ROW; else { xprintf("%s:%d: edge weight format `%s' not recognized\n", dsa->fname, dsa->seqn, dsa->token); goto fail; } xprintf("tsp_read_data: EDGE_WEIGHT_FORMAT: %s\n", dsa->token); if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "DISPLAY_DATA_TYPE") == 0) { if (tsp->display_data_type != TSP_UNDEF) { xprintf("%s:%d: DISPLAY_DATA_TYPE entry multiply defined\n", dsa->fname, dsa->seqn); goto fail; } if (check_colon(dsa)) goto fail; if (scan_keyword(dsa)) goto fail; if (strcmp(dsa->token, "COORD_DISPLAY") == 0) tsp->display_data_type = TSP_COORD_DISPLAY; else if (strcmp(dsa->token, "TWOD_DISPLAY") == 0) tsp->display_data_type = TSP_TWOD_DISPLAY; else { xprintf("%s:%d: display data type `%s' not recognized\n", dsa->fname, dsa->seqn, dsa->token); goto fail; } xprintf("tsp_read_data: DISPLAY_DATA_TYPE: %s\n", dsa->token); if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "NODE_COORD_SECTION") == 0) { int n = tsp->dimension, k, node; if (n == 0) { xprintf("%s:%d: DIMENSION entry not specified\n", dsa->fname, dsa->seqn); goto fail; } if (tsp->node_x_coord != NULL) { xprintf("%s:%d: NODE_COORD_SECTION multiply specified\n", dsa->fname, dsa->seqn); goto fail; } if (check_newline(dsa)) goto fail; tsp->node_x_coord = xcalloc(1+n, sizeof(double)); tsp->node_y_coord = xcalloc(1+n, sizeof(double)); for (node = 1; node <= n; node++) tsp->node_x_coord[node] = tsp->node_y_coord[node] = DBL_MAX; for (k = 1; k <= n; k++) { if (scan_integer(dsa, 0, &node)) goto fail; if (!(1 <= node && node <= n)) { xprintf("%s:%d: invalid node number %d\n", dsa->fname, dsa->seqn, node); goto fail; } if (tsp->node_x_coord[node] != DBL_MAX) { xprintf("%s:%d: node number %d multiply specified\n", dsa->fname, dsa->seqn, node); goto fail; } if (scan_number(dsa, 0, &tsp->node_x_coord[node])) goto fail; if (scan_number(dsa, 0, &tsp->node_y_coord[node])) goto fail; if (check_newline(dsa)) goto fail; } } else if (strcmp(dsa->token, "DISPLAY_DATA_SECTION") == 0) { int n = tsp->dimension, k, node; if (n == 0) { xprintf("%s:%d: DIMENSION entry not specified\n", dsa->fname, dsa->seqn); goto fail; } if (tsp->dply_x_coord != NULL) { xprintf("%s:%d: DISPLAY_DATA_SECTION multiply specified\n", dsa->fname, dsa->seqn); goto fail; } if (check_newline(dsa)) goto fail; tsp->dply_x_coord = xcalloc(1+n, sizeof(double)); tsp->dply_y_coord = xcalloc(1+n, sizeof(double)); for (node = 1; node <= n; node++) tsp->dply_x_coord[node] = tsp->dply_y_coord[node] = DBL_MAX; for (k = 1; k <= n; k++) { if (scan_integer(dsa, 0, &node)) goto fail; if (!(1 <= node && node <= n)) { xprintf("%s:%d: invalid node number %d\n", dsa->fname, dsa->seqn, node); goto fail; } if (tsp->dply_x_coord[node] != DBL_MAX) { xprintf("%s:%d: node number %d multiply specified\n", dsa->fname, dsa->seqn, node); goto fail; } if (scan_number(dsa, 0, &tsp->dply_x_coord[node])) goto fail; if (scan_number(dsa, 0, &tsp->dply_y_coord[node])) goto fail; if (check_newline(dsa)) goto fail; } } else if (strcmp(dsa->token, "TOUR_SECTION") == 0) { int n = tsp->dimension, k, node; if (n == 0) { xprintf("%s:%d: DIMENSION entry not specified\n", dsa->fname, dsa->seqn); goto fail; } if (tsp->tour != NULL) { xprintf("%s:%d: TOUR_SECTION multiply specified\n", dsa->fname, dsa->seqn); goto fail; } if (check_newline(dsa)) goto fail; tsp->tour = xcalloc(1+n, sizeof(int)); for (k = 1; k <= n; k++) { if (scan_integer(dsa, 1, &node)) goto fail; if (!(1 <= node && node <= n)) { xprintf("%s:%d: invalid node number %d\n", dsa->fname, dsa->seqn, node); goto fail; } tsp->tour[k] = node; } if (scan_integer(dsa, 1, &node)) goto fail; if (node != -1) { xprintf("%s:%d: extra node(s) detected\n", dsa->fname, dsa->seqn); goto fail; } if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "EDGE_WEIGHT_SECTION") == 0) { int n = tsp->dimension, i, j, temp; if (n == 0) { xprintf("%s:%d: DIMENSION entry not specified\n", dsa->fname, dsa->seqn); goto fail; } if (tsp->edge_weight_format == TSP_UNDEF) { xprintf("%s:%d: EDGE_WEIGHT_FORMAT entry not specified\n", dsa->fname, dsa->seqn); goto fail; } if (tsp->edge_weight != NULL) { xprintf("%s:%d: EDGE_WEIGHT_SECTION multiply specified\n", dsa->fname, dsa->seqn); goto fail; } if (check_newline(dsa)) goto fail; tsp->edge_weight = xcalloc(1+n*n, sizeof(int)); switch (tsp->edge_weight_format) { case TSP_FULL_MATRIX: for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { if (scan_integer(dsa, 1, &temp)) goto fail; tsp->edge_weight[(i - 1) * n + j] = temp; } } break; case TSP_UPPER_ROW: for (i = 1; i <= n; i++) { tsp->edge_weight[(i - 1) * n + i] = 0; for (j = i + 1; j <= n; j++) { if (scan_integer(dsa, 1, &temp)) goto fail; tsp->edge_weight[(i - 1) * n + j] = temp; tsp->edge_weight[(j - 1) * n + i] = temp; } } break; case TSP_LOWER_DIAG_ROW: for (i = 1; i <= n; i++) { for (j = 1; j <= i; j++) { if (scan_integer(dsa, 1, &temp)) goto fail; tsp->edge_weight[(i - 1) * n + j] = temp; tsp->edge_weight[(j - 1) * n + i] = temp; } } break; default: goto fail; } if (check_newline(dsa)) goto fail; } else if (strcmp(dsa->token, "EOF") == 0) { if (check_newline(dsa)) goto fail; goto done; } else { xprintf("%s:%d: keyword `%s' not recognized\n", dsa->fname, dsa->seqn, dsa->token); goto fail; } goto loop; done: xprintf("tsp_read_data: %d lines were read\n", dsa->seqn-1); fclose(dsa->fp); return tsp; fail: if (tsp != NULL) { if (tsp->name != NULL) xfree(tsp->name); if (tsp->comment != NULL) xfree(tsp->comment); if (tsp->node_x_coord != NULL) xfree(tsp->node_x_coord); if (tsp->node_y_coord != NULL) xfree(tsp->node_y_coord); if (tsp->dply_x_coord != NULL) xfree(tsp->dply_x_coord); if (tsp->dply_y_coord != NULL) xfree(tsp->dply_y_coord); if (tsp->tour != NULL) xfree(tsp->tour); if (tsp->edge_weight != NULL) xfree(tsp->edge_weight); xfree(tsp); } if (dsa->fp != NULL) fclose(dsa->fp); return NULL; } /*---------------------------------------------------------------------- -- tsp_free_data - free TSP instance data. -- -- *Synopsis* -- -- #include "glptsp.h" -- void tsp_free_data(TSP *tsp); -- -- *Description* -- -- The routine tsp_free_data frees all the memory allocated to the TSP -- instance data block, which the parameter tsp points to. */ void tsp_free_data(TSP *tsp) { if (tsp->name != NULL) xfree(tsp->name); if (tsp->comment != NULL) xfree(tsp->comment); if (tsp->node_x_coord != NULL) xfree(tsp->node_x_coord); if (tsp->node_y_coord != NULL) xfree(tsp->node_y_coord); if (tsp->dply_x_coord != NULL) xfree(tsp->dply_x_coord); if (tsp->dply_y_coord != NULL) xfree(tsp->dply_y_coord); if (tsp->tour != NULL) xfree(tsp->tour); if (tsp->edge_weight != NULL) xfree(tsp->edge_weight); xfree(tsp); return; } /*---------------------------------------------------------------------- -- tsp_distance - compute distance between two nodes. -- -- *Synopsis* -- -- #include "glptsp.h" -- int tsp_distance(TSP *tsp, int i, int j); -- -- *Description* -- -- The routine tsp_distance computes the distance between i-th and j-th -- nodes for the TSP instance, which tsp points to. -- -- *Returns* -- -- The routine tsp_distance returns the computed distance. */ #define nint(x) ((int)((x) + 0.5)) static double rad(double x) { /* convert input coordinate to longitude/latitude, in radians */ double pi = 3.141592, deg, min; deg = (int)x; min = x - deg; return pi * (deg + 5.0 * min / 3.0) / 180.0; } int tsp_distance(TSP *tsp, int i, int j) { int n = tsp->dimension, dij; if (!(tsp->type == TSP_TSP || tsp->type == TSP_ATSP)) xfault("tsp_distance: invalid TSP instance\n"); if (!(1 <= i && i <= n && 1 <= j && j <= n)) xfault("tsp_distance: node number out of range\n"); switch (tsp->edge_weight_type) { case TSP_UNDEF: xfault("tsp_distance: edge weight type not specified\n"); case TSP_EXPLICIT: if (tsp->edge_weight == NULL) xfault("tsp_distance: edge weights not specified\n"); dij = tsp->edge_weight[(i - 1) * n + j]; break; case TSP_EUC_2D: if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) xfault("tsp_distance: node coordinates not specified\n"); { double xd, yd; xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; dij = nint(sqrt(xd * xd + yd * yd)); } break; case TSP_CEIL_2D: if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) xfault("tsp_distance: node coordinates not specified\n"); { double xd, yd; xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; dij = (int)ceil(sqrt(xd * xd + yd * yd)); } break; case TSP_GEO: if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) xfault("tsp_distance: node coordinates not specified\n"); { double rrr = 6378.388; double latitude_i = rad(tsp->node_x_coord[i]); double latitude_j = rad(tsp->node_x_coord[j]); double longitude_i = rad(tsp->node_y_coord[i]); double longitude_j = rad(tsp->node_y_coord[j]); double q1 = cos(longitude_i - longitude_j); double q2 = cos(latitude_i - latitude_j); double q3 = cos(latitude_i + latitude_j); dij = (int)(rrr * acos(0.5 * ((1.0 + q1) * q2 - (1.0 - q1) *q3)) + 1.0); } break; case TSP_ATT: if (tsp->node_x_coord == NULL || tsp->node_y_coord == NULL) xfault("tsp_distance: node coordinates not specified\n"); { int tij; double xd, yd, rij; xd = tsp->node_x_coord[i] - tsp->node_x_coord[j]; yd = tsp->node_y_coord[i] - tsp->node_y_coord[j]; rij = sqrt((xd * xd + yd * yd) / 10.0); tij = nint(rij); if (tij < rij) dij = tij + 1; else dij = tij; } break; default: xassert(tsp->edge_weight_type != tsp->edge_weight_type); } return dij; } /* eof */ glpk-4.52.1/src/glptsp.h0000644000062000006210000001053312175147600014174 0ustar maomkpasswd/* glptsp.h (TSP format) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, * 2009, 2010, 2011, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef GLPTSP_H #define GLPTSP_H typedef struct TSP TSP; struct TSP { /* TSP (or related problem) instance in the format described in the report [G.Reinelt, TSPLIB 95] */ /*--------------------------------------------------------------*/ /* the specification part */ char *name; /* identifies the data file */ int type; /* specifies the type of data: */ #define TSP_UNDEF 0 /* undefined */ #define TSP_TSP 1 /* symmetric TSP */ #define TSP_ATSP 2 /* asymmetric TSP */ #define TSP_TOUR 3 /* collection of tours */ char *comment; /* additional comments (usually the name of the contributor or creator of the problem instance is given here) */ int dimension; /* for a TSP or ATSP, the dimension is the number of its nodes for a TOUR it is the dimension of the corresponding problem */ int edge_weight_type; /* specifies how the edge weights (or distances) are given: */ #define TSP_UNDEF 0 /* undefined */ #define TSP_EXPLICIT 1 /* listed explicitly */ #define TSP_EUC_2D 2 /* Eucl. distances in 2-D */ #define TSP_CEIL_2D 3 /* Eucl. distances in 2-D rounded up */ #define TSP_GEO 4 /* geographical distances */ #define TSP_ATT 5 /* special distance function */ int edge_weight_format; /* describes the format of the edge weights if they are given explicitly: */ #define TSP_UNDEF 0 /* undefined */ #define TSP_FUNCTION 1 /* given by a function */ #define TSP_FULL_MATRIX 2 /* given by a full matrix */ #define TSP_UPPER_ROW 3 /* upper triangulat matrix (row-wise without diagonal entries) */ #define TSP_LOWER_DIAG_ROW 4 /* lower triangular matrix (row-wise including diagonal entries) */ int display_data_type; /* specifies how a graphical display of the nodes can be obtained: */ #define TSP_UNDEF 0 /* undefined */ #define TSP_COORD_DISPLAY 1 /* display is generated from the node coordinates */ #define TSP_TWOD_DISPLAY 2 /* explicit coordinates in 2-D are given */ /*--------------------------------------------------------------*/ /* data part */ /* NODE_COORD_SECTION: */ double *node_x_coord; /* double node_x_coord[1+dimension]; */ double *node_y_coord; /* double node_y_coord[1+dimension]; */ /* DISPLAY_DATA_SECTION: */ double *dply_x_coord; /* double dply_x_coord[1+dimension]; */ double *dply_y_coord; /* double dply_y_coord[1+dimension]; */ /* TOUR_SECTION: */ int *tour; /* int tour[1+dimension]; */ /* EDGE_WEIGHT_SECTION: */ int *edge_weight; /* int edge_weight[1+dimension*dimension]; */ }; #define tsp_read_data _glp_tsp_read_data #define tsp_free_data _glp_tsp_free_data #define tsp_distance _glp_tsp_distance TSP *tsp_read_data(char *fname); /* read TSP instance data */ void tsp_free_data(TSP *tsp); /* free TSP instance data */ int tsp_distance(TSP *tsp, int i, int j); /* compute distance between two nodes */ #endif /* eof */ glpk-4.52.1/src/Makefile.am0000644000062000006210000000452712175147600014554 0ustar maomkpasswd## Process this file with automake to produce Makefile.in ## include_HEADERS = glpk.h lib_LTLIBRARIES = libglpk.la libglpk_la_CPPFLAGS = \ -I$(srcdir) \ -I$(srcdir)/amd \ -I$(srcdir)/bflib \ -I$(srcdir)/cglib \ -I$(srcdir)/colamd \ -I$(srcdir)/env \ -I$(srcdir)/minisat \ -I$(srcdir)/misc \ -I$(srcdir)/proxy \ -I$(srcdir)/zlib libglpk_la_LDFLAGS = \ -version-info 36:1:0 \ -export-symbols-regex '^glp_*' libglpk_la_SOURCES = \ glpapi01.c \ glpapi02.c \ glpapi03.c \ glpapi04.c \ glpapi05.c \ glpapi06.c \ glpapi07.c \ glpapi08.c \ glpapi09.c \ glpapi10.c \ glpapi11.c \ glpapi12.c \ glpapi13.c \ glpapi14.c \ glpapi15.c \ glpapi16.c \ glpapi17.c \ glpapi18.c \ glpapi19.c \ glpapi20.c \ glpapi21.c \ glpavl.c \ glpbfd.c \ glpbfx.c \ glpcpx.c \ glpdmx.c \ glpenv07.c \ glpenv08.c \ glpgmp.c \ glphbm.c \ glpini01.c \ glpini02.c \ glpios01.c \ glpios02.c \ glpios03.c \ glpios04.c \ glpios05.c \ glpios06.c \ glpios07.c \ glpios08.c \ glpios09.c \ glpios10.c \ glpios11.c \ glpios12.c \ glpipm.c \ glplib03.c \ glplpf.c \ glplpx01.c \ glplpx02.c \ glplpx03.c \ glplux.c \ glpmat.c \ glpmpl01.c \ glpmpl02.c \ glpmpl03.c \ glpmpl04.c \ glpmpl05.c \ glpmpl06.c \ glpmps.c \ glpnet03.c \ glpnet04.c \ glpnet05.c \ glpnpp01.c \ glpnpp02.c \ glpnpp03.c \ glpnpp04.c \ glpnpp05.c \ glpnpp06.c \ glprgr.c \ glpscf.c \ glpscl.c \ glpsdf.c \ glpspm.c \ glpspx01.c \ glpspx02.c \ glpsql.c \ glpssx01.c \ glpssx02.c \ glptsp.c \ amd/amd_1.c \ amd/amd_2.c \ amd/amd_aat.c \ amd/amd_control.c \ amd/amd_defaults.c \ amd/amd_dump.c \ amd/amd_info.c \ amd/amd_order.c \ amd/amd_post_tree.c \ amd/amd_postorder.c \ amd/amd_preprocess.c \ amd/amd_valid.c \ bflib/fhv.c \ bflib/fhvint.c \ bflib/luf.c \ bflib/lufint.c \ bflib/sgf.c \ bflib/sva.c \ cglib/cfg.c \ cglib/cfg1.c \ colamd/colamd.c \ env/alloc.c \ env/env.c \ env/error.c \ env/stdout.c \ env/time.c \ env/tls.c \ minisat/minisat.c \ misc/bignum.c \ misc/dmp.c \ misc/ffalg.c \ misc/jd.c \ misc/keller.c \ misc/mc13d.c \ misc/mc21a.c \ misc/okalg.c \ misc/qmd.c \ misc/relax4.c \ misc/rng.c \ misc/rng1.c \ misc/triang.c \ misc/wclique.c \ misc/wclique1.c \ proxy/proxy.c \ proxy/proxy1.c \ zlib/adler32.c \ zlib/compress.c \ zlib/crc32.c \ zlib/deflate.c \ zlib/gzclose.c \ zlib/gzlib.c \ zlib/gzread.c \ zlib/gzwrite.c \ zlib/inffast.c \ zlib/inflate.c \ zlib/inftrees.c \ zlib/trees.c \ zlib/uncompr.c \ zlib/zio.c \ zlib/zutil.c ## eof ## glpk-4.52.1/src/Makefile.in0000644000062000006210000051530212175147600014563 0ustar maomkpasswd# Makefile.in generated by automake 1.12.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = src DIST_COMMON = $(include_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libglpk_la_LIBADD = am_libglpk_la_OBJECTS = libglpk_la-glpapi01.lo libglpk_la-glpapi02.lo \ libglpk_la-glpapi03.lo libglpk_la-glpapi04.lo \ libglpk_la-glpapi05.lo libglpk_la-glpapi06.lo \ libglpk_la-glpapi07.lo libglpk_la-glpapi08.lo \ libglpk_la-glpapi09.lo libglpk_la-glpapi10.lo \ libglpk_la-glpapi11.lo libglpk_la-glpapi12.lo \ libglpk_la-glpapi13.lo libglpk_la-glpapi14.lo \ libglpk_la-glpapi15.lo libglpk_la-glpapi16.lo \ libglpk_la-glpapi17.lo libglpk_la-glpapi18.lo \ libglpk_la-glpapi19.lo libglpk_la-glpapi20.lo \ libglpk_la-glpapi21.lo libglpk_la-glpavl.lo \ libglpk_la-glpbfd.lo libglpk_la-glpbfx.lo libglpk_la-glpcpx.lo \ libglpk_la-glpdmx.lo libglpk_la-glpenv07.lo \ libglpk_la-glpenv08.lo libglpk_la-glpgmp.lo \ libglpk_la-glphbm.lo libglpk_la-glpini01.lo \ libglpk_la-glpini02.lo libglpk_la-glpios01.lo \ libglpk_la-glpios02.lo libglpk_la-glpios03.lo \ libglpk_la-glpios04.lo libglpk_la-glpios05.lo \ libglpk_la-glpios06.lo libglpk_la-glpios07.lo \ libglpk_la-glpios08.lo libglpk_la-glpios09.lo \ libglpk_la-glpios10.lo libglpk_la-glpios11.lo \ libglpk_la-glpios12.lo libglpk_la-glpipm.lo \ libglpk_la-glplib03.lo libglpk_la-glplpf.lo \ libglpk_la-glplpx01.lo libglpk_la-glplpx02.lo \ libglpk_la-glplpx03.lo libglpk_la-glplux.lo \ libglpk_la-glpmat.lo libglpk_la-glpmpl01.lo \ libglpk_la-glpmpl02.lo libglpk_la-glpmpl03.lo \ libglpk_la-glpmpl04.lo libglpk_la-glpmpl05.lo \ libglpk_la-glpmpl06.lo libglpk_la-glpmps.lo \ libglpk_la-glpnet03.lo libglpk_la-glpnet04.lo \ libglpk_la-glpnet05.lo libglpk_la-glpnpp01.lo \ libglpk_la-glpnpp02.lo libglpk_la-glpnpp03.lo \ libglpk_la-glpnpp04.lo libglpk_la-glpnpp05.lo \ libglpk_la-glpnpp06.lo libglpk_la-glprgr.lo \ libglpk_la-glpscf.lo libglpk_la-glpscl.lo libglpk_la-glpsdf.lo \ libglpk_la-glpspm.lo libglpk_la-glpspx01.lo \ libglpk_la-glpspx02.lo libglpk_la-glpsql.lo \ libglpk_la-glpssx01.lo libglpk_la-glpssx02.lo \ libglpk_la-glptsp.lo libglpk_la-amd_1.lo libglpk_la-amd_2.lo \ libglpk_la-amd_aat.lo libglpk_la-amd_control.lo \ libglpk_la-amd_defaults.lo libglpk_la-amd_dump.lo \ libglpk_la-amd_info.lo libglpk_la-amd_order.lo \ libglpk_la-amd_post_tree.lo libglpk_la-amd_postorder.lo \ libglpk_la-amd_preprocess.lo libglpk_la-amd_valid.lo \ libglpk_la-fhv.lo libglpk_la-fhvint.lo libglpk_la-luf.lo \ libglpk_la-lufint.lo libglpk_la-sgf.lo libglpk_la-sva.lo \ libglpk_la-cfg.lo libglpk_la-cfg1.lo libglpk_la-colamd.lo \ libglpk_la-alloc.lo libglpk_la-env.lo libglpk_la-error.lo \ libglpk_la-stdout.lo libglpk_la-time.lo libglpk_la-tls.lo \ libglpk_la-minisat.lo libglpk_la-bignum.lo libglpk_la-dmp.lo \ libglpk_la-ffalg.lo libglpk_la-jd.lo libglpk_la-keller.lo \ libglpk_la-mc13d.lo libglpk_la-mc21a.lo libglpk_la-okalg.lo \ libglpk_la-qmd.lo libglpk_la-relax4.lo libglpk_la-rng.lo \ libglpk_la-rng1.lo libglpk_la-triang.lo libglpk_la-wclique.lo \ libglpk_la-wclique1.lo libglpk_la-proxy.lo \ libglpk_la-proxy1.lo libglpk_la-adler32.lo \ libglpk_la-compress.lo libglpk_la-crc32.lo \ libglpk_la-deflate.lo libglpk_la-gzclose.lo \ libglpk_la-gzlib.lo libglpk_la-gzread.lo libglpk_la-gzwrite.lo \ libglpk_la-inffast.lo libglpk_la-inflate.lo \ libglpk_la-inftrees.lo libglpk_la-trees.lo \ libglpk_la-uncompr.lo libglpk_la-zio.lo libglpk_la-zutil.lo libglpk_la_OBJECTS = $(am_libglpk_la_OBJECTS) libglpk_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libglpk_la_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libglpk_la_SOURCES) DIST_SOURCES = $(libglpk_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(include_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ include_HEADERS = glpk.h lib_LTLIBRARIES = libglpk.la libglpk_la_CPPFLAGS = \ -I$(srcdir) \ -I$(srcdir)/amd \ -I$(srcdir)/bflib \ -I$(srcdir)/cglib \ -I$(srcdir)/colamd \ -I$(srcdir)/env \ -I$(srcdir)/minisat \ -I$(srcdir)/misc \ -I$(srcdir)/proxy \ -I$(srcdir)/zlib libglpk_la_LDFLAGS = \ -version-info 36:1:0 \ -export-symbols-regex '^glp_*' libglpk_la_SOURCES = \ glpapi01.c \ glpapi02.c \ glpapi03.c \ glpapi04.c \ glpapi05.c \ glpapi06.c \ glpapi07.c \ glpapi08.c \ glpapi09.c \ glpapi10.c \ glpapi11.c \ glpapi12.c \ glpapi13.c \ glpapi14.c \ glpapi15.c \ glpapi16.c \ glpapi17.c \ glpapi18.c \ glpapi19.c \ glpapi20.c \ glpapi21.c \ glpavl.c \ glpbfd.c \ glpbfx.c \ glpcpx.c \ glpdmx.c \ glpenv07.c \ glpenv08.c \ glpgmp.c \ glphbm.c \ glpini01.c \ glpini02.c \ glpios01.c \ glpios02.c \ glpios03.c \ glpios04.c \ glpios05.c \ glpios06.c \ glpios07.c \ glpios08.c \ glpios09.c \ glpios10.c \ glpios11.c \ glpios12.c \ glpipm.c \ glplib03.c \ glplpf.c \ glplpx01.c \ glplpx02.c \ glplpx03.c \ glplux.c \ glpmat.c \ glpmpl01.c \ glpmpl02.c \ glpmpl03.c \ glpmpl04.c \ glpmpl05.c \ glpmpl06.c \ glpmps.c \ glpnet03.c \ glpnet04.c \ glpnet05.c \ glpnpp01.c \ glpnpp02.c \ glpnpp03.c \ glpnpp04.c \ glpnpp05.c \ glpnpp06.c \ glprgr.c \ glpscf.c \ glpscl.c \ glpsdf.c \ glpspm.c \ glpspx01.c \ glpspx02.c \ glpsql.c \ glpssx01.c \ glpssx02.c \ glptsp.c \ amd/amd_1.c \ amd/amd_2.c \ amd/amd_aat.c \ amd/amd_control.c \ amd/amd_defaults.c \ amd/amd_dump.c \ amd/amd_info.c \ amd/amd_order.c \ amd/amd_post_tree.c \ amd/amd_postorder.c \ amd/amd_preprocess.c \ amd/amd_valid.c \ bflib/fhv.c \ bflib/fhvint.c \ bflib/luf.c \ bflib/lufint.c \ bflib/sgf.c \ bflib/sva.c \ cglib/cfg.c \ cglib/cfg1.c \ colamd/colamd.c \ env/alloc.c \ env/env.c \ env/error.c \ env/stdout.c \ env/time.c \ env/tls.c \ minisat/minisat.c \ misc/bignum.c \ misc/dmp.c \ misc/ffalg.c \ misc/jd.c \ misc/keller.c \ misc/mc13d.c \ misc/mc21a.c \ misc/okalg.c \ misc/qmd.c \ misc/relax4.c \ misc/rng.c \ misc/rng1.c \ misc/triang.c \ misc/wclique.c \ misc/wclique1.c \ proxy/proxy.c \ proxy/proxy1.c \ zlib/adler32.c \ zlib/compress.c \ zlib/crc32.c \ zlib/deflate.c \ zlib/gzclose.c \ zlib/gzlib.c \ zlib/gzread.c \ zlib/gzwrite.c \ zlib/inffast.c \ zlib/inflate.c \ zlib/inftrees.c \ zlib/trees.c \ zlib/uncompr.c \ zlib/zio.c \ zlib/zutil.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libglpk.la: $(libglpk_la_OBJECTS) $(libglpk_la_DEPENDENCIES) $(EXTRA_libglpk_la_DEPENDENCIES) $(libglpk_la_LINK) -rpath $(libdir) $(libglpk_la_OBJECTS) $(libglpk_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-adler32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-alloc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_2.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_aat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_control.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_defaults.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_dump.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_info.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_order.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_post_tree.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_postorder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_preprocess.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-amd_valid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-bignum.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-cfg1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-colamd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-compress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-crc32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-deflate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-dmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-env.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-ffalg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fhv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-fhvint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi03.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi04.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi05.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi06.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi07.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi08.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi09.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi10.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi12.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi13.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi14.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi15.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi16.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi17.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi18.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi19.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi20.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpapi21.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpavl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpbfd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpbfx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpcpx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpdmx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpenv07.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpenv08.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpgmp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glphbm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpini01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpini02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios03.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios04.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios05.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios06.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios07.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios08.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios09.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios10.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpios12.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpipm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplib03.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplpf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplpx01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplpx02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplpx03.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glplux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl03.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl04.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl05.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmpl06.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpmps.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnet03.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnet04.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnet05.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp03.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp04.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp05.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpnpp06.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glprgr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpscf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpscl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpsdf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspx01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpspx02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpsql.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx01.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glpssx02.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-glptsp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzclose.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzlib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-gzwrite.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inffast.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inflate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-inftrees.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-jd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-keller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-luf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-lufint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mc13d.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-mc21a.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-minisat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-okalg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-proxy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-proxy1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-qmd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-relax4.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-rng1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-sgf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-stdout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-sva.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-time.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-tls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-trees.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-triang.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-uncompr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wclique.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-wclique1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-zio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libglpk_la-zutil.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libglpk_la-glpapi01.lo: glpapi01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi01.Tpo -c -o libglpk_la-glpapi01.lo `test -f 'glpapi01.c' || echo '$(srcdir)/'`glpapi01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi01.Tpo $(DEPDIR)/libglpk_la-glpapi01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi01.c' object='libglpk_la-glpapi01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi01.lo `test -f 'glpapi01.c' || echo '$(srcdir)/'`glpapi01.c libglpk_la-glpapi02.lo: glpapi02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi02.Tpo -c -o libglpk_la-glpapi02.lo `test -f 'glpapi02.c' || echo '$(srcdir)/'`glpapi02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi02.Tpo $(DEPDIR)/libglpk_la-glpapi02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi02.c' object='libglpk_la-glpapi02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi02.lo `test -f 'glpapi02.c' || echo '$(srcdir)/'`glpapi02.c libglpk_la-glpapi03.lo: glpapi03.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi03.Tpo -c -o libglpk_la-glpapi03.lo `test -f 'glpapi03.c' || echo '$(srcdir)/'`glpapi03.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi03.Tpo $(DEPDIR)/libglpk_la-glpapi03.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi03.c' object='libglpk_la-glpapi03.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi03.lo `test -f 'glpapi03.c' || echo '$(srcdir)/'`glpapi03.c libglpk_la-glpapi04.lo: glpapi04.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi04.Tpo -c -o libglpk_la-glpapi04.lo `test -f 'glpapi04.c' || echo '$(srcdir)/'`glpapi04.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi04.Tpo $(DEPDIR)/libglpk_la-glpapi04.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi04.c' object='libglpk_la-glpapi04.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi04.lo `test -f 'glpapi04.c' || echo '$(srcdir)/'`glpapi04.c libglpk_la-glpapi05.lo: glpapi05.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi05.Tpo -c -o libglpk_la-glpapi05.lo `test -f 'glpapi05.c' || echo '$(srcdir)/'`glpapi05.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi05.Tpo $(DEPDIR)/libglpk_la-glpapi05.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi05.c' object='libglpk_la-glpapi05.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi05.lo `test -f 'glpapi05.c' || echo '$(srcdir)/'`glpapi05.c libglpk_la-glpapi06.lo: glpapi06.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi06.Tpo -c -o libglpk_la-glpapi06.lo `test -f 'glpapi06.c' || echo '$(srcdir)/'`glpapi06.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi06.Tpo $(DEPDIR)/libglpk_la-glpapi06.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi06.c' object='libglpk_la-glpapi06.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi06.lo `test -f 'glpapi06.c' || echo '$(srcdir)/'`glpapi06.c libglpk_la-glpapi07.lo: glpapi07.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi07.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi07.Tpo -c -o libglpk_la-glpapi07.lo `test -f 'glpapi07.c' || echo '$(srcdir)/'`glpapi07.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi07.Tpo $(DEPDIR)/libglpk_la-glpapi07.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi07.c' object='libglpk_la-glpapi07.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi07.lo `test -f 'glpapi07.c' || echo '$(srcdir)/'`glpapi07.c libglpk_la-glpapi08.lo: glpapi08.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi08.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi08.Tpo -c -o libglpk_la-glpapi08.lo `test -f 'glpapi08.c' || echo '$(srcdir)/'`glpapi08.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi08.Tpo $(DEPDIR)/libglpk_la-glpapi08.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi08.c' object='libglpk_la-glpapi08.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi08.lo `test -f 'glpapi08.c' || echo '$(srcdir)/'`glpapi08.c libglpk_la-glpapi09.lo: glpapi09.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi09.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi09.Tpo -c -o libglpk_la-glpapi09.lo `test -f 'glpapi09.c' || echo '$(srcdir)/'`glpapi09.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi09.Tpo $(DEPDIR)/libglpk_la-glpapi09.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi09.c' object='libglpk_la-glpapi09.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi09.lo `test -f 'glpapi09.c' || echo '$(srcdir)/'`glpapi09.c libglpk_la-glpapi10.lo: glpapi10.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi10.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi10.Tpo -c -o libglpk_la-glpapi10.lo `test -f 'glpapi10.c' || echo '$(srcdir)/'`glpapi10.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi10.Tpo $(DEPDIR)/libglpk_la-glpapi10.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi10.c' object='libglpk_la-glpapi10.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi10.lo `test -f 'glpapi10.c' || echo '$(srcdir)/'`glpapi10.c libglpk_la-glpapi11.lo: glpapi11.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi11.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi11.Tpo -c -o libglpk_la-glpapi11.lo `test -f 'glpapi11.c' || echo '$(srcdir)/'`glpapi11.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi11.Tpo $(DEPDIR)/libglpk_la-glpapi11.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi11.c' object='libglpk_la-glpapi11.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi11.lo `test -f 'glpapi11.c' || echo '$(srcdir)/'`glpapi11.c libglpk_la-glpapi12.lo: glpapi12.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi12.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi12.Tpo -c -o libglpk_la-glpapi12.lo `test -f 'glpapi12.c' || echo '$(srcdir)/'`glpapi12.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi12.Tpo $(DEPDIR)/libglpk_la-glpapi12.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi12.c' object='libglpk_la-glpapi12.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi12.lo `test -f 'glpapi12.c' || echo '$(srcdir)/'`glpapi12.c libglpk_la-glpapi13.lo: glpapi13.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi13.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi13.Tpo -c -o libglpk_la-glpapi13.lo `test -f 'glpapi13.c' || echo '$(srcdir)/'`glpapi13.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi13.Tpo $(DEPDIR)/libglpk_la-glpapi13.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi13.c' object='libglpk_la-glpapi13.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi13.lo `test -f 'glpapi13.c' || echo '$(srcdir)/'`glpapi13.c libglpk_la-glpapi14.lo: glpapi14.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi14.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi14.Tpo -c -o libglpk_la-glpapi14.lo `test -f 'glpapi14.c' || echo '$(srcdir)/'`glpapi14.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi14.Tpo $(DEPDIR)/libglpk_la-glpapi14.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi14.c' object='libglpk_la-glpapi14.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi14.lo `test -f 'glpapi14.c' || echo '$(srcdir)/'`glpapi14.c libglpk_la-glpapi15.lo: glpapi15.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi15.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi15.Tpo -c -o libglpk_la-glpapi15.lo `test -f 'glpapi15.c' || echo '$(srcdir)/'`glpapi15.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi15.Tpo $(DEPDIR)/libglpk_la-glpapi15.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi15.c' object='libglpk_la-glpapi15.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi15.lo `test -f 'glpapi15.c' || echo '$(srcdir)/'`glpapi15.c libglpk_la-glpapi16.lo: glpapi16.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi16.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi16.Tpo -c -o libglpk_la-glpapi16.lo `test -f 'glpapi16.c' || echo '$(srcdir)/'`glpapi16.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi16.Tpo $(DEPDIR)/libglpk_la-glpapi16.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi16.c' object='libglpk_la-glpapi16.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi16.lo `test -f 'glpapi16.c' || echo '$(srcdir)/'`glpapi16.c libglpk_la-glpapi17.lo: glpapi17.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi17.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi17.Tpo -c -o libglpk_la-glpapi17.lo `test -f 'glpapi17.c' || echo '$(srcdir)/'`glpapi17.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi17.Tpo $(DEPDIR)/libglpk_la-glpapi17.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi17.c' object='libglpk_la-glpapi17.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi17.lo `test -f 'glpapi17.c' || echo '$(srcdir)/'`glpapi17.c libglpk_la-glpapi18.lo: glpapi18.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi18.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi18.Tpo -c -o libglpk_la-glpapi18.lo `test -f 'glpapi18.c' || echo '$(srcdir)/'`glpapi18.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi18.Tpo $(DEPDIR)/libglpk_la-glpapi18.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi18.c' object='libglpk_la-glpapi18.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi18.lo `test -f 'glpapi18.c' || echo '$(srcdir)/'`glpapi18.c libglpk_la-glpapi19.lo: glpapi19.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi19.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi19.Tpo -c -o libglpk_la-glpapi19.lo `test -f 'glpapi19.c' || echo '$(srcdir)/'`glpapi19.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi19.Tpo $(DEPDIR)/libglpk_la-glpapi19.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi19.c' object='libglpk_la-glpapi19.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi19.lo `test -f 'glpapi19.c' || echo '$(srcdir)/'`glpapi19.c libglpk_la-glpapi20.lo: glpapi20.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi20.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi20.Tpo -c -o libglpk_la-glpapi20.lo `test -f 'glpapi20.c' || echo '$(srcdir)/'`glpapi20.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi20.Tpo $(DEPDIR)/libglpk_la-glpapi20.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi20.c' object='libglpk_la-glpapi20.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi20.lo `test -f 'glpapi20.c' || echo '$(srcdir)/'`glpapi20.c libglpk_la-glpapi21.lo: glpapi21.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpapi21.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpapi21.Tpo -c -o libglpk_la-glpapi21.lo `test -f 'glpapi21.c' || echo '$(srcdir)/'`glpapi21.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpapi21.Tpo $(DEPDIR)/libglpk_la-glpapi21.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpapi21.c' object='libglpk_la-glpapi21.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpapi21.lo `test -f 'glpapi21.c' || echo '$(srcdir)/'`glpapi21.c libglpk_la-glpavl.lo: glpavl.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpavl.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpavl.Tpo -c -o libglpk_la-glpavl.lo `test -f 'glpavl.c' || echo '$(srcdir)/'`glpavl.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpavl.Tpo $(DEPDIR)/libglpk_la-glpavl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpavl.c' object='libglpk_la-glpavl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpavl.lo `test -f 'glpavl.c' || echo '$(srcdir)/'`glpavl.c libglpk_la-glpbfd.lo: glpbfd.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpbfd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpbfd.Tpo -c -o libglpk_la-glpbfd.lo `test -f 'glpbfd.c' || echo '$(srcdir)/'`glpbfd.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpbfd.Tpo $(DEPDIR)/libglpk_la-glpbfd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpbfd.c' object='libglpk_la-glpbfd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpbfd.lo `test -f 'glpbfd.c' || echo '$(srcdir)/'`glpbfd.c libglpk_la-glpbfx.lo: glpbfx.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpbfx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpbfx.Tpo -c -o libglpk_la-glpbfx.lo `test -f 'glpbfx.c' || echo '$(srcdir)/'`glpbfx.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpbfx.Tpo $(DEPDIR)/libglpk_la-glpbfx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpbfx.c' object='libglpk_la-glpbfx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpbfx.lo `test -f 'glpbfx.c' || echo '$(srcdir)/'`glpbfx.c libglpk_la-glpcpx.lo: glpcpx.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpcpx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpcpx.Tpo -c -o libglpk_la-glpcpx.lo `test -f 'glpcpx.c' || echo '$(srcdir)/'`glpcpx.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpcpx.Tpo $(DEPDIR)/libglpk_la-glpcpx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpcpx.c' object='libglpk_la-glpcpx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpcpx.lo `test -f 'glpcpx.c' || echo '$(srcdir)/'`glpcpx.c libglpk_la-glpdmx.lo: glpdmx.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpdmx.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpdmx.Tpo -c -o libglpk_la-glpdmx.lo `test -f 'glpdmx.c' || echo '$(srcdir)/'`glpdmx.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpdmx.Tpo $(DEPDIR)/libglpk_la-glpdmx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpdmx.c' object='libglpk_la-glpdmx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpdmx.lo `test -f 'glpdmx.c' || echo '$(srcdir)/'`glpdmx.c libglpk_la-glpenv07.lo: glpenv07.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpenv07.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpenv07.Tpo -c -o libglpk_la-glpenv07.lo `test -f 'glpenv07.c' || echo '$(srcdir)/'`glpenv07.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpenv07.Tpo $(DEPDIR)/libglpk_la-glpenv07.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpenv07.c' object='libglpk_la-glpenv07.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpenv07.lo `test -f 'glpenv07.c' || echo '$(srcdir)/'`glpenv07.c libglpk_la-glpenv08.lo: glpenv08.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpenv08.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpenv08.Tpo -c -o libglpk_la-glpenv08.lo `test -f 'glpenv08.c' || echo '$(srcdir)/'`glpenv08.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpenv08.Tpo $(DEPDIR)/libglpk_la-glpenv08.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpenv08.c' object='libglpk_la-glpenv08.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpenv08.lo `test -f 'glpenv08.c' || echo '$(srcdir)/'`glpenv08.c libglpk_la-glpgmp.lo: glpgmp.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpgmp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpgmp.Tpo -c -o libglpk_la-glpgmp.lo `test -f 'glpgmp.c' || echo '$(srcdir)/'`glpgmp.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpgmp.Tpo $(DEPDIR)/libglpk_la-glpgmp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpgmp.c' object='libglpk_la-glpgmp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpgmp.lo `test -f 'glpgmp.c' || echo '$(srcdir)/'`glpgmp.c libglpk_la-glphbm.lo: glphbm.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glphbm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glphbm.Tpo -c -o libglpk_la-glphbm.lo `test -f 'glphbm.c' || echo '$(srcdir)/'`glphbm.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glphbm.Tpo $(DEPDIR)/libglpk_la-glphbm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glphbm.c' object='libglpk_la-glphbm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glphbm.lo `test -f 'glphbm.c' || echo '$(srcdir)/'`glphbm.c libglpk_la-glpini01.lo: glpini01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpini01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpini01.Tpo -c -o libglpk_la-glpini01.lo `test -f 'glpini01.c' || echo '$(srcdir)/'`glpini01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpini01.Tpo $(DEPDIR)/libglpk_la-glpini01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpini01.c' object='libglpk_la-glpini01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpini01.lo `test -f 'glpini01.c' || echo '$(srcdir)/'`glpini01.c libglpk_la-glpini02.lo: glpini02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpini02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpini02.Tpo -c -o libglpk_la-glpini02.lo `test -f 'glpini02.c' || echo '$(srcdir)/'`glpini02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpini02.Tpo $(DEPDIR)/libglpk_la-glpini02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpini02.c' object='libglpk_la-glpini02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpini02.lo `test -f 'glpini02.c' || echo '$(srcdir)/'`glpini02.c libglpk_la-glpios01.lo: glpios01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios01.Tpo -c -o libglpk_la-glpios01.lo `test -f 'glpios01.c' || echo '$(srcdir)/'`glpios01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios01.Tpo $(DEPDIR)/libglpk_la-glpios01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios01.c' object='libglpk_la-glpios01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios01.lo `test -f 'glpios01.c' || echo '$(srcdir)/'`glpios01.c libglpk_la-glpios02.lo: glpios02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios02.Tpo -c -o libglpk_la-glpios02.lo `test -f 'glpios02.c' || echo '$(srcdir)/'`glpios02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios02.Tpo $(DEPDIR)/libglpk_la-glpios02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios02.c' object='libglpk_la-glpios02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios02.lo `test -f 'glpios02.c' || echo '$(srcdir)/'`glpios02.c libglpk_la-glpios03.lo: glpios03.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios03.Tpo -c -o libglpk_la-glpios03.lo `test -f 'glpios03.c' || echo '$(srcdir)/'`glpios03.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios03.Tpo $(DEPDIR)/libglpk_la-glpios03.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios03.c' object='libglpk_la-glpios03.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios03.lo `test -f 'glpios03.c' || echo '$(srcdir)/'`glpios03.c libglpk_la-glpios04.lo: glpios04.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios04.Tpo -c -o libglpk_la-glpios04.lo `test -f 'glpios04.c' || echo '$(srcdir)/'`glpios04.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios04.Tpo $(DEPDIR)/libglpk_la-glpios04.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios04.c' object='libglpk_la-glpios04.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios04.lo `test -f 'glpios04.c' || echo '$(srcdir)/'`glpios04.c libglpk_la-glpios05.lo: glpios05.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios05.Tpo -c -o libglpk_la-glpios05.lo `test -f 'glpios05.c' || echo '$(srcdir)/'`glpios05.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios05.Tpo $(DEPDIR)/libglpk_la-glpios05.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios05.c' object='libglpk_la-glpios05.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios05.lo `test -f 'glpios05.c' || echo '$(srcdir)/'`glpios05.c libglpk_la-glpios06.lo: glpios06.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios06.Tpo -c -o libglpk_la-glpios06.lo `test -f 'glpios06.c' || echo '$(srcdir)/'`glpios06.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios06.Tpo $(DEPDIR)/libglpk_la-glpios06.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios06.c' object='libglpk_la-glpios06.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios06.lo `test -f 'glpios06.c' || echo '$(srcdir)/'`glpios06.c libglpk_la-glpios07.lo: glpios07.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios07.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios07.Tpo -c -o libglpk_la-glpios07.lo `test -f 'glpios07.c' || echo '$(srcdir)/'`glpios07.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios07.Tpo $(DEPDIR)/libglpk_la-glpios07.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios07.c' object='libglpk_la-glpios07.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios07.lo `test -f 'glpios07.c' || echo '$(srcdir)/'`glpios07.c libglpk_la-glpios08.lo: glpios08.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios08.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios08.Tpo -c -o libglpk_la-glpios08.lo `test -f 'glpios08.c' || echo '$(srcdir)/'`glpios08.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios08.Tpo $(DEPDIR)/libglpk_la-glpios08.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios08.c' object='libglpk_la-glpios08.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios08.lo `test -f 'glpios08.c' || echo '$(srcdir)/'`glpios08.c libglpk_la-glpios09.lo: glpios09.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios09.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios09.Tpo -c -o libglpk_la-glpios09.lo `test -f 'glpios09.c' || echo '$(srcdir)/'`glpios09.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios09.Tpo $(DEPDIR)/libglpk_la-glpios09.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios09.c' object='libglpk_la-glpios09.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios09.lo `test -f 'glpios09.c' || echo '$(srcdir)/'`glpios09.c libglpk_la-glpios10.lo: glpios10.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios10.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios10.Tpo -c -o libglpk_la-glpios10.lo `test -f 'glpios10.c' || echo '$(srcdir)/'`glpios10.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios10.Tpo $(DEPDIR)/libglpk_la-glpios10.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios10.c' object='libglpk_la-glpios10.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios10.lo `test -f 'glpios10.c' || echo '$(srcdir)/'`glpios10.c libglpk_la-glpios11.lo: glpios11.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios11.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios11.Tpo -c -o libglpk_la-glpios11.lo `test -f 'glpios11.c' || echo '$(srcdir)/'`glpios11.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios11.Tpo $(DEPDIR)/libglpk_la-glpios11.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios11.c' object='libglpk_la-glpios11.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios11.lo `test -f 'glpios11.c' || echo '$(srcdir)/'`glpios11.c libglpk_la-glpios12.lo: glpios12.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpios12.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpios12.Tpo -c -o libglpk_la-glpios12.lo `test -f 'glpios12.c' || echo '$(srcdir)/'`glpios12.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpios12.Tpo $(DEPDIR)/libglpk_la-glpios12.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpios12.c' object='libglpk_la-glpios12.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpios12.lo `test -f 'glpios12.c' || echo '$(srcdir)/'`glpios12.c libglpk_la-glpipm.lo: glpipm.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpipm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpipm.Tpo -c -o libglpk_la-glpipm.lo `test -f 'glpipm.c' || echo '$(srcdir)/'`glpipm.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpipm.Tpo $(DEPDIR)/libglpk_la-glpipm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpipm.c' object='libglpk_la-glpipm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpipm.lo `test -f 'glpipm.c' || echo '$(srcdir)/'`glpipm.c libglpk_la-glplib03.lo: glplib03.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplib03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplib03.Tpo -c -o libglpk_la-glplib03.lo `test -f 'glplib03.c' || echo '$(srcdir)/'`glplib03.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplib03.Tpo $(DEPDIR)/libglpk_la-glplib03.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplib03.c' object='libglpk_la-glplib03.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplib03.lo `test -f 'glplib03.c' || echo '$(srcdir)/'`glplib03.c libglpk_la-glplpf.lo: glplpf.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplpf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplpf.Tpo -c -o libglpk_la-glplpf.lo `test -f 'glplpf.c' || echo '$(srcdir)/'`glplpf.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplpf.Tpo $(DEPDIR)/libglpk_la-glplpf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplpf.c' object='libglpk_la-glplpf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplpf.lo `test -f 'glplpf.c' || echo '$(srcdir)/'`glplpf.c libglpk_la-glplpx01.lo: glplpx01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplpx01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplpx01.Tpo -c -o libglpk_la-glplpx01.lo `test -f 'glplpx01.c' || echo '$(srcdir)/'`glplpx01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplpx01.Tpo $(DEPDIR)/libglpk_la-glplpx01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplpx01.c' object='libglpk_la-glplpx01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplpx01.lo `test -f 'glplpx01.c' || echo '$(srcdir)/'`glplpx01.c libglpk_la-glplpx02.lo: glplpx02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplpx02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplpx02.Tpo -c -o libglpk_la-glplpx02.lo `test -f 'glplpx02.c' || echo '$(srcdir)/'`glplpx02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplpx02.Tpo $(DEPDIR)/libglpk_la-glplpx02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplpx02.c' object='libglpk_la-glplpx02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplpx02.lo `test -f 'glplpx02.c' || echo '$(srcdir)/'`glplpx02.c libglpk_la-glplpx03.lo: glplpx03.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplpx03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplpx03.Tpo -c -o libglpk_la-glplpx03.lo `test -f 'glplpx03.c' || echo '$(srcdir)/'`glplpx03.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplpx03.Tpo $(DEPDIR)/libglpk_la-glplpx03.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplpx03.c' object='libglpk_la-glplpx03.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplpx03.lo `test -f 'glplpx03.c' || echo '$(srcdir)/'`glplpx03.c libglpk_la-glplux.lo: glplux.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glplux.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glplux.Tpo -c -o libglpk_la-glplux.lo `test -f 'glplux.c' || echo '$(srcdir)/'`glplux.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glplux.Tpo $(DEPDIR)/libglpk_la-glplux.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glplux.c' object='libglpk_la-glplux.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glplux.lo `test -f 'glplux.c' || echo '$(srcdir)/'`glplux.c libglpk_la-glpmat.lo: glpmat.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmat.Tpo -c -o libglpk_la-glpmat.lo `test -f 'glpmat.c' || echo '$(srcdir)/'`glpmat.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmat.Tpo $(DEPDIR)/libglpk_la-glpmat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmat.c' object='libglpk_la-glpmat.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmat.lo `test -f 'glpmat.c' || echo '$(srcdir)/'`glpmat.c libglpk_la-glpmpl01.lo: glpmpl01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl01.Tpo -c -o libglpk_la-glpmpl01.lo `test -f 'glpmpl01.c' || echo '$(srcdir)/'`glpmpl01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl01.Tpo $(DEPDIR)/libglpk_la-glpmpl01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl01.c' object='libglpk_la-glpmpl01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl01.lo `test -f 'glpmpl01.c' || echo '$(srcdir)/'`glpmpl01.c libglpk_la-glpmpl02.lo: glpmpl02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl02.Tpo -c -o libglpk_la-glpmpl02.lo `test -f 'glpmpl02.c' || echo '$(srcdir)/'`glpmpl02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl02.Tpo $(DEPDIR)/libglpk_la-glpmpl02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl02.c' object='libglpk_la-glpmpl02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl02.lo `test -f 'glpmpl02.c' || echo '$(srcdir)/'`glpmpl02.c libglpk_la-glpmpl03.lo: glpmpl03.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl03.Tpo -c -o libglpk_la-glpmpl03.lo `test -f 'glpmpl03.c' || echo '$(srcdir)/'`glpmpl03.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl03.Tpo $(DEPDIR)/libglpk_la-glpmpl03.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl03.c' object='libglpk_la-glpmpl03.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl03.lo `test -f 'glpmpl03.c' || echo '$(srcdir)/'`glpmpl03.c libglpk_la-glpmpl04.lo: glpmpl04.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl04.Tpo -c -o libglpk_la-glpmpl04.lo `test -f 'glpmpl04.c' || echo '$(srcdir)/'`glpmpl04.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl04.Tpo $(DEPDIR)/libglpk_la-glpmpl04.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl04.c' object='libglpk_la-glpmpl04.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl04.lo `test -f 'glpmpl04.c' || echo '$(srcdir)/'`glpmpl04.c libglpk_la-glpmpl05.lo: glpmpl05.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl05.Tpo -c -o libglpk_la-glpmpl05.lo `test -f 'glpmpl05.c' || echo '$(srcdir)/'`glpmpl05.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl05.Tpo $(DEPDIR)/libglpk_la-glpmpl05.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl05.c' object='libglpk_la-glpmpl05.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl05.lo `test -f 'glpmpl05.c' || echo '$(srcdir)/'`glpmpl05.c libglpk_la-glpmpl06.lo: glpmpl06.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmpl06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmpl06.Tpo -c -o libglpk_la-glpmpl06.lo `test -f 'glpmpl06.c' || echo '$(srcdir)/'`glpmpl06.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmpl06.Tpo $(DEPDIR)/libglpk_la-glpmpl06.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmpl06.c' object='libglpk_la-glpmpl06.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmpl06.lo `test -f 'glpmpl06.c' || echo '$(srcdir)/'`glpmpl06.c libglpk_la-glpmps.lo: glpmps.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpmps.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpmps.Tpo -c -o libglpk_la-glpmps.lo `test -f 'glpmps.c' || echo '$(srcdir)/'`glpmps.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpmps.Tpo $(DEPDIR)/libglpk_la-glpmps.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpmps.c' object='libglpk_la-glpmps.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpmps.lo `test -f 'glpmps.c' || echo '$(srcdir)/'`glpmps.c libglpk_la-glpnet03.lo: glpnet03.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnet03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnet03.Tpo -c -o libglpk_la-glpnet03.lo `test -f 'glpnet03.c' || echo '$(srcdir)/'`glpnet03.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnet03.Tpo $(DEPDIR)/libglpk_la-glpnet03.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnet03.c' object='libglpk_la-glpnet03.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnet03.lo `test -f 'glpnet03.c' || echo '$(srcdir)/'`glpnet03.c libglpk_la-glpnet04.lo: glpnet04.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnet04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnet04.Tpo -c -o libglpk_la-glpnet04.lo `test -f 'glpnet04.c' || echo '$(srcdir)/'`glpnet04.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnet04.Tpo $(DEPDIR)/libglpk_la-glpnet04.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnet04.c' object='libglpk_la-glpnet04.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnet04.lo `test -f 'glpnet04.c' || echo '$(srcdir)/'`glpnet04.c libglpk_la-glpnet05.lo: glpnet05.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnet05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnet05.Tpo -c -o libglpk_la-glpnet05.lo `test -f 'glpnet05.c' || echo '$(srcdir)/'`glpnet05.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnet05.Tpo $(DEPDIR)/libglpk_la-glpnet05.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnet05.c' object='libglpk_la-glpnet05.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnet05.lo `test -f 'glpnet05.c' || echo '$(srcdir)/'`glpnet05.c libglpk_la-glpnpp01.lo: glpnpp01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp01.Tpo -c -o libglpk_la-glpnpp01.lo `test -f 'glpnpp01.c' || echo '$(srcdir)/'`glpnpp01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp01.Tpo $(DEPDIR)/libglpk_la-glpnpp01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp01.c' object='libglpk_la-glpnpp01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp01.lo `test -f 'glpnpp01.c' || echo '$(srcdir)/'`glpnpp01.c libglpk_la-glpnpp02.lo: glpnpp02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp02.Tpo -c -o libglpk_la-glpnpp02.lo `test -f 'glpnpp02.c' || echo '$(srcdir)/'`glpnpp02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp02.Tpo $(DEPDIR)/libglpk_la-glpnpp02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp02.c' object='libglpk_la-glpnpp02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp02.lo `test -f 'glpnpp02.c' || echo '$(srcdir)/'`glpnpp02.c libglpk_la-glpnpp03.lo: glpnpp03.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp03.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp03.Tpo -c -o libglpk_la-glpnpp03.lo `test -f 'glpnpp03.c' || echo '$(srcdir)/'`glpnpp03.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp03.Tpo $(DEPDIR)/libglpk_la-glpnpp03.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp03.c' object='libglpk_la-glpnpp03.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp03.lo `test -f 'glpnpp03.c' || echo '$(srcdir)/'`glpnpp03.c libglpk_la-glpnpp04.lo: glpnpp04.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp04.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp04.Tpo -c -o libglpk_la-glpnpp04.lo `test -f 'glpnpp04.c' || echo '$(srcdir)/'`glpnpp04.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp04.Tpo $(DEPDIR)/libglpk_la-glpnpp04.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp04.c' object='libglpk_la-glpnpp04.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp04.lo `test -f 'glpnpp04.c' || echo '$(srcdir)/'`glpnpp04.c libglpk_la-glpnpp05.lo: glpnpp05.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp05.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp05.Tpo -c -o libglpk_la-glpnpp05.lo `test -f 'glpnpp05.c' || echo '$(srcdir)/'`glpnpp05.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp05.Tpo $(DEPDIR)/libglpk_la-glpnpp05.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp05.c' object='libglpk_la-glpnpp05.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp05.lo `test -f 'glpnpp05.c' || echo '$(srcdir)/'`glpnpp05.c libglpk_la-glpnpp06.lo: glpnpp06.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpnpp06.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpnpp06.Tpo -c -o libglpk_la-glpnpp06.lo `test -f 'glpnpp06.c' || echo '$(srcdir)/'`glpnpp06.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpnpp06.Tpo $(DEPDIR)/libglpk_la-glpnpp06.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpnpp06.c' object='libglpk_la-glpnpp06.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpnpp06.lo `test -f 'glpnpp06.c' || echo '$(srcdir)/'`glpnpp06.c libglpk_la-glprgr.lo: glprgr.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glprgr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glprgr.Tpo -c -o libglpk_la-glprgr.lo `test -f 'glprgr.c' || echo '$(srcdir)/'`glprgr.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glprgr.Tpo $(DEPDIR)/libglpk_la-glprgr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glprgr.c' object='libglpk_la-glprgr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glprgr.lo `test -f 'glprgr.c' || echo '$(srcdir)/'`glprgr.c libglpk_la-glpscf.lo: glpscf.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpscf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpscf.Tpo -c -o libglpk_la-glpscf.lo `test -f 'glpscf.c' || echo '$(srcdir)/'`glpscf.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpscf.Tpo $(DEPDIR)/libglpk_la-glpscf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpscf.c' object='libglpk_la-glpscf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpscf.lo `test -f 'glpscf.c' || echo '$(srcdir)/'`glpscf.c libglpk_la-glpscl.lo: glpscl.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpscl.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpscl.Tpo -c -o libglpk_la-glpscl.lo `test -f 'glpscl.c' || echo '$(srcdir)/'`glpscl.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpscl.Tpo $(DEPDIR)/libglpk_la-glpscl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpscl.c' object='libglpk_la-glpscl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpscl.lo `test -f 'glpscl.c' || echo '$(srcdir)/'`glpscl.c libglpk_la-glpsdf.lo: glpsdf.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpsdf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpsdf.Tpo -c -o libglpk_la-glpsdf.lo `test -f 'glpsdf.c' || echo '$(srcdir)/'`glpsdf.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpsdf.Tpo $(DEPDIR)/libglpk_la-glpsdf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpsdf.c' object='libglpk_la-glpsdf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpsdf.lo `test -f 'glpsdf.c' || echo '$(srcdir)/'`glpsdf.c libglpk_la-glpspm.lo: glpspm.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspm.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspm.Tpo -c -o libglpk_la-glpspm.lo `test -f 'glpspm.c' || echo '$(srcdir)/'`glpspm.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspm.Tpo $(DEPDIR)/libglpk_la-glpspm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspm.c' object='libglpk_la-glpspm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspm.lo `test -f 'glpspm.c' || echo '$(srcdir)/'`glpspm.c libglpk_la-glpspx01.lo: glpspx01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspx01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspx01.Tpo -c -o libglpk_la-glpspx01.lo `test -f 'glpspx01.c' || echo '$(srcdir)/'`glpspx01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspx01.Tpo $(DEPDIR)/libglpk_la-glpspx01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspx01.c' object='libglpk_la-glpspx01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspx01.lo `test -f 'glpspx01.c' || echo '$(srcdir)/'`glpspx01.c libglpk_la-glpspx02.lo: glpspx02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpspx02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpspx02.Tpo -c -o libglpk_la-glpspx02.lo `test -f 'glpspx02.c' || echo '$(srcdir)/'`glpspx02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpspx02.Tpo $(DEPDIR)/libglpk_la-glpspx02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpspx02.c' object='libglpk_la-glpspx02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpspx02.lo `test -f 'glpspx02.c' || echo '$(srcdir)/'`glpspx02.c libglpk_la-glpsql.lo: glpsql.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpsql.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpsql.Tpo -c -o libglpk_la-glpsql.lo `test -f 'glpsql.c' || echo '$(srcdir)/'`glpsql.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpsql.Tpo $(DEPDIR)/libglpk_la-glpsql.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpsql.c' object='libglpk_la-glpsql.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpsql.lo `test -f 'glpsql.c' || echo '$(srcdir)/'`glpsql.c libglpk_la-glpssx01.lo: glpssx01.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpssx01.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpssx01.Tpo -c -o libglpk_la-glpssx01.lo `test -f 'glpssx01.c' || echo '$(srcdir)/'`glpssx01.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpssx01.Tpo $(DEPDIR)/libglpk_la-glpssx01.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpssx01.c' object='libglpk_la-glpssx01.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpssx01.lo `test -f 'glpssx01.c' || echo '$(srcdir)/'`glpssx01.c libglpk_la-glpssx02.lo: glpssx02.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glpssx02.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glpssx02.Tpo -c -o libglpk_la-glpssx02.lo `test -f 'glpssx02.c' || echo '$(srcdir)/'`glpssx02.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glpssx02.Tpo $(DEPDIR)/libglpk_la-glpssx02.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glpssx02.c' object='libglpk_la-glpssx02.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glpssx02.lo `test -f 'glpssx02.c' || echo '$(srcdir)/'`glpssx02.c libglpk_la-glptsp.lo: glptsp.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-glptsp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-glptsp.Tpo -c -o libglpk_la-glptsp.lo `test -f 'glptsp.c' || echo '$(srcdir)/'`glptsp.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-glptsp.Tpo $(DEPDIR)/libglpk_la-glptsp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='glptsp.c' object='libglpk_la-glptsp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-glptsp.lo `test -f 'glptsp.c' || echo '$(srcdir)/'`glptsp.c libglpk_la-amd_1.lo: amd/amd_1.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_1.Tpo -c -o libglpk_la-amd_1.lo `test -f 'amd/amd_1.c' || echo '$(srcdir)/'`amd/amd_1.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_1.Tpo $(DEPDIR)/libglpk_la-amd_1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_1.c' object='libglpk_la-amd_1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_1.lo `test -f 'amd/amd_1.c' || echo '$(srcdir)/'`amd/amd_1.c libglpk_la-amd_2.lo: amd/amd_2.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_2.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_2.Tpo -c -o libglpk_la-amd_2.lo `test -f 'amd/amd_2.c' || echo '$(srcdir)/'`amd/amd_2.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_2.Tpo $(DEPDIR)/libglpk_la-amd_2.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_2.c' object='libglpk_la-amd_2.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_2.lo `test -f 'amd/amd_2.c' || echo '$(srcdir)/'`amd/amd_2.c libglpk_la-amd_aat.lo: amd/amd_aat.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_aat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_aat.Tpo -c -o libglpk_la-amd_aat.lo `test -f 'amd/amd_aat.c' || echo '$(srcdir)/'`amd/amd_aat.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_aat.Tpo $(DEPDIR)/libglpk_la-amd_aat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_aat.c' object='libglpk_la-amd_aat.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_aat.lo `test -f 'amd/amd_aat.c' || echo '$(srcdir)/'`amd/amd_aat.c libglpk_la-amd_control.lo: amd/amd_control.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_control.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_control.Tpo -c -o libglpk_la-amd_control.lo `test -f 'amd/amd_control.c' || echo '$(srcdir)/'`amd/amd_control.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_control.Tpo $(DEPDIR)/libglpk_la-amd_control.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_control.c' object='libglpk_la-amd_control.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_control.lo `test -f 'amd/amd_control.c' || echo '$(srcdir)/'`amd/amd_control.c libglpk_la-amd_defaults.lo: amd/amd_defaults.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_defaults.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_defaults.Tpo -c -o libglpk_la-amd_defaults.lo `test -f 'amd/amd_defaults.c' || echo '$(srcdir)/'`amd/amd_defaults.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_defaults.Tpo $(DEPDIR)/libglpk_la-amd_defaults.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_defaults.c' object='libglpk_la-amd_defaults.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_defaults.lo `test -f 'amd/amd_defaults.c' || echo '$(srcdir)/'`amd/amd_defaults.c libglpk_la-amd_dump.lo: amd/amd_dump.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_dump.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_dump.Tpo -c -o libglpk_la-amd_dump.lo `test -f 'amd/amd_dump.c' || echo '$(srcdir)/'`amd/amd_dump.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_dump.Tpo $(DEPDIR)/libglpk_la-amd_dump.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_dump.c' object='libglpk_la-amd_dump.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_dump.lo `test -f 'amd/amd_dump.c' || echo '$(srcdir)/'`amd/amd_dump.c libglpk_la-amd_info.lo: amd/amd_info.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_info.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_info.Tpo -c -o libglpk_la-amd_info.lo `test -f 'amd/amd_info.c' || echo '$(srcdir)/'`amd/amd_info.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_info.Tpo $(DEPDIR)/libglpk_la-amd_info.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_info.c' object='libglpk_la-amd_info.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_info.lo `test -f 'amd/amd_info.c' || echo '$(srcdir)/'`amd/amd_info.c libglpk_la-amd_order.lo: amd/amd_order.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_order.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_order.Tpo -c -o libglpk_la-amd_order.lo `test -f 'amd/amd_order.c' || echo '$(srcdir)/'`amd/amd_order.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_order.Tpo $(DEPDIR)/libglpk_la-amd_order.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_order.c' object='libglpk_la-amd_order.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_order.lo `test -f 'amd/amd_order.c' || echo '$(srcdir)/'`amd/amd_order.c libglpk_la-amd_post_tree.lo: amd/amd_post_tree.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_post_tree.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_post_tree.Tpo -c -o libglpk_la-amd_post_tree.lo `test -f 'amd/amd_post_tree.c' || echo '$(srcdir)/'`amd/amd_post_tree.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_post_tree.Tpo $(DEPDIR)/libglpk_la-amd_post_tree.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_post_tree.c' object='libglpk_la-amd_post_tree.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_post_tree.lo `test -f 'amd/amd_post_tree.c' || echo '$(srcdir)/'`amd/amd_post_tree.c libglpk_la-amd_postorder.lo: amd/amd_postorder.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_postorder.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_postorder.Tpo -c -o libglpk_la-amd_postorder.lo `test -f 'amd/amd_postorder.c' || echo '$(srcdir)/'`amd/amd_postorder.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_postorder.Tpo $(DEPDIR)/libglpk_la-amd_postorder.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_postorder.c' object='libglpk_la-amd_postorder.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_postorder.lo `test -f 'amd/amd_postorder.c' || echo '$(srcdir)/'`amd/amd_postorder.c libglpk_la-amd_preprocess.lo: amd/amd_preprocess.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_preprocess.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_preprocess.Tpo -c -o libglpk_la-amd_preprocess.lo `test -f 'amd/amd_preprocess.c' || echo '$(srcdir)/'`amd/amd_preprocess.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_preprocess.Tpo $(DEPDIR)/libglpk_la-amd_preprocess.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_preprocess.c' object='libglpk_la-amd_preprocess.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_preprocess.lo `test -f 'amd/amd_preprocess.c' || echo '$(srcdir)/'`amd/amd_preprocess.c libglpk_la-amd_valid.lo: amd/amd_valid.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-amd_valid.lo -MD -MP -MF $(DEPDIR)/libglpk_la-amd_valid.Tpo -c -o libglpk_la-amd_valid.lo `test -f 'amd/amd_valid.c' || echo '$(srcdir)/'`amd/amd_valid.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-amd_valid.Tpo $(DEPDIR)/libglpk_la-amd_valid.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='amd/amd_valid.c' object='libglpk_la-amd_valid.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-amd_valid.lo `test -f 'amd/amd_valid.c' || echo '$(srcdir)/'`amd/amd_valid.c libglpk_la-fhv.lo: bflib/fhv.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fhv.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fhv.Tpo -c -o libglpk_la-fhv.lo `test -f 'bflib/fhv.c' || echo '$(srcdir)/'`bflib/fhv.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fhv.Tpo $(DEPDIR)/libglpk_la-fhv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/fhv.c' object='libglpk_la-fhv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fhv.lo `test -f 'bflib/fhv.c' || echo '$(srcdir)/'`bflib/fhv.c libglpk_la-fhvint.lo: bflib/fhvint.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-fhvint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-fhvint.Tpo -c -o libglpk_la-fhvint.lo `test -f 'bflib/fhvint.c' || echo '$(srcdir)/'`bflib/fhvint.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-fhvint.Tpo $(DEPDIR)/libglpk_la-fhvint.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/fhvint.c' object='libglpk_la-fhvint.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-fhvint.lo `test -f 'bflib/fhvint.c' || echo '$(srcdir)/'`bflib/fhvint.c libglpk_la-luf.lo: bflib/luf.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-luf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-luf.Tpo -c -o libglpk_la-luf.lo `test -f 'bflib/luf.c' || echo '$(srcdir)/'`bflib/luf.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-luf.Tpo $(DEPDIR)/libglpk_la-luf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/luf.c' object='libglpk_la-luf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-luf.lo `test -f 'bflib/luf.c' || echo '$(srcdir)/'`bflib/luf.c libglpk_la-lufint.lo: bflib/lufint.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-lufint.lo -MD -MP -MF $(DEPDIR)/libglpk_la-lufint.Tpo -c -o libglpk_la-lufint.lo `test -f 'bflib/lufint.c' || echo '$(srcdir)/'`bflib/lufint.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-lufint.Tpo $(DEPDIR)/libglpk_la-lufint.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/lufint.c' object='libglpk_la-lufint.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-lufint.lo `test -f 'bflib/lufint.c' || echo '$(srcdir)/'`bflib/lufint.c libglpk_la-sgf.lo: bflib/sgf.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-sgf.lo -MD -MP -MF $(DEPDIR)/libglpk_la-sgf.Tpo -c -o libglpk_la-sgf.lo `test -f 'bflib/sgf.c' || echo '$(srcdir)/'`bflib/sgf.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-sgf.Tpo $(DEPDIR)/libglpk_la-sgf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/sgf.c' object='libglpk_la-sgf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-sgf.lo `test -f 'bflib/sgf.c' || echo '$(srcdir)/'`bflib/sgf.c libglpk_la-sva.lo: bflib/sva.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-sva.lo -MD -MP -MF $(DEPDIR)/libglpk_la-sva.Tpo -c -o libglpk_la-sva.lo `test -f 'bflib/sva.c' || echo '$(srcdir)/'`bflib/sva.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-sva.Tpo $(DEPDIR)/libglpk_la-sva.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='bflib/sva.c' object='libglpk_la-sva.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-sva.lo `test -f 'bflib/sva.c' || echo '$(srcdir)/'`bflib/sva.c libglpk_la-cfg.lo: cglib/cfg.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cfg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cfg.Tpo -c -o libglpk_la-cfg.lo `test -f 'cglib/cfg.c' || echo '$(srcdir)/'`cglib/cfg.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cfg.Tpo $(DEPDIR)/libglpk_la-cfg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cglib/cfg.c' object='libglpk_la-cfg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cfg.lo `test -f 'cglib/cfg.c' || echo '$(srcdir)/'`cglib/cfg.c libglpk_la-cfg1.lo: cglib/cfg1.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-cfg1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-cfg1.Tpo -c -o libglpk_la-cfg1.lo `test -f 'cglib/cfg1.c' || echo '$(srcdir)/'`cglib/cfg1.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-cfg1.Tpo $(DEPDIR)/libglpk_la-cfg1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cglib/cfg1.c' object='libglpk_la-cfg1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-cfg1.lo `test -f 'cglib/cfg1.c' || echo '$(srcdir)/'`cglib/cfg1.c libglpk_la-colamd.lo: colamd/colamd.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-colamd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-colamd.Tpo -c -o libglpk_la-colamd.lo `test -f 'colamd/colamd.c' || echo '$(srcdir)/'`colamd/colamd.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-colamd.Tpo $(DEPDIR)/libglpk_la-colamd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='colamd/colamd.c' object='libglpk_la-colamd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-colamd.lo `test -f 'colamd/colamd.c' || echo '$(srcdir)/'`colamd/colamd.c libglpk_la-alloc.lo: env/alloc.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-alloc.lo -MD -MP -MF $(DEPDIR)/libglpk_la-alloc.Tpo -c -o libglpk_la-alloc.lo `test -f 'env/alloc.c' || echo '$(srcdir)/'`env/alloc.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-alloc.Tpo $(DEPDIR)/libglpk_la-alloc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/alloc.c' object='libglpk_la-alloc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-alloc.lo `test -f 'env/alloc.c' || echo '$(srcdir)/'`env/alloc.c libglpk_la-env.lo: env/env.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-env.lo -MD -MP -MF $(DEPDIR)/libglpk_la-env.Tpo -c -o libglpk_la-env.lo `test -f 'env/env.c' || echo '$(srcdir)/'`env/env.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-env.Tpo $(DEPDIR)/libglpk_la-env.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/env.c' object='libglpk_la-env.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-env.lo `test -f 'env/env.c' || echo '$(srcdir)/'`env/env.c libglpk_la-error.lo: env/error.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-error.lo -MD -MP -MF $(DEPDIR)/libglpk_la-error.Tpo -c -o libglpk_la-error.lo `test -f 'env/error.c' || echo '$(srcdir)/'`env/error.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-error.Tpo $(DEPDIR)/libglpk_la-error.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/error.c' object='libglpk_la-error.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-error.lo `test -f 'env/error.c' || echo '$(srcdir)/'`env/error.c libglpk_la-stdout.lo: env/stdout.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-stdout.lo -MD -MP -MF $(DEPDIR)/libglpk_la-stdout.Tpo -c -o libglpk_la-stdout.lo `test -f 'env/stdout.c' || echo '$(srcdir)/'`env/stdout.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-stdout.Tpo $(DEPDIR)/libglpk_la-stdout.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/stdout.c' object='libglpk_la-stdout.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-stdout.lo `test -f 'env/stdout.c' || echo '$(srcdir)/'`env/stdout.c libglpk_la-time.lo: env/time.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-time.lo -MD -MP -MF $(DEPDIR)/libglpk_la-time.Tpo -c -o libglpk_la-time.lo `test -f 'env/time.c' || echo '$(srcdir)/'`env/time.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-time.Tpo $(DEPDIR)/libglpk_la-time.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/time.c' object='libglpk_la-time.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-time.lo `test -f 'env/time.c' || echo '$(srcdir)/'`env/time.c libglpk_la-tls.lo: env/tls.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-tls.lo -MD -MP -MF $(DEPDIR)/libglpk_la-tls.Tpo -c -o libglpk_la-tls.lo `test -f 'env/tls.c' || echo '$(srcdir)/'`env/tls.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-tls.Tpo $(DEPDIR)/libglpk_la-tls.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='env/tls.c' object='libglpk_la-tls.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-tls.lo `test -f 'env/tls.c' || echo '$(srcdir)/'`env/tls.c libglpk_la-minisat.lo: minisat/minisat.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-minisat.lo -MD -MP -MF $(DEPDIR)/libglpk_la-minisat.Tpo -c -o libglpk_la-minisat.lo `test -f 'minisat/minisat.c' || echo '$(srcdir)/'`minisat/minisat.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-minisat.Tpo $(DEPDIR)/libglpk_la-minisat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='minisat/minisat.c' object='libglpk_la-minisat.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-minisat.lo `test -f 'minisat/minisat.c' || echo '$(srcdir)/'`minisat/minisat.c libglpk_la-bignum.lo: misc/bignum.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-bignum.lo -MD -MP -MF $(DEPDIR)/libglpk_la-bignum.Tpo -c -o libglpk_la-bignum.lo `test -f 'misc/bignum.c' || echo '$(srcdir)/'`misc/bignum.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-bignum.Tpo $(DEPDIR)/libglpk_la-bignum.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/bignum.c' object='libglpk_la-bignum.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-bignum.lo `test -f 'misc/bignum.c' || echo '$(srcdir)/'`misc/bignum.c libglpk_la-dmp.lo: misc/dmp.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-dmp.lo -MD -MP -MF $(DEPDIR)/libglpk_la-dmp.Tpo -c -o libglpk_la-dmp.lo `test -f 'misc/dmp.c' || echo '$(srcdir)/'`misc/dmp.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-dmp.Tpo $(DEPDIR)/libglpk_la-dmp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/dmp.c' object='libglpk_la-dmp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-dmp.lo `test -f 'misc/dmp.c' || echo '$(srcdir)/'`misc/dmp.c libglpk_la-ffalg.lo: misc/ffalg.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-ffalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-ffalg.Tpo -c -o libglpk_la-ffalg.lo `test -f 'misc/ffalg.c' || echo '$(srcdir)/'`misc/ffalg.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-ffalg.Tpo $(DEPDIR)/libglpk_la-ffalg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/ffalg.c' object='libglpk_la-ffalg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-ffalg.lo `test -f 'misc/ffalg.c' || echo '$(srcdir)/'`misc/ffalg.c libglpk_la-jd.lo: misc/jd.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-jd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-jd.Tpo -c -o libglpk_la-jd.lo `test -f 'misc/jd.c' || echo '$(srcdir)/'`misc/jd.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-jd.Tpo $(DEPDIR)/libglpk_la-jd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/jd.c' object='libglpk_la-jd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-jd.lo `test -f 'misc/jd.c' || echo '$(srcdir)/'`misc/jd.c libglpk_la-keller.lo: misc/keller.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-keller.lo -MD -MP -MF $(DEPDIR)/libglpk_la-keller.Tpo -c -o libglpk_la-keller.lo `test -f 'misc/keller.c' || echo '$(srcdir)/'`misc/keller.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-keller.Tpo $(DEPDIR)/libglpk_la-keller.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/keller.c' object='libglpk_la-keller.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-keller.lo `test -f 'misc/keller.c' || echo '$(srcdir)/'`misc/keller.c libglpk_la-mc13d.lo: misc/mc13d.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mc13d.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mc13d.Tpo -c -o libglpk_la-mc13d.lo `test -f 'misc/mc13d.c' || echo '$(srcdir)/'`misc/mc13d.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mc13d.Tpo $(DEPDIR)/libglpk_la-mc13d.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mc13d.c' object='libglpk_la-mc13d.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mc13d.lo `test -f 'misc/mc13d.c' || echo '$(srcdir)/'`misc/mc13d.c libglpk_la-mc21a.lo: misc/mc21a.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-mc21a.lo -MD -MP -MF $(DEPDIR)/libglpk_la-mc21a.Tpo -c -o libglpk_la-mc21a.lo `test -f 'misc/mc21a.c' || echo '$(srcdir)/'`misc/mc21a.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-mc21a.Tpo $(DEPDIR)/libglpk_la-mc21a.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/mc21a.c' object='libglpk_la-mc21a.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-mc21a.lo `test -f 'misc/mc21a.c' || echo '$(srcdir)/'`misc/mc21a.c libglpk_la-okalg.lo: misc/okalg.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-okalg.lo -MD -MP -MF $(DEPDIR)/libglpk_la-okalg.Tpo -c -o libglpk_la-okalg.lo `test -f 'misc/okalg.c' || echo '$(srcdir)/'`misc/okalg.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-okalg.Tpo $(DEPDIR)/libglpk_la-okalg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/okalg.c' object='libglpk_la-okalg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-okalg.lo `test -f 'misc/okalg.c' || echo '$(srcdir)/'`misc/okalg.c libglpk_la-qmd.lo: misc/qmd.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-qmd.lo -MD -MP -MF $(DEPDIR)/libglpk_la-qmd.Tpo -c -o libglpk_la-qmd.lo `test -f 'misc/qmd.c' || echo '$(srcdir)/'`misc/qmd.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-qmd.Tpo $(DEPDIR)/libglpk_la-qmd.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/qmd.c' object='libglpk_la-qmd.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-qmd.lo `test -f 'misc/qmd.c' || echo '$(srcdir)/'`misc/qmd.c libglpk_la-relax4.lo: misc/relax4.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-relax4.lo -MD -MP -MF $(DEPDIR)/libglpk_la-relax4.Tpo -c -o libglpk_la-relax4.lo `test -f 'misc/relax4.c' || echo '$(srcdir)/'`misc/relax4.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-relax4.Tpo $(DEPDIR)/libglpk_la-relax4.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/relax4.c' object='libglpk_la-relax4.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-relax4.lo `test -f 'misc/relax4.c' || echo '$(srcdir)/'`misc/relax4.c libglpk_la-rng.lo: misc/rng.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rng.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rng.Tpo -c -o libglpk_la-rng.lo `test -f 'misc/rng.c' || echo '$(srcdir)/'`misc/rng.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rng.Tpo $(DEPDIR)/libglpk_la-rng.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/rng.c' object='libglpk_la-rng.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rng.lo `test -f 'misc/rng.c' || echo '$(srcdir)/'`misc/rng.c libglpk_la-rng1.lo: misc/rng1.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-rng1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-rng1.Tpo -c -o libglpk_la-rng1.lo `test -f 'misc/rng1.c' || echo '$(srcdir)/'`misc/rng1.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-rng1.Tpo $(DEPDIR)/libglpk_la-rng1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/rng1.c' object='libglpk_la-rng1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-rng1.lo `test -f 'misc/rng1.c' || echo '$(srcdir)/'`misc/rng1.c libglpk_la-triang.lo: misc/triang.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-triang.lo -MD -MP -MF $(DEPDIR)/libglpk_la-triang.Tpo -c -o libglpk_la-triang.lo `test -f 'misc/triang.c' || echo '$(srcdir)/'`misc/triang.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-triang.Tpo $(DEPDIR)/libglpk_la-triang.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/triang.c' object='libglpk_la-triang.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-triang.lo `test -f 'misc/triang.c' || echo '$(srcdir)/'`misc/triang.c libglpk_la-wclique.lo: misc/wclique.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wclique.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wclique.Tpo -c -o libglpk_la-wclique.lo `test -f 'misc/wclique.c' || echo '$(srcdir)/'`misc/wclique.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wclique.Tpo $(DEPDIR)/libglpk_la-wclique.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/wclique.c' object='libglpk_la-wclique.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wclique.lo `test -f 'misc/wclique.c' || echo '$(srcdir)/'`misc/wclique.c libglpk_la-wclique1.lo: misc/wclique1.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-wclique1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-wclique1.Tpo -c -o libglpk_la-wclique1.lo `test -f 'misc/wclique1.c' || echo '$(srcdir)/'`misc/wclique1.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-wclique1.Tpo $(DEPDIR)/libglpk_la-wclique1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc/wclique1.c' object='libglpk_la-wclique1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-wclique1.lo `test -f 'misc/wclique1.c' || echo '$(srcdir)/'`misc/wclique1.c libglpk_la-proxy.lo: proxy/proxy.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-proxy.lo -MD -MP -MF $(DEPDIR)/libglpk_la-proxy.Tpo -c -o libglpk_la-proxy.lo `test -f 'proxy/proxy.c' || echo '$(srcdir)/'`proxy/proxy.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-proxy.Tpo $(DEPDIR)/libglpk_la-proxy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='proxy/proxy.c' object='libglpk_la-proxy.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-proxy.lo `test -f 'proxy/proxy.c' || echo '$(srcdir)/'`proxy/proxy.c libglpk_la-proxy1.lo: proxy/proxy1.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-proxy1.lo -MD -MP -MF $(DEPDIR)/libglpk_la-proxy1.Tpo -c -o libglpk_la-proxy1.lo `test -f 'proxy/proxy1.c' || echo '$(srcdir)/'`proxy/proxy1.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-proxy1.Tpo $(DEPDIR)/libglpk_la-proxy1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='proxy/proxy1.c' object='libglpk_la-proxy1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-proxy1.lo `test -f 'proxy/proxy1.c' || echo '$(srcdir)/'`proxy/proxy1.c libglpk_la-adler32.lo: zlib/adler32.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-adler32.lo -MD -MP -MF $(DEPDIR)/libglpk_la-adler32.Tpo -c -o libglpk_la-adler32.lo `test -f 'zlib/adler32.c' || echo '$(srcdir)/'`zlib/adler32.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-adler32.Tpo $(DEPDIR)/libglpk_la-adler32.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/adler32.c' object='libglpk_la-adler32.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-adler32.lo `test -f 'zlib/adler32.c' || echo '$(srcdir)/'`zlib/adler32.c libglpk_la-compress.lo: zlib/compress.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-compress.lo -MD -MP -MF $(DEPDIR)/libglpk_la-compress.Tpo -c -o libglpk_la-compress.lo `test -f 'zlib/compress.c' || echo '$(srcdir)/'`zlib/compress.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-compress.Tpo $(DEPDIR)/libglpk_la-compress.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/compress.c' object='libglpk_la-compress.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-compress.lo `test -f 'zlib/compress.c' || echo '$(srcdir)/'`zlib/compress.c libglpk_la-crc32.lo: zlib/crc32.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-crc32.lo -MD -MP -MF $(DEPDIR)/libglpk_la-crc32.Tpo -c -o libglpk_la-crc32.lo `test -f 'zlib/crc32.c' || echo '$(srcdir)/'`zlib/crc32.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-crc32.Tpo $(DEPDIR)/libglpk_la-crc32.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/crc32.c' object='libglpk_la-crc32.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-crc32.lo `test -f 'zlib/crc32.c' || echo '$(srcdir)/'`zlib/crc32.c libglpk_la-deflate.lo: zlib/deflate.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-deflate.lo -MD -MP -MF $(DEPDIR)/libglpk_la-deflate.Tpo -c -o libglpk_la-deflate.lo `test -f 'zlib/deflate.c' || echo '$(srcdir)/'`zlib/deflate.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-deflate.Tpo $(DEPDIR)/libglpk_la-deflate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/deflate.c' object='libglpk_la-deflate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-deflate.lo `test -f 'zlib/deflate.c' || echo '$(srcdir)/'`zlib/deflate.c libglpk_la-gzclose.lo: zlib/gzclose.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzclose.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzclose.Tpo -c -o libglpk_la-gzclose.lo `test -f 'zlib/gzclose.c' || echo '$(srcdir)/'`zlib/gzclose.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzclose.Tpo $(DEPDIR)/libglpk_la-gzclose.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzclose.c' object='libglpk_la-gzclose.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzclose.lo `test -f 'zlib/gzclose.c' || echo '$(srcdir)/'`zlib/gzclose.c libglpk_la-gzlib.lo: zlib/gzlib.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzlib.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzlib.Tpo -c -o libglpk_la-gzlib.lo `test -f 'zlib/gzlib.c' || echo '$(srcdir)/'`zlib/gzlib.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzlib.Tpo $(DEPDIR)/libglpk_la-gzlib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzlib.c' object='libglpk_la-gzlib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzlib.lo `test -f 'zlib/gzlib.c' || echo '$(srcdir)/'`zlib/gzlib.c libglpk_la-gzread.lo: zlib/gzread.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzread.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzread.Tpo -c -o libglpk_la-gzread.lo `test -f 'zlib/gzread.c' || echo '$(srcdir)/'`zlib/gzread.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzread.Tpo $(DEPDIR)/libglpk_la-gzread.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzread.c' object='libglpk_la-gzread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzread.lo `test -f 'zlib/gzread.c' || echo '$(srcdir)/'`zlib/gzread.c libglpk_la-gzwrite.lo: zlib/gzwrite.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-gzwrite.lo -MD -MP -MF $(DEPDIR)/libglpk_la-gzwrite.Tpo -c -o libglpk_la-gzwrite.lo `test -f 'zlib/gzwrite.c' || echo '$(srcdir)/'`zlib/gzwrite.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-gzwrite.Tpo $(DEPDIR)/libglpk_la-gzwrite.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/gzwrite.c' object='libglpk_la-gzwrite.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-gzwrite.lo `test -f 'zlib/gzwrite.c' || echo '$(srcdir)/'`zlib/gzwrite.c libglpk_la-inffast.lo: zlib/inffast.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inffast.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inffast.Tpo -c -o libglpk_la-inffast.lo `test -f 'zlib/inffast.c' || echo '$(srcdir)/'`zlib/inffast.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inffast.Tpo $(DEPDIR)/libglpk_la-inffast.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inffast.c' object='libglpk_la-inffast.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inffast.lo `test -f 'zlib/inffast.c' || echo '$(srcdir)/'`zlib/inffast.c libglpk_la-inflate.lo: zlib/inflate.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inflate.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inflate.Tpo -c -o libglpk_la-inflate.lo `test -f 'zlib/inflate.c' || echo '$(srcdir)/'`zlib/inflate.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inflate.Tpo $(DEPDIR)/libglpk_la-inflate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inflate.c' object='libglpk_la-inflate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inflate.lo `test -f 'zlib/inflate.c' || echo '$(srcdir)/'`zlib/inflate.c libglpk_la-inftrees.lo: zlib/inftrees.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-inftrees.lo -MD -MP -MF $(DEPDIR)/libglpk_la-inftrees.Tpo -c -o libglpk_la-inftrees.lo `test -f 'zlib/inftrees.c' || echo '$(srcdir)/'`zlib/inftrees.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-inftrees.Tpo $(DEPDIR)/libglpk_la-inftrees.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/inftrees.c' object='libglpk_la-inftrees.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-inftrees.lo `test -f 'zlib/inftrees.c' || echo '$(srcdir)/'`zlib/inftrees.c libglpk_la-trees.lo: zlib/trees.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-trees.lo -MD -MP -MF $(DEPDIR)/libglpk_la-trees.Tpo -c -o libglpk_la-trees.lo `test -f 'zlib/trees.c' || echo '$(srcdir)/'`zlib/trees.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-trees.Tpo $(DEPDIR)/libglpk_la-trees.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/trees.c' object='libglpk_la-trees.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-trees.lo `test -f 'zlib/trees.c' || echo '$(srcdir)/'`zlib/trees.c libglpk_la-uncompr.lo: zlib/uncompr.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-uncompr.lo -MD -MP -MF $(DEPDIR)/libglpk_la-uncompr.Tpo -c -o libglpk_la-uncompr.lo `test -f 'zlib/uncompr.c' || echo '$(srcdir)/'`zlib/uncompr.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-uncompr.Tpo $(DEPDIR)/libglpk_la-uncompr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/uncompr.c' object='libglpk_la-uncompr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-uncompr.lo `test -f 'zlib/uncompr.c' || echo '$(srcdir)/'`zlib/uncompr.c libglpk_la-zio.lo: zlib/zio.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-zio.lo -MD -MP -MF $(DEPDIR)/libglpk_la-zio.Tpo -c -o libglpk_la-zio.lo `test -f 'zlib/zio.c' || echo '$(srcdir)/'`zlib/zio.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-zio.Tpo $(DEPDIR)/libglpk_la-zio.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/zio.c' object='libglpk_la-zio.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-zio.lo `test -f 'zlib/zio.c' || echo '$(srcdir)/'`zlib/zio.c libglpk_la-zutil.lo: zlib/zutil.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libglpk_la-zutil.lo -MD -MP -MF $(DEPDIR)/libglpk_la-zutil.Tpo -c -o libglpk_la-zutil.lo `test -f 'zlib/zutil.c' || echo '$(srcdir)/'`zlib/zutil.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libglpk_la-zutil.Tpo $(DEPDIR)/libglpk_la-zutil.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zlib/zutil.c' object='libglpk_la-zutil.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libglpk_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libglpk_la-zutil.lo `test -f 'zlib/zutil.c' || echo '$(srcdir)/'`zlib/zutil.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-includeHEADERS: $(include_HEADERS) @$(NORMAL_INSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ done uninstall-includeHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: $(HEADERS) $(SOURCES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-includeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-includeHEADERS install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-includeHEADERS \ uninstall-libLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: glpk-4.52.1/src/minisat/0000755000062000006210000000000012175147600014154 5ustar maomkpasswdglpk-4.52.1/src/minisat/LICENSE0000644000062000006210000000206012175147600015157 0ustar maomkpasswdMiniSat -- Copyright (c) 2005, Niklas Sorensson 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. glpk-4.52.1/src/minisat/minisat.c0000644000062000006210000011176412175147600015776 0ustar maomkpasswd/* minisat.c */ /* Modified by Andrew Makhorin , August 2011 */ /*********************************************************************** * MiniSat -- Copyright (c) 2005, Niklas Sorensson * http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ * * 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. ***********************************************************************/ /* Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko */ #include "env.h" #include "minisat.h" #if 1 /* by mao */ static void *ymalloc(int size) { void *ptr; xassert(size > 0); ptr = malloc(size); if (ptr == NULL) xerror("MiniSat: no memory available\n"); return ptr; } static void *yrealloc(void *ptr, int size) { xassert(size > 0); if (ptr == NULL) ptr = malloc(size); else ptr = realloc(ptr, size); if (ptr == NULL) xerror("MiniSat: no memory available\n"); return ptr; } static void yfree(void *ptr) { xassert(ptr != NULL); free(ptr); return; } #define assert xassert #define printf xprintf #define fflush(f) /* nop */ #define malloc ymalloc #define realloc yrealloc #define free yfree #define inline /* empty */ #endif /*====================================================================*/ /* Debug: */ #if 0 #define VERBOSEDEBUG 1 #endif /* For derivation output (verbosity level 2) */ #define L_IND "%-*d" #define L_ind solver_dlevel(s)*3+3,solver_dlevel(s) #define L_LIT "%sx%d" #define L_lit(p) lit_sign(p)?"~":"", (lit_var(p)) #if 0 /* by mao */ /* Just like 'assert()' but expression will be evaluated in the release version as well. */ static inline void check(int expr) { assert(expr); } #endif #if 0 /* by mao */ static void printlits(lit* begin, lit* end) { int i; for (i = 0; i < end - begin; i++) printf(L_LIT" ",L_lit(begin[i])); } #endif /*====================================================================*/ /* Random numbers: */ /* Returns a random float 0 <= x < 1. Seed must never be 0. */ static inline double drand(double* seed) { int q; *seed *= 1389796; q = (int)(*seed / 2147483647); *seed -= (double)q * 2147483647; return *seed / 2147483647; } /* Returns a random integer 0 <= x < size. Seed must never be 0. */ static inline int irand(double* seed, int size) { return (int)(drand(seed) * size); } /*====================================================================*/ /* Predeclarations: */ static void sort(void** array, int size, int(*comp)(const void *, const void *)); /*====================================================================*/ /* Clause datatype + minor functions: */ #if 0 /* by mao; see minisat.h */ struct clause_t { int size_learnt; lit lits[0]; }; #endif #define clause_size(c) ((c)->size_learnt >> 1) #define clause_begin(c) ((c)->lits) #define clause_learnt(c) ((c)->size_learnt & 1) #define clause_activity(c) \ (*((float*)&(c)->lits[(c)->size_learnt>>1])) #define clause_setactivity(c, a) \ (void)(*((float*)&(c)->lits[(c)->size_learnt>>1]) = (a)) /*====================================================================*/ /* Encode literals in clause pointers: */ #define clause_from_lit(l) \ (clause*)((unsigned long)(l) + (unsigned long)(l) + 1) #define clause_is_lit(c) \ ((unsigned long)(c) & 1) #define clause_read_lit(c) \ (lit)((unsigned long)(c) >> 1) /*====================================================================*/ /* Simple helpers: */ #define solver_dlevel(s) \ (int)veci_size(&(s)->trail_lim) #define solver_read_wlist(s, l) \ (vecp *)(&(s)->wlists[l]) static inline void vecp_remove(vecp* v, void* e) { void** ws = vecp_begin(v); int j = 0; for (; ws[j] != e ; j++); assert(j < vecp_size(v)); for (; j < vecp_size(v)-1; j++) ws[j] = ws[j+1]; vecp_resize(v,vecp_size(v)-1); } /*====================================================================*/ /* Variable order functions: */ static inline void order_update(solver* s, int v) { /* updateorder */ int* orderpos = s->orderpos; double* activity = s->activity; int* heap = veci_begin(&s->order); int i = orderpos[v]; int x = heap[i]; int parent = (i - 1) / 2; assert(s->orderpos[v] != -1); while (i != 0 && activity[x] > activity[heap[parent]]){ heap[i] = heap[parent]; orderpos[heap[i]] = i; i = parent; parent = (i - 1) / 2; } heap[i] = x; orderpos[x] = i; } #define order_assigned(s, v) /* nop */ static inline void order_unassigned(solver* s, int v) { /* undoorder */ int* orderpos = s->orderpos; if (orderpos[v] == -1){ orderpos[v] = veci_size(&s->order); veci_push(&s->order,v); order_update(s,v); } } static int order_select(solver* s, float random_var_freq) { /* selectvar */ int* heap; double* activity; int* orderpos; lbool* values = s->assigns; /* Random decision: */ if (drand(&s->random_seed) < random_var_freq){ int next = irand(&s->random_seed,s->size); assert(next >= 0 && next < s->size); if (values[next] == l_Undef) return next; } /* Activity based decision: */ heap = veci_begin(&s->order); activity = s->activity; orderpos = s->orderpos; while (veci_size(&s->order) > 0){ int next = heap[0]; int size = veci_size(&s->order)-1; int x = heap[size]; veci_resize(&s->order,size); orderpos[next] = -1; if (size > 0){ double act = activity[x]; int i = 0; int child = 1; while (child < size){ if (child+1 < size && activity[heap[child]] < activity[heap[child+1]]) child++; assert(child < size); if (act >= activity[heap[child]]) break; heap[i] = heap[child]; orderpos[heap[i]] = i; i = child; child = 2 * child + 1; } heap[i] = x; orderpos[heap[i]] = i; } if (values[next] == l_Undef) return next; } return var_Undef; } /*====================================================================*/ /* Activity functions: */ static inline void act_var_rescale(solver* s) { double* activity = s->activity; int i; for (i = 0; i < s->size; i++) activity[i] *= 1e-100; s->var_inc *= 1e-100; } static inline void act_var_bump(solver* s, int v) { double* activity = s->activity; if ((activity[v] += s->var_inc) > 1e100) act_var_rescale(s); /* printf("bump %d %f\n", v-1, activity[v]); */ if (s->orderpos[v] != -1) order_update(s,v); } static inline void act_var_decay(solver* s) { s->var_inc *= s->var_decay; } static inline void act_clause_rescale(solver* s) { clause** cs = (clause**)vecp_begin(&s->learnts); int i; for (i = 0; i < vecp_size(&s->learnts); i++){ float a = clause_activity(cs[i]); clause_setactivity(cs[i], a * (float)1e-20); } s->cla_inc *= (float)1e-20; } static inline void act_clause_bump(solver* s, clause *c) { float a = clause_activity(c) + s->cla_inc; clause_setactivity(c,a); if (a > 1e20) act_clause_rescale(s); } static inline void act_clause_decay(solver* s) { s->cla_inc *= s->cla_decay; } /*====================================================================*/ /* Clause functions: */ /* pre: size > 1 && no variable occurs twice */ static clause* clause_new(solver* s, lit* begin, lit* end, int learnt) { int size; clause* c; int i; assert(end - begin > 1); assert(learnt >= 0 && learnt < 2); size = end - begin; c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); c->size_learnt = (size << 1) | learnt; #if 0 /* by mao; meaningless non-portable check */ assert(((unsigned int)c & 1) == 0); #endif for (i = 0; i < size; i++) c->lits[i] = begin[i]; if (learnt) *((float*)&c->lits[size]) = 0.0; assert(begin[0] >= 0); assert(begin[0] < s->size*2); assert(begin[1] >= 0); assert(begin[1] < s->size*2); assert(lit_neg(begin[0]) < s->size*2); assert(lit_neg(begin[1]) < s->size*2); /* vecp_push(solver_read_wlist(s,lit_neg(begin[0])),(void*)c); */ /* vecp_push(solver_read_wlist(s,lit_neg(begin[1])),(void*)c); */ vecp_push(solver_read_wlist(s,lit_neg(begin[0])), (void*)(size > 2 ? c : clause_from_lit(begin[1]))); vecp_push(solver_read_wlist(s,lit_neg(begin[1])), (void*)(size > 2 ? c : clause_from_lit(begin[0]))); return c; } static void clause_remove(solver* s, clause* c) { lit* lits = clause_begin(c); assert(lit_neg(lits[0]) < s->size*2); assert(lit_neg(lits[1]) < s->size*2); /* vecp_remove(solver_read_wlist(s,lit_neg(lits[0])),(void*)c); */ /* vecp_remove(solver_read_wlist(s,lit_neg(lits[1])),(void*)c); */ assert(lits[0] < s->size*2); vecp_remove(solver_read_wlist(s,lit_neg(lits[0])), (void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[1]))); vecp_remove(solver_read_wlist(s,lit_neg(lits[1])), (void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[0]))); if (clause_learnt(c)){ s->stats.learnts--; s->stats.learnts_literals -= clause_size(c); }else{ s->stats.clauses--; s->stats.clauses_literals -= clause_size(c); } free(c); } static lbool clause_simplify(solver* s, clause* c) { lit* lits = clause_begin(c); lbool* values = s->assigns; int i; assert(solver_dlevel(s) == 0); for (i = 0; i < clause_size(c); i++){ lbool sig = !lit_sign(lits[i]); sig += sig - 1; if (values[lit_var(lits[i])] == sig) return l_True; } return l_False; } /*====================================================================*/ /* Minor (solver) functions: */ void solver_setnvars(solver* s,int n) { int var; if (s->cap < n){ while (s->cap < n) s->cap = s->cap*2+1; s->wlists = (vecp*) realloc(s->wlists, sizeof(vecp)*s->cap*2); s->activity = (double*) realloc(s->activity, sizeof(double)*s->cap); s->assigns = (lbool*) realloc(s->assigns, sizeof(lbool)*s->cap); s->orderpos = (int*) realloc(s->orderpos, sizeof(int)*s->cap); s->reasons = (clause**)realloc(s->reasons, sizeof(clause*)*s->cap); s->levels = (int*) realloc(s->levels, sizeof(int)*s->cap); s->tags = (lbool*) realloc(s->tags, sizeof(lbool)*s->cap); s->trail = (lit*) realloc(s->trail, sizeof(lit)*s->cap); } for (var = s->size; var < n; var++){ vecp_new(&s->wlists[2*var]); vecp_new(&s->wlists[2*var+1]); s->activity [var] = 0; s->assigns [var] = l_Undef; s->orderpos [var] = veci_size(&s->order); s->reasons [var] = (clause*)0; s->levels [var] = 0; s->tags [var] = l_Undef; /* does not hold because variables enqueued at top level will not be reinserted in the heap assert(veci_size(&s->order) == var); */ veci_push(&s->order,var); order_update(s, var); } s->size = n > s->size ? n : s->size; } static inline bool enqueue(solver* s, lit l, clause* from) { lbool* values = s->assigns; int v = lit_var(l); lbool val = values[v]; lbool sig; #ifdef VERBOSEDEBUG printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l)); #endif /* lbool */ sig = !lit_sign(l); sig += sig - 1; if (val != l_Undef){ return val == sig; }else{ /* New fact -- store it. */ int* levels; clause** reasons; #ifdef VERBOSEDEBUG printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l)); #endif /* int* */ levels = s->levels; /* clause** */ reasons = s->reasons; values [v] = sig; levels [v] = solver_dlevel(s); reasons[v] = from; s->trail[s->qtail++] = l; order_assigned(s, v); return true; } } static inline void assume(solver* s, lit l){ assert(s->qtail == s->qhead); assert(s->assigns[lit_var(l)] == l_Undef); #ifdef VERBOSEDEBUG printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(l)); #endif veci_push(&s->trail_lim,s->qtail); enqueue(s,l,(clause*)0); } static inline void solver_canceluntil(solver* s, int level) { lit* trail; lbool* values; clause** reasons; int bound; int c; if (solver_dlevel(s) <= level) return; trail = s->trail; values = s->assigns; reasons = s->reasons; bound = (veci_begin(&s->trail_lim))[level]; for (c = s->qtail-1; c >= bound; c--) { int x = lit_var(trail[c]); values [x] = l_Undef; reasons[x] = (clause*)0; } for (c = s->qhead-1; c >= bound; c--) order_unassigned(s,lit_var(trail[c])); s->qhead = s->qtail = bound; veci_resize(&s->trail_lim,level); } static void solver_record(solver* s, veci* cls) { lit* begin = veci_begin(cls); lit* end = begin + veci_size(cls); clause* c = (veci_size(cls) > 1) ? clause_new(s,begin,end,1) : (clause*)0; enqueue(s,*begin,c); assert(veci_size(cls) > 0); if (c != 0) { vecp_push(&s->learnts,c); act_clause_bump(s,c); s->stats.learnts++; s->stats.learnts_literals += veci_size(cls); } } static double solver_progress(solver* s) { lbool* values = s->assigns; int* levels = s->levels; int i; double progress = 0; double F = 1.0 / s->size; for (i = 0; i < s->size; i++) if (values[i] != l_Undef) progress += pow(F, levels[i]); return progress / s->size; } /*====================================================================*/ /* Major methods: */ static bool solver_lit_removable(solver* s, lit l, int minl) { lbool* tags = s->tags; clause** reasons = s->reasons; int* levels = s->levels; int top = veci_size(&s->tagged); assert(lit_var(l) >= 0 && lit_var(l) < s->size); assert(reasons[lit_var(l)] != 0); veci_resize(&s->stack,0); veci_push(&s->stack,lit_var(l)); while (veci_size(&s->stack) > 0){ clause* c; int v = veci_begin(&s->stack)[veci_size(&s->stack)-1]; assert(v >= 0 && v < s->size); veci_resize(&s->stack,veci_size(&s->stack)-1); assert(reasons[v] != 0); c = reasons[v]; if (clause_is_lit(c)){ int v = lit_var(clause_read_lit(c)); if (tags[v] == l_Undef && levels[v] != 0){ if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ veci_push(&s->stack,v); tags[v] = l_True; veci_push(&s->tagged,v); }else{ int* tagged = veci_begin(&s->tagged); int j; for (j = top; j < veci_size(&s->tagged); j++) tags[tagged[j]] = l_Undef; veci_resize(&s->tagged,top); return false; } } }else{ lit* lits = clause_begin(c); int i, j; for (i = 1; i < clause_size(c); i++){ int v = lit_var(lits[i]); if (tags[v] == l_Undef && levels[v] != 0){ if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ veci_push(&s->stack,lit_var(lits[i])); tags[v] = l_True; veci_push(&s->tagged,v); }else{ int* tagged = veci_begin(&s->tagged); for (j = top; j < veci_size(&s->tagged); j++) tags[tagged[j]] = l_Undef; veci_resize(&s->tagged,top); return false; } } } } } return true; } static void solver_analyze(solver* s, clause* c, veci* learnt) { lit* trail = s->trail; lbool* tags = s->tags; clause** reasons = s->reasons; int* levels = s->levels; int cnt = 0; lit p = lit_Undef; int ind = s->qtail-1; lit* lits; int i, j, minl; int* tagged; veci_push(learnt,lit_Undef); do{ assert(c != 0); if (clause_is_lit(c)){ lit q = clause_read_lit(c); assert(lit_var(q) >= 0 && lit_var(q) < s->size); if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ tags[lit_var(q)] = l_True; veci_push(&s->tagged,lit_var(q)); act_var_bump(s,lit_var(q)); if (levels[lit_var(q)] == solver_dlevel(s)) cnt++; else veci_push(learnt,q); } }else{ if (clause_learnt(c)) act_clause_bump(s,c); lits = clause_begin(c); /* printlits(lits,lits+clause_size(c)); printf("\n"); */ for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){ lit q = lits[j]; assert(lit_var(q) >= 0 && lit_var(q) < s->size); if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ tags[lit_var(q)] = l_True; veci_push(&s->tagged,lit_var(q)); act_var_bump(s,lit_var(q)); if (levels[lit_var(q)] == solver_dlevel(s)) cnt++; else veci_push(learnt,q); } } } while (tags[lit_var(trail[ind--])] == l_Undef); p = trail[ind+1]; c = reasons[lit_var(p)]; cnt--; }while (cnt > 0); *veci_begin(learnt) = lit_neg(p); lits = veci_begin(learnt); minl = 0; for (i = 1; i < veci_size(learnt); i++){ int lev = levels[lit_var(lits[i])]; minl |= 1 << (lev & 31); } /* simplify (full) */ for (i = j = 1; i < veci_size(learnt); i++){ if (reasons[lit_var(lits[i])] == 0 || !solver_lit_removable(s,lits[i],minl)) lits[j++] = lits[i]; } /* update size of learnt + statistics */ s->stats.max_literals += veci_size(learnt); veci_resize(learnt,j); s->stats.tot_literals += j; /* clear tags */ tagged = veci_begin(&s->tagged); for (i = 0; i < veci_size(&s->tagged); i++) tags[tagged[i]] = l_Undef; veci_resize(&s->tagged,0); #ifdef DEBUG for (i = 0; i < s->size; i++) assert(tags[i] == l_Undef); #endif #ifdef VERBOSEDEBUG printf(L_IND"Learnt {", L_ind); for (i = 0; i < veci_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i])); #endif if (veci_size(learnt) > 1){ int max_i = 1; int max = levels[lit_var(lits[1])]; lit tmp; for (i = 2; i < veci_size(learnt); i++) if (levels[lit_var(lits[i])] > max){ max = levels[lit_var(lits[i])]; max_i = i; } tmp = lits[1]; lits[1] = lits[max_i]; lits[max_i] = tmp; } #ifdef VERBOSEDEBUG { int lev = veci_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0; printf(" } at level %d\n", lev); } #endif } clause* solver_propagate(solver* s) { lbool* values = s->assigns; clause* confl = (clause*)0; lit* lits; /* printf("solver_propagate\n"); */ while (confl == 0 && s->qtail - s->qhead > 0){ lit p = s->trail[s->qhead++]; vecp* ws = solver_read_wlist(s,p); clause **begin = (clause**)vecp_begin(ws); clause **end = begin + vecp_size(ws); clause **i, **j; s->stats.propagations++; s->simpdb_props--; /* printf("checking lit %d: "L_LIT"\n", veci_size(ws), L_lit(p)); */ for (i = j = begin; i < end; ){ if (clause_is_lit(*i)){ *j++ = *i; if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ confl = s->binary; (clause_begin(confl))[1] = lit_neg(p); (clause_begin(confl))[0] = clause_read_lit(*i++); /* Copy the remaining watches: */ while (i < end) *j++ = *i++; } }else{ lit false_lit; lbool sig; lits = clause_begin(*i); /* Make sure the false literal is data[1]: */ false_lit = lit_neg(p); if (lits[0] == false_lit){ lits[0] = lits[1]; lits[1] = false_lit; } assert(lits[1] == false_lit); /* printf("checking clause: "); printlits(lits, lits+clause_size(*i)); printf("\n"); */ /* If 0th watch is true, then clause is already satisfied. */ sig = !lit_sign(lits[0]); sig += sig - 1; if (values[lit_var(lits[0])] == sig){ *j++ = *i; }else{ /* Look for new watch: */ lit* stop = lits + clause_size(*i); lit* k; for (k = lits + 2; k < stop; k++){ lbool sig = lit_sign(*k); sig += sig - 1; if (values[lit_var(*k)] != sig){ lits[1] = *k; *k = false_lit; vecp_push(solver_read_wlist(s, lit_neg(lits[1])),*i); goto next; } } *j++ = *i; /* Clause is unit under assignment: */ if (!enqueue(s,lits[0], *i)){ confl = *i++; /* Copy the remaining watches: */ while (i < end) *j++ = *i++; } } } next: i++; } s->stats.inspects += j - (clause**)vecp_begin(ws); vecp_resize(ws,j - (clause**)vecp_begin(ws)); } return confl; } static inline int clause_cmp (const void* x, const void* y) { return clause_size((clause*)x) > 2 && (clause_size((clause*)y) == 2 || clause_activity((clause*)x) < clause_activity((clause*)y)) ? -1 : 1; } void solver_reducedb(solver* s) { int i, j; double extra_lim = s->cla_inc / vecp_size(&s->learnts); /* Remove any clause below this activity */ clause** learnts = (clause**)vecp_begin(&s->learnts); clause** reasons = s->reasons; sort(vecp_begin(&s->learnts), vecp_size(&s->learnts), clause_cmp); for (i = j = 0; i < vecp_size(&s->learnts) / 2; i++){ if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i]) clause_remove(s,learnts[i]); else learnts[j++] = learnts[i]; } for (; i < vecp_size(&s->learnts); i++){ if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i] && clause_activity(learnts[i]) < extra_lim) clause_remove(s,learnts[i]); else learnts[j++] = learnts[i]; } /* printf("reducedb deleted %d\n", vecp_size(&s->learnts) - j); */ vecp_resize(&s->learnts,j); } static lbool solver_search(solver* s, int nof_conflicts, int nof_learnts) { int* levels = s->levels; double var_decay = 0.95; double clause_decay = 0.999; double random_var_freq = 0.02; int conflictC = 0; veci learnt_clause; assert(s->root_level == solver_dlevel(s)); s->stats.starts++; s->var_decay = (float)(1 / var_decay ); s->cla_decay = (float)(1 / clause_decay); veci_resize(&s->model,0); veci_new(&learnt_clause); for (;;){ clause* confl = solver_propagate(s); if (confl != 0){ /* CONFLICT */ int blevel; #ifdef VERBOSEDEBUG printf(L_IND"**CONFLICT**\n", L_ind); #endif s->stats.conflicts++; conflictC++; if (solver_dlevel(s) == s->root_level){ veci_delete(&learnt_clause); return l_False; } veci_resize(&learnt_clause,0); solver_analyze(s, confl, &learnt_clause); blevel = veci_size(&learnt_clause) > 1 ? levels[lit_var(veci_begin(&learnt_clause)[1])] : s->root_level; blevel = s->root_level > blevel ? s->root_level : blevel; solver_canceluntil(s,blevel); solver_record(s,&learnt_clause); act_var_decay(s); act_clause_decay(s); }else{ /* NO CONFLICT */ int next; if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ /* Reached bound on number of conflicts: */ s->progress_estimate = solver_progress(s); solver_canceluntil(s,s->root_level); veci_delete(&learnt_clause); return l_Undef; } if (solver_dlevel(s) == 0) /* Simplify the set of problem clauses: */ solver_simplify(s); if (nof_learnts >= 0 && vecp_size(&s->learnts) - s->qtail >= nof_learnts) /* Reduce the set of learnt clauses: */ solver_reducedb(s); /* New variable decision: */ s->stats.decisions++; next = order_select(s,(float)random_var_freq); if (next == var_Undef){ /* Model found: */ lbool* values = s->assigns; int i; for (i = 0; i < s->size; i++) veci_push(&s->model,(int)values[i]); solver_canceluntil(s,s->root_level); veci_delete(&learnt_clause); /* veci apa; veci_new(&apa); for (i = 0; i < s->size; i++) veci_push(&apa,(int)(s->model.ptr[i] == l_True ? toLit(i) : lit_neg(toLit(i)))); printf("model: "); printlits((lit*)apa.ptr, (lit*)apa.ptr + veci_size(&apa)); printf("\n"); veci_delete(&apa); */ return l_True; } assume(s,lit_neg(toLit(next))); } } #if 0 /* by mao; unreachable code */ return l_Undef; /* cannot happen */ #endif } /*====================================================================*/ /* External solver functions: */ solver* solver_new(void) { solver* s = (solver*)malloc(sizeof(solver)); /* initialize vectors */ vecp_new(&s->clauses); vecp_new(&s->learnts); veci_new(&s->order); veci_new(&s->trail_lim); veci_new(&s->tagged); veci_new(&s->stack); veci_new(&s->model); /* initialize arrays */ s->wlists = 0; s->activity = 0; s->assigns = 0; s->orderpos = 0; s->reasons = 0; s->levels = 0; s->tags = 0; s->trail = 0; /* initialize other vars */ s->size = 0; s->cap = 0; s->qhead = 0; s->qtail = 0; s->cla_inc = 1; s->cla_decay = 1; s->var_inc = 1; s->var_decay = 1; s->root_level = 0; s->simpdb_assigns = 0; s->simpdb_props = 0; s->random_seed = 91648253; s->progress_estimate = 0; s->binary = (clause*)malloc(sizeof(clause) + sizeof(lit)*2); s->binary->size_learnt = (2 << 1); s->verbosity = 0; s->stats.starts = 0; s->stats.decisions = 0; s->stats.propagations = 0; s->stats.inspects = 0; s->stats.conflicts = 0; s->stats.clauses = 0; s->stats.clauses_literals = 0; s->stats.learnts = 0; s->stats.learnts_literals = 0; s->stats.max_literals = 0; s->stats.tot_literals = 0; return s; } void solver_delete(solver* s) { int i; for (i = 0; i < vecp_size(&s->clauses); i++) free(vecp_begin(&s->clauses)[i]); for (i = 0; i < vecp_size(&s->learnts); i++) free(vecp_begin(&s->learnts)[i]); /* delete vectors */ vecp_delete(&s->clauses); vecp_delete(&s->learnts); veci_delete(&s->order); veci_delete(&s->trail_lim); veci_delete(&s->tagged); veci_delete(&s->stack); veci_delete(&s->model); free(s->binary); /* delete arrays */ if (s->wlists != 0){ int i; for (i = 0; i < s->size*2; i++) vecp_delete(&s->wlists[i]); /* if one is different from null, all are */ free(s->wlists); free(s->activity ); free(s->assigns ); free(s->orderpos ); free(s->reasons ); free(s->levels ); free(s->trail ); free(s->tags ); } free(s); } bool solver_addclause(solver* s, lit* begin, lit* end) { lit *i,*j; int maxvar; lbool* values; lit last; if (begin == end) return false; /* printlits(begin,end); printf("\n"); */ /* insertion sort */ maxvar = lit_var(*begin); for (i = begin + 1; i < end; i++){ lit l = *i; maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; for (j = i; j > begin && *(j-1) > l; j--) *j = *(j-1); *j = l; } solver_setnvars(s,maxvar+1); /* printlits(begin,end); printf("\n"); */ values = s->assigns; /* delete duplicates */ last = lit_Undef; for (i = j = begin; i < end; i++){ /* printf("lit: "L_LIT", value = %d\n", L_lit(*i), (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)])); */ lbool sig = !lit_sign(*i); sig += sig - 1; if (*i == lit_neg(last) || sig == values[lit_var(*i)]) return true; /* tautology */ else if (*i != last && values[lit_var(*i)] == l_Undef) last = *j++ = *i; } /* printf("final: "); printlits(begin,j); printf("\n"); */ if (j == begin) /* empty clause */ return false; else if (j - begin == 1) /* unit clause */ return enqueue(s,*begin,(clause*)0); /* create new clause */ vecp_push(&s->clauses,clause_new(s,begin,j,0)); s->stats.clauses++; s->stats.clauses_literals += j - begin; return true; } bool solver_simplify(solver* s) { clause** reasons; int type; assert(solver_dlevel(s) == 0); if (solver_propagate(s) != 0) return false; if (s->qhead == s->simpdb_assigns || s->simpdb_props > 0) return true; reasons = s->reasons; for (type = 0; type < 2; type++){ vecp* cs = type ? &s->learnts : &s->clauses; clause** cls = (clause**)vecp_begin(cs); int i, j; for (j = i = 0; i < vecp_size(cs); i++){ if (reasons[lit_var(*clause_begin(cls[i]))] != cls[i] && clause_simplify(s,cls[i]) == l_True) clause_remove(s,cls[i]); else cls[j++] = cls[i]; } vecp_resize(cs,j); } s->simpdb_assigns = s->qhead; /* (shouldn't depend on 'stats' really, but it will do for now) */ s->simpdb_props = (int)(s->stats.clauses_literals + s->stats.learnts_literals); return true; } bool solver_solve(solver* s, lit* begin, lit* end) { double nof_conflicts = 100; double nof_learnts = solver_nclauses(s) / 3; lbool status = l_Undef; lbool* values = s->assigns; lit* i; /* printf("solve: "); printlits(begin, end); printf("\n"); */ for (i = begin; i < end; i++){ switch (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]){ case 1: /* l_True: */ break; case 0: /* l_Undef */ assume(s, *i); if (solver_propagate(s) == NULL) break; /* falltrough */ case -1: /* l_False */ solver_canceluntil(s, 0); return false; } } s->root_level = solver_dlevel(s); if (s->verbosity >= 1){ printf("==================================[MINISAT]============" "=======================\n"); printf("| Conflicts | ORIGINAL | LEARNT " " | Progress |\n"); printf("| | Clauses Literals | Limit Clauses Litera" "ls Lit/Cl | |\n"); printf("=======================================================" "=======================\n"); } while (status == l_Undef){ double Ratio = (s->stats.learnts == 0)? 0.0 : s->stats.learnts_literals / (double)s->stats.learnts; if (s->verbosity >= 1){ printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %" "6.3f %% |\n", (double)s->stats.conflicts, (double)s->stats.clauses, (double)s->stats.clauses_literals, (double)nof_learnts, (double)s->stats.learnts, (double)s->stats.learnts_literals, Ratio, s->progress_estimate*100); fflush(stdout); } status = solver_search(s,(int)nof_conflicts, (int)nof_learnts); nof_conflicts *= 1.5; nof_learnts *= 1.1; } if (s->verbosity >= 1) printf("=======================================================" "=======================\n"); solver_canceluntil(s,0); return status != l_False; } int solver_nvars(solver* s) { return s->size; } int solver_nclauses(solver* s) { return vecp_size(&s->clauses); } int solver_nconflicts(solver* s) { return (int)s->stats.conflicts; } /*====================================================================*/ /* Sorting functions (sigh): */ static inline void selectionsort(void** array, int size, int(*comp)(const void *, const void *)) { int i, j, best_i; void* tmp; for (i = 0; i < size-1; i++){ best_i = i; for (j = i+1; j < size; j++){ if (comp(array[j], array[best_i]) < 0) best_i = j; } tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; } } static void sortrnd(void** array, int size, int(*comp)(const void *, const void *), double* seed) { if (size <= 15) selectionsort(array, size, comp); else{ void* pivot = array[irand(seed, size)]; void* tmp; int i = -1; int j = size; for(;;){ do i++; while(comp(array[i], pivot)<0); do j--; while(comp(pivot, array[j])<0); if (i >= j) break; tmp = array[i]; array[i] = array[j]; array[j] = tmp; } sortrnd(array , i , comp, seed); sortrnd(&array[i], size-i, comp, seed); } } static void sort(void** array, int size, int(*comp)(const void *, const void *)) { double seed = 91648253; sortrnd(array,size,comp,&seed); } /* eof */ glpk-4.52.1/src/minisat/minisat.h0000644000062000006210000001617612175147600016004 0ustar maomkpasswd/* minisat.h */ /* Modified by Andrew Makhorin , August 2011 */ /*********************************************************************** * MiniSat -- Copyright (c) 2005, Niklas Sorensson * http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ * * 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. ***********************************************************************/ /* Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko */ #ifndef MINISAT_H #define MINISAT_H /*====================================================================*/ /* Simple types: */ typedef int bool; #define true 1 #define false 0 typedef int lit; #if 0 /* by mao */ typedef char lbool; #else typedef int lbool; #endif #define var_Undef (int)(-1) #define lit_Undef (lit)(-2) #define l_Undef (lbool)0 #define l_True (lbool)1 #define l_False (lbool)(-1) #define toLit(v) (lit)((v) + (v)) #define lit_neg(l) (lit)((l) ^ 1) #define lit_var(l) (int)((l) >> 1) #define lit_sign(l) (int)((l) & 1) /*====================================================================*/ /* Vectors: */ /* vector of 32-bit intergers (added for 64-bit portability) */ typedef struct /* veci_t */ { int size; int cap; int* ptr; } veci; #define veci_new(v) \ { (v)->size = 0; \ (v)->cap = 4; \ (v)->ptr = (int*)malloc(sizeof(int)*(v)->cap); \ } #define veci_delete(v) free((v)->ptr) #define veci_begin(v) ((v)->ptr) #define veci_size(v) ((v)->size) #define veci_resize(v, k) (void)((v)->size = (k)) /* only safe to shrink !! */ #define veci_push(v, e) \ { if ((v)->size == (v)->cap) \ { int newsize = (v)->cap * 2+1; \ (v)->ptr = (int*)realloc((v)->ptr,sizeof(int)*newsize); \ (v)->cap = newsize; \ } \ (v)->ptr[(v)->size++] = (e); \ } /* vector of 32- or 64-bit pointers */ typedef struct /* vecp_t */ { int size; int cap; void** ptr; } vecp; #define vecp_new(v) \ { (v)->size = 0; \ (v)->cap = 4; \ (v)->ptr = (void**)malloc(sizeof(void*)*(v)->cap); \ } #define vecp_delete(v) free((v)->ptr) #define vecp_begin(v) ((v)->ptr) #define vecp_size(v) ((v)->size) #define vecp_resize(v, k) (void)((v)->size = (k)) /* only safe to shrink !! */ #define vecp_push(v, e) \ { if ((v)->size == (v)->cap) \ { int newsize = (v)->cap * 2+1; \ (v)->ptr = (void**)realloc((v)->ptr,sizeof(void*)*newsize); \ (v)->cap = newsize; \ } \ (v)->ptr[(v)->size++] = (e); \ } /*====================================================================*/ /* Solver representation: */ typedef struct /* clause_t */ { int size_learnt; lit lits[1]; } clause; typedef struct /* stats_t */ { double starts, decisions, propagations, inspects, conflicts; double clauses, clauses_literals, learnts, learnts_literals, max_literals, tot_literals; } stats; typedef struct /* solver_t */ { int size; /* nof variables */ int cap; /* size of varmaps */ int qhead; /* Head index of queue. */ int qtail; /* Tail index of queue. */ /* clauses */ vecp clauses; /* List of problem constraints. (contains: clause*) */ vecp learnts; /* List of learnt clauses. (contains: clause*) */ /* activities */ double var_inc; /* Amount to bump next variable with. */ double var_decay; /* INVERSE decay factor for variable activity: stores 1/decay. */ float cla_inc; /* Amount to bump next clause with. */ float cla_decay; /* INVERSE decay factor for clause activity: stores 1/decay. */ vecp* wlists; double* activity; /* A heuristic measurement of the activity of a variable. */ lbool* assigns; /* Current values of variables. */ int* orderpos; /* Index in variable order. */ clause** reasons; int* levels; lit* trail; clause* binary; /* A temporary binary clause */ lbool* tags; veci tagged; /* (contains: var) */ veci stack; /* (contains: var) */ veci order; /* Variable order. (heap) (contains: var) */ veci trail_lim; /* Separator indices for different decision levels in 'trail'. (contains: int) */ veci model; /* If problem is solved, this vector contains the model (contains: lbool). */ int root_level; /* Level of first proper decision. */ int simpdb_assigns;/* Number of top-level assignments at last 'simplifyDB()'. */ int simpdb_props; /* Number of propagations before next 'simplifyDB()'. */ double random_seed; double progress_estimate; int verbosity; /* Verbosity level. 0=silent, 1=some progress report, 2=everything */ stats stats; } solver; /*====================================================================*/ /* Public interface: */ #if 1 /* by mao; to keep namespace clean */ #define solver_new _glp_minisat_new #define solver_delete _glp_minisat_delete #define solver_addclause _glp_minisat_addclause #define solver_simplify _glp_minisat_simplify #define solver_solve _glp_minisat_solve #define solver_nvars _glp_minisat_nvars #define solver_nclauses _glp_minisat_nclauses #define solver_nconflicts _glp_minisat_nconflicts #define solver_setnvars _glp_minisat_setnvars #define solver_propagate _glp_minisat_propagate #define solver_reducedb _glp_minisat_reducedb #endif solver* solver_new(void); void solver_delete(solver* s); bool solver_addclause(solver* s, lit* begin, lit* end); bool solver_simplify(solver* s); bool solver_solve(solver* s, lit* begin, lit* end); int solver_nvars(solver* s); int solver_nclauses(solver* s); int solver_nconflicts(solver* s); void solver_setnvars(solver* s,int n); #endif /* eof */ glpk-4.52.1/src/minisat/README0000644000062000006210000000160712175147600015040 0ustar maomkpasswdNOTE: Files in this subdirectory are NOT part of the GLPK package, but are used with GLPK. The original code was modified according to GLPK requirements by Andrew Makhorin . ************************************************************************ MiniSat-C v1.14.1 ======================================== * Fixed some serious bugs. * Tweaked to be Visual Studio friendly (by Alan Mishchenko). This disabled reading of gzipped DIMACS files and signal handling, but none of these features are essential (and easy to re-enable, if wanted). MiniSat-C v1.14 ======================================== Ok, we get it. You hate C++. You hate templates. We agree; C++ is a seriously messed up language. Although we are more pragmatic about the quirks and maldesigns in C++, we sympathize with you. So here is a pure C version of MiniSat, put together by Niklas Sorensson. glpk-4.52.1/src/misc/0000755000062000006210000000000012175147600013443 5ustar maomkpasswdglpk-4.52.1/src/misc/bignum.c0000644000062000006210000002246312175147600015077 0ustar maomkpasswd/* bignum.c (bignum arithmetic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2006, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "bignum.h" /*********************************************************************** * Two routines below are intended to multiply and divide unsigned * integer numbers of arbitrary precision. * * The routines assume that an unsigned integer number is represented in * the positional numeral system with the base 2^16 = 65536, i.e. each * "digit" of the number is in the range [0, 65535] and represented as * a 16-bit value of the unsigned short type. In other words, a number x * has the following representation: * * n-1 * x = sum d[j] * 65536^j, * j=0 * * where n is the number of places (positions), and d[j] is j-th "digit" * of x, 0 <= d[j] <= 65535. ***********************************************************************/ /*********************************************************************** * NAME * * bigmul - multiply unsigned integer numbers of arbitrary precision * * SYNOPSIS * * #include "bignum.h" * void bigmul(int n, int m, unsigned short x[], unsigned short y[]); * * DESCRIPTION * * The routine bigmul multiplies unsigned integer numbers of arbitrary * precision. * * n is the number of digits of multiplicand, n >= 1; * * m is the number of digits of multiplier, m >= 1; * * x is an array containing digits of the multiplicand in elements * x[m], x[m+1], ..., x[n+m-1]. Contents of x[0], x[1], ..., x[m-1] are * ignored on entry. * * y is an array containing digits of the multiplier in elements y[0], * y[1], ..., y[m-1]. * * On exit digits of the product are stored in elements x[0], x[1], ..., * x[n+m-1]. The array y is not changed. */ void bigmul(int n, int m, unsigned short x[], unsigned short y[]) { int i, j; unsigned int t; xassert(n >= 1); xassert(m >= 1); for (j = 0; j < m; j++) x[j] = 0; for (i = 0; i < n; i++) { if (x[i+m]) { t = 0; for (j = 0; j < m; j++) { t += (unsigned int)x[i+m] * (unsigned int)y[j] + (unsigned int)x[i+j]; x[i+j] = (unsigned short)t; t >>= 16; } x[i+m] = (unsigned short)t; } } return; } /*********************************************************************** * NAME * * bigdiv - divide unsigned integer numbers of arbitrary precision * * SYNOPSIS * * #include "bignum.h" * void bigdiv(int n, int m, unsigned short x[], unsigned short y[]); * * DESCRIPTION * * The routine bigdiv divides one unsigned integer number of arbitrary * precision by another with the algorithm described in [1]. * * n is the difference between the number of digits of dividend and the * number of digits of divisor, n >= 0. * * m is the number of digits of divisor, m >= 1. * * x is an array containing digits of the dividend in elements x[0], * x[1], ..., x[n+m-1]. * * y is an array containing digits of the divisor in elements y[0], * y[1], ..., y[m-1]. The highest digit y[m-1] must be non-zero. * * On exit n+1 digits of the quotient are stored in elements x[m], * x[m+1], ..., x[n+m], and m digits of the remainder are stored in * elements x[0], x[1], ..., x[m-1]. The array y is changed but then * restored. * * REFERENCES * * 1. D. Knuth. The Art of Computer Programming. Vol. 2: Seminumerical * Algorithms. Stanford University, 1969. */ void bigdiv(int n, int m, unsigned short x[], unsigned short y[]) { int i, j; unsigned int t; unsigned short d, q, r; xassert(n >= 0); xassert(m >= 1); xassert(y[m-1] != 0); /* special case when divisor has the only digit */ if (m == 1) { d = 0; for (i = n; i >= 0; i--) { t = ((unsigned int)d << 16) + (unsigned int)x[i]; x[i+1] = (unsigned short)(t / y[0]); d = (unsigned short)(t % y[0]); } x[0] = d; goto done; } /* multiply dividend and divisor by a normalizing coefficient in * order to provide the condition y[m-1] >= base / 2 */ d = (unsigned short)(0x10000 / ((unsigned int)y[m-1] + 1)); if (d == 1) x[n+m] = 0; else { t = 0; for (i = 0; i < n+m; i++) { t += (unsigned int)x[i] * (unsigned int)d; x[i] = (unsigned short)t; t >>= 16; } x[n+m] = (unsigned short)t; t = 0; for (j = 0; j < m; j++) { t += (unsigned int)y[j] * (unsigned int)d; y[j] = (unsigned short)t; t >>= 16; } } /* main loop */ for (i = n; i >= 0; i--) { /* estimate and correct the current digit of quotient */ if (x[i+m] < y[m-1]) { t = ((unsigned int)x[i+m] << 16) + (unsigned int)x[i+m-1]; q = (unsigned short)(t / (unsigned int)y[m-1]); r = (unsigned short)(t % (unsigned int)y[m-1]); if (q == 0) goto putq; else goto test; } q = 0; r = x[i+m-1]; decr: q--; /* if q = 0 then q-- = 0xFFFF */ t = (unsigned int)r + (unsigned int)y[m-1]; r = (unsigned short)t; if (t > 0xFFFF) goto msub; test: t = (unsigned int)y[m-2] * (unsigned int)q; if ((unsigned short)(t >> 16) > r) goto decr; if ((unsigned short)(t >> 16) < r) goto msub; if ((unsigned short)t > x[i+m-2]) goto decr; msub: /* now subtract divisor multiplied by the current digit of * quotient from the current dividend */ if (q == 0) goto putq; t = 0; for (j = 0; j < m; j++) { t += (unsigned int)y[j] * (unsigned int)q; if (x[i+j] < (unsigned short)t) t += 0x10000; x[i+j] -= (unsigned short)t; t >>= 16; } if (x[i+m] >= (unsigned short)t) goto putq; /* perform correcting addition, because the current digit of * quotient is greater by one than its correct value */ q--; t = 0; for (j = 0; j < m; j++) { t += (unsigned int)x[i+j] + (unsigned int)y[j]; x[i+j] = (unsigned short)t; t >>= 16; } putq: /* store the current digit of quotient */ x[i+m] = q; } /* divide divisor and remainder by the normalizing coefficient in * order to restore their original values */ if (d > 1) { t = 0; for (i = m-1; i >= 0; i--) { t = (t << 16) + (unsigned int)x[i]; x[i] = (unsigned short)(t / (unsigned int)d); t %= (unsigned int)d; } t = 0; for (j = m-1; j >= 0; j--) { t = (t << 16) + (unsigned int)y[j]; y[j] = (unsigned short)(t / (unsigned int)d); t %= (unsigned int)d; } } done: return; } /**********************************************************************/ #ifdef GLP_TEST #include #include #include #include "rng.h" #define N_MAX 7 /* maximal number of digits in multiplicand */ #define M_MAX 5 /* maximal number of digits in multiplier */ #define N_TEST 1000000 /* number of tests */ int main(void) { RNG *rand; int d, j, n, m, test; unsigned short x[N_MAX], y[M_MAX], z[N_MAX+M_MAX]; rand = rng_create_rand(); for (test = 1; test <= N_TEST; test++) { /* x[0,...,n-1] := multiplicand */ n = 1 + rng_unif_rand(rand, N_MAX-1); assert(1 <= n && n <= N_MAX); for (j = 0; j < n; j++) { d = rng_unif_rand(rand, 65536); assert(0 <= d && d <= 65535); x[j] = (unsigned short)d; } /* y[0,...,m-1] := multiplier */ m = 1 + rng_unif_rand(rand, M_MAX-1); assert(1 <= m && m <= M_MAX); for (j = 0; j < m; j++) { d = rng_unif_rand(rand, 65536); assert(0 <= d && d <= 65535); y[j] = (unsigned short)d; } if (y[m-1] == 0) y[m-1] = 1; /* z[0,...,n+m-1] := x * y */ for (j = 0; j < n; j++) z[m+j] = x[j]; bigmul(n, m, z, y); /* z[0,...,m-1] := z mod y, z[m,...,n+m-1] := z div y */ bigdiv(n, m, z, y); /* z mod y must be 0 */ for (j = 0; j < m; j++) assert(z[j] == 0); /* z div y must be x */ for (j = 0; j < n; j++) assert(z[m+j] == x[j]); } fprintf(stderr, "%d tests successfully passed\n", N_TEST); rng_delete_rand(rand); return 0; } #endif /* eof */ glpk-4.52.1/src/misc/bignum.h0000644000062000006210000000261212175147600015076 0ustar maomkpasswd/* bignum.h (arbitrary precision arithmetic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2006, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef BIGNUM_H #define BIGNUM_H #define bigmul _glp_bigmul void bigmul(int n, int m, unsigned short x[], unsigned short y[]); /* multiply unsigned integer numbers of arbitrary precision */ #define bigdiv _glp_bigdiv void bigdiv(int n, int m, unsigned short x[], unsigned short y[]); /* divide unsigned integer numbers of arbitrary precision */ #endif /* eof */ glpk-4.52.1/src/misc/dmp.c0000644000062000006210000001572712175147600014403 0ustar maomkpasswd/* dmp.c (dynamic memory pool) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "dmp.h" struct DMP { /* dynamic memory pool */ void *avail[32]; /* avail[k], 0 <= k <= 31, is a pointer to first available (free) * atom of (k+1)*8 bytes long; at the beginning of each free atom * there is a pointer to another free atom of the same size */ void *block; /* pointer to most recently allocated memory block; at the * beginning of each allocated memory block there is a pointer to * previously allocated memory block */ int used; /* number of bytes used in most recently allocated memory block */ size_t count; /* number of atoms which are currently in use */ }; #define DMP_BLK_SIZE 8000 /* size of memory blocks, in bytes, allocated for memory pools */ struct prefix { /* atom prefix (for debugging only) */ DMP *pool; /* dynamic memory pool */ int size; /* original atom size, in bytes */ }; #define prefix_size ((sizeof(struct prefix) + 7) & ~7) /* size of atom prefix rounded up to multiple of 8 bytes */ int dmp_debug; /* debug mode flag */ /*********************************************************************** * NAME * * dmp_create_pool - create dynamic memory pool * * SYNOPSIS * * #include "dmp.h" * DMP *dmp_create_pool(void); * * DESCRIPTION * * The routine dmp_create_pool creates a dynamic memory pool. * * RETURNS * * The routine returns a pointer to the memory pool created. */ DMP *dmp_create_pool(void) { DMP *pool; int k; xassert(sizeof(void *) <= 8); if (dmp_debug) xprintf("dmp_create_pool: warning: debug mode is on\n"); pool = talloc(1, DMP); for (k = 0; k <= 31; k++) pool->avail[k] = NULL; pool->block = NULL; pool->used = DMP_BLK_SIZE; pool->count = 0; return pool; } /*********************************************************************** * NAME * * dmp_get_atom - get free atom from dynamic memory pool * * SYNOPSIS * * #include "dmp.h" * void *dmp_get_atom(DMP *pool, int size); * * DESCRIPTION * * The routine dmp_get_atom obtains a free atom (memory space) from the * specified memory pool. * * The parameter size is the atom size, in bytes, 1 <= size <= 256. * * Note that the free atom contains arbitrary data, not binary zeros. * * RETURNS * * The routine returns a pointer to the free atom obtained. */ void *dmp_get_atom(DMP *pool, int size) { void *atom; int k, need; xassert(1 <= size && size <= 256); /* round up atom size to multiple of 8 bytes */ need = (size + 7) & ~7; /* determine number of corresponding list of free atoms */ k = (need >> 3) - 1; /* obtain free atom */ if (pool->avail[k] == NULL) { /* corresponding list of free atoms is empty */ /* if debug mode is on, add atom prefix size */ if (dmp_debug) need += prefix_size; if (pool->used + need > DMP_BLK_SIZE) { /* allocate new memory block */ void *block = talloc(DMP_BLK_SIZE, char); *(void **)block = pool->block; pool->block = block; pool->used = 8; /* sufficient to store pointer */ } /* allocate new atom in current memory block */ atom = (char *)pool->block + pool->used; pool->used += need; } else { /* obtain atom from corresponding list of free atoms */ atom = pool->avail[k]; pool->avail[k] = *(void **)atom; } /* if debug mode is on, fill atom prefix */ if (dmp_debug) { ((struct prefix *)atom)->pool = pool; ((struct prefix *)atom)->size = size; atom = (char *)atom + prefix_size; } /* increase number of allocated atoms */ pool->count++; return atom; } /*********************************************************************** * NAME * * dmp_free_atom - return atom to dynamic memory pool * * SYNOPSIS * * #include "dmp.h" * void dmp_free_atom(DMP *pool, void *atom, int size); * * DESCRIPTION * * The routine dmp_free_atom returns the specified atom (memory space) * to the specified memory pool, making the atom free. * * The parameter size is the atom size, in bytes, 1 <= size <= 256. * * Note that the atom can be returned only to the pool, from which it * was obtained, and its size must be exactly the same as on obtaining * it from the pool. */ void dmp_free_atom(DMP *pool, void *atom, int size) { int k; xassert(1 <= size && size <= 256); /* determine number of corresponding list of free atoms */ k = ((size + 7) >> 3) - 1; /* if debug mode is on, check atom prefix */ if (dmp_debug) { atom = (char *)atom - prefix_size; xassert(((struct prefix *)atom)->pool == pool); xassert(((struct prefix *)atom)->size == size); } /* return atom to corresponding list of free atoms */ *(void **)atom = pool->avail[k]; pool->avail[k] = atom; /* decrease number of allocated atoms */ xassert(pool->count > 0); pool->count--; return; } /*********************************************************************** * NAME * * dmp_in_use - determine how many atoms are still in use * * SYNOPSIS * * #include "dmp.h" * size_t dmp_in_use(DMP *pool); * * RETURNS * * The routine returns the number of atoms of the specified memory pool * which are still in use. */ size_t dmp_in_use(DMP *pool) { return pool->count; } /*********************************************************************** * NAME * * dmp_delete_pool - delete dynamic memory pool * * SYNOPSIS * * #include "dmp.h" * void dmp_delete_pool(DMP *pool); * * DESCRIPTION * * The routine dmp_delete_pool deletes the specified dynamic memory * pool freeing all the memory allocated to this object. */ void dmp_delete_pool(DMP *pool) { while (pool->block != NULL) { void *block = pool->block; pool->block = *(void **)block; tfree(block); } tfree(pool); return; } /* eof */ glpk-4.52.1/src/misc/dmp.h0000644000062000006210000000365612175147600014406 0ustar maomkpasswd/* dmp.h (dynamic memory pool) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef DMP_H #define DMP_H #include "stdc.h" typedef struct DMP DMP; #define dmp_debug _glp_dmp_debug extern int dmp_debug; /* debug mode flag */ #define dmp_create_pool _glp_dmp_create_pool DMP *dmp_create_pool(void); /* create dynamic memory pool */ #define dmp_talloc(pool, type) \ ((type *)dmp_get_atom(pool, sizeof(type))) #define dmp_get_atom _glp_dmp_get_atom void *dmp_get_atom(DMP *pool, int size); /* get free atom from dynamic memory pool */ #define dmp_tfree(pool, atom) \ dmp_free_atom(pool, atom, sizeof(*(atom))) #define dmp_free_atom _glp_dmp_free_atom void dmp_free_atom(DMP *pool, void *atom, int size); /* return atom to dynamic memory pool */ #define dmp_in_use _glp_dmp_in_use size_t dmp_in_use(DMP *pool); /* determine how many atoms are still in use */ #define dmp_delete_pool _glp_dmp_delete_pool void dmp_delete_pool(DMP *pool); /* delete dynamic memory pool */ #endif /* eof */ glpk-4.52.1/src/misc/ffalg.c0000644000062000006210000001643312175147600014675 0ustar maomkpasswd/* ffalg.c (Ford-Fulkerson algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "ffalg.h" /*********************************************************************** * NAME * * ffalg - Ford-Fulkerson algorithm * * SYNOPSIS * * #include "ffalg.h" * void ffalg(int nv, int na, const int tail[], const int head[], * int s, int t, const int cap[], int x[], char cut[]); * * DESCRIPTION * * The routine ffalg implements the Ford-Fulkerson algorithm to find a * maximal flow in the specified flow network. * * INPUT PARAMETERS * * nv is the number of nodes, nv >= 2. * * na is the number of arcs, na >= 0. * * tail[a], a = 1,...,na, is the index of tail node of arc a. * * head[a], a = 1,...,na, is the index of head node of arc a. * * s is the source node index, 1 <= s <= nv. * * t is the sink node index, 1 <= t <= nv, t != s. * * cap[a], a = 1,...,na, is the capacity of arc a, cap[a] >= 0. * * NOTE: Multiple arcs are allowed, but self-loops are not allowed. * * OUTPUT PARAMETERS * * x[a], a = 1,...,na, is optimal value of the flow through arc a. * * cut[i], i = 1,...,nv, is 1 if node i is labelled, and 0 otherwise. * The set of arcs, whose one endpoint is labelled and other is not, * defines the minimal cut corresponding to the maximal flow found. * If the parameter cut is NULL, the cut information are not stored. * * REFERENCES * * L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND * Corp., Report R-375-PR (August 1962), Chap. I "Static Maximal Flow," * pp.30-33. */ void ffalg(int nv, int na, const int tail[], const int head[], int s, int t, const int cap[], int x[], char cut[]) { int a, delta, i, j, k, pos1, pos2, temp, *ptr, *arc, *link, *list; /* sanity checks */ xassert(nv >= 2); xassert(na >= 0); xassert(1 <= s && s <= nv); xassert(1 <= t && t <= nv); xassert(s != t); for (a = 1; a <= na; a++) { i = tail[a], j = head[a]; xassert(1 <= i && i <= nv); xassert(1 <= j && j <= nv); xassert(i != j); xassert(cap[a] >= 0); } /* allocate working arrays */ ptr = xcalloc(1+nv+1, sizeof(int)); arc = xcalloc(1+na+na, sizeof(int)); link = xcalloc(1+nv, sizeof(int)); list = xcalloc(1+nv, sizeof(int)); /* ptr[i] := (degree of node i) */ for (i = 1; i <= nv; i++) ptr[i] = 0; for (a = 1; a <= na; a++) { ptr[tail[a]]++; ptr[head[a]]++; } /* initialize arc pointers */ ptr[1]++; for (i = 1; i < nv; i++) ptr[i+1] += ptr[i]; ptr[nv+1] = ptr[nv]; /* build arc lists */ for (a = 1; a <= na; a++) { arc[--ptr[tail[a]]] = a; arc[--ptr[head[a]]] = a; } xassert(ptr[1] == 1); xassert(ptr[nv+1] == na+na+1); /* now the indices of arcs incident to node i are stored in * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */ /* initialize arc flows */ for (a = 1; a <= na; a++) x[a] = 0; loop: /* main loop starts here */ /* build augmenting tree rooted at s */ /* link[i] = 0 means that node i is not labelled yet; * link[i] = a means that arc a immediately precedes node i */ /* initially node s is labelled as the root */ for (i = 1; i <= nv; i++) link[i] = 0; link[s] = -1, list[1] = s, pos1 = pos2 = 1; /* breadth first search */ while (pos1 <= pos2) { /* dequeue node i */ i = list[pos1++]; /* consider all arcs incident to node i */ for (k = ptr[i]; k < ptr[i+1]; k++) { a = arc[k]; if (tail[a] == i) { /* a = i->j is a forward arc from s to t */ j = head[a]; /* if node j has been labelled, skip the arc */ if (link[j] != 0) continue; /* if the arc does not allow increasing the flow through * it, skip the arc */ if (x[a] == cap[a]) continue; } else if (head[a] == i) { /* a = i<-j is a backward arc from s to t */ j = tail[a]; /* if node j has been labelled, skip the arc */ if (link[j] != 0) continue; /* if the arc does not allow decreasing the flow through * it, skip the arc */ if (x[a] == 0) continue; } else xassert(a != a); /* label node j and enqueue it */ link[j] = a, list[++pos2] = j; /* check for breakthrough */ if (j == t) goto brkt; } } /* NONBREAKTHROUGH */ /* no augmenting path exists; current flow is maximal */ /* store minimal cut information, if necessary */ if (cut != NULL) { for (i = 1; i <= nv; i++) cut[i] = (char)(link[i] != 0); } goto done; brkt: /* BREAKTHROUGH */ /* walk through arcs of the augmenting path (s, ..., t) found in * the reverse order and determine maximal change of the flow */ delta = 0; for (j = t; j != s; j = i) { /* arc a immediately precedes node j in the path */ a = link[j]; if (head[a] == j) { /* a = i->j is a forward arc of the cycle */ i = tail[a]; /* x[a] may be increased until its upper bound */ temp = cap[a] - x[a]; } else if (tail[a] == j) { /* a = i<-j is a backward arc of the cycle */ i = head[a]; /* x[a] may be decreased until its lower bound */ temp = x[a]; } else xassert(a != a); if (delta == 0 || delta > temp) delta = temp; } xassert(delta > 0); /* increase the flow along the path */ for (j = t; j != s; j = i) { /* arc a immediately precedes node j in the path */ a = link[j]; if (head[a] == j) { /* a = i->j is a forward arc of the cycle */ i = tail[a]; x[a] += delta; } else if (tail[a] == j) { /* a = i<-j is a backward arc of the cycle */ i = head[a]; x[a] -= delta; } else xassert(a != a); } goto loop; done: /* free working arrays */ xfree(ptr); xfree(arc); xfree(link); xfree(list); return; } /* eof */ glpk-4.52.1/src/misc/ffalg.h0000644000062000006210000000237212175147600014677 0ustar maomkpasswd/* ffalg.h (Ford-Fulkerson algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef FFALG_H #define FFALG_H #define ffalg _glp_ffalg void ffalg(int nv, int na, const int tail[], const int head[], int s, int t, const int cap[], int x[], char cut[]); /* Ford-Fulkerson algorithm */ #endif /* eof */ glpk-4.52.1/src/misc/jd.c0000644000062000006210000001006712175147600014210 0ustar maomkpasswd/* jd.c (conversions between calendar date and Julian day number) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include #include "jd.h" /*********************************************************************** * NAME * * jday - convert calendar date to Julian day number * * SYNOPSIS * * #include "jd.h" * int jday(int d, int m, int y); * * DESCRIPTION * * The routine jday converts a calendar date, Gregorian calendar, to * corresponding Julian day number j. * * From the given day d, month m, and year y, the Julian day number j * is computed without using tables. * * The routine is valid for 1 <= y <= 4000. * * RETURNS * * The routine jday returns the Julian day number, or negative value if * the specified date is incorrect. * * REFERENCES * * R. G. Tantzen, Algorithm 199: conversions between calendar date and * Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444, * Aug. 1963. */ int jday(int d, int m, int y) { int c, ya, j, dd; if (!(1 <= d && d <= 31 && 1 <= m && m <= 12 && 1 <= y && y <= 4000)) return -1; if (m >= 3) m -= 3; else m += 9, y--; c = y / 100; ya = y - 100 * c; j = (146097 * c) / 4 + (1461 * ya) / 4 + (153 * m + 2) / 5 + d + 1721119; jdate(j, &dd, NULL, NULL); if (d != dd) return -1; return j; } /*********************************************************************** * NAME * * jdate - convert Julian day number to calendar date * * SYNOPSIS * * #include "jd.h" * int jdate(int j, int *d, int *m, int *y); * * DESCRIPTION * * The routine jdate converts a Julian day number j to corresponding * calendar date, Gregorian calendar. * * The day d, month m, and year y are computed without using tables and * stored in corresponding locations. * * The routine is valid for 1721426 <= j <= 3182395. * * RETURNS * * If the conversion is successful, the routine returns zero, otherwise * non-zero. * * REFERENCES * * R. G. Tantzen, Algorithm 199: conversions between calendar date and * Julian day number, Communications of the ACM, vol. 6, no. 8, p. 444, * Aug. 1963. */ int jdate(int j, int *d_, int *m_, int *y_) { int d, m, y; if (!(1721426 <= j && j <= 3182395)) return 1; j -= 1721119; y = (4 * j - 1) / 146097; j = (4 * j - 1) % 146097; d = j / 4; j = (4 * d + 3) / 1461; d = (4 * d + 3) % 1461; d = (d + 4) / 4; m = (5 * d - 3) / 153; d = (5 * d - 3) % 153; d = (d + 5) / 5; y = 100 * y + j; if (m <= 9) m += 3; else m -= 9, y++; if (d_ != NULL) *d_ = d; if (m_ != NULL) *m_ = m; if (y_ != NULL) *y_ = y; return 0; } #ifdef GLP_TEST #include #include #include int main(void) { int jbeg, jend, j, d, m, y; jbeg = jday(1, 1, 1); jend = jday(31, 12, 4000); for (j = jbeg; j <= jend; j++) { assert(jdate(j, &d, &m, &y) == 0); assert(jday(d, m, y) == j); } printf("Routines jday and jdate work correctly.\n"); return 0; } #endif /* eof */ glpk-4.52.1/src/misc/jd.h0000644000062000006210000000242712175147600014216 0ustar maomkpasswd/* jd.h (conversions between calendar date and Julian day number) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2000, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #define jday _glp_jday int jday(int d, int m, int y); /* convert calendar date to Julian day number */ #define jdate _glp_jdate int jdate(int j, int *d, int *m, int *y); /* convert Julian day number to calendar date */ /* eof */ glpk-4.52.1/src/misc/keller.c0000644000062000006210000002230512175147600015067 0ustar maomkpasswd/* keller.c (cover edges by cliques, Kellerman's heuristic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "glpk.h" #include "env.h" #include "keller.h" /*********************************************************************** * NAME * * kellerman - cover edges by cliques with Kellerman's heuristic * * SYNOPSIS * * #include "keller.h" * int kellerman(int n, int (*func)(void *info, int i, int ind[]), * void *info, glp_graph *H); * * DESCRIPTION * * The routine kellerman implements Kellerman's heuristic algorithm * to find a minimal set of cliques which cover all edges of specified * graph G = (V, E). * * The parameter n specifies the number of vertices |V|, n >= 0. * * Formal routine func specifies the set of edges E in the following * way. Running the routine kellerman calls the routine func and passes * to it parameter i, which is the number of some vertex, 1 <= i <= n. * In response the routine func should store numbers of all vertices * adjacent to vertex i to locations ind[1], ind[2], ..., ind[len] and * return the value of len, which is the number of adjacent vertices, * 0 <= len <= n. Self-loops are allowed, but ignored. Multiple edges * are not allowed. * * The parameter info is a transit pointer (magic cookie) passed to the * formal routine func as its first parameter. * * The result provided by the routine kellerman is the bipartite graph * H = (V union C, F), which defines the covering found. (The program * object of type glp_graph specified by the parameter H should be * previously created with the routine glp_create_graph. On entry the * routine kellerman erases the content of this object with the routine * glp_erase_graph.) Vertices of first part V correspond to vertices of * the graph G and have the same ordinal numbers 1, 2, ..., n. Vertices * of second part C correspond to cliques and have ordinal numbers * n+1, n+2, ..., n+k, where k is the total number of cliques in the * edge covering found. Every edge f in F in the program object H is * represented as arc f = (i->j), where i in V and j in C, which means * that vertex i of the graph G is in clique C[j], 1 <= j <= k. (Thus, * if two vertices of the graph G are in the same clique, these vertices * are adjacent in G, and corresponding edge is covered by that clique.) * * RETURNS * * The routine Kellerman returns k, the total number of cliques in the * edge covering found. * * REFERENCE * * For more details see: glpk/doc/notes/keller.pdf (in Russian). */ struct set { /* set of vertices */ int size; /* size (cardinality) of the set, 0 <= card <= n */ int *list; /* int list[1+n]; */ /* the set contains vertices list[1,...,size] */ int *pos; /* int pos[1+n]; */ /* pos[i] > 0 means that vertex i is in the set and * list[pos[i]] = i; pos[i] = 0 means that vertex i is not in * the set */ }; int kellerman(int n, int (*func)(void *info, int i, int ind[]), void *info, void /* glp_graph */ *H_) { glp_graph *H = H_; struct set W_, *W = &W_, V_, *V = &V_; glp_arc *a; int i, j, k, m, t, len, card, best; xassert(n >= 0); /* H := (V, 0; 0), where V is the set of vertices of graph G */ glp_erase_graph(H, H->v_size, H->a_size); glp_add_vertices(H, n); /* W := 0 */ W->size = 0; W->list = xcalloc(1+n, sizeof(int)); W->pos = xcalloc(1+n, sizeof(int)); memset(&W->pos[1], 0, sizeof(int) * n); /* V := 0 */ V->size = 0; V->list = xcalloc(1+n, sizeof(int)); V->pos = xcalloc(1+n, sizeof(int)); memset(&V->pos[1], 0, sizeof(int) * n); /* main loop */ for (i = 1; i <= n; i++) { /* W must be empty */ xassert(W->size == 0); /* W := { j : i > j and (i,j) in E } */ len = func(info, i, W->list); xassert(0 <= len && len <= n); for (t = 1; t <= len; t++) { j = W->list[t]; xassert(1 <= j && j <= n); if (j >= i) continue; xassert(W->pos[j] == 0); W->list[++W->size] = j, W->pos[j] = W->size; } /* on i-th iteration we need to cover edges (i,j) for all * j in W */ /* if W is empty, it is a special case */ if (W->size == 0) { /* set k := k + 1 and create new clique C[k] = { i } */ k = glp_add_vertices(H, 1) - n; glp_add_arc(H, i, n + k); continue; } /* try to include vertex i into existing cliques */ /* V must be empty */ xassert(V->size == 0); /* k is the number of cliques found so far */ k = H->nv - n; for (m = 1; m <= k; m++) { /* do while V != W; since here V is within W, we can use * equivalent condition: do while |V| < |W| */ if (V->size == W->size) break; /* check if C[m] is within W */ for (a = H->v[n + m]->in; a != NULL; a = a->h_next) { j = a->tail->i; if (W->pos[j] == 0) break; } if (a != NULL) continue; /* C[m] is within W, expand clique C[m] with vertex i */ /* C[m] := C[m] union {i} */ glp_add_arc(H, i, n + m); /* V is a set of vertices whose incident edges are already * covered by existing cliques */ /* V := V union C[m] */ for (a = H->v[n + m]->in; a != NULL; a = a->h_next) { j = a->tail->i; if (V->pos[j] == 0) V->list[++V->size] = j, V->pos[j] = V->size; } } /* remove from set W the vertices whose incident edges are * already covered by existing cliques */ /* W := W \ V, V := 0 */ for (t = 1; t <= V->size; t++) { j = V->list[t], V->pos[j] = 0; if (W->pos[j] != 0) { /* remove vertex j from W */ if (W->pos[j] != W->size) { int jj = W->list[W->size]; W->list[W->pos[j]] = jj; W->pos[jj] = W->pos[j]; } W->size--, W->pos[j] = 0; } } V->size = 0; /* now set W contains only vertices whose incident edges are * still not covered by existing cliques; create new cliques * to cover remaining edges until set W becomes empty */ while (W->size > 0) { /* find clique C[m], 1 <= m <= k, which shares maximal * number of vertices with W; to break ties choose clique * having smallest number m */ m = 0, best = -1; k = H->nv - n; for (t = 1; t <= k; t++) { /* compute cardinality of intersection of W and C[t] */ card = 0; for (a = H->v[n + t]->in; a != NULL; a = a->h_next) { j = a->tail->i; if (W->pos[j] != 0) card++; } if (best < card) m = t, best = card; } xassert(m > 0); /* set k := k + 1 and create new clique: * C[k] := (W intersect C[m]) union { i }, which covers all * edges incident to vertices from (W intersect C[m]) */ k = glp_add_vertices(H, 1) - n; for (a = H->v[n + m]->in; a != NULL; a = a->h_next) { j = a->tail->i; if (W->pos[j] != 0) { /* vertex j is in both W and C[m]; include it in new * clique C[k] */ glp_add_arc(H, j, n + k); /* remove vertex j from W, since edge (i,j) will be * covered by new clique C[k] */ if (W->pos[j] != W->size) { int jj = W->list[W->size]; W->list[W->pos[j]] = jj; W->pos[jj] = W->pos[j]; } W->size--, W->pos[j] = 0; } } /* include vertex i to new clique C[k] to cover edges (i,j) * incident to all vertices j just removed from W */ glp_add_arc(H, i, n + k); } } /* free working arrays */ xfree(W->list); xfree(W->pos); xfree(V->list); xfree(V->pos); /* return the number of cliques in the edge covering found */ return H->nv - n; } /* eof */ glpk-4.52.1/src/misc/keller.h0000644000062000006210000000244512175147600015077 0ustar maomkpasswd/* keller.h (cover edges by cliques, Kellerman's heuristic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef KELLER_H #define KELLER_H #define kellerman _glp_kellerman int kellerman(int n, int (*func)(void *info, int i, int ind[]), void *info, void /* glp_graph */ *H); /* cover edges by cliques with Kellerman's heuristic */ #endif /* eof */ glpk-4.52.1/src/misc/mc13d.c0000644000062000006210000002444012175147600014522 0ustar maomkpasswd/* mc13d.c (permutations to block triangular form) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * This code is the result of translation of the Fortran subroutines * MC13D and MC13E associated with the following paper: * * I.S.Duff, J.K.Reid, Algorithm 529: Permutations to block triangular * form, ACM Trans. on Math. Softw. 4 (1978), 189-192. * * Use of ACM Algorithms is subject to the ACM Software Copyright and * License Agreement. See . * * The translation was made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "mc13d.h" /*********************************************************************** * NAME * * mc13d - permutations to block triangular form * * SYNOPSIS * * #include "mc13d.h" * int mc13d(int n, const int icn[], const int ip[], const int lenr[], * int ior[], int ib[], int lowl[], int numb[], int prev[]); * * DESCRIPTION * * Given the column numbers of the nonzeros in each row of the sparse * matrix, the routine mc13d finds a symmetric permutation that makes * the matrix block lower triangular. * * INPUT PARAMETERS * * n order of the matrix. * * icn array containing the column indices of the non-zeros. Those * belonging to a single row must be contiguous but the ordering * of column indices within each row is unimportant and wasted * space between rows is permitted. * * ip ip[i], i = 1,2,...,n, is the position in array icn of the * first column index of a non-zero in row i. * * lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i. * * OUTPUT PARAMETERS * * ior ior[i], i = 1,2,...,n, gives the position on the original * ordering of the row or column which is in position i in the * permuted form. * * ib ib[i], i = 1,2,...,num, is the row number in the permuted * matrix of the beginning of block i, 1 <= num <= n. * * WORKING ARRAYS * * arp working array of length [1+n], where arp[0] is not used. * arp[i] is one less than the number of unsearched edges leaving * node i. At the end of the algorithm it is set to a permutation * which puts the matrix in block lower triangular form. * * ib working array of length [1+n], where ib[0] is not used. * ib[i] is the position in the ordering of the start of the ith * block. ib[n+1-i] holds the node number of the ith node on the * stack. * * lowl working array of length [1+n], where lowl[0] is not used. * lowl[i] is the smallest stack position of any node to which a * path from node i has been found. It is set to n+1 when node i * is removed from the stack. * * numb working array of length [1+n], where numb[0] is not used. * numb[i] is the position of node i in the stack if it is on it, * is the permuted order of node i for those nodes whose final * position has been found and is otherwise zero. * * prev working array of length [1+n], where prev[0] is not used. * prev[i] is the node at the end of the path when node i was * placed on the stack. * * RETURNS * * The routine mc13d returns num, the number of blocks found. */ int mc13d(int n, const int icn[], const int ip[], const int lenr[], int ior[], int ib[], int lowl[], int numb[], int prev[]) { int *arp = ior; int dummy, i, i1, i2, icnt, ii, isn, ist, ist1, iv, iw, j, lcnt, nnm1, num, stp; /* icnt is the number of nodes whose positions in final ordering * have been found. */ icnt = 0; /* num is the number of blocks that have been found. */ num = 0; nnm1 = n + n - 1; /* Initialization of arrays. */ for (j = 1; j <= n; j++) { numb[j] = 0; arp[j] = lenr[j] - 1; } for (isn = 1; isn <= n; isn++) { /* Look for a starting node. */ if (numb[isn] != 0) continue; iv = isn; /* ist is the number of nodes on the stack ... it is the stack * pointer. */ ist = 1; /* Put node iv at beginning of stack. */ lowl[iv] = numb[iv] = 1; ib[n] = iv; /* The body of this loop puts a new node on the stack or * backtracks. */ for (dummy = 1; dummy <= nnm1; dummy++) { i1 = arp[iv]; /* Have all edges leaving node iv been searched? */ if (i1 >= 0) { i2 = ip[iv] + lenr[iv] - 1; i1 = i2 - i1; /* Look at edges leaving node iv until one enters a new * node or all edges are exhausted. */ for (ii = i1; ii <= i2; ii++) { iw = icn[ii]; /* Has node iw been on stack already? */ if (numb[iw] == 0) goto L70; /* Update value of lowl[iv] if necessary. */ if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw]; } /* There are no more edges leaving node iv. */ arp[iv] = -1; } /* Is node iv the root of a block? */ if (lowl[iv] < numb[iv]) goto L60; /* Order nodes in a block. */ num++; ist1 = n + 1 - ist; lcnt = icnt + 1; /* Peel block off the top of the stack starting at the top * and working down to the root of the block. */ for (stp = ist1; stp <= n; stp++) { iw = ib[stp]; lowl[iw] = n + 1; numb[iw] = ++icnt; if (iw == iv) break; } ist = n - stp; ib[num] = lcnt; /* Are there any nodes left on the stack? */ if (ist != 0) goto L60; /* Have all the nodes been ordered? */ if (icnt < n) break; goto L100; L60: /* Backtrack to previous node on path. */ iw = iv; iv = prev[iv]; /* Update value of lowl[iv] if necessary. */ if (lowl[iw] < lowl[iv]) lowl[iv] = lowl[iw]; continue; L70: /* Put new node on the stack. */ arp[iv] = i2 - ii - 1; prev[iw] = iv; iv = iw; lowl[iv] = numb[iv] = ++ist; ib[n+1-ist] = iv; } } L100: /* Put permutation in the required form. */ for (i = 1; i <= n; i++) arp[numb[i]] = i; return num; } /**********************************************************************/ #ifdef GLP_TEST #include "env.h" void test(int n, int ipp); int main(void) { /* test program for routine mc13d */ test( 1, 0); test( 2, 1); test( 2, 2); test( 3, 3); test( 4, 4); test( 5, 10); test(10, 10); test(10, 20); test(20, 20); test(20, 50); test(50, 50); test(50, 200); return 0; } void fa01bs(int max, int *nrand); void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]); void test(int n, int ipp) { int ip[1+50], icn[1+1000], ior[1+50], ib[1+51], iw[1+150], lenr[1+50]; char a[1+50][1+50], hold[1+100]; int i, ii, iblock, ij, index, j, jblock, jj, k9, num; xprintf("\n\n\nMatrix is of order %d and has %d off-diagonal non-" "zeros\n", n, ipp); for (j = 1; j <= n; j++) { for (i = 1; i <= n; i++) a[i][j] = 0; a[j][j] = 1; } for (k9 = 1; k9 <= ipp; k9++) { /* these statements should be replaced by calls to your * favorite random number generator to place two pseudo-random * numbers between 1 and n in the variables i and j */ for (;;) { fa01bs(n, &i); fa01bs(n, &j); if (!a[i][j]) break; } a[i][j] = 1; } /* setup converts matrix a[i,j] to required sparsity-oriented * storage format */ setup(n, a, ip, icn, lenr); num = mc13d(n, icn, ip, lenr, ior, ib, &iw[0], &iw[n], &iw[n+n]); /* output reordered matrix with blocking to improve clarity */ xprintf("\nThe reordered matrix which has %d block%s is of the fo" "rm\n", num, num == 1 ? "" : "s"); ib[num+1] = n + 1; index = 100; iblock = 1; for (i = 1; i <= n; i++) { for (ij = 1; ij <= index; ij++) hold[ij] = ' '; if (i == ib[iblock]) { xprintf("\n"); iblock++; } jblock = 1; index = 0; for (j = 1; j <= n; j++) { if (j == ib[jblock]) { hold[++index] = ' '; jblock++; } ii = ior[i]; jj = ior[j]; hold[++index] = (char)(a[ii][jj] ? 'X' : '0'); } xprintf("%.*s\n", index, &hold[1]); } xprintf("\nThe starting point for each block is given by\n"); for (i = 1; i <= num; i++) { if ((i - 1) % 12 == 0) xprintf("\n"); xprintf(" %4d", ib[i]); } xprintf("\n"); return; } void setup(int n, char a[1+50][1+50], int ip[], int icn[], int lenr[]) { int i, j, ind; for (i = 1; i <= n; i++) lenr[i] = 0; ind = 1; for (i = 1; i <= n; i++) { ip[i] = ind; for (j = 1; j <= n; j++) { if (a[i][j]) { lenr[i]++; icn[ind++] = j; } } } return; } double g = 1431655765.0; double fa01as(int i) { /* random number generator */ g = fmod(g * 9228907.0, 4294967296.0); if (i >= 0) return g / 4294967296.0; else return 2.0 * g / 4294967296.0 - 1.0; } void fa01bs(int max, int *nrand) { *nrand = (int)(fa01as(1) * (double)max) + 1; return; } #endif /* eof */ glpk-4.52.1/src/misc/mc13d.h0000644000062000006210000000236612175147600014532 0ustar maomkpasswd/* mc13d.h */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef MC13D_H #define MC13D_H #define mc13d _glp_mc13d int mc13d(int n, const int icn[], const int ip[], const int lenr[], int ior[], int ib[], int lowl[], int numb[], int prev[]); /* permutations to block triangular form */ #endif /* eof */ glpk-4.52.1/src/misc/mc21a.c0000644000062000006210000002335212175147600014517 0ustar maomkpasswd/* mc21a.c (permutations for zero-free diagonal) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * This code is the result of translation of the Fortran subroutines * MC21A and MC21B associated with the following paper: * * I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM * Trans. on Math. Softw. 7 (1981), 387-390. * * Use of ACM Algorithms is subject to the ACM Software Copyright and * License Agreement. See . * * The translation was made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "mc21a.h" /*********************************************************************** * NAME * * mc21a - permutations for zero-free diagonal * * SYNOPSIS * * #include "mc21a.h" * int mc21a(int n, const int icn[], const int ip[], const int lenr[], * int iperm[], int pr[], int arp[], int cv[], int out[]); * * DESCRIPTION * * Given the pattern of nonzeros of a sparse matrix, the routine mc21a * attempts to find a permutation of its rows that makes the matrix have * no zeros on its diagonal. * * INPUT PARAMETERS * * n order of matrix. * * icn array containing the column indices of the non-zeros. Those * belonging to a single row must be contiguous but the ordering * of column indices within each row is unimportant and wasted * space between rows is permitted. * * ip ip[i], i = 1,2,...,n, is the position in array icn of the * first column index of a non-zero in row i. * * lenr lenr[i], i = 1,2,...,n, is the number of non-zeros in row i. * * OUTPUT PARAMETER * * iperm contains permutation to make diagonal have the smallest * number of zeros on it. Elements (iperm[i], i), i = 1,2,...,n, * are non-zero at the end of the algorithm unless the matrix is * structurally singular. In this case, (iperm[i], i) will be * zero for n - numnz entries. * * WORKING ARRAYS * * pr working array of length [1+n], where pr[0] is not used. * pr[i] is the previous row to i in the depth first search. * * arp working array of length [1+n], where arp[0] is not used. * arp[i] is one less than the number of non-zeros in row i which * have not been scanned when looking for a cheap assignment. * * cv working array of length [1+n], where cv[0] is not used. * cv[i] is the most recent row extension at which column i was * visited. * * out working array of length [1+n], where out[0] is not used. * out[i] is one less than the number of non-zeros in row i * which have not been scanned during one pass through the main * loop. * * RETURNS * * The routine mc21a returns numnz, the number of non-zeros on diagonal * of permuted matrix. */ int mc21a(int n, const int icn[], const int ip[], const int lenr[], int iperm[], int pr[], int arp[], int cv[], int out[]) { int i, ii, in1, in2, j, j1, jord, k, kk, numnz; /* Initialization of arrays. */ for (i = 1; i <= n; i++) { arp[i] = lenr[i] - 1; cv[i] = iperm[i] = 0; } numnz = 0; /* Main loop. */ /* Each pass round this loop either results in a new assignment * or gives a row with no assignment. */ for (jord = 1; jord <= n; jord++) { j = jord; pr[j] = -1; for (k = 1; k <= jord; k++) { /* Look for a cheap assignment. */ in1 = arp[j]; if (in1 >= 0) { in2 = ip[j] + lenr[j] - 1; in1 = in2 - in1; for (ii = in1; ii <= in2; ii++) { i = icn[ii]; if (iperm[i] == 0) goto L110; } /* No cheap assignment in row. */ arp[j] = -1; } /* Begin looking for assignment chain starting with row j.*/ out[j] = lenr[j] - 1; /* Inner loop. Extends chain by one or backtracks. */ for (kk = 1; kk <= jord; kk++) { in1 = out[j]; if (in1 >= 0) { in2 = ip[j] + lenr[j] - 1; in1 = in2 - in1; /* Forward scan. */ for (ii = in1; ii <= in2; ii++) { i = icn[ii]; if (cv[i] != jord) { /* Column i has not yet been accessed during * this pass. */ j1 = j; j = iperm[i]; cv[i] = jord; pr[j] = j1; out[j1] = in2 - ii - 1; goto L100; } } } /* Backtracking step. */ j = pr[j]; if (j == -1) goto L130; } L100: ; } L110: /* New assignment is made. */ iperm[i] = j; arp[j] = in2 - ii - 1; numnz++; for (k = 1; k <= jord; k++) { j = pr[j]; if (j == -1) break; ii = ip[j] + lenr[j] - out[j] - 2; i = icn[ii]; iperm[i] = j; } L130: ; } /* If matrix is structurally singular, we now complete the * permutation iperm. */ if (numnz < n) { for (i = 1; i <= n; i++) arp[i] = 0; k = 0; for (i = 1; i <= n; i++) { if (iperm[i] == 0) out[++k] = i; else arp[iperm[i]] = i; } k = 0; for (i = 1; i <= n; i++) { if (arp[i] == 0) iperm[out[++k]] = i; } } return numnz; } /**********************************************************************/ #ifdef GLP_TEST #include "env.h" int sing; void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum, int iw[]); void fa01bs(int max, int *nrand); int main(void) { /* test program for the routine mc21a */ /* these runs on random matrices cause all possible statements in * mc21a to be executed */ int i, iold, j, j1, j2, jj, knum, l, licn, n, nov4, num, numnz; int ip[1+21], icn[1+1000], iperm[1+20], lenr[1+20], iw1[1+80]; licn = 1000; /* run on random matrices of orders 1 through 20 */ for (n = 1; n <= 20; n++) { nov4 = n / 4; if (nov4 < 1) nov4 = 1; L10: fa01bs(nov4, &l); knum = l * n; /* knum is requested number of non-zeros in random matrix */ if (knum > licn) goto L10; /* if sing is false, matrix is guaranteed structurally * non-singular */ sing = ((n / 2) * 2 == n); /* call to subroutine to generate random matrix */ ranmat(n, n, icn, ip, n+1, &knum, iw1); /* knum is now actual number of non-zeros in random matrix */ if (knum > licn) goto L10; xprintf("n = %2d; nz = %4d; sing = %d\n", n, knum, sing); /* set up array of row lengths */ for (i = 1; i <= n; i++) lenr[i] = ip[i+1] - ip[i]; /* call to mc21a */ numnz = mc21a(n, icn, ip, lenr, iperm, &iw1[0], &iw1[n], &iw1[n+n], &iw1[n+n+n]); /* testing to see if there are numnz non-zeros on the diagonal * of the permuted matrix. */ num = 0; for (i = 1; i <= n; i++) { iold = iperm[i]; j1 = ip[iold]; j2 = j1 + lenr[iold] - 1; if (j2 < j1) continue; for (jj = j1; jj <= j2; jj++) { j = icn[jj]; if (j == i) { num++; break; } } } if (num != numnz) xprintf("Failure in mc21a, numnz = %d instead of %d\n", numnz, num); } return 0; } void ranmat(int m, int n, int icn[], int iptr[], int nnnp1, int *knum, int iw[]) { /* subroutine to generate random matrix */ int i, ii, inum, j, lrow, matnum; inum = (*knum / n) * 2; if (inum > n-1) inum = n-1; matnum = 1; /* each pass through this loop generates a row of the matrix */ for (j = 1; j <= m; j++) { iptr[j] = matnum; if (!(sing || j > n)) icn[matnum++] = j; if (n == 1) continue; for (i = 1; i <= n; i++) iw[i] = 0; if (!sing) iw[j] = 1; fa01bs(inum, &lrow); lrow--; if (lrow == 0) continue; /* lrow off-diagonal non-zeros in row j of the matrix */ for (ii = 1; ii <= lrow; ii++) { for (;;) { fa01bs(n, &i); if (iw[i] != 1) break; } iw[i] = 1; icn[matnum++] = i; } } for (i = m+1; i <= nnnp1; i++) iptr[i] = matnum; *knum = matnum - 1; return; } double g = 1431655765.0; double fa01as(int i) { /* random number generator */ g = fmod(g * 9228907.0, 4294967296.0); if (i >= 0) return g / 4294967296.0; else return 2.0 * g / 4294967296.0 - 1.0; } void fa01bs(int max, int *nrand) { *nrand = (int)(fa01as(1) * (double)max) + 1; return; } #endif /* eof */ glpk-4.52.1/src/misc/mc21a.h0000644000062000006210000000243012175147600014516 0ustar maomkpasswd/* mc21a.h (permutations for zero-free diagonal) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef MC21A_H #define MC21A_H #define mc21a _glp_mc21a int mc21a(int n, const int icn[], const int ip[], const int lenr[], int iperm[], int pr[], int arp[], int cv[], int out[]); /* permutations for zero-free diagonal */ #endif /* eof */ glpk-4.52.1/src/misc/okalg.c0000644000062000006210000003051512175147600014710 0ustar maomkpasswd/* okalg.c (out-of-kilter algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "okalg.h" /*********************************************************************** * NAME * * okalg - out-of-kilter algorithm * * SYNOPSIS * * #include "okalg.h" * int okalg(int nv, int na, const int tail[], const int head[], * const int low[], const int cap[], const int cost[], int x[], * int pi[]); * * DESCRIPTION * * The routine okalg implements the out-of-kilter algorithm to find a * minimal-cost circulation in the specified flow network. * * INPUT PARAMETERS * * nv is the number of nodes, nv >= 0. * * na is the number of arcs, na >= 0. * * tail[a], a = 1,...,na, is the index of tail node of arc a. * * head[a], a = 1,...,na, is the index of head node of arc a. * * low[a], a = 1,...,na, is an lower bound to the flow through arc a. * * cap[a], a = 1,...,na, is an upper bound to the flow through arc a, * which is the capacity of the arc. * * cost[a], a = 1,...,na, is a per-unit cost of the flow through arc a. * * NOTES * * 1. Multiple arcs are allowed, but self-loops are not allowed. * * 2. It is required that 0 <= low[a] <= cap[a] for all arcs. * * 3. Arc costs may have any sign. * * OUTPUT PARAMETERS * * x[a], a = 1,...,na, is optimal value of the flow through arc a. * * pi[i], i = 1,...,nv, is Lagrange multiplier for flow conservation * equality constraint corresponding to node i (the node potential). * * RETURNS * * 0 optimal circulation found; * * 1 there is no feasible circulation; * * 2 integer overflow occured; * * 3 optimality test failed (logic error). * * REFERENCES * * L.R.Ford, Jr., and D.R.Fulkerson, "Flows in Networks," The RAND * Corp., Report R-375-PR (August 1962), Chap. III "Minimal Cost Flow * Problems," pp.113-26. */ static int overflow(int u, int v) { /* check for integer overflow on computing u + v */ if (u > 0 && v > 0 && u + v < 0) return 1; if (u < 0 && v < 0 && u + v > 0) return 1; return 0; } int okalg(int nv, int na, const int tail[], const int head[], const int low[], const int cap[], const int cost[], int x[], int pi[]) { int a, aok, delta, i, j, k, lambda, pos1, pos2, s, t, temp, ret, *ptr, *arc, *link, *list; /* sanity checks */ xassert(nv >= 0); xassert(na >= 0); for (a = 1; a <= na; a++) { i = tail[a], j = head[a]; xassert(1 <= i && i <= nv); xassert(1 <= j && j <= nv); xassert(i != j); xassert(0 <= low[a] && low[a] <= cap[a]); } /* allocate working arrays */ ptr = xcalloc(1+nv+1, sizeof(int)); arc = xcalloc(1+na+na, sizeof(int)); link = xcalloc(1+nv, sizeof(int)); list = xcalloc(1+nv, sizeof(int)); /* ptr[i] := (degree of node i) */ for (i = 1; i <= nv; i++) ptr[i] = 0; for (a = 1; a <= na; a++) { ptr[tail[a]]++; ptr[head[a]]++; } /* initialize arc pointers */ ptr[1]++; for (i = 1; i < nv; i++) ptr[i+1] += ptr[i]; ptr[nv+1] = ptr[nv]; /* build arc lists */ for (a = 1; a <= na; a++) { arc[--ptr[tail[a]]] = a; arc[--ptr[head[a]]] = a; } xassert(ptr[1] == 1); xassert(ptr[nv+1] == na+na+1); /* now the indices of arcs incident to node i are stored in * locations arc[ptr[i]], arc[ptr[i]+1], ..., arc[ptr[i+1]-1] */ /* initialize arc flows and node potentials */ for (a = 1; a <= na; a++) x[a] = 0; for (i = 1; i <= nv; i++) pi[i] = 0; loop: /* main loop starts here */ /* find out-of-kilter arc */ aok = 0; for (a = 1; a <= na; a++) { i = tail[a], j = head[a]; if (overflow(cost[a], pi[i] - pi[j])) { ret = 2; goto done; } lambda = cost[a] + (pi[i] - pi[j]); if (x[a] < low[a] || (lambda < 0 && x[a] < cap[a])) { /* arc a = i->j is out of kilter, and we need to increase * the flow through this arc */ aok = a, s = j, t = i; break; } if (x[a] > cap[a] || (lambda > 0 && x[a] > low[a])) { /* arc a = i->j is out of kilter, and we need to decrease * the flow through this arc */ aok = a, s = i, t = j; break; } } if (aok == 0) { /* all arcs are in kilter */ /* check for feasibility */ for (a = 1; a <= na; a++) { if (!(low[a] <= x[a] && x[a] <= cap[a])) { ret = 3; goto done; } } for (i = 1; i <= nv; i++) { temp = 0; for (k = ptr[i]; k < ptr[i+1]; k++) { a = arc[k]; if (tail[a] == i) { /* a is outgoing arc */ temp += x[a]; } else if (head[a] == i) { /* a is incoming arc */ temp -= x[a]; } else xassert(a != a); } if (temp != 0) { ret = 3; goto done; } } /* check for optimality */ for (a = 1; a <= na; a++) { i = tail[a], j = head[a]; lambda = cost[a] + (pi[i] - pi[j]); if ((lambda > 0 && x[a] != low[a]) || (lambda < 0 && x[a] != cap[a])) { ret = 3; goto done; } } /* current circulation is optimal */ ret = 0; goto done; } /* now we need to find a cycle (t, a, s, ..., t), which allows * increasing the flow along it, where a is the out-of-kilter arc * just found */ /* link[i] = 0 means that node i is not labelled yet; * link[i] = a means that arc a immediately precedes node i */ /* initially only node s is labelled */ for (i = 1; i <= nv; i++) link[i] = 0; link[s] = aok, list[1] = s, pos1 = pos2 = 1; /* breadth first search */ while (pos1 <= pos2) { /* dequeue node i */ i = list[pos1++]; /* consider all arcs incident to node i */ for (k = ptr[i]; k < ptr[i+1]; k++) { a = arc[k]; if (tail[a] == i) { /* a = i->j is a forward arc from s to t */ j = head[a]; /* if node j has been labelled, skip the arc */ if (link[j] != 0) continue; /* if the arc does not allow increasing the flow through * it, skip the arc */ if (x[a] >= cap[a]) continue; if (overflow(cost[a], pi[i] - pi[j])) { ret = 2; goto done; } lambda = cost[a] + (pi[i] - pi[j]); if (lambda > 0 && x[a] >= low[a]) continue; } else if (head[a] == i) { /* a = i<-j is a backward arc from s to t */ j = tail[a]; /* if node j has been labelled, skip the arc */ if (link[j] != 0) continue; /* if the arc does not allow decreasing the flow through * it, skip the arc */ if (x[a] <= low[a]) continue; if (overflow(cost[a], pi[j] - pi[i])) { ret = 2; goto done; } lambda = cost[a] + (pi[j] - pi[i]); if (lambda < 0 && x[a] <= cap[a]) continue; } else xassert(a != a); /* label node j and enqueue it */ link[j] = a, list[++pos2] = j; /* check for breakthrough */ if (j == t) goto brkt; } } /* NONBREAKTHROUGH */ /* consider all arcs, whose one endpoint is labelled and other is * not, and determine maximal change of node potentials */ delta = 0; for (a = 1; a <= na; a++) { i = tail[a], j = head[a]; if (link[i] != 0 && link[j] == 0) { /* a = i->j, where node i is labelled, node j is not */ if (overflow(cost[a], pi[i] - pi[j])) { ret = 2; goto done; } lambda = cost[a] + (pi[i] - pi[j]); if (x[a] <= cap[a] && lambda > 0) if (delta == 0 || delta > + lambda) delta = + lambda; } else if (link[i] == 0 && link[j] != 0) { /* a = j<-i, where node j is labelled, node i is not */ if (overflow(cost[a], pi[i] - pi[j])) { ret = 2; goto done; } lambda = cost[a] + (pi[i] - pi[j]); if (x[a] >= low[a] && lambda < 0) if (delta == 0 || delta > - lambda) delta = - lambda; } } if (delta == 0) { /* there is no feasible circulation */ ret = 1; goto done; } /* increase potentials of all unlabelled nodes */ for (i = 1; i <= nv; i++) { if (link[i] == 0) { if (overflow(pi[i], delta)) { ret = 2; goto done; } pi[i] += delta; } } goto loop; brkt: /* BREAKTHROUGH */ /* walk through arcs of the cycle (t, a, s, ..., t) found in the * reverse order and determine maximal change of the flow */ delta = 0; for (j = t;; j = i) { /* arc a immediately precedes node j in the cycle */ a = link[j]; if (head[a] == j) { /* a = i->j is a forward arc of the cycle */ i = tail[a]; lambda = cost[a] + (pi[i] - pi[j]); if (lambda > 0 && x[a] < low[a]) { /* x[a] may be increased until its lower bound */ temp = low[a] - x[a]; } else if (lambda <= 0 && x[a] < cap[a]) { /* x[a] may be increased until its upper bound */ temp = cap[a] - x[a]; } else xassert(a != a); } else if (tail[a] == j) { /* a = i<-j is a backward arc of the cycle */ i = head[a]; lambda = cost[a] + (pi[j] - pi[i]); if (lambda < 0 && x[a] > cap[a]) { /* x[a] may be decreased until its upper bound */ temp = x[a] - cap[a]; } else if (lambda >= 0 && x[a] > low[a]) { /* x[a] may be decreased until its lower bound */ temp = x[a] - low[a]; } else xassert(a != a); } else xassert(a != a); if (delta == 0 || delta > temp) delta = temp; /* check for end of the cycle */ if (i == t) break; } xassert(delta > 0); /* increase the flow along the cycle */ for (j = t;; j = i) { /* arc a immediately precedes node j in the cycle */ a = link[j]; if (head[a] == j) { /* a = i->j is a forward arc of the cycle */ i = tail[a]; /* overflow cannot occur */ x[a] += delta; } else if (tail[a] == j) { /* a = i<-j is a backward arc of the cycle */ i = head[a]; /* overflow cannot occur */ x[a] -= delta; } else xassert(a != a); /* check for end of the cycle */ if (i == t) break; } goto loop; done: /* free working arrays */ xfree(ptr); xfree(arc); xfree(link); xfree(list); return ret; } /* eof */ glpk-4.52.1/src/misc/okalg.h0000644000062000006210000000242012175147600014707 0ustar maomkpasswd/* okalg.h (out-of-kilter algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef OKALG_H #define OKALG_H #define okalg _glp_okalg int okalg(int nv, int na, const int tail[], const int head[], const int low[], const int cap[], const int cost[], int x[], int pi[]); /* out-of-kilter algorithm */ #endif /* eof */ glpk-4.52.1/src/misc/qmd.c0000644000062000006210000004353712175147600014404 0ustar maomkpasswd/* qmd.c (quotient minimum degree algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN SUBROUTINES * GENQMD, QMDRCH, QMDQT, QMDUPD, AND QMDMRG FROM THE BOOK: * * ALAN GEORGE, JOSEPH W-H LIU. COMPUTER SOLUTION OF LARGE SPARSE * POSITIVE DEFINITE SYSTEMS. PRENTICE-HALL, 1981. * * THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHORS * OF THE ORIGINAL FORTRAN SUBROUTINES: ALAN GEORGE AND JOSEPH LIU, * UNIVERSITY OF WATERLOO, WATERLOO, ONTARIO, CANADA. * * The translation was made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "qmd.h" /*********************************************************************** * NAME * * genqmd - GENeral Quotient Minimum Degree algorithm * * SYNOPSIS * * #include "qmd.h" * void genqmd(int *neqns, int xadj[], int adjncy[], int perm[], * int invp[], int deg[], int marker[], int rchset[], int nbrhd[], * int qsize[], int qlink[], int *nofsub); * * PURPOSE * * This routine implements the minimum degree algorithm. It makes use * of the implicit representation of the elimination graph by quotient * graphs, and the notion of indistinguishable nodes. * * CAUTION * * The adjancy vector adjncy will be destroyed. * * INPUT PARAMETERS * * neqns - number of equations; * (xadj, adjncy) - * the adjancy structure. * * OUTPUT PARAMETERS * * perm - the minimum degree ordering; * invp - the inverse of perm. * * WORKING PARAMETERS * * deg - the degree vector. deg[i] is negative means node i has been * numbered; * marker - a marker vector, where marker[i] is negative means node i * has been merged with another nodeand thus can be ignored; * rchset - vector used for the reachable set; * nbrhd - vector used for neighborhood set; * qsize - vector used to store the size of indistinguishable * supernodes; * qlink - vector used to store indistinguishable nodes, i, qlink[i], * qlink[qlink[i]], ... are the members of the supernode * represented by i. * * PROGRAM SUBROUTINES * * qmdrch, qmdqt, qmdupd. ***********************************************************************/ void genqmd(int *_neqns, int xadj[], int adjncy[], int perm[], int invp[], int deg[], int marker[], int rchset[], int nbrhd[], int qsize[], int qlink[], int *_nofsub) { int inode, ip, irch, j, mindeg, ndeg, nhdsze, node, np, num, nump1, nxnode, rchsze, search, thresh; # define neqns (*_neqns) # define nofsub (*_nofsub) /* Initialize degree vector and other working variables. */ mindeg = neqns; nofsub = 0; for (node = 1; node <= neqns; node++) { perm[node] = node; invp[node] = node; marker[node] = 0; qsize[node] = 1; qlink[node] = 0; ndeg = xadj[node+1] - xadj[node]; deg[node] = ndeg; if (ndeg < mindeg) mindeg = ndeg; } num = 0; /* Perform threshold search to get a node of min degree. * Variable search point to where search should start. */ s200: search = 1; thresh = mindeg; mindeg = neqns; s300: nump1 = num + 1; if (nump1 > search) search = nump1; for (j = search; j <= neqns; j++) { node = perm[j]; if (marker[node] >= 0) { ndeg = deg[node]; if (ndeg <= thresh) goto s500; if (ndeg < mindeg) mindeg = ndeg; } } goto s200; /* Node has minimum degree. Find its reachable sets by calling * qmdrch. */ s500: search = j; nofsub += deg[node]; marker[node] = 1; qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset, &nhdsze, nbrhd); /* Eliminate all nodes indistinguishable from node. They are given * by node, qlink[node], ... . */ nxnode = node; s600: num++; np = invp[nxnode]; ip = perm[num]; perm[np] = ip; invp[ip] = np; perm[num] = nxnode; invp[nxnode] = num; deg[nxnode] = -1; nxnode = qlink[nxnode]; if (nxnode > 0) goto s600; if (rchsze > 0) { /* Update the degrees of the nodes in the reachable set and * identify indistinguishable nodes. */ qmdupd(xadj, adjncy, &rchsze, rchset, deg, qsize, qlink, marker, &rchset[rchsze+1], &nbrhd[nhdsze+1]); /* Reset marker value of nodes in reach set. Update threshold * value for cyclic search. Also call qmdqt to form new * quotient graph. */ marker[node] = 0; for (irch = 1; irch <= rchsze; irch++) { inode = rchset[irch]; if (marker[inode] >= 0) { marker[inode] = 0; ndeg = deg[inode]; if (ndeg < mindeg) mindeg = ndeg; if (ndeg <= thresh) { mindeg = thresh; thresh = ndeg; search = invp[inode]; } } } if (nhdsze > 0) qmdqt(&node, xadj, adjncy, marker, &rchsze, rchset, nbrhd); } if (num < neqns) goto s300; return; # undef neqns # undef nofsub } /*********************************************************************** * NAME * * qmdrch - Quotient MD ReaCHable set * * SYNOPSIS * * #include "qmd.h" * void qmdrch(int *root, int xadj[], int adjncy[], int deg[], * int marker[], int *rchsze, int rchset[], int *nhdsze, * int nbrhd[]); * * PURPOSE * * This subroutine determines the reachable set of a node through a * given subset. The adjancy structure is assumed to be stored in a * quotient graph format. * * INPUT PARAMETERS * * root - the given node not in the subset; * (xadj, adjncy) - * the adjancy structure pair; * deg - the degree vector. deg[i] < 0 means the node belongs to the * given subset. * * OUTPUT PARAMETERS * * (rchsze, rchset) - * the reachable set; * (nhdsze, nbrhd) - * the neighborhood set. * * UPDATED PARAMETERS * * marker - the marker vector for reach and nbrhd sets. > 0 means the * node is in reach set. < 0 means the node has been merged * with others in the quotient or it is in nbrhd set. ***********************************************************************/ void qmdrch(int *_root, int xadj[], int adjncy[], int deg[], int marker[], int *_rchsze, int rchset[], int *_nhdsze, int nbrhd[]) { int i, istop, istrt, j, jstop, jstrt, nabor, node; # define root (*_root) # define rchsze (*_rchsze) # define nhdsze (*_nhdsze) /* Loop through the neighbors of root in the quotient graph. */ nhdsze = 0; rchsze = 0; istrt = xadj[root]; istop = xadj[root+1] - 1; if (istop < istrt) return; for (i = istrt; i <= istop; i++) { nabor = adjncy[i]; if (nabor == 0) return; if (marker[nabor] == 0) { if (deg[nabor] >= 0) { /* Include nabor into the reachable set. */ rchsze++; rchset[rchsze] = nabor; marker[nabor] = 1; goto s600; } /* nabor has been eliminated. Find nodes reachable from * it. */ marker[nabor] = -1; nhdsze++; nbrhd[nhdsze] = nabor; s300: jstrt = xadj[nabor]; jstop = xadj[nabor+1] - 1; for (j = jstrt; j <= jstop; j++) { node = adjncy[j]; nabor = - node; if (node < 0) goto s300; if (node == 0) goto s600; if (marker[node] == 0) { rchsze++; rchset[rchsze] = node; marker[node] = 1; } } } s600: ; } return; # undef root # undef rchsze # undef nhdsze } /*********************************************************************** * NAME * * qmdqt - Quotient MD Quotient graph Transformation * * SYNOPSIS * * #include "qmd.h" * void qmdqt(int *root, int xadj[], int adjncy[], int marker[], * int *rchsze, int rchset[], int nbrhd[]); * * PURPOSE * * This subroutine performs the quotient graph transformation after a * node has been eliminated. * * INPUT PARAMETERS * * root - the node just eliminated. It becomes the representative of * the new supernode; * (xadj, adjncy) - * the adjancy structure; * (rchsze, rchset) - * the reachable set of root in the old quotient graph; * nbrhd - the neighborhood set which will be merged with root to form * the new supernode; * marker - the marker vector. * * UPDATED PARAMETERS * * adjncy - becomes the adjncy of the quotient graph. ***********************************************************************/ void qmdqt(int *_root, int xadj[], int adjncy[], int marker[], int *_rchsze, int rchset[], int nbrhd[]) { int inhd, irch, j, jstop, jstrt, link, nabor, node; # define root (*_root) # define rchsze (*_rchsze) irch = 0; inhd = 0; node = root; s100: jstrt = xadj[node]; jstop = xadj[node+1] - 2; if (jstop >= jstrt) { /* Place reach nodes into the adjacent list of node. */ for (j = jstrt; j <= jstop; j++) { irch++; adjncy[j] = rchset[irch]; if (irch >= rchsze) goto s400; } } /* Link to other space provided by the nbrhd set. */ link = adjncy[jstop+1]; node = - link; if (link >= 0) { inhd++; node = nbrhd[inhd]; adjncy[jstop+1] = - node; } goto s100; /* All reachable nodes have been saved. End the adjacent list. * Add root to the neighborhood list of each node in the reach * set. */ s400: adjncy[j+1] = 0; for (irch = 1; irch <= rchsze; irch++) { node = rchset[irch]; if (marker[node] >= 0) { jstrt = xadj[node]; jstop = xadj[node+1] - 1; for (j = jstrt; j <= jstop; j++) { nabor = adjncy[j]; if (marker[nabor] < 0) { adjncy[j] = root; goto s600; } } } s600: ; } return; # undef root # undef rchsze } /*********************************************************************** * NAME * * qmdupd - Quotient MD UPDate * * SYNOPSIS * * #include "qmd.h" * void qmdupd(int xadj[], int adjncy[], int *nlist, int list[], * int deg[], int qsize[], int qlink[], int marker[], int rchset[], * int nbrhd[]); * * PURPOSE * * This routine performs degree update for a set of nodes in the minimum * degree algorithm. * * INPUT PARAMETERS * * (xadj, adjncy) - * the adjancy structure; * (nlist, list) - * the list of nodes whose degree has to be updated. * * UPDATED PARAMETERS * * deg - the degree vector; * qsize - size of indistinguishable supernodes; * qlink - linked list for indistinguishable nodes; * marker - used to mark those nodes in reach/nbrhd sets. * * WORKING PARAMETERS * * rchset - the reachable set; * nbrhd - the neighborhood set. * * PROGRAM SUBROUTINES * * qmdmrg. ***********************************************************************/ void qmdupd(int xadj[], int adjncy[], int *_nlist, int list[], int deg[], int qsize[], int qlink[], int marker[], int rchset[], int nbrhd[]) { int deg0, deg1, il, inhd, inode, irch, j, jstop, jstrt, mark, nabor, nhdsze, node, rchsze; # define nlist (*_nlist) /* Find all eliminated supernodes that are adjacent to some nodes * in the given list. Put them into (nhdsze, nbrhd). deg0 contains * the number of nodes in the list. */ if (nlist <= 0) return; deg0 = 0; nhdsze = 0; for (il = 1; il <= nlist; il++) { node = list[il]; deg0 += qsize[node]; jstrt = xadj[node]; jstop = xadj[node+1] - 1; for (j = jstrt; j <= jstop; j++) { nabor = adjncy[j]; if (marker[nabor] == 0 && deg[nabor] < 0) { marker[nabor] = -1; nhdsze++; nbrhd[nhdsze] = nabor; } } } /* Merge indistinguishable nodes in the list by calling the * subroutine qmdmrg. */ if (nhdsze > 0) qmdmrg(xadj, adjncy, deg, qsize, qlink, marker, °0, &nhdsze, nbrhd, rchset, &nbrhd[nhdsze+1]); /* Find the new degrees of the nodes that have not been merged. */ for (il = 1; il <= nlist; il++) { node = list[il]; mark = marker[node]; if (mark == 0 || mark == 1) { marker[node] = 2; qmdrch(&node, xadj, adjncy, deg, marker, &rchsze, rchset, &nhdsze, nbrhd); deg1 = deg0; if (rchsze > 0) { for (irch = 1; irch <= rchsze; irch++) { inode = rchset[irch]; deg1 += qsize[inode]; marker[inode] = 0; } } deg[node] = deg1 - 1; if (nhdsze > 0) { for (inhd = 1; inhd <= nhdsze; inhd++) { inode = nbrhd[inhd]; marker[inode] = 0; } } } } return; # undef nlist } /*********************************************************************** * NAME * * qmdmrg - Quotient MD MeRGe * * SYNOPSIS * * #include "qmd.h" * void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], * int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[], * int rchset[], int ovrlp[]); * * PURPOSE * * This routine merges indistinguishable nodes in the minimum degree * ordering algorithm. It also computes the new degrees of these new * supernodes. * * INPUT PARAMETERS * * (xadj, adjncy) - * the adjancy structure; * deg0 - the number of nodes in the given set; * (nhdsze, nbrhd) - * the set of eliminated supernodes adjacent to some nodes in * the set. * * UPDATED PARAMETERS * * deg - the degree vector; * qsize - size of indistinguishable nodes; * qlink - linked list for indistinguishable nodes; * marker - the given set is given by those nodes with marker value set * to 1. Those nodes with degree updated will have marker value * set to 2. * * WORKING PARAMETERS * * rchset - the reachable set; * ovrlp - temp vector to store the intersection of two reachable sets. ***********************************************************************/ void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], int qlink[], int marker[], int *_deg0, int *_nhdsze, int nbrhd[], int rchset[], int ovrlp[]) { int deg1, head, inhd, iov, irch, j, jstop, jstrt, link, lnode, mark, mrgsze, nabor, node, novrlp, rchsze, root; # define deg0 (*_deg0) # define nhdsze (*_nhdsze) /* Initialization. */ if (nhdsze <= 0) return; for (inhd = 1; inhd <= nhdsze; inhd++) { root = nbrhd[inhd]; marker[root] = 0; } /* Loop through each eliminated supernode in the set * (nhdsze, nbrhd). */ for (inhd = 1; inhd <= nhdsze; inhd++) { root = nbrhd[inhd]; marker[root] = -1; rchsze = 0; novrlp = 0; deg1 = 0; s200: jstrt = xadj[root]; jstop = xadj[root+1] - 1; /* Determine the reachable set and its intersection with the * input reachable set. */ for (j = jstrt; j <= jstop; j++) { nabor = adjncy[j]; root = - nabor; if (nabor < 0) goto s200; if (nabor == 0) break; mark = marker[nabor]; if (mark == 0) { rchsze++; rchset[rchsze] = nabor; deg1 += qsize[nabor]; marker[nabor] = 1; } else if (mark == 1) { novrlp++; ovrlp[novrlp] = nabor; marker[nabor] = 2; } } /* From the overlapped set, determine the nodes that can be * merged together. */ head = 0; mrgsze = 0; for (iov = 1; iov <= novrlp; iov++) { node = ovrlp[iov]; jstrt = xadj[node]; jstop = xadj[node+1] - 1; for (j = jstrt; j <= jstop; j++) { nabor = adjncy[j]; if (marker[nabor] == 0) { marker[node] = 1; goto s1100; } } /* Node belongs to the new merged supernode. Update the * vectors qlink and qsize. */ mrgsze += qsize[node]; marker[node] = -1; lnode = node; s900: link = qlink[lnode]; if (link > 0) { lnode = link; goto s900; } qlink[lnode] = head; head = node; s1100: ; } if (head > 0) { qsize[head] = mrgsze; deg[head] = deg0 + deg1 - 1; marker[head] = 2; } /* Reset marker values. */ root = nbrhd[inhd]; marker[root] = 0; if (rchsze > 0) { for (irch = 1; irch <= rchsze; irch++) { node = rchset[irch]; marker[node] = 0; } } } return; # undef deg0 # undef nhdsze } /* eof */ glpk-4.52.1/src/misc/qmd.h0000644000062000006210000000415712175147600014404 0ustar maomkpasswd/* qmd.h (quotient minimum degree algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2001, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef QMD_H #define QMD_H #define genqmd _glp_genqmd void genqmd(int *neqns, int xadj[], int adjncy[], int perm[], int invp[], int deg[], int marker[], int rchset[], int nbrhd[], int qsize[], int qlink[], int *nofsub); /* GENeral Quotient Minimum Degree algorithm */ #define qmdrch _glp_qmdrch void qmdrch(int *root, int xadj[], int adjncy[], int deg[], int marker[], int *rchsze, int rchset[], int *nhdsze, int nbrhd[]); /* Quotient MD ReaCHable set */ #define qmdqt _glp_qmdqt void qmdqt(int *root, int xadj[], int adjncy[], int marker[], int *rchsze, int rchset[], int nbrhd[]); /* Quotient MD Quotient graph Transformation */ #define qmdupd _glp_qmdupd void qmdupd(int xadj[], int adjncy[], int *nlist, int list[], int deg[], int qsize[], int qlink[], int marker[], int rchset[], int nbrhd[]); /* Quotient MD UPDate */ #define qmdmrg _glp_qmdmrg void qmdmrg(int xadj[], int adjncy[], int deg[], int qsize[], int qlink[], int marker[], int *deg0, int *nhdsze, int nbrhd[], int rchset[], int ovrlp[]); /* Quotient MD MeRGe */ #endif /* eof */ glpk-4.52.1/src/misc/relax4.c0000644000062000006210000027304312175147600015017 0ustar maomkpasswd/* relax4.c (relaxation method of Bertsekas and Tseng) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * THIS CODE IS THE RESULT OF TRANSLATION OF THE FORTRAN CODE RELAX4. * * THE TRANSLATION HAS BEEN DONE WITH THE PERMISSION OF THE AUTHOR OF * THE ORIGINAL FORTRAN CODE PROF. DIMITRI P. BERTSEKAS, MASSACHUSETTS * INSTITUTE OF TECHNOLOGY, CAMBRIDGE, MASSACHUSETTS, USA. * * The translation was made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "relax4.h" /*********************************************************************** * WARNING * * A serious bug was *tentatively* fixed in this code (see #if/#endif * marked by 'mao'). * * This bug is inherited from the original Fortran version of the * RELAX-IV code. Unfortunately, the code is very intricate, so this * bug is still under investigation. Thanks to Sylvain Fournier for bug * report. * * RELAX-IV bug details * -------------------- * In the original RELAX-IV code there are four similar fragments in * subroutines ascnt1 and ascnt2 like this: * * C * C DECREASE THE PRICES OF THE SCANNED NODES BY DELPRC. * C ADJUST FLOW TO MAINTAIN COMPLEMENTARY SLACKNESS WITH * C THE PRICES. * C * NB = 0 * DO 6 I=1,NSAVE * . . . * IF (RC(ARC).EQ.0) THEN * DELX=DELX+U(ARC) * NB = NB + 1 * PRDCSR(NB) = ARC * END IF * . . . * * On some instances the variable NB becomes greater than N (the number * of nodes) that leads to indexing error, because the array PRDCSR is * declared as array of N elements (more precisely, as array of MAXNN * elements, however, NB becomes even much greater than MAXNN). ***********************************************************************/ #define false 0 #define true 1 /*********************************************************************** * NAME * * RELAX-IV (version of October 1994) * * PURPOSE * * This routine implements the relaxation method of Bertsekas and Tseng * (see [1], [2]) for linear cost ordinary network flow problems. * * [1] Bertsekas, D. P., "A Unified Framework for Primal-Dual Methods" * Mathematical Programming, Vol. 32, 1985, pp. 125-145. * [2] Bertsekas, D. P., and Tseng, P., "Relaxation Methods for * Minimum Cost" Operations Research, Vol. 26, 1988, pp. 93-114. * * The relaxation method is also described in the books: * * [3] Bertsekas, D. P., "Linear Network Optimization: Algorithms and * Codes" MIT Press, 1991. * [4] Bertsekas, D. P. and Tsitsiklis, J. N., "Parallel and Distributed * Computation: Numerical Methods", Prentice-Hall, 1989. * [5] Bertsekas, D. P., "Network Optimization: Continuous and Discrete * Models", Athena Scientific, 1998. * * RELEASE NOTE * * This version of relaxation code has option for a special crash * procedure for the initial price-flow pair. This is recommended for * difficult problems where the default initialization results in long * running times. crash = 1 corresponds to an auction/shortest path * method * * These initializations are recommended in the absence of any prior * information on a favorable initial flow-price vector pair that * satisfies complementary slackness. * * The relaxation portion of the code differs from the code RELAXT-III * and other earlier relaxation codes in that it maintains the set of * nodes with nonzero deficit in a fifo queue. Like its predecessor * RELAXT-III, this code maintains a linked list of balanced (i.e., of * zero reduced cost) arcs so to reduce the work in labeling and * scanning. Unlike RELAXT-III, it does not use selectively shortest * path iterations for initialization. * * SOURCE * * The original Fortran code was written by Dimitri P. Bertsekas and * Paul Tseng, with a contribution by Jonathan Eckstein in the phase II * initialization. The original Fortran routine AUCTION was written by * Dimitri P. Bertsekas and is based on the method described in the * paper: * * [6] Bertsekas, D. P., "An Auction/Sequential Shortest Path Algorithm * for the Minimum Cost Flow Problem", LIDS Report P-2146, MIT, * Nov. 1992. * * For inquiries about the original Fortran code, please contact: * * Dimitri P. Bertsekas * Laboratory for information and decision systems * Massachusetts Institute of Technology * Cambridge, MA 02139 * (617) 253-7267, dimitrib@mit.edu * * This code is the result of translation of the original Fortran code. * The translation was made by Andrew Makhorin . * * USER GUIDELINES * * This routine is in the public domain to be used only for research * purposes. It cannot be used as part of a commercial product, or to * satisfy in any part commercial delivery requirements to government * or industry, without prior agreement with the authors. Users are * requested to acknowledge the authorship of the code, and the * relaxation method. * * No modification should be made to this code other than the minimal * necessary to make it compatible with specific platforms. * * INPUT PARAMETERS (see notes 1, 2, 4) * * n = number of nodes * na = number of arcs * large = a very large integer to represent infinity * (see note 3) * repeat = true if initialization is to be skipped * (false otherwise) * crash = 0 if default initialization is used * 1 if auction initialization is used * startn[j] = starting node for arc j, j = 1,...,na * endn[j] = ending node for arc j, j = 1,...,na * fou[i] = first arc out of node i, i = 1,...,n * nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na * fin[i] = first arc into node i, i = 1,...,n * nxtin[j] = next arc into the ending node of arc j, j = 1,...,na * * UPDATED PARAMETERS (see notes 1, 3, 4) * * rc[j] = reduced cost of arc j, j = 1,...,na * u[j] = capacity of arc j on input * and (capacity of arc j) - x[j] on output, j = 1,...,na * dfct[i] = demand at node i on input * and zero on output, i = 1,...,n * * OUTPUT PARAMETERS (see notes 1, 3, 4) * * x[j] = flow on arc j, j = 1,...,na * nmultinode = number of multinode relaxation iterations in RELAX4 * iter = number of relaxation iterations in RELAX4 * num_augm = number of flow augmentation steps in RELAX4 * num_ascnt = number of multinode ascent steps in RELAX4 * nsp = number of auction/shortest path iterations * * WORKING PARAMETERS (see notes 1, 4, 5) * * label[1+n], prdcsr[1+n], save[1+na], tfstou[1+n], tnxtou[1+na], * tfstin[1+n], tnxtin[1+na], nxtqueue[1+n], scan[1+n], mark[1+n], * extend_arc[1+n], sb_level[1+n], sb_arc[1+n] * * RETURNS * * 0 = normal return * 1,...,8 = problem is found to be infeasible * * NOTE 1 * * To run in limited memory systems, declare the arrays startn, endn, * nxtin, nxtou, fin, fou, label, prdcsr, save, tfstou, tnxtou, tfstin, * tnxtin, ddpos, ddneg, nxtqueue as short instead. * * NOTE 2 * * This routine makes no effort to initialize with a favorable x from * amongst those flow vectors that satisfy complementary slackness with * the initial reduced cost vector rc. If a favorable x is known, then * it can be passed, together with the corresponding arrays u and dfct, * to this routine directly. This, however, requires that the capacity * tightening portion and the flow initialization portion of this * routine (up to line labeled 90) be skipped. * * NOTE 3 * * All problem data should be less than large in magnitude, and large * should be less than, say, 1/4 the largest int of the machine used. * This will guard primarily against overflow in uncapacitated problems * where the arc capacities are taken finite but very large. Note, * however, that as in all codes operating with integers, overflow may * occur if some of the problem data takes very large values. * * NOTE 4 * * [This note being specific to Fortran was removed.-A.M.] * * NOTE 5 * * ddpos and ddneg are arrays that give the directional derivatives for * all positive and negative single-node price changes. These are used * only in phase II of the initialization procedure, before the linked * list of balanced arcs comes to play. Therefore, to reduce storage, * they are equivalence to tfstou and tfstin, which are of the same size * (number of nodes) and are used only after the tree comes into use. */ static void ascnt1(struct relax4_csa *csa, int dm, int *delx, int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, int *prevnode); static void ascnt2(struct relax4_csa *csa, int dm, int *delx, int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, int *prevnode); static int auction(struct relax4_csa *csa); int relax4(struct relax4_csa *csa) { /* input parameters */ int n = csa->n; int na = csa->na; int large = csa->large; int repeat = csa->repeat; int crash = csa->crash; int *startn = csa->startn; int *endn = csa->endn; int *fou = csa->fou; int *nxtou = csa->nxtou; int *fin = csa->fin; int *nxtin = csa->nxtin; /* updated parameters */ int *rc = csa->rc; int *u = csa->u; int *dfct = csa->dfct; /* output parameters */ int *x = csa->x; # define nmultinode (csa->nmultinode) # define iter (csa->iter) # define num_augm (csa->num_augm) # define num_ascnt (csa->num_ascnt) # define nsp (csa->nsp) /* working parameters */ int *label = csa->label; int *prdcsr = csa->prdcsr; int *save = csa->save; int *tfstou = csa->tfstou; int *tnxtou = csa->tnxtou; int *tfstin = csa->tfstin; int *tnxtin = csa->tnxtin; int *nxtqueue = csa->nxtqueue; char *scan = csa->scan; char *mark = csa->mark; int *ddpos = tfstou; int *ddneg = tfstin; /* local variables */ int arc, augnod, capin, capout, defcit, delprc, delx, dm, dp, dx, feasbl, i, ib, indef, j, lastqueue, maxcap, narc, nb, nlabel, node, node2, node_def, naugnod, nscan, num_passes, numnz, numnz_new, numpasses, nxtarc, nxtbrk, nxtnode, passes, pchange, posit, prevnode, prvarc, quit, rdcost, scapin, scapou, svitch, t, t1, t2, tmparc, tp, trc, ts; /*--------------------------------------------------------------*/ /* Initialization phase I */ /* In this phase, we reduce the arc capacities by as much as * possible without changing the problem; then we set the initial * flow array x, together with the corresponding arrays u and * dfct. */ /* This phase and phase II (from here up to line labeled 90) can * be skipped (by setting repeat to true) if the calling program * places in common user-chosen values for the arc flows, the * residual arc capacities, and the nodal deficits. When this is * done, it is critical that the flow and the reduced cost for * each arc satisfy complementary slackness and the dfct array * properly correspond to the initial arc/flows. */ if (repeat) goto L90; for (node = 1; node <= n; node++) { node_def = dfct[node]; ddpos[node] = node_def; ddneg[node] = -node_def; maxcap = 0; scapou = 0; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { if (scapou <= large - u[arc]) scapou += u[arc]; else goto L10; } if (scapou <= large - node_def) capout = scapou + node_def; else goto L10; if (capout < 0) { /* problem is infeasible */ /* exogenous flow into node exceeds out capacity */ return 1; } scapin = 0; for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { if (u[arc] > capout) u[arc] = capout; if (maxcap < u[arc]) maxcap = u[arc]; if (scapin <= large - u[arc]) scapin += u[arc]; else goto L10; } if (scapin <= large + node_def) capin = scapin - node_def; else goto L10; if (capin < 0) { /* problem is infeasible */ /* exogenous flow out of node exceeds in capacity */ return 2; } for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { if (u[arc] > capin) u[arc] = capin; } L10: ; } /*--------------------------------------------------------------*/ /* Initialization phase II */ /* In this phase, we initialize the prices and flows by either * calling the routine auction or by performing only single node * (coordinate) relaxation iterations. */ if (crash == 1) { nsp = 0; if (auction(csa) != 0) { /* problem is found to be infeasible */ return 3; } goto L70; } /* Initialize the arc flows to satisfy complementary slackness * with the prices. u[arc] is the residual capacity of arc, and * x[arc] is the flow. These two always add up to the total * capacity for arc. Also compute the directional derivatives for * each coordinate and compute the actual deficits. */ for (arc = 1; arc <= na; arc++) { x[arc] = 0; if (rc[arc] <= 0) { t = u[arc]; t1 = startn[arc]; t2 = endn[arc]; ddpos[t1] += t; ddneg[t2] += t; if (rc[arc] < 0) { x[arc] = t; u[arc] = 0; dfct[t1] += t; dfct[t2] -= t; ddneg[t1] -= t; ddpos[t2] -= t; } } } /* Make 2 or 3 passes through all nodes, performing only single * node relaxation iterations. The number of passes depends on the * density of the network. */ if (na > n * 10) numpasses = 2; else numpasses = 3; for (passes = 1; passes <= numpasses; passes++) for (node = 1; node <= n; node++) { if (dfct[node] == 0) continue; if (ddpos[node] <= 0) { /* Compute delprc, the stepsize to the next breakpoint in * the dual cost as the price of node is increased. * [Since the reduced cost of all outgoing (resp., incoming) * arcs will decrease (resp., increase) as the price of node * is increased, the next breakpoint is the minimum of the * positive reduced cost on outgoing arcs and of the * negative reduced cost on incoming arcs.] */ delprc = large; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { trc = rc[arc]; if ((trc > 0) && (trc < delprc)) delprc = trc; } for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { trc = rc[arc]; if ((trc < 0) && (trc > -delprc)) delprc = -trc; } /* If no breakpoint is left and dual ascent is still * possible, the problem is infeasible. */ if (delprc >= large) { if (ddpos[node] == 0) continue; return 4; } /* delprc is the stepsize to next breakpoint. Increase * price of node by delprc and compute the stepsize to the * next breakpoint in the dual cost. */ L53: nxtbrk = large; /* Look at all arcs out of node. */ for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { trc = rc[arc]; if (trc == 0) { t1 = endn[arc]; t = u[arc]; if (t > 0) { dfct[node] += t; dfct[t1] -= t; x[arc] = t; u[arc] = 0; } else t = x[arc]; ddneg[node] -= t; ddpos[t1] -= t; } /* Decrease the reduced costs on all outgoing arcs. */ trc -= delprc; if ((trc > 0) && (trc < nxtbrk)) nxtbrk = trc; else if (trc == 0) { /* Arc goes from inactive to balanced. Update the rate * of dual ascent at node and at its neighbor. */ ddpos[node] += u[arc]; ddneg[endn[arc]] += u[arc]; } rc[arc] = trc; } /* Look at all arcs into node. */ for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { trc = rc[arc]; if (trc == 0) { t1 = startn[arc]; t = x[arc]; if (t > 0) { dfct[node] += t; dfct[t1] -= t; u[arc] = t; x[arc] = 0; } else t = u[arc]; ddpos[t1] -= t; ddneg[node] -= t; } /* Increase the reduced cost on all incoming arcs. */ trc += delprc; if ((trc < 0) && (trc > -nxtbrk)) nxtbrk = -trc; else if (trc == 0) { /* Arc goes from active to balanced. Update the rate * of dual ascent at node and at its neighbor. */ ddneg[startn[arc]] += x[arc]; ddpos[node] += x[arc]; } rc[arc] = trc; } /* If price of node can be increased further without * decreasing the dual cost (even the dual cost doesn't * increase), return to increase the price further. */ if ((ddpos[node] <= 0) && (nxtbrk < large)) { delprc = nxtbrk; goto L53; } } else if (ddneg[node] <= 0) { /* Compute delprc, the stepsize to the next breakpoint in * the dual cost as the price of node is decreased. * [Since the reduced cost of all outgoing (resp., incoming) * arcs will increase (resp., decrease) as the price of node * is decreased, the next breakpoint is the minimum of the * negative reduced cost on outgoing arcs and of the * positive reduced cost on incoming arcs.] */ delprc = large; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { trc = rc[arc]; if ((trc < 0) && (trc > -delprc)) delprc = -trc; } for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { trc = rc[arc]; if ((trc > 0) && (trc < delprc)) delprc = trc; } /* If no breakpoint is left and dual ascent is still * possible, the problem is infeasible. */ if (delprc == large) { if (ddneg[node] == 0) continue; return 5; } /* delprc is the stepsize to next breakpoint. Decrease * price of node by delprc and compute the stepsize to the * next breakpoint in the dual cost. */ L63: nxtbrk = large; /* Look at all arcs out of node. */ for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { trc = rc[arc]; if (trc == 0) { t1 = endn[arc]; t = x[arc]; if (t > 0) { dfct[node] -= t; dfct[t1] += t; u[arc] = t; x[arc] = 0; } else t = u[arc]; ddpos[node] -= t; ddneg[t1] -= t; } /* Increase the reduced cost on all outgoing arcs. */ trc += delprc; if ((trc < 0) && (trc > -nxtbrk)) nxtbrk = -trc; else if (trc == 0) { /* Arc goes from active to balanced. Update the rate * of dual ascent at node and at its neighbor. */ ddneg[node] += x[arc]; ddpos[endn[arc]] += x[arc]; } rc[arc] = trc; } /* Look at all arcs into node. */ for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { trc = rc[arc]; if (trc == 0) { t1 = startn[arc]; t = u[arc]; if (t > 0) { dfct[node] -= t; dfct[t1] += t; x[arc] = t; u[arc] = 0; } else t = x[arc]; ddneg[t1] -= t; ddpos[node] -= t; } /* Decrease the reduced cost on all incoming arcs. */ trc -= delprc; if ((trc > 0) && (trc < nxtbrk)) nxtbrk = trc; else if (trc == 0) { /* Arc goes from inactive to balanced. Update the rate * of dual ascent at node and at its neighbor. */ ddpos[startn[arc]] += u[arc]; ddneg[node] += u[arc]; } rc[arc] = trc; } /* If price of node can be decreased further without * decreasing the dual cost (even the dual cost doesn't * increase), return to decrease the price further. */ if ((ddneg[node] <= 0) && (nxtbrk < large)) { delprc = nxtbrk; goto L63; } } } /*--------------------------------------------------------------*/ L70: /* Initialize tree data structure. */ for (i = 1; i <= n; i++) tfstou[i] = tfstin[i] = 0; for (i = 1; i <= na; i++) { tnxtin[i] = tnxtou[i] = -1; if (rc[i] == 0) { tnxtou[i] = tfstou[startn[i]]; tfstou[startn[i]] = i; tnxtin[i] = tfstin[endn[i]]; tfstin[endn[i]] = i; } } L90: /* Initialize other variables. */ feasbl = true; iter = 0; nmultinode = 0; num_augm = 0; num_ascnt = 0; num_passes = 0; numnz = n; numnz_new = 0; svitch = false; for (i = 1; i <= n; i++) mark[i] = scan[i] = false; nlabel = 0; /* RELAX4 uses an adaptive strategy to decide whether to continue * the scanning process after a multinode price change. * The threshold parameter tp and ts that control this strategy * are set in the next two lines. */ tp = 10; ts = n / 15; /* Initialize the queue of nodes with nonzero deficit. */ for (node = 1; node <= n - 1; node++) nxtqueue[node] = node + 1; nxtqueue[n] = 1; node = lastqueue = n; /*--------------------------------------------------------------*/ /* Start the relaxation algorithm. */ L100: /* Code for advancing the queue of nonzero deficit nodes. */ prevnode = node; node = nxtqueue[node]; defcit = dfct[node]; if (node == lastqueue) { numnz = numnz_new; numnz_new = 0; lastqueue = prevnode; num_passes++; } /* Code for deleting a node from the queue. */ if (defcit == 0) { nxtnode = nxtqueue[node]; if (node == nxtnode) return 0; else { nxtqueue[prevnode] = nxtnode; nxtqueue[node] = 0; node = nxtnode; goto L100; } } else posit = (defcit > 0); iter++; numnz_new++; if (posit) { /* Attempt a single node iteration from node with positive * deficit. */ pchange = false; indef = defcit; delx = 0; nb = 0; /* Check outgoing (probably) balanced arcs from node. */ for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc]) { if ((rc[arc] == 0) && (x[arc] > 0)) { delx += x[arc]; nb++; save[nb] = arc; } } /* Check incoming arcs. */ for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc]) { if ((rc[arc] == 0) && (u[arc] > 0)) { delx += u[arc]; nb++; save[nb] = -arc; } } /* End of initial node scan. */ L4018: /* If no price change is possible, exit. */ if (delx > defcit) { quit = (defcit < indef); goto L4016; } /* RELAX4 searches along the ascent direction for the best * price by checking the slope of the dual cost at successive * break points. First, we compute the distance to the next * break point. */ delprc = large; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { rdcost = rc[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { rdcost = rc[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } /* Check if problem is infeasible. */ if ((delx < defcit) && (delprc == large)) { /* The dual cost can be decreased without bound. */ return 6; } /* Skip flow adjustment if there is no flow to modify. */ if (delx == 0) goto L4014; /* Adjust the flow on the balanced arcs incident to node to * maintain complementary slackness after the price change. */ for (j = 1; j <= nb; j++) { arc = save[j]; if (arc > 0) { node2 = endn[arc]; t1 = x[arc]; dfct[node2] += t1; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } u[arc] += t1; x[arc] = 0; } else { narc = -arc; node2 = startn[narc]; t1 = u[narc]; dfct[node2] += t1; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } x[narc] += t1; u[narc] = 0; } } defcit -= delx; L4014: if (delprc == large) { quit = true; goto L4019; } /* Node corresponds to a dual ascent direction. Decrease the * price of node by delprc and compute the stepsize to the next * breakpoint in the dual cost. */ nb = 0; pchange = true; dp = delprc; delprc = large; delx = 0; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { rdcost = rc[arc] + dp; rc[arc] = rdcost; if (rdcost == 0) { nb++; save[nb] = arc; delx += x[arc]; } if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { rdcost = rc[arc] - dp; rc[arc] = rdcost; if (rdcost == 0) { nb++; save[nb] = -arc; delx += u[arc]; } if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } /* Return to check if another price change is possible. */ goto L4018; L4016: /* Perform flow augmentation at node. */ for (j = 1; j <= nb; j++) { arc = save[j]; if (arc > 0) { /* arc is an outgoing arc from node. */ node2 = endn[arc]; t1 = dfct[node2]; if (t1 < 0) { /* Decrease the total deficit by decreasing flow of * arc. */ quit = true; t2 = x[arc]; dx = defcit; if (dx > -t1) dx = -t1; if (dx > t2) dx = t2; defcit -= dx; dfct[node2] = t1 + dx; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } x[arc] = t2 - dx; u[arc] += dx; if (defcit == 0) break; } } else { /* -arc is an incoming arc to node. */ narc = -arc; node2 = startn[narc]; t1 = dfct[node2]; if (t1 < 0) { /* Decrease the total deficit by increasing flow of * -arc. */ quit = true; t2 = u[narc]; dx = defcit; if (dx > -t1) dx = -t1; if (dx > t2) dx = t2; defcit -= dx; dfct[node2] = t1 + dx; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } x[narc] += dx; u[narc] = t2 - dx; if (defcit == 0) break; } } } L4019: dfct[node] = defcit; /* Reconstruct the linked list of balance arcs incident to this * node. For each adjacent node, we add any newly balanced arcs * to the list, but do not bother removing formerly balanced * ones (they will be removed the next time each adjacent node * is scanned). */ if (pchange) { arc = tfstou[node]; tfstou[node] = 0; while (arc > 0) { nxtarc = tnxtou[arc]; tnxtou[arc] = -1; arc = nxtarc; } arc = tfstin[node]; tfstin[node] = 0; while (arc > 0) { nxtarc = tnxtin[arc]; tnxtin[arc] = -1; arc = nxtarc; } /* Now add the currently balanced arcs to the list for this * node (which is now empty), and the appropriate adjacent * ones. */ for (j = 1; j <= nb; j++) { arc = save[j]; if (arc < 0) arc = -arc; if (tnxtou[arc] < 0) { tnxtou[arc] = tfstou[startn[arc]]; tfstou[startn[arc]] = arc; } if (tnxtin[arc] < 0) { tnxtin[arc] = tfstin[endn[arc]]; tfstin[endn[arc]] = arc; } } } /* End of single node iteration for positive deficit node. */ } else { /* Attempt a single node iteration from node with negative * deficit. */ pchange = false; defcit = -defcit; indef = defcit; delx = 0; nb = 0; for (arc = tfstin[node]; arc > 0; arc = tnxtin[arc]) { if ((rc[arc] == 0) && (x[arc] > 0)) { delx += x[arc]; nb++; save[nb] = arc; } } for (arc = tfstou[node]; arc > 0; arc = tnxtou[arc]) { if ((rc[arc] == 0) && (u[arc] > 0)) { delx += u[arc]; nb++; save[nb] = -arc; } } L4028: if (delx >= defcit) { quit = (defcit < indef); goto L4026; } /* Compute distance to next breakpoint. */ delprc = large; for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { rdcost = rc[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { rdcost = rc[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } /* Check if problem is infeasible. */ if ((delx < defcit) && (delprc == large)) return 7; if (delx == 0) goto L4024; /* Flow augmentation is possible. */ for (j = 1; j <= nb; j++) { arc = save[j]; if (arc > 0) { node2 = startn[arc]; t1 = x[arc]; dfct[node2] -= t1; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } u[arc] += t1; x[arc] = 0; } else { narc = -arc; node2 = endn[narc]; t1 = u[narc]; dfct[node2] -= t1; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } x[narc] += t1; u[narc] = 0; } } defcit -= delx; L4024: if (delprc == large) { quit = true; goto L4029; } /* Price increase at node is possible. */ nb = 0; pchange = true; dp = delprc; delprc = large; delx = 0; for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { rdcost = rc[arc] + dp; rc[arc] = rdcost; if (rdcost == 0) { nb++; save[nb] = arc; delx += x[arc]; } if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { rdcost = rc[arc] - dp; rc[arc] = rdcost; if (rdcost == 0) { nb++; save[nb] = -arc; delx += u[arc]; } if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } goto L4028; L4026: /* Perform flow augmentation at node. */ for (j = 1; j <= nb; j++) { arc = save[j]; if (arc > 0) { /* arc is an incoming arc to node. */ node2 = startn[arc]; t1 = dfct[node2]; if (t1 > 0) { quit = true; t2 = x[arc]; dx = defcit; if (dx > t1) dx = t1; if (dx > t2) dx = t2; defcit -= dx; dfct[node2] = t1 - dx; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } x[arc] = t2 - dx; u[arc] += dx; if (defcit == 0) break; } } else { /* -arc is an outgoing arc from node. */ narc = -arc; node2 = endn[narc]; t1 = dfct[node2]; if (t1 > 0) { quit = true; t2 = u[narc]; dx = defcit; if (dx > t1) dx = t1; if (dx > t2) dx = t2; defcit -= dx; dfct[node2] = t1 - dx; if (nxtqueue[node2] == 0) { nxtqueue[prevnode] = node2; nxtqueue[node2] = node; prevnode = node2; } x[narc] += dx; u[narc] = t2 - dx; if (defcit == 0) break; } } } L4029: dfct[node] = -defcit; /* Reconstruct the list of balanced arcs incident to node. */ if (pchange) { arc = tfstou[node]; tfstou[node] = 0; while (arc > 0) { nxtarc = tnxtou[arc]; tnxtou[arc] = -1; arc = nxtarc; } arc = tfstin[node]; tfstin[node] = 0; while (arc > 0) { nxtarc = tnxtin[arc]; tnxtin[arc] = -1; arc = nxtarc; } /* Now add the currently balanced arcs to the list for this * node (which is now empty), and the appropriate adjacent * ones. */ for (j = 1; j <= nb; j++) { arc = save[j]; if (arc <= 0) arc = -arc; if (tnxtou[arc] < 0) { tnxtou[arc] = tfstou[startn[arc]]; tfstou[startn[arc]] = arc; } if (tnxtin[arc] < 0) { tnxtin[arc] = tfstin[endn[arc]]; tfstin[endn[arc]] = arc; } } } /* End of single node iteration for a negative deficit node. */ } if (quit || (num_passes <= 3)) goto L100; /* Do a multinode iteration from node. */ nmultinode++; /* If number of nonzero deficit nodes is small, continue labeling * until a flow augmentation is done. */ svitch = (numnz < tp); /* Unmark nodes labeled earlier. */ for (j = 1; j <= nlabel; j++) { node2 = label[j]; mark[node2] = scan[node2] = false; } /* Initialize labeling. */ nlabel = 1; label[1] = node; mark[node] = true; prdcsr[node] = 0; /* Scan starting node. */ scan[node] = true; nscan = 1; dm = dfct[node]; delx = 0; for (j = 1; j <= nb; j++) { arc = save[j]; if (arc > 0) { if (posit) node2 = endn[arc]; else node2 = startn[arc]; if (!mark[node2]) { nlabel++; label[nlabel] = node2; prdcsr[node2] = arc; mark[node2] = true; delx += x[arc]; } } else { narc = -arc; if (posit) node2 = startn[narc]; else node2 = endn[narc]; if (!mark[node2]) { nlabel++; label[nlabel] = node2; prdcsr[node2] = arc; mark[node2] = true; delx += u[narc]; } } } L4120:/* Start scanning a labeled but unscanned node. */ nscan++; /* Check to see if switch needs to be set to true so to continue * scanning even after a price change. */ svitch = svitch || ((nscan > ts) && (numnz < ts)); /* Scanning will continue until either an overestimate of the * residual capacity across the cut corresponding to the scanned * set of nodes (called delx) exceeds the absolute value of the * total deficit of the scanned nodes (called dm), or else an * augmenting path is found. Arcs that are in the tree but are not * balanced are removed as part of the scanning process. */ i = label[nscan]; scan[i] = true; naugnod = 0; if (posit) { /* Scanning node i in case of positive deficit. */ prvarc = 0; arc = tfstou[i]; while (arc > 0) { /* arc is an outgoing arc from node. */ if (rc[arc] == 0) { if (x[arc] > 0) { node2 = endn[arc]; if (!mark[node2]) { /* node2 is not labeled, so add node2 to the labeled set. */ prdcsr[node2] = arc; if (dfct[node2] < 0) { naugnod++; save[naugnod] = node2; } nlabel++; label[nlabel] = node2; mark[node2] = true; delx += x[arc]; } } prvarc = arc; arc = tnxtou[arc]; } else { tmparc = arc; arc = tnxtou[arc]; tnxtou[tmparc] = -1; if (prvarc == 0) tfstou[i] = arc; else tnxtou[prvarc] = arc; } } prvarc = 0; arc = tfstin[i]; while (arc > 0) { /* arc is an incoming arc into node. */ if (rc[arc] == 0) { if (u[arc] > 0) { node2 = startn[arc]; if (!mark[node2]) { /* node2 is not labeled, so add node2 to the * labeled set. */ prdcsr[node2] = -arc; if (dfct[node2] < 0) { naugnod++; save[naugnod] = node2; } nlabel++; label[nlabel] = node2; mark[node2] = true; delx += u[arc]; } } prvarc = arc; arc = tnxtin[arc]; } else { tmparc = arc; arc = tnxtin[arc]; tnxtin[tmparc] = -1; if (prvarc == 0) tfstin[i] = arc; else tnxtin[prvarc] = arc; } } /* Correct the residual capacity of the scanned node cut. */ arc = prdcsr[i]; if (arc > 0) delx -= x[arc]; else delx -= u[-arc]; /* End of scanning of node i for positive deficit case. */ } else { /* Scanning node i for negative deficit case. */ prvarc = 0; arc = tfstin[i]; while (arc > 0) { if (rc[arc] == 0) { if (x[arc] > 0) { node2 = startn[arc]; if (!mark[node2]) { prdcsr[node2] = arc; if (dfct[node2] > 0) { naugnod++; save[naugnod] = node2; } nlabel++; label[nlabel] = node2; mark[node2] = true; delx += x[arc]; } } prvarc = arc; arc = tnxtin[arc]; } else { tmparc = arc; arc = tnxtin[arc]; tnxtin[tmparc] = -1; if (prvarc == 0) tfstin[i] = arc; else tnxtin[prvarc] = arc; } } prvarc = 0; arc = tfstou[i]; while (arc > 0) { if (rc[arc] == 0) { if (u[arc] > 0) { node2 = endn[arc]; if (!mark[node2]) { prdcsr[node2] = -arc; if (dfct[node2] > 0) { naugnod++; save[naugnod] = node2; } nlabel++; label[nlabel] = node2; mark[node2] = true; delx += u[arc]; } } prvarc = arc; arc = tnxtou[arc]; } else { tmparc = arc; arc = tnxtou[arc]; tnxtou[tmparc] = -1; if (prvarc == 0) tfstou[i] = arc; else tnxtou[prvarc] = arc; } } arc = prdcsr[i]; if (arc > 0) delx -= x[arc]; else delx -= u[-arc]; } /* Add deficit of node scanned to dm. */ dm += dfct[i]; /* Check if the set of scanned nodes correspond to a dual ascent * direction; if yes, perform a price adjustment step, otherwise * continue labeling. */ if (nscan < nlabel) { if (svitch) goto L4210; if ((delx >= dm) && (delx >= -dm)) goto L4210; } /* Try a price change. * [Note that since delx - abs(dm) is an overestimate of ascent * slope, we may occasionally try a direction that is not an * ascent direction. In this case the ascnt routines return with * quit = false, so we continue labeling nodes.] */ if (posit) { ascnt1(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node, &prevnode); num_ascnt++; } else { ascnt2(csa, dm, &delx, &nlabel, &feasbl, &svitch, nscan, node, &prevnode); num_ascnt++; } if (!feasbl) return 8; if (!svitch) goto L100; /* Store those newly labeled nodes to which flow augmentation is * possible. */ naugnod = 0; for (j = nscan + 1; j <= nlabel; j++) { node2 = label[j]; if (posit && (dfct[node2] < 0)) { naugnod++; save[naugnod] = node2; } else if ((!posit) && (dfct[node2] > 0)) { naugnod++; save[naugnod] = node2; } } L4210:/* Check if flow augmentation is possible. If not, return to scan * another node. */ if (naugnod == 0) goto L4120; for (j = 1; j <= naugnod; j++) { num_augm++; augnod = save[j]; if (posit) { /* Do the augmentation from node with positive deficit. */ dx = -dfct[augnod]; ib = augnod; while (ib != node) { arc = prdcsr[ib]; if (arc > 0) { if (dx > x[arc]) dx = x[arc]; ib = startn[arc]; } else { if (dx > u[-arc]) dx = u[-arc]; ib = endn[-arc]; } } if (dx > dfct[node]) dx = dfct[node]; if (dx > 0) { /* Increase (decrease) the flow of all forward (backward) * arcs in the flow augmenting path. Adjust node deficit * accordingly. */ if (nxtqueue[augnod] == 0) { nxtqueue[prevnode] = augnod; nxtqueue[augnod] = node; prevnode = augnod; } dfct[augnod] += dx; dfct[node] -= dx; ib = augnod; while (ib != node) { arc = prdcsr[ib]; if (arc > 0) { x[arc] -= dx; u[arc] += dx; ib = startn[arc]; } else { narc = -arc; x[narc] += dx; u[narc] -= dx; ib = endn[narc]; } } } } else { /* Do the augmentation from node with negative deficit. */ dx = dfct[augnod]; ib = augnod; while (ib != node) { arc = prdcsr[ib]; if (arc > 0) { if (dx > x[arc]) dx = x[arc]; ib = endn[arc]; } else { if (dx > u[-arc]) dx = u[-arc]; ib = startn[-arc]; } } if (dx > -dfct[node]) dx = -dfct[node]; if (dx > 0) { /* Update the flow and deficits. */ if (nxtqueue[augnod] == 0) { nxtqueue[prevnode] = augnod; nxtqueue[augnod] = node; prevnode = augnod; } dfct[augnod] -= dx; dfct[node] += dx; ib = augnod; while (ib != node) { arc = prdcsr[ib]; if (arc > 0) { x[arc] -= dx; u[arc] += dx; ib = endn[arc]; } else { narc = -arc; x[narc] += dx; u[narc] -= dx; ib = startn[narc]; } } } } if (dfct[node] == 0) goto L100; if (dfct[augnod] != 0) svitch = false; } /* If node still has nonzero deficit and all newly labeled nodes * have same sign for their deficit as node, we can continue * labeling. In this case, continue labeling only when flow * augmentation is done relatively infrequently. */ if (svitch && (iter > 8 * num_augm)) goto L4120; /* Return to do another relaxation iteration. */ goto L100; # undef nmultinode # undef iter # undef num_augm # undef num_ascnt # undef nsp } /*********************************************************************** * NAME * * relax4_inidat - construct linked lists for network topology * * PURPOSE * * This routine constructs two linked lists for the network topology: * one list (given by fou, nxtou) for the outgoing arcs of nodes and * one list (given by fin, nxtin) for the incoming arcs of nodes. These * two lists are required by RELAX4. * * INPUT PARAMETERS * * n = number of nodes * na = number of arcs * startn[j] = starting node for arc j, j = 1,...,na * endn[j] = ending node for arc j, j = 1,...,na * * OUTPUT PARAMETERS * * fou[i] = first arc out of node i, i = 1,...,n * nxtou[j] = next arc out of the starting node of arc j, j = 1,...,na * fin[i] = first arc into node i, i = 1,...,n * nxtin[j] = next arc into the ending node of arc j, j = 1,...,na * * WORKING PARAMETERS * * tempin[1+n], tempou[1+n] */ void relax4_inidat(struct relax4_csa *csa) { /* input parameters */ int n = csa->n; int na = csa->na; int *startn = csa->startn; int *endn = csa->endn; /* output parameters */ int *fou = csa->fou; int *nxtou = csa->nxtou; int *fin = csa->fin; int *nxtin = csa->nxtin; /* working parameters */ int *tempin = csa->label; int *tempou = csa->prdcsr; /* local variables */ int i, i1, i2; for (i = 1; i <= n; i++) { fin[i] = fou[i] = 0; tempin[i] = tempou[i] = 0; } for (i = 1; i <= na; i++) { nxtin[i] = nxtou[i] = 0; i1 = startn[i]; i2 = endn[i]; if (fou[i1] != 0) nxtou[tempou[i1]] = i; else fou[i1] = i; tempou[i1] = i; if (fin[i2] != 0) nxtin[tempin[i2]] = i; else fin[i2] = i; tempin[i2] = i; } return; } /*********************************************************************** * NAME * * ascnt1 - multi-node price adjustment for positive deficit case * * PURPOSE * * This subroutine performs the multi-node price adjustment step for * the case where the scanned nodes have positive deficit. It first * checks if decreasing the price of the scanned nodes increases the * dual cost. If yes, then it decreases the price of all scanned nodes. * There are two possibilities for price decrease: if switch = true, * then the set of scanned nodes corresponds to an elementary direction * of maximal rate of ascent, in which case the price of all scanned * nodes are decreased until the next breakpoint in the dual cost is * encountered. At this point, some arc becomes balanced and more * node(s) are added to the labeled set and the subroutine is exited. * If switch = false, then the price of all scanned nodes are decreased * until the rate of ascent becomes negative (this corresponds to the * price adjustment step in which both the line search and the * degenerate ascent iteration are implemented). * * INPUT PARAMETERS * * dm = total deficit of scanned nodes * switch = true if labeling is to continue after price change * nscan = number of scanned nodes * curnode = most recently scanned node * n = number of nodes * na = number of arcs * large = a very large integer to represent infinity (see note 3) * startn[i] = starting node for the i-th arc, i = 1,...,na * endn[i] = ending node for the i-th arc, i = 1,...,na * fou[i] = first arc leaving i-th node, i = 1,...,n * nxtou[i] = next arc leaving the starting node of j-th arc, * i = 1,...,na * fin[i] = first arc entering i-th node, i = 1,...,n * nxtin[i] = next arc entering the ending node of j-th arc, * i = 1,...,na * * UPDATED PARAMETERS * * delx = a lower estimate of the total flow on balanced arcs in * the scanned-nodes cut * nlabel = number of labeled nodes * feasbl = false if problem is found to be infeasible * prevnode = the node before curnode in queue * rc[j] = reduced cost of arc j, j = 1,...,na * u[j] = residual capacity of arc j, j = 1,...,na * x[j] = flow on arc j, j = 1,...,na * dfct[i] = deficit at node i, i = 1,...,n * label[k] = k-th node labeled, k = 1,...,nlabel * prdcsr[i] = predecessor of node i in tree of labeled nodes (0 if i * is unlabeled), i = 1,...,n * tfstou[i] = first balanced arc out of node i, i = 1,...,n * tnxtou[j] = next balanced arc out of the starting node of arc j, * j = 1,...,na * tfstin[i] = first balanced arc into node i, i = 1,...,n * tnxtin[j] = next balanced arc into the ending node of arc j, * j = 1,...,na * nxtqueue[i] = node following node i in the fifo queue (0 if node is * not in the queue), i = 1,...,n * scan[i] = true if node i is scanned, i = 1,...,n * mark[i] = true if node i is labeled, i = 1,...,n * * WORKING PARAMETERS * * save[1+na] */ static void ascnt1(struct relax4_csa *csa, int dm, int *delx, int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, int *prevnode) { /* input parameters */ int n = csa->n; /* int na = csa->na; */ int large = csa->large; int *startn = csa->startn; int *endn = csa->endn; int *fou = csa->fou; int *nxtou = csa->nxtou; int *fin = csa->fin; int *nxtin = csa->nxtin; /* updated parameters */ # define delx (*delx) # define nlabel (*nlabel) # define feasbl (*feasbl) # define svitch (*svitch) # define prevnode (*prevnode) int *rc = csa->rc; int *u = csa->u; int *x = csa->x; int *dfct = csa->dfct; int *label = csa->label; int *prdcsr = csa->prdcsr; int *tfstou = csa->tfstou; int *tnxtou = csa->tnxtou; int *tfstin = csa->tfstin; int *tnxtin = csa->tnxtin; int *nxtqueue = csa->nxtqueue; char *scan = csa->scan; char *mark = csa->mark; int *save = csa->save; /* local variables */ int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1, t2, t3; /* Store the arcs between the set of scanned nodes and its * complement in save and compute delprc, the stepsize to the next * breakpoint in the dual cost in the direction of decreasing * prices of the scanned nodes. * [The arcs are stored into save by looking at the arcs incident * to either the set of scanned nodes or its complement, depending * on whether nscan > n/2 or not. This improves the efficiency of * storing.] */ delprc = large; dlx = 0; nsave = 0; if (nscan <= n / 2) { for (i = 1; i <= nscan; i++) { node = label[i]; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { /* arc points from scanned node to an unscanned node. */ node2 = endn[arc]; if (!scan[node2]) { nsave++; save[nsave] = arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node2] != arc)) dlx += x[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } } for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { /* arc points from unscanned node to scanned node. */ node2 = startn[arc]; if (!scan[node2]) { nsave++; save[nsave] = -arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node2] != -arc)) dlx += u[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } } } } else { for (node = 1; node <= n; node++) { if (scan[node]) continue; for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { node2 = startn[arc]; if (scan[node2]) { nsave++; save[nsave] = arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node] != arc)) dlx += x[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } } for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { node2 = endn[arc]; if (scan[node2]) { nsave++; save[nsave] = -arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node] != -arc)) dlx += u[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } } } } /* Check if the set of scanned nodes truly corresponds to a dual * ascent direction. [Here delx + dlx is the exact sum of the flow * on arcs from the scanned set to the unscanned set plus the * (capacity - flow) on arcs from the unscanned set to the scanned * set.] If this were not the case, set switch to true and exit * subroutine. */ if ((!svitch) && (delx + dlx >= dm)) { svitch = true; return; } delx += dlx; L4: /* Check that the problem is feasible. */ if (delprc == large) { /* We can increase the dual cost without bound, so the primal * problem is infeasible. */ feasbl = false; return; } /* Decrease the prices of the scanned nodes, add more nodes to * the labeled set and check if a newly labeled node has negative * deficit. */ if (svitch) { for (i = 1; i <= nsave; i++) { arc = save[i]; if (arc > 0) { rc[arc] += delprc; if (rc[arc] == 0) { node2 = endn[arc]; if (tnxtou[arc] < 0) { tnxtou[arc] = tfstou[startn[arc]]; tfstou[startn[arc]] = arc; } if (tnxtin[arc] < 0) { tnxtin[arc] = tfstin[node2]; tfstin[node2] = arc; } if (!mark[node2]) { prdcsr[node2] = arc; nlabel++; label[nlabel] = node2; mark[node2] = true; } } } else { arc = -arc; rc[arc] -= delprc; if (rc[arc] == 0) { node2 = startn[arc]; if (tnxtou[arc] < 0) { tnxtou[arc] = tfstou[node2]; tfstou[node2] = arc; } if (tnxtin[arc] < 0) { tnxtin[arc] = tfstin[endn[arc]]; tfstin[endn[arc]] = arc; } if (!mark[node2]) { prdcsr[node2] = -arc; nlabel++; label[nlabel] = node2; mark[node2] = true; } } } } return; } else { /* Decrease the prices of the scanned nodes by delprc. Adjust * flow to maintain complementary slackness with the prices. */ nb = 0; for (i = 1; i <= nsave; i++) { arc = save[i]; if (arc > 0) { t1 = rc[arc]; if (t1 == 0) { t2 = x[arc]; t3 = startn[arc]; dfct[t3] -= t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } t3 = endn[arc]; dfct[t3] += t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } u[arc] += t2; x[arc] = 0; } rc[arc] = t1 + delprc; #if 0 /* by mao; 26/IV-2013 */ if (rc[arc] == 0) #else if (rc[arc] == 0 && nb < n) #endif { delx += x[arc]; nb++; prdcsr[nb] = arc; } } else { arc = -arc; t1 = rc[arc]; if (t1 == 0) { t2 = u[arc]; t3 = startn[arc]; dfct[t3] += t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } t3 = endn[arc]; dfct[t3] -= t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } x[arc] += t2; u[arc] = 0; } rc[arc] = t1 - delprc; #if 0 /* by mao; 26/IV-2013 */ if (rc[arc] == 0) #else if (rc[arc] == 0 && nb < n) #endif { delx += u[arc]; nb++; prdcsr[nb] = arc; } } } } if (delx <= dm) { /* The set of scanned nodes still corresponds to a dual * (possibly degenerate) ascent direction. Compute the stepsize * delprc to the next breakpoint in the dual cost. */ delprc = large; for (i = 1; i <= nsave; i++) { arc = save[i]; if (arc > 0) { rdcost = rc[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } else { arc = -arc; rdcost = rc[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } } if ((delprc != large) || (delx < dm)) goto L4; } /* Add new balanced arcs to the superset of balanced arcs. */ for (i = 1; i <= nb; i++) { arc = prdcsr[i]; if (tnxtin[arc] == -1) { j = endn[arc]; tnxtin[arc] = tfstin[j]; tfstin[j] = arc; } if (tnxtou[arc] == -1) { j = startn[arc]; tnxtou[arc] = tfstou[j]; tfstou[j] = arc; } } return; # undef delx # undef nlabel # undef feasbl # undef svitch # undef prevnode } /*********************************************************************** * NAME * * ascnt2 - multi-node price adjustment for negative deficit case * * PURPOSE * * This routine is analogous to ascnt1 but for the case where the * scanned nodes have negative deficit. */ static void ascnt2(struct relax4_csa *csa, int dm, int *delx, int *nlabel, int *feasbl, int *svitch, int nscan, int curnode, int *prevnode) { /* input parameters */ int n = csa->n; /* int na = csa->na; */ int large = csa->large; int *startn = csa->startn; int *endn = csa->endn; int *fou = csa->fou; int *nxtou = csa->nxtou; int *fin = csa->fin; int *nxtin = csa->nxtin; /* updated parameters */ # define delx (*delx) # define nlabel (*nlabel) # define feasbl (*feasbl) # define svitch (*svitch) # define prevnode (*prevnode) int *rc = csa->rc; int *u = csa->u; int *x = csa->x; int *dfct = csa->dfct; int *label = csa->label; int *prdcsr = csa->prdcsr; int *tfstou = csa->tfstou; int *tnxtou = csa->tnxtou; int *tfstin = csa->tfstin; int *tnxtin = csa->tnxtin; int *nxtqueue = csa->nxtqueue; char *scan = csa->scan; char *mark = csa->mark; int *save = csa->save; /* local variables */ int arc, delprc, dlx, i, j, nb, node, node2, nsave, rdcost, t1, t2, t3; /* Store the arcs between the set of scanned nodes and its * complement in save and compute delprc, the stepsize to the next * breakpoint in the dual cost in the direction of increasing * prices of the scanned nodes. */ delprc = large; dlx = 0; nsave = 0; if (nscan <= n / 2) { for (i = 1; i <= nscan; i++) { node = label[i]; for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { node2 = startn[arc]; if (!scan[node2]) { nsave++; save[nsave] = arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node2] != arc)) dlx += x[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } } for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { node2 = endn[arc]; if (!scan[node2]) { nsave++; save[nsave] = -arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node2] != -arc)) dlx += u[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } } } } else { for (node = 1; node <= n; node++) { if (scan[node]) continue; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { node2 = endn[arc]; if (scan[node2]) { nsave++; save[nsave] = arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node] != arc)) dlx += x[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } } for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { node2 = startn[arc]; if (scan[node2]) { nsave++; save[nsave] = -arc; rdcost = rc[arc]; if ((rdcost == 0) && (prdcsr[node] != -arc)) dlx += u[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } } } } if ((!svitch) && (delx + dlx >= -dm)) { svitch = true; return; } delx += dlx; /* Check that the problem is feasible. */ L4: if (delprc == large) { feasbl = false; return; } /* Increase the prices of the scanned nodes, add more nodes to * the labeled set and check if a newly labeled node has positive * deficit. */ if (svitch) { for (i = 1; i <= nsave; i++) { arc = save[i]; if (arc > 0) { rc[arc] += delprc; if (rc[arc] == 0) { node2 = startn[arc]; if (tnxtou[arc] < 0) { tnxtou[arc] = tfstou[node2]; tfstou[node2] = arc; } if (tnxtin[arc] < 0) { tnxtin[arc] = tfstin[endn[arc]]; tfstin[endn[arc]] = arc; } if (!mark[node2]) { prdcsr[node2] = arc; nlabel++; label[nlabel] = node2; mark[node2] = true; } } } else { arc = -arc; rc[arc] -= delprc; if (rc[arc] == 0) { node2 = endn[arc]; if (tnxtou[arc] < 0) { tnxtou[arc] = tfstou[startn[arc]]; tfstou[startn[arc]] = arc; } if (tnxtin[arc] < 0) { tnxtin[arc] = tfstin[node2]; tfstin[node2] = arc; } if (!mark[node2]) { prdcsr[node2] = -arc; nlabel++; label[nlabel] = node2; mark[node2] = true; } } } } return; } else { nb = 0; for (i = 1; i <= nsave; i++) { arc = save[i]; if (arc > 0) { t1 = rc[arc]; if (t1 == 0) { t2 = x[arc]; t3 = startn[arc]; dfct[t3] -= t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } t3 = endn[arc]; dfct[t3] += t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } u[arc] += t2; x[arc] = 0; } rc[arc] = t1 + delprc; #if 0 /* by mao; 26/IV-2013 */ if (rc[arc] == 0) #else if (rc[arc] == 0 && nb < n) #endif { delx += x[arc]; nb++; prdcsr[nb] = arc; } } else { arc = -arc; t1 = rc[arc]; if (t1 == 0) { t2 = u[arc]; t3 = startn[arc]; dfct[t3] += t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } t3 = endn[arc]; dfct[t3] -= t2; if (nxtqueue[t3] == 0) { nxtqueue[prevnode] = t3; nxtqueue[t3] = curnode; prevnode = t3; } x[arc] += t2; u[arc] = 0; } rc[arc] = t1 - delprc; #if 0 /* by mao; 26/IV-2013 */ if (rc[arc] == 0) #else if (rc[arc] == 0 && nb < n) #endif { delx += u[arc]; nb++; prdcsr[nb] = arc; } } } } if (delx <= -dm) { delprc = large; for (i = 1; i <= nsave; i++) { arc = save[i]; if (arc > 0) { rdcost = rc[arc]; if ((rdcost < 0) && (rdcost > -delprc)) delprc = -rdcost; } else { arc = -arc; rdcost = rc[arc]; if ((rdcost > 0) && (rdcost < delprc)) delprc = rdcost; } } if ((delprc != large) || (delx < -dm)) goto L4; } /* Add new balanced arcs to the superset of balanced arcs. */ for (i = 1; i <= nb; i++) { arc = prdcsr[i]; if (tnxtin[arc] == -1) { j = endn[arc]; tnxtin[arc] = tfstin[j]; tfstin[j] = arc; } if (tnxtou[arc] == -1) { j = startn[arc]; tnxtou[arc] = tfstou[j]; tfstou[j] = arc; } } return; # undef delx # undef nlabel # undef feasbl # undef svitch # undef prevnode } /*********************************************************************** * NAME * * auction - compute good initial flow and prices * * PURPOSE * * This subroutine uses a version of the auction algorithm for min * cost network flow to compute a good initial flow and prices for the * problem. * * INPUT PARAMETERS * * n = number of nodes * na = number of arcs * large = a very large integer to represent infinity (see note 3) * startn[i] = starting node for the i-th arc, i = 1,...,na * endn[i] = ending node for the i-th arc, i = 1,...,na * fou[i] = first arc leaving i-th node, i = 1,...,n * nxtou[i] = next arc leaving the starting node of j-th arc, * i = 1,...,na * fin[i] = first arc entering i-th node, i = 1,...,n * nxtin[i] = next arc entering the ending node of j-th arc, * i = 1,...,na * * UPDATED PARAMETERS * * rc[j] = reduced cost of arc j, j = 1,...,na * u[j] = residual capacity of arc j, j = 1,...,na * x[j] = flow on arc j, j = 1,...,na * dfct[i] = deficit at node i, i = 1,...,n * * OUTPUT PARAMETERS * * nsp = number of auction/shortest path iterations * * WORKING PARAMETERS * * p[1+n], prdcsr[1+n], save[1+na], fpushf[1+n], nxtpushf[1+na], * fpushb[1+n], nxtpushb[1+na], nxtqueue[1+n], extend_arc[1+n], * sb_level[1+n], sb_arc[1+n], path_id[1+n] * * RETURNS * * 0 = normal return * 1 = problem is found to be infeasible */ static int auction(struct relax4_csa *csa) { /* input parameters */ int n = csa->n; int na = csa->na; int large = csa->large; int *startn = csa->startn; int *endn = csa->endn; int *fou = csa->fou; int *nxtou = csa->nxtou; int *fin = csa->fin; int *nxtin = csa->nxtin; /* updated parameters */ # define crash (csa->crash) int *rc = csa->rc; int *u = csa->u; int *x = csa->x; int *dfct = csa->dfct; /* output parameters */ # define nsp (csa->nsp) /* working parameters */ int *p = csa->label; int *prdcsr = csa->prdcsr; int *save = csa->save; int *fpushf = csa->tfstou; int *nxtpushf = csa->tnxtou; int *fpushb = csa->tfstin; int *nxtpushb = csa->tnxtin; int *nxtqueue = csa->nxtqueue; int *extend_arc = csa->extend_arc; int *sb_level = csa->sb_level; int *sb_arc = csa->sb_arc; char *path_id = csa->mark; /* local variables */ int arc, bstlevel, end, eps, extarc, factor, flow, i, incr, last, lastqueue, maxcost, mincost, nas, naug, new_level, node, nolist, num_passes, nxtnode, pass, pend, pr_term, prd, prevarc, prevlevel, prevnode, pstart, pterm, rdcost, red_cost, resid, root, secarc, seclevel, start, term, thresh_dfct; /* start initialization using auction */ naug = 0; pass = 0; thresh_dfct = 0; /* factor determines by how much epsilon is reduced at each * minimization */ factor = 3; /* num_passes determines how many auction scaling phases are * performed */ num_passes = 1; /* set arc flows to satisfy cs and calculate maxcost and * mincost */ maxcost = -large; mincost = large; for (arc = 1; arc <= na; arc++) { start = startn[arc]; end = endn[arc]; rdcost = rc[arc]; if (maxcost < rdcost) maxcost = rdcost; if (mincost > rdcost) mincost = rdcost; if (rdcost < 0) { dfct[start] += u[arc]; dfct[end] -= u[arc]; x[arc] = u[arc]; u[arc] = 0; } else x[arc] = 0; } /* set initial epsilon */ if ((maxcost - mincost) >= 8) eps = (maxcost - mincost) / 8; else eps = 1; /* set initial prices to zero */ for (node = 1; node <= n; node++) p[node] = 0; /* Initialization using auction/shortest paths. */ L100: /* Start of the first scaling phase. */ pass++; if ((pass == num_passes) || (eps == 1)) crash = 0; nolist = 0; /* construct list of positive surplus nodes and queue of negative * surplus nodes */ for (node = 1; node <= n; node++) { prdcsr[node] = 0; path_id[node] = false; extend_arc[node] = 0; sb_level[node] = -large; nxtqueue[node] = node + 1; if (dfct[node] > 0) { nolist++; save[nolist] = node; } } nxtqueue[n] = 1; root = 1; prevnode = lastqueue = n; /* initialization with down iterations for negative surplus * nodes */ for (i = 1; i <= nolist; i++) { node = save[i]; nsp++; /* build the list of arcs w/ room for pushing flow and find * proper price for down iteration */ bstlevel = -large; fpushf[node] = 0; for (arc = fou[node]; arc > 0; arc = nxtou[arc]) { if (u[arc] > 0) { if (fpushf[node] == 0) { fpushf[node] = arc; nxtpushf[arc] = 0; last = arc; } else { nxtpushf[last] = arc; nxtpushf[arc] = 0; last = arc; } } if (x[arc] > 0) { new_level = p[endn[arc]] + rc[arc]; if (new_level > bstlevel) { bstlevel = new_level; extarc = arc; } } } fpushb[node] = 0; for (arc = fin[node]; arc > 0; arc = nxtin[arc]) { if (x[arc] > 0) { if (fpushb[node] == 0) { fpushb[node] = arc; nxtpushb[arc] = 0; last = arc; } else { nxtpushb[last] = arc; nxtpushb[arc] = 0; last = arc; } } if (u[arc] > 0) { new_level = p[startn[arc]] - rc[arc]; if (new_level > bstlevel) { bstlevel = new_level; extarc = -arc; } } } extend_arc[node] = extarc; p[node] = bstlevel - eps; } L200: /* Start the augmentation cycles of the new scaling phase. */ if (dfct[root] >= thresh_dfct) goto L3000; term = root; path_id[root] = true; L500: /* Main forward algorithm with root as origin. */ /* start of a new forward iteration */ pterm = p[term]; extarc = extend_arc[term]; if (extarc == 0) { /* build the list of arcs w/ room for pushing flow */ fpushf[term] = 0; for (arc = fou[term]; arc > 0; arc = nxtou[arc]) { if (u[arc] > 0) { if (fpushf[term] == 0) { fpushf[term] = arc; nxtpushf[arc] = 0; last = arc; } else { nxtpushf[last] = arc; nxtpushf[arc] = 0; last = arc; } } } fpushb[term] = 0; for (arc = fin[term]; arc > 0; arc = nxtin[arc]) { if (x[arc] > 0) { if (fpushb[term] == 0) { fpushb[term] = arc; nxtpushb[arc] = 0; last = arc; } else { nxtpushb[last] = arc; nxtpushb[arc] = 0; last = arc; } } } goto L600; } /* speculative path extension attempt */ /* note: arc > 0 means that arc is oriented from the root to the * destinations * arc < 0 means that arc is oriented from the destinations to the * root * extarc = 0 or prdarc = 0, means the extension arc or the * predecessor arc, respectively, has not been established */ if (extarc > 0) { if (u[extarc] == 0) { seclevel = sb_level[term]; goto L580; } end = endn[extarc]; bstlevel = p[end] + rc[extarc]; if (pterm >= bstlevel) { if (path_id[end]) goto L1200; term = end; prdcsr[term] = extarc; path_id[term] = true; /* if negative surplus node is found, do an augmentation */ if (dfct[term] > 0) goto L2000; /* return for another iteration */ goto L500; } } else { extarc = -extarc; if (x[extarc] == 0) { seclevel = sb_level[term]; goto L580; } start = startn[extarc]; bstlevel = p[start] - rc[extarc]; if (pterm >= bstlevel) { if (path_id[start]) goto L1200; term = start; prdcsr[term] = -extarc; path_id[term] = true; /* if negative surplus node is found, do an augmentation */ if (dfct[term] > 0) goto L2000; /* return for another iteration */ goto L500; } } L550: /* second best logic test applied to save a full node scan * if old best level continues to be best go for another * contraction */ seclevel = sb_level[term]; if (bstlevel <= seclevel) goto L800; L580: /* if second best can be used do either a contraction or start * over with a speculative extension */ if (seclevel > -large) { extarc = sb_arc[term]; if (extarc > 0) { if (u[extarc] == 0) goto L600; bstlevel = p[endn[extarc]] + rc[extarc]; } else { if (x[-extarc] == 0) goto L600; bstlevel = p[startn[-extarc]] - rc[-extarc]; } if (bstlevel == seclevel) { sb_level[term] = -large; extend_arc[term] = extarc; goto L800; } } L600: /* extension/contraction attempt was unsuccessful, so scan * terminal node */ nsp++; bstlevel = seclevel = large; for (arc = fpushf[term]; arc > 0; arc = nxtpushf[arc]) { new_level = p[endn[arc]] + rc[arc]; if (new_level < seclevel) { if (new_level < bstlevel) { seclevel = bstlevel; bstlevel = new_level; secarc = extarc; extarc = arc; } else { seclevel = new_level; secarc = arc; } } } for (arc = fpushb[term]; arc > 0; arc = nxtpushb[arc]) { new_level = p[startn[arc]] - rc[arc]; if (new_level < seclevel) { if (new_level < bstlevel) { seclevel = bstlevel; bstlevel = new_level; secarc = extarc; extarc = -arc; } else { seclevel = new_level; secarc = -arc; } } } sb_level[term] = seclevel; sb_arc[term] = secarc; extend_arc[term] = extarc; L800: /* End of node scan. */ /* if the terminal node is the root, adjust its price and change * root */ if (term == root) { p[term] = bstlevel + eps; if (p[term] >= large) { /* no path to the destination */ /* problem is found to be infeasible */ return 1; } path_id[root] = false; prevnode = root; root = nxtqueue[root]; goto L200; } /* check whether extension or contraction */ prd = prdcsr[term]; if (prd > 0) { pr_term = startn[prd]; prevlevel = p[pr_term] - rc[prd]; } else { pr_term = endn[-prd]; prevlevel = p[pr_term] + rc[-prd]; } if (prevlevel > bstlevel) { /* path extension */ if (prevlevel >= bstlevel + eps) p[term] = bstlevel + eps; else p[term] = prevlevel; if (extarc > 0) { end = endn[extarc]; if (path_id[end]) goto L1200; term = end; } else { start = startn[-extarc]; if (path_id[start]) goto L1200; term = start; } prdcsr[term] = extarc; path_id[term] = true; /* if negative surplus node is found, do an augmentation */ if (dfct[term] > 0) goto L2000; /* return for another iteration */ goto L500; } else { /* path contraction */ p[term] = bstlevel + eps; path_id[term] = false; term = pr_term; if (pr_term != root) { if (bstlevel <= pterm + eps) goto L2000; } pterm = p[term]; extarc = prd; if (prd > 0) bstlevel += eps + rc[prd]; else bstlevel += eps - rc[-prd]; /* do a second best test and if that fails, do a full node * scan */ goto L550; } L1200:/* A cycle is about to form; do a retreat sequence. */ node = term; L1600:if (node != root) { path_id[node] = false; prd = prdcsr[node]; if (prd > 0) { pr_term = startn[prd]; if (p[pr_term] == p[node] + rc[prd] + eps) { node = pr_term; goto L1600; } } else { pr_term = endn[-prd]; if (p[pr_term] == p[node] - rc[-prd] + eps) { node = pr_term; goto L1600; } } /* do a full scan and price rise at pr_term */ nsp++; bstlevel = seclevel = large; for (arc = fpushf[pr_term]; arc > 0; arc = nxtpushf[arc]) { new_level = p[endn[arc]] + rc[arc]; if (new_level < seclevel) { if (new_level < bstlevel) { seclevel = bstlevel; bstlevel = new_level; secarc = extarc; extarc = arc; } else { seclevel = new_level; secarc = arc; } } } for (arc = fpushb[pr_term]; arc > 0; arc = nxtpushb[arc]) { new_level = p[startn[arc]] - rc[arc]; if (new_level < seclevel) { if (new_level < bstlevel) { seclevel = bstlevel; bstlevel = new_level; secarc = extarc; extarc = -arc; } else { seclevel = new_level; secarc = -arc; } } } sb_level[pr_term] = seclevel; sb_arc[pr_term] = secarc; extend_arc[pr_term] = extarc; p[pr_term] = bstlevel + eps; if (pr_term == root) { prevnode = root; path_id[root] = false; root = nxtqueue[root]; goto L200; } path_id[pr_term] = false; prd = prdcsr[pr_term]; if (prd > 0) term = startn[prd]; else term = endn[-prd]; if (term == root) { prevnode = root; path_id[root] = false; root = nxtqueue[root]; goto L200; } else goto L2000; } L2000:/* End of auction/shortest path routine. */ /* do augmentation from root and correct the push lists */ incr = -dfct[root]; for (node = root;;) { extarc = extend_arc[node]; path_id[node] = false; if (extarc > 0) { node = endn[extarc]; if (incr > u[extarc]) incr = u[extarc]; } else { node = startn[-extarc]; if (incr > x[-extarc]) incr = x[-extarc]; } if (node == term) break; } path_id[term] = false; if (dfct[term] > 0) { if (incr > dfct[term]) incr = dfct[term]; } for (node = root;;) { extarc = extend_arc[node]; if (extarc > 0) { end = endn[extarc]; /* add arc to the reduced graph */ if (x[extarc] == 0) { nxtpushb[extarc] = fpushb[end]; fpushb[end] = extarc; new_level = p[node] - rc[extarc]; if (sb_level[end] > new_level) { sb_level[end] = new_level; sb_arc[end] = -extarc; } } x[extarc] += incr; u[extarc] -= incr; /* remove arc from the reduced graph */ if (u[extarc] == 0) { nas++; arc = fpushf[node]; if (arc == extarc) fpushf[node] = nxtpushf[arc]; else { prevarc = arc; arc = nxtpushf[arc]; while (arc > 0) { if (arc == extarc) { nxtpushf[prevarc] = nxtpushf[arc]; break; } prevarc = arc; arc = nxtpushf[arc]; } } } node = end; } else { extarc = -extarc; start = startn[extarc]; /* add arc to the reduced graph */ if (u[extarc] == 0) { nxtpushf[extarc] = fpushf[start]; fpushf[start] = extarc; new_level = p[node] + rc[extarc]; if (sb_level[start] > new_level) { sb_level[start] = new_level; sb_arc[start] = extarc; } } u[extarc] += incr; x[extarc] -= incr; /* remove arc from the reduced graph */ if (x[extarc] == 0) { nas++; arc = fpushb[node]; if (arc == extarc) fpushb[node] = nxtpushb[arc]; else { prevarc = arc; arc = nxtpushb[arc]; while (arc > 0) { if (arc == extarc) { nxtpushb[prevarc] = nxtpushb[arc]; break; } prevarc = arc; arc = nxtpushb[arc]; } } } node = start; } if (node == term) break; } dfct[term] -= incr; dfct[root] += incr; /* insert term in the queue if it has a large enough surplus */ if (dfct[term] < thresh_dfct) { if (nxtqueue[term] == 0) { nxtnode = nxtqueue[root]; if ((p[term] >= p[nxtnode]) && (root != nxtnode)) { nxtqueue[root] = term; nxtqueue[term] = nxtnode; } else { nxtqueue[prevnode] = term; nxtqueue[term] = root; prevnode = term; } } } /* if root has a large enough surplus, keep it in the queue and * return for another iteration */ if (dfct[root] < thresh_dfct) { prevnode = root; root = nxtqueue[root]; goto L200; } L3000:/* end of augmentation cycle */ /* Check for termination of scaling phase. If scaling phase is not * finished, advance the queue and return to take another node. */ nxtnode = nxtqueue[root]; if (root != nxtnode) { nxtqueue[root] = 0; nxtqueue[prevnode] = nxtnode; root = nxtnode; goto L200; } /* End of subproblem (scaling phase). */ /* Reduce epsilon. */ eps /= factor; if (eps < 1) eps = 1; thresh_dfct /= factor; if (eps == 1) thresh_dfct = 0; /* if another auction scaling phase remains, reset the flows & * the push lists; else reset arc flows to satisfy cs and compute * reduced costs */ if (crash == 1) { for (arc = 1; arc <= na; arc++) { start = startn[arc]; end = endn[arc]; pstart = p[start]; pend = p[end]; if (pstart > pend + eps + rc[arc]) { resid = u[arc]; if (resid > 0) { dfct[start] += resid; dfct[end] -= resid; x[arc] += resid; u[arc] = 0; } } else if (pstart < pend - eps + rc[arc]) { flow = x[arc]; if (flow > 0) { dfct[start] -= flow; dfct[end] += flow; x[arc] = 0; u[arc] += flow; } } } /* return for another phase */ goto L100; } else { crash = 1; for (arc = 1; arc <= na; arc++) { start = startn[arc]; end = endn[arc]; red_cost = rc[arc] + p[end] - p[start]; if (red_cost < 0) { resid = u[arc]; if (resid > 0) { dfct[start] += resid; dfct[end] -= resid; x[arc] += resid; u[arc] = 0; } } else if (red_cost > 0) { flow = x[arc]; if (flow > 0) { dfct[start] -= flow; dfct[end] += flow; x[arc] = 0; u[arc] += flow; } } rc[arc] = red_cost; } } return 0; # undef crash # undef nsp } /* eof */ glpk-4.52.1/src/misc/relax4.h0000644000062000006210000000775212175147600015026 0ustar maomkpasswd/* relax4.h */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef RELAX4_H #define RELAX4_H struct relax4_csa { /* common storage area */ /* input parameters --------------------------------------------*/ int n; /* number of nodes */ int na; /* number of arcs */ int large; /* very large int to represent infinity */ int repeat; /* true if initialization is to be skipped (false otherwise) */ int crash; /* 0 if default initialization is used * 1 if auction initialization is used */ int *startn; /* int startn[1+na]; */ /* startn[j] = starting node for arc j, j = 1,...,na */ int *endn; /* int endn[1+na] */ /* endn[j] = ending node for arc j, j = 1,...,na */ int *fou; /* int fou[1+n]; */ /* fou[i] = first arc out of node i, i = 1,...,n */ int *nxtou; /* int nxtou[1+na]; */ /* nxtou[j] = next arc out of the starting node of arc j, * j = 1,...,na */ int *fin; /* int fin[1+n]; */ /* fin[i] = first arc into node i, i = 1,...,n */ int *nxtin; /* int nxtin[1+na]; */ /* nxtin[j] = next arc into the ending node of arc j, * j = 1,...,na */ /* updated parameters ------------------------------------------*/ int *rc; /* int rc[1+na]; */ /* rc[j] = reduced cost of arc j, j = 1,...,na */ int *u; /* int u[1+na]; */ /* u[j] = capacity of arc j on input * and (capacity of arc j) - x(j) on output, j = 1,...,na */ int *dfct; /* int dfct[1+n]; */ /* dfct[i] = demand at node i on input * and zero on output, i = 1,...,n */ /* output parameters -------------------------------------------*/ int *x; /* int x[1+na]; */ /* x[j] = flow on arc j, j = 1,...,na */ int nmultinode; /* number of multinode relaxation iterations in RELAX4 */ int iter; /* number of relaxation iterations in RELAX4 */ int num_augm; /* number of flow augmentation steps in RELAX4 */ int num_ascnt; /* number of multinode ascent steps in RELAX4 */ int nsp; /* number of auction/shortest path iterations */ /* working parameters ------------------------------------------*/ int *label; /* int label, tempin, p[1+n]; */ int *prdcsr; /* int prdcsr, tempou, price[1+n]; */ int *save; /* int save[1+na]; */ int *tfstou; /* int tfstou, fpushf[1+n]; */ int *tnxtou; /* int tnxtou, nxtpushf[1+na]; */ int *tfstin; /* int tfstin, fpushb[1+n]; */ int *tnxtin; /* int tnxtin, nxtpushb[1+na]; */ int *nxtqueue; /* int nxtqueue[1+n]; */ char *scan; /* bool scan[1+n]; */ char *mark; /* bool mark, path_id[1+n]; */ /* working parameters used by routine auction only -------------*/ int *extend_arc; /* int extend_arc[1+n]; */ int *sb_level; /* int sb_level[1+n]; */ int *sb_arc; /* int sb_arc[1+n]; */ }; #define relax4 _glp_relax4 int relax4(struct relax4_csa *csa); #define relax4_inidat _glp_relax4_inidat void relax4_inidat(struct relax4_csa *csa); #endif /* eof */ glpk-4.52.1/src/misc/rng.c0000644000062000006210000001414612175147600014403 0ustar maomkpasswd/* rng.c (pseudo-random number generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * This code is a modified version of the module GB_FLIP, a portable * pseudo-random number generator. The original version of GB_FLIP is * a part of The Stanford GraphBase developed by Donald E. Knuth (see * http://www-cs-staff.stanford.edu/~knuth/sgb.html). * * Note that all changes concern only external names, so this modified * version produces exactly the same results as the original version. * * Changes were made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "rng.h" #if 0 int A[56] = { -1 }; #else #define A (rand->A) #endif /* pseudo-random values */ #if 0 int *fptr = A; #else #define fptr (rand->fptr) #endif /* the next A value to be exported */ #define mod_diff(x, y) (((x) - (y)) & 0x7FFFFFFF) /* difference modulo 2^31 */ static int flip_cycle(RNG *rand) { /* this is an auxiliary routine to do 55 more steps of the basic * recurrence, at high speed, and to reset fptr */ int *ii, *jj; for (ii = &A[1], jj = &A[32]; jj <= &A[55]; ii++, jj++) *ii = mod_diff(*ii, *jj); for (jj = &A[1]; ii <= &A[55]; ii++, jj++) *ii = mod_diff(*ii, *jj); fptr = &A[54]; return A[55]; } /*********************************************************************** * NAME * * rng_create_rand - create pseudo-random number generator * * SYNOPSIS * * #include "rng.h" * RNG *rng_create_rand(void); * * DESCRIPTION * * The routine rng_create_rand creates and initializes a pseudo-random * number generator. * * RETURNS * * The routine returns a pointer to the generator created. */ RNG *rng_create_rand(void) { RNG *rand; int i; rand = talloc(1, RNG); A[0] = -1; for (i = 1; i <= 55; i++) A[i] = 0; fptr = A; rng_init_rand(rand, 1); return rand; } /*********************************************************************** * NAME * * rng_init_rand - initialize pseudo-random number generator * * SYNOPSIS * * #include "rng.h" * void rng_init_rand(RNG *rand, int seed); * * DESCRIPTION * * The routine rng_init_rand initializes the pseudo-random number * generator. The parameter seed may be any integer number. Note that * on creating the generator this routine is called with the parameter * seed equal to 1. */ void rng_init_rand(RNG *rand, int seed) { int i; int prev = seed, next = 1; seed = prev = mod_diff(prev, 0); A[55] = prev; for (i = 21; i; i = (i + 21) % 55) { A[i] = next; next = mod_diff(prev, next); if (seed & 1) seed = 0x40000000 + (seed >> 1); else seed >>= 1; next = mod_diff(next, seed); prev = A[i]; } flip_cycle(rand); flip_cycle(rand); flip_cycle(rand); flip_cycle(rand); flip_cycle(rand); return; } /*********************************************************************** * NAME * * rng_next_rand - obtain pseudo-random integer in the range [0, 2^31-1] * * SYNOPSIS * * #include "rng.h" * int rng_next_rand(RNG *rand); * * RETURNS * * The routine rng_next_rand returns a next pseudo-random integer which * is uniformly distributed between 0 and 2^31-1, inclusive. The period * length of the generated numbers is 2^85 - 2^30. The low order bits of * the generated numbers are just as random as the high-order bits. */ int rng_next_rand(RNG *rand) { return *fptr >= 0 ? *fptr-- : flip_cycle(rand); } /*********************************************************************** * NAME * * rng_unif_rand - obtain pseudo-random integer in the range [0, m-1] * * SYNOPSIS * * #include "rng.h" * int rng_unif_rand(RNG *rand, int m); * * RETURNS * * The routine rng_unif_rand returns a next pseudo-random integer which * is uniformly distributed between 0 and m-1, inclusive, where m is any * positive integer less than 2^31. */ #define two_to_the_31 ((unsigned int)0x80000000) int rng_unif_rand(RNG *rand, int m) { unsigned int t = two_to_the_31 - (two_to_the_31 % m); int r; xassert(m > 0); do { r = rng_next_rand(rand); } while (t <= (unsigned int)r); return r % m; } /*********************************************************************** * NAME * * rng_delete_rand - delete pseudo-random number generator * * SYNOPSIS * * #include "rng.h" * void rng_delete_rand(RNG *rand); * * DESCRIPTION * * The routine rng_delete_rand frees all the memory allocated to the * specified pseudo-random number generator. */ void rng_delete_rand(RNG *rand) { tfree(rand); return; } /**********************************************************************/ #ifdef GLP_TEST /* To be sure that this modified version produces the same results as * the original version, run this validation program. */ int main(void) { RNG *rand; int j; rand = rng_create_rand(); rng_init_rand(rand, -314159); if (rng_next_rand(rand) != 119318998) { fprintf(stderr, "Failure on the first try!\n"); return -1; } for (j = 1; j <= 133; j++) rng_next_rand(rand); if (rng_unif_rand(rand, 0x55555555) != 748103812) { fprintf(stderr, "Failure on the second try!\n"); return -2; } fprintf(stderr, "OK, the random-number generator routines seem to" " work!\n"); rng_delete_rand(rand); return 0; } #endif /* eof */ glpk-4.52.1/src/misc/rng.h0000644000062000006210000000424412175147600014406 0ustar maomkpasswd/* rng.h (pseudo-random number generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2003, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef RNG_H #define RNG_H typedef struct RNG RNG; struct RNG { /* Knuth's portable pseudo-random number generator */ int A[56]; /* pseudo-random values */ int *fptr; /* the next A value to be exported */ }; #define rng_create_rand _glp_rng_create_rand RNG *rng_create_rand(void); /* create pseudo-random number generator */ #define rng_init_rand _glp_rng_init_rand void rng_init_rand(RNG *rand, int seed); /* initialize pseudo-random number generator */ #define rng_next_rand _glp_rng_next_rand int rng_next_rand(RNG *rand); /* obtain pseudo-random integer in the range [0, 2^31-1] */ #define rng_unif_rand _glp_rng_unif_rand int rng_unif_rand(RNG *rand, int m); /* obtain pseudo-random integer in the range [0, m-1] */ #define rng_delete_rand _glp_rng_delete_rand void rng_delete_rand(RNG *rand); /* delete pseudo-random number generator */ #define rng_unif_01 _glp_rng_unif_01 double rng_unif_01(RNG *rand); /* obtain pseudo-random number in the range [0, 1] */ #define rng_uniform _glp_rng_uniform double rng_uniform(RNG *rand, double a, double b); /* obtain pseudo-random number in the range [a, b] */ #endif /* eof */ glpk-4.52.1/src/misc/rng1.c0000644000062000006210000000420612175147600014460 0ustar maomkpasswd/* rng1.c (pseudo-random number generator) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2003, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "rng.h" /*********************************************************************** * NAME * * rng_unif_01 - obtain pseudo-random number in the range [0, 1] * * SYNOPSIS * * #include "rng.h" * double rng_unif_01(RNG *rand); * * RETURNS * * The routine rng_unif_01 returns a next pseudo-random number which is * uniformly distributed in the range [0, 1]. */ double rng_unif_01(RNG *rand) { double x; x = (double)rng_next_rand(rand) / 2147483647.0; xassert(0.0 <= x && x <= 1.0); return x; } /*********************************************************************** * NAME * * rng_uniform - obtain pseudo-random number in the range [a, b] * * SYNOPSIS * * #include "rng.h" * double rng_uniform(RNG *rand, double a, double b); * * RETURNS * * The routine rng_uniform returns a next pseudo-random number which is * uniformly distributed in the range [a, b]. */ double rng_uniform(RNG *rand, double a, double b) { double x; xassert(a < b); x = rng_unif_01(rand); x = a * (1.0 - x) + b * x; xassert(a <= x && x <= b); return x; } /* eof */ glpk-4.52.1/src/misc/triang.c0000644000062000006210000002775112175147600015107 0ustar maomkpasswd/* triang.c (find maximal triangular part of rectangular matrix) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "triang.h" /*********************************************************************** * triang - find maximal triangular part of rectangular matrix * * Given a mxn sparse matrix A this routine finds permutation matrices * P and Q such that matrix A' = P * A * Q has the following structure: * * 1 s n * 1 * . . . . . x x x x x * * * . . . . x x x x x * * * * . . . x x x x x * * * * * . . x x x x x * * * * * * . x x x x x * s * * * * * * x x x x x * x x x x x x x x x x x * x x x x x x x x x x x * m x x x x x x x x x x x * * where '*' are elements of the triangular part, '.' are structural * zeros, 'x' are other elements. * * The formal routine mat specifies the original matrix A in both row- * and column-wise format. If the routine mat is called with k = +i, * 1 <= i <= m, it should store column indices and values of non-zero * elements of i-th row of A in locations ind[1], ..., ind[len] and * val[1], ..., val[len], resp., where len is the returned number of * non-zeros in the row, 0 <= len <= n. Similarly, if the routine mat * is called with k = -j, 1 <= j <= n, it should store row indices and * values of non-zero elements of j-th column of A and return len, the * number of non-zeros in the column, 0 <= len <= m. Should note that * duplicate indices are not allowed. * * The parameter info is a transit pointer passed to the routine mat. * * The parameter tol is a tolerance. The routine triang guarantees that * each diagonal element in the triangular part of matrix A' is not * less in magnitude than tol * max, where max is the maximal magnitude * of elements in corresponding column. * * On exit the routine triang stores information on the triangular part * found in the arrays rn and cn. Elements rn[1], ..., rn[s] specify * row numbers and elements cn[1], ..., cn[s] specify column numbers * of the original matrix A, which correspond to rows/columns 1, ..., s * of matrix A', where s is the size of the triangular part returned by * the routine, 0 <= s <= min(m, n). The order of rows and columns that * are not included in the triangular part remains unspecified. * * ALGORITHM * * The routine triang uses a simple greedy heuristic. * * At some step the matrix A' = P * A * Q has the following structure: * * 1 n * 1 * . . . . . . . x x x * * * . . . . . . x x x * * * * . . . . . x x x * * * * * . . . . x x x * x x x x # # # # x x x * x x x x # # # # x x x * x x x x # # # # x x x * x x x x # # # # x x x * m x x x x # # # # x x x * * where '#' are elements of active submatrix. Initially P = Q = I, so * the active submatrix is the original matrix A = A'. * * If some row has exactly one non-zero in the active submatrix (row * singleton), the routine includes this row and corresponding column * in the triangular part, and removes the column from the active * submatrix. Otherwise, the routine simply removes a column having * maximal number of non-zeros from the active submatrix in the hope * that new row singleton(s) will appear. * * COMPLEXITY * * The time complexity of the routine triang is O(nnz), where nnz is * number of non-zeros in the original matrix A. */ int triang(int m, int n, int (*mat)(void *info, int k, int ind[], double val[]), void *info, double tol, int rn[], int cn[]) { int head, i, j, jj, k, kk, ks, len, len2, next_j, ns, size; int *cind, *rind, *cnt, *ptr, *list, *prev, *next; double *cval, *rval, *big; char *flag; /* allocate working arrays */ cind = talloc(1+m, int); cval = talloc(1+m, double); rind = talloc(1+n, int); rval = talloc(1+n, double); cnt = ptr = talloc(1+m, int); list = talloc(1+n, int); prev = talloc(1+n, int); next = talloc(1+n, int); big = talloc(1+n, double); flag = talloc(1+n, char); /*--------------------------------------------------------------*/ /* build linked lists of columns having equal lengths */ /*--------------------------------------------------------------*/ /* ptr[len], 0 <= len <= m, is number of first column of length * len; * next[j], 1 <= j <= n, is number of next column having the same * length as column j; * big[j], 1 <= j <= n, is maximal magnitude of elements in j-th * column */ for (len = 0; len <= m; len++) ptr[len] = 0; for (j = 1; j <= n; j++) { /* get j-th column */ len = mat(info, -j, cind, cval); xassert(0 <= len && len <= m); /* add this column to beginning of list ptr[len] */ next[j] = ptr[len]; ptr[len] = j; /* determine maximal magnitude of elements in this column */ big[j] = 0.0; for (k = 1; k <= len; k++) { if (big[j] < fabs(cval[k])) big[j] = fabs(cval[k]); } } /*--------------------------------------------------------------*/ /* build doubly linked list of columns ordered by decreasing */ /* column lengths */ /*--------------------------------------------------------------*/ /* head is number of first column in the list; * prev[j], 1 <= j <= n, is number of column that precedes j-th * column in the list; * next[j], 1 <= j <= n, is number of column that follows j-th * column in the list */ head = 0; for (len = 0; len <= m; len++) { /* walk thru list of columns of length len */ for (j = ptr[len]; j != 0; j = next_j) { next_j = next[j]; /* add j-th column to beginning of the column list */ prev[j] = 0; next[j] = head; if (head != 0) prev[head] = j; head = j; } } /*--------------------------------------------------------------*/ /* build initial singleton list */ /*--------------------------------------------------------------*/ /* there are used two list of columns: * 1) doubly linked list of active columns, in which all columns * are ordered by decreasing column lengths; * 2) singleton list; an active column is included in this list * if it has at least one row singleton in active submatrix */ /* flag[j], 1 <= j <= n, is a flag of j-th column: * 0 j-th column is inactive; * 1 j-th column is active; * 2 j-th column is active and has row singleton(s) */ /* initially all columns are active */ for (j = 1; j <= n; j++) flag[j] = 1; /* initialize row counts and build initial singleton list */ /* cnt[i], 1 <= i <= m, is number of non-zeros, which i-th row * has in active submatrix; * ns is size of singleton list; * list[1], ..., list[ns] are numbers of active columns included * in the singleton list */ ns = 0; for (i = 1; i <= m; i++) { /* get i-th row */ len = cnt[i] = mat(info, +i, rind, rval); xassert(0 <= len && len <= n); if (len == 1) { /* a[i,j] is row singleton */ j = rind[1]; xassert(1 <= j && j <= n); if (flag[j] != 2) { /* include j-th column in singleton list */ flag[j] = 2; list[++ns] = j; } } } /*--------------------------------------------------------------*/ /* main loop */ /*--------------------------------------------------------------*/ size = 0; /* size of triangular part */ /* loop until active column list is non-empty, i.e. until the * active submatrix has at least one column */ while (head != 0) { if (ns == 0) { /* singleton list is empty */ /* remove from the active submatrix a column of maximal * length in the hope that some row singletons appear */ j = head; len = mat(info, -j, cind, cval); xassert(0 <= len && len <= m); goto drop; } /* take column j from the singleton list */ j = list[ns--]; xassert(flag[j] == 2); /* j-th column has at least one row singleton in the active * submatrix; choose one having maximal magnitude */ len = mat(info, -j, cind, cval); xassert(0 <= len && len <= m); kk = 0; for (k = 1; k <= len; k++) { i = cind[k]; xassert(1 <= i && i <= m); if (cnt[i] == 1) { /* a[i,j] is row singleton */ if (kk == 0 || fabs(cval[kk]) < fabs(cval[k])) kk = k; } } xassert(kk > 0); /* check magnitude of the row singleton chosen */ if (fabs(cval[kk]) < tol * big[j]) { /* all row singletons are too small in magnitude; drop j-th * column */ goto drop; } /* row singleton a[i,j] is ok; add i-th row and j-th column to * the triangular part */ size++; rn[size] = cind[kk]; cn[size] = j; drop: /* remove j-th column from the active submatrix */ xassert(flag[j]); flag[j] = 0; if (prev[j] == 0) head = next[j]; else next[prev[j]] = next[j]; if (next[j] == 0) ; else prev[next[j]] = prev[j]; /* decrease row counts */ for (k = 1; k <= len; k++) { i = cind[k]; xassert(1 <= i && i <= m); xassert(cnt[i] > 0); cnt[i]--; if (cnt[i] == 1) { /* new singleton appeared in i-th row; determine number * of corresponding column (it is the only active column * in this row) */ len2 = mat(info, +i, rind, rval); xassert(0 <= len2 && len2 <= n); ks = 0; for (kk = 1; kk <= len2; kk++) { jj = rind[kk]; xassert(1 <= jj && jj <= n); if (flag[jj]) { xassert(ks == 0); ks = kk; } } xassert(ks > 0); /* a[i,jj] is new row singleton */ jj = rind[ks]; if (flag[jj] != 2) { /* include jj-th column in the singleton list */ flag[jj] = 2; list[++ns] = jj; } } } } /* now all row counts should be zero */ for (i = 1; i <= m; i++) xassert(cnt[i] == 0); /* deallocate working arrays */ tfree(cind); tfree(cval); tfree(rind); tfree(rval); tfree(ptr); tfree(list); tfree(prev); tfree(next); tfree(big); tfree(flag); return size; } /* eof */ glpk-4.52.1/src/misc/triang.h0000644000062000006210000000247512175147600015110 0ustar maomkpasswd/* triang.h (find maximal triangular part of rectangular matrix) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef TRIANG_H #define TRIANG_H #define triang _glp_triang int triang(int m, int n, int (*mat)(void *info, int k, int ind[], double val[]), void *info, double tol, int rn[], int cn[]); /* find maximal triangular part of rectangular matrix */ #endif /* eof */ glpk-4.52.1/src/misc/wclique.c0000644000062000006210000001653012175147600015265 0ustar maomkpasswd/* wclique.c (maximum weight clique, Ostergard's algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Two subroutines sub() and wclique() below are intended to find a * maximum weight clique in a given undirected graph. These subroutines * are slightly modified version of the program WCLIQUE developed by * Patric Ostergard and based * on ideas from the article "P. R. J. Ostergard, A new algorithm for * the maximum-weight clique problem, submitted for publication", which * in turn is a generalization of the algorithm for unweighted graphs * presented in "P. R. J. Ostergard, A fast algorithm for the maximum * clique problem, submitted for publication". * * USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE. * * Changes were made by Andrew Makhorin . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "wclique.h" /*********************************************************************** * NAME * * wclique - find maximum weight clique with Ostergard's algorithm * * SYNOPSIS * * #include "wclique.h" * int wclique(int n, const int w[], const unsigned char a[], * int ind[]); * * DESCRIPTION * * The routine wclique finds a maximum weight clique in an undirected * graph with Ostergard's algorithm. * * INPUT PARAMETERS * * n is the number of vertices, n > 0. * * w[i], i = 1,...,n, is a weight of vertex i. * * a[*] is the strict (without main diagonal) lower triangle of the * graph adjacency matrix in packed format. * * OUTPUT PARAMETER * * ind[k], k = 1,...,size, is the number of a vertex included in the * clique found, 1 <= ind[k] <= n, where size is the number of vertices * in the clique returned on exit. * * RETURNS * * The routine returns the clique size, i.e. the number of vertices in * the clique. */ struct csa { /* common storage area */ int n; /* number of vertices */ const int *wt; /* int wt[0:n-1]; */ /* weights */ const unsigned char *a; /* adjacency matrix (packed lower triangle without main diag.) */ int record; /* weight of best clique */ int rec_level; /* number of vertices in best clique */ int *rec; /* int rec[0:n-1]; */ /* best clique so far */ int *clique; /* int clique[0:n-1]; */ /* table for pruning */ int *set; /* int set[0:n-1]; */ /* current clique */ }; #define n (csa->n) #define wt (csa->wt) #define a (csa->a) #define record (csa->record) #define rec_level (csa->rec_level) #define rec (csa->rec) #define clique (csa->clique) #define set (csa->set) #if 0 static int is_edge(struct csa *csa, int i, int j) { /* if there is arc (i,j), the routine returns true; otherwise * false; 0 <= i, j < n */ int k; xassert(0 <= i && i < n); xassert(0 <= j && j < n); if (i == j) return 0; if (i < j) k = i, i = j, j = k; k = (i * (i - 1)) / 2 + j; return a[k / CHAR_BIT] & (unsigned char)(1 << ((CHAR_BIT - 1) - k % CHAR_BIT)); } #else #define is_edge(csa, i, j) ((i) == (j) ? 0 : \ (i) > (j) ? is_edge1(i, j) : is_edge1(j, i)) #define is_edge1(i, j) is_edge2(((i) * ((i) - 1)) / 2 + (j)) #define is_edge2(k) (a[(k) / CHAR_BIT] & \ (unsigned char)(1 << ((CHAR_BIT - 1) - (k) % CHAR_BIT))) #endif static void sub(struct csa *csa, int ct, int table[], int level, int weight, int l_weight) { int i, j, k, curr_weight, left_weight, *p1, *p2, *newtable; newtable = xcalloc(n, sizeof(int)); if (ct <= 0) { /* 0 or 1 elements left; include these */ if (ct == 0) { set[level++] = table[0]; weight += l_weight; } if (weight > record) { record = weight; rec_level = level; for (i = 0; i < level; i++) rec[i] = set[i]; } goto done; } for (i = ct; i >= 0; i--) { if ((level == 0) && (i < ct)) goto done; k = table[i]; if ((level > 0) && (clique[k] <= (record - weight))) goto done; /* prune */ set[level] = k; curr_weight = weight + wt[k]; l_weight -= wt[k]; if (l_weight <= (record - curr_weight)) goto done; /* prune */ p1 = newtable; p2 = table; left_weight = 0; while (p2 < table + i) { j = *p2++; if (is_edge(csa, j, k)) { *p1++ = j; left_weight += wt[j]; } } if (left_weight <= (record - curr_weight)) continue; sub(csa, p1 - newtable - 1, newtable, level + 1, curr_weight, left_weight); } done: xfree(newtable); return; } int wclique(int n_, const int w[], const unsigned char a_[], int ind[]) { struct csa csa_, *csa = &csa_; int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos; double timer; n = n_; xassert(n > 0); wt = &w[1]; a = a_; record = 0; rec_level = 0; rec = &ind[1]; clique = xcalloc(n, sizeof(int)); set = xcalloc(n, sizeof(int)); used = xcalloc(n, sizeof(int)); nwt = xcalloc(n, sizeof(int)); pos = xcalloc(n, sizeof(int)); /* start timer */ timer = xtime(); /* order vertices */ for (i = 0; i < n; i++) { nwt[i] = 0; for (j = 0; j < n; j++) if (is_edge(csa, i, j)) nwt[i] += wt[j]; } for (i = 0; i < n; i++) used[i] = 0; for (i = n-1; i >= 0; i--) { max_wt = -1; max_nwt = -1; for (j = 0; j < n; j++) { if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt && nwt[j] > max_nwt))) { max_wt = wt[j]; max_nwt = nwt[j]; p = j; } } pos[i] = p; used[p] = 1; for (j = 0; j < n; j++) if ((!used[j]) && (j != p) && (is_edge(csa, p, j))) nwt[j] -= wt[p]; } /* main routine */ wth = 0; for (i = 0; i < n; i++) { wth += wt[pos[i]]; sub(csa, i, pos, 0, 0, wth); clique[pos[i]] = record; if (xdifftime(xtime(), timer) >= 5.0 - 0.001) { /* print current record and reset timer */ xprintf("level = %d (%d); best = %d\n", i+1, n, record); timer = xtime(); } } xfree(clique); xfree(set); xfree(used); xfree(nwt); xfree(pos); /* return the solution found */ for (i = 1; i <= rec_level; i++) ind[i]++; return rec_level; } #undef n #undef wt #undef a #undef record #undef rec_level #undef rec #undef clique #undef set /* eof */ glpk-4.52.1/src/misc/wclique.h0000644000062000006210000000240212175147600015263 0ustar maomkpasswd/* wclique.h (maximum weight clique, Ostergard's algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2009, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef WCLIQUE_H #define WCLIQUE_H #define wclique _glp_wclique int wclique(int n, const int w[], const unsigned char a[], int ind[]); /* find maximum weight clique with Ostergard's algorithm */ #endif /* eof */ glpk-4.52.1/src/misc/wclique1.c0000644000062000006210000002574412175147600015355 0ustar maomkpasswd/* wclique1.c (maximum weight clique, greedy heuristic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #include "env.h" #include "wclique1.h" /*********************************************************************** * NAME * * wclique1 - find maximum weight clique with greedy heuristic * * SYNOPSIS * * #include "wclique1.h" * int wclique1(int n, const double w[], * int (*func)(void *info, int i, int ind[]), void *info, int c[]); * * DESCRIPTION * * The routine wclique1 implements a sequential greedy heuristic to * find maximum weight clique in a given (undirected) graph G = (V, E). * * The parameter n specifies the number of vertices |V| in the graph, * n >= 0. * * The array w specifies vertex weights in locations w[i], i = 1,...,n. * All weights must be non-negative. * * The formal routine func specifies the graph. For a given vertex i, * 1 <= i <= n, it stores indices of all vertices adjacent to vertex i * in locations ind[1], ..., ind[deg], where deg is the degree of * vertex i, 0 <= deg < n, returned on exit. Note that self-loops and * multiple edges are not allowed. * * The parameter info is a cookie passed to the routine func. * * On exit the routine wclique1 stores vertex indices included in * the clique found to locations c[1], ..., c[size], where size is the * clique size returned by the routine, 0 <= size <= n. * * RETURNS * * The routine wclique1 returns the size of the clique found. */ struct vertex { int i; double cw; }; static int fcmp(const void *xx, const void *yy) { const struct vertex *x = xx, *y = yy; if (x->cw > y->cw) return -1; if (x->cw < y->cw) return +1; return 0; } int wclique1(int n, const double w[], int (*func)(void *info, int i, int ind[]), void *info, int c[]) { struct vertex *v_list; int deg, c_size, d_size, i, j, k, kk, l, *ind, *c_list, *d_list, size = 0; double c_wght, d_wght, *sw, best = 0.0; char *d_flag, *skip; /* perform sanity checks */ xassert(n >= 0); for (i = 1; i <= n; i++) xassert(w[i] >= 0.0); /* if the graph is empty, nothing to do */ if (n == 0) goto done; /* allocate working arrays */ ind = xcalloc(1+n, sizeof(int)); v_list = xcalloc(1+n, sizeof(struct vertex)); c_list = xcalloc(1+n, sizeof(int)); d_list = xcalloc(1+n, sizeof(int)); d_flag = xcalloc(1+n, sizeof(char)); skip = xcalloc(1+n, sizeof(char)); sw = xcalloc(1+n, sizeof(double)); /* build the vertex list */ for (i = 1; i <= n; i++) { v_list[i].i = i; /* compute the cumulative weight of each vertex i, which is * cw[i] = w[i] + sum{j : (i,j) in E} w[j] */ v_list[i].cw = w[i]; deg = func(info, i, ind); xassert(0 <= deg && deg < n); for (k = 1; k <= deg; k++) { j = ind[k]; xassert(1 <= j && j <= n && j != i); v_list[i].cw += w[j]; } } /* sort the vertex list to access vertices in descending order of * cumulative weights */ qsort(&v_list[1], n, sizeof(struct vertex), fcmp); /* initially all vertices are unmarked */ memset(&skip[1], 0, sizeof(char) * n); /* clear flags of all vertices */ memset(&d_flag[1], 0, sizeof(char) * n); /* look through all vertices of the graph */ for (l = 1; l <= n; l++) { /* take vertex i */ i = v_list[l].i; /* if this vertex was already included in one of previosuly * constructed cliques, skip it */ if (skip[i]) continue; /* use vertex i as the initial clique vertex */ c_size = 1; /* size of current clique */ c_list[1] = i; /* list of vertices in current clique */ c_wght = w[i]; /* weight of current clique */ /* determine the candidate set D = { j : (i,j) in E } */ d_size = func(info, i, d_list); xassert(0 <= d_size && d_size < n); d_wght = 0.0; /* weight of set D */ for (k = 1; k <= d_size; k++) { j = d_list[k]; xassert(1 <= j && j <= n && j != i); xassert(!d_flag[j]); d_flag[j] = 1; d_wght += w[j]; } /* check an upper bound to the final clique weight */ if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best))) { /* skip constructing the current clique */ goto next; } /* compute the summary weight of each vertex i in D, which is * sw[i] = w[i] + sum{j in D and (i,j) in E} w[j] */ for (k = 1; k <= d_size; k++) { i = d_list[k]; sw[i] = w[i]; /* consider vertices adjacent to vertex i */ deg = func(info, i, ind); xassert(0 <= deg && deg < n); for (kk = 1; kk <= deg; kk++) { j = ind[kk]; xassert(1 <= j && j <= n && j != i); if (d_flag[j]) sw[i] += w[j]; } } /* grow the current clique by adding vertices from D */ while (d_size > 0) { /* check an upper bound to the final clique weight */ if (c_wght + d_wght < best + 1e-5 * (1.0 + fabs(best))) { /* skip constructing the current clique */ goto next; } /* choose vertex i in D having maximal summary weight */ i = d_list[1]; for (k = 2; k <= d_size; k++) { j = d_list[k]; if (sw[i] < sw[j]) i = j; } /* include vertex i in the current clique */ c_size++; c_list[c_size] = i; c_wght += w[i]; /* remove all vertices not adjacent to vertex i, including * vertex i itself, from the candidate set D */ deg = func(info, i, ind); xassert(0 <= deg && deg < n); for (k = 1; k <= deg; k++) { j = ind[k]; xassert(1 <= j && j <= n && j != i); /* vertex j is adjacent to vertex i */ if (d_flag[j]) { xassert(d_flag[j] == 1); /* mark vertex j to keep it in D */ d_flag[j] = 2; } } kk = d_size, d_size = 0; for (k = 1; k <= kk; k++) { j = d_list[k]; if (d_flag[j] == 1) { /* remove vertex j from D */ d_flag[j] = 0; d_wght -= w[j]; } else if (d_flag[j] == 2) { /* keep vertex j in D */ d_list[++d_size] = j; d_flag[j] = 1; } else xassert(d_flag != d_flag); } } /* the current clique has been completely constructed */ if (best < c_wght) { best = c_wght; size = c_size; xassert(1 <= size && size <= n); memcpy(&c[1], &c_list[1], size * sizeof(int)); } next: /* mark the current clique vertices in order not to use them * as initial vertices anymore */ for (k = 1; k <= c_size; k++) skip[c_list[k]] = 1; /* set D can be non-empty, so clean up vertex flags */ for (k = 1; k <= d_size; k++) d_flag[d_list[k]] = 0; } /* free working arrays */ xfree(ind); xfree(v_list); xfree(c_list); xfree(d_list); xfree(d_flag); xfree(skip); xfree(sw); done: /* return to the calling program */ return size; } /**********************************************************************/ #ifdef GLP_TEST #include "glpk.h" #include "rng.h" typedef struct { double w; } v_data; #define weight(v) (((v_data *)((v)->data))->w) glp_graph *G; char *flag; int func(void *info, int i, int ind[]) { glp_arc *e; int j, k, deg = 0; xassert(info == NULL); xassert(1 <= i && i <= G->nv); /* look through incoming arcs */ for (e = G->v[i]->in; e != NULL; e = e->h_next) { j = e->tail->i; /* j->i */ if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1; } /* look through outgoing arcs */ for (e = G->v[i]->out; e != NULL; e = e->t_next) { j = e->head->i; /* i->j */ if (j != i && !flag[j]) ind[++deg] = j, flag[j] = 1; } /* clear the flag array */ xassert(deg < G->nv); for (k = 1; k <= deg; k++) flag[ind[k]] = 0; return deg; } int main(int argc, char *argv[]) { RNG *rand; int i, k, kk, size, *c, *ind, deg; double *w, sum, t; /* read graph in DIMACS format */ G = glp_create_graph(sizeof(v_data), 0); xassert(argc == 2); xassert(glp_read_ccdata(G, offsetof(v_data, w), argv[1]) == 0); /* print the number of connected components */ xprintf("nc = %d\n", glp_weak_comp(G, -1)); /* assign random weights unformly distributed in [1,100] */ w = xcalloc(1+G->nv, sizeof(double)); rand = rng_create_rand(); for (i = 1; i <= G->nv; i++) #if 0 w[i] = weight(G->v[i]) = 1.0; #else w[i] = weight(G->v[i]) = rng_unif_rand(rand, 100) + 1; #endif /* write graph in DIMACS format */ xassert(glp_write_ccdata(G, offsetof(v_data, w), "graph") == 0); /* find maximum weight clique */ c = xcalloc(1+G->nv, sizeof(int)); flag = xcalloc(1+G->nv, sizeof(char)); memset(&flag[1], 0, G->nv); t = xtime(); size = wclique1(G->nv, w, func, NULL, c); xprintf("Time used: %.1f s\n", xdifftime(xtime(), t)); /* check the clique found */ ind = xcalloc(1+G->nv, sizeof(int)); for (k = 1; k <= size; k++) { i = c[k]; deg = func(NULL, i, ind); for (kk = 1; kk <= size; kk++) flag[c[kk]] = 1; flag[i] = 0; for (kk = 1; kk <= deg; kk++) flag[ind[kk]] = 0; for (kk = 1; kk <= size; kk++) xassert(flag[c[kk]] == 0); } /* compute the clique weight */ sum = 0.0; for (i = 1; i <= size; i++) sum += w[c[i]]; xprintf("size = %d; sum = %g\n", size, sum); return 0; } #endif /* eof */ glpk-4.52.1/src/misc/wclique1.h0000644000062000006210000000244312175147600015351 0ustar maomkpasswd/* wclique1.h (maximum weight clique, greedy heuristic) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Copyright (C) 2012, 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef WCLIQUE1_H #define WCLIQUE1_H #define wclique1 _glp_wclique1 int wclique1(int n, const double w[], int (*func)(void *info, int i, int ind[]), void *info, int c[]); /* find maximum weight clique with greedy heuristic */ #endif /* eof */ glpk-4.52.1/src/proxy/0000755000062000006210000000000012175147600013671 5ustar maomkpasswdglpk-4.52.1/src/proxy/main.c0000644000062000006210000000405712175147600014767 0ustar maomkpasswd/* Last update: 08-May-2013 */ #include #include #include #include "glpk.h" #include "proxy.h" /**********************************************************************/ int main(int argc, char **argv) /**********************************************************************/ { glp_prob *lp; int ncols, status; double *initsol, zstar, *xstar; /* check arguments */ if ( (argc == 1) || (argc > 3) ) { printf("ERROR: Usage: ts <(possibly) xml initsols>\n" ); exit(1); } /* creating the problem */ lp = glp_create_prob(); glp_set_prob_name(lp, "Proxy"); /* reading the problem */ glp_term_out(GLP_OFF); #if 0 /* by mao */ status = glp_read_lp(lp, NULL, argv[1]); #else status = glp_read_mps(lp, GLP_MPS_FILE, NULL, argv[1]); #endif glp_term_out(GLP_ON); if ( status ) { printf("Problem %s does not exist!!!, status %d\n", argv[1], status); exit(1); } ncols = glp_get_num_cols(lp); initsol = (double *) calloc(ncols+1, sizeof(double)); if (argc == 3) { FILE *fp=fopen(argv[2],"r"); char tmp[256]={0x0}; int counter = 1; while(fp!=NULL && fgets(tmp, sizeof(tmp),fp)!=NULL) { char *valini = strstr(tmp, "value"); if (valini!=NULL){ int num; double dnum; valini +=7; sscanf(valini, "%d%*s",&num); dnum = (double)num; initsol[counter] = dnum; counter++; } } fclose(fp); } xstar = (double *) calloc(ncols+1, sizeof(double)); if (argc == 3) { status = proxy(lp, &zstar, xstar, initsol, 0.0, 0, 1); } else { status = proxy(lp, &zstar, xstar, NULL, 0.0, 0, 1); } printf("Status = %d; ZSTAR = %f\n",status,zstar); /* int i; for (i=1; i< ncols+1; i++) { printf("XSTAR[%d] = %f\n",i, xstar[i]); } */ glp_delete_prob(lp); return 0; } glpk-4.52.1/src/proxy/proxy.c0000644000062000006210000010315412175147600015222 0ustar maomkpasswd/* proxy.c (proximity search heuristic algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Author: Giorgio Sartor <0gioker0@gmail.com>. * * Copyright (C) 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . * ************************************************************************ * * THIS CODE IS AN IMPLEMENTATION OF THE ALGORITHM PROPOSED IN * * M. Fischetti, M. Monaci, * "Proximity Search for 0-1 Mixed-Integer Convex Programming" * Technical Report DEI, University of Padua, March 2013. * * AVAILABLE AT * http://www.dei.unipd.it/~fisch/papers/proximity_search.pdf * * THE CODE HAS BEEN WRITTEN BY GIORGIO SARTOR, " 0gioker0@gmail.com " * * BASIC IDEA: * * The initial feasible solution x_tilde is defined. This initial * solution can be found by an ad-hoc heuristic and proxy can be used to * refine it by exploiting an underlying MIP model whose solution from * scratch turned out to be problematic. Otherwise, x_tilde can be found * by running the GLPK mip solver until a first feasible solution is * found, setting a conservative time limit of 10 minutes (by default). * Time limit can be modified passing variable tlim [ms]. * * Then the cutoff tolerance "delta" is defined. The default tolerance * is 1% of the last feasible solution obj value--rounded to integer if * all the variables and obj coefficients are integer. * * Next, the objective function c' x is replaced by the Hamming distance * between x (the actual obj coefficients) and x_tilde (the given * solution). Distance is only computed wrt the binary variables. * * The GLPK solver is then invoked to hopefully find a new incumbent * x_star with cost c' x_star <= c' x_tilde - delta. A crucial property * here is that the root-node solution of the LP relaxation is expected * to be not too different from x_tilde, as this latter solution would * be optimal without the cutoff constraint, that for a small delta can * typically be fulfilled with just local adjustments. * * If no new solution x_star is found within the time limit the * algorithm stops. Of course, if the MIP solver proved infeasibility * for the given delta, we have that c' x_tilde - delta is a valid lower * bound (in case of minimazation) on the optimal value of the original * MIP. * * The new solution x_star, if any, is possibly improved by solving a * simplified problem (refinement) where all binary variables have been * fixed to their value in x_star so as to find the best solution within * the neighborhood. * * Finally, the approach is reapplied on x_star (that replaces x_tilde) * so as to recenter the distance Hamming function and by modifying the * cutoff tolerance delta. * * In this way, there will be a series of hopefully not-too-difficult * sub-MIPs to solve, each leading to an improvement of the incumbent. * More aggressive policies on the definition of tolerance delta can * lead to a better performance, but would require an ad-hoc tuning. * ************************************************************************ * * int proxy(glp_prob *lp, double *zstar, double *xstar, * const double[] initsol, double rel_impr, int tlim, * int verbose) * * lp : GLPK problem pointer to a MIP with binary variables * * zstar : the value of objective function of the best solution found * * xstar : best solution with components xstar[1],...,xstar[ncols] * * initsol : pointer to a initial feasible solution, see * glp_ios_heur_sol * If initsol = NULL, the procedure finds the first solution * by itself. * * rel_impr : minimum relative obj improvement to be achieved at each * internal step; if <= 0.0 a default value of 0.01 (1%) is * used; for some problems (e.g., set covering with small * integer costs) a more-conservative choice of 0.001 (0.1%) * can lead to a better final solution; values larger than * 0.05 (5%) are typically too aggressive and do not work * well. * * tlim : time limit to find a new solution, in ms. * If tlim = 0, it is set to its default value, 600000 ms * * verbose : if 1 the output is activated. If 0 only errors are * displayed * * The procedure returns -1 if an error occurred, 0 otherwise (possibly, * time limit) * ***********************************************************************/ /**********************************************************************/ /* 1. INCLUDE */ /**********************************************************************/ #include "glpk.h" #include "env.h" #include "proxy.h" /**********************************************************************/ /* 2. PARAMETERS AND CONSTANTS */ /**********************************************************************/ #define TDAY 86400.0 #define TRUE 1 #define FALSE 0 #define EPS 1e-6 #define RINF 1e38 #define MAXVAL 1e20 #define MINVAL -1e20 /**********************************************************************/ /* 3. GLOBAL VARIABLES */ /**********************************************************************/ struct csa { int integer_obj; /* TRUE if each feasible solution has an integral cost */ int b_vars_exist; /* TRUE if there is at least one binary variable in the problem */ int i_vars_exist; /* TRUE if there is at least one general integer variable in the problem */ const double *startsol; /* Pointer to the initial solution */ int *ckind; /* Store the kind of the structural variables of the problem */ double *clb; /* Store the lower bound on the structural variables of the problem */ double *cub; /* Store the upper bound on the structural variables of the problem */ double *true_obj; /* Store the obj coefficients of the problem */ int dir; /* Minimization or maximization problem */ int ncols; /* Number of structural variables of the problem */ time_t GLOtstart; /* starting time of the algorithm */ glp_prob *lp_ref; /* glp problem for refining only*/ }; /**********************************************************************/ /* 4. FUNCTIONS PROTOTYPES */ /**********************************************************************/ static void callback(glp_tree *tree, void *info); static void get_info(struct csa *csa, glp_prob *lp); static int is_integer(struct csa *csa); static void check_integrality(struct csa *csa); static int check_ref(struct csa *csa, glp_prob *lp, double *xref); static double second(void); static int add_cutoff(struct csa *csa, glp_prob *lp); static void get_sol(struct csa *csa, glp_prob *lp, double *xstar); static double elapsed_time(struct csa *csa); static void redefine_obj(glp_prob *lp, double *xtilde, int ncols, int *ckind, double *clb, double *cub); static double update_cutoff(struct csa *csa, glp_prob *lp, double zstar, int index, double rel_impr); static double compute_delta(struct csa *csa, double z, double rel_impr); static double objval(int ncols, double *x, double *true_obj); static void array_copy(int begin, int end, double *source, double *destination); static int do_refine(struct csa *csa, glp_prob *lp_ref, int ncols, int *ckind, double *xref, int *tlim, int tref_lim, int verbose); static void deallocate(struct csa *csa, int refine); /**********************************************************************/ /* 5. FUNCTIONS */ /**********************************************************************/ int proxy(glp_prob *lp, double *zfinal, double *xfinal, const double initsol[], double rel_impr, int tlim, int verbose) { struct csa csa_, *csa = &csa_; glp_iocp parm; glp_smcp parm_lp; size_t tpeak; int refine, tref_lim, err, cutoff_row, niter, status, i, tout; double *xref, *xstar, zstar, tela, cutoff, zz; memset(csa, 0, sizeof(struct csa)); /********** **********/ /********** RETRIEVING PROBLEM INFO **********/ /********** **********/ /* getting problem direction (min or max) */ csa->dir = glp_get_obj_dir(lp); /* getting number of variables */ csa->ncols = glp_get_num_cols(lp); /* getting kind, bounds and obj coefficient of each variable information is stored in ckind, cub, clb, true_obj */ get_info(csa, lp); /* checking if the objective function is always integral */ check_integrality(csa); /* Proximity search cannot be used if there are no binary variables */ if (csa->b_vars_exist == FALSE) { if (verbose) { xprintf("The problem has not binary variables. Proximity se" "arch cannot be used.\n"); } tfree(csa->ckind); tfree(csa->clb); tfree(csa->cub); tfree(csa->true_obj); return -1; } /* checking if the problem needs refinement, i.e., not all variables are binary. If so, the routine creates a copy of the lp problem named lp_ref and initializes the solution xref to zero. */ xref = talloc(csa->ncols+1, double); #if 0 /* by mao */ memset(xref, 0, sizeof(double)*(csa->ncols+1)); #endif refine = check_ref(csa, lp, xref); #ifdef PROXY_DEBUG xprintf("REFINE = %d\n",refine); #endif /* Initializing the solution */ xstar = talloc(csa->ncols+1, double); #if 0 /* by mao */ memset(xstar, 0, sizeof(double)*(csa->ncols+1)); #endif /********** **********/ /********** FINDING FIRST SOLUTION **********/ /********** **********/ if (verbose) { xprintf("Applying PROXY heuristic...\n"); } /* get the initial time */ csa->GLOtstart = second(); /* setting the optimization parameters */ glp_init_iocp(&parm); glp_init_smcp(&parm_lp); #if 0 /* by gioker */ /* Preprocessing should be disabled because the mip passed to proxy is already preprocessed */ parm.presolve = GLP_ON; #endif #if 1 /* by mao */ /* best projection backtracking seems to be more efficient to find any integer feasible solution */ parm.bt_tech = GLP_BT_BPH; #endif /* Setting the default value of the minimum relative improvement to 1% */ if ( rel_impr <= 0.0 ) { rel_impr = 0.01; } /* Setting the default value of time limit to 10 minutes */ if (tlim <= 0) { tlim = INT_MAX; } if (verbose) { xprintf("Proxy's time limit set to %d seconds.\n",tlim/1000); xprintf("Proxy's relative improvement " "set to %2.2lf %c.\n",rel_impr*100,37); } parm_lp.tm_lim = tlim; parm.mip_gap = 9999999.9; /* to stop the optimization at the first feasible solution found */ /* finding the first solution */ if (verbose) { xprintf("Searching for a feasible solution...\n"); } /* verifying the existence of an input starting solution */ if (initsol != NULL) { csa->startsol = initsol; parm.cb_func = callback; parm.cb_info = csa; if (verbose) { xprintf("Input solution found.\n"); } } tout = glp_term_out(GLP_OFF); err = glp_simplex(lp,&parm_lp); glp_term_out(tout); status = glp_get_status(lp); if (status != GLP_OPT) { if (verbose) { xprintf("Proxy heuristic terminated.\n"); } #ifdef PROXY_DEBUG /* For debug only */ xprintf("GLP_SIMPLEX status = %d\n",status); xprintf("GLP_SIMPLEX error code = %d\n",err); #endif tfree(xref); tfree(xstar); deallocate(csa, refine); return -1; } tela = elapsed_time(csa); if (tlim-tela*1000 <= 0) { if (verbose) { xprintf("Time limit exceeded. Proxy could not " "find optimal solution to LP relaxation.\n"); xprintf("Proxy heuristic aborted.\n"); } tfree(xref); tfree(xstar); deallocate(csa, refine); return -1; } parm.tm_lim = tlim - tela*1000; tref_lim = (tlim - tela *1000) / 20; tout = glp_term_out(GLP_OFF); err = glp_intopt(lp, &parm); glp_term_out(tout); status = glp_mip_status(lp); /***** If no solution was found *****/ if (status == GLP_NOFEAS || status == GLP_UNDEF) { if (err == GLP_ETMLIM) { if (verbose) { xprintf("Time limit exceeded. Proxy could not " "find an initial integer feasible solution.\n"); xprintf("Proxy heuristic aborted.\n"); } } else { if (verbose) { xprintf("Proxy could not " "find an initial integer feasible solution.\n"); xprintf("Proxy heuristic aborted.\n"); } } tfree(xref); tfree(xstar); deallocate(csa, refine); return -1; } /* getting the first solution and its value */ get_sol(csa, lp,xstar); zstar = glp_mip_obj_val(lp); if (verbose) { xprintf(">>>>> first solution = %e;\n", zstar); } /* If a feasible solution was found but the time limit is exceeded */ if (err == GLP_ETMLIM) { if (verbose) { xprintf("Time limit exceeded. Proxy heuristic terminated.\n"); } goto done; } tela = elapsed_time(csa); tpeak = 0; glp_mem_usage(NULL, NULL, NULL, &tpeak); if (verbose) { xprintf("Time used: %3.1lf secs. Memory used: %2.1lf Mb\n", tela,(double)tpeak/1048576); xprintf("Starting proximity search...\n"); } /********** **********/ /********** PREPARING THE PROBLEM FOR PROXY **********/ /********** **********/ /* adding a dummy cutoff constraint */ cutoff_row = add_cutoff(csa, lp); /* proximity search needs minimization direction even if the problem is a maximization one */ if (csa->dir == GLP_MAX) { glp_set_obj_dir(lp, GLP_MIN); } /********** **********/ /********** STARTING PROXIMITY SEARCH **********/ /********** **********/ niter = 0; while (TRUE) { niter++; /********** CHANGING THE OBJ FUNCTION **********/ redefine_obj(lp,xstar, csa->ncols, csa->ckind, csa->clb, csa->cub); /********** UPDATING THE CUTOFF CONSTRAINT **********/ cutoff = update_cutoff(csa, lp,zstar, cutoff_row, rel_impr); #ifdef PROXY_DEBUG xprintf("TRUE_OBJ[0] = %f\n",csa->true_obj[0]); xprintf("ZSTAR = %f\n",zstar); xprintf("CUTOFF = %f\n",cutoff); #endif /********** SEARCHING FOR A BETTER SOLUTION **********/ tela = elapsed_time(csa); if (tlim-tela*1000 <= 0) { if (verbose) { xprintf("Time limit exceeded. Proxy heuristic " "terminated.\n"); } goto done; } parm_lp.tm_lim = tlim -tela*1000; tout = glp_term_out(GLP_OFF); err = glp_simplex(lp,&parm_lp); glp_term_out(tout); status = glp_get_status(lp); if (status != GLP_OPT) { if (status == GLP_NOFEAS) { if (verbose) { xprintf("Bound exceeded = %f. ",cutoff); } } if (verbose) { xprintf("Proxy heuristic terminated.\n"); } #ifdef PROXY_DEBUG xprintf("GLP_SIMPLEX status = %d\n",status); xprintf("GLP_SIMPLEX error code = %d\n",err); #endif goto done; } tela = elapsed_time(csa); if (tlim-tela*1000 <= 0) { if (verbose) { xprintf("Time limit exceeded. Proxy heuristic " "terminated.\n"); } goto done; } parm.tm_lim = tlim - tela*1000; parm.cb_func = NULL; #if 0 /* by gioker */ /* Preprocessing should be disabled because the mip passed to proxy is already preprocessed */ parm.presolve = GLP_ON; #endif tout = glp_term_out(GLP_OFF); err = glp_intopt(lp, &parm); glp_term_out(tout); /********** MANAGEMENT OF THE SOLUTION **********/ status = glp_mip_status(lp); /***** No feasible solutions *****/ if (status == GLP_NOFEAS) { if (verbose) { xprintf("Bound exceeded = %f. Proxy heuristic " "terminated.\n",cutoff); } goto done; } /***** Undefined solution *****/ if (status == GLP_UNDEF) { if (err == GLP_ETMLIM) { if (verbose) { xprintf("Time limit exceeded. Proxy heuristic " "terminated.\n"); } } else { if (verbose) { xprintf("Proxy terminated unexpectedly.\n"); #ifdef PROXY_DEBUG xprintf("GLP_INTOPT error code = %d\n",err); #endif } } goto done; } /***** Feasible solution *****/ if ((status == GLP_FEAS) || (status == GLP_OPT)) { /* getting the solution and computing its value */ get_sol(csa, lp,xstar); zz = objval(csa->ncols, xstar, csa->true_obj); /* Comparing the incumbent solution with the current best one */ #ifdef PROXY_DEBUG xprintf("ZZ = %f\n",zz); xprintf("ZSTAR = %f\n",zstar); xprintf("REFINE = %d\n",refine); #endif if (((zzdir == GLP_MIN)) || ((zz>zstar) && (csa->dir == GLP_MAX))) { /* refining (possibly) the solution */ if (refine) { /* copying the incumbent solution in the refinement one */ array_copy(1, csa->ncols +1, xstar, xref); err = do_refine(csa, csa->lp_ref, csa->ncols, csa->ckind, xref, &tlim, tref_lim, verbose); if (!err) { double zref = objval(csa->ncols, xref, csa->true_obj); if (((zrefdir == GLP_MIN)) || ((zref>zz) && (csa->dir == GLP_MAX))) { zz = zref; /* copying the refinement solution in the incumbent one */ array_copy(1, csa->ncols +1, xref, xstar); } } } zstar = zz; tela = elapsed_time(csa); if (verbose) { xprintf(">>>>> it: %3d: mip = %e; elapsed time " "%3.1lf sec.s\n", niter,zstar,tela); } } } } done: tela = elapsed_time(csa); glp_mem_usage(NULL, NULL, NULL, &tpeak); if (verbose) { xprintf("Time used: %3.1lf. Memory used: %2.1lf Mb\n", tela,(double)tpeak/1048576); } /* Exporting solution and obj val */ *zfinal = zstar; for (i=1; i < (csa->ncols + 1); i++) { xfinal[i]=xstar[i]; } /* Freeing allocated memory */ tfree(xref); tfree(xstar); deallocate(csa, refine); return 0; } /**********************************************************************/ static void callback(glp_tree *tree, void *info){ /**********************************************************************/ struct csa *csa = info; switch(glp_ios_reason(tree)) { case GLP_IHEUR: glp_ios_heur_sol(tree, csa->startsol); break; default: break; } } /**********************************************************************/ static void get_info(struct csa *csa, glp_prob *lp) /**********************************************************************/ { int i; /* Storing helpful info of the problem */ csa->ckind = talloc(csa->ncols+1, int); #if 0 /* by mao */ memset(csa->ckind, 0, sizeof(int)*(csa->ncols+1)); #endif csa->clb = talloc(csa->ncols+1, double); #if 0 /* by mao */ memset(csa->clb, 0, sizeof(double)*(csa->ncols+1)); #endif csa->cub = talloc(csa->ncols+1, double); #if 0 /* by mao */ memset(csa->cub, 0, sizeof(double)*(csa->ncols+1)); #endif csa->true_obj = talloc(csa->ncols+1, double); #if 0 /* by mao */ memset(csa->true_obj, 0, sizeof(double)*(csa->ncols+1)); #endif for( i = 1 ; i < (csa->ncols + 1); i++ ) { csa->ckind[i] = glp_get_col_kind(lp, i); csa->clb[i] = glp_get_col_lb(lp, i); csa->cub[i] = glp_get_col_ub(lp, i); csa->true_obj[i] = glp_get_obj_coef(lp, i); } csa->true_obj[0] = glp_get_obj_coef(lp, 0); } /**********************************************************************/ static int is_integer(struct csa *csa) /**********************************************************************/ { int i; csa->integer_obj = TRUE; for ( i = 1; i < (csa->ncols + 1); i++ ) { if (fabs(csa->true_obj[i]) > INT_MAX ) { csa->integer_obj = FALSE; } if (fabs(csa->true_obj[i]) <= INT_MAX) { double tmp, rem; if (fabs(csa->true_obj[i]) - floor(fabs(csa->true_obj[i])) < 0.5) { tmp = floor(fabs(csa->true_obj[i])); } else { tmp = ceil(fabs(csa->true_obj[i])); } rem = fabs(csa->true_obj[i]) - tmp; rem = fabs(rem); if (rem > EPS) { csa->integer_obj = FALSE; } } } return csa->integer_obj; } /**********************************************************************/ static void check_integrality(struct csa *csa) /**********************************************************************/ { /* Checking if the problem has binary, integer or continuos variables. integer_obj is TRUE if the problem has no continuous variables and all the obj coefficients are integer (and < INT_MAX). */ int i; csa->integer_obj = is_integer(csa); csa->b_vars_exist = FALSE; csa->i_vars_exist = FALSE; for ( i = 1; i < (csa->ncols + 1); i++ ) { if ( csa->ckind[i] == GLP_IV ){ csa->i_vars_exist = TRUE; continue; } if ( csa->ckind[i] == GLP_BV ){ csa->b_vars_exist =TRUE; continue; } csa->integer_obj = FALSE; } } /**********************************************************************/ static int check_ref(struct csa *csa, glp_prob *lp, double *xref) /**********************************************************************/ { /* checking if the problem has continuos or integer variables. If so, refinement is prepared. */ int refine = FALSE; int i; for ( i = 1; i < (csa->ncols + 1); i++ ) { if ( csa->ckind[i] != GLP_BV) { refine = TRUE; break; } } /* possibly creating a mip clone for refinement only */ if ( refine ) { csa->lp_ref = glp_create_prob(); glp_copy_prob(csa->lp_ref, lp, GLP_ON); } return refine; } /**********************************************************************/ static double second(void) /**********************************************************************/ { #if 0 /* by mao */ return ((double)clock()/(double)CLOCKS_PER_SEC); #else return xtime() / 1000.0; #endif } /**********************************************************************/ static int add_cutoff(struct csa *csa, glp_prob *lp) /**********************************************************************/ { /* Adding a cutoff constraint to set an upper bound (in case of minimaztion) on the obj value of the next solution, i.e., the next value of the true obj function that we would like to find */ /* store non-zero coefficients in the objective function */ int *obj_index = talloc(csa->ncols+1, int); #if 0 /* by mao */ memset(obj_index, 0, sizeof(int)*(csa->ncols+1)); #endif double *obj_value = talloc(csa->ncols+1, double); #if 0 /* by mao */ memset(obj_value, 0, sizeof(double)*(csa->ncols+1)); #endif int obj_nzcnt = 0; int i, irow; const char *rowname; for ( i = 1; i < (csa->ncols + 1); i++ ) { if ( fabs(csa->true_obj[i]) > EPS ) { obj_nzcnt++; obj_index[obj_nzcnt] = i; obj_value[obj_nzcnt] = csa->true_obj[i]; } } irow = glp_add_rows(lp, 1); rowname = "Cutoff"; glp_set_row_name(lp, irow, rowname); if (csa->dir == GLP_MIN) { /* minimization problem */ glp_set_row_bnds(lp, irow, GLP_UP, MAXVAL, MAXVAL); } else { /* maximization problem */ glp_set_row_bnds(lp, irow, GLP_LO, MINVAL, MINVAL); } glp_set_mat_row(lp, irow, obj_nzcnt, obj_index, obj_value); tfree(obj_index); tfree(obj_value); return irow; } /**********************************************************************/ static void get_sol(struct csa *csa, glp_prob *lp, double *xstar) /**********************************************************************/ { /* Retrieving and storing the coefficients of the solution */ int i; for (i = 1; i < (csa->ncols +1); i++) { xstar[i] = glp_mip_col_val(lp, i); } } /**********************************************************************/ static double elapsed_time(struct csa *csa) /**********************************************************************/ { double tela = second() - csa->GLOtstart; if ( tela < 0 ) tela += TDAY; return(tela); } /**********************************************************************/ static void redefine_obj(glp_prob *lp, double *xtilde, int ncols, int *ckind, double *clb, double *cub) /**********************************************************************/ /* Redefine the lp objective function obj as the distance-to-integrality (Hamming distance) from xtilde (the incumbent feasible solution), wrt to binary vars only */ { int j; double *delta = talloc(ncols+1, double); #if 0 /* by mao */ memset(delta, 0, sizeof(double)*(ncols+1)); #endif for ( j = 1; j < (ncols +1); j++ ) { delta[j] = 0.0; /* skip continuous variables */ if ( ckind[j] == GLP_CV ) continue; /* skip integer variables that have been fixed */ if ( cub[j]-clb[j] < 0.5 ) continue; /* binary variable */ if ( ckind[j] == GLP_BV ) { if ( xtilde[j] > 0.5 ) { delta[j] = -1.0; } else { delta[j] = 1.0; } } } /* changing the obj coeff. for all variables, including continuous ones */ for ( j = 1; j < (ncols +1); j++ ) { glp_set_obj_coef(lp, j, delta[j]); } glp_set_obj_coef(lp, 0, 0.0); tfree(delta); } /**********************************************************************/ static double update_cutoff(struct csa *csa, glp_prob *lp, double zstar, int cutoff_row, double rel_impr) /**********************************************************************/ { /* Updating the cutoff constraint with the value we would like to find during the next optimization */ double cutoff; zstar -= csa->true_obj[0]; if (csa->dir == GLP_MIN) { cutoff = zstar - compute_delta(csa, zstar, rel_impr); glp_set_row_bnds(lp, cutoff_row, GLP_UP, cutoff, cutoff); } else { cutoff = zstar + compute_delta(csa, zstar, rel_impr); glp_set_row_bnds(lp, cutoff_row, GLP_LO, cutoff, cutoff); } return cutoff; } /**********************************************************************/ static double compute_delta(struct csa *csa, double z, double rel_impr) /**********************************************************************/ { /* Computing the offset for the next best solution */ double delta = rel_impr * fabs(z); if ( csa->integer_obj ) delta = ceil(delta); return(delta); } /**********************************************************************/ static double objval(int ncols, double *x, double *true_obj) /**********************************************************************/ { /* Computing the true cost of x (using the original obj coeff.s) */ int j; double z = 0.0; for ( j = 1; j < (ncols +1); j++ ) { z += x[j] * true_obj[j]; } return z + true_obj[0]; } /**********************************************************************/ static void array_copy(int begin, int end, double *source, double *destination) /**********************************************************************/ { int i; for (i = begin; i < end; i++) { destination[i] = source[i]; } } /**********************************************************************/ static int do_refine(struct csa *csa, glp_prob *lp_ref, int ncols, int *ckind, double *xref, int *tlim, int tref_lim, int verbose) /**********************************************************************/ { /* Refinement is applied when the variables of the problem are not all binary. Binary variables are fixed to their value and remaining ones are optimized. If there are only continuos variables (in addition to those binary) the problem becomes just an LP. Otherwise, it remains a MIP but of smaller size. */ int j, tout; double refineStart = second(); double val, tela; if ( glp_get_num_cols(lp_ref) != ncols ) { if (verbose) { xprintf("Error in Proxy refinement: "); xprintf("wrong number of columns (%d vs %d).\n", ncols, glp_get_num_cols(lp_ref)); } return 1; } val = -1.0; /* fixing all binary variables to their current value in xref */ for ( j = 1; j < (ncols + 1); j++ ) { if ( ckind[j] == GLP_BV ) { val = 0.0; if ( xref[j] > 0.5 ) val = 1.0; glp_set_col_bnds(lp_ref, j, GLP_FX, val, val); } } /* re-optimizing (refining) if some bound has been changed */ if ( val > -1.0 ) { glp_iocp parm_ref; glp_smcp parm_ref_lp; int err, status; glp_init_iocp(&parm_ref); parm_ref.presolve = GLP_ON; glp_init_smcp(&parm_ref_lp); /* If there are no general integer variable the problem becomes an LP (after fixing the binary variables) and can be solved quickly. Otherwise the problem is still a MIP problem and a timelimit has to be set. */ parm_ref.tm_lim = tref_lim; if (parm_ref.tm_lim > *tlim) { parm_ref.tm_lim = *tlim; } parm_ref_lp.tm_lim = parm_ref.tm_lim; #ifdef PROXY_DEBUG xprintf("***** REFINING *****\n"); #endif tout = glp_term_out(GLP_OFF); if (csa->i_vars_exist == TRUE) { err = glp_intopt(lp_ref, &parm_ref); } else { err = glp_simplex(lp_ref, &parm_ref_lp); } glp_term_out(tout); if (csa->i_vars_exist == TRUE) { status = glp_mip_status(lp_ref); } else { status = glp_get_status(lp_ref); } #ifdef PROXY_DEBUG xprintf("STATUS REFINING = %d\n",status); #endif if (status == GLP_UNDEF) { if (err == GLP_ETMLIM) { #ifdef PROXY_DEBUG xprintf("Time limit exceeded on Proxy refining.\n"); #endif return 1; } } for( j = 1 ; j < (ncols + 1); j++ ){ if (ckind[j] != GLP_BV) { if (csa->i_vars_exist == TRUE) { xref[j] = glp_mip_col_val(lp_ref, j); } else{ xref[j] = glp_get_col_prim(lp_ref, j); } } } } tela = second() - refineStart; *tlim = *tlim - tela*1000; return 0; } /**********************************************************************/ static void deallocate(struct csa *csa, int refine) /**********************************************************************/ { /* Deallocating routine */ if (refine) { glp_delete_prob(csa->lp_ref); } tfree(csa->ckind); tfree(csa->clb); tfree(csa->cub); tfree(csa->true_obj); } /* eof */ glpk-4.52.1/src/proxy/proxy.h0000644000062000006210000000244412175147600015227 0ustar maomkpasswd/* proxy.h (proximity search heuristic algorithm) */ /*********************************************************************** * This code is part of GLPK (GNU Linear Programming Kit). * * Author: Giorgio Sartor <0gioker0@gmail.com>. * * Copyright (C) 2013 Andrew Makhorin, Department for Applied * Informatics, Moscow Aviation Institute, Moscow, Russia. All rights * reserved. E-mail: . * * GLPK is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GLPK 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 General Public * License for more details. * * You should have received a copy of the GNU General Public License * along with GLPK. If not, see . ***********************************************************************/ #ifndef PROXY_H #define PROXY_H #define proxy _glp_proxy int proxy(glp_prob *lp, double *zstar, double *xstar, const double initsol[], double rel_impr, int tlim, int verbose); #endif /* eof */ glpk-4.52.1/src/proxy/proxy1.c0000644000062000006210000000206212175147600015277 0ustar maomkpasswd/* proxy1.c */ /* (reserved for copyright notice) */ #include "glpios.h" #include "proxy.h" void ios_proxy_heur(glp_tree *T) { glp_prob *prob; int j, status; double *xstar, zstar; /* this heuristic is applied only once on the root level */ if (!(T->curr->level == 0 && T->curr->solved == 1)) goto done; prob = glp_create_prob(); glp_copy_prob(prob, T->mip, 0); xstar = xcalloc(1+prob->n, sizeof(double)); for (j = 1; j <= prob->n; j++) xstar[j] = 0.0; if (T->mip->mip_stat != GLP_FEAS) status = proxy(prob, &zstar, xstar, NULL, 0.0, T->parm->ps_tm_lim, 1); else { double *xinit = xcalloc(1+prob->n, sizeof(double)); for (j = 1; j <= prob->n; j++) xinit[j] = T->mip->col[j]->mipx; status = proxy(prob, &zstar, xstar, xinit, 0.0, T->parm->ps_tm_lim, 1); xfree(xinit); } if (status == 0) glp_ios_heur_sol(T, xstar); xfree(xstar); glp_delete_prob(prob); done: return; } /* eof */ glpk-4.52.1/src/zlib/0000755000062000006210000000000012175147600013450 5ustar maomkpasswdglpk-4.52.1/src/zlib/adler32.c0000644000062000006210000001146012175147600015052 0ustar maomkpasswd/* adler32.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* adler32.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" static uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); #define BASE 65521 /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); /* use NO_DIVIDE if your processor does not do division in hardware -- try it both ways to see which is faster */ #ifdef NO_DIVIDE /* note that this assumes BASE is 65521, where 65536 % 65521 == 15 (thank you to John Reiser for pointing this out) */ # define CHOP(a) \ do { \ unsigned long tmp = a >> 16; \ a &= 0xffffUL; \ a += (tmp << 4) - tmp; \ } while (0) # define MOD28(a) \ do { \ CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) # define MOD(a) \ do { \ CHOP(a); \ MOD28(a); \ } while (0) # define MOD63(a) \ do { /* this assumes a is not negative */ \ z_off64_t tmp = a >> 32; \ a &= 0xffffffffL; \ a += (tmp << 8) - (tmp << 5) + tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ tmp = a >> 16; \ a &= 0xffffL; \ a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE # define MOD28(a) a %= BASE # define MOD63(a) a %= BASE #endif /* ========================================================================= */ uLong adler32(uLong adler, const Bytef *buf, uInt len) { unsigned long sum2; unsigned n; /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { adler += buf[0]; if (adler >= BASE) adler -= BASE; sum2 += adler; if (sum2 >= BASE) sum2 -= BASE; return adler | (sum2 << 16); } /* initial Adler-32 value (deferred check for len == 1 speed) */ if (buf == Z_NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { while (len--) { adler += *buf++; sum2 += adler; } if (adler >= BASE) adler -= BASE; MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } /* do length NMAX blocks -- requires just one modulo operation */ while (len >= NMAX) { len -= NMAX; n = NMAX / 16; /* NMAX is divisible by 16 */ do { DO16(buf); /* 16 sums unrolled */ buf += 16; } while (--n); MOD(adler); MOD(sum2); } /* do remaining bytes (less than NMAX, still just one modulo) */ if (len) { /* avoid modulos if none remaining */ while (len >= 16) { len -= 16; DO16(buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } MOD(adler); MOD(sum2); } /* return recombined sums */ return adler | (sum2 << 16); } /* ========================================================================= */ static uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) { unsigned long sum1; unsigned long sum2; unsigned rem; /* for negative len, return invalid adler32 as a clue for debugging */ if (len2 < 0) return 0xffffffffUL; /* the derivation of this formula is left as an exercise for the reader */ MOD63(len2); /* assumes len2 >= 0 */ rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); sum1 += (adler2 & 0xffff) + BASE - 1; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } /* ========================================================================= */ uLong adler32_combine(uLong adler1, uLong adler2, z_off_t len2) { return adler32_combine_(adler1, adler2, len2); } uLong adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) { return adler32_combine_(adler1, adler2, len2); } /* eof */ glpk-4.52.1/src/zlib/compress.c0000644000062000006210000000472612175147600015460 0ustar maomkpasswd/* compress.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* compress.c -- compress a memory buffer * Copyright (C) 1995-2005 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zlib.h" /* =========================================================================== Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least 0.1% larger than sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ int compress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) { z_stream stream; int err; stream.next_in = (Bytef*)source; stream.avail_in = (uInt)sourceLen; #if 0 /* by mao; #ifdef MAXSEG_64K */ /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; #endif stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; stream.opaque = (voidpf)0; err = deflateInit(&stream, level); if (err != Z_OK) return err; err = deflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { deflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } *destLen = stream.total_out; err = deflateEnd(&stream); return err; } /* =========================================================================== */ int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } /* =========================================================================== If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ uLong compressBound(uLong sourceLen) { return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; } /* eof */ glpk-4.52.1/src/zlib/crc32.c0000644000062000006210000003132512175147600014534 0ustar maomkpasswd/* crc32.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* crc32.c -- compute the CRC-32 of a data stream * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing * tables for updating the shift register in one step with three exclusive-ors * instead of four steps with four exclusive-ors. This results in about a * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. */ /* Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore protection on the static variables used to control the first-use generation of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. */ #ifdef MAKECRCH # include # ifndef DYNAMIC_CRC_TABLE # define DYNAMIC_CRC_TABLE # endif /* !DYNAMIC_CRC_TABLE */ #endif /* MAKECRCH */ #include "zutil.h" /* for STDC definitions */ /* Definitions for doing the crc four data bytes at a time. */ #if !defined(NOBYFOUR) # define BYFOUR #endif #ifdef BYFOUR static unsigned long crc32_little(unsigned long, const unsigned char *, unsigned); static unsigned long crc32_big(unsigned long, const unsigned char *, unsigned); # define TBLS 8 #else # define TBLS 1 #endif /* BYFOUR */ /* Local functions for crc concatenation */ static unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec); static void gf2_matrix_square(unsigned long *square, unsigned long *mat); static uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); #ifdef DYNAMIC_CRC_TABLE static volatile int crc_table_empty = 1; static z_crc_t crc_table[TBLS][256]; static void make_crc_table(void); #ifdef MAKECRCH static void write_table(FILE *, const z_crc_t *); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x (which is shifting right by one and adding x^32 mod p if the bit shifted out is a one). We start with the highest power (least significant bit) of q and repeat for all eight bits of q. The first table is simply the CRC of all possible eight bit values. This is all the information needed to generate CRCs on data a byte at a time for all combinations of CRC register values and incoming bytes. The remaining tables allow for word-at-a-time CRC calculation for both big-endian and little- endian machines, where a word is four bytes. */ static void make_crc_table(void) { z_crc_t c; int n, k; z_crc_t poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static volatile int first = 1; /* flag to limit concurrent making */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; /* See if another task is already doing this (not thread-safe, but better than nothing -- significantly reduces duration of vulnerability in case the advice about DYNAMIC_CRC_TABLE is ignored) */ if (first) { first = 0; /* make exclusive-or pattern from polynomial (0xedb88320UL) */ poly = 0; for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) poly |= (z_crc_t)1 << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { c = (z_crc_t)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table[0][n] = c; } #ifdef BYFOUR /* generate crc for each value followed by one, two, and three zeros, and then the byte reversal of those as well as the first table */ for (n = 0; n < 256; n++) { c = crc_table[0][n]; crc_table[4][n] = ZSWAP32(c); for (k = 1; k < 4; k++) { c = crc_table[0][c & 0xff] ^ (c >> 8); crc_table[k][n] = c; crc_table[k + 4][n] = ZSWAP32(c); } } #endif /* BYFOUR */ crc_table_empty = 0; } else { /* not first */ /* wait for the other guy to finish (not efficient, but rare) */ while (crc_table_empty) ; } #ifdef MAKECRCH /* write out CRC tables to crc32.h */ { FILE *out; out = fopen("crc32.h", "w"); if (out == NULL) return; fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); fprintf(out, "static const z_crc_t "); fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); write_table(out, crc_table[0]); # ifdef BYFOUR fprintf(out, "#ifdef BYFOUR\n"); for (k = 1; k < 8; k++) { fprintf(out, " },\n {\n"); write_table(out, crc_table[k]); } fprintf(out, "#endif\n"); # endif /* BYFOUR */ fprintf(out, " }\n};\n"); fclose(out); } #endif /* MAKECRCH */ } #ifdef MAKECRCH static void write_table(FILE *out, const z_crc_t *table) { int n; for (n = 0; n < 256; n++) fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", (unsigned long)(table[n]), n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ #else /* !DYNAMIC_CRC_TABLE */ /* ======================================================================== * Tables of CRC-32s of all single-byte values, made by make_crc_table(). */ #include "crc32.h" #endif /* DYNAMIC_CRC_TABLE */ /* ========================================================================= * This function can be used by asm versions of crc32() */ const z_crc_t *get_crc_table(void) { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ return (const z_crc_t *)crc_table; } /* ========================================================================= */ #define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ unsigned long crc32(unsigned long crc, const unsigned char *buf, uInt len) { if (buf == Z_NULL) return 0UL; #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { z_crc_t endian; endian = 1; if (*((unsigned char *)(&endian))) return crc32_little(crc, buf, len); else return crc32_big(crc, buf, len); } #endif /* BYFOUR */ crc = crc ^ 0xffffffffUL; while (len >= 8) { DO8; len -= 8; } if (len) do { DO1; } while (--len); return crc ^ 0xffffffffUL; } #ifdef BYFOUR /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 /* ========================================================================= */ static unsigned long crc32_little(unsigned long crc, const unsigned char *buf, unsigned len) { register z_crc_t c; register const z_crc_t *buf4; c = (z_crc_t)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } buf4 = (const z_crc_t *)(const void *)buf; while (len >= 32) { DOLIT32; len -= 32; } while (len >= 4) { DOLIT4; len -= 4; } buf = (const unsigned char *)buf4; if (len) do { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); } while (--len); c = ~c; return (unsigned long)c; } /* ========================================================================= */ #define DOBIG4 c ^= *++buf4; \ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 /* ========================================================================= */ static unsigned long crc32_big(unsigned long crc, const unsigned char *buf, unsigned len) { register z_crc_t c; register const z_crc_t *buf4; c = ZSWAP32((z_crc_t)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } buf4 = (const z_crc_t *)(const void *)buf; buf4--; while (len >= 32) { DOBIG32; len -= 32; } while (len >= 4) { DOBIG4; len -= 4; } buf4++; buf = (const unsigned char *)buf4; if (len) do { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); } while (--len); c = ~c; return (unsigned long)(ZSWAP32(c)); } #endif /* BYFOUR */ #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ /* ========================================================================= */ static unsigned long gf2_matrix_times(unsigned long *mat, unsigned long vec) { unsigned long sum; sum = 0; while (vec) { if (vec & 1) sum ^= *mat; vec >>= 1; mat++; } return sum; } /* ========================================================================= */ static void gf2_matrix_square(unsigned long *square, unsigned long *mat) { int n; for (n = 0; n < GF2_DIM; n++) square[n] = gf2_matrix_times(mat, mat[n]); } /* ========================================================================= */ static uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2) { int n; unsigned long row; unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ /* degenerate case (also disallow negative lengths) */ if (len2 <= 0) return crc1; /* put operator for one zero bit in odd */ odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ row = 1; for (n = 1; n < GF2_DIM; n++) { odd[n] = row; row <<= 1; } /* put operator for two zero bits in even */ gf2_matrix_square(even, odd); /* put operator for four zero bits in odd */ gf2_matrix_square(odd, even); /* apply len2 zeros to crc1 (first square will put the operator for one zero byte, eight zero bits, in even) */ do { /* apply zeros operator for this bit of len2 */ gf2_matrix_square(even, odd); if (len2 & 1) crc1 = gf2_matrix_times(even, crc1); len2 >>= 1; /* if no more bits set, then done */ if (len2 == 0) break; /* another iteration of the loop with odd and even swapped */ gf2_matrix_square(odd, even); if (len2 & 1) crc1 = gf2_matrix_times(odd, crc1); len2 >>= 1; /* if no more bits set, then done */ } while (len2 != 0); /* return combined crc */ crc1 ^= crc2; return crc1; } /* ========================================================================= */ uLong crc32_combine(uLong crc1, uLong crc2, z_off_t len2) { return crc32_combine_(crc1, crc2, len2); } uLong crc32_combine64(uLong crc1, uLong crc2, z_off64_t len2) { return crc32_combine_(crc1, crc2, len2); } /* eof */ glpk-4.52.1/src/zlib/crc32.h0000644000062000006210000007353712175147600014554 0ustar maomkpasswd/* crc32.h -- tables for rapid CRC calculation * Generated automatically by crc32.c */ static const z_crc_t crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, 0x2d02ef8dUL #ifdef BYFOUR }, { 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, 0x9324fd72UL }, { 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, 0xbe9834edUL }, { 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, 0xde0506f1UL }, { 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, 0x8def022dUL }, { 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, 0x72fd2493UL }, { 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, 0xed3498beUL }, { 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, 0xf10605deUL #endif } }; glpk-4.52.1/src/zlib/deflate.c0000644000062000006210000021150212175147600015221 0ustar maomkpasswd/* deflate.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* deflate.c -- compress data using the deflation algorithm * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ #include "deflate.h" const char deflate_copyright[] = " deflate 1.2.7 Copyright 1995-2012 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* =========================================================================== * Function prototypes. */ typedef enum { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ } block_state; typedef block_state (*compress_func)(deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ static void fill_window(deflate_state *s); static block_state deflate_stored(deflate_state *s, int flush); static block_state deflate_fast(deflate_state *s, int flush); #ifndef FASTEST static block_state deflate_slow(deflate_state *s, int flush); #endif static block_state deflate_rle(deflate_state *s, int flush); static block_state deflate_huff(deflate_state *s, int flush); static void lm_init(deflate_state *s); static void putShortMSB(deflate_state *s, uInt b); static void flush_pending(z_streamp strm); static int read_buf(z_streamp strm, Bytef *buf, unsigned size); static uInt longest_match(deflate_state *s, IPos cur_match); #ifdef DEBUG static void check_match(deflate_state *s, IPos start, IPos match, int length); #endif /* =========================================================================== * Local data */ #define NIL 0 /* Tail of hash chains */ #ifndef TOO_FAR # define TOO_FAR 4096 #endif /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ typedef struct config_s { ush good_length; /* reduce lazy search above this match length */ ush max_lazy; /* do not perform lazy search above this match length */ ush nice_length; /* quit search above this match length */ ush max_chain; compress_func func; } config; #ifdef FASTEST static const config configuration_table[2] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ #else static const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, /* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, /* 7 */ {8, 32, 128, 256, deflate_slow}, /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ #endif /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ #define EQUAL 0 /* result of memcmp for equal strings */ #ifndef NO_DUMMY_DECL struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ #define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) /* =========================================================================== * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. * IN assertion: all calls to to INSERT_STRING are made with consecutive * input characters and the first MIN_MATCH bytes of str are valid * (except for the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #else #define INSERT_STRING(s, str, match_head) \ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ s->head[s->ins_h] = (Pos)(str)) #endif /* =========================================================================== * Initialize the hash table (avoiding 64K overflow for 16 bit systems). * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ int deflateInit_(z_streamp strm, int level, const char *version, int stream_size) { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size) { deflate_state *s; int wrap = 1; static const char my_version[] = ZLIB_VERSION; ushf *overlay; /* We overlay pending_buf and d_buf+l_buf. This works since the average * output size for (length,distance) codes is <= 24 bits. */ if (version == Z_NULL || version[0] != my_version[0] || stream_size != sizeof(z_stream)) { return Z_VERSION_ERROR; } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; windowBits = -windowBits; } #ifdef GZIP else if (windowBits > 15) { wrap = 2; /* write gzip wrapper instead */ windowBits -= 16; } #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state *)s; s->strm = strm; s->wrap = wrap; s->gzhead = Z_NULL; s->w_bits = windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; s->hash_bits = memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->high_water = 0; /* nothing written to s->window yet */ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); s->pending_buf = (uchf *) overlay; s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } s->d_buf = overlay + s->lit_bufsize/sizeof(ush); s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; s->level = level; s->strategy = strategy; s->method = (Byte)method; return deflateReset(strm); } /* ========================================================================= */ int deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) { deflate_state *s; uInt str, n; int wrap; unsigned avail; unsigned char *next; if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) return Z_STREAM_ERROR; /* when using zlib wrappers, compute Adler-32 for provided dictionary */ if (wrap == 1) strm->adler = adler32(strm->adler, dictionary, dictLength); s->wrap = 0; /* avoid computing Adler-32 in read_buf */ /* if dictionary would fill window, just replace the history */ if (dictLength >= s->w_size) { if (wrap == 0) { /* already empty otherwise */ CLEAR_HASH(s); s->strstart = 0; s->block_start = 0L; s->insert = 0; } dictionary += dictLength - s->w_size; /* use the tail */ dictLength = s->w_size; } /* insert dictionary into window and hash */ avail = strm->avail_in; next = strm->next_in; strm->avail_in = dictLength; strm->next_in = (Bytef *)dictionary; fill_window(s); while (s->lookahead >= MIN_MATCH) { str = s->strstart; n = s->lookahead - (MIN_MATCH-1); do { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; } while (--n); s->strstart = str; s->lookahead = MIN_MATCH-1; fill_window(s); } s->strstart += s->lookahead; s->block_start = (long)s->strstart; s->insert = s->lookahead; s->lookahead = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; strm->next_in = next; strm->avail_in = avail; s->wrap = wrap; return Z_OK; } /* ========================================================================= */ int deflateResetKeep(z_streamp strm) { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { return Z_STREAM_ERROR; } strm->total_in = strm->total_out = 0; strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ strm->data_type = Z_UNKNOWN; s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } s->status = s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); s->last_flush = Z_NO_FLUSH; _tr_init(s); return Z_OK; } /* ========================================================================= */ int deflateReset(z_streamp strm) { int ret; ret = deflateResetKeep(strm); if (ret == Z_OK) lm_init(strm->state); return ret; } /* ========================================================================= */ int deflateSetHeader(z_streamp strm, gz_headerp head) { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (strm->state->wrap != 2) return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } /* ========================================================================= */ int deflatePending(z_streamp strm, unsigned *pending, int *bits) { if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) *bits = strm->state->bi_valid; return Z_OK; } /* ========================================================================= */ int deflatePrime(z_streamp strm, int bits, int value) { deflate_state *s; int put; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; do { put = Buf_size - s->bi_valid; if (put > bits) put = bits; s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); s->bi_valid += put; _tr_flush_bits(s); value >>= put; bits -= put; } while (bits); return Z_OK; } /* ========================================================================= */ int deflateParams(z_streamp strm, int level, int strategy) { deflate_state *s; compress_func func; int err = Z_OK; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST if (level != 0) level = 1; #else if (level == Z_DEFAULT_COMPRESSION) level = 6; #endif if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { return Z_STREAM_ERROR; } func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_BLOCK); } if (s->level != level) { s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; return err; } /* ========================================================================= */ int deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain) { deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; s = strm->state; s->good_match = good_length; s->max_lazy_match = max_lazy; s->nice_match = nice_length; s->max_chain_length = max_chain; return Z_OK; } /* ========================================================================= * For the default windowBits of 15 and memLevel of 8, this function returns * a close to exact, as well as small, upper bound on the compressed size. * They are coded as constants here for a reason--if the #define's are * changed, then this function needs to be changed as well. The return * value for 15 and 8 only works for those exact settings. * * For any setting other than those defaults for windowBits and memLevel, * the value returned is a conservative worst case for the maximum expansion * resulting from using fixed blocks instead of stored blocks, which deflate * can emit on compressed data for some combinations of the parameters. * * This function could be more sophisticated to provide closer upper bounds for * every combination of windowBits and memLevel. But even the conservative * upper bound of about 14% expansion does not seem onerous for output buffer * allocation. */ uLong deflateBound(z_streamp strm, uLong sourceLen) { deflate_state *s; uLong complen, wraplen; Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ if (strm == Z_NULL || strm->state == Z_NULL) return complen + 6; /* compute wrapper length */ s = strm->state; switch (s->wrap) { case 0: /* raw deflate */ wraplen = 0; break; case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; if (str != Z_NULL) do { wraplen++; } while (*str++); str = s->gzhead->comment; if (str != Z_NULL) do { wraplen++; } while (*str++); if (s->gzhead->hcrc) wraplen += 2; } break; default: /* for compiler happiness */ wraplen = 6; } /* if not default parameters, return conservative bound */ if (s->w_bits != 15 || s->hash_bits != 8 + 7) return complen + wraplen; /* default settings: return tight bound for that case */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } /* ========================================================================= * Put a short in the pending buffer. The 16-bit value is put in MSB order. * IN assertion: the stream state is correct and there is enough room in * pending_buf. */ static void putShortMSB(deflate_state *s, uInt b) { put_byte(s, (Byte)(b >> 8)); put_byte(s, (Byte)(b & 0xff)); } /* ========================================================================= * Flush as much pending output as possible. All deflate() output goes * through this function so some applications may wish to modify it * to avoid allocating a large strm->next_out buffer and copying into it. * (See also read_buf()). */ static void flush_pending(z_streamp strm) { unsigned len; deflate_state *s = strm->state; _tr_flush_bits(s); len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; s->pending_out += len; strm->total_out += len; strm->avail_out -= len; s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } /* ========================================================================= */ int deflate(z_streamp strm, int flush) { int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; if (strm == Z_NULL || strm->state == Z_NULL || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; /* Write the header */ if (s->status == INIT_STATE) { #ifdef GZIP if (s->wrap == 2) { strm->adler = crc32(0L, Z_NULL, 0); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); if (s->gzhead == Z_NULL) { put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, 0); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, OS_CODE); s->status = BUSY_STATE; } else { put_byte(s, (s->gzhead->text ? 1 : 0) + (s->gzhead->hcrc ? 2 : 0) + (s->gzhead->extra == Z_NULL ? 0 : 4) + (s->gzhead->name == Z_NULL ? 0 : 8) + (s->gzhead->comment == Z_NULL ? 0 : 16) ); put_byte(s, (Byte)(s->gzhead->time & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); put_byte(s, s->level == 9 ? 2 : (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? 4 : 0)); put_byte(s, s->gzhead->os & 0xff); if (s->gzhead->extra != Z_NULL) { put_byte(s, s->gzhead->extra_len & 0xff); put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); } if (s->gzhead->hcrc) strm->adler = crc32(strm->adler, s->pending_buf, s->pending); s->gzindex = 0; s->status = EXTRA_STATE; } } else #endif { uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; uInt level_flags; if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) level_flags = 0; else if (s->level < 6) level_flags = 1; else if (s->level == 6) level_flags = 2; else level_flags = 3; header |= (level_flags << 6); if (s->strstart != 0) header |= PRESET_DICT; header += 31 - (header % 31); s->status = BUSY_STATE; putShortMSB(s, header); /* Save the adler32 of the preset dictionary: */ if (s->strstart != 0) { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } strm->adler = adler32(0L, Z_NULL, 0); } } #ifdef GZIP if (s->status == EXTRA_STATE) { if (s->gzhead->extra != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) break; } put_byte(s, s->gzhead->extra[s->gzindex]); s->gzindex++; } if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (s->gzindex == s->gzhead->extra_len) { s->gzindex = 0; s->status = NAME_STATE; } } else s->status = NAME_STATE; } if (s->status == NAME_STATE) { if (s->gzhead->name != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->name[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) { s->gzindex = 0; s->status = COMMENT_STATE; } } else s->status = COMMENT_STATE; } if (s->status == COMMENT_STATE) { if (s->gzhead->comment != Z_NULL) { uInt beg = s->pending; /* start of bytes to update crc */ int val; do { if (s->pending == s->pending_buf_size) { if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); flush_pending(strm); beg = s->pending; if (s->pending == s->pending_buf_size) { val = 1; break; } } val = s->gzhead->comment[s->gzindex++]; put_byte(s, val); } while (val != 0); if (s->gzhead->hcrc && s->pending > beg) strm->adler = crc32(strm->adler, s->pending_buf + beg, s->pending - beg); if (val == 0) s->status = HCRC_STATE; } else s->status = HCRC_STATE; } if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { if (s->pending + 2 > s->pending_buf_size) flush_pending(strm); if (s->pending + 2 <= s->pending_buf_size) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); strm->adler = crc32(0L, Z_NULL, 0); s->status = BUSY_STATE; } } else s->status = BUSY_STATE; } #endif /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ s->last_flush = -1; return Z_OK; } /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } /* User must not provide more input after the first FINISH: */ if (s->status == FINISH_STATE && strm->avail_in != 0) { ERR_RETURN(strm, Z_BUF_ERROR); } /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : (s->strategy == Z_RLE ? deflate_rle(s, flush) : (*(configuration_table[s->level].func))(s, flush)); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; } if (bstate == need_more || bstate == finish_started) { if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ } return Z_OK; /* If flush != Z_NO_FLUSH && avail_out == 0, the next call * of deflate should use the same flush parameter to make sure * that the flush is complete. So we don't have to output an * empty block here, this will be done at next call. This also * ensures that for a very small output buffer, we emit at most * one empty block. */ } if (bstate == block_done) { if (flush == Z_PARTIAL_FLUSH) { _tr_align(s); } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ _tr_stored_block(s, (char*)0, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if (flush == Z_FULL_FLUSH) { CLEAR_HASH(s); /* forget history */ if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; s->insert = 0; } } } flush_pending(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; } } } Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { put_byte(s, (Byte)(strm->adler & 0xff)); put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); put_byte(s, (Byte)(strm->total_in & 0xff)); put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); } else #endif { putShortMSB(s, (uInt)(strm->adler >> 16)); putShortMSB(s, (uInt)(strm->adler & 0xffff)); } flush_pending(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ return s->pending != 0 ? Z_OK : Z_STREAM_END; } /* ========================================================================= */ int deflateEnd(z_streamp strm) { int status; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; status = strm->state->status; if (status != INIT_STATE && status != EXTRA_STATE && status != NAME_STATE && status != COMMENT_STATE && status != HCRC_STATE && status != BUSY_STATE && status != FINISH_STATE) { return Z_STREAM_ERROR; } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; } /* ========================================================================= * Copy the source state to the destination state. * To simplify the source, this is not supported for 16-bit MSDOS (which * doesn't have enough memory anyway to duplicate compression states). */ int deflateCopy(z_streamp dest, z_streamp source) { #if 0 /* by mao; #ifdef MAXSEG_64K */ return Z_STREAM_ERROR; #else deflate_state *ds; deflate_state *ss; ushf *overlay; if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { return Z_STREAM_ERROR; } ss = source->state; zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state *) ds; zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); ds->pending_buf = (uchf *) overlay; if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || ds->pending_buf == Z_NULL) { deflateEnd (dest); return Z_MEM_ERROR; } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; ds->l_desc.dyn_tree = ds->dyn_ltree; ds->d_desc.dyn_tree = ds->dyn_dtree; ds->bl_desc.dyn_tree = ds->bl_tree; return Z_OK; #endif /* MAXSEG_64K */ } /* =========================================================================== * Read a new buffer from the current input stream, update the adler32 * and total number of bytes read. All deflate() input goes through * this function so some applications may wish to modify it to avoid * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ static int read_buf(z_streamp strm, Bytef *buf, unsigned size) { unsigned len = strm->avail_in; if (len > size) len = size; if (len == 0) return 0; strm->avail_in -= len; zmemcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) { strm->adler = adler32(strm->adler, buf, len); } #ifdef GZIP else if (strm->state->wrap == 2) { strm->adler = crc32(strm->adler, buf, len); } #endif strm->next_in += len; strm->total_in += len; return (int)len; } /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ static void lm_init(deflate_state *s) { s->window_size = (ulg)2L*s->w_size; CLEAR_HASH(s); /* Set the default configuration parameters: */ s->max_lazy_match = configuration_table[s->level].max_lazy; s->good_match = configuration_table[s->level].good_length; s->nice_match = configuration_table[s->level].nice_length; s->max_chain_length = configuration_table[s->level].max_chain; s->strstart = 0; s->block_start = 0L; s->lookahead = 0; s->insert = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; #ifndef FASTEST #if 0 /* by mao; #ifdef ASMV */ match_init(); /* initialize the asm code */ #endif #endif } #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and * return its length. Matches shorter or equal to prev_length are discarded, * in which case the result is equal to prev_length and match_start is * garbage. * IN assertions: cur_match is the head of the hash chain for the current * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 * OUT assertion: the match length is not greater than s->lookahead. */ #if 1 /* by mao; #ifndef ASMV */ /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ static uInt longest_match(deflate_state *s, IPos cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ int best_len = s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ Posf *prev = s->prev; uInt wmask = s->w_mask; #ifdef UNALIGNED_OK /* Compare two bytes at a time. Note: this is not always beneficial. * Try with and without -DUNALIGNED_OK to check. */ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; register ush scan_start = *(ushf*)scan; register ush scan_end = *(ushf*)(scan+best_len-1); #else register Bytef *strend = s->window + s->strstart + MAX_MATCH; register Byte scan_end1 = scan[best_len-1]; register Byte scan_end = scan[best_len]; #endif /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); /* Do not waste too much time if we already have a good match: */ if (s->prev_length >= s->good_match) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below * for insufficient lookahead only occur occasionally for performance * reasons. Therefore uninitialized memory will be accessed, and * conditional jumps will be made that depend on those values. * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ #if (defined(UNALIGNED_OK) && MAX_MATCH == 258) /* This code assumes sizeof(unsigned short) == 2. Do not use * UNALIGNED_OK if your compiler uses a different size. */ if (*(ushf*)(match+best_len-1) != scan_end || *(ushf*)match != scan_start) continue; /* It is not necessary to compare scan[2] and match[2] since they are * always equal when the other bytes match, given that the hash keys * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at * strstart+3, +5, ... up to strstart+257. We check for insufficient * lookahead only every 4th comparison; the 128th check will be made * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is * necessary to put more guard bytes at the end of the window, or * to check more often for insufficient lookahead. */ Assert(scan[2] == match[2], "scan[2]?"); scan++, match++; do { } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && *(ushf*)(scan+=2) == *(ushf*)(match+=2) && scan < strend); /* The funny "do {}" generates better code on most compilers */ /* Here, scan <= window+strstart+257 */ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); if (*scan == *match) scan++; len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); scan = strend - MAX_MATCH; #endif /* UNALIGNED_OK */ if (len > best_len) { s->match_start = cur_match; best_len = len; if (len >= nice_match) break; #ifdef UNALIGNED_OK scan_end = *(ushf*)(scan+best_len-1); #else scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; #endif } } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if ((uInt)best_len <= s->lookahead) return (uInt)best_len; return s->lookahead; } #endif /* ASMV */ #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ static uInt longest_match(deflate_state *s, IPos cur_match) { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; /* Return failure if the match length is less than 2: */ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match += 2; Assert(*scan == *match, "match[2]?"); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while (*++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); len = MAX_MATCH - (int)(strend - scan); if (len < MIN_MATCH) return MIN_MATCH - 1; s->match_start = cur_match; return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; } #endif /* FASTEST */ #ifdef DEBUG /* =========================================================================== * Check that the match at match_start is indeed a match. */ static void check_match(deflate_state *s, IPos start, IPos match, int length) { /* check that the match is indeed a match */ if (zmemcmp(s->window + match, s->window + start, length) != EQUAL) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); do { fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); } while (--length != 0); z_error("invalid match"); } if (z_verbose > 1) { fprintf(stderr,"\\[%d,%d]", start-match, length); do { putc(s->window[start++], stderr); } while (--length != 0); } } #else # define check_match(s, start, match, length) #endif /* DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. * * IN assertion: lookahead < MIN_LOOKAHEAD * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD * At least one byte has been read, or avail_in == 0; reads are * performed for at least two bytes (required for the zip translate_eol * option -- not supported here). */ static void fill_window(deflate_state *s) { register unsigned n, m; register Posf *p; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); /* Deal with !@#$% 64K limit: */ if (sizeof(int) <= 2) { if (more == 0 && s->strstart == 0 && s->lookahead == 0) { more = wsize; } else if (more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if * strstart == 0 && lookahead == 1 (input done a byte at time) */ more--; } } /* If the window is almost full and there is insufficient lookahead, * move the upper half to the lower one to make room in the upper half. */ if (s->strstart >= wsize+MAX_DIST(s)) { zmemcpy(s->window, s->window+wsize, (unsigned)wsize); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values at the expense of memory usage). We slide even when level == 0 to keep the hash table consistent if we switch back to level > 0 later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ n = s->hash_size; p = &s->head[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); } while (--n); n = wsize; #ifndef FASTEST p = &s->prev[n]; do { m = *--p; *p = (Pos)(m >= wsize ? m-wsize : NIL); /* If n is not on any hash chain, prev[n] is garbage but * its value will never be used. */ } while (--n); #endif more += wsize; } if (s->strm->avail_in == 0) break; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && * more == window_size - lookahead - strstart * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) * => more >= window_size - 2*WSIZE + 2 * In the BIG_MEM or MMAP case (not yet supported), * window_size == input_size + MIN_LOOKAHEAD && * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. * Otherwise, window_size == 2*WSIZE so more >= 2. * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ if (s->lookahead + s->insert >= MIN_MATCH) { uInt str = s->strstart - s->insert; s->ins_h = s->window[str]; UPDATE_HASH(s, s->ins_h, s->window[str + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif while (s->insert) { UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); #ifndef FASTEST s->prev[str & s->w_mask] = s->head[s->ins_h]; #endif s->head[s->ins_h] = (Pos)str; str++; s->insert--; if (s->lookahead + s->insert < MIN_MATCH) break; } } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); /* If the WIN_INIT bytes after the end of the current data have never been * written, then zero those bytes in order to avoid memory check reports of * the use of uninitialized (or uninitialised as Julian writes) bytes by * the longest match routines. Update the high water mark for the next * time through here. WIN_INIT is set to MAX_MATCH since the longest match * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. */ if (s->high_water < s->window_size) { ulg curr = s->strstart + (ulg)(s->lookahead); ulg init; if (s->high_water < curr) { /* Previous high water mark below current data -- zero WIN_INIT * bytes or up to end of window, whichever is less. */ init = s->window_size - curr; if (init > WIN_INIT) init = WIN_INIT; zmemzero(s->window + curr, (unsigned)init); s->high_water = curr + init; } else if (s->high_water < (ulg)curr + WIN_INIT) { /* High water mark at or above current data, but below current data * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up * to end of window, whichever is less. */ init = (ulg)curr + WIN_INIT - s->high_water; if (init > s->window_size - s->high_water) init = s->window_size - s->high_water; zmemzero(s->window + s->high_water, (unsigned)init); s->high_water += init; } } Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, "not enough room for search"); } /* =========================================================================== * Flush the current block, with given end-of-file flag. * IN assertion: strstart is set to the end of the current match. */ #define FLUSH_BLOCK_ONLY(s, last) { \ _tr_flush_block(s, (s->block_start >= 0L ? \ (charf *)&s->window[(unsigned)s->block_start] : \ (charf *)Z_NULL), \ (ulg)((long)s->strstart - s->block_start), \ (last)); \ s->block_start = s->strstart; \ flush_pending(s->strm); \ Tracev((stderr,"[FLUSH]")); \ } /* Same but force premature exit if necessary. */ #define FLUSH_BLOCK(s, last) { \ FLUSH_BLOCK_ONLY(s, last); \ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. * This function does not insert new strings in the dictionary since * uncompressible data is probably not useful. This function is used * only for the level=0 compression option. * NOTE: this function should be optimized to avoid extra copying from * window to pending_buf. */ static block_state deflate_stored(deflate_state *s, int flush) { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: */ ulg max_block_size = 0xffff; ulg max_start; if (max_block_size > s->pending_buf_size - 5) { max_block_size = s->pending_buf_size - 5; } /* Copy as much as possible from input to output: */ for (;;) { /* Fill the window as much as possible: */ if (s->lookahead <= 1) { Assert(s->strstart < s->w_size+MAX_DIST(s) || s->block_start >= (long)s->w_size, "slide too late"); fill_window(s); if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) break; /* flush the current block */ } Assert(s->block_start >= 0L, "block gone"); s->strstart += s->lookahead; s->lookahead = 0; /* Emit a stored block if pending_buf will be full: */ max_start = s->block_start + max_block_size; if (s->strstart == 0 || (ulg)s->strstart >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ s->lookahead = (uInt)(s->strstart - max_start); s->strstart = (uInt)max_start; FLUSH_BLOCK(s, 0); } /* Flush if we may have to slide, otherwise block_start may become * negative and the data will be gone: */ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { FLUSH_BLOCK(s, 0); } } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if ((long)s->strstart > s->block_start) FLUSH_BLOCK(s, 0); return block_done; } /* =========================================================================== * Compress as much as possible from the input stream, return the current * block state. * This function does not perform lazy evaluation of matches and inserts * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ static block_state deflate_fast(deflate_state *s, int flush) { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < MIN_MATCH */ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->match_start, s->match_length); _tr_tally_dist(s, s->strstart - s->match_start, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ #ifndef FASTEST if (s->match_length <= s->max_insert_length && s->lookahead >= MIN_MATCH) { s->match_length--; /* string at strstart already in table */ do { s->strstart++; INSERT_STRING(s, s->strstart, hash_head); /* strstart never exceeds WSIZE-MAX_MATCH, so there are * always MIN_MATCH bytes ahead. */ } while (--s->match_length != 0); s->strstart++; } else #endif { s->strstart += s->match_length; s->match_length = 0; s->ins_h = s->window[s->strstart]; UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } #ifndef FASTEST /* =========================================================================== * Same as above, but achieves better compression. We use a lazy * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ static block_state deflate_slow(deflate_state *s, int flush) { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the next match, plus MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { fill_window(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = NIL; if (s->lookahead >= MIN_MATCH) { INSERT_STRING(s, s->strstart, hash_head); } /* Find the longest match, discarding those <= prev_length. */ s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; if (hash_head != NIL && s->prev_length < s->max_lazy_match && s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED #if TOO_FAR <= 32767 || (s->match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) #endif )) { /* If prev_match is also MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ s->match_length = MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); _tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH, bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ s->lookahead -= s->prev_length-1; s->prev_length -= 2; do { if (++s->strstart <= max_insert) { INSERT_STRING(s, s->strstart, hash_head); } } while (--s->prev_length != 0); s->match_available = 0; s->match_length = MIN_MATCH-1; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } else if (s->match_available) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); if (bflush) { FLUSH_BLOCK_ONLY(s, 0); } s->strstart++; s->lookahead--; if (s->strm->avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ s->match_available = 1; s->strstart++; s->lookahead--; } } Assert (flush != Z_NO_FLUSH, "no flush?"); if (s->match_available) { Tracevv((stderr,"%c", s->window[s->strstart-1])); _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } #endif /* FASTEST */ /* =========================================================================== * For Z_RLE, simply look for runs of bytes, generate matches only of distance * one. Do not maintain a hash table. (It will be regenerated if this run of * deflate switches away from Z_RLE.) */ static block_state deflate_rle(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ uInt prev; /* byte at distance one to match */ Bytef *scan, *strend; /* scan goes up to strend for length of run */ for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes * for the longest run, plus one for the unrolled loop. */ if (s->lookahead <= MAX_MATCH) { fill_window(s); if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ s->match_length = 0; if (s->lookahead >= MIN_MATCH && s->strstart > 0) { scan = s->window + s->strstart - 1; prev = *scan; if (prev == *++scan && prev == *++scan && prev == *++scan) { strend = s->window + s->strstart + MAX_MATCH; do { } while (prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); s->match_length = MAX_MATCH - (int)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ if (s->match_length >= MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, s->match_length); _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); s->lookahead -= s->match_length; s->strstart += s->match_length; s->match_length = 0; } else { /* No match, output a literal byte */ Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; } if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } /* =========================================================================== * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ static block_state deflate_huff(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ for (;;) { /* Make sure that we have a literal to write. */ if (s->lookahead == 0) { fill_window(s); if (s->lookahead == 0) { if (flush == Z_NO_FLUSH) return need_more; break; /* flush the current block */ } } /* Output a literal byte */ s->match_length = 0; Tracevv((stderr,"%c", s->window[s->strstart])); _tr_tally_lit (s, s->window[s->strstart], bflush); s->lookahead--; s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } s->insert = 0; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; } if (s->last_lit) FLUSH_BLOCK(s, 0); return block_done; } /* eof */ glpk-4.52.1/src/zlib/deflate.h0000644000062000006210000003063412175147600015233 0ustar maomkpasswd/* deflate.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* deflate.h -- internal compression state * Copyright (C) 1995-2012 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ #ifndef DEFLATE_H #define DEFLATE_H #include "zutil.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip encoding should be left enabled. */ #ifndef NO_GZIP # define GZIP #endif /* =========================================================================== * Internal compression state. */ #define LENGTH_CODES 29 /* number of length codes, not counting the special END_BLOCK code */ #define LITERALS 256 /* number of literal bytes 0..255 */ #define L_CODES (LITERALS+1+LENGTH_CODES) /* number of Literal or Length codes, including the END_BLOCK code */ #define D_CODES 30 /* number of distance codes */ #define BL_CODES 19 /* number of codes used to transfer the bit lengths */ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ #define Buf_size 16 /* size of bit buffer in bi_buf */ #define INIT_STATE 42 #define EXTRA_STATE 69 #define NAME_STATE 73 #define COMMENT_STATE 91 #define HCRC_STATE 103 #define BUSY_STATE 113 #define FINISH_STATE 666 /* Stream status */ /* Data structure describing a single value and its code string. */ typedef struct ct_data_s { union { ush freq; /* frequency count */ ush code; /* bit string */ } fc; union { ush dad; /* father node in Huffman tree */ ush len; /* length of bit string */ } dl; } ct_data; #define Freq fc.freq #define Code fc.code #define Dad dl.dad #define Len dl.len typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ static_tree_desc *stat_desc; /* the corresponding static tree */ } tree_desc; typedef ush Pos; typedef Pos Posf; typedef unsigned IPos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ uInt pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ uInt gzindex; /* where in extra, name, or comment */ Byte method; /* STORED (for zip only) or DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ uInt w_size; /* LZ77 window size (32K by default) */ uInt w_bits; /* log2(w_size) (8..16) */ uInt w_mask; /* w_size - 1 */ Bytef *window; /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of * wSize-MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. */ ulg window_size; /* Actual size of window: 2*wSize, except when the user input buffer * is directly used as sliding window. */ Posf *prev; /* Link to older string with same hash index. To limit the size of this * array to 64K, this link is maintained only for the last 32K strings. * An index in this array is thus a window index modulo 32K. */ Posf *head; /* Heads of the hash chains or NIL. */ uInt ins_h; /* hash index of string to be inserted */ uInt hash_size; /* number of elements in hash table */ uInt hash_bits; /* log2(hash_size) */ uInt hash_mask; /* hash_size-1 */ uInt hash_shift; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: * hash_shift * MIN_MATCH >= hash_bits */ long block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. */ uInt match_length; /* length of best match */ IPos prev_match; /* previous match */ int match_available; /* set if previous match exists */ uInt strstart; /* start of string to insert */ uInt match_start; /* start of matching string */ uInt lookahead; /* number of valid bytes ahead in window */ uInt prev_length; /* Length of the best match at previous step. Matches not greater than this * are discarded. This is used in the lazy match evaluation. */ uInt max_chain_length; /* To speed up deflation, hash chains are never searched beyond this * length. A higher limit improves compression ratio but degrades the * speed. */ uInt max_lazy_match; /* Attempt to find a better match only when the current match is strictly * smaller than this value. This mechanism is used only for compression * levels >= 4. */ # define max_insert_length max_lazy_match /* Insert new strings in the hash table only if the match length is not * greater than this length. This saves time but degrades compression. * max_insert_length is used only for compression levels <= 3. */ int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ uInt good_match; /* Use a faster search when the previous match is longer than this */ int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ struct tree_desc_s l_desc; /* desc. for literal tree */ struct tree_desc_s d_desc; /* desc. for distance tree */ struct tree_desc_s bl_desc; /* desc. for bit length tree */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ int heap_len; /* number of elements in the heap */ int heap_max; /* element of largest frequency */ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. * The same heap array is used to build all trees. */ uch depth[2*L_CODES+1]; /* Depth of each subtree used as tie breaker for trees of equal frequency */ uchf *l_buf; /* buffer for literals or lengths */ uInt lit_bufsize; /* Size of match buffer for literals/lengths. There are 4 reasons for * limiting lit_bufsize to 64K: * - frequencies can be kept in 16 bit counters * - if compression is not successful for the first block, all input * data is still in the window so we can still emit a stored block even * when input comes from standard input. (This can also be done for * all blocks if lit_bufsize is not greater than 32K.) * - if compression is not successful for a file smaller than 64K, we can * even emit a stored file instead of a stored block (saving 5 bytes). * This is applicable only for zip (not gzip or zlib). * - creating new Huffman trees less frequently may not provide fast * adaptation to changes in the input data statistics. (Take for * example a binary file with poorly compressible code followed by * a highly compressible string table.) Smaller buffer sizes give * fast adaptation but have of course the overhead of transmitting * trees more frequently. * - I can't count above 4 */ uInt last_lit; /* running index in l_buf */ ushf *d_buf; /* Buffer for distances. To simplify the code, d_buf and l_buf have * the same number of elements. To use different lengths, an extra flag * array would be necessary. */ ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ uInt insert; /* bytes at end of window left to insert */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif ush bi_buf; /* Output buffer. bits are inserted starting at the bottom (least * significant bits). */ int bi_valid; /* Number of valid bits in bi_buf. All bits above the last valid bit * are always zero. */ ulg high_water; /* High water mark offset in window for initialized bytes -- bytes above * this are set to zero in order to avoid memory check warnings when * longest match routines access bytes past the input. This is then * updated to the new high water mark. */ } deflate_state; /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ #define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) /* Minimum amount of lookahead, except at the end of the input file. * See deflate.c for comments about the MIN_MATCH+1. */ #define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ #define WIN_INIT MAX_MATCH /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ /* in trees.c */ void _tr_init(deflate_state *s); int _tr_tally(deflate_state *s, unsigned dist, unsigned lc); void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last); void _tr_flush_bits(deflate_state *s); void _tr_align(deflate_state *s); void _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last); #define d_code(dist) \ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. _dist_code[256] and _dist_code[257] are never * used. */ #ifndef DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) extern uch _length_code[]; extern uch _dist_code[]; #else extern const uch _length_code[]; extern const uch _dist_code[]; #endif # define _tr_tally_lit(s, c, flush) \ { uch cc = (c); \ s->d_buf[s->last_lit] = 0; \ s->l_buf[s->last_lit++] = cc; \ s->dyn_ltree[cc].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ { uch len = (length); \ ush dist = (distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \ flush = (s->last_lit == s->lit_bufsize-1); \ } #else # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_dist(s, distance, length, flush) \ flush = _tr_tally(s, distance, length) #endif #endif /* DEFLATE_H */ /* eof */ glpk-4.52.1/src/zlib/gzclose.c0000644000062000006210000000144112175147600015262 0ustar maomkpasswd/* gzclose.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* gzclose.c -- zlib gzclose() function * Copyright (C) 2004, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* gzclose() is in a separate file so that it is linked in only if it is used. That way the other gzclose functions can be used instead to avoid linking in unneeded compression or decompression routines. */ int gzclose(gzFile file) { #ifndef NO_GZCOMPRESS gz_statep state; if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); #else return gzclose_r(file); #endif } /* eof */ glpk-4.52.1/src/zlib/gzguts.h0000644000062000006210000000673412175147600015156 0ustar maomkpasswd/* gzguts.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* gzguts.h -- zlib internal header definitions for gz* operations * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include #include #include #include #include #include "zio.h" #include "zlib.h" /* get errno and strerror definition */ #define zstrerror() strerror(errno) gzFile gzopen64(const char *, const char *); z_off64_t gzseek64(gzFile, z_off64_t, int); z_off64_t gztell64(gzFile); z_off64_t gzoffset64(gzFile); /* default memLevel */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default i/o buffer size -- double this for output when reading */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ #define GZ_NONE 0 #define GZ_READ 7247 #define GZ_WRITE 31153 #define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ /* values for gz_state how */ #define LOOK 0 /* look for a gzip header */ #define COPY 1 /* copy input directly */ #define GZIP 2 /* decompress a gzip stream */ /* internal gzip file state data structure */ typedef struct { /* exposed contents for gzgetc() macro */ struct gzFile_s x; /* "x" for exposed */ /* x.have: number of bytes available at x.next */ /* x.next: next output data to deliver or write */ /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ int how; /* 0: get header, 1: copy, 2: decompress */ z_off64_t start; /* where the gzip data started, for rewinding */ int eof; /* true if end of input file reached */ int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ /* seek request */ z_off64_t skip; /* amount to skip (already rewound if backwards) */ int seek; /* true if seek request pending */ /* error information */ int err; /* error code */ char *msg; /* error message */ /* zlib inflate or deflate stream */ z_stream strm; /* stream structure in-place (not a pointer) */ } gz_state; typedef gz_state *gz_statep; void gz_error (gz_statep, int, const char *); /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ #define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) /* eof */ glpk-4.52.1/src/zlib/gzlib.c0000644000062000006210000003240012175147600014722 0ustar maomkpasswd/* gzlib.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* gzlib.c -- zlib functions common to reading and writing gzip files * Copyright (C) 2004, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" #define LSEEK lseek /* Local functions */ static void gz_reset (gz_statep); static gzFile gz_open (const void *, int, const char *); /* Reset gzip file state */ static void gz_reset(gz_statep state) { state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ state->eof = 0; /* not at end of file */ state->past = 0; /* have not read past end yet */ state->how = LOOK; /* look for gzip header */ } state->seek = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ } /* Open a gzip file either by name or file descriptor. */ static gzFile gz_open(const void *path, int fd, const char *mode) { gz_statep state; size_t len; int oflag; #if 0 /* by mao; #ifdef O_CLOEXEC */ int cloexec = 0; #endif #if 0 /* by mao; #ifdef O_EXCL */ int exclusive = 0; #endif /* check input */ if (path == NULL) return NULL; /* allocate gzFile structure to return */ state = malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ state->want = GZBUFSIZE; /* requested buffer size */ state->msg = NULL; /* no error message yet */ /* interpret mode */ state->mode = GZ_NONE; state->level = Z_DEFAULT_COMPRESSION; state->strategy = Z_DEFAULT_STRATEGY; state->direct = 0; while (*mode) { if (*mode >= '0' && *mode <= '9') state->level = *mode - '0'; else switch (*mode) { case 'r': state->mode = GZ_READ; break; #ifndef NO_GZCOMPRESS case 'w': state->mode = GZ_WRITE; break; case 'a': state->mode = GZ_APPEND; break; #endif case '+': /* can't read and write at the same time */ free(state); return NULL; case 'b': /* ignore -- will request binary anyway */ break; #if 0 /* by mao; #ifdef O_CLOEXEC */ case 'e': cloexec = 1; break; #endif #if 0 /* by mao; #ifdef O_EXCL */ case 'x': exclusive = 1; break; #endif case 'f': state->strategy = Z_FILTERED; break; case 'h': state->strategy = Z_HUFFMAN_ONLY; break; case 'R': state->strategy = Z_RLE; break; case 'F': state->strategy = Z_FIXED; case 'T': state->direct = 1; default: /* could consider as an error, but just ignore */ ; } mode++; } /* must provide an "r", "w", or "a" */ if (state->mode == GZ_NONE) { free(state); return NULL; } /* can't force transparent read */ if (state->mode == GZ_READ) { if (state->direct) { free(state); return NULL; } state->direct = 1; /* for empty file */ } /* save the path name for error messages */ #if 0 /* by mao; #ifdef _WIN32 */ if (fd == -2) { len = wcstombs(NULL, path, 0); if (len == (size_t)-1) len = 0; } else #endif len = strlen(path); state->path = malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } #if 0 /* by mao; #ifdef _WIN32 */ if (fd == -2) if (len) wcstombs(state->path, path, len + 1); else *(state->path) = 0; else #endif strcpy(state->path, path); /* compute the flags for open() */ oflag = #if 0 /* by mao; #ifdef O_LARGEFILE */ O_LARGEFILE | #endif #if 0 /* by mao; #ifdef O_BINARY */ O_BINARY | #endif #if 0 /* by mao; #ifdef O_CLOEXEC */ (cloexec ? O_CLOEXEC : 0) | #endif (state->mode == GZ_READ ? O_RDONLY : (O_WRONLY | O_CREAT | #if 0 /* by mao; #ifdef O_EXCL */ (exclusive ? O_EXCL : 0) | #endif (state->mode == GZ_WRITE ? O_TRUNC : O_APPEND))); /* open the file with the appropriate flags (or just use fd) */ state->fd = fd > -1 ? fd : ( #if 0 /* by mao; #ifdef _WIN32 */ fd == -2 ? _wopen(path, oflag, 0666) : #endif open(path, oflag, 0666)); if (state->fd == -1) { free(state->path); free(state); return NULL; } if (state->mode == GZ_APPEND) state->mode = GZ_WRITE; /* simplify later checks */ /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { state->start = LSEEK(state->fd, 0, SEEK_CUR); if (state->start == -1) state->start = 0; } /* initialize stream */ gz_reset(state); /* return stream */ return (gzFile)state; } /* -- see zlib.h -- */ gzFile gzopen(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile gzopen64(const char *path, const char *mode) { return gz_open(path, -1, mode); } /* -- see zlib.h -- */ gzFile gzdopen(int fd, const char *mode) { char *path; /* identifier for error messages */ gzFile gz; if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) return NULL; sprintf(path, "", fd); /* for debugging */ gz = gz_open(path, fd, mode); free(path); return gz; } /* -- see zlib.h -- */ int gzbuffer(gzFile file, unsigned size) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* make sure we haven't already allocated memory */ if (state->size != 0) return -1; /* check and set requested size */ if (size < 2) size = 2; /* need two bytes to check magic header */ state->want = size; return 0; } /* -- see zlib.h -- */ int gzrewind(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* back up and start over */ if (LSEEK(state->fd, state->start, SEEK_SET) == -1) return -1; gz_reset(state); return 0; } /* -- see zlib.h -- */ z_off64_t gzseek64(gzFile file, z_off64_t offset, int whence) { unsigned n; z_off64_t ret; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* check that there's no error */ if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; /* can only seek from start or relative to current position */ if (whence != SEEK_SET && whence != SEEK_CUR) return -1; /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) offset -= state->x.pos; else if (state->seek) offset += state->skip; state->seek = 0; /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); if (ret == -1) return -1; state->x.have = 0; state->eof = 0; state->past = 0; state->seek = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; state->x.pos += offset; return state->x.pos; } /* calculate skip amount, rewinding if needed for back seek when reading */ if (offset < 0) { if (state->mode != GZ_READ) /* writing -- can't go backwards */ return -1; offset += state->x.pos; if (offset < 0) /* before start of file! */ return -1; if (gzrewind(file) == -1) /* rewind, then skip to offset */ return -1; } /* if reading, skip what's in output buffer (one less gzgetc() check) */ if (state->mode == GZ_READ) { n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? (unsigned)offset : state->x.have; state->x.have -= n; state->x.next += n; state->x.pos += n; offset -= n; } /* request skip (if not zero) */ if (offset) { state->seek = 1; state->skip = offset; } return state->x.pos + offset; } /* -- see zlib.h -- */ z_off_t gzseek(gzFile file, z_off_t offset, int whence) { z_off64_t ret; ret = gzseek64(file, (z_off64_t)offset, whence); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t gztell64(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* return position */ return state->x.pos + (state->seek ? state->skip : 0); } /* -- see zlib.h -- */ z_off_t gztell(gzFile file) { z_off64_t ret; ret = gztell64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ z_off64_t gzoffset64(gzFile file) { z_off64_t offset; gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return -1; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return -1; /* compute and return effective offset in file */ offset = LSEEK(state->fd, 0, SEEK_CUR); if (offset == -1) return -1; if (state->mode == GZ_READ) /* reading */ offset -= state->strm.avail_in; /* don't count buffered input */ return offset; } /* -- see zlib.h -- */ z_off_t gzoffset(gzFile file) { z_off64_t ret; ret = gzoffset64(file); return ret == (z_off_t)ret ? (z_off_t)ret : -1; } /* -- see zlib.h -- */ int gzeof(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return 0; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return 0; /* return end-of-file state */ return state->mode == GZ_READ ? state->past : 0; } /* -- see zlib.h -- */ const char *gzerror(gzFile file, int *errnum) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return NULL; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return NULL; /* return error information */ if (errnum != NULL) *errnum = state->err; return state->msg == NULL ? "" : state->msg; } /* -- see zlib.h -- */ void gzclearerr(gzFile file) { gz_statep state; /* get internal structure and check integrity */ if (file == NULL) return; state = (gz_statep)file; if (state->mode != GZ_READ && state->mode != GZ_WRITE) return; /* clear error and end-of-file */ if (state->mode == GZ_READ) { state->eof = 0; state->past = 0; } gz_error(state, Z_OK, NULL); } /* Create an error message in allocated memory and set state->err and state->msg accordingly. Free any previous error message already there. Do not try to free or allocate space if the error is Z_MEM_ERROR (out of memory). Simply save the error message as a static string. If there is an allocation failure constructing the error message, then convert the error to out of memory. */ void gz_error(gz_statep state, int err, const char *msg) { /* free previously allocated message and clear */ if (state->msg != NULL) { if (state->err != Z_MEM_ERROR) free(state->msg); state->msg = NULL; } /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ if (err != Z_OK && err != Z_BUF_ERROR) state->x.have = 0; /* set error code, and if no message, then done */ state->err = err; if (msg == NULL) return; /* for an out of memory error, save as static string */ if (err == Z_MEM_ERROR) { state->msg = (char *)msg; return; } /* construct error message with path */ if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { state->err = Z_MEM_ERROR; state->msg = (char *)"out of memory"; return; } strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); return; } /* eof */ glpk-4.52.1/src/zlib/gzread.c0000644000062000006210000004362612175147600015103 0ustar maomkpasswd/* gzread.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* gzread.c -- zlib functions for reading gzip files * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* Local functions */ static int gz_load (gz_statep, unsigned char *, unsigned, unsigned *); static int gz_avail (gz_statep); static int gz_look (gz_statep); static int gz_decomp (gz_statep); static int gz_fetch (gz_statep); static int gz_skip (gz_statep, z_off64_t); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. This function needs to loop on read(), since read() is not guaranteed to read the number of bytes requested, depending on the type of descriptor. */ static int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have) { int ret; *have = 0; do { ret = read(state->fd, buf + *have, len - *have); if (ret <= 0) break; *have += ret; } while (*have < len); if (ret < 0) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } if (ret == 0) state->eof = 1; return 0; } /* Load up input buffer and set eof flag if last data loaded -- return -1 on error, 0 otherwise. Note that the eof flag is set when the end of the input file is reached, even though there may be unused data in the buffer. Once that data has been used, no more attempts will be made to read the file. If strm->avail_in != 0, then the current data is moved to the beginning of the input buffer, and then the remainder of the buffer is loaded with the available data from the input file. */ static int gz_avail(gz_statep state) { unsigned got; z_streamp strm = &(state->strm); if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; if (state->eof == 0) { if (strm->avail_in) { /* copy what's there to the start */ unsigned char *p = state->in, *q = strm->next_in; unsigned n = strm->avail_in; do { *p++ = *q++; } while (--n); } if (gz_load(state, state->in + strm->avail_in, state->size - strm->avail_in, &got) == -1) return -1; strm->avail_in += got; strm->next_in = state->in; } return 0; } /* Look for gzip header, set up for inflate or copy. state->x.have must be 0. If this is the first time in, allocate required memory. state->how will be left unchanged if there is no more input data available, will be set to COPY if there is no gzip header and direct copying will be performed, or it will be set to GZIP for decompression. If direct copying, then leftover input data from the input buffer will be copied to the output buffer. In that case, all further file reads will be directly to either the output buffer or a user buffer. If decompressing, the inflate state will be initialized. gz_look() will return 0 on success or -1 on failure. */ static int gz_look(gz_statep state) { z_streamp strm = &(state->strm); /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ state->in = malloc(state->want); state->out = malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { if (state->out != NULL) free(state->out); if (state->in != NULL) free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } state->size = state->want; /* allocate inflate memory */ state->strm.zalloc = Z_NULL; state->strm.zfree = Z_NULL; state->strm.opaque = Z_NULL; state->strm.avail_in = 0; state->strm.next_in = Z_NULL; if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ free(state->out); free(state->in); state->size = 0; gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } } /* get at least the magic bytes in the input buffer */ if (strm->avail_in < 2) { if (gz_avail(state) == -1) return -1; if (strm->avail_in == 0) return 0; } /* look for gzip magic bytes -- if there, do gzip decoding (note: there is a logical dilemma here when considering the case of a partially written gzip file, to wit, if a single 31 byte is written, then we cannot tell whether this is a single-byte file, or just a partially written gzip file -- for here we assume that if a gzip file is being written, then the header will be written in a single operation, so that reading a single byte is sufficient indication that it is not a gzip file) */ if (strm->avail_in > 1 && strm->next_in[0] == 31 && strm->next_in[1] == 139) { inflateReset(strm); state->how = GZIP; state->direct = 0; return 0; } /* no gzip header -- if we were decoding gzip before, then this is trailing garbage. Ignore the trailing garbage and finish. */ if (state->direct == 0) { strm->avail_in = 0; state->eof = 1; state->x.have = 0; return 0; } /* doing raw i/o, copy any leftover input to output -- this assumes that the output buffer is larger than the input buffer, which also assures space for gzungetc() */ state->x.next = state->out; if (strm->avail_in) { memcpy(state->x.next, strm->next_in, strm->avail_in); state->x.have = strm->avail_in; strm->avail_in = 0; } state->how = COPY; state->direct = 1; return 0; } /* Decompress from input to the provided next_out and avail_out in the state. On return, state->x.have and state->x.next point to the just decompressed data. If the gzip stream completes, state->how is reset to LOOK to look for the next gzip stream or raw data, once state->x.have is depleted. Returns 0 on success, -1 on failure. */ static int gz_decomp(gz_statep state) { int ret = Z_OK; unsigned had; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ had = strm->avail_out; do { /* get more input for inflate() */ if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in == 0) { gz_error(state, Z_BUF_ERROR, "unexpected end of file"); break; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, "internal error: inflate stream corrupt"); return -1; } if (ret == Z_MEM_ERROR) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ gz_error(state, Z_DATA_ERROR, strm->msg == NULL ? "compressed data error" : strm->msg); return -1; } } while (strm->avail_out && ret != Z_STREAM_END); /* update available output */ state->x.have = had - strm->avail_out; state->x.next = strm->next_out - state->x.have; /* if the gzip stream completed successfully, look for another */ if (ret == Z_STREAM_END) state->how = LOOK; /* good decompression */ return 0; } /* Fetch data and put it in the output buffer. Assumes state->x.have is 0. Data is either copied from the input file or decompressed from the input file depending on state->how. If state->how is LOOK, then a gzip header is looked for to determine whether to copy or decompress. Returns -1 on error, otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the end of the input file has been reached and all data has been processed. */ static int gz_fetch(gz_statep state) { z_streamp strm = &(state->strm); do { switch(state->how) { case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ if (gz_look(state) == -1) return -1; if (state->how == LOOK) return 0; break; case COPY: /* -> COPY */ if (gz_load(state, state->out, state->size << 1, &(state->x.have)) == -1) return -1; state->x.next = state->out; return 0; case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ strm->avail_out = state->size << 1; strm->next_out = state->out; if (gz_decomp(state) == -1) return -1; } } while (state->x.have == 0 && (!state->eof || strm->avail_in)); return 0; } /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ static int gz_skip(gz_statep state, z_off64_t len) { unsigned n; /* skip over len bytes or reach end-of-file, whichever comes first */ while (len) /* skip over whatever is in output buffer */ if (state->x.have) { n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? (unsigned)len : state->x.have; state->x.have -= n; state->x.next += n; state->x.pos += n; len -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && state->strm.avail_in == 0) break; /* need more data to skip -- load up output buffer */ else { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) return -1; } return 0; } /* -- see zlib.h -- */ int gzread(gzFile file, voidp buf, unsigned len) { unsigned got, n; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return -1; } /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return -1; } /* get len bytes to buf, or less than len if at the end */ got = 0; do { /* first just try copying data from the output buffer */ if (state->x.have) { n = state->x.have > len ? len : state->x.have; memcpy(buf, state->x.next, n); state->x.next += n; state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ else if (state->eof && strm->avail_in == 0) { state->past = 1; /* tried to read past end */ break; } /* need output data -- for small len or new stream load up our output buffer */ else if (state->how == LOOK || len < (state->size << 1)) { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) return -1; continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ if (gz_load(state, buf, len, &n) == -1) return -1; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ strm->avail_out = len; strm->next_out = buf; if (gz_decomp(state) == -1) return -1; n = state->x.have; state->x.have = 0; } /* update progress */ len -= n; buf = (char *)buf + n; got += n; state->x.pos += n; } while (len); /* return number of bytes read into user buffer (will fit in int) */ return (int)got; } /* -- see zlib.h -- */ int gzgetc(gzFile file) { int ret; unsigned char buf[1]; gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* try output buffer (no need to check for skip request) */ if (state->x.have) { state->x.have--; state->x.pos++; return *(state->x.next)++; } /* nothing there -- try gzread() */ ret = gzread(file, buf, 1); return ret < 1 ? -1 : buf[0]; } /* -- see zlib.h -- */ int gzungetc(int c, gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return -1; } /* can't push EOF */ if (c < 0) return -1; /* if output buffer empty, put byte at end (allows more pushing) */ if (state->x.have == 0) { state->x.have = 1; state->x.next = state->out + (state->size << 1) - 1; state->x.next[0] = c; state->x.pos--; state->past = 0; return c; } /* if no room, give up (must have already done a gzungetc()) */ if (state->x.have == (state->size << 1)) { gz_error(state, Z_DATA_ERROR, "out of room to push characters"); return -1; } /* slide output data if needed and insert byte before existing data */ if (state->x.next == state->out) { unsigned char *src = state->out + state->x.have; unsigned char *dest = state->out + (state->size << 1); while (src > state->out) *--dest = *--src; state->x.next = dest; } state->x.have++; state->x.next--; state->x.next[0] = c; state->x.pos--; state->past = 0; return c; } /* -- see zlib.h -- */ char *gzgets(gzFile file, char *buf, int len) { unsigned left, n; char *str; unsigned char *eol; gz_statep state; /* check parameters and get internal structure */ if (file == NULL || buf == NULL || len < 1) return NULL; state = (gz_statep)file; /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return NULL; /* process a skip request */ if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) return NULL; } /* copy output bytes up to new line or len - 1, whichever comes first -- append a terminating zero to the string (we don't check for a zero in the contents, let the user worry about that) */ str = buf; left = (unsigned)len - 1; if (left) do { /* assure that something is in the output buffer */ if (state->x.have == 0 && gz_fetch(state) == -1) return NULL; /* error */ if (state->x.have == 0) { /* end of file */ state->past = 1; /* read past end */ break; /* return what we have */ } /* look for end-of-line in current output buffer */ n = state->x.have > left ? left : state->x.have; eol = memchr(state->x.next, '\n', n); if (eol != NULL) n = (unsigned)(eol - state->x.next) + 1; /* copy through end-of-line, or remainder if not found */ memcpy(buf, state->x.next, n); state->x.have -= n; state->x.next += n; state->x.pos += n; left -= n; buf += n; } while (left && eol == NULL); /* return terminated string, or if nothing, end of file */ if (buf == str) return NULL; buf[0] = 0; return str; } /* -- see zlib.h -- */ int gzdirect(gzFile file) { gz_statep state; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; /* if the state is not known, but we can find out, then do so (this is mainly for right after a gzopen() or gzdopen()) */ if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) (void)gz_look(state); /* return 1 if transparent, 0 if processing a gzip stream */ return state->direct; } /* -- see zlib.h -- */ int gzclose_r(gzFile file) { int ret, err; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're reading */ if (state->mode != GZ_READ) return Z_STREAM_ERROR; /* free memory and close file */ if (state->size) { inflateEnd(&(state->strm)); free(state->out); free(state->in); } err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; gz_error(state, Z_OK, NULL); free(state->path); ret = close(state->fd); free(state); return ret ? Z_ERRNO : err; } /* eof */ glpk-4.52.1/src/zlib/gzwrite.c0000644000062000006210000003055212175147600015314 0ustar maomkpasswd/* gzwrite.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* gzwrite.c -- zlib functions for writing gzip files * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" /* Local functions */ static int gz_init (gz_statep); static int gz_comp (gz_statep, int); static int gz_zero (gz_statep, z_off64_t); /* Initialize state for writing a gzip file. Mark initialization by setting state->size to non-zero. Return -1 on failure or 0 on success. */ static int gz_init(gz_statep state) { int ret; z_streamp strm = &(state->strm); /* allocate input buffer */ state->in = malloc(state->want); if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* only need output buffer and deflate state if compressing */ if (!state->direct) { /* allocate output buffer */ state->out = malloc(state->want); if (state->out == NULL) { free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } /* allocate deflate memory, set up for gzip compression */ strm->zalloc = Z_NULL; strm->zfree = Z_NULL; strm->opaque = Z_NULL; ret = deflateInit2(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); if (ret != Z_OK) { free(state->out); free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } } /* mark state as initialized */ state->size = state->want; /* initialize write buffer if compressing */ if (!state->direct) { strm->avail_out = state->size; strm->next_out = state->out; state->x.next = strm->next_out; } return 0; } /* Compress whatever is at avail_in and next_in and write to the output file. Return -1 if there is an error writing to the output file, otherwise 0. flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, then the deflate() state is reset to start a new gzip stream. If gz->direct is true, then simply write to the output file without compressing, and ignore flush. */ static int gz_comp(gz_statep state, int flush) { int ret, got; unsigned have; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return -1; /* write directly if requested */ if (state->direct) { got = write(state->fd, strm->next_in, strm->avail_in); if (got < 0 || (unsigned)got != strm->avail_in) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } strm->avail_in = 0; return 0; } /* run deflate() on provided input until it produces no more output */ ret = Z_OK; do { /* write out current buffer contents if full, or if flushing, but if doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { have = (unsigned)(strm->next_out - state->x.next); if (have && ((got = write(state->fd, state->x.next, have)) < 0 || (unsigned)got != have)) { gz_error(state, Z_ERRNO, zstrerror()); return -1; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; } state->x.next = strm->next_out; } /* compress */ have = strm->avail_out; ret = deflate(strm, flush); if (ret == Z_STREAM_ERROR) { gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt"); return -1; } have -= strm->avail_out; } while (have); /* if that completed a deflate stream, allow another to start */ if (flush == Z_FINISH) deflateReset(strm); /* all done, no errors */ return 0; } /* Compress len zeros to output. Return -1 on error, 0 on success. */ static int gz_zero(gz_statep state, z_off64_t len) { int first; unsigned n; z_streamp strm = &(state->strm); /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return -1; /* compress len zeros (len guaranteed > 0) */ first = 1; while (len) { n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size; if (first) { memset(state->in, 0, n); first = 0; } strm->avail_in = n; strm->next_in = state->in; state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return -1; len -= n; } return 0; } /* -- see zlib.h -- */ int gzwrite(gzFile file, voidpc buf, unsigned len) { unsigned put = len; unsigned n; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return 0; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return 0; } /* if len is zero, avoid unnecessary operations */ if (len == 0) return 0; /* allocate memory if this is the first time through */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* for small len, copy to input buffer, otherwise compress directly */ if (len < state->size) { /* copy to input buffer, compress when full */ do { if (strm->avail_in == 0) strm->next_in = state->in; n = state->size - strm->avail_in; if (n > len) n = len; memcpy(strm->next_in + strm->avail_in, buf, n); strm->avail_in += n; state->x.pos += n; buf = (char *)buf + n; len -= n; if (len && gz_comp(state, Z_NO_FLUSH) == -1) return 0; } while (len); } else { /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ strm->avail_in = len; strm->next_in = (voidp)buf; state->x.pos += len; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; } /* input was all buffered or compressed (put will fit in int) */ return (int)put; } /* -- see zlib.h -- */ int gzputc(gzFile file, int c) { unsigned char buf[1]; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return -1; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ if (strm->avail_in < state->size) { if (strm->avail_in == 0) strm->next_in = state->in; strm->next_in[strm->avail_in++] = c; state->x.pos++; return c & 0xff; } /* no room in buffer or not initialized, use gz_write() */ buf[0] = c; if (gzwrite(file, buf, 1) != 1) return -1; return c & 0xff; } /* -- see zlib.h -- */ int gzputs(gzFile file, const char *str) { int ret; unsigned len; /* write string */ len = (unsigned)strlen(str); ret = gzwrite(file, str, len); return ret == 0 && len != 0 ? -1 : ret; } /* -- see zlib.h -- */ int gzprintf(gzFile file, const char *format, ...) { int size, len; gz_statep state; z_streamp strm; va_list va; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) return 0; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return 0; } /* consume whatever's left in the input buffer */ if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* do the printf() into the input buffer, put length in len */ size = (int)(state->size); state->in[size - 1] = 0; va_start(va, format); len = vsprintf((char *)(state->in), format, va); va_end(va); /* check that printf() results fit in buffer */ if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) return 0; /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; state->x.pos += len; return len; } /* -- see zlib.h -- */ int gzflush(gzFile file, int flush) { gz_statep state; /* get internal structure */ if (file == NULL) return -1; state = (gz_statep)file; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* check flush parameter */ if (flush < 0 || flush > Z_FINISH) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* compress remaining data with requested flush */ gz_comp(state, flush); return state->err; } /* -- see zlib.h -- */ int gzsetparams(gzFile file, int level, int strategy) { gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ if (level == state->level && strategy == state->strategy) return Z_OK; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) return -1; } /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) return state->err; deflateParams(strm, level, strategy); } state->level = level; state->strategy = strategy; return Z_OK; } /* -- see zlib.h -- */ int gzclose_w(gzFile file) { int ret = Z_OK; gz_statep state; /* get internal structure */ if (file == NULL) return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing */ if (state->mode != GZ_WRITE) return Z_STREAM_ERROR; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) ret = state->err; } /* flush, free memory, and close file */ if (state->size) { if (gz_comp(state, Z_FINISH) == -1) ret = state->err; if (!state->direct) { (void)deflateEnd(&(state->strm)); free(state->out); } free(state->in); } gz_error(state, Z_OK, NULL); free(state->path); if (close(state->fd) == -1) ret = Z_ERRNO; free(state); return ret; } /* eof */ glpk-4.52.1/src/zlib/inffast.c0000644000062000006210000003230712175147600015253 0ustar maomkpasswd/* inffast.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* inffast.c -- fast decoding * Copyright (C) 1995-2008, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" /* Allow machine dependent optimization for post-increment or pre-increment. Based on testing to date, Pre-increment preferred for: - PowerPC G3 (Adler) - MIPS R5000 (Randers-Pehrson) Post-increment preferred for: - none No measurable difference: - Pentium III (Anderson) - M68060 (Nikl) */ #ifdef POSTINC # define OFF 0 # define PUP(a) *(a)++ #else # define OFF 1 # define PUP(a) *++(a) #endif /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode == LEN strm->avail_in >= 6 strm->avail_out >= 258 start >= strm->avail_out state->bits < 8 On return, state->mode is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if strm->avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ void inflate_fast(z_streamp strm, unsigned start) /* start = inflate()'s starting value for strm->avail_out */ { struct inflate_state *state; unsigned char *in; /* local strm->next_in */ unsigned char *last; /* while in < last, enough input available */ unsigned char *out; /* local strm->next_out */ unsigned char *beg; /* inflate()'s initial strm->next_out */ unsigned char *end; /* while out < end, enough space available */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ code const *lcode; /* local strm->lencode */ code const *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ code here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char *from; /* where to copy match from */ /* copy state to local variables */ state = (struct inflate_state *)strm->state; in = strm->next_in - OFF; last = in + (strm->avail_in - 5); out = strm->next_out - OFF; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT dmax = state->dmax; #endif wsize = state->wsize; whave = state->whave; wnext = state->wnext; window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; dcode = state->distcode; lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = lcode[hold & lmask]; dolen: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op == 0) { /* literal */ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); PUP(out) = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); hold >>= op; bits -= op; } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; hold += (unsigned long)(PUP(in)) << bits; bits += 8; } here = dcode[hold & dmask]; dodist: op = (unsigned)(here.bits); hold >>= op; bits -= op; op = (unsigned)(here.op); if (op & 16) { /* distance base */ dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; if (bits < op) { hold += (unsigned long)(PUP(in)) << bits; bits += 8; } } dist += (unsigned)hold & ((1U << op) - 1); #ifdef INFLATE_STRICT if (dist > dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif hold >>= op; bits -= op; Tracevv((stderr, "inflate: distance %u\n", dist)); op = (unsigned)(out - beg); /* max distance in output */ if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { PUP(out) = 0; } while (--len); continue; } len -= op - whave; do { PUP(out) = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { PUP(out) = PUP(from); } while (--len); continue; } #endif } from = window - OFF; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } else if (wnext < op) { /* wrap around window */ from += wsize + wnext - op; op -= wnext; if (op < len) { /* some from end of window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = window - OFF; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ from += wnext - op; if (op < len) { /* some from window */ len -= op; do { PUP(out) = PUP(from); } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ PUP(out) = PUP(from); PUP(out) = PUP(from); PUP(out) = PUP(from); len -= 3; } while (len > 2); if (len) { PUP(out) = PUP(from); if (len > 1) PUP(out) = PUP(from); } } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode[here.val + (hold & ((1U << op) - 1))]; goto dodist; } else { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } } else if ((op & 64) == 0) { /* 2nd level length code */ here = lcode[here.val + (hold & ((1U << op) - 1))]; goto dolen; } else if (op & 32) { /* end-of-block */ Tracevv((stderr, "inflate: end of block\n")); state->mode = TYPE; break; } else { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; in -= len; bits -= len << 3; hold &= (1U << bits) - 1; /* update state and return */ strm->next_in = in + OFF; strm->next_out = out + OFF; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); state->hold = hold; state->bits = bits; return; } /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ /* eof */ glpk-4.52.1/src/zlib/inffast.h0000644000062000006210000000104512175147600015253 0ustar maomkpasswd/* inffast.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* inffast.h -- header to use inffast.c * Copyright (C) 1995-2003, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ void inflate_fast(z_streamp strm, unsigned start); /* eof */ glpk-4.52.1/src/zlib/inffixed.h0000644000062000006210000001427412175147600015425 0ustar maomkpasswd /* inffixed.h -- table for decoding fixed codes * Generated automatically by makefixed(). */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of this library and is subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, {0,9,255} }; static const code distfix[32] = { {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, {22,5,193},{64,5,0} }; glpk-4.52.1/src/zlib/inflate.c0000644000062000006210000014663212175147600015252 0ustar maomkpasswd/* inflate.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* inflate.c -- zlib decompression * Copyright (C) 1995-2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* * Change history: * * 1.2.beta0 24 Nov 2002 * - First version -- complete rewrite of inflate to simplify code, avoid * creation of window when not needed, minimize use of window when it is * needed, make inffast.c even faster, implement gzip decoding, and to * improve code readability and style over the previous zlib inflate code * * 1.2.beta1 25 Nov 2002 * - Use pointers for available input and output checking in inffast.c * - Remove input and output counters in inffast.c * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 * - Remove unnecessary second byte pull from length extra in inffast.c * - Unroll direct copy to three copies per loop in inffast.c * * 1.2.beta2 4 Dec 2002 * - Change external routine names to reduce potential conflicts * - Correct filename to inffixed.h for fixed tables in inflate.c * - Make hbuf[] unsigned char to match parameter type in inflate.c * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) * to avoid negation problem on Alphas (64 bit) in inflate.c * * 1.2.beta3 22 Dec 2002 * - Add comments on state->bits assertion in inffast.c * - Add comments on op field in inftrees.h * - Fix bug in reuse of allocated window after inflateReset() * - Remove bit fields--back to byte structure for speed * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths * - Change post-increments to pre-increments in inflate_fast(), PPC biased? * - Add compile time option, POSTINC, to use post-increments instead (Intel?) * - Make MATCH copy in inflate() much faster for when inflate_fast() not used * - Use local copies of stream next and avail values, as well as local bit * buffer and bit count in inflate()--for speed when inflate_fast() not used * * 1.2.beta4 1 Jan 2003 * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings * - Move a comment on output buffer sizes from inffast.c to inflate.c * - Add comments in inffast.c to introduce the inflate_fast() routine * - Rearrange window copies in inflate_fast() for speed and simplification * - Unroll last copy for window match in inflate_fast() * - Use local copies of window variables in inflate_fast() for speed * - Pull out common wnext == 0 case for speed in inflate_fast() * - Make op and len in inflate_fast() unsigned for consistency * - Add FAR to lcode and dcode declarations in inflate_fast() * - Simplified bad distance check in inflate_fast() * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new * source file infback.c to provide a call-back interface to inflate for * programs like gzip and unzip -- uses window as output buffer to avoid * window copying * * 1.2.beta5 1 Jan 2003 * - Improved inflateBack() interface to allow the caller to provide initial * input in strm. * - Fixed stored blocks bug in inflateBack() * * 1.2.beta6 4 Jan 2003 * - Added comments in inffast.c on effectiveness of POSTINC * - Typecasting all around to reduce compiler warnings * - Changed loops from while (1) or do {} while (1) to for (;;), again to * make compilers happy * - Changed type of window in inflateBackInit() to unsigned char * * * 1.2.beta7 27 Jan 2003 * - Changed many types to unsigned or unsigned short to avoid warnings * - Added inflateCopy() function * * 1.2.0 9 Mar 2003 * - Changed inflateBack() interface to provide separate opaque descriptors * for the in() and out() functions * - Changed inflateBack() argument and in_func typedef to swap the length * and buffer address return values for the input function * - Check next_in and next_out for Z_NULL on entry to inflate() * * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. */ #include "zutil.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" #ifdef MAKEFIXED # ifndef BUILDFIXED # define BUILDFIXED # endif #endif /* function prototypes */ static void fixedtables(struct inflate_state *state); static int updatewindow(z_streamp strm, unsigned out); #ifdef BUILDFIXED void makefixed(void); #endif static unsigned syncsearch(unsigned *have, unsigned char *buf, unsigned len); int inflateResetKeep(z_streamp strm) { struct inflate_state *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; if (state->wrap) /* to support ill-conceived Java test suite */ strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->dmax = 32768U; state->head = Z_NULL; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; state->sane = 1; state->back = -1; Tracev((stderr, "inflate: reset\n")); return Z_OK; } int inflateReset(z_streamp strm) { struct inflate_state *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; state->wsize = 0; state->whave = 0; state->wnext = 0; return inflateResetKeep(strm); } int inflateReset2(z_streamp strm, int windowBits) { int wrap; struct inflate_state *state; /* get the state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; /* extract wrap request from windowBits parameter */ if (windowBits < 0) { wrap = 0; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 1; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; #endif } /* set number of window bits, free window if different */ if (windowBits && (windowBits < 8 || windowBits > 15)) return Z_STREAM_ERROR; if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { ZFREE(strm, state->window); state->window = Z_NULL; } /* update state and reset the rest of it */ state->wrap = wrap; state->wbits = (unsigned)windowBits; return inflateReset(strm); } int inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) { int ret; struct inflate_state *state; if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || stream_size != (int)(sizeof(z_stream))) return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; #endif } if (strm->zfree == (free_func)0) #ifdef Z_SOLO return Z_STREAM_ERROR; #else strm->zfree = zcfree; #endif state = (struct inflate_state *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state *)state; state->window = Z_NULL; ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); strm->state = Z_NULL; } return ret; } int inflateInit_(z_streamp strm, const char *version, int stream_size) { return inflateInit2_(strm, DEF_WBITS, version, stream_size); } int inflatePrime(z_streamp strm, int bits, int value) { struct inflate_state *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; state->hold += value << state->bits; state->bits += bits; return Z_OK; } /* Return state with length and distance decoding tables and index sizes set to fixed code decoding. Normally this returns fixed tables from inffixed.h. If BUILDFIXED is defined, then instead this routine builds the tables the first time it's called, and returns those tables the first time and thereafter. This reduces the size of the code by about 2K bytes, in exchange for a little execution time. However, BUILDFIXED should not be used for threaded applications, since the rewriting of the tables and virgin may not be thread-safe. */ static void fixedtables(struct inflate_state *state) { #ifdef BUILDFIXED static int virgin = 1; static code *lenfix, *distfix; static code fixed[544]; /* build fixed huffman tables if first call (may not be thread safe) */ if (virgin) { unsigned sym, bits; static code *next; /* literal/length table */ sym = 0; while (sym < 144) state->lens[sym++] = 8; while (sym < 256) state->lens[sym++] = 9; while (sym < 280) state->lens[sym++] = 7; while (sym < 288) state->lens[sym++] = 8; next = fixed; lenfix = next; bits = 9; inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); /* distance table */ sym = 0; while (sym < 32) state->lens[sym++] = 5; distfix = next; bits = 5; inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); /* do this just once */ virgin = 0; } #else /* !BUILDFIXED */ # include "inffixed.h" #endif /* BUILDFIXED */ state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; state->distbits = 5; } #ifdef MAKEFIXED #include /* Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also defines BUILDFIXED, so the tables are built on the fly. makefixed() writes those tables to stdout, which would be piped to inffixed.h. A small program can simply call makefixed to do this: void makefixed(void); int main(void) { makefixed(); return 0; } Then that can be linked with zlib built with MAKEFIXED defined and run: a.out > inffixed.h */ void makefixed(void) { unsigned low, size; struct inflate_state state; fixedtables(&state); puts(" /* inffixed.h -- table for decoding fixed codes"); puts(" * Generated automatically by makefixed()."); puts(" */"); puts(""); puts(" /* WARNING: this file should *not* be used by applications."); puts(" It is part of the implementation of this library and is"); puts(" subject to change. Applications should only use zlib.h."); puts(" */"); puts(""); size = 1U << 9; printf(" static const code lenfix[%u] = {", size); low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); size = 1U << 5; printf("\n static const code distfix[%u] = {", size); low = 0; for (;;) { if ((low % 6) == 0) printf("\n "); printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, state.distcode[low].val); if (++low == size) break; putchar(','); } puts("\n };"); } #endif /* MAKEFIXED */ /* Update the window with the last wsize (normally 32K) bytes written before returning. If window does not exist yet, create it. This is only called when a window is already in use, or when output has been written during this inflate call, but the end of the deflate stream has not been reached yet. It is also called to create a window for dictionary data when a dictionary is loaded. Providing output buffers larger than 32K to inflate() should provide a speed advantage, since only the last 32K of output is copied to the sliding window upon return from inflate(), and since all distances after the first 32K of output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ static int updatewindow(z_streamp strm, unsigned out) { struct inflate_state *state; unsigned copy, dist; state = (struct inflate_state *)strm->state; /* if it hasn't been done already, allocate space for the window */ if (state->window == Z_NULL) { state->window = (unsigned char *) ZALLOC(strm, 1U << state->wbits, sizeof(unsigned char)); if (state->window == Z_NULL) return 1; } /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; state->wnext = 0; state->whave = 0; } /* copy state->wsize or less output bytes into the circular window */ copy = out - strm->avail_out; if (copy >= state->wsize) { zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, strm->next_out - copy, copy); state->wnext = copy; state->whave = state->wsize; } else { state->wnext += dist; if (state->wnext == state->wsize) state->wnext = 0; if (state->whave < state->wsize) state->whave += dist; } } return 0; } /* Macros for inflate(): */ /* check function to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP # define UPDATE(check, buf, len) \ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) #else # define UPDATE(check, buf, len) adler32(check, buf, len) #endif /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ check = crc32(check, hbuf, 2); \ } while (0) # define CRC4(check, word) \ do { \ hbuf[0] = (unsigned char)(word); \ hbuf[1] = (unsigned char)((word) >> 8); \ hbuf[2] = (unsigned char)((word) >> 16); \ hbuf[3] = (unsigned char)((word) >> 24); \ check = crc32(check, hbuf, 4); \ } while (0) #endif /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ hold = state->hold; \ bits = state->bits; \ } while (0) /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = next; \ strm->avail_in = have; \ state->hold = hold; \ state->bits = bits; \ } while (0) /* Clear the input bit accumulator */ #define INITBITS() \ do { \ hold = 0; \ bits = 0; \ } while (0) /* Get a byte of input into the bit accumulator, or return from inflate() if there is no input available. */ #define PULLBYTE() \ do { \ if (have == 0) goto inf_leave; \ have--; \ hold += (unsigned long)(*next++) << bits; \ bits += 8; \ } while (0) /* Assure that there are at least n bits in the bit accumulator. If there is not enough available input to do that, then return from inflate(). */ #define NEEDBITS(n) \ do { \ while (bits < (unsigned)(n)) \ PULLBYTE(); \ } while (0) /* Return the low n bits of the bit accumulator (n < 16) */ #define BITS(n) \ ((unsigned)hold & ((1U << (n)) - 1)) /* Remove n bits from the bit accumulator */ #define DROPBITS(n) \ do { \ hold >>= (n); \ bits -= (unsigned)(n); \ } while (0) /* Remove zero to seven bits as needed to go to a byte boundary */ #define BYTEBITS() \ do { \ hold >>= bits & 7; \ bits -= bits & 7; \ } while (0) /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is structured roughly as follows: for (;;) switch (state) { ... case STATEn: if (not enough input data or output space to make progress) return; ... make progress ... state = STATEm; break; ... } so when inflate() is called again, the same case is attempted again, and if the appropriate resources are provided, the machine proceeds to the next state. The NEEDBITS() macro is usually the way the state evaluates whether it can proceed or should return. NEEDBITS() does the return if the requested bits are not available. The typical use of the BITS macros is: NEEDBITS(n); ... do something with BITS(n) ... DROPBITS(n); where NEEDBITS(n) either returns from inflate() if there isn't enough input left to load n bits into the accumulator, or it continues. BITS(n) gives the low n bits in the accumulator. When done, DROPBITS(n) drops the low n bits off the accumulator. INITBITS() clears the accumulator and sets the number of available bits to zero. BYTEBITS() discards just enough bits to put the accumulator on a byte boundary. After BYTEBITS() and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return if there is no input available. The decoding of variable length codes uses PULLBYTE() directly in order to pull just enough bytes to decode the next code, and no more. Some states loop until they get enough input, making sure that enough state information is maintained to continue the loop where it left off if NEEDBITS() returns in the loop. For example, want, need, and keep would all have to actually be part of the saved state in case NEEDBITS() returns: case STATEw: while (want < need) { NEEDBITS(n); keep[want++] = BITS(n); DROPBITS(n); } state = STATEx; case STATEx: As shown above, if the next state is also the next case, then the break is omitted. A state may also return if there is not enough output space available to complete that state. Those states are copying stored data, writing a literal byte, and copying a matching string. When returning, a "goto inf_leave" is used to update the total counters, update the check value, and determine whether any progress has been made during that inflate() call in order to return the proper return code. Progress is defined as a change in either strm->avail_in or strm->avail_out. When there is a window, goto inf_leave will update the window with the last output written. If a goto inf_leave occurs in the middle of decompression and there is no window currently, goto inf_leave will create one and copy output to the window for the next call of inflate(). In this implementation, the flush parameter of inflate() only affects the return code (per zlib.h). inflate() always writes as much as possible to strm->next_out, given the space available and the provided input--the effect documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers the allocation of and copying into a sliding window until necessary, which provides the effect documented in zlib.h for Z_FINISH when the entire input stream available. So the only thing the flush parameter actually does is: when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ int inflate(z_streamp strm, int flush) { struct inflate_state *state; unsigned char *next; /* next input */ unsigned char *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ unsigned bits; /* bits in bit buffer */ unsigned in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ unsigned char *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ int ret; /* return code */ #ifdef GUNZIP unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ #endif static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ LOAD(); in = have; out = left; ret = Z_OK; for (;;) switch (state->mode) { case HEAD: if (state->wrap == 0) { state->mode = TYPEDO; break; } NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; break; } state->flags = 0; /* expect zlib header */ if (state->head != Z_NULL) state->head->done = -1; if (!(state->wrap & 1) || /* check if zlib header allowed */ #else if ( #endif ((BITS(8) << 8) + (hold >> 8)) % 31) { strm->msg = (char *)"incorrect header check"; state->mode = BAD; break; } if (BITS(4) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } DROPBITS(4); len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; else if (len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; } state->dmax = 1U << len; Tracev((stderr, "inflate: zlib header ok\n")); strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); break; #ifdef GUNZIP case FLAGS: NEEDBITS(16); state->flags = (int)(hold); if ((state->flags & 0xff) != Z_DEFLATED) { strm->msg = (char *)"unknown compression method"; state->mode = BAD; break; } if (state->flags & 0xe000) { strm->msg = (char *)"unknown header flags set"; state->mode = BAD; break; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; if (state->flags & 0x0200) CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: NEEDBITS(16); if (state->head != Z_NULL) { state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: if (state->flags & 0x0400) { NEEDBITS(16); state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; if (state->flags & 0x0200) CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) state->head->extra = Z_NULL; state->mode = EXTRA; case EXTRA: if (state->flags & 0x0400) { copy = state->length; if (copy > have) copy = have; if (copy) { if (state->head != Z_NULL && state->head->extra != Z_NULL) { len = state->head->extra_len - state->length; zmemcpy(state->head->extra + len, next, len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; state->length -= copy; } if (state->length) goto inf_leave; } state->length = 0; state->mode = NAME; case NAME: if (state->flags & 0x0800) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) state->head->name[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->name = Z_NULL; state->length = 0; state->mode = COMMENT; case COMMENT: if (state->flags & 0x1000) { if (have == 0) goto inf_leave; copy = 0; do { len = (unsigned)(next[copy++]); if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) state->head->comment[state->length++] = len; } while (len && copy < have); if (state->flags & 0x0200) state->check = crc32(state->check, next, copy); have -= copy; next += copy; if (len) goto inf_leave; } else if (state->head != Z_NULL) state->head->comment = Z_NULL; state->mode = HCRC; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); if (hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; } INITBITS(); } if (state->head != Z_NULL) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } strm->adler = state->check = crc32(0L, Z_NULL, 0); state->mode = TYPE; break; #endif case DICTID: NEEDBITS(32); strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; case DICT: if (state->havedict == 0) { RESTORE(); return Z_NEED_DICT; } strm->adler = state->check = adler32(0L, Z_NULL, 0); state->mode = TYPE; case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; case TYPEDO: if (state->last) { BYTEBITS(); state->mode = CHECK; break; } NEEDBITS(3); state->last = BITS(1); DROPBITS(1); switch (BITS(2)) { case 0: /* stored block */ Tracev((stderr, "inflate: stored block%s\n", state->last ? " (last)" : "")); state->mode = STORED; break; case 1: /* fixed block */ fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ if (flush == Z_TREES) { DROPBITS(2); goto inf_leave; } break; case 2: /* dynamic block */ Tracev((stderr, "inflate: dynamic codes block%s\n", state->last ? " (last)" : "")); state->mode = TABLE; break; case 3: strm->msg = (char *)"invalid block type"; state->mode = BAD; } DROPBITS(2); break; case STORED: BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { strm->msg = (char *)"invalid stored block lengths"; state->mode = BAD; break; } state->length = (unsigned)hold & 0xffff; Tracev((stderr, "inflate: stored length %u\n", state->length)); INITBITS(); state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; case COPY_: state->mode = COPY; case COPY: copy = state->length; if (copy) { if (copy > have) copy = have; if (copy > left) copy = left; if (copy == 0) goto inf_leave; zmemcpy(put, next, copy); have -= copy; next += copy; left -= copy; put += copy; state->length -= copy; break; } Tracev((stderr, "inflate: stored end\n")); state->mode = TYPE; break; case TABLE: NEEDBITS(14); state->nlen = BITS(5) + 257; DROPBITS(5); state->ndist = BITS(5) + 1; DROPBITS(5); state->ncode = BITS(4) + 4; DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { strm->msg = (char *)"too many length or distance symbols"; state->mode = BAD; break; } #endif Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; case LENLENS: while (state->have < state->ncode) { NEEDBITS(3); state->lens[order[state->have++]] = (unsigned short)BITS(3); DROPBITS(3); } while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; state->lencode = (code const *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid code lengths set"; state->mode = BAD; break; } Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; case CODELENS: while (state->have < state->nlen + state->ndist) { for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.val < 16) { DROPBITS(here.bits); state->lens[state->have++] = here.val; } else { if (here.val == 16) { NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } len = state->lens[state->have - 1]; copy = 3 + BITS(2); DROPBITS(2); } else if (here.val == 17) { NEEDBITS(here.bits + 3); DROPBITS(here.bits); len = 0; copy = 3 + BITS(3); DROPBITS(3); } else { NEEDBITS(here.bits + 7); DROPBITS(here.bits); len = 0; copy = 11 + BITS(7); DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { strm->msg = (char *)"invalid bit length repeat"; state->mode = BAD; break; } while (copy--) state->lens[state->have++] = (unsigned short)len; } } /* handle error breaks in while */ if (state->mode == BAD) break; /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { strm->msg = (char *)"invalid code -- missing end-of-block"; state->mode = BAD; break; } /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (code const *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { strm->msg = (char *)"invalid literal/lengths set"; state->mode = BAD; break; } state->distcode = (code const *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { strm->msg = (char *)"invalid distances set"; state->mode = BAD; break; } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; case LEN_: state->mode = LEN; case LEN: if (have >= 6 && left >= 258) { RESTORE(); inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; break; } state->back = 0; for (;;) { here = state->lencode[BITS(state->lenbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if (here.op && (here.op & 0xf0) == 0) { last = here; for (;;) { here = state->lencode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; state->length = (unsigned)here.val; if ((int)(here.op) == 0) { Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); state->mode = LIT; break; } if (here.op & 32) { Tracevv((stderr, "inflate: end of block\n")); state->back = -1; state->mode = TYPE; break; } if (here.op & 64) { strm->msg = (char *)"invalid literal/length code"; state->mode = BAD; break; } state->extra = (unsigned)(here.op) & 15; state->mode = LENEXT; case LENEXT: if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; case DIST: for (;;) { here = state->distcode[BITS(state->distbits)]; if ((unsigned)(here.bits) <= bits) break; PULLBYTE(); } if ((here.op & 0xf0) == 0) { last = here; for (;;) { here = state->distcode[last.val + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } DROPBITS(last.bits); state->back += last.bits; } DROPBITS(here.bits); state->back += here.bits; if (here.op & 64) { strm->msg = (char *)"invalid distance code"; state->mode = BAD; break; } state->offset = (unsigned)here.val; state->extra = (unsigned)(here.op) & 15; state->mode = DISTEXT; case DISTEXT: if (state->extra) { NEEDBITS(state->extra); state->offset += BITS(state->extra); DROPBITS(state->extra); state->back += state->extra; } #ifdef INFLATE_STRICT if (state->offset > state->dmax) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; case MATCH: if (left == 0) goto inf_leave; copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; if (copy > state->whave) { if (state->sane) { strm->msg = (char *)"invalid distance too far back"; state->mode = BAD; break; } #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; if (copy > state->length) copy = state->length; if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = 0; } while (--copy); if (state->length == 0) state->mode = LEN; break; #endif } if (copy > state->wnext) { copy -= state->wnext; from = state->window + (state->wsize - copy); } else from = state->window + (state->wnext - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ from = put - state->offset; copy = state->length; } if (copy > left) copy = left; left -= copy; state->length -= copy; do { *put++ = *from++; } while (--copy); if (state->length == 0) state->mode = LEN; break; case LIT: if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); left--; state->mode = LEN; break; case CHECK: if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; if (out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; if (( #ifdef GUNZIP state->flags ? hold : #endif ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: check matches trailer\n")); } #ifdef GUNZIP state->mode = LENGTH; case LENGTH: if (state->wrap && state->flags) { NEEDBITS(32); if (hold != (state->total & 0xffffffffUL)) { strm->msg = (char *)"incorrect length check"; state->mode = BAD; break; } INITBITS(); Tracev((stderr, "inflate: length matches trailer\n")); } #endif state->mode = DONE; case DONE: ret = Z_STREAM_END; goto inf_leave; case BAD: ret = Z_DATA_ERROR; goto inf_leave; case MEM: return Z_MEM_ERROR; case SYNC: default: return Z_STREAM_ERROR; } /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); if (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH))) if (updatewindow(strm, out)) { state->mode = MEM; return Z_MEM_ERROR; } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; if (state->wrap && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); strm->data_type = state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) ret = Z_BUF_ERROR; return ret; } int inflateEnd(z_streamp strm) { struct inflate_state *state; if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); ZFREE(strm, strm->state); strm->state = Z_NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; } int inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) { struct inflate_state *state; unsigned long dictid; unsigned char *next; unsigned avail; int ret; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; /* check for correct dictionary identifier */ if (state->mode == DICT) { dictid = adler32(0L, Z_NULL, 0); dictid = adler32(dictid, dictionary, dictLength); if (dictid != state->check) return Z_DATA_ERROR; } /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ next = strm->next_out; avail = strm->avail_out; strm->next_out = (Bytef *)dictionary + dictLength; strm->avail_out = 0; ret = updatewindow(strm, dictLength); strm->avail_out = avail; strm->next_out = next; if (ret) { state->mode = MEM; return Z_MEM_ERROR; } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; } int inflateGetHeader(z_streamp strm, gz_headerp head) { struct inflate_state *state; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; /* save header structure */ state->head = head; head->done = 0; return Z_OK; } /* Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found or when out of input. When called, *have is the number of pattern bytes found in order so far, in 0..3. On return *have is updated to the new state. If on return *have equals four, then the pattern was found and the return value is how many bytes were read including the last byte of the pattern. If *have is less than four, then the pattern has not been found yet and the return value is len. In the latter case, syncsearch() can be called again with more data and the *have state. *have is initialized to zero for the first call. */ static unsigned syncsearch(unsigned *have, unsigned char *buf, unsigned len) { unsigned got; unsigned next; got = *have; next = 0; while (next < len && got < 4) { if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) got++; else if (buf[next]) got = 0; else got = 4 - got; next++; } *have = got; return next; } int inflateSync(z_streamp strm) { unsigned len; /* number of bytes to look at or looked at */ unsigned long in, out; /* temporary to save total_in and total_out */ unsigned char buf[4]; /* to restore bit buffer to byte string */ struct inflate_state *state; /* check parameters */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; /* if first time, start search in bit buffer */ if (state->mode != SYNC) { state->mode = SYNC; state->hold <<= state->bits & 7; state->bits -= state->bits & 7; len = 0; while (state->bits >= 8) { buf[len++] = (unsigned char)(state->hold); state->hold >>= 8; state->bits -= 8; } state->have = 0; syncsearch(&(state->have), buf, len); } /* search available input */ len = syncsearch(&(state->have), strm->next_in, strm->avail_in); strm->avail_in -= len; strm->next_in += len; strm->total_in += len; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; state->mode = TYPE; return Z_OK; } /* Returns true if inflate is currently at the end of a block generated by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored block. When decompressing, PPP checks that at the end of input packet, inflate is waiting for these length bytes. */ int inflateSyncPoint(z_streamp strm) { struct inflate_state *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; return state->mode == STORED && state->bits == 0; } int inflateCopy(z_streamp dest, z_streamp source) { struct inflate_state *state; struct inflate_state *copy; unsigned char *window; unsigned wsize; /* check input */ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) return Z_STREAM_ERROR; state = (struct inflate_state *)source->state; /* allocate space */ copy = (struct inflate_state *) ZALLOC(source, 1, sizeof(struct inflate_state)); if (copy == Z_NULL) return Z_MEM_ERROR; window = Z_NULL; if (state->window != Z_NULL) { window = (unsigned char *) ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); if (window == Z_NULL) { ZFREE(source, copy); return Z_MEM_ERROR; } } /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); if (window != Z_NULL) { wsize = 1U << state->wbits; zmemcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state *)copy; return Z_OK; } int inflateUndermine(z_streamp strm, int subvert) { struct inflate_state *state; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR return Z_OK; #else state->sane = 1; return Z_DATA_ERROR; #endif } long inflateMark(z_streamp strm) { struct inflate_state *state; if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; state = (struct inflate_state *)strm->state; return ((long)(state->back) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } /* eof */ glpk-4.52.1/src/zlib/inflate.h0000644000062000006210000001461412175147600015251 0ustar maomkpasswd/* inflate.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* inflate.h -- internal inflate state definition * Copyright (C) 1995-2009 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ #ifndef NO_GZIP # define GUNZIP #endif /* Possible inflate modes between inflate() calls */ typedef enum { HEAD, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ EXLEN, /* i: waiting for extra length (gzip) */ EXTRA, /* i: waiting for extra bytes (gzip) */ NAME, /* i: waiting for end of file name (gzip) */ COMMENT, /* i: waiting for end of comment (gzip) */ HCRC, /* i: waiting for header crc (gzip) */ DICTID, /* i: waiting for dictionary check value */ DICT, /* waiting for inflateSetDictionary() call */ TYPE, /* i: waiting for type bits, including last-flag bit */ TYPEDO, /* i: same, but skip check to exit inflate on new block */ STORED, /* i: waiting for stored size (length and complement) */ COPY_, /* i/o: same as COPY below, but only first time in */ COPY, /* i/o: waiting for input or output to copy stored block */ TABLE, /* i: waiting for dynamic block table lengths */ LENLENS, /* i: waiting for code length code lengths */ CODELENS, /* i: waiting for length/lit and distance code lengths */ LEN_, /* i: same as LEN below, but only first time in */ LEN, /* i: waiting for length/lit/eob code */ LENEXT, /* i: waiting for length extra bits */ DIST, /* i: waiting for distance code */ DISTEXT, /* i: waiting for distance extra bits */ MATCH, /* o: waiting for output space to copy string */ LIT, /* o: waiting for output space to write literal */ CHECK, /* i: waiting for 32-bit check value */ LENGTH, /* i: waiting for 32-bit length (gzip) */ DONE, /* finished check, done -- remain here until reset */ BAD, /* got a data error -- remain here until reset */ MEM, /* got an inflate() memory error -- remain here until reset */ SYNC /* looking for synchronization bytes to restart inflate() */ } inflate_mode; /* State transitions between above modes - (most modes can go to BAD or MEM on error -- not shown for clarity) Process header: HEAD -> (gzip) or (zlib) or (raw) (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> HCRC -> TYPE (zlib) -> DICTID or TYPE DICTID -> DICT -> TYPE (raw) -> TYPEDO Read deflate blocks: TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK STORED -> COPY_ -> COPY -> TYPE TABLE -> LENLENS -> CODELENS -> LEN_ LEN_ -> LEN Read deflate codes in fixed or dynamic block: LEN -> LENEXT or LIT or TYPE LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LIT -> LEN Process trailer: CHECK -> LENGTH -> DONE */ /* state maintained between inflate() calls. Approximately 10K bytes. */ struct inflate_state { inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned long check; /* protected copy of check value */ unsigned long total; /* protected copy of output count */ gz_headerp head; /* where to save gzip header information */ /* sliding window */ unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ unsigned wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ /* for string and stored block copying */ unsigned length; /* literal or length of data to copy */ unsigned offset; /* distance back to copy string from */ /* for table and code decoding */ unsigned extra; /* extra bits needed */ /* fixed and dynamic code tables */ code const *lencode; /* starting table for length/literal codes */ code const *distcode; /* starting table for distance codes */ unsigned lenbits; /* index bits for lencode */ unsigned distbits; /* index bits for distcode */ /* dynamic table building */ unsigned ncode; /* number of code length code lengths */ unsigned nlen; /* number of length code lengths */ unsigned ndist; /* number of distance code lengths */ unsigned have; /* number of code lengths in lens[] */ code *next; /* next available space in codes[] */ unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short work[288]; /* work area for code table building */ code codes[ENOUGH]; /* space for code tables */ int sane; /* if false, allow invalid distance too far */ int back; /* bits back of last unprocessed length/lit */ unsigned was; /* initial length of match */ }; /* eof */ glpk-4.52.1/src/zlib/inftrees.c0000644000062000006210000003161012175147600015434 0ustar maomkpasswd/* inftrees.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* inftrees.c -- generate Huffman trees for efficient decoding * Copyright (C) 1995-2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #include "inftrees.h" #define MAXBITS 15 const char inflate_copyright[] = " inflate 1.2.7 Copyright 1995-2012 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot include such an acknowledgment, I would appreciate that you keep this copyright string in the executable of your product. */ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, CODES, LENS, or DISTS. On return, zero is success, -1 is an invalid code, and +1 means that ENOUGH isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ int inflate_table(codetype type, unsigned short *lens, unsigned codes, code **table, unsigned *bits, unsigned short *work) { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ unsigned min, max; /* minimum and maximum code lengths */ unsigned root; /* number of index bits for root table */ unsigned curr; /* number of index bits for current table */ unsigned drop; /* code bits to drop for sub-table */ int left; /* number of prefix codes available */ unsigned used; /* code entries in table used */ unsigned huff; /* Huffman code */ unsigned incr; /* for incrementing code, index */ unsigned fill; /* index for replicating entries */ unsigned low; /* low bits for current root entry */ unsigned mask; /* mask for low root bits */ code here; /* table entry for duplication */ code *next; /* next available space in table */ const unsigned short *base; /* base value table to use */ const unsigned short *extra; /* extra bits table to use */ int end; /* use base and extra for symbol > end */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 78, 68}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..MAXBITS. The caller must assure this. 1..MAXBITS is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ for (len = 0; len <= MAXBITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (unsigned short)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return 0; /* no symbols, but wait for decoding to report error */ } for (min = 1; min < max; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= MAXBITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ } if (left > 0 && (type == CODES || max != 1)) return -1; /* incomplete set */ /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for LENS and DIST tables against the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in the initial root table size constants. See the comments in inftrees.h for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case CODES: base = extra = work; /* dummy value--not used */ end = 19; break; case LENS: base = lbase; base -= 257; extra = lext; extra -= 257; end = 256; break; default: /* DISTS */ base = dbase; extra = dext; end = -1; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ /* check available table space */ if ((type == LENS && used >= ENOUGH_LENS) || (type == DISTS && used >= ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); if ((int)(work[sym]) < end) { here.op = (unsigned char)0; here.val = work[sym]; } else if ((int)(work[sym]) > end) { here.op = (unsigned char)(extra[work[sym]]); here.val = base[work[sym]]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == LENS && used >= ENOUGH_LENS) || (type == DISTS && used >= ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (unsigned char)curr; (*table)[low].bits = (unsigned char)root; (*table)[low].val = (unsigned short)(next - *table); } } /* fill in remaining table entry if code is incomplete (guaranteed to have at most one remaining entry, since if the code is incomplete, the maximum code length that was allowed to get this far is one bit) */ if (huff != 0) { here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (unsigned short)0; next[huff] = here; } /* set return parameters */ *table += used; *bits = root; return 0; } /* eof */ glpk-4.52.1/src/zlib/inftrees.h0000644000062000006210000000570112175147600015443 0ustar maomkpasswd/* inftrees.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* inftrees.h -- header to use inftrees.c * Copyright (C) 1995-2005, 2010 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. */ typedef struct { unsigned char op; /* operation, extra bits, table bits */ unsigned char bits; /* bits in this part of the code */ unsigned short val; /* offset in table or code value */ } code; /* op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ #define ENOUGH_LENS 852 #define ENOUGH_DISTS 592 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) /* Type of code to build for inflate_table() */ typedef enum { CODES, LENS, DISTS } codetype; int inflate_table(codetype type, unsigned short *lens, unsigned codes, code **table, unsigned *bits, unsigned short *work); /* eof */ glpk-4.52.1/src/zlib/README0000644000062000006210000000254712175147600014340 0ustar maomkpasswdNOTE: Files in this subdirectory are NOT part of the GLPK package, but are used with GLPK. The original code was modified according to GLPK requirements by Andrew Makhorin . The following files were added: zio.h, zio.c, zsymb.h. ************************************************************************ zlib general purpose compression library version 1.2.7, May 2nd, 2012 Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu glpk-4.52.1/src/zlib/trees.c0000644000062000006210000012554612175147600014753 0ustar maomkpasswd/* trees.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* trees.c -- output deflated data using Huffman coding * Copyright (C) 1995-2012 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ /* * ALGORITHM * * The "deflation" process uses several Huffman trees. The more * common source values are represented by shorter bit sequences. * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * REFERENCES * * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc * * Storer, James A. * Data Compression: Methods and Theory, pp. 49-50. * Computer Science Press, 1988. ISBN 0-7167-8156-5. * * Sedgewick, R. * Algorithms, p290. * Addison-Wesley, 1983. ISBN 0-201-06672-6. */ #include "deflate.h" #ifdef DEBUG # include #endif /* =========================================================================== * Constants */ #define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS bits */ #define END_BLOCK 256 /* end of block literal code */ #define REP_3_6 16 /* repeat previous bit length 3-6 times (2 bits of repeat count) */ #define REPZ_3_10 17 /* repeat a zero length 3-10 times (3 bits of repeat count) */ #define REPZ_11_138 18 /* repeat a zero length 11-138 times (7 bits of repeat count) */ static const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; static const int extra_dbits[D_CODES] /* extra bits for each distance code */ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; static const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; static const uch bl_order[BL_CODES] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; /* The lengths of the bit length codes are sent in order of decreasing * probability, to avoid transmitting the lengths for unused bit length codes. */ /* =========================================================================== * Local data. These are initialized only once. */ #define DIST_CODE_LEN 512 /* see definition of array dist_code below */ #if defined(GEN_TREES_H) static ct_data static_ltree[L_CODES+2]; /* The static literal tree. Since the bit lengths are imposed, there is no * need for the L_CODES extra codes used during heap construction. However * The codes 286 and 287 are needed to build a canonical tree (see _tr_init * below). */ static ct_data static_dtree[D_CODES]; /* The static distance tree. (Actually a trivial tree since all codes use * 5 bits.) */ uch _dist_code[DIST_CODE_LEN]; /* Distance codes. The first 256 values correspond to the distances * 3 .. 258, the last 256 values correspond to the top 8 bits of * the 15 bit distances. */ uch _length_code[MAX_MATCH-MIN_MATCH+1]; /* length code for each normalized match length (0 == MIN_MATCH) */ static int base_length[LENGTH_CODES]; /* First normalized length for each code (0 = MIN_MATCH) */ static int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ #else # include "trees.h" #endif /* GEN_TREES_H */ struct static_tree_desc_s { const ct_data *static_tree; /* static tree or NULL */ const intf *extra_bits; /* extra bits for each code or NULL */ int extra_base; /* base index for extra_bits */ int elems; /* max number of elements in the tree */ int max_length; /* max bit length for the codes */ }; static static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; static static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; static static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== * Local (static) routines in this file. */ static void tr_static_init (void); static void init_block (deflate_state *s); static void pqdownheap (deflate_state *s, ct_data *tree, int k); static void gen_bitlen (deflate_state *s, tree_desc *desc); static void gen_codes (ct_data *tree, int max_code, ushf *bl_count); static void build_tree (deflate_state *s, tree_desc *desc); static void scan_tree (deflate_state *s, ct_data *tree, int max_code); static void send_tree (deflate_state *s, ct_data *tree, int max_code); static int build_bl_tree (deflate_state *s); static void send_all_trees (deflate_state *s, int lcodes, int dcodes, int blcodes); static void compress_block (deflate_state *s, ct_data *ltree, ct_data *dtree); static int detect_data_type (deflate_state *s); static unsigned bi_reverse (unsigned value, int length); static void bi_windup (deflate_state *s); static void bi_flush (deflate_state *s); static void copy_block (deflate_state *s, charf *buf, unsigned len, int header); #ifdef GEN_TREES_H static void gen_trees_header (void); #endif #ifndef DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ #else /* DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } #endif /* =========================================================================== * Output a short LSB first on the stream. * IN assertion: there is enough room in pendingBuf. */ #define put_short(s, w) { \ put_byte(s, (uch)((w) & 0xff)); \ put_byte(s, (uch)((ush)(w) >> 8)); \ } /* =========================================================================== * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ #ifdef DEBUG static void send_bits(deflate_state *s, int value, int length); static void send_bits(deflate_state *s, int value, int length) /* value = value to send */ /* length = number of bits */ { Tracevv((stderr," l %2d v %4x ", length, value)); Assert(length > 0 && length <= 15, "invalid length"); s->bits_sent += (ulg)length; /* If not enough room in bi_buf, use (valid) bits from bi_buf and * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * unused bits in value. */ if (s->bi_valid > (int)Buf_size - length) { s->bi_buf |= (ush)value << s->bi_valid; put_short(s, s->bi_buf); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_valid += length - Buf_size; } else { s->bi_buf |= (ush)value << s->bi_valid; s->bi_valid += length; } } #else /* !DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ int val = value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_valid += len - Buf_size;\ } else {\ s->bi_buf |= (ush)(value) << s->bi_valid;\ s->bi_valid += len;\ }\ } #endif /* DEBUG */ /* the arguments must not have side effects */ /* =========================================================================== * Initialize the various 'constant' tables. */ static void tr_static_init(void) { #if defined(GEN_TREES_H) static int static_init_done = 0; int n; /* iterates over tree elements */ int bits; /* bit counter */ int length; /* length value */ int code; /* code value */ int dist; /* distance index */ ush bl_count[MAX_BITS+1]; /* number of codes at each bit length for an optimal tree */ if (static_init_done) return; /* For some embedded targets, global variables are not initialized: */ #ifdef NO_INIT_GLOBAL_POINTERS static_l_desc.static_tree = static_ltree; static_l_desc.extra_bits = extra_lbits; static_d_desc.static_tree = static_dtree; static_d_desc.extra_bits = extra_dbits; static_bl_desc.extra_bits = extra_blbits; #endif /* Initialize the mapping length (0..255) -> length code (0..28) */ length = 0; for (code = 0; code < LENGTH_CODES-1; code++) { base_length[code] = length; for (n = 0; n < (1< dist code (0..29) */ dist = 0; for (code = 0 ; code < 16; code++) { base_dist[code] = dist; for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ for ( ; code < D_CODES; code++) { base_dist[code] = dist << 7; for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { _dist_code[256 + dist++] = (uch)code; } } Assert (dist == 256, "tr_static_init: 256+dist != 512"); /* Construct the codes of the static literal tree */ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; n = 0; while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; /* Codes 286 and 287 do not exist, but we must include them in the * tree construction to get a canonical Huffman tree (longest code * all ones) */ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; static_dtree[n].Code = bi_reverse((unsigned)n, 5); } static_init_done = 1; # ifdef GEN_TREES_H gen_trees_header(); # endif #endif /* defined(GEN_TREES_H) */ } #ifdef GEN_TREES_H /* by mao */ void maketrees(void) { tr_static_init(); return; } #endif /* =========================================================================== * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H # ifndef DEBUG # include # endif # define SEPARATOR(i, last, width) \ ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width)-1 ? ",\n" : ", ")) void gen_trees_header(void) { FILE *header = fopen("trees.h", "w"); int i; Assert (header != NULL, "Can't open trees.h"); fprintf(header, "/* header created automatically with -DGEN_TREES_H */\n\n"); fprintf(header, "static const ct_data static_ltree[L_CODES+2] = {\n"); for (i = 0; i < L_CODES+2; i++) { fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); } fprintf(header, "static const ct_data static_dtree[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); } fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); for (i = 0; i < DIST_CODE_LEN; i++) { fprintf(header, "%2u%s", _dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { fprintf(header, "%2u%s", _length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); } fprintf(header, "static const int base_length[LENGTH_CODES] = {\n"); for (i = 0; i < LENGTH_CODES; i++) { fprintf(header, "%1u%s", base_length[i], SEPARATOR(i, LENGTH_CODES-1, 20)); } fprintf(header, "static const int base_dist[D_CODES] = {\n"); for (i = 0; i < D_CODES; i++) { fprintf(header, "%5u%s", base_dist[i], SEPARATOR(i, D_CODES-1, 10)); } fclose(header); } #endif /* GEN_TREES_H */ /* =========================================================================== * Initialize the tree data structures for a new zlib stream. */ void _tr_init(deflate_state *s) { tr_static_init(); s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.stat_desc = &static_l_desc; s->d_desc.dyn_tree = s->dyn_dtree; s->d_desc.stat_desc = &static_d_desc; s->bl_desc.dyn_tree = s->bl_tree; s->bl_desc.stat_desc = &static_bl_desc; s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif /* Initialize the first block of the first file: */ init_block(s); } /* =========================================================================== * Initialize a new block. */ static void init_block(deflate_state *s) { int n; /* iterates over tree elements */ /* Initialize the trees. */ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; s->dyn_ltree[END_BLOCK].Freq = 1; s->opt_len = s->static_len = 0L; s->last_lit = s->matches = 0; } #define SMALLEST 1 /* Index within the heap array of least frequent node in the Huffman tree */ /* =========================================================================== * Remove the smallest element from the heap and recreate the heap with * one less element. Updates heap and heap_len. */ #define pqremove(s, tree, top) \ {\ top = s->heap[SMALLEST]; \ s->heap[SMALLEST] = s->heap[s->heap_len--]; \ pqdownheap(s, tree, SMALLEST); \ } /* =========================================================================== * Compares to subtrees, using the tree depth as tie breaker when * the subtrees have equal frequency. This minimizes the worst case length. */ #define smaller(tree, n, m, depth) \ (tree[n].Freq < tree[m].Freq || \ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) /* =========================================================================== * Restore the heap property by moving down the tree starting at node k, * exchanging a node with the smallest of its two sons if necessary, stopping * when the heap property is re-established (each father smaller than its * two sons). */ static void pqdownheap(deflate_state *s, ct_data *tree, int k) /* tree = the tree to restore */ /* k = node to move down */ { int v = s->heap[k]; int j = k << 1; /* left son of k */ while (j <= s->heap_len) { /* Set j to the smallest of the two sons: */ if (j < s->heap_len && smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { j++; } /* Exit if v is smaller than both sons */ if (smaller(tree, v, s->heap[j], s->depth)) break; /* Exchange v with the smallest son */ s->heap[k] = s->heap[j]; k = j; /* And continue down the tree, setting j to the left son of k */ j <<= 1; } s->heap[k] = v; } /* =========================================================================== * Compute the optimal bit lengths for a tree and update the total bit length * for the current block. * IN assertion: the fields freq and dad are set, heap[heap_max] and * above are the tree nodes sorted by increasing frequency. * OUT assertions: the field len is set to the optimal bit length, the * array bl_count contains the frequencies for each bit length. * The length opt_len is updated; static_len is also updated if stree is * not null. */ static void gen_bitlen(deflate_state *s, tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; const ct_data *stree = desc->stat_desc->static_tree; const intf *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; /* heap index */ int n, m; /* iterate over the tree elements */ int bits; /* bit length */ int xbits; /* extra bits */ ush f; /* frequency */ int overflow = 0; /* number of elements with bit length too large */ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ for (h = s->heap_max+1; h < HEAP_SIZE; h++) { n = s->heap[h]; bits = tree[tree[n].Dad].Len + 1; if (bits > max_length) bits = max_length, overflow++; tree[n].Len = (ush)bits; /* We overwrite tree[n].Dad which is no longer needed */ if (n > max_code) continue; /* not a leaf node */ s->bl_count[bits]++; xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; s->opt_len += (ulg)f * (bits + xbits); if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); } if (overflow == 0) return; Trace((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ do { bits = max_length-1; while (s->bl_count[bits] == 0) bits--; s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ s->bl_count[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while (overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for (bits = max_length; bits != 0; bits--) { n = s->bl_count[bits]; while (n != 0) { m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); s->opt_len += ((long)bits - (long)tree[m].Len) *(long)tree[m].Freq; tree[m].Len = (ush)bits; } n--; } } } /* =========================================================================== * Generate the codes for a given tree and bit counts (which need not be * optimal). * IN assertion: the array bl_count contains the bit length statistics for * the given tree and the field len is set for all tree elements. * OUT assertion: the field code is set for all tree elements of non * zero code length. */ static void gen_codes(ct_data *tree, int max_code, ushf *bl_count) /* tree = the tree to decorate */ /* max_code = largest code with non zero frequency */ /* bl_count = number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ush code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ /* The distribution counts are first used to generate the code values * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { next_code[bits] = code = (code + bl_count[bits-1]) << 1; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; const ct_data *stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; /* iterate over heap elements */ int max_code = -1; /* largest code with non zero frequency */ int node; /* new node being created */ /* Construct the initial heap, with least frequent element in * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ s->heap_len = 0, s->heap_max = HEAP_SIZE; for (n = 0; n < elems; n++) { if (tree[n].Freq != 0) { s->heap[++(s->heap_len)] = max_code = n; s->depth[n] = 0; } else { tree[n].Len = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while (s->heap_len < 2) { node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); tree[node].Freq = 1; s->depth[node] = 0; s->opt_len--; if (stree) s->static_len -= stree[node].Len; /* node is 0 or 1 so it does not have extra bits */ } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(s, tree, n); /* n = node of least frequency */ m = s->heap[SMALLEST]; /* m = node of next least frequency */ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ s->heap[--(s->heap_max)] = m; /* Create a new node father of n and m */ tree[node].Freq = tree[n].Freq + tree[m].Freq; s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? s->depth[n] : s->depth[m]) + 1); tree[n].Dad = tree[m].Dad = (ush)node; #ifdef DUMP_BL_TREE if (tree == s->bl_tree) { fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); } #endif /* and insert the new node in the heap */ s->heap[SMALLEST] = node++; pqdownheap(s, tree, SMALLEST); } while (s->heap_len >= 2); s->heap[--(s->heap_max)] = s->heap[SMALLEST]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen(s, (tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes ((ct_data *)tree, max_code, s->bl_count); } /* =========================================================================== * Scan a literal or distance tree to determine the frequencies of the codes * in the bit length tree. */ static void scan_tree(deflate_state *s, ct_data *tree, int max_code) /* tree = the tree to be scanned */ /* max_code = and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ if (nextlen == 0) max_count = 138, min_count = 3; tree[max_code+1].Len = (ush)0xffff; /* guard */ for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { s->bl_tree[curlen].Freq += count; } else if (curlen != 0) { if (curlen != prevlen) s->bl_tree[curlen].Freq++; s->bl_tree[REP_3_6].Freq++; } else if (count <= 10) { s->bl_tree[REPZ_3_10].Freq++; } else { s->bl_tree[REPZ_11_138].Freq++; } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Send a literal or distance tree in compressed form, using the codes in * bl_tree. */ static void send_tree(deflate_state *s, ct_data *tree, int max_code) /* tree = the tree to be scanned */ /* max_code = and its largest code of non zero frequency */ { int n; /* iterates over all tree elements */ int prevlen = -1; /* last emitted length */ int curlen; /* length of current code */ int nextlen = tree[0].Len; /* length of next code */ int count = 0; /* repeat count of the current code */ int max_count = 7; /* max repeat count */ int min_count = 4; /* min repeat count */ /* tree[max_code+1].Len = -1; */ /* guard already set */ if (nextlen == 0) max_count = 138, min_count = 3; for (n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].Len; if (++count < max_count && curlen == nextlen) { continue; } else if (count < min_count) { do { send_code(s, curlen, s->bl_tree); } while (--count != 0); } else if (curlen != 0) { if (curlen != prevlen) { send_code(s, curlen, s->bl_tree); count--; } Assert(count >= 3 && count <= 6, " 3_6?"); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); } else if (count <= 10) { send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); } else { send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); } count = 0; prevlen = curlen; if (nextlen == 0) { max_count = 138, min_count = 3; } else if (curlen == nextlen) { max_count = 6, min_count = 3; } else { max_count = 7, min_count = 4; } } } /* =========================================================================== * Construct the Huffman tree for the bit lengths and return the index in * bl_order of the last bit length code to send. */ static int build_bl_tree(deflate_state *s) { int max_blindex; /* index of last bit length code of non zero freq */ /* Determine the bit length frequencies for literal and distance trees */ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); /* Build the bit length tree: */ build_tree(s, (tree_desc *)(&(s->bl_desc))); /* opt_len now includes the length of the tree representations, except * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ s->opt_len += 3*(max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); return max_blindex; } /* =========================================================================== * Send the header for a block using dynamic Huffman trees: the counts, the * lengths of the bit length codes, the literal tree and the distance tree. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ static void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) /* lcodes, dcodes, blcodes = number of codes for each tree */ { int rank; /* index in bl_order */ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, "too many codes"); Tracev((stderr, "\nbl counts: ")); send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, dcodes-1, 5); send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ for (rank = 0; rank < blcodes; rank++) { Tracev((stderr, "\nbl code %2d ", bl_order[rank])); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); } Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); } /* =========================================================================== * Send a stored block */ void _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int last) /* buf = input block */ /* stored_len = length of input block */ /* last = one if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ #ifdef DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; #endif copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) */ void _tr_flush_bits(deflate_state *s) { bi_flush(s); } /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. */ void _tr_align(deflate_state *s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); #ifdef DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); } /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static * trees or store, and output the encoded block to the zip file. */ void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int last) /* buf = input block, or NULL if too old */ /* stored_len = length of input block */ /* last = one if this is the last block for a file */ { ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ int max_blindex = 0; /* index of last bit length code of non zero freq */ /* Build the Huffman trees unless a stored block is forced */ if (s->level > 0) { /* Check if the file is binary or text */ if (s->strm->data_type == Z_UNKNOWN) s->strm->data_type = detect_data_type(s); /* Construct the literal and distance trees */ build_tree(s, (tree_desc *)(&(s->l_desc))); Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, s->static_len)); build_tree(s, (tree_desc *)(&(s->d_desc))); Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, s->static_len)); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(s); /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (s->opt_len+3+7)>>3; static_lenb = (s->static_len+3+7)>>3; Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->last_lit)); if (static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { Assert(buf != (char*)0, "lost buf"); opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ } #ifdef FORCE_STORED if (buf != (char*)0) { /* force stored block */ #else if (stored_len+4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ _tr_stored_block(s, buf, stored_len, last); #ifdef FORCE_STATIC } else if (static_lenb >= 0) { /* force static trees */ #else } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+last, 3); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif } else { send_bits(s, (DYN_TREES<<1)+last, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif } Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. */ init_block(s); if (last) { bi_windup(s); #ifdef DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, s->compressed_len-7*last)); } /* =========================================================================== * Save the match info and tally the frequency counts. Return true if * the current block must be flushed. */ int _tr_tally(deflate_state *s, unsigned dist, unsigned lc) /* dist = distance of matched string */ /* lc = match length-MIN_MATCH or unmatched char (if dist==0) */ { s->d_buf[s->last_lit] = (ush)dist; s->l_buf[s->last_lit++] = (uch)lc; if (dist == 0) { /* lc is the unmatched char */ s->dyn_ltree[lc].Freq++; } else { s->matches++; /* Here, lc is the match length - MIN_MATCH */ dist--; /* dist = match distance - 1 */ Assert((ush)dist < (ush)MAX_DIST(s) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_dtree[d_code(dist)].Freq++; } #ifdef TRUNCATE_BLOCK /* Try to guess if it is profitable to stop the current block here */ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { /* Compute an upper bound for the compressed length */ ulg out_length = (ulg)s->last_lit*8L; ulg in_length = (ulg)((long)s->strstart - s->block_start); int dcode; for (dcode = 0; dcode < D_CODES; dcode++) { out_length += (ulg)s->dyn_dtree[dcode].Freq * (5L+extra_dbits[dcode]); } out_length >>= 3; Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", s->last_lit, in_length, out_length, 100L - out_length*100L/in_length)); if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; } #endif return (s->last_lit == s->lit_bufsize-1); /* We avoid equality with lit_bufsize because of wraparound at 64K * on 16 bit machines and because stored blocks are restricted to * 64K-1 bytes. */ } /* =========================================================================== * Send the block data compressed using the given Huffman trees */ static void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree) /* ltree = literal tree */ /* dtree = distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if (s->last_lit != 0) do { dist = s->d_buf[lx]; lc = s->l_buf[lx++]; if (dist == 0) { send_code(s, lc, ltree); /* send a literal byte */ Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ code = _length_code[lc]; send_code(s, code+LITERALS+1, ltree); /* send the length code */ extra = extra_lbits[code]; if (extra != 0) { lc -= base_length[code]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); Assert (code < D_CODES, "bad d_code"); send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { dist -= base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, "pendingBuf overflow"); } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); } /* =========================================================================== * Check if the data type is TEXT or BINARY, using the following algorithm: * - TEXT if the two conditions below are satisfied: * a) There are no non-portable control characters belonging to the * "black list" (0..6, 14..25, 28..31). * b) There is at least one printable character belonging to the * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). * - BINARY otherwise. * - The following partially-portable control characters form a * "gray list" that is ignored in this detection algorithm: * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). * IN assertion: the fields Freq of dyn_ltree are set. */ static int detect_data_type(deflate_state *s) { /* black_mask is the bit mask of black-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ unsigned long black_mask = 0xf3ffc07fUL; int n; /* Check for non-textual ("black-listed") bytes. */ for (n = 0; n <= 31; n++, black_mask >>= 1) if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) return Z_BINARY; /* Check for textual ("white-listed") bytes. */ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 || s->dyn_ltree[13].Freq != 0) return Z_TEXT; for (n = 32; n < LITERALS; n++) if (s->dyn_ltree[n].Freq != 0) return Z_TEXT; /* There are no "black-listed" or "white-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return Z_BINARY; } /* =========================================================================== * Reverse the first len bits of a code, using straightforward code (a faster * method would use a table) * IN assertion: 1 <= len <= 15 */ static unsigned bi_reverse(unsigned code, int len) /* code = the value to invert */ /* len = its bit length */ { register unsigned res = 0; do { res |= code & 1; code >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } /* =========================================================================== * Flush the bit buffer, keeping at most 7 bits in it. */ static void bi_flush(deflate_state *s) { if (s->bi_valid == 16) { put_short(s, s->bi_buf); s->bi_buf = 0; s->bi_valid = 0; } else if (s->bi_valid >= 8) { put_byte(s, (Byte)s->bi_buf); s->bi_buf >>= 8; s->bi_valid -= 8; } } /* =========================================================================== * Flush the bit buffer and align the output on a byte boundary */ static void bi_windup(deflate_state *s) { if (s->bi_valid > 8) { put_short(s, s->bi_buf); } else if (s->bi_valid > 0) { put_byte(s, (Byte)s->bi_buf); } s->bi_buf = 0; s->bi_valid = 0; #ifdef DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } /* =========================================================================== * Copy a stored block, storing first the length and its * one's complement if requested. */ static void copy_block(deflate_state *s, charf *buf, unsigned len, int header) /* buf = the input data */ /* len = its length */ /* header = true if block header must be written */ { bi_windup(s); /* align on byte boundary */ if (header) { put_short(s, (ush)len); put_short(s, (ush)~len); #ifdef DEBUG s->bits_sent += 2*16; #endif } #ifdef DEBUG s->bits_sent += (ulg)len<<3; #endif while (len--) { put_byte(s, *buf++); } } /* eof */ glpk-4.52.1/src/zlib/trees.h0000644000062000006210000002040012175147600014737 0ustar maomkpasswd/* header created automatically with -DGEN_TREES_H */ static const ct_data static_ltree[L_CODES+2] = { {{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, {{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, {{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, {{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, {{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, {{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, {{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, {{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, {{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, {{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, {{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, {{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, {{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, {{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, {{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, {{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, {{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, {{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, {{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, {{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, {{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, {{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, {{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, {{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, {{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, {{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, {{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, {{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, {{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, {{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, {{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, {{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, {{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, {{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, {{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, {{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, {{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, {{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, {{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, {{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, {{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, {{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, {{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, {{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, {{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, {{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, {{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, {{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, {{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, {{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, {{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, {{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, {{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, {{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, {{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, {{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, {{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, {{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} }; static const ct_data static_dtree[D_CODES] = { {{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, {{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, {{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, {{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, {{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} }; const uch _dist_code[DIST_CODE_LEN] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 }; static const int base_length[LENGTH_CODES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 }; static const int base_dist[D_CODES] = { 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 }; glpk-4.52.1/src/zlib/uncompr.c0000644000062000006210000000400412175147600015275 0ustar maomkpasswd/* uncompr.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* uncompr.c -- decompress a memory buffer * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zlib.h" /* =========================================================================== Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the compressed buffer. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. */ int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) { z_stream stream; int err; stream.next_in = (Bytef*)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; stream.next_out = dest; stream.avail_out = (uInt)*destLen; if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; err = inflateInit(&stream); if (err != Z_OK) return err; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) return Z_DATA_ERROR; return err; } *destLen = stream.total_out; err = inflateEnd(&stream); return err; } /* eof */ glpk-4.52.1/src/zlib/zconf.h0000644000062000006210000000362512175147600014746 0ustar maomkpasswd/* zconf.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef ZCONF_H #define ZCONF_H #if 1 /* by mao */ #include "zsymb.h" #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # define MAX_MEM_LEVEL 9 #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus a few kilobytes for small objects. */ /* Type declarations */ typedef unsigned char Byte; /* 8 bits */ typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ typedef Byte Bytef; typedef char charf; typedef int intf; typedef uInt uIntf; typedef uLong uLongf; typedef void const *voidpc; typedef void *voidpf; typedef void *voidp; typedef unsigned long z_crc_t; #ifndef z_off_t # define z_off_t long #endif #define z_off64_t z_off_t #endif /* ZCONF_H */ /* eof */ glpk-4.52.1/src/zlib/zio.c0000644000062000006210000000344712175147600014425 0ustar maomkpasswd/* zio.c (simulation of POSIX low-level I/O functions) */ /* Written by Andrew Makhorin , June 2013 * For conditions of distribution and use, see copyright notice in * zlib.h */ #include #include #include "zio.h" static FILE *file[FOPEN_MAX]; int open(const char *path, int oflag, ...) { FILE *f; int fd; /* see file gzlib.c, function gz_open */ if (oflag == O_RDONLY) f = fopen(path, "rb"); else if (oflag == (O_WRONLY | O_CREAT | O_TRUNC)) f = fopen(path, "wb"); else if (oflag == (O_WRONLY | O_CREAT | O_APPEND)) f = fopen(path, "ab"); else assert(oflag != oflag); if (f == NULL) return -1; for (fd = 3; fd < FOPEN_MAX; fd++) if (file[fd] == NULL) break; assert(fd < FOPEN_MAX); file[fd] = f; return fd; } long read(int fd, void *buf, unsigned long cnt) { FILE *f; assert(3 <= fd && fd < FOPEN_MAX); f = file[fd]; assert(f != NULL); cnt = fread(buf, 1, cnt, f); if (ferror(f)) return -1; return cnt; } long write(int fd, const void *buf, unsigned long cnt) { FILE *f; assert(3 <= fd && fd < FOPEN_MAX); f = file[fd]; assert(f != NULL); cnt = fwrite(buf, 1, cnt, f); if (ferror(f)) return -1; if (fflush(f) != 0) return -1; return cnt; } long lseek(int fd, long offset, int whence) { FILE *f; assert(3 <= fd && fd < FOPEN_MAX); f = file[fd]; assert(f != NULL); if (fseek(f, offset, whence) != 0) return -1; return ftell(f); } int close(int fd) { FILE *f; assert(3 <= fd && fd < FOPEN_MAX); f = file[fd]; assert(f != NULL); file[fd] = NULL; return fclose(f); } /* eof */ glpk-4.52.1/src/zlib/zio.h0000644000062000006210000000111312175147600014416 0ustar maomkpasswd/* zio.h (simulation of POSIX low-level I/O functions) */ /* Written by Andrew Makhorin , June 2013 * For conditions of distribution and use, see copyright notice in * zlib.h */ #ifndef ZIO_H #define ZIO_H #include "zsymb.h" #define O_RDONLY 0x00 #define O_WRONLY 0x01 #define O_CREAT 0x10 #define O_TRUNC 0x20 #define O_APPEND 0x40 int open(const char *path, int oflag, ...); long read(int fd, void *buf, unsigned long cnt); long write(int fd, const void *buf, unsigned long cnt); long lseek(int fd, long offset, int whence); int close(int fd); #endif /* eof */ glpk-4.52.1/src/zlib/zlib.h0000644000062000006210000023623312175147600014572 0ustar maomkpasswd/* zlib.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.7, May 2nd, 2012 Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include "zconf.h" #define ZLIB_VERSION "1.2.7" #define ZLIB_VERNUM 0x1270 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 #define ZLIB_VER_REVISION 7 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough, or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in case of corrupted input. */ typedef voidpf (*alloc_func) (voidpf opaque, uInt items, uInt size); typedef void (*free_func) (voidpf opaque, voidpf address); struct internal_state; typedef struct z_stream_s { Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ const char *msg; /* last error message, NULL if no error */ struct internal_state *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative values * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field (though see inflate()) */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ const char *zlibVersion(void); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* int deflateInit(z_streamp strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ int deflate(z_streamp strm, int flush); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed code block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six to avoid repeated flush markers due to avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space; if deflate returns with Z_OK, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least the value returned by deflateBound (see below). Then deflate is guaranteed to return Z_STREAM_END. If not enough output space is provided, deflate will not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ int deflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* int inflateInit(z_streamp strm); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. If next_in is not Z_NULL and avail_in is large enough (the exact value depends on the compression method), inflateInit determines the compression method from the zlib header and allocates all data structures accordingly; otherwise the allocation will be deferred to the first call of inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ int inflate(z_streamp strm, int flush); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in is updated and processing will resume at this point for the next call of inflate(). - Provide more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. Also to assist in this, on return inflate() will set strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. data_type is set as noted here every time inflate() returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The Z_TREES option behaves as Z_BLOCK does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of strm->data_type when inflate() returns immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the stream completes, which reduces inflate's memory footprint. If the stream does not complete, either because not all of the stream is provided or not enough output space is provided, then a sliding window will be allocated and inflate() can be called again to continue the operation as if Z_NO_FLUSH had been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the effects of the flush parameter in this implementation are on the return value of inflate() as noted below, when inflate() returns early when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip header is not retained, so applications that need that information should instead use raw inflate, see inflateInit2() below, or inflateBack() and perform their own processing of the gzip header and trailer. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output producted so far. The CRC-32 is checked against the gzip trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value), Z_STREAM_ERROR if the stream structure was inconsistent (for example next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress is possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is desired. */ int inflateEnd(z_streamp strm); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent. In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* int deflateInit2(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy); This is another version of deflateInit with more compression options. The fields next_in, zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute an adler32 check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to 255 (unknown). If a gzip stream is being written, strm->adler is a crc32 instead of an adler32. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ int deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this function must be called immediately after deflateInit, deflateInit2 or deflateReset, and before any call of deflate. When doing raw deflate, this function must be called either before any call of deflate, or immediately after the completion of a deflate block, i.e. after all input has been consumed and all output has been delivered when using any of the flush options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size provided in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the adler32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The adler32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the adler32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream or if not at a block boundary for raw deflate). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ int deflateCopy(z_streamp dest, z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ int deflateReset(z_streamp strm); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate all the internal compression state. The stream will keep the same compression level and any other attributes that may have been set by deflateInit2. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ int deflateParams(z_streamp strm, int level, int strategy); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2. This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of deflate(). Before the call of deflateParams, the stream state must be set as for a call of deflate(), since the currently available input may have to be compressed and flushed. In particular, strm->avail_out must be non-zero. deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if strm->avail_out was zero. */ int deflateTune(z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ uLong deflateBound(z_streamp strm, uLong sourceLen); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). If that first deflate() call is provided the sourceLen input bytes, an output buffer allocated to the size returned by deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used. */ int deflatePending(z_streamp strm, unsigned *pending, int *bits); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they await more bits to join them in order to fill out a full byte. If pending or bits are Z_NULL, then those values are not set. deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ int deflatePrime(z_streamp strm, int bits, int value); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the source stream state was inconsistent. */ int deflateSetHeader(z_streamp strm, gz_headerp head); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to 255, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* int inflateInit2(z_streamp strm, int windowBits); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be zero to request that inflate use the window size in the zlib header of the compressed stream. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an adler32 or a crc32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a crc32 instead of an adler32. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ int inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the adler32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the window and there is already data in the window, then the provided dictionary will amend what's there. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect adler32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ int inflateSync(z_streamp strm); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync searches for a 00 00 FF FF pattern in the compressed data. All full flush points have this pattern, but not all occurences of this pattern are full flush points. inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ int inflateCopy(z_streamp dest, z_streamp source); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ int inflateReset(z_streamp strm); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate all the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ int inflateReset2(z_streamp strm, int windowBits); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ int inflatePrime(z_streamp strm, int bits, int value); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ long inflateMark(z_streamp strm); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. If the upper value is -1 and the lower value is non-zero, then inflate is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy. If the upper value is not -1, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code. A code is being processed if inflate is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data. inflateMark() is used to mark locations in the input data for random access, which may be at bit positions, and to note those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. inflateMark returns the value noted above or -1 << 16 if the provided source stream state was inconsistent. */ int inflateGetHeader(z_streamp strm, gz_headerp head); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* int inflateBackInit(z_streamp strm, int windowBits, unsigned char *window); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func)(void *, unsigned char **); typedef int (*out_func)(void *, unsigned char *, unsigned); int inflateBack(z_streamp strm, in_func in, void *in_desc, out_func out, void *out_desc); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is more efficient than inflate() for file i/o applications in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. This function trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the normal behavior of inflate(), which expects either a zlib or gzip header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero--buf is ignored in that case--and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ int inflateBackEnd(z_streamp strm); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ uLong zlibCompileFlags(void); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ #ifndef Z_SOLO /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ int compress2(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed buffer. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ uLong compressBound(uLong sourceLen); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the uncompressed buffer. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In the case where there is not enough room, uncompress() will fill the output buffer with the uncompressed data up to that point. */ /* gzip file access functions */ /* This library supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio, using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. */ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* gzFile gzopen(const char *path, const char *mode); Opens a gzip (.gz) file for reading or writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) 'T' will request transparent writing or appending with no compression and not using the gzip format. "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since reading and writing to the same gzip file is not supported. The addition of "x" when writing will create the file exclusively, which fails if the file already exists. On systems that support it, the addition of "e" when reading or writing will set the flag to close the file on an execve() call. These functions, as well as gzip, will read and decode a sequence of gzip streams in a file. The append function of gzopen() can be used to create such a file. (Also see gzflush() for another way to do this.) When appending, gzopen does not test whether the file begins with a gzip stream, nor does it look for the end of the gzip streams to begin appending. gzopen will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. When reading, this will be detected automatically by looking for the magic two- byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ gzFile gzdopen(int fd, const char *mode); /* gzdopen associates a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since gzdopen does not close fd if it fails. If you are using fileno() to get the file descriptor from a FILE *, then you will have to use dup() to avoid double-close()ing the file descriptor. Both gzclose() and fclose() will close the associated file descriptor, so they need to have different file descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ int gzbuffer(gzFile file, unsigned size); /* Set the internal buffer size used by this library's functions. The default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or write. Two buffers are allocated, either both of the specified size when writing, or one of the specified size and the other twice that size when reading. A larger buffer size of, for example, 64K or 128K bytes will noticeably increase the speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ int gzsetparams(gzFile file, int level, int strategy); /* Dynamically update the compression level or strategy. See the description of deflateInit2 for the meaning of these parameters. gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not opened for writing. */ int gzread(gzFile file, voidp buf, unsigned len); /* Reads the given number of uncompressed bytes from the compressed file. If the input file is not in gzip format, gzread copies the given number of bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream. Any number of gzip streams may be concatenated in the input file, and will all be decompressed by gzread(). If something other than a gzip stream is encountered after a gzip stream, that remaining trailing garbage is ignored (and no error is returned). gzread can be used to read a gzip file that is being concurrently written. Upon reaching the end of the input, gzread will return with the available data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then gzclearerr can be used to clear the end of file indicator in order to permit gzread to be tried again. Z_OK indicates that a gzip stream was completed on the last gzread. Z_BUF_ERROR indicates that the input file ended in the middle of a gzip stream. Note that gzread does not return -1 in the event of an incomplete gzip stream. This error is deferred until gzclose(), which will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip stream. Alternatively, gzerror can be used before gzclose to detect this case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. */ int gzwrite(gzFile file, voidpc buf, unsigned len); /* Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ int gzprintf(gzFile file, const char *format, ...); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or 0 in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf() because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ int gzputs(gzFile file, const char *s); /* Writes the given null-terminated string to the compressed file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ char *gzgets(gzFile file, char *buf, int len); /* Reads bytes from the compressed file until len-1 characters are read, or a newline character is read and transferred to buf, or an end-of-file condition is encountered. If any characters are read or if len == 1, the string is terminated with a null character. If no characters are read due to an end-of-file or len < 1, then the buffer is left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ int gzputc(gzFile file, int c); /* Writes c, converted to an unsigned char, into the compressed file. gzputc returns the value that was written, or -1 in case of error. */ int gzgetc(gzFile file); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. As such, it does not do all of the checking the other functions do. I.e. it does not check to see if file is NULL, nor whether the structure file points to has been clobbered or not. */ int gzungetc(int c, gzFile file); /* Push one character back onto the stream to be read as the first character on the next read. At least one character of push-back is allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ int gzflush(gzFile file, int flush); /* Flushes all pending output into the compressed file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatented gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* z_off_t gzseek(gzFile file, z_off_t offset, int whence); Sets the starting position for the next gzread or gzwrite on the given compressed file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ int gzrewind(gzFile file); /* Rewinds the given file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) */ /* z_off_t gztell(gzFile file); Returns the starting position for the next gzread or gzwrite on the given compressed file. This position represents a number of bytes in the uncompressed data stream, and is zero when starting, even if appending or reading a gzip stream from the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* z_off_t gzoffset(gzFile file); Returns the current offset in the file being read or written. This offset includes the count of bytes that precede the gzip stream, for example when appending or when using gzdopen() for reading. When reading, the offset does not include as yet unused buffered input. This information can be used for a progress indicator. On error, gzoffset() returns -1. */ int gzeof(gzFile file); /* Returns true (1) if the end-of-file indicator has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set only if the read tried to go past the end of the input, but came up short. Therefore, just like feof(), gzeof() may return false even if there is no more data to read, in the event that the last read request was for the exact number of bytes remaining in the input file. This will happen if the input file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ int gzdirect(gzFile file); /* Returns true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). When writing, gzdirect() returns true (1) if transparent writing was requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: gzdirect() is not needed when writing. Transparent writing must be explicitly requested, so the application already knows the answer. When linking statically, using gzdirect() will include all of the zlib code for gzip file reading and decompression, which may not be desired.) */ int gzclose(gzFile file); /* Flushes all pending output if necessary, closes the compressed file and deallocates the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the last read ended in the middle of a gzip stream, or Z_OK on success. */ int gzclose_r(gzFile file); int gzclose_w(gzFile file); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ const char *gzerror(gzFile file, int *errnum); /* Returns the error message for the last error which occurred on the given compressed file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ void gzclearerr(gzFile file); /* Clears the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ #endif /* !Z_SOLO */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ uLong adler32(uLong adler, const Bytef *buf, uInt len); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is Z_NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ /* uLong adler32_combine(uLong adler1, uLong adler2, z_off_t len2); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note that the z_off_t type (like off_t) is a signed integer. If len2 is negative, the result has no meaning or utility. */ uLong crc32(uLong crc, const Bytef *buf, uInt len); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is Z_NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ /* uLong crc32_combine(uLong crc1, uLong crc2, z_off_t len2); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ int deflateInit_(z_streamp strm, int level, const char *version, int stream_size); int inflateInit_(z_streamp strm, const char *version, int stream_size); int deflateInit2_(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size); int inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size); int inflateBackInit_(z_streamp strm, int windowBits, unsigned char *window, const char *version, int stream_size); #define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #ifndef Z_SOLO /* gzgetc() macro and its supporting function and exposed data structure. Note * that the real internal state is much larger than the exposed structure. * This abbreviated structure exposes just enough for the gzgetc() macro. The * user should not mess with these exposed elements, since their names or * behavior could change in the future, perhaps even capriciously. They can * only be used by the gzgetc() macro. You have been warned. */ struct gzFile_s { unsigned have; unsigned char *next; z_off64_t pos; }; gzFile gzopen(const char *, const char *); z_off_t gzseek(gzFile, z_off_t, int); z_off_t gztell(gzFile); z_off_t gzoffset(gzFile); uLong adler32_combine(uLong, uLong, z_off_t); uLong crc32_combine(uLong, uLong, z_off_t); #else /* Z_SOLO */ uLong adler32_combine(uLong, uLong, z_off_t); uLong crc32_combine(uLong, uLong, z_off_t); #endif /* !Z_SOLO */ /* undocumented functions */ const char *zError(int); int inflateSyncPoint(z_streamp); const z_crc_t *get_crc_table(void); int inflateUndermine(z_streamp, int); int inflateResetKeep(z_streamp); int deflateResetKeep(z_streamp); #endif /* ZLIB_H */ /* eof */ glpk-4.52.1/src/zlib/zsymb.h0000644000062000006210000001124112175147600014764 0ustar maomkpasswd/* zsymb.h */ /* Written by Andrew Makhorin , June 2013 * For conditions of distribution and use, see copyright notice in * zlib.h */ #ifndef ZSYMB_H #define ZSYMB_H /* (adler32.c) */ #define adler32 zlib_adler32 #define adler32_combine zlib_adler32_combine #define adler32_combine64 zlib_adler32_combine64 /* (compress.c) */ #define compress2 zlib_compress2 #define compress zlib_compress #define compressBound zlib_compressBound /* (crc32.c) */ #define get_crc_table zlib_get_crc_table #define crc32 zlib_crc32 #define crc32_combine zlib_crc32_combine #define crc32_combine64 zlib_crc32_combine64 /* (deflate.c) */ #define deflate_copyright zlib_deflate_copyright #define deflateInit_ zlib_deflateInit_ #define deflateInit2_ zlib_deflateInit2_ #define deflateSetDictionary zlib_deflateSetDictionary #define deflateResetKeep zlib_deflateResetKeep #define deflateReset zlib_deflateReset #define deflateSetHeader zlib_deflateSetHeader #define deflatePending zlib_deflatePending #define deflatePrime zlib_deflatePrime #define deflateParams zlib_deflateParams #define deflateTune zlib_deflateTune #define deflateBound zlib_deflateBound #define deflate zlib_deflate #define deflateEnd zlib_deflateEnd #define deflateCopy zlib_deflateCopy /* (gzclose.c) */ #define gzclose zlib_gzclose /* (gzlib.c) */ #define gzopen zlib_gzopen #define gzopen64 zlib_gzopen64 #define gzdopen zlib_gzdopen #define gzbuffer zlib_gzbuffer #define gzrewind zlib_gzrewind #define gzseek64 zlib_gzseek64 #define gzseek zlib_gzseek #define gztell64 zlib_gztell64 #define gztell zlib_gztell #define gzoffset64 zlib_gzoffset64 #define gzoffset zlib_gzoffset #define gzeof zlib_gzeof #define gzerror zlib_gzerror #define gzclearerr zlib_gzclearerr #define gz_error zlib_gz_error /* (gzread.c) */ #define gzread zlib_gzread #define gzgetc zlib_gzgetc #define gzungetc zlib_gzungetc #define gzgets zlib_gzgets #define gzdirect zlib_gzdirect #define gzclose_r zlib_gzclose_r /* (gzwrite.c) */ #define gzwrite zlib_gzwrite #define gzputc zlib_gzputc #define gzputs zlib_gzputs #define gzprintf zlib_gzprintf #define gzflush zlib_gzflush #define gzsetparams zlib_gzsetparams #define gzclose_w zlib_gzclose_w /* (inffast.c) */ #define inflate_fast zlib_inflate_fast /* (inflate.c) */ #define inflate_copyright zlib_inflate_copyright #define inflateResetKeep zlib_inflateResetKeep #define inflateReset zlib_inflateReset #define inflateReset2 zlib_inflateReset2 #define inflateInit2_ zlib_inflateInit2_ #define inflateInit_ zlib_inflateInit_ #define inflatePrime zlib_inflatePrime #define inflate zlib_inflate #define inflateEnd zlib_inflateEnd #define inflateSetDictionary zlib_inflateSetDictionary #define inflateGetHeader zlib_inflateGetHeader #define inflateSync zlib_inflateSync #define inflateSyncPoint zlib_inflateSyncPoint #define inflateCopy zlib_inflateCopy #define inflateUndermine zlib_inflateUndermine #define inflateMark zlib_inflateMark /* (inftrees.c) */ #define inflate_table zlib_inflate_table /* (trees.c) */ #define _dist_code zlib_dist_code #define _length_code zlib_length_code #define _tr_init zlib_tr_init #define _tr_stored_block zlib_tr_stored_block #define _tr_flush_bits zlib_tr_flush_bits #define _tr_align zlib_tr_align #define _tr_flush_block zlib_tr_flush_block #define _tr_tally zlib_tr_tally /* (uncompr.c) */ #define uncompress zlib_uncompress /* (zio.c) */ #define open zlib_open #define read zlib_read #define write zlib_write #define lseek zlib_lseek #define close zlib_close /* (zutil.c) */ #define z_errmsg zlib_z_errmsg #define zlibVersion zlib_zlibVersion #define zlibCompileFlags zlib_zlibCompileFlags #define z_error zlib_z_error #define zError zlib_zError #define zcalloc zlib_zcalloc #define zcfree zlib_zcfree #endif /* eof */ glpk-4.52.1/src/zlib/zutil.c0000644000062000006210000000605012175147600014764 0ustar maomkpasswd/* zutil.c */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* zutil.c -- target dependent utility functions for the compression library * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zutil.h" #ifndef Z_SOLO # include "gzguts.h" #endif const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ "file error", /* Z_ERRNO (-1) */ "stream error", /* Z_STREAM_ERROR (-2) */ "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ "incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; const char *zlibVersion(void) { return ZLIB_VERSION; } uLong zlibCompileFlags(void) { uLong flags; flags = 0; switch ((int)(sizeof(uInt))) { case 2: break; case 4: flags += 1; break; case 8: flags += 2; break; default: flags += 3; } switch ((int)(sizeof(uLong))) { case 2: break; case 4: flags += 1 << 2; break; case 8: flags += 2 << 2; break; default: flags += 3 << 2; } switch ((int)(sizeof(voidpf))) { case 2: break; case 4: flags += 1 << 4; break; case 8: flags += 2 << 4; break; default: flags += 3 << 4; } switch ((int)(sizeof(z_off_t))) { case 2: break; case 4: flags += 1 << 6; break; case 8: flags += 2 << 6; break; default: flags += 3 << 6; } #ifdef DEBUG flags += 1 << 8; #endif #if 0 /* by mao; #if defined(ASMV) || defined(ASMINF) */ flags += 1 << 9; #endif #if 0 /* by mao; #ifdef ZLIB_WINAPI */ flags += 1 << 10; #endif #ifdef BUILDFIXED flags += 1 << 12; #endif #ifdef DYNAMIC_CRC_TABLE flags += 1 << 13; #endif #ifdef NO_GZCOMPRESS flags += 1L << 16; #endif #ifdef NO_GZIP flags += 1L << 17; #endif #ifdef PKZIP_BUG_WORKAROUND flags += 1L << 20; #endif #ifdef FASTEST flags += 1L << 21; #endif return flags; } #ifdef DEBUG # ifndef verbose # define verbose 0 # endif int z_verbose = verbose; void z_error(char *m) { fprintf(stderr, "%s\n", m); exit(1); } #endif /* exported to allow conversion of error code to string for compress() and * uncompress() */ const char *zError(int err) { return ERR_MSG(err); } #ifndef Z_SOLO #ifndef MY_ZCALLOC /* Any system without a special alloc function */ voidpf zcalloc(voidpf opaque, unsigned items, unsigned size) { if (opaque) items += size - size; /* make compiler happy */ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } void zcfree(voidpf opaque, voidpf ptr) { free(ptr); if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ #endif /* !Z_SOLO */ /* eof */ glpk-4.52.1/src/zlib/zutil.h0000644000062000006210000000617312175147600014777 0ustar maomkpasswd/* zutil.h */ /* Modified by Andrew Makhorin , June 2013. */ /* For original code see . */ /* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* WARNING: this file should *not* be used by applications. It is part of the implementation of the compression library and is subject to change. Applications should only use zlib.h. */ #ifndef ZUTIL_H #define ZUTIL_H #include #include #include "zlib.h" typedef unsigned char uch; typedef uch uchf; typedef unsigned short ush; typedef ush ushf; typedef unsigned long ulg; extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ return (strm->msg = (char*)ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ #ifndef DEF_WBITS # define DEF_WBITS MAX_WBITS #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif /* default memLevel */ #define STORED_BLOCK 0 #define STATIC_TREES 1 #define DYN_TREES 2 /* The three kinds of block type */ #define MIN_MATCH 3 #define MAX_MATCH 258 /* The minimum and maximum match lengths */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ /* target dependencies */ uLong adler32_combine64(uLong, uLong, z_off_t); uLong crc32_combine64(uLong, uLong, z_off_t); /* common defaults */ #ifndef OS_CODE # define OS_CODE 0x03 /* assume Unix */ #endif #ifndef F_OPEN # define F_OPEN(name, mode) fopen((name), (mode)) #endif /* functions */ #define zmemcpy memcpy #define zmemcmp memcmp #define zmemzero(dest, len) memset(dest, 0, len) /* Diagnostic functions */ #ifdef DEBUG # include extern int z_verbose; extern void z_error(char *m); # define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracevv(x) {if (z_verbose>1) fprintf x ;} # define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} # define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} #else # define Assert(cond,msg) # define Trace(x) # define Tracev(x) # define Tracevv(x) # define Tracec(c,x) # define Tracecv(c,x) #endif #ifndef Z_SOLO voidpf zcalloc(voidpf opaque, unsigned items, unsigned size); void zcfree(voidpf opaque, voidpf ptr); #endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} /* Reverse the bytes in a 32-bit value */ #define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) #endif /* ZUTIL_H */ /* eof */ glpk-4.52.1/THANKS0000644000062000006210000001414312175147600012637 0ustar maomkpasswdSebastien Villemot for bug report. Charles Brixko for bug report. Giorgio Sartor <0gioker0@gmail.com> for contribution of routines that implement the proximity search heuristic for MIP. Sylvain Fournier for bug report. Jeffrey Kantor for reporting typos in the MathProg language reference. David T. Price for bug report. Heinrich Schuchardt for testing the package on 32- and 64-bit MS Windows platforms. Raniere Gaia Costa da Silva for bug report. Marco Atzeri for bug report. Noli Sicad for testing glpk under Mac OS. Pietro Scionti for report typos found in the reference manual. Noli Sicad for example model in MathProg. Nigel Galloway for example model in MathProg. Xypron for contribution and testing batch scripts to build Glpk with MS Visual Studio 2010. Xypron for improving the SQL table driver. Stefan Vigerske for bug report. Uday Venkatadri for bug report. Xypron for bug fixing and some improvments in the FPUMP module. Niels Klitgord for bug report. Thomas Kahle for some suggestions. Jonathan Senning for bug report. Xypron for testing GLPK on 64-bit platforms and for maintaining Windows versions of the package. Nelson H. F. Beebe for bug report. Larry D'Agostino for example model in MathProg. Marco Atzeri for bug report. Robert Wood for example model in MathProg. Sebastien Briais for bug report. Kelly Westbrooks for suggestions. Nigel Galloway for example models in MathProg. Xypron for bug patch. Sebastian Nowozin for example models in MathProg. Stefan Vigerske for bug report. Luiz Bettoni for some suggestions. Nigel Galloway for bug report. Peter Ingerfeld for bug report. Heinrich Schuchardt for contribution of makefiles and testing the package under 64-bit Windows. Oscar Gustafsson for contribution of a new version of the routine to write data in OPB (pseudo boolean) format. Heinrich Schuchardt for some patches for the MathProg translator. Markus Pilz for bug report. Anne-Laurence Putz for bug report. Robbie Morrison for correcting the glpk manual. Axel Simon for bug report. Vijay Patil for testing the package under Windows XP. Heinrich Schuchardt for contribution of two MathProg table drivers for iODBC and MySQL. Rafael Laboissiere for useful advices concerning shared library support under GNU/Linux. Nigel Galloway for an example program in C#. Enric Rodriguez for bug report. Nigel Galloway for an example MathProg model. Roberto Bagnara (Department of Mathematics, University of Parma, Italy) for bug report. Peter T. Breuer for bug report. Graham Rockwell for bug report. Cedric[FR] for bug report. Cameron Kellough for bug report. Oscar Gustafsson for contribution of a routine to write data in OPB (pseudo boolean) format. Boris Wirtz for bug report. Sebastian Nowozin for three example MathProg models. Rafael Laboissiere for useful advices concerning shared library support. Dr. Harley Mackenzie for two example MathProg models (curve fitting problem). Minh Ha Duong for fixing doc typos. Brady Hunsaker for some suggestions concerning MIP routines. Karel Zimmermann for bug report. Christophe Caron for bug report. Nicolo Giorgetti for contribution of GLPKMEX, a Matlab MEX interface. Harley Mackenzie for contribution of GLPK FAQ. Andre Girard for bug report. Morten Welinder for bug report. Brady Hunsaker for contribution of a routine for bounds sensitivity analysis. Chris Rosebrugh for contribution of a new version of GLPK JNI (Java Native Interface). Ivo van Baren for contribution of GLPK DELI (Delphi Interface). Andrew Hamilton-Wright for bug report. Jiri Spitz for bug report. Giles Thompson for bug report. Sebastien de Menten for bug report. Kendall Demaree for bug report. Bernhard Schmidt for bug report. Yuri Victorovich for contribution of GLPK Java binding. Olivier for bug report. Kjell Eikland for bug report. Ivan Luzzi for comments concerning CPLEX LP format. Peter Lee for example LP model and bug report. Morten Welinder for bug report. Vlahos Kiriakos for bug report. Flavio Keidi Miyazawa for bug report. Hans Schwengeler for bug report. Sami Farin for bug report. Peter A. Huegler for bug report. Alexandre Oliva for bug report. Andrew Hood for bug report. glpk-4.52.1/w32/0000755000062000006210000000000012175147600012334 5ustar maomkpasswdglpk-4.52.1/w32/Build_GLPK_with_VC10.bat0000777000062000006210000000051312175147600016472 0ustar maomkpasswdrem Build GLPK with Microsoft Visual Studio Express 2010 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files\Microsoft Visual Studio 10.0\VC" call %HOME%\vcvarsall.bat x86 copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC %HOME%\bin\nmake.exe /f Makefile_VC check pause glpk-4.52.1/w32/Build_GLPK_with_VC10_DLL.bat0000777000062000006210000000052712175147600017172 0ustar maomkpasswdrem Build GLPK DLL with Microsoft Visual Studio Express 2010 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files\Microsoft Visual Studio 10.0\VC" call %HOME%\vcvarsall.bat x86 copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC_DLL %HOME%\bin\nmake.exe /f Makefile_VC_DLL check pause glpk-4.52.1/w32/Build_GLPK_with_VC9.bat0000777000062000006210000000051112175147600016420 0ustar maomkpasswdrem Build GLPK with Microsoft Visual Studio Express 2008 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files\Microsoft Visual Studio 9.0\VC" call %HOME%\bin\vcvars32.bat copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC %HOME%\bin\nmake.exe /f Makefile_VC check pause glpk-4.52.1/w32/Build_GLPK_with_VC9_DLL.bat0000777000062000006210000000052512175147600017120 0ustar maomkpasswdrem Build GLPK DLL with Microsoft Visual Studio Express 2008 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files\Microsoft Visual Studio 9.0\VC" call %HOME%\bin\vcvars32.bat copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC_DLL %HOME%\bin\nmake.exe /f Makefile_VC_DLL check pause glpk-4.52.1/w32/config_VC0000644000062000006210000000046412175147600014120 0ustar maomkpasswd/* GLPK configuration file (Microsoft Visual Studio Express) */ #define __WOE__ 1 #define ODBC_DLNAME "odbc32.dll" /* ODBC shared library name if this feature is enabled */ #if 0 #define MYSQL_DLNAME "libmysql.dll" /* MySQL shared library name if this feature is enabled */ #endif /* eof */ glpk-4.52.1/w32/glpk_4_52.1.def0000644000062000006210000000656112175147600014651 0ustar maomkpasswdLIBRARY glpk_4_52.1 VERSION 4.52.1 DESCRIPTION "GNU Linear Programming Kit" EXPORTS glp_create_prob glp_set_prob_name glp_set_obj_name glp_set_obj_dir glp_add_rows glp_add_cols glp_set_row_name glp_set_col_name glp_set_row_bnds glp_set_col_bnds glp_set_obj_coef glp_set_mat_row glp_set_mat_col glp_load_matrix glp_check_dup glp_sort_matrix glp_del_rows glp_del_cols glp_copy_prob glp_erase_prob glp_delete_prob glp_get_prob_name glp_get_obj_name glp_get_obj_dir glp_get_num_rows glp_get_num_cols glp_get_row_name glp_get_col_name glp_get_row_type glp_get_row_lb glp_get_row_ub glp_get_col_type glp_get_col_lb glp_get_col_ub glp_get_obj_coef glp_get_num_nz glp_get_mat_row glp_get_mat_col glp_create_index glp_find_row glp_find_col glp_delete_index glp_set_rii glp_set_sjj glp_get_rii glp_get_sjj glp_scale_prob glp_unscale_prob glp_set_row_stat glp_set_col_stat glp_std_basis glp_adv_basis glp_cpx_basis glp_simplex glp_exact glp_init_smcp glp_get_status glp_get_prim_stat glp_get_dual_stat glp_get_obj_val glp_get_row_stat glp_get_row_prim glp_get_row_dual glp_get_col_stat glp_get_col_prim glp_get_col_dual glp_get_unbnd_ray glp_interior glp_init_iptcp glp_ipt_status glp_ipt_obj_val glp_ipt_row_prim glp_ipt_row_dual glp_ipt_col_prim glp_ipt_col_dual glp_set_col_kind glp_get_col_kind glp_get_num_int glp_get_num_bin glp_intopt glp_init_iocp glp_mip_status glp_mip_obj_val glp_mip_row_val glp_mip_col_val glp_check_kkt glp_print_sol glp_read_sol glp_write_sol glp_print_ranges glp_print_ipt glp_read_ipt glp_write_ipt glp_print_mip glp_read_mip glp_write_mip glp_bf_exists glp_factorize glp_bf_updated glp_get_bfcp glp_set_bfcp glp_get_bhead glp_get_row_bind glp_get_col_bind glp_ftran glp_btran glp_warm_up glp_eval_tab_row glp_eval_tab_col glp_transform_row glp_transform_col glp_prim_rtest glp_dual_rtest glp_analyze_bound glp_analyze_coef glp_ios_reason glp_ios_get_prob glp_ios_tree_size glp_ios_curr_node glp_ios_next_node glp_ios_prev_node glp_ios_up_node glp_ios_node_level glp_ios_node_bound glp_ios_best_node glp_ios_mip_gap glp_ios_node_data glp_ios_row_attr glp_ios_pool_size glp_ios_add_row glp_ios_del_row glp_ios_clear_pool glp_ios_can_branch glp_ios_branch_upon glp_ios_select_node glp_ios_heur_sol glp_ios_terminate glp_init_mpscp glp_read_mps glp_write_mps glp_init_cpxcp glp_read_lp glp_write_lp glp_read_prob glp_write_prob glp_mpl_alloc_wksp glp_mpl_read_model glp_mpl_read_data glp_mpl_generate glp_mpl_build_prob glp_mpl_postsolve glp_mpl_free_wksp glp_main glp_read_cnfsat glp_check_cnfsat glp_write_cnfsat glp_minisat1 glp_intfeas1 glp_init_env glp_version glp_free_env glp_puts glp_printf glp_vprintf glp_term_out glp_term_hook glp_open_tee glp_close_tee glp_error_ glp_assert_ glp_error_hook glp_alloc glp_realloc glp_free glp_mem_limit glp_mem_usage glp_create_graph glp_set_graph_name glp_add_vertices glp_set_vertex_name glp_add_arc glp_del_vertices glp_del_arc glp_erase_graph glp_delete_graph glp_create_v_index glp_find_vertex glp_delete_v_index glp_read_graph glp_write_graph glp_mincost_lp glp_mincost_okalg glp_mincost_relax4 glp_maxflow_lp glp_maxflow_ffalg glp_check_asnprob glp_asnprob_lp glp_asnprob_okalg glp_asnprob_hall glp_cpp glp_read_mincost glp_write_mincost glp_read_maxflow glp_write_maxflow glp_read_asnprob glp_write_asnprob glp_read_ccdata glp_write_ccdata glp_netgen glp_netgen_prob glp_gridgen glp_rmfgen glp_weak_comp glp_strong_comp glp_top_sort glp_wclique_exact ;; end of file ;; glpk-4.52.1/w32/Makefile_VC0000644000062000006210000001030712175147600014365 0ustar maomkpasswd## Build GLPK with Microsoft Visual Studio Express ## CFLAGS = \ /I. \ /I..\src \ /I..\src\amd \ /I..\src\bflib \ /I..\src\cglib \ /I..\src\colamd \ /I..\src\env \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ /O2 OBJSET = \ ..\src\glpapi01.obj \ ..\src\glpapi02.obj \ ..\src\glpapi03.obj \ ..\src\glpapi04.obj \ ..\src\glpapi05.obj \ ..\src\glpapi06.obj \ ..\src\glpapi07.obj \ ..\src\glpapi08.obj \ ..\src\glpapi09.obj \ ..\src\glpapi10.obj \ ..\src\glpapi11.obj \ ..\src\glpapi12.obj \ ..\src\glpapi13.obj \ ..\src\glpapi14.obj \ ..\src\glpapi15.obj \ ..\src\glpapi16.obj \ ..\src\glpapi17.obj \ ..\src\glpapi18.obj \ ..\src\glpapi19.obj \ ..\src\glpapi20.obj \ ..\src\glpapi21.obj \ ..\src\glpavl.obj \ ..\src\glpbfd.obj \ ..\src\glpbfx.obj \ ..\src\glpcpx.obj \ ..\src\glpdmx.obj \ ..\src\glpenv07.obj \ ..\src\glpenv08.obj \ ..\src\glpgmp.obj \ ..\src\glphbm.obj \ ..\src\glpini01.obj \ ..\src\glpini02.obj \ ..\src\glpios01.obj \ ..\src\glpios02.obj \ ..\src\glpios03.obj \ ..\src\glpios04.obj \ ..\src\glpios05.obj \ ..\src\glpios06.obj \ ..\src\glpios07.obj \ ..\src\glpios08.obj \ ..\src\glpios09.obj \ ..\src\glpios10.obj \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ ..\src\glplib03.obj \ ..\src\glplpf.obj \ ..\src\glplpx01.obj \ ..\src\glplpx02.obj \ ..\src\glplpx03.obj \ ..\src\glplux.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ ..\src\glpmpl03.obj \ ..\src\glpmpl04.obj \ ..\src\glpmpl05.obj \ ..\src\glpmpl06.obj \ ..\src\glpmps.obj \ ..\src\glpnet03.obj \ ..\src\glpnet04.obj \ ..\src\glpnet05.obj \ ..\src\glpnpp01.obj \ ..\src\glpnpp02.obj \ ..\src\glpnpp03.obj \ ..\src\glpnpp04.obj \ ..\src\glpnpp05.obj \ ..\src\glpnpp06.obj \ ..\src\glprgr.obj \ ..\src\glpscf.obj \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ ..\src\glpspx01.obj \ ..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ ..\src\glptsp.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ ..\src\amd\amd_aat.obj \ ..\src\amd\amd_control.obj \ ..\src\amd\amd_defaults.obj \ ..\src\amd\amd_dump.obj \ ..\src\amd\amd_info.obj \ ..\src\amd\amd_order.obj \ ..\src\amd\amd_post_tree.obj \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ ..\src\cglib\cfg1.obj \ ..\src\colamd\colamd.obj \ ..\src\env\alloc.obj \ ..\src\env\env.obj \ ..\src\env\error.obj \ ..\src\env\stdout.obj \ ..\src\env\time.obj \ ..\src\env\tls.obj \ ..\src\minisat\minisat.obj \ ..\src\misc\bignum.obj \ ..\src\misc\dmp.obj \ ..\src\misc\ffalg.obj \ ..\src\misc\jd.obj \ ..\src\misc\keller.obj \ ..\src\misc\mc13d.obj \ ..\src\misc\mc21a.obj \ ..\src\misc\okalg.obj \ ..\src\misc\qmd.obj \ ..\src\misc\relax4.obj \ ..\src\misc\rng.obj \ ..\src\misc\rng1.obj \ ..\src\misc\triang.obj \ ..\src\misc\wclique.obj \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ ..\src\zlib\deflate.obj \ ..\src\zlib\gzclose.obj \ ..\src\zlib\gzlib.obj \ ..\src\zlib\gzread.obj \ ..\src\zlib\gzwrite.obj \ ..\src\zlib\inffast.obj \ ..\src\zlib\inflate.obj \ ..\src\zlib\inftrees.obj \ ..\src\zlib\trees.obj \ ..\src\zlib\uncompr.obj \ ..\src\zlib\zio.obj \ ..\src\zlib\zutil.obj .c.obj: cl.exe $(CFLAGS) /Fo$*.obj /c $*.c all: glpk.lib glpsol.exe glpk.lib: $(OBJSET) lib.exe /out:glpk.lib \ ..\src\*.obj \ ..\src\amd\*.obj \ ..\src\bflib\*.obj \ ..\src\cglib\*.obj \ ..\src\colamd\*.obj \ ..\src\env\*.obj \ ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ ..\src\zlib\*.obj glpsol.exe: ..\examples\glpsol.obj glpk.lib cl.exe $(CFLAGS) /Feglpsol.exe \ ..\examples\glpsol.obj glpk.lib check: glpsol.exe .\glpsol.exe --version .\glpsol.exe --mps ..\examples\plan.mps ## eof ## glpk-4.52.1/w32/Makefile_VC_DLL0000644000062000006210000001043412175147600015061 0ustar maomkpasswd## Build GLPK DLL with Microsoft Visual Studio Express ## CFLAGS = \ /I. \ /I..\src \ /I..\src\amd \ /I..\src\bflib \ /I..\src\cglib \ /I..\src\colamd \ /I..\src\env \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ /O2 OBJSET = \ ..\src\glpapi01.obj \ ..\src\glpapi02.obj \ ..\src\glpapi03.obj \ ..\src\glpapi04.obj \ ..\src\glpapi05.obj \ ..\src\glpapi06.obj \ ..\src\glpapi07.obj \ ..\src\glpapi08.obj \ ..\src\glpapi09.obj \ ..\src\glpapi10.obj \ ..\src\glpapi11.obj \ ..\src\glpapi12.obj \ ..\src\glpapi13.obj \ ..\src\glpapi14.obj \ ..\src\glpapi15.obj \ ..\src\glpapi16.obj \ ..\src\glpapi17.obj \ ..\src\glpapi18.obj \ ..\src\glpapi19.obj \ ..\src\glpapi20.obj \ ..\src\glpapi21.obj \ ..\src\glpavl.obj \ ..\src\glpbfd.obj \ ..\src\glpbfx.obj \ ..\src\glpcpx.obj \ ..\src\glpdmx.obj \ ..\src\glpenv07.obj \ ..\src\glpenv08.obj \ ..\src\glpgmp.obj \ ..\src\glphbm.obj \ ..\src\glpini01.obj \ ..\src\glpini02.obj \ ..\src\glpios01.obj \ ..\src\glpios02.obj \ ..\src\glpios03.obj \ ..\src\glpios04.obj \ ..\src\glpios05.obj \ ..\src\glpios06.obj \ ..\src\glpios07.obj \ ..\src\glpios08.obj \ ..\src\glpios09.obj \ ..\src\glpios10.obj \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ ..\src\glplib03.obj \ ..\src\glplpf.obj \ ..\src\glplpx01.obj \ ..\src\glplpx02.obj \ ..\src\glplpx03.obj \ ..\src\glplux.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ ..\src\glpmpl03.obj \ ..\src\glpmpl04.obj \ ..\src\glpmpl05.obj \ ..\src\glpmpl06.obj \ ..\src\glpmps.obj \ ..\src\glpnet03.obj \ ..\src\glpnet04.obj \ ..\src\glpnet05.obj \ ..\src\glpnpp01.obj \ ..\src\glpnpp02.obj \ ..\src\glpnpp03.obj \ ..\src\glpnpp04.obj \ ..\src\glpnpp05.obj \ ..\src\glpnpp06.obj \ ..\src\glprgr.obj \ ..\src\glpscf.obj \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ ..\src\glpspx01.obj \ ..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ ..\src\glptsp.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ ..\src\amd\amd_aat.obj \ ..\src\amd\amd_control.obj \ ..\src\amd\amd_defaults.obj \ ..\src\amd\amd_dump.obj \ ..\src\amd\amd_info.obj \ ..\src\amd\amd_order.obj \ ..\src\amd\amd_post_tree.obj \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ ..\src\cglib\cfg1.obj \ ..\src\colamd\colamd.obj \ ..\src\env\alloc.obj \ ..\src\env\env.obj \ ..\src\env\error.obj \ ..\src\env\stdout.obj \ ..\src\env\time.obj \ ..\src\env\tls.obj \ ..\src\minisat\minisat.obj \ ..\src\misc\bignum.obj \ ..\src\misc\dmp.obj \ ..\src\misc\ffalg.obj \ ..\src\misc\jd.obj \ ..\src\misc\keller.obj \ ..\src\misc\mc13d.obj \ ..\src\misc\mc21a.obj \ ..\src\misc\okalg.obj \ ..\src\misc\qmd.obj \ ..\src\misc\relax4.obj \ ..\src\misc\rng.obj \ ..\src\misc\rng1.obj \ ..\src\misc\triang.obj \ ..\src\misc\wclique.obj \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ ..\src\zlib\deflate.obj \ ..\src\zlib\gzclose.obj \ ..\src\zlib\gzlib.obj \ ..\src\zlib\gzread.obj \ ..\src\zlib\gzwrite.obj \ ..\src\zlib\inffast.obj \ ..\src\zlib\inflate.obj \ ..\src\zlib\inftrees.obj \ ..\src\zlib\trees.obj \ ..\src\zlib\uncompr.obj \ ..\src\zlib\zio.obj \ ..\src\zlib\zutil.obj .c.obj: cl.exe $(CFLAGS) /Fo$*.obj /c $*.c all: glpk_4_52.1.dll glpsol.exe glpk_4_52.1.dll: $(OBJSET) cl.exe $(CFLAGS) /LD /Feglpk_4_52.1.dll \ ..\src\*.obj \ ..\src\amd\*.obj \ ..\src\bflib\*.obj \ ..\src\cglib\*.obj \ ..\src\colamd\*.obj \ ..\src\env\*.obj \ ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ ..\src\zlib\*.obj \ glpk_4_52.1.def glpsol.exe: ..\examples\glpsol.obj glpk_4_52.1.dll cl.exe $(CFLAGS) /Feglpsol.exe \ ..\examples\glpsol.obj glpk_4_52.1.lib check: glpsol.exe .\glpsol.exe --version .\glpsol.exe --mps ..\examples\plan.mps ## eof ## glpk-4.52.1/w32/readme.txt0000644000062000006210000000166712175147600014344 0ustar maomkpasswdThis directory contains batch files and other stuff which you can use to build GLPK for 32-bit Windows with the native C/C++ compilers. Before running the batch file do the following: 1. Make sure that you have installed the compiler you are going to use to build GLPK. 2. Look into corresponding batch file (just right-click it and choose 'Edit' in the popup menu; DO NOT choose 'Open'). Make sure that HOME variable specifies correct path to the compiler directory; if not, make necessary changes. To run the batch file just double-click it and wait a bit while the Make utility does its job. The message 'OPTIMAL SOLUTION FOUND' in the MS-DOS window means that all is OK. If you do not see it, something is wrong. Once GLPK has been successfully built, there must appear two files in this directory: glpk.lib, which is the GLPK object library, and glpsol.exe, which is the stand-alone GLPK LP/MIP solver. glpk-4.52.1/w64/0000755000062000006210000000000012175147600012341 5ustar maomkpasswdglpk-4.52.1/w64/Build_GLPK_with_VC10.bat0000777000062000006210000000052112175147600016476 0ustar maomkpasswdrem Build GLPK with Microsoft Visual Studio Express 2010 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC" call %HOME%\vcvarsall.bat x64 copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC %HOME%\bin\nmake.exe /f Makefile_VC check pause glpk-4.52.1/w64/Build_GLPK_with_VC10_DLL.bat0000777000062000006210000000053512175147600017176 0ustar maomkpasswdrem Build GLPK DLL with Microsoft Visual Studio Express 2010 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC" call %HOME%\vcvarsall.bat x64 copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC_DLL %HOME%\bin\nmake.exe /f Makefile_VC_DLL check pause glpk-4.52.1/w64/Build_GLPK_with_VC9.bat0000777000062000006210000000051712175147600016433 0ustar maomkpasswdrem Build GLPK with Microsoft Visual Studio Express 2008 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC" call %HOME%\bin\vcvars64.bat copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC %HOME%\bin\nmake.exe /f Makefile_VC check pause glpk-4.52.1/w64/Build_GLPK_with_VC9_DLL.bat0000777000062000006210000000053312175147600017124 0ustar maomkpasswdrem Build GLPK DLL with Microsoft Visual Studio Express 2008 rem NOTE: Make sure that HOME variable specifies correct path set HOME="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC" call %HOME%\bin\vcvars64.bat copy config_VC config.h %HOME%\bin\nmake.exe /f Makefile_VC_DLL %HOME%\bin\nmake.exe /f Makefile_VC_DLL check pause glpk-4.52.1/w64/config_VC0000644000062000006210000000046412175147600014125 0ustar maomkpasswd/* GLPK configuration file (Microsoft Visual Studio Express) */ #define __WOE__ 1 #define ODBC_DLNAME "odbc32.dll" /* ODBC shared library name if this feature is enabled */ #if 0 #define MYSQL_DLNAME "libmysql.dll" /* MySQL shared library name if this feature is enabled */ #endif /* eof */ glpk-4.52.1/w64/glpk_4_52.1.def0000644000062000006210000000656112175147600014656 0ustar maomkpasswdLIBRARY glpk_4_52.1 VERSION 4.52.1 DESCRIPTION "GNU Linear Programming Kit" EXPORTS glp_create_prob glp_set_prob_name glp_set_obj_name glp_set_obj_dir glp_add_rows glp_add_cols glp_set_row_name glp_set_col_name glp_set_row_bnds glp_set_col_bnds glp_set_obj_coef glp_set_mat_row glp_set_mat_col glp_load_matrix glp_check_dup glp_sort_matrix glp_del_rows glp_del_cols glp_copy_prob glp_erase_prob glp_delete_prob glp_get_prob_name glp_get_obj_name glp_get_obj_dir glp_get_num_rows glp_get_num_cols glp_get_row_name glp_get_col_name glp_get_row_type glp_get_row_lb glp_get_row_ub glp_get_col_type glp_get_col_lb glp_get_col_ub glp_get_obj_coef glp_get_num_nz glp_get_mat_row glp_get_mat_col glp_create_index glp_find_row glp_find_col glp_delete_index glp_set_rii glp_set_sjj glp_get_rii glp_get_sjj glp_scale_prob glp_unscale_prob glp_set_row_stat glp_set_col_stat glp_std_basis glp_adv_basis glp_cpx_basis glp_simplex glp_exact glp_init_smcp glp_get_status glp_get_prim_stat glp_get_dual_stat glp_get_obj_val glp_get_row_stat glp_get_row_prim glp_get_row_dual glp_get_col_stat glp_get_col_prim glp_get_col_dual glp_get_unbnd_ray glp_interior glp_init_iptcp glp_ipt_status glp_ipt_obj_val glp_ipt_row_prim glp_ipt_row_dual glp_ipt_col_prim glp_ipt_col_dual glp_set_col_kind glp_get_col_kind glp_get_num_int glp_get_num_bin glp_intopt glp_init_iocp glp_mip_status glp_mip_obj_val glp_mip_row_val glp_mip_col_val glp_check_kkt glp_print_sol glp_read_sol glp_write_sol glp_print_ranges glp_print_ipt glp_read_ipt glp_write_ipt glp_print_mip glp_read_mip glp_write_mip glp_bf_exists glp_factorize glp_bf_updated glp_get_bfcp glp_set_bfcp glp_get_bhead glp_get_row_bind glp_get_col_bind glp_ftran glp_btran glp_warm_up glp_eval_tab_row glp_eval_tab_col glp_transform_row glp_transform_col glp_prim_rtest glp_dual_rtest glp_analyze_bound glp_analyze_coef glp_ios_reason glp_ios_get_prob glp_ios_tree_size glp_ios_curr_node glp_ios_next_node glp_ios_prev_node glp_ios_up_node glp_ios_node_level glp_ios_node_bound glp_ios_best_node glp_ios_mip_gap glp_ios_node_data glp_ios_row_attr glp_ios_pool_size glp_ios_add_row glp_ios_del_row glp_ios_clear_pool glp_ios_can_branch glp_ios_branch_upon glp_ios_select_node glp_ios_heur_sol glp_ios_terminate glp_init_mpscp glp_read_mps glp_write_mps glp_init_cpxcp glp_read_lp glp_write_lp glp_read_prob glp_write_prob glp_mpl_alloc_wksp glp_mpl_read_model glp_mpl_read_data glp_mpl_generate glp_mpl_build_prob glp_mpl_postsolve glp_mpl_free_wksp glp_main glp_read_cnfsat glp_check_cnfsat glp_write_cnfsat glp_minisat1 glp_intfeas1 glp_init_env glp_version glp_free_env glp_puts glp_printf glp_vprintf glp_term_out glp_term_hook glp_open_tee glp_close_tee glp_error_ glp_assert_ glp_error_hook glp_alloc glp_realloc glp_free glp_mem_limit glp_mem_usage glp_create_graph glp_set_graph_name glp_add_vertices glp_set_vertex_name glp_add_arc glp_del_vertices glp_del_arc glp_erase_graph glp_delete_graph glp_create_v_index glp_find_vertex glp_delete_v_index glp_read_graph glp_write_graph glp_mincost_lp glp_mincost_okalg glp_mincost_relax4 glp_maxflow_lp glp_maxflow_ffalg glp_check_asnprob glp_asnprob_lp glp_asnprob_okalg glp_asnprob_hall glp_cpp glp_read_mincost glp_write_mincost glp_read_maxflow glp_write_maxflow glp_read_asnprob glp_write_asnprob glp_read_ccdata glp_write_ccdata glp_netgen glp_netgen_prob glp_gridgen glp_rmfgen glp_weak_comp glp_strong_comp glp_top_sort glp_wclique_exact ;; end of file ;; glpk-4.52.1/w64/makefile_VC0000644000062000006210000001030712175147600014432 0ustar maomkpasswd## Build GLPK with Microsoft Visual Studio Express ## CFLAGS = \ /I. \ /I..\src \ /I..\src\amd \ /I..\src\bflib \ /I..\src\cglib \ /I..\src\colamd \ /I..\src\env \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ /O2 OBJSET = \ ..\src\glpapi01.obj \ ..\src\glpapi02.obj \ ..\src\glpapi03.obj \ ..\src\glpapi04.obj \ ..\src\glpapi05.obj \ ..\src\glpapi06.obj \ ..\src\glpapi07.obj \ ..\src\glpapi08.obj \ ..\src\glpapi09.obj \ ..\src\glpapi10.obj \ ..\src\glpapi11.obj \ ..\src\glpapi12.obj \ ..\src\glpapi13.obj \ ..\src\glpapi14.obj \ ..\src\glpapi15.obj \ ..\src\glpapi16.obj \ ..\src\glpapi17.obj \ ..\src\glpapi18.obj \ ..\src\glpapi19.obj \ ..\src\glpapi20.obj \ ..\src\glpapi21.obj \ ..\src\glpavl.obj \ ..\src\glpbfd.obj \ ..\src\glpbfx.obj \ ..\src\glpcpx.obj \ ..\src\glpdmx.obj \ ..\src\glpenv07.obj \ ..\src\glpenv08.obj \ ..\src\glpgmp.obj \ ..\src\glphbm.obj \ ..\src\glpini01.obj \ ..\src\glpini02.obj \ ..\src\glpios01.obj \ ..\src\glpios02.obj \ ..\src\glpios03.obj \ ..\src\glpios04.obj \ ..\src\glpios05.obj \ ..\src\glpios06.obj \ ..\src\glpios07.obj \ ..\src\glpios08.obj \ ..\src\glpios09.obj \ ..\src\glpios10.obj \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ ..\src\glplib03.obj \ ..\src\glplpf.obj \ ..\src\glplpx01.obj \ ..\src\glplpx02.obj \ ..\src\glplpx03.obj \ ..\src\glplux.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ ..\src\glpmpl03.obj \ ..\src\glpmpl04.obj \ ..\src\glpmpl05.obj \ ..\src\glpmpl06.obj \ ..\src\glpmps.obj \ ..\src\glpnet03.obj \ ..\src\glpnet04.obj \ ..\src\glpnet05.obj \ ..\src\glpnpp01.obj \ ..\src\glpnpp02.obj \ ..\src\glpnpp03.obj \ ..\src\glpnpp04.obj \ ..\src\glpnpp05.obj \ ..\src\glpnpp06.obj \ ..\src\glprgr.obj \ ..\src\glpscf.obj \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ ..\src\glpspx01.obj \ ..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ ..\src\glptsp.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ ..\src\amd\amd_aat.obj \ ..\src\amd\amd_control.obj \ ..\src\amd\amd_defaults.obj \ ..\src\amd\amd_dump.obj \ ..\src\amd\amd_info.obj \ ..\src\amd\amd_order.obj \ ..\src\amd\amd_post_tree.obj \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ ..\src\cglib\cfg1.obj \ ..\src\colamd\colamd.obj \ ..\src\env\alloc.obj \ ..\src\env\env.obj \ ..\src\env\error.obj \ ..\src\env\stdout.obj \ ..\src\env\time.obj \ ..\src\env\tls.obj \ ..\src\minisat\minisat.obj \ ..\src\misc\bignum.obj \ ..\src\misc\dmp.obj \ ..\src\misc\ffalg.obj \ ..\src\misc\jd.obj \ ..\src\misc\keller.obj \ ..\src\misc\mc13d.obj \ ..\src\misc\mc21a.obj \ ..\src\misc\okalg.obj \ ..\src\misc\qmd.obj \ ..\src\misc\relax4.obj \ ..\src\misc\rng.obj \ ..\src\misc\rng1.obj \ ..\src\misc\triang.obj \ ..\src\misc\wclique.obj \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ ..\src\zlib\deflate.obj \ ..\src\zlib\gzclose.obj \ ..\src\zlib\gzlib.obj \ ..\src\zlib\gzread.obj \ ..\src\zlib\gzwrite.obj \ ..\src\zlib\inffast.obj \ ..\src\zlib\inflate.obj \ ..\src\zlib\inftrees.obj \ ..\src\zlib\trees.obj \ ..\src\zlib\uncompr.obj \ ..\src\zlib\zio.obj \ ..\src\zlib\zutil.obj .c.obj: cl.exe $(CFLAGS) /Fo$*.obj /c $*.c all: glpk.lib glpsol.exe glpk.lib: $(OBJSET) lib.exe /out:glpk.lib \ ..\src\*.obj \ ..\src\amd\*.obj \ ..\src\bflib\*.obj \ ..\src\cglib\*.obj \ ..\src\colamd\*.obj \ ..\src\env\*.obj \ ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ ..\src\zlib\*.obj glpsol.exe: ..\examples\glpsol.obj glpk.lib cl.exe $(CFLAGS) /Feglpsol.exe \ ..\examples\glpsol.obj glpk.lib check: glpsol.exe .\glpsol.exe --version .\glpsol.exe --mps ..\examples\plan.mps ## eof ## glpk-4.52.1/w64/makefile_VC_DLL0000644000062000006210000001043412175147600015126 0ustar maomkpasswd## Build GLPK DLL with Microsoft Visual Studio Express ## CFLAGS = \ /I. \ /I..\src \ /I..\src\amd \ /I..\src\bflib \ /I..\src\cglib \ /I..\src\colamd \ /I..\src\env \ /I..\src\minisat \ /I..\src\misc \ /I..\src\proxy \ /I..\src\zlib \ /DHAVE_CONFIG_H=1 \ /D_CRT_SECURE_NO_WARNINGS=1 \ /nologo \ /W3 \ /O2 OBJSET = \ ..\src\glpapi01.obj \ ..\src\glpapi02.obj \ ..\src\glpapi03.obj \ ..\src\glpapi04.obj \ ..\src\glpapi05.obj \ ..\src\glpapi06.obj \ ..\src\glpapi07.obj \ ..\src\glpapi08.obj \ ..\src\glpapi09.obj \ ..\src\glpapi10.obj \ ..\src\glpapi11.obj \ ..\src\glpapi12.obj \ ..\src\glpapi13.obj \ ..\src\glpapi14.obj \ ..\src\glpapi15.obj \ ..\src\glpapi16.obj \ ..\src\glpapi17.obj \ ..\src\glpapi18.obj \ ..\src\glpapi19.obj \ ..\src\glpapi20.obj \ ..\src\glpapi21.obj \ ..\src\glpavl.obj \ ..\src\glpbfd.obj \ ..\src\glpbfx.obj \ ..\src\glpcpx.obj \ ..\src\glpdmx.obj \ ..\src\glpenv07.obj \ ..\src\glpenv08.obj \ ..\src\glpgmp.obj \ ..\src\glphbm.obj \ ..\src\glpini01.obj \ ..\src\glpini02.obj \ ..\src\glpios01.obj \ ..\src\glpios02.obj \ ..\src\glpios03.obj \ ..\src\glpios04.obj \ ..\src\glpios05.obj \ ..\src\glpios06.obj \ ..\src\glpios07.obj \ ..\src\glpios08.obj \ ..\src\glpios09.obj \ ..\src\glpios10.obj \ ..\src\glpios11.obj \ ..\src\glpios12.obj \ ..\src\glpipm.obj \ ..\src\glplib03.obj \ ..\src\glplpf.obj \ ..\src\glplpx01.obj \ ..\src\glplpx02.obj \ ..\src\glplpx03.obj \ ..\src\glplux.obj \ ..\src\glpmat.obj \ ..\src\glpmpl01.obj \ ..\src\glpmpl02.obj \ ..\src\glpmpl03.obj \ ..\src\glpmpl04.obj \ ..\src\glpmpl05.obj \ ..\src\glpmpl06.obj \ ..\src\glpmps.obj \ ..\src\glpnet03.obj \ ..\src\glpnet04.obj \ ..\src\glpnet05.obj \ ..\src\glpnpp01.obj \ ..\src\glpnpp02.obj \ ..\src\glpnpp03.obj \ ..\src\glpnpp04.obj \ ..\src\glpnpp05.obj \ ..\src\glpnpp06.obj \ ..\src\glprgr.obj \ ..\src\glpscf.obj \ ..\src\glpscl.obj \ ..\src\glpsdf.obj \ ..\src\glpspm.obj \ ..\src\glpspx01.obj \ ..\src\glpspx02.obj \ ..\src\glpsql.obj \ ..\src\glpssx01.obj \ ..\src\glpssx02.obj \ ..\src\glptsp.obj \ ..\src\amd\amd_1.obj \ ..\src\amd\amd_2.obj \ ..\src\amd\amd_aat.obj \ ..\src\amd\amd_control.obj \ ..\src\amd\amd_defaults.obj \ ..\src\amd\amd_dump.obj \ ..\src\amd\amd_info.obj \ ..\src\amd\amd_order.obj \ ..\src\amd\amd_post_tree.obj \ ..\src\amd\amd_postorder.obj \ ..\src\amd\amd_preprocess.obj \ ..\src\amd\amd_valid.obj \ ..\src\bflib\fhv.obj \ ..\src\bflib\fhvint.obj \ ..\src\bflib\luf.obj \ ..\src\bflib\lufint.obj \ ..\src\bflib\sgf.obj \ ..\src\bflib\sva.obj \ ..\src\cglib\cfg.obj \ ..\src\cglib\cfg1.obj \ ..\src\colamd\colamd.obj \ ..\src\env\alloc.obj \ ..\src\env\env.obj \ ..\src\env\error.obj \ ..\src\env\stdout.obj \ ..\src\env\time.obj \ ..\src\env\tls.obj \ ..\src\minisat\minisat.obj \ ..\src\misc\bignum.obj \ ..\src\misc\dmp.obj \ ..\src\misc\ffalg.obj \ ..\src\misc\jd.obj \ ..\src\misc\keller.obj \ ..\src\misc\mc13d.obj \ ..\src\misc\mc21a.obj \ ..\src\misc\okalg.obj \ ..\src\misc\qmd.obj \ ..\src\misc\relax4.obj \ ..\src\misc\rng.obj \ ..\src\misc\rng1.obj \ ..\src\misc\triang.obj \ ..\src\misc\wclique.obj \ ..\src\misc\wclique1.obj \ ..\src\proxy\proxy.obj \ ..\src\proxy\proxy1.obj \ ..\src\zlib\adler32.obj \ ..\src\zlib\compress.obj \ ..\src\zlib\crc32.obj \ ..\src\zlib\deflate.obj \ ..\src\zlib\gzclose.obj \ ..\src\zlib\gzlib.obj \ ..\src\zlib\gzread.obj \ ..\src\zlib\gzwrite.obj \ ..\src\zlib\inffast.obj \ ..\src\zlib\inflate.obj \ ..\src\zlib\inftrees.obj \ ..\src\zlib\trees.obj \ ..\src\zlib\uncompr.obj \ ..\src\zlib\zio.obj \ ..\src\zlib\zutil.obj .c.obj: cl.exe $(CFLAGS) /Fo$*.obj /c $*.c all: glpk_4_52.1.dll glpsol.exe glpk_4_52.1.dll: $(OBJSET) cl.exe $(CFLAGS) /LD /Feglpk_4_52.1.dll \ ..\src\*.obj \ ..\src\amd\*.obj \ ..\src\bflib\*.obj \ ..\src\cglib\*.obj \ ..\src\colamd\*.obj \ ..\src\env\*.obj \ ..\src\minisat\*.obj \ ..\src\misc\*.obj \ ..\src\proxy\*.obj \ ..\src\zlib\*.obj \ glpk_4_52.1.def glpsol.exe: ..\examples\glpsol.obj glpk_4_52.1.dll cl.exe $(CFLAGS) /Feglpsol.exe \ ..\examples\glpsol.obj glpk_4_52.1.lib check: glpsol.exe .\glpsol.exe --version .\glpsol.exe --mps ..\examples\plan.mps ## eof ## glpk-4.52.1/w64/readme.txt0000644000062000006210000000166712175147600014351 0ustar maomkpasswdThis directory contains batch files and other stuff which you can use to build GLPK for 64-bit Windows with the native C/C++ compilers. Before running the batch file do the following: 1. Make sure that you have installed the compiler you are going to use to build GLPK. 2. Look into corresponding batch file (just right-click it and choose 'Edit' in the popup menu; DO NOT choose 'Open'). Make sure that HOME variable specifies correct path to the compiler directory; if not, make necessary changes. To run the batch file just double-click it and wait a bit while the Make utility does its job. The message 'OPTIMAL SOLUTION FOUND' in the MS-DOS window means that all is OK. If you do not see it, something is wrong. Once GLPK has been successfully built, there must appear two files in this directory: glpk.lib, which is the GLPK object library, and glpsol.exe, which is the stand-alone GLPK LP/MIP solver.